diff --git a/.gitignore b/.gitignore index bd1ae6b7..5ff569c8 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ dist/ !openclaw.plugin.json .openclaw node_modules +.claude/ diff --git a/lib/tools/admin/autoconfigure-models.ts b/lib/tools/admin/autoconfigure-models.ts index c4bada45..a722408c 100644 --- a/lib/tools/admin/autoconfigure-models.ts +++ b/lib/tools/admin/autoconfigure-models.ts @@ -3,7 +3,7 @@ * * Queries available authenticated models and intelligently assigns them to DevClaw roles. */ -import { jsonResult } from "openclaw/plugin-sdk"; +import { jsonResult } from "../helpers.js"; import type { ToolContext } from "../../types.js"; import type { PluginContext, RunCommand } from "../../context.js"; import { diff --git a/lib/tools/admin/channel-link.ts b/lib/tools/admin/channel-link.ts index 8e0324f3..6d1bea02 100644 --- a/lib/tools/admin/channel-link.ts +++ b/lib/tools/admin/channel-link.ts @@ -6,12 +6,11 @@ * (auto-detach). This is the primary way to switch which project a chat * controls. */ -import { jsonResult } from "openclaw/plugin-sdk"; import type { PluginContext } from "../../context.js"; import type { ToolContext } from "../../types.js"; import { readProjects, writeProjects, type Channel } from "../../projects/index.js"; import { log as auditLog } from "../../audit.js"; -import { requireWorkspaceDir } from "../helpers.js"; +import { jsonResult, requireWorkspaceDir } from "../helpers.js"; export function createChannelLinkTool(_ctx: PluginContext) { return (toolCtx: ToolContext) => ({ diff --git a/lib/tools/admin/channel-list.ts b/lib/tools/admin/channel-list.ts index f5bed3cc..303366db 100644 --- a/lib/tools/admin/channel-list.ts +++ b/lib/tools/admin/channel-list.ts @@ -4,11 +4,10 @@ * Shows registered channels with their type, ID, name, and event subscriptions. * Can list channels for a specific project or all projects. */ -import { jsonResult } from "openclaw/plugin-sdk"; import type { PluginContext } from "../../context.js"; import type { ToolContext } from "../../types.js"; import { readProjects } from "../../projects/index.js"; -import { requireWorkspaceDir } from "../helpers.js"; +import { jsonResult, requireWorkspaceDir } from "../helpers.js"; export function createChannelListTool(_ctx: PluginContext) { return (toolCtx: ToolContext) => ({ diff --git a/lib/tools/admin/channel-unlink.ts b/lib/tools/admin/channel-unlink.ts index ed1e3642..ebac36a7 100644 --- a/lib/tools/admin/channel-unlink.ts +++ b/lib/tools/admin/channel-unlink.ts @@ -5,12 +5,11 @@ * exists and prevents removing the last channel from a project (projects must * have at least one notification endpoint). */ -import { jsonResult } from "openclaw/plugin-sdk"; import type { PluginContext } from "../../context.js"; import type { ToolContext } from "../../types.js"; import { readProjects, writeProjects } from "../../projects/index.js"; import { log as auditLog } from "../../audit.js"; -import { requireWorkspaceDir } from "../helpers.js"; +import { jsonResult, requireWorkspaceDir } from "../helpers.js"; export function createChannelUnlinkTool(_ctx: PluginContext) { return (toolCtx: ToolContext) => ({ diff --git a/lib/tools/admin/config-diff.ts b/lib/tools/admin/config-diff.ts index 33afa135..a2606e14 100644 --- a/lib/tools/admin/config-diff.ts +++ b/lib/tools/admin/config-diff.ts @@ -6,10 +6,9 @@ */ import fs from "node:fs/promises"; import path from "node:path"; -import { jsonResult } from "openclaw/plugin-sdk"; import type { ToolContext } from "../../types.js"; import type { PluginContext } from "../../context.js"; -import { requireWorkspaceDir } from "../helpers.js"; +import { jsonResult, requireWorkspaceDir } from "../helpers.js"; import { WORKFLOW_YAML_TEMPLATE } from "../../setup/templates.js"; import { DATA_DIR } from "../../setup/migrate-layout.js"; diff --git a/lib/tools/admin/config-reset.ts b/lib/tools/admin/config-reset.ts index 4cc0966f..7e68611f 100644 --- a/lib/tools/admin/config-reset.ts +++ b/lib/tools/admin/config-reset.ts @@ -6,10 +6,9 @@ */ import fs from "node:fs/promises"; import path from "node:path"; -import { jsonResult } from "openclaw/plugin-sdk"; import type { ToolContext } from "../../types.js"; import type { PluginContext } from "../../context.js"; -import { requireWorkspaceDir } from "../helpers.js"; +import { jsonResult, requireWorkspaceDir } from "../helpers.js"; import { backupAndWrite } from "../../setup/workspace.js"; import { WORKFLOW_YAML_TEMPLATE, DEFAULT_ROLE_INSTRUCTIONS } from "../../setup/templates.js"; import { getAllRoleIds } from "../../roles/index.js"; diff --git a/lib/tools/admin/config.ts b/lib/tools/admin/config.ts index 4e5284e2..f9209a3d 100644 --- a/lib/tools/admin/config.ts +++ b/lib/tools/admin/config.ts @@ -8,7 +8,7 @@ */ import fs from "node:fs/promises"; import path from "node:path"; -import { jsonResult } from "openclaw/plugin-sdk"; +import { jsonResult } from "../helpers.js"; import type { ToolContext } from "../../types.js"; import type { PluginContext } from "../../context.js"; import { writeAllDefaults, backupAndWrite, fileExists } from "../../setup/workspace.js"; diff --git a/lib/tools/admin/health.ts b/lib/tools/admin/health.ts index 6ba03d3f..04702d4e 100644 --- a/lib/tools/admin/health.ts +++ b/lib/tools/admin/health.ts @@ -12,13 +12,12 @@ * * Read-only by default (surfaces issues). Pass fix=true to apply fixes. */ -import { jsonResult } from "openclaw/plugin-sdk"; import type { PluginContext } from "../../context.js"; import type { ToolContext } from "../../types.js"; import { readProjects, getProject } from "../../projects/index.js"; import { log as auditLog } from "../../audit.js"; import { checkWorkerHealth, scanOrphanedLabels, fetchGatewaySessions, type HealthFix } from "../../services/heartbeat/health.js"; -import { requireWorkspaceDir, resolveProvider } from "../helpers.js"; +import { jsonResult, requireWorkspaceDir, resolveProvider } from "../helpers.js"; export function createHealthTool(ctx: PluginContext) { return (toolCtx: ToolContext) => ({ diff --git a/lib/tools/admin/onboard.ts b/lib/tools/admin/onboard.ts index 8ac3dad8..7cf3cd08 100644 --- a/lib/tools/admin/onboard.ts +++ b/lib/tools/admin/onboard.ts @@ -3,7 +3,7 @@ * * Returns step-by-step guidance. Call this before setup. */ -import { jsonResult } from "openclaw/plugin-sdk"; +import { jsonResult } from "../helpers.js"; import type { ToolContext } from "../../types.js"; import type { PluginContext } from "../../context.js"; import { isPluginConfigured, hasWorkspaceFiles, buildOnboardToolContext, buildReconfigContext } from "../../setup/onboarding.js"; diff --git a/lib/tools/admin/project-register.ts b/lib/tools/admin/project-register.ts index 3ed4a27e..d6ecf229 100644 --- a/lib/tools/admin/project-register.ts +++ b/lib/tools/admin/project-register.ts @@ -6,7 +6,7 @@ * * Replaces the manual steps of running glab/gh label create + editing projects.json. */ -import { jsonResult } from "openclaw/plugin-sdk"; +import { jsonResult } from "../helpers.js"; import type { ToolContext } from "../../types.js"; import type { PluginContext } from "../../context.js"; import fs from "node:fs/promises"; diff --git a/lib/tools/admin/project-status.ts b/lib/tools/admin/project-status.ts index 2ff84cd6..9201b177 100644 --- a/lib/tools/admin/project-status.ts +++ b/lib/tools/admin/project-status.ts @@ -5,10 +5,9 @@ * workflow config, and execution settings. No issue-tracker API calls. * Use `tasks_status` for live issue counts. */ -import { jsonResult } from "openclaw/plugin-sdk"; import type { ToolContext } from "../../types.js"; import type { PluginContext } from "../../context.js"; -import { requireWorkspaceDir, resolveChannelId, resolveProject } from "../helpers.js"; +import { jsonResult, requireWorkspaceDir, resolveChannelId, resolveProject } from "../helpers.js"; import { ExecutionMode, StateType } from "../../workflow/index.js"; import { loadConfig } from "../../config/index.js"; import { loadInstanceName } from "../../instance.js"; diff --git a/lib/tools/admin/setup.ts b/lib/tools/admin/setup.ts index a29be596..942b2939 100644 --- a/lib/tools/admin/setup.ts +++ b/lib/tools/admin/setup.ts @@ -4,7 +4,7 @@ * Creates agent, configures model levels, writes workspace files. * Thin wrapper around lib/setup/. */ -import { jsonResult } from "openclaw/plugin-sdk"; +import { jsonResult } from "../helpers.js"; import type { ToolContext } from "../../types.js"; import type { PluginContext } from "../../context.js"; import { runSetup, type SetupOpts } from "../../setup/index.js"; diff --git a/lib/tools/admin/sync-labels.ts b/lib/tools/admin/sync-labels.ts index 27e5786c..34629d62 100644 --- a/lib/tools/admin/sync-labels.ts +++ b/lib/tools/admin/sync-labels.ts @@ -8,10 +8,9 @@ * Calls provider.ensureLabel() directly instead of provider.ensureAllStateLabels() * so that custom workflow states from workspace/project overrides are included. */ -import { jsonResult } from "openclaw/plugin-sdk"; import type { ToolContext } from "../../types.js"; import type { PluginContext } from "../../context.js"; -import { requireWorkspaceDir } from "../helpers.js"; +import { jsonResult, requireWorkspaceDir } from "../helpers.js"; import { readProjects, getProject } from "../../projects/index.js"; import { createProvider } from "../../providers/index.js"; import { loadConfig } from "../../config/index.js"; diff --git a/lib/tools/admin/workflow-guide.ts b/lib/tools/admin/workflow-guide.ts index 33cb4df8..589cce98 100644 --- a/lib/tools/admin/workflow-guide.ts +++ b/lib/tools/admin/workflow-guide.ts @@ -8,10 +8,9 @@ * * No parameters, no side effects — pure documentation. */ -import { jsonResult } from "openclaw/plugin-sdk"; import type { PluginContext } from "../../context.js"; import type { ToolContext } from "../../types.js"; -import { requireWorkspaceDir } from "../helpers.js"; +import { jsonResult, requireWorkspaceDir } from "../helpers.js"; import { DATA_DIR } from "../../setup/migrate-layout.js"; export function createWorkflowGuideTool(_ctx: PluginContext) { diff --git a/lib/tools/helpers.ts b/lib/tools/helpers.ts index 3e0ab2dc..25f89313 100644 --- a/lib/tools/helpers.ts +++ b/lib/tools/helpers.ts @@ -5,6 +5,14 @@ * project resolution, provider creation. */ import type { ToolContext } from "../types.js"; + +/** + * Wrap a payload as a tool result with pretty-printed JSON text. + * Replaces the removed `jsonResult` export from openclaw/plugin-sdk. + */ +export function jsonResult(payload: unknown): { content: { type: "text"; text: string }[]; details: unknown } { + return { content: [{ type: "text", text: JSON.stringify(payload, null, 2) }], details: payload }; +} import type { RunCommand } from "../context.js"; import { readProjects, getProject, type Project, type ProjectsData } from "../projects/index.js"; import { createProvider, type ProviderWithType } from "../providers/index.js"; diff --git a/lib/tools/tasks/research-task.ts b/lib/tools/tasks/research-task.ts index 403202e0..0bd40061 100644 --- a/lib/tools/tasks/research-task.ts +++ b/lib/tools/tasks/research-task.ts @@ -12,14 +12,13 @@ * → architect calls work_finish(result="done") → "Researching" → "Done" (issue closed) * → operator reviews created tasks in Planning, moves to "To Do" when ready */ -import { jsonResult } from "openclaw/plugin-sdk"; import type { ToolContext } from "../../types.js"; import type { PluginContext } from "../../context.js"; import type { StateLabel } from "../../providers/provider.js"; import { getRoleWorker, countActiveSlots } from "../../projects/index.js"; import { dispatchTask } from "../../dispatch/index.js"; import { log as auditLog } from "../../audit.js"; -import { requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider, autoAssignOwnerLabel, applyNotifyLabel } from "../helpers.js"; +import { jsonResult, requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider, autoAssignOwnerLabel, applyNotifyLabel } from "../helpers.js"; import { loadConfig } from "../../config/index.js"; import { getActiveLabel } from "../../workflow/index.js"; import { selectLevel } from "../../roles/model-selector.js"; diff --git a/lib/tools/tasks/task-attach.ts b/lib/tools/tasks/task-attach.ts index de2cdf85..767294b3 100644 --- a/lib/tools/tasks/task-attach.ts +++ b/lib/tools/tasks/task-attach.ts @@ -6,11 +6,10 @@ * - Manually attach a local file to an issue * - View attachment metadata and local paths */ -import { jsonResult } from "openclaw/plugin-sdk"; import type { PluginContext } from "../../context.js"; import type { ToolContext } from "../../types.js"; import { log as auditLog } from "../../audit.js"; -import { requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider, autoAssignOwnerLabel, applyNotifyLabel } from "../helpers.js"; +import { jsonResult, requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider, autoAssignOwnerLabel, applyNotifyLabel } from "../helpers.js"; import { listAttachments, saveAttachment, diff --git a/lib/tools/tasks/task-comment.ts b/lib/tools/tasks/task-comment.ts index 3a7b12da..a3a96a39 100644 --- a/lib/tools/tasks/task-comment.ts +++ b/lib/tools/tasks/task-comment.ts @@ -6,11 +6,10 @@ * - Developer worker posts implementation notes * - Orchestrator adds summary comments */ -import { jsonResult } from "openclaw/plugin-sdk"; import type { PluginContext } from "../../context.js"; import type { ToolContext } from "../../types.js"; import { log as auditLog } from "../../audit.js"; -import { requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider, autoAssignOwnerLabel, applyNotifyLabel } from "../helpers.js"; +import { jsonResult, requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider, autoAssignOwnerLabel, applyNotifyLabel } from "../helpers.js"; import { getAllRoleIds, getFallbackEmoji } from "../../roles/index.js"; /** Valid author roles for attribution — all registry roles + orchestrator */ diff --git a/lib/tools/tasks/task-create.ts b/lib/tools/tasks/task-create.ts index 28d29f90..c2d30104 100644 --- a/lib/tools/tasks/task-create.ts +++ b/lib/tools/tasks/task-create.ts @@ -9,12 +9,11 @@ * - A sub-agent finds a bug and needs to file a follow-up issue * - Breaking down an epic into smaller tasks */ -import { jsonResult } from "openclaw/plugin-sdk"; import type { PluginContext } from "../../context.js"; import type { ToolContext } from "../../types.js"; import { log as auditLog } from "../../audit.js"; import { DEFAULT_WORKFLOW } from "../../workflow/index.js"; -import { requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider, autoAssignOwnerLabel, applyNotifyLabel } from "../helpers.js"; +import { jsonResult, requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider, autoAssignOwnerLabel, applyNotifyLabel } from "../helpers.js"; /** Derive the initial state label from the workflow config. */ const INITIAL_LABEL = DEFAULT_WORKFLOW.states[DEFAULT_WORKFLOW.initial].label; diff --git a/lib/tools/tasks/task-edit-body.ts b/lib/tools/tasks/task-edit-body.ts index 93bba48b..deadc8b7 100644 --- a/lib/tools/tasks/task-edit-body.ts +++ b/lib/tools/tasks/task-edit-body.ts @@ -8,13 +8,12 @@ * DevClaw adds an explicit audit entry with who, when, and what changed. * Optionally posts an auto-comment on the issue for traceability. */ -import { jsonResult } from "openclaw/plugin-sdk"; import type { PluginContext } from "../../context.js"; import type { ToolContext } from "../../types.js"; import { log as auditLog } from "../../audit.js"; import { loadConfig } from "../../config/index.js"; import { getInitialStateLabel, getCurrentStateLabel } from "../../workflow/index.js"; -import { requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider, autoAssignOwnerLabel, applyNotifyLabel } from "../helpers.js"; +import { jsonResult, requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider, autoAssignOwnerLabel, applyNotifyLabel } from "../helpers.js"; export function createTaskEditBodyTool(ctx: PluginContext) { return (toolCtx: ToolContext) => ({ diff --git a/lib/tools/tasks/task-list.ts b/lib/tools/tasks/task-list.ts index 5e27aaaa..0d95e11f 100644 --- a/lib/tools/tasks/task-list.ts +++ b/lib/tools/tasks/task-list.ts @@ -4,11 +4,10 @@ * Lists issues grouped by state label with optional filtering by state type, * specific label, or text search. Supports terminal (closed) issues. */ -import { jsonResult } from "openclaw/plugin-sdk"; import type { PluginContext } from "../../context.js"; import type { ToolContext } from "../../types.js"; import { log as auditLog } from "../../audit.js"; -import { requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider } from "../helpers.js"; +import { jsonResult, requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider } from "../helpers.js"; import { loadWorkflow, StateType, findStateByLabel } from "../../workflow/index.js"; export function createTaskListTool(ctx: PluginContext) { diff --git a/lib/tools/tasks/task-owner.ts b/lib/tools/tasks/task-owner.ts index 6aecc1be..47c39de9 100644 --- a/lib/tools/tasks/task-owner.ts +++ b/lib/tools/tasks/task-owner.ts @@ -5,10 +5,9 @@ * owns them for queue scanning and dispatch. Supports claiming a * single issue or all unclaimed queued issues for a project. */ -import { jsonResult } from "openclaw/plugin-sdk"; import type { PluginContext } from "../../context.js"; import type { ToolContext } from "../../types.js"; -import { requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider } from "../helpers.js"; +import { jsonResult, requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider } from "../helpers.js"; import { loadConfig } from "../../config/index.js"; import { loadInstanceName } from "../../instance.js"; import { diff --git a/lib/tools/tasks/task-set-level.ts b/lib/tools/tasks/task-set-level.ts index 39fed954..456b8604 100644 --- a/lib/tools/tasks/task-set-level.ts +++ b/lib/tools/tasks/task-set-level.ts @@ -5,13 +5,12 @@ * applied as a role:level label and respected by the heartbeat when the * issue is later advanced via task_start. */ -import { jsonResult } from "openclaw/plugin-sdk"; import type { PluginContext } from "../../context.js"; import type { ToolContext } from "../../types.js"; import { log as auditLog } from "../../audit.js"; import { StateType, findStateByLabel, getCurrentStateLabel, getRoleLabelColor } from "../../workflow/index.js"; import { loadConfig } from "../../config/index.js"; -import { requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider, autoAssignOwnerLabel, applyNotifyLabel } from "../helpers.js"; +import { jsonResult, requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider, autoAssignOwnerLabel, applyNotifyLabel } from "../helpers.js"; export function createTaskSetLevelTool(ctx: PluginContext) { return (toolCtx: ToolContext) => ({ diff --git a/lib/tools/tasks/task-start.ts b/lib/tools/tasks/task-start.ts index 35b53764..c1c6fc82 100644 --- a/lib/tools/tasks/task-start.ts +++ b/lib/tools/tasks/task-start.ts @@ -8,7 +8,6 @@ * The heartbeat is the sole dispatcher — this tool only places issues in * queues, never dispatches workers directly. */ -import { jsonResult } from "openclaw/plugin-sdk"; import type { PluginContext } from "../../context.js"; import type { ToolContext } from "../../types.js"; import { log as auditLog } from "../../audit.js"; @@ -26,7 +25,7 @@ import { } from "../../workflow/index.js"; import { getLevelsForRole } from "../../roles/index.js"; import { loadConfig } from "../../config/index.js"; -import { requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider, autoAssignOwnerLabel, applyNotifyLabel } from "../helpers.js"; +import { jsonResult, requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider, autoAssignOwnerLabel, applyNotifyLabel } from "../helpers.js"; export function createTaskStartTool(ctx: PluginContext) { return (toolCtx: ToolContext) => ({ diff --git a/lib/tools/tasks/tasks-status.ts b/lib/tools/tasks/tasks-status.ts index 164d32ba..448ee421 100644 --- a/lib/tools/tasks/tasks-status.ts +++ b/lib/tools/tasks/tasks-status.ts @@ -4,12 +4,11 @@ * Fetches all non-terminal issues grouped by state type (hold, active, queue). * Use `project_status` for instant local info, this tool for live issue data. */ -import { jsonResult } from "openclaw/plugin-sdk"; import type { ToolContext } from "../../types.js"; import type { PluginContext } from "../../context.js"; import { log as auditLog } from "../../audit.js"; import { getStateLabelsByType } from "../../services/queue.js"; -import { requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider } from "../helpers.js"; +import { jsonResult, requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider } from "../helpers.js"; import { loadConfig } from "../../config/index.js"; type IssueSummary = { id: number; title: string; url: string }; diff --git a/lib/tools/worker/work-finish.ts b/lib/tools/worker/work-finish.ts index 4b3ba989..db3d5608 100644 --- a/lib/tools/worker/work-finish.ts +++ b/lib/tools/worker/work-finish.ts @@ -7,7 +7,6 @@ * All roles (including architect) use the standard pipeline via executeCompletion. * Architect workflow: Researching → Done (done, closes issue), Researching → Refining (blocked). */ -import { jsonResult } from "openclaw/plugin-sdk"; import { readFile } from "node:fs/promises"; import { join } from "node:path"; import type { ToolContext } from "../../types.js"; @@ -16,7 +15,7 @@ import { getRoleWorker, resolveRepoPath, findSlotByIssue } from "../../projects/ import { executeCompletion, getRule } from "../../services/pipeline.js"; import { log as auditLog } from "../../audit.js"; import { DATA_DIR } from "../../setup/migrate-layout.js"; -import { requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider } from "../helpers.js"; +import { jsonResult, requireWorkspaceDir, resolveChannelId, resolveProject, resolveProvider } from "../helpers.js"; import { getAllRoleIds, isValidResult, getCompletionResults } from "../../roles/index.js"; import { loadWorkflow } from "../../workflow/index.js"; diff --git a/package-lock.json b/package-lock.json index 47d03855..ad84d2a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -969,6 +969,14 @@ "url": "https://github.com/discordjs/discord.js?sponsor" } }, + "node_modules/@discordjs/voice/node_modules/opusscript": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/opusscript/-/opusscript-0.0.8.tgz", + "integrity": "sha512-VSTi1aWFuCkRCVq+tx/BQ5q9fMnQ9pVZ3JU4UHKqTkf0ED3fKEPdr+gKAAl3IA2hj9rrP6iyq3hlcJq3HELtNQ==", + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/@discordjs/voice/node_modules/prism-media": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.3.5.tgz",