@xopcai/xopc 0.0.20 → 0.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/extensions/feishu/src/adapters/cli-login.d.ts +8 -0
- package/dist/extensions/feishu/src/adapters/cli-login.js +225 -0
- package/dist/extensions/feishu/src/adapters/cli-login.js.map +1 -0
- package/dist/extensions/feishu/src/adapters/onboard-cli.js +1 -105
- package/dist/extensions/feishu/src/adapters/onboard-cli.js.map +1 -1
- package/dist/extensions/feishu/src/auth/app-registration.d.ts +47 -0
- package/dist/extensions/feishu/src/auth/app-registration.js +122 -0
- package/dist/extensions/feishu/src/auth/app-registration.js.map +1 -0
- package/dist/extensions/feishu/src/plugin.d.ts +2 -0
- package/dist/extensions/feishu/src/plugin.js +2 -0
- package/dist/extensions/feishu/src/plugin.js.map +1 -1
- package/dist/extensions/telegram/src/inbound-processor.js +1 -1
- package/dist/extensions/telegram/src/plugin.d.ts +1 -1
- package/dist/extensions/telegram/src/plugin.js +1 -1
- package/dist/extensions/telegram/src/routing-integration.js +2 -2
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/extensions/weixin/src/plugin.js +1 -1
- package/dist/gateway/static/root/assets/{agents-DbLV2ldC.js → agents-MbH57-L9.js} +2 -2
- package/dist/gateway/static/root/assets/{agents-DbLV2ldC.js.map → agents-MbH57-L9.js.map} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-CDRSbv3l.js → apps-page-3i3DvI7i.js} +2 -2
- package/dist/gateway/static/root/assets/{apps-page-CDRSbv3l.js.map → apps-page-3i3DvI7i.js.map} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-CcuSzoB6.js +9 -0
- package/dist/gateway/static/root/assets/channels-settings-CcuSzoB6.js.map +1 -0
- package/dist/gateway/static/root/assets/{cron-page-D-fhl446.js → cron-page-Be1h9Yub.js} +2 -2
- package/dist/gateway/static/root/assets/{cron-page-D-fhl446.js.map → cron-page-Be1h9Yub.js.map} +1 -1
- package/dist/gateway/static/root/assets/{cron-utils-DqyPqEDr.js → cron-utils-CR97EvZS.js} +2 -2
- package/dist/gateway/static/root/assets/{cron-utils-DqyPqEDr.js.map → cron-utils-CR97EvZS.js.map} +1 -1
- package/dist/gateway/static/root/assets/{dist-BTNDXpKu.js → dist-r_Gy-XJv.js} +2 -2
- package/dist/gateway/static/root/assets/{dist-BTNDXpKu.js.map → dist-r_Gy-XJv.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-CiOtMG3X.js → extension-debug-page-QfYEYruq.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-debug-page-CiOtMG3X.js.map → extension-debug-page-QfYEYruq.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-a59AFw7Q.js → extension-page-4FW-BmKG.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-page-a59AFw7Q.js.map → extension-page-4FW-BmKG.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-BQyLvxBY.js → extension-settings-page-E_Wq9LL8.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-settings-page-BQyLvxBY.js.map → extension-settings-page-E_Wq9LL8.js.map} +1 -1
- package/dist/gateway/static/root/assets/{index-fGYWcYhm.js → index-CcQtNJKo.js} +60 -54
- package/dist/gateway/static/root/assets/{index-fGYWcYhm.js.map → index-CcQtNJKo.js.map} +1 -1
- package/dist/gateway/static/root/assets/index-D9Wmfh2f.css +1 -0
- package/dist/gateway/static/root/assets/{logs-page-DMSWW0-k.js → logs-page-DFhTU-kG.js} +2 -2
- package/dist/gateway/static/root/assets/{logs-page-DMSWW0-k.js.map → logs-page-DFhTU-kG.js.map} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-CL2E3nPk.js → sessions-page-wmnnIj6Z.js} +2 -2
- package/dist/gateway/static/root/assets/{sessions-page-CL2E3nPk.js.map → sessions-page-wmnnIj6Z.js.map} +1 -1
- package/dist/gateway/static/root/assets/settings-page-BTmUXY4s.js +2 -0
- package/dist/gateway/static/root/assets/settings-page-BTmUXY4s.js.map +1 -0
- package/dist/gateway/static/root/assets/{skills-page-0rmNu4AL.js → skills-page-D-fRbJG0.js} +2 -2
- package/dist/gateway/static/root/assets/{skills-page-0rmNu4AL.js.map → skills-page-D-fRbJG0.js.map} +1 -1
- package/dist/gateway/static/root/index.html +2 -2
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.js +6 -6
- package/dist/src/agent/context/workspace-seed.js +1 -1
- package/dist/src/agent/ipc/bus.js +1 -1
- package/dist/src/agent/ipc/inbox.js +1 -1
- package/dist/src/agent/ipc/socket.js +1 -1
- package/dist/src/agent/memory/builtin-memory-store.d.ts +2 -1
- package/dist/src/agent/memory/builtin-memory-store.js +7 -6
- package/dist/src/agent/memory/builtin-memory-store.js.map +1 -1
- package/dist/src/agent/models/manager.js +1 -1
- package/dist/src/agent/prompt/memory/index.d.ts +4 -2
- package/dist/src/agent/prompt/memory/index.js +22 -10
- package/dist/src/agent/prompt/memory/index.js.map +1 -1
- package/dist/src/agent/prompt/service-prompt-builder.js +1 -1
- package/dist/src/agent/service.js +5 -5
- package/dist/src/agent/skills/index.js +1 -1
- package/dist/src/agent/skills/scanner.js +1 -1
- package/dist/src/agent/skills/skill-manage-ops.js +1 -1
- package/dist/src/agent/skills/skill-manager.js +1 -1
- package/dist/src/agent/tools/factory.js +10 -3
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/index.d.ts +1 -1
- package/dist/src/agent/tools/memory-tool.d.ts +7 -2
- package/dist/src/agent/tools/memory-tool.js +11 -5
- package/dist/src/agent/tools/memory-tool.js.map +1 -1
- package/dist/src/agent/tools/send-media.js +1 -1
- package/dist/src/agent/tools/skill-manage-tool.js +1 -1
- package/dist/src/agent/tools/write.js +1 -1
- package/dist/src/auth/credentials.js +2 -2
- package/dist/src/auth/sync-provider-auth.js +1 -1
- package/dist/src/channels/attachments/inbound-persist.js +1 -1
- package/dist/src/channels/attachments/outbound-tts-persist.js +1 -1
- package/dist/src/channels/registry.d.ts +1 -1
- package/dist/src/channels/registry.js +25 -1
- package/dist/src/channels/registry.js.map +1 -1
- package/dist/src/chat-commands/builtins/config.js +3 -3
- package/dist/src/chat-commands/builtins/session.js +1 -1
- package/dist/src/chat-commands/context.js +1 -1
- package/dist/src/chat-commands/index.js +1 -1
- package/dist/src/chat-commands/processor.js +1 -1
- package/dist/src/cli/commands/agent.js +1 -1
- package/dist/src/cli/commands/channels.js +20 -2
- package/dist/src/cli/commands/channels.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
- package/dist/src/cli/commands/gateway/call.d.ts +2 -0
- package/dist/src/cli/commands/gateway/call.js +90 -0
- package/dist/src/cli/commands/gateway/call.js.map +1 -0
- package/dist/src/cli/commands/gateway/health.d.ts +2 -0
- package/dist/src/cli/commands/gateway/health.js +77 -0
- package/dist/src/cli/commands/gateway/health.js.map +1 -0
- package/dist/src/cli/commands/gateway/index.d.ts +3 -0
- package/dist/src/cli/commands/gateway/index.js +4 -1
- package/dist/src/cli/commands/gateway/probe.d.ts +2 -0
- package/dist/src/cli/commands/gateway/probe.js +102 -0
- package/dist/src/cli/commands/gateway/probe.js.map +1 -0
- package/dist/src/cli/commands/gateway/status.d.ts +0 -3
- package/dist/src/cli/commands/gateway/status.js +107 -24
- package/dist/src/cli/commands/gateway/status.js.map +1 -1
- package/dist/src/cli/commands/gateway.js +7 -1
- package/dist/src/cli/commands/gateway.js.map +1 -1
- package/dist/src/cli/commands/init.js +3 -3
- package/dist/src/cli/commands/update.js +19 -1
- package/dist/src/cli/commands/update.js.map +1 -1
- package/dist/src/cli/utils/gateway-client.d.ts +28 -0
- package/dist/src/cli/utils/gateway-client.js +115 -0
- package/dist/src/cli/utils/gateway-client.js.map +1 -0
- package/dist/src/config/index.js +2 -2
- package/dist/src/config/loader.js +1 -1
- package/dist/src/config/models-json.js +1 -1
- package/dist/src/config/paths-state.d.ts +4 -0
- package/dist/src/config/paths-state.js +9 -1
- package/dist/src/config/paths-state.js.map +1 -1
- package/dist/src/config/profile.js +2 -2
- package/dist/src/config/reload.d.ts +2 -0
- package/dist/src/config/reload.js +9 -1
- package/dist/src/config/reload.js.map +1 -1
- package/dist/src/config/rules.js +12 -2
- package/dist/src/config/rules.js.map +1 -1
- package/dist/src/cron/executor.js +2 -2
- package/dist/src/cron/persistence.js +1 -1
- package/dist/src/cron/run-log-store.js +1 -1
- package/dist/src/extensions/api.d.ts +6 -1
- package/dist/src/extensions/api.js +52 -1
- package/dist/src/extensions/api.js.map +1 -1
- package/dist/src/extensions/health.js +1 -1
- package/dist/src/extensions/loader.d.ts +6 -1
- package/dist/src/extensions/loader.js +21 -2
- package/dist/src/extensions/loader.js.map +1 -1
- package/dist/src/extensions/lockfile.js +1 -1
- package/dist/src/extensions/normalize-manifest.js +33 -0
- package/dist/src/extensions/normalize-manifest.js.map +1 -1
- package/dist/src/extensions/sdk/index.d.ts +1 -1
- package/dist/src/extensions/sdk/index.js.map +1 -1
- package/dist/src/extensions/types/core.d.ts +35 -1
- package/dist/src/extensions/types/manifest.d.ts +14 -0
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +3 -0
- package/dist/src/gateway/hono/lib/config-payload.js +1 -0
- package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
- package/dist/src/gateway/hono/oauth.js +1 -1
- package/dist/src/gateway/hono/routes/channels.js +111 -0
- package/dist/src/gateway/hono/routes/channels.js.map +1 -1
- package/dist/src/gateway/hono/routes/commands-skills.js +13 -2
- package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
- package/dist/src/gateway/hono/routes/config.js +82 -1
- package/dist/src/gateway/hono/routes/config.js.map +1 -1
- package/dist/src/gateway/hono/routes/public-gateway.js +17 -0
- package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +16 -0
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/hono/routes/status.js +31 -7
- package/dist/src/gateway/hono/routes/status.js.map +1 -1
- package/dist/src/gateway/hono/routes/update.js +118 -15
- package/dist/src/gateway/hono/routes/update.js.map +1 -1
- package/dist/src/gateway/hono/routes/workspace.js +2 -2
- package/dist/src/gateway/hono/sse.js +2 -2
- package/dist/src/gateway/index.js +1 -1
- package/dist/src/gateway/server.js +3 -0
- package/dist/src/gateway/server.js.map +1 -1
- package/dist/src/gateway/service.d.ts +23 -0
- package/dist/src/gateway/service.js +111 -4
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/workspace-heartbeat-path.js +1 -1
- package/dist/src/infra/update-check.js +54 -21
- package/dist/src/infra/update-check.js.map +1 -1
- package/dist/src/infra/update-lock.d.ts +13 -0
- package/dist/src/infra/update-lock.js +67 -0
- package/dist/src/infra/update-lock.js.map +1 -0
- package/dist/src/infra/update-runner.d.ts +6 -5
- package/dist/src/infra/update-runner.js +93 -13
- package/dist/src/infra/update-runner.js.map +1 -1
- package/dist/src/infra/update-startup.js +37 -11
- package/dist/src/infra/update-startup.js.map +1 -1
- package/dist/src/providers/index.js +2 -2
- package/dist/src/providers/model-registry.js +1 -1
- package/dist/src/session/config-store.js +1 -1
- package/dist/src/session/session-title.js +1 -1
- package/dist/src/session/store.js +3 -3
- package/dist/src/utils/logger/audit.js +1 -1
- package/dist/src/utils/logger/log-store.js +1 -1
- package/dist/src/utils/logger/rotation.js +1 -1
- package/dist/src/voice/tts/audio.js +1 -1
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/channels-settings-DyNnMN1-.js +0 -9
- package/dist/gateway/static/root/assets/channels-settings-DyNnMN1-.js.map +0 -1
- package/dist/gateway/static/root/assets/index-BQNdJlkw.css +0 -1
- package/dist/gateway/static/root/assets/settings-page-CSIVMAJE.js +0 -2
- package/dist/gateway/static/root/assets/settings-page-CSIVMAJE.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-tool.js","names":[],"sources":["../../../../src/agent/tools/memory-tool.ts"],"sourcesContent":["// Memory search tools for xopc agent\nimport { Type } from '@sinclair/typebox';\nimport type { AgentTool, AgentToolResult } from '@mariozechner/pi-agent-core';\nimport { memorySearch, memoryGet } from '../prompt/memory/index.js';\n\n// =============================================================================\n// Memory Search Tool\n// =============================================================================\nconst MemorySearchSchema = Type.Object({\n query: Type.String(),\n maxResults: Type.Optional(Type.Number()),\n minScore: Type.Optional(Type.Number()),\n});\n\ntype MemorySearchParams = { query: string; maxResults?: number; minScore?: number };\n\nexport function createMemorySearchTool(
|
|
1
|
+
{"version":3,"file":"memory-tool.js","names":[],"sources":["../../../../src/agent/tools/memory-tool.ts"],"sourcesContent":["// Memory search tools for xopc agent\nimport { Type } from '@sinclair/typebox';\nimport type { AgentTool, AgentToolResult } from '@mariozechner/pi-agent-core';\nimport { memorySearch, memoryGet } from '../prompt/memory/index.js';\n\n// =============================================================================\n// Memory Search Tool\n// =============================================================================\nconst MemorySearchSchema = Type.Object({\n query: Type.String(),\n maxResults: Type.Optional(Type.Number()),\n minScore: Type.Optional(Type.Number()),\n});\n\ntype MemorySearchParams = { query: string; maxResults?: number; minScore?: number };\n\nexport interface MemoryToolOptions {\n workspaceDir: string;\n /** Agent home curated memories dir, e.g. ~/.xopc/agents/<id>/memories/ */\n memoriesDir?: string;\n}\n\nexport function createMemorySearchTool(options: MemoryToolOptions): AgentTool {\n const { workspaceDir, memoriesDir } = options;\n return {\n name: 'memory_search',\n label: '🔍 Memory Search',\n description:\n 'Mandatory recall step: semantically search bootstrap MEMORY.md, agent-home `memories/*.md`, and workspace `memory/*.md` before answering questions about prior work, decisions, dates, people, preferences, or todos; returns top snippets with path + lines.',\n parameters: MemorySearchSchema,\n\n async execute(\n _toolCallId: string,\n params: any,\n _signal?: AbortSignal,\n ): Promise<AgentToolResult<{}>> {\n const { query, maxResults, minScore } = params as MemorySearchParams;\n\n try {\n const results = await memorySearch(workspaceDir, query, { maxResults, minScore, memoriesDir });\n const withCitations = results.map((entry) => ({\n ...entry,\n citation: `${entry.file}#L${entry.lineNumbers[0]}${entry.lineNumbers.length > 1 ? `-L${entry.lineNumbers[entry.lineNumbers.length - 1]}` : ''}`,\n snippet: `${entry.lines.trim()}\\n\\nSource: ${entry.file}#L${entry.lineNumbers[0]}${entry.lineNumbers.length > 1 ? `-L${entry.lineNumbers[entry.lineNumbers.length - 1]}` : ''}`,\n }));\n\n return {\n content: [{ type: 'text', text: JSON.stringify({ results: withCitations, provider: 'simple' }, null, 2) }],\n details: { results: withCitations },\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n content: [{ type: 'text', text: `Search error: ${message}` }],\n details: { error: message },\n };\n }\n },\n } as any;\n}\n\n// =============================================================================\n// Memory Get Tool\n// =============================================================================\nconst MemoryGetSchema = Type.Object({\n path: Type.String(),\n from: Type.Optional(Type.Number()),\n lines: Type.Optional(Type.Number()),\n});\n\ntype MemoryGetParams = { path: string; from?: number; lines?: number };\n\nexport function createMemoryGetTool(options: MemoryToolOptions): AgentTool {\n const { workspaceDir, memoriesDir } = options;\n return {\n name: 'memory_get',\n label: '📄 Memory Get',\n description: 'Safe snippet read from MEMORY.md or memory/*.md with optional from/lines; use after memory_search to pull only the needed lines and keep context small.',\n parameters: MemoryGetSchema,\n\n async execute(\n _toolCallId: string,\n params: any,\n _signal?: AbortSignal,\n ): Promise<AgentToolResult<{}>> {\n const { path, from, lines } = params as MemoryGetParams;\n\n try {\n const result = memoryGet(workspaceDir, path, from, lines, memoriesDir);\n if (!result) {\n return {\n content: [{ type: 'text', text: `File not found: ${path}` }],\n details: { path, text: '' },\n };\n }\n return {\n content: [{ type: 'text', text: result.content }],\n details: { path, text: result.content, lineNumbers: result.lineNumbers },\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n content: [{ type: 'text', text: `Read error: ${message}` }],\n details: { error: message },\n };\n }\n },\n } as any;\n}\n"],"mappings":";;;AAQA,MAAM,qBAAqB,KAAK,OAAO;CACrC,OAAO,KAAK,QAAQ;CACpB,YAAY,KAAK,SAAS,KAAK,QAAQ,CAAC;CACxC,UAAU,KAAK,SAAS,KAAK,QAAQ,CAAC;CACvC,CAAC;AAUF,SAAgB,uBAAuB,SAAuC;CAC5E,MAAM,EAAE,cAAc,gBAAgB;AACtC,QAAO;EACL,MAAM;EACN,OAAO;EACP,aACE;EACF,YAAY;EAEZ,MAAM,QACJ,aACA,QACA,SAC8B;GAC9B,MAAM,EAAE,OAAO,YAAY,aAAa;AAExC,OAAI;IAEF,MAAM,iBAAgB,MADA,aAAa,cAAc,OAAO;KAAE;KAAY;KAAU;KAAa,CAAC,EAChE,KAAK,WAAW;KAC5C,GAAG;KACH,UAAU,GAAG,MAAM,KAAK,IAAI,MAAM,YAAY,KAAK,MAAM,YAAY,SAAS,IAAI,KAAK,MAAM,YAAY,MAAM,YAAY,SAAS,OAAO;KAC3I,SAAS,GAAG,MAAM,MAAM,MAAM,CAAC,cAAc,MAAM,KAAK,IAAI,MAAM,YAAY,KAAK,MAAM,YAAY,SAAS,IAAI,KAAK,MAAM,YAAY,MAAM,YAAY,SAAS,OAAO;KAC5K,EAAE;AAEH,WAAO;KACL,SAAS,CAAC;MAAE,MAAM;MAAQ,MAAM,KAAK,UAAU;OAAE,SAAS;OAAe,UAAU;OAAU,EAAE,MAAM,EAAE;MAAE,CAAC;KAC1G,SAAS,EAAE,SAAS,eAAe;KACpC;YACM,KAAK;IACZ,MAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAChE,WAAO;KACL,SAAS,CAAC;MAAE,MAAM;MAAQ,MAAM,iBAAiB;MAAW,CAAC;KAC7D,SAAS,EAAE,OAAO,SAAS;KAC5B;;;EAGN;;AAMH,MAAM,kBAAkB,KAAK,OAAO;CAClC,MAAM,KAAK,QAAQ;CACnB,MAAM,KAAK,SAAS,KAAK,QAAQ,CAAC;CAClC,OAAO,KAAK,SAAS,KAAK,QAAQ,CAAC;CACpC,CAAC;AAIF,SAAgB,oBAAoB,SAAuC;CACzE,MAAM,EAAE,cAAc,gBAAgB;AACtC,QAAO;EACL,MAAM;EACN,OAAO;EACP,aAAa;EACb,YAAY;EAEZ,MAAM,QACJ,aACA,QACA,SAC8B;GAC9B,MAAM,EAAE,MAAM,MAAM,UAAU;AAE9B,OAAI;IACF,MAAM,SAAS,UAAU,cAAc,MAAM,MAAM,OAAO,YAAY;AACtE,QAAI,CAAC,OACH,QAAO;KACL,SAAS,CAAC;MAAE,MAAM;MAAQ,MAAM,mBAAmB;MAAQ,CAAC;KAC5D,SAAS;MAAE;MAAM,MAAM;MAAI;KAC5B;AAEH,WAAO;KACL,SAAS,CAAC;MAAE,MAAM;MAAQ,MAAM,OAAO;MAAS,CAAC;KACjD,SAAS;MAAE;MAAM,MAAM,OAAO;MAAS,aAAa,OAAO;MAAa;KACzE;YACM,KAAK;IACZ,MAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAChE,WAAO;KACL,SAAS,CAAC;MAAE,MAAM;MAAQ,MAAM,eAAe;MAAW,CAAC;KAC3D,SAAS,EAAE,OAAO,SAAS;KAC5B;;;EAGN"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { checkFileSafety } from "../prompt/safety.js";
|
|
2
2
|
import { resolvePathUnderWorkspace } from "./tool-paths.js";
|
|
3
|
-
import { readFile } from "fs/promises";
|
|
4
3
|
import { basename } from "node:path";
|
|
4
|
+
import { readFile } from "fs/promises";
|
|
5
5
|
import { Type } from "@sinclair/typebox";
|
|
6
6
|
//#region src/agent/tools/send-media.ts
|
|
7
7
|
const SendMediaSchema = Type.Object({
|
|
@@ -2,9 +2,9 @@ import { resolveStateDir } from "../../config/paths-state.js";
|
|
|
2
2
|
import { init_paths } from "../../config/paths.js";
|
|
3
3
|
import { createSkillConfigManager } from "../skills/config.js";
|
|
4
4
|
import { applyPatchToContent, atomicWriteUtf8, effectiveAgentWritePolicy, ensureCategorySegment, isPathInsideDir, maxSkillMdChars, maxSupportFileBytes, mutatableSkillOrNull, resolveCreateSkillDir, scanSkillDirOrError, validateSkillMdContent, validateSkillNameSegment, validateSupportingRelativePath } from "../skills/skill-manage-ops.js";
|
|
5
|
-
import { readFile, rm } from "fs/promises";
|
|
6
5
|
import { join } from "path";
|
|
7
6
|
import { existsSync, rmSync } from "fs";
|
|
7
|
+
import { readFile, rm } from "fs/promises";
|
|
8
8
|
import { Type } from "@sinclair/typebox";
|
|
9
9
|
//#region src/agent/tools/skill-manage-tool.ts
|
|
10
10
|
init_paths();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { checkFileSafety } from "../prompt/safety.js";
|
|
2
2
|
import { resolvePathUnderWorkspace } from "./tool-paths.js";
|
|
3
|
-
import { mkdir, writeFile } from "fs/promises";
|
|
4
3
|
import { dirname } from "path";
|
|
4
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
5
5
|
import { Type } from "@sinclair/typebox";
|
|
6
6
|
//#region src/agent/tools/write.ts
|
|
7
7
|
const MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { createLogger } from "../utils/logger/index.js";
|
|
3
3
|
import { init_logger } from "../utils/logger.js";
|
|
4
|
-
import { getApiKeyFromEnv, init_env_keys } from "../providers/env-keys.js";
|
|
5
4
|
import { init_paths, resolveAgentAuthProfilesPath, resolveAuthProfilesPath, resolveCredentialsDir, resolveOAuthPath } from "../config/paths.js";
|
|
6
|
-
import {
|
|
5
|
+
import { getApiKeyFromEnv, init_env_keys } from "../providers/env-keys.js";
|
|
7
6
|
import { dirname, join } from "path";
|
|
7
|
+
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
8
8
|
//#region src/auth/credentials.ts
|
|
9
9
|
function getCredentialResolver(options) {
|
|
10
10
|
return new CredentialResolver(options);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
|
|
2
3
|
import { init_paths, resolveAgentAuthProfilesPath, resolveAuthProfilesPath, resolveOAuthPath } from "../config/paths.js";
|
|
3
4
|
import { init_loader, loadConfig } from "../config/loader.js";
|
|
4
|
-
import { getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
|
|
5
5
|
import { existsSync, readFileSync } from "node:fs";
|
|
6
6
|
//#region src/auth/sync-provider-auth.ts
|
|
7
7
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
|
-
import { mkdir, writeFile } from "fs/promises";
|
|
4
3
|
import { join, resolve } from "path";
|
|
4
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
5
5
|
import { randomBytes } from "crypto";
|
|
6
6
|
//#region src/channels/attachments/inbound-persist.ts
|
|
7
7
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
|
-
import { mkdir, writeFile } from "fs/promises";
|
|
4
3
|
import { join, resolve } from "path";
|
|
4
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
5
5
|
import { randomBytes } from "crypto";
|
|
6
6
|
//#region src/channels/attachments/outbound-tts-persist.ts
|
|
7
7
|
/**
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Extension-provided channels register separately; keep protocol IDs aligned.
|
|
4
4
|
*/
|
|
5
5
|
import type { ChannelCapabilities } from './plugin-types.js';
|
|
6
|
-
export declare const CHAT_CHANNEL_ORDER: readonly ["telegram", "weixin"];
|
|
6
|
+
export declare const CHAT_CHANNEL_ORDER: readonly ["telegram", "weixin", "feishu"];
|
|
7
7
|
export type ChatChannelId = (typeof CHAT_CHANNEL_ORDER)[number];
|
|
8
8
|
export interface ChatChannelMeta {
|
|
9
9
|
id: ChatChannelId;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
//#region src/channels/registry.ts
|
|
2
|
-
const CHAT_CHANNEL_ORDER = [
|
|
2
|
+
const CHAT_CHANNEL_ORDER = [
|
|
3
|
+
"telegram",
|
|
4
|
+
"weixin",
|
|
5
|
+
"feishu"
|
|
6
|
+
];
|
|
3
7
|
const CHAT_CHANNEL_META = {
|
|
4
8
|
telegram: {
|
|
5
9
|
id: "telegram",
|
|
@@ -41,6 +45,26 @@ const CHAT_CHANNEL_META = {
|
|
|
41
45
|
outbound: { textChunkLimit: 4e3 },
|
|
42
46
|
queue: { debounceMs: 0 }
|
|
43
47
|
}
|
|
48
|
+
},
|
|
49
|
+
feishu: {
|
|
50
|
+
id: "feishu",
|
|
51
|
+
label: "Feishu",
|
|
52
|
+
description: "Feishu/Lark enterprise messaging (Socket Mode)",
|
|
53
|
+
capabilities: {
|
|
54
|
+
chatTypes: ["direct", "channel"],
|
|
55
|
+
reactions: true,
|
|
56
|
+
threads: true,
|
|
57
|
+
media: true,
|
|
58
|
+
polls: false,
|
|
59
|
+
nativeCommands: false,
|
|
60
|
+
blockStreaming: false,
|
|
61
|
+
edit: true,
|
|
62
|
+
reply: true
|
|
63
|
+
},
|
|
64
|
+
dock: {
|
|
65
|
+
outbound: { textChunkLimit: 4e3 },
|
|
66
|
+
queue: { debounceMs: 0 }
|
|
67
|
+
}
|
|
44
68
|
}
|
|
45
69
|
};
|
|
46
70
|
function getChatChannelMeta(id) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","names":[],"sources":["../../../src/channels/registry.ts"],"sourcesContent":["/**\n * Built-in chat channel registry: stable ordering and UI-facing metadata.\n * Extension-provided channels register separately; keep protocol IDs aligned.\n */\n\nimport type { ChannelCapabilities } from './plugin-types.js';\n\nexport const CHAT_CHANNEL_ORDER = ['telegram', 'weixin'] as const;\n\nexport type ChatChannelId = (typeof CHAT_CHANNEL_ORDER)[number];\n\nexport interface ChatChannelMeta {\n id: ChatChannelId;\n label: string;\n description: string;\n capabilities: ChannelCapabilities;\n /** Optional UI/dock tuning (queue debounce, outbound chunk size). */\n dock?: {\n outbound?: { textChunkLimit?: number };\n queue?: { debounceMs?: number };\n };\n}\n\nconst DEFAULT_CAPABILITIES: ChannelCapabilities = {\n chatTypes: ['direct', 'group', 'channel', 'thread'],\n reactions: true,\n threads: true,\n media: true,\n polls: false,\n nativeCommands: true,\n blockStreaming: true,\n};\n\nconst WEIXIN_CAPABILITIES: ChannelCapabilities = {\n chatTypes: ['direct'],\n reactions: false,\n threads: false,\n media: true,\n polls: false,\n nativeCommands: false,\n blockStreaming: true,\n};\n\nconst CHAT_CHANNEL_META: Record<ChatChannelId, ChatChannelMeta> = {\n telegram: {\n id: 'telegram',\n label: 'Telegram',\n description: 'Telegram Bot API (GrammY)',\n capabilities: DEFAULT_CAPABILITIES,\n dock: {\n outbound: { textChunkLimit: 4000 },\n queue: { debounceMs: 300 },\n },\n },\n weixin: {\n id: 'weixin',\n label: 'Weixin',\n description: 'WeChat via Tencent ilink (QR login)',\n capabilities: WEIXIN_CAPABILITIES,\n dock: {\n outbound: { textChunkLimit: 4000 },\n queue: { debounceMs: 0 },\n },\n },\n};\n\nexport function getChatChannelMeta(id: ChatChannelId): ChatChannelMeta {\n return CHAT_CHANNEL_META[id];\n}\n\nexport function isChatChannelId(id: string): id is ChatChannelId {\n return (CHAT_CHANNEL_ORDER as readonly string[]).includes(id);\n}\n\nexport function listChatChannelMeta(): ChatChannelMeta[] {\n return CHAT_CHANNEL_ORDER.map((id) => CHAT_CHANNEL_META[id]);\n}\n"],"mappings":";AAOA,MAAa,qBAAqB
|
|
1
|
+
{"version":3,"file":"registry.js","names":[],"sources":["../../../src/channels/registry.ts"],"sourcesContent":["/**\n * Built-in chat channel registry: stable ordering and UI-facing metadata.\n * Extension-provided channels register separately; keep protocol IDs aligned.\n */\n\nimport type { ChannelCapabilities } from './plugin-types.js';\n\nexport const CHAT_CHANNEL_ORDER = ['telegram', 'weixin', 'feishu'] as const;\n\nexport type ChatChannelId = (typeof CHAT_CHANNEL_ORDER)[number];\n\nexport interface ChatChannelMeta {\n id: ChatChannelId;\n label: string;\n description: string;\n capabilities: ChannelCapabilities;\n /** Optional UI/dock tuning (queue debounce, outbound chunk size). */\n dock?: {\n outbound?: { textChunkLimit?: number };\n queue?: { debounceMs?: number };\n };\n}\n\nconst DEFAULT_CAPABILITIES: ChannelCapabilities = {\n chatTypes: ['direct', 'group', 'channel', 'thread'],\n reactions: true,\n threads: true,\n media: true,\n polls: false,\n nativeCommands: true,\n blockStreaming: true,\n};\n\nconst WEIXIN_CAPABILITIES: ChannelCapabilities = {\n chatTypes: ['direct'],\n reactions: false,\n threads: false,\n media: true,\n polls: false,\n nativeCommands: false,\n blockStreaming: true,\n};\n\nconst FEISHU_CAPABILITIES: ChannelCapabilities = {\n chatTypes: ['direct', 'channel'],\n reactions: true,\n threads: true,\n media: true,\n polls: false,\n nativeCommands: false,\n blockStreaming: false,\n edit: true,\n reply: true,\n};\n\nconst CHAT_CHANNEL_META: Record<ChatChannelId, ChatChannelMeta> = {\n telegram: {\n id: 'telegram',\n label: 'Telegram',\n description: 'Telegram Bot API (GrammY)',\n capabilities: DEFAULT_CAPABILITIES,\n dock: {\n outbound: { textChunkLimit: 4000 },\n queue: { debounceMs: 300 },\n },\n },\n weixin: {\n id: 'weixin',\n label: 'Weixin',\n description: 'WeChat via Tencent ilink (QR login)',\n capabilities: WEIXIN_CAPABILITIES,\n dock: {\n outbound: { textChunkLimit: 4000 },\n queue: { debounceMs: 0 },\n },\n },\n feishu: {\n id: 'feishu',\n label: 'Feishu',\n description: 'Feishu/Lark enterprise messaging (Socket Mode)',\n capabilities: FEISHU_CAPABILITIES,\n dock: {\n outbound: { textChunkLimit: 4000 },\n queue: { debounceMs: 0 },\n },\n },\n};\n\nexport function getChatChannelMeta(id: ChatChannelId): ChatChannelMeta {\n return CHAT_CHANNEL_META[id];\n}\n\nexport function isChatChannelId(id: string): id is ChatChannelId {\n return (CHAT_CHANNEL_ORDER as readonly string[]).includes(id);\n}\n\nexport function listChatChannelMeta(): ChatChannelMeta[] {\n return CHAT_CHANNEL_ORDER.map((id) => CHAT_CHANNEL_META[id]);\n}\n"],"mappings":";AAOA,MAAa,qBAAqB;CAAC;CAAY;CAAU;CAAS;AAgDlE,MAAM,oBAA4D;CAChE,UAAU;EACR,IAAI;EACJ,OAAO;EACP,aAAa;EACb,cAAc;GApChB,WAAW;IAAC;IAAU;IAAS;IAAW;IAAS;GACnD,WAAW;GACX,SAAS;GACT,OAAO;GACP,OAAO;GACP,gBAAgB;GAChB,gBAAgB;GA8BoB;EAClC,MAAM;GACJ,UAAU,EAAE,gBAAgB,KAAM;GAClC,OAAO,EAAE,YAAY,KAAK;GAC3B;EACF;CACD,QAAQ;EACN,IAAI;EACJ,OAAO;EACP,aAAa;EACb,cAAc;GApChB,WAAW,CAAC,SAAS;GACrB,WAAW;GACX,SAAS;GACT,OAAO;GACP,OAAO;GACP,gBAAgB;GAChB,gBAAgB;GA8BmB;EACjC,MAAM;GACJ,UAAU,EAAE,gBAAgB,KAAM;GAClC,OAAO,EAAE,YAAY,GAAG;GACzB;EACF;CACD,QAAQ;EACN,IAAI;EACJ,OAAO;EACP,aAAa;EACb,cAAc;GApChB,WAAW,CAAC,UAAU,UAAU;GAChC,WAAW;GACX,SAAS;GACT,OAAO;GACP,OAAO;GACP,gBAAgB;GAChB,gBAAgB;GAChB,MAAM;GACN,OAAO;GA4B4B;EACjC,MAAM;GACJ,UAAU,EAAE,gBAAgB,KAAM;GAClC,OAAO,EAAE,YAAY,GAAG;GACzB;EACF;CACF;AAED,SAAgB,mBAAmB,IAAoC;AACrE,QAAO,kBAAkB;;AAG3B,SAAgB,gBAAgB,IAAiC;AAC/D,QAAQ,mBAAyC,SAAS,GAAG;;AAG/D,SAAgB,sBAAyC;AACvD,QAAO,mBAAmB,KAAK,OAAO,kBAAkB,IAAI"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import { ConfigSchema, init_schema } from "../../config/schema.js";
|
|
2
|
+
import { init_session_key, parseSessionKey } from "../../routing/session-key.js";
|
|
1
3
|
import { createLogger } from "../../utils/logger/index.js";
|
|
2
4
|
import { init_logger } from "../../utils/logger.js";
|
|
3
5
|
import { init_paths, resolveConfigPath } from "../../config/paths.js";
|
|
4
|
-
import { ConfigSchema, init_schema } from "../../config/schema.js";
|
|
5
6
|
import { init_loader, loadConfig, saveConfig } from "../../config/loader.js";
|
|
6
|
-
import { init_session_key, parseSessionKey } from "../../routing/session-key.js";
|
|
7
|
-
import { resolveAllowlistMatchSimple } from "../../channels/security.js";
|
|
8
7
|
import { commandRegistry } from "../registry.js";
|
|
8
|
+
import { resolveAllowlistMatchSimple } from "../../channels/security.js";
|
|
9
9
|
import { parseConfigValue } from "../config-value.js";
|
|
10
10
|
import { getConfigValueAtPath, parseConfigPath, setConfigValueAtPath, unsetConfigValueAtPath } from "../config-paths.js";
|
|
11
11
|
//#region src/chat-commands/builtins/config.ts
|
|
@@ -4,8 +4,8 @@ import { init_loader, saveConfig } from "../config/loader.js";
|
|
|
4
4
|
import { effectiveWorkspacePathForSession } from "../session/session-workspace.js";
|
|
5
5
|
import { getRoutingInfo, getSessionDisplayName } from "./session-key.js";
|
|
6
6
|
import { wrapMarkdownExportAsHtml } from "../session/chat-export.js";
|
|
7
|
-
import { mkdir, writeFile } from "fs/promises";
|
|
8
7
|
import { join } from "path";
|
|
8
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
9
9
|
//#region src/chat-commands/context.ts
|
|
10
10
|
init_logger();
|
|
11
11
|
init_loader();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { generateSessionKey, getRoutingInfo, getSessionDisplayName, isValidSessionKey, parseSessionKey } from "./session-key.js";
|
|
2
1
|
import { normalizeTelegramCommandName, parseSlashCommand } from "./command-parse.js";
|
|
3
2
|
import { CommandRegistry, commandRegistry } from "./registry.js";
|
|
3
|
+
import { generateSessionKey, getRoutingInfo, getSessionDisplayName, isValidSessionKey, parseSessionKey } from "./session-key.js";
|
|
4
4
|
import { registerSessionCommands } from "./builtins/session.js";
|
|
5
5
|
import { registerModelCommands } from "./builtins/model.js";
|
|
6
6
|
import { registerSystemCommands } from "./builtins/system.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createLogger } from "../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../utils/logger.js";
|
|
3
|
-
import { getRoutingInfo } from "./session-key.js";
|
|
4
3
|
import { commandRegistry } from "./registry.js";
|
|
4
|
+
import { getRoutingInfo } from "./session-key.js";
|
|
5
5
|
import { createCommandContext } from "./context.js";
|
|
6
6
|
//#region src/chat-commands/processor.ts
|
|
7
7
|
init_logger();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { getWorkspacePath } from "../../config/schema.js";
|
|
1
2
|
import { createLogger } from "../../utils/logger/index.js";
|
|
2
3
|
import { init_logger } from "../../utils/logger.js";
|
|
3
|
-
import { getWorkspacePath } from "../../config/schema.js";
|
|
4
4
|
import { loadConfig } from "../../config/loader.js";
|
|
5
5
|
import { MessageBus, MessageBusShutdownError } from "../../infra/bus/queue.js";
|
|
6
6
|
import "../../infra/bus/index.js";
|
|
@@ -16,11 +16,29 @@ function createChannelsCommand(ctx) {
|
|
|
16
16
|
const cmd = new Command("channels").description("Messaging channel login and credentials").addHelpText("after", formatExamples([
|
|
17
17
|
"xopc channels login",
|
|
18
18
|
"xopc channels login --channel weixin",
|
|
19
|
+
"xopc channels login --channel feishu",
|
|
19
20
|
"xopc channels login --account my-bot-id"
|
|
20
21
|
]));
|
|
21
|
-
cmd.command("login").description("Log in with QR code or channel-specific credentials flow").option("--channel <id>", "Channel id
|
|
22
|
+
cmd.command("login").description("Log in with QR code or channel-specific credentials flow").option("--channel <id>", "Channel id (auto-detected when only one login-capable channel is registered)").option("--account <id>", "Optional account id when re-logging an existing bot").option("--timeout <ms>", "Max wait for scan (default 480000)", "480000").option("--credentials-only", "Only save token files; do not update xopc.json").action(async (options, command) => {
|
|
22
23
|
ensureChannelRegistryForCli();
|
|
23
|
-
const
|
|
24
|
+
const explicitChannel = options.channel?.trim?.();
|
|
25
|
+
let channelId;
|
|
26
|
+
if (explicitChannel) channelId = explicitChannel;
|
|
27
|
+
else {
|
|
28
|
+
const loginCapable = listChannelPlugins().filter((p) => p.cliLogin);
|
|
29
|
+
if (loginCapable.length === 1) {
|
|
30
|
+
channelId = loginCapable[0].id;
|
|
31
|
+
console.log(`Auto-detected channel: ${channelId}`);
|
|
32
|
+
} else if (loginCapable.length === 0) {
|
|
33
|
+
console.error("No channels with login support found.");
|
|
34
|
+
process.exitCode = 1;
|
|
35
|
+
return;
|
|
36
|
+
} else {
|
|
37
|
+
console.error(`Multiple channels support login: ${loginCapable.map((p) => p.id).join(", ")}. Use --channel <id> to specify.`);
|
|
38
|
+
process.exitCode = 1;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
24
42
|
const plugin = getChannelPlugin(channelId);
|
|
25
43
|
if (!plugin?.cliLogin) {
|
|
26
44
|
console.error(`Channel "${channelId}" does not support CLI login.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channels.js","names":[],"sources":["../../../../src/cli/commands/channels.ts"],"sourcesContent":["import { Command } from 'commander';\n\nimport { resolveConfigPath } from '../../config/paths.js';\nimport {\n getChannelPlugin,\n listChannelPlugins,\n syncChannelPluginsFromManager,\n} from '../../channels/plugins/registry.js';\nimport { bundledChannelPlugins } from '../../generated/bundled-channel-plugins.js';\nimport { register, formatExamples, type CLIContext } from '../registry.js';\n\nfunction ensureChannelRegistryForCli(): void {\n if (listChannelPlugins().length === 0) {\n syncChannelPluginsFromManager(bundledChannelPlugins);\n }\n}\n\nfunction resolveConfigPathFromCommand(command: Command): string {\n const root =\n command.parent?.parent && command.parent.parent instanceof Command\n ? command.parent.parent\n : command.parent && command.parent instanceof Command\n ? command.parent\n : null;\n const globalOpts = (root && typeof root.opts === 'function'\n ? (root.opts() as { config?: string })\n : {}) as { config?: string };\n return (\n globalOpts.config?.trim() ||\n process.env.XOPC_CONFIG_PATH?.trim() ||\n process.env.XOPC_CONFIG?.trim() ||\n resolveConfigPath()\n );\n}\n\nfunction createChannelsCommand(ctx: CLIContext): Command {\n const cmd = new Command('channels')\n .description('Messaging channel login and credentials')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc channels login',\n 'xopc channels login --channel weixin',\n 'xopc channels login --account my-bot-id',\n ]),\n );\n\n cmd\n .command('login')\n .description('Log in with QR code or channel-specific credentials flow')\n .option('--channel <id>'
|
|
1
|
+
{"version":3,"file":"channels.js","names":[],"sources":["../../../../src/cli/commands/channels.ts"],"sourcesContent":["import { Command } from 'commander';\n\nimport { resolveConfigPath } from '../../config/paths.js';\nimport {\n getChannelPlugin,\n listChannelPlugins,\n syncChannelPluginsFromManager,\n} from '../../channels/plugins/registry.js';\nimport { bundledChannelPlugins } from '../../generated/bundled-channel-plugins.js';\nimport { register, formatExamples, type CLIContext } from '../registry.js';\n\nfunction ensureChannelRegistryForCli(): void {\n if (listChannelPlugins().length === 0) {\n syncChannelPluginsFromManager(bundledChannelPlugins);\n }\n}\n\nfunction resolveConfigPathFromCommand(command: Command): string {\n const root =\n command.parent?.parent && command.parent.parent instanceof Command\n ? command.parent.parent\n : command.parent && command.parent instanceof Command\n ? command.parent\n : null;\n const globalOpts = (root && typeof root.opts === 'function'\n ? (root.opts() as { config?: string })\n : {}) as { config?: string };\n return (\n globalOpts.config?.trim() ||\n process.env.XOPC_CONFIG_PATH?.trim() ||\n process.env.XOPC_CONFIG?.trim() ||\n resolveConfigPath()\n );\n}\n\nfunction createChannelsCommand(ctx: CLIContext): Command {\n const cmd = new Command('channels')\n .description('Messaging channel login and credentials')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc channels login',\n 'xopc channels login --channel weixin',\n 'xopc channels login --channel feishu',\n 'xopc channels login --account my-bot-id',\n ]),\n );\n\n cmd\n .command('login')\n .description('Log in with QR code or channel-specific credentials flow')\n .option(\n '--channel <id>',\n 'Channel id (auto-detected when only one login-capable channel is registered)',\n )\n .option('--account <id>', 'Optional account id when re-logging an existing bot')\n .option('--timeout <ms>', 'Max wait for scan (default 480000)', '480000')\n .option('--credentials-only', 'Only save token files; do not update xopc.json')\n .action(async (options, command) => {\n ensureChannelRegistryForCli();\n const explicitChannel = options.channel?.trim?.();\n let channelId: string;\n if (explicitChannel) {\n channelId = explicitChannel;\n } else {\n const loginCapable = listChannelPlugins().filter((p) => p.cliLogin);\n if (loginCapable.length === 1) {\n channelId = loginCapable[0].id;\n console.log(`Auto-detected channel: ${channelId}`);\n } else if (loginCapable.length === 0) {\n console.error('No channels with login support found.');\n process.exitCode = 1;\n return;\n } else {\n console.error(\n `Multiple channels support login: ${loginCapable.map((p) => p.id).join(', ')}. ` +\n 'Use --channel <id> to specify.',\n );\n process.exitCode = 1;\n return;\n }\n }\n const plugin = getChannelPlugin(channelId);\n if (!plugin?.cliLogin) {\n console.error(`Channel \"${channelId}\" does not support CLI login.`);\n const capable = listChannelPlugins()\n .filter((p) => p.cliLogin)\n .map((p) => p.id);\n if (capable.length > 0) {\n console.error(`Channels with login support: ${capable.join(', ')}`);\n }\n process.exitCode = 1;\n return;\n }\n\n const configPath = resolveConfigPathFromCommand(command);\n const timeoutMs = Math.max(60_000, Number.parseInt(String(options.timeout), 10) || 480_000);\n const verbose = ctx.isVerbose;\n\n const result = await plugin.cliLogin.runLogin({\n configPath,\n verbose,\n timeoutMs,\n accountId: options.account?.trim() || undefined,\n writeConfig: !options.credentialsOnly,\n });\n\n if (!result.ok) {\n console.error(result.message || 'Login failed');\n process.exitCode = 1;\n }\n });\n\n return cmd;\n}\n\nregister({\n id: 'channels',\n name: 'channels',\n description: 'Messaging channel login',\n factory: createChannelsCommand,\n metadata: {\n category: 'setup',\n examples: [\n 'xopc channels login',\n 'xopc channels login --account my-account-id',\n ],\n },\n});\n"],"mappings":";;;;;;YAE0D;AAS1D,SAAS,8BAAoC;AAC3C,KAAI,oBAAoB,CAAC,WAAW,EAClC,+BAA8B,sBAAsB;;AAIxD,SAAS,6BAA6B,SAA0B;CAC9D,MAAM,OACJ,QAAQ,QAAQ,UAAU,QAAQ,OAAO,kBAAkB,UACvD,QAAQ,OAAO,SACf,QAAQ,UAAU,QAAQ,kBAAkB,UAC1C,QAAQ,SACR;AAIR,SAHoB,QAAQ,OAAO,KAAK,SAAS,aAC5C,KAAK,MAAM,GACZ,EAAE,EAEO,QAAQ,MAAM,IACzB,QAAQ,IAAI,kBAAkB,MAAM,IACpC,QAAQ,IAAI,aAAa,MAAM,IAC/B,mBAAmB;;AAIvB,SAAS,sBAAsB,KAA0B;CACvD,MAAM,MAAM,IAAI,QAAQ,WAAW,CAChC,YAAY,0CAA0C,CACtD,YACC,SACA,eAAe;EACb;EACA;EACA;EACA;EACD,CAAC,CACH;AAEH,KACG,QAAQ,QAAQ,CAChB,YAAY,2DAA2D,CACvE,OACC,kBACA,+EACD,CACA,OAAO,kBAAkB,sDAAsD,CAC/E,OAAO,kBAAkB,sCAAsC,SAAS,CACxE,OAAO,sBAAsB,iDAAiD,CAC9E,OAAO,OAAO,SAAS,YAAY;AAClC,+BAA6B;EAC7B,MAAM,kBAAkB,QAAQ,SAAS,QAAQ;EACjD,IAAI;AACJ,MAAI,gBACF,aAAY;OACP;GACL,MAAM,eAAe,oBAAoB,CAAC,QAAQ,MAAM,EAAE,SAAS;AACnE,OAAI,aAAa,WAAW,GAAG;AAC7B,gBAAY,aAAa,GAAG;AAC5B,YAAQ,IAAI,0BAA0B,YAAY;cACzC,aAAa,WAAW,GAAG;AACpC,YAAQ,MAAM,wCAAwC;AACtD,YAAQ,WAAW;AACnB;UACK;AACL,YAAQ,MACN,oCAAoC,aAAa,KAAK,MAAM,EAAE,GAAG,CAAC,KAAK,KAAK,CAAC,kCAE9E;AACD,YAAQ,WAAW;AACnB;;;EAGJ,MAAM,SAAS,iBAAiB,UAAU;AAC1C,MAAI,CAAC,QAAQ,UAAU;AACrB,WAAQ,MAAM,YAAY,UAAU,+BAA+B;GACnE,MAAM,UAAU,oBAAoB,CACjC,QAAQ,MAAM,EAAE,SAAS,CACzB,KAAK,MAAM,EAAE,GAAG;AACnB,OAAI,QAAQ,SAAS,EACnB,SAAQ,MAAM,gCAAgC,QAAQ,KAAK,KAAK,GAAG;AAErE,WAAQ,WAAW;AACnB;;EAGF,MAAM,aAAa,6BAA6B,QAAQ;EACxD,MAAM,YAAY,KAAK,IAAI,KAAQ,OAAO,SAAS,OAAO,QAAQ,QAAQ,EAAE,GAAG,IAAI,KAAQ;EAC3F,MAAM,UAAU,IAAI;EAEpB,MAAM,SAAS,MAAM,OAAO,SAAS,SAAS;GAC5C;GACA;GACA;GACA,WAAW,QAAQ,SAAS,MAAM,IAAI,KAAA;GACtC,aAAa,CAAC,QAAQ;GACvB,CAAC;AAEF,MAAI,CAAC,OAAO,IAAI;AACd,WAAQ,MAAM,OAAO,WAAW,eAAe;AAC/C,WAAQ,WAAW;;GAErB;AAEJ,QAAO;;AAGT,SAAS;CACP,IAAI;CACJ,MAAM;CACN,aAAa;CACb,SAAS;CACT,UAAU;EACR,UAAU;EACV,UAAU,CACR,uBACA,8CACD;EACF;CACF,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { PROVIDER_ENV_MAP, getApiKeyFromEnv, init_env_keys } from "../../../../providers/env-keys.js";
|
|
2
1
|
import { getAgentDefaultModelRef, init_schema, parseModelRef } from "../../../../config/schema.js";
|
|
3
2
|
import { init_loader, loadConfig } from "../../../../config/loader.js";
|
|
3
|
+
import { PROVIDER_ENV_MAP, getApiKeyFromEnv, init_env_keys } from "../../../../providers/env-keys.js";
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
5
|
//#region src/cli/commands/doctor/checks/provider-auth.ts
|
|
6
6
|
init_loader();
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { init_paths, resolveConfigPath } from "../../../config/paths.js";
|
|
2
|
+
import { addGatewayClientOptions, callGatewayApi, parseGatewayClientOptions } from "../../utils/gateway-client.js";
|
|
3
|
+
import { getContextWithOpts } from "../../index.js";
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
//#region src/cli/commands/gateway/call.ts
|
|
6
|
+
init_paths();
|
|
7
|
+
const METHOD_ALIASES = {
|
|
8
|
+
health: {
|
|
9
|
+
method: "GET",
|
|
10
|
+
path: "/api/health"
|
|
11
|
+
},
|
|
12
|
+
status: {
|
|
13
|
+
method: "GET",
|
|
14
|
+
path: "/api/status"
|
|
15
|
+
},
|
|
16
|
+
config: {
|
|
17
|
+
method: "GET",
|
|
18
|
+
path: "/api/config"
|
|
19
|
+
},
|
|
20
|
+
sessions: {
|
|
21
|
+
method: "GET",
|
|
22
|
+
path: "/api/sessions"
|
|
23
|
+
},
|
|
24
|
+
models: {
|
|
25
|
+
method: "GET",
|
|
26
|
+
path: "/api/models"
|
|
27
|
+
},
|
|
28
|
+
channels: {
|
|
29
|
+
method: "GET",
|
|
30
|
+
path: "/api/channels/status"
|
|
31
|
+
},
|
|
32
|
+
cron: {
|
|
33
|
+
method: "GET",
|
|
34
|
+
path: "/api/cron"
|
|
35
|
+
},
|
|
36
|
+
logs: {
|
|
37
|
+
method: "GET",
|
|
38
|
+
path: "/api/logs"
|
|
39
|
+
},
|
|
40
|
+
agents: {
|
|
41
|
+
method: "GET",
|
|
42
|
+
path: "/api/agents"
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
function createCallCommand() {
|
|
46
|
+
const cmd = new Command("call").description("Call a gateway API method").argument("<method>", `Method name or API path. Built-in aliases: ${Object.keys(METHOD_ALIASES).join(", ")}`).option("--params <json>", "JSON body for POST/PATCH/DELETE requests", "{}").option("--http-method <method>", "HTTP method when using a raw path", "GET");
|
|
47
|
+
addGatewayClientOptions(cmd);
|
|
48
|
+
cmd.action(async (methodArg, options) => {
|
|
49
|
+
const configPath = getContextWithOpts().configPath || resolveConfigPath();
|
|
50
|
+
const clientOpts = {
|
|
51
|
+
...parseGatewayClientOptions(options),
|
|
52
|
+
configPath
|
|
53
|
+
};
|
|
54
|
+
const alias = METHOD_ALIASES[methodArg.toLowerCase()];
|
|
55
|
+
let httpMethod;
|
|
56
|
+
let apiPath;
|
|
57
|
+
if (alias) {
|
|
58
|
+
httpMethod = alias.method;
|
|
59
|
+
apiPath = alias.path;
|
|
60
|
+
} else if (methodArg.startsWith("/")) {
|
|
61
|
+
httpMethod = options.httpMethod?.toUpperCase() ?? "GET";
|
|
62
|
+
apiPath = methodArg;
|
|
63
|
+
} else {
|
|
64
|
+
httpMethod = options.httpMethod?.toUpperCase() ?? "GET";
|
|
65
|
+
apiPath = `/api/${methodArg}`;
|
|
66
|
+
}
|
|
67
|
+
let body;
|
|
68
|
+
if (httpMethod !== "GET" && options.params && options.params !== "{}") try {
|
|
69
|
+
body = JSON.parse(options.params);
|
|
70
|
+
} catch {
|
|
71
|
+
console.error(`❌ Invalid JSON in --params: ${options.params}`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
const result = await callGatewayApi(httpMethod, apiPath, clientOpts, body);
|
|
75
|
+
if (clientOpts.json || result.ok) console.log(JSON.stringify(result.ok ? result.data : {
|
|
76
|
+
error: result.error,
|
|
77
|
+
status: result.status,
|
|
78
|
+
durationMs: result.durationMs
|
|
79
|
+
}, null, 2));
|
|
80
|
+
if (!result.ok) {
|
|
81
|
+
if (!clientOpts.json) console.error(`❌ Gateway call failed: ${result.error} (status ${result.status}, ${result.durationMs}ms)`);
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
return cmd;
|
|
86
|
+
}
|
|
87
|
+
//#endregion
|
|
88
|
+
export { createCallCommand };
|
|
89
|
+
|
|
90
|
+
//# sourceMappingURL=call.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"call.js","names":[],"sources":["../../../../../src/cli/commands/gateway/call.ts"],"sourcesContent":["import { Command } from 'commander';\n\nimport {\n callGatewayApi,\n addGatewayClientOptions,\n parseGatewayClientOptions,\n} from '../../utils/gateway-client.js';\nimport { getContextWithOpts } from '../../index.js';\nimport { resolveConfigPath } from '../../../config/paths.js';\n\nconst METHOD_ALIASES: Record<string, { method: 'GET' | 'POST'; path: string }> = {\n health: { method: 'GET', path: '/api/health' },\n status: { method: 'GET', path: '/api/status' },\n config: { method: 'GET', path: '/api/config' },\n sessions: { method: 'GET', path: '/api/sessions' },\n models: { method: 'GET', path: '/api/models' },\n channels: { method: 'GET', path: '/api/channels/status' },\n cron: { method: 'GET', path: '/api/cron' },\n logs: { method: 'GET', path: '/api/logs' },\n agents: { method: 'GET', path: '/api/agents' },\n};\n\nexport function createCallCommand(): Command {\n const cmd = new Command('call')\n .description('Call a gateway API method')\n .argument(\n '<method>',\n `Method name or API path. Built-in aliases: ${Object.keys(METHOD_ALIASES).join(', ')}`,\n )\n .option('--params <json>', 'JSON body for POST/PATCH/DELETE requests', '{}')\n .option('--http-method <method>', 'HTTP method when using a raw path', 'GET');\n\n addGatewayClientOptions(cmd);\n\n cmd.action(async (methodArg: string, options: { params?: string; httpMethod?: string }) => {\n const ctx = getContextWithOpts();\n const configPath = ctx.configPath || resolveConfigPath();\n const clientOpts = { ...parseGatewayClientOptions(options as Record<string, unknown>), configPath };\n\n const alias = METHOD_ALIASES[methodArg.toLowerCase()];\n let httpMethod: 'GET' | 'POST' | 'PATCH' | 'DELETE';\n let apiPath: string;\n\n if (alias) {\n httpMethod = alias.method;\n apiPath = alias.path;\n } else if (methodArg.startsWith('/')) {\n httpMethod = (options.httpMethod?.toUpperCase() ?? 'GET') as 'GET' | 'POST' | 'PATCH' | 'DELETE';\n apiPath = methodArg;\n } else {\n httpMethod = (options.httpMethod?.toUpperCase() ?? 'GET') as 'GET' | 'POST' | 'PATCH' | 'DELETE';\n apiPath = `/api/${methodArg}`;\n }\n\n let body: unknown | undefined;\n if (httpMethod !== 'GET' && options.params && options.params !== '{}') {\n try {\n body = JSON.parse(options.params);\n } catch {\n console.error(`❌ Invalid JSON in --params: ${options.params}`);\n process.exit(1);\n }\n }\n\n const result = await callGatewayApi(httpMethod, apiPath, clientOpts, body);\n\n if (clientOpts.json || result.ok) {\n console.log(\n JSON.stringify(\n result.ok\n ? result.data\n : { error: result.error, status: result.status, durationMs: result.durationMs },\n null,\n 2,\n ),\n );\n }\n\n if (!result.ok) {\n if (!clientOpts.json) {\n console.error(`❌ Gateway call failed: ${result.error} (status ${result.status}, ${result.durationMs}ms)`);\n }\n process.exit(1);\n }\n });\n\n return cmd;\n}\n"],"mappings":";;;;;YAQ6D;AAE7D,MAAM,iBAA2E;CAC/E,QAAQ;EAAE,QAAQ;EAAO,MAAM;EAAe;CAC9C,QAAQ;EAAE,QAAQ;EAAO,MAAM;EAAe;CAC9C,QAAQ;EAAE,QAAQ;EAAO,MAAM;EAAe;CAC9C,UAAU;EAAE,QAAQ;EAAO,MAAM;EAAiB;CAClD,QAAQ;EAAE,QAAQ;EAAO,MAAM;EAAe;CAC9C,UAAU;EAAE,QAAQ;EAAO,MAAM;EAAwB;CACzD,MAAM;EAAE,QAAQ;EAAO,MAAM;EAAa;CAC1C,MAAM;EAAE,QAAQ;EAAO,MAAM;EAAa;CAC1C,QAAQ;EAAE,QAAQ;EAAO,MAAM;EAAe;CAC/C;AAED,SAAgB,oBAA6B;CAC3C,MAAM,MAAM,IAAI,QAAQ,OAAO,CAC5B,YAAY,4BAA4B,CACxC,SACC,YACA,8CAA8C,OAAO,KAAK,eAAe,CAAC,KAAK,KAAK,GACrF,CACA,OAAO,mBAAmB,4CAA4C,KAAK,CAC3E,OAAO,0BAA0B,qCAAqC,MAAM;AAE/E,yBAAwB,IAAI;AAE5B,KAAI,OAAO,OAAO,WAAmB,YAAsD;EAEzF,MAAM,aADM,oBACU,CAAC,cAAc,mBAAmB;EACxD,MAAM,aAAa;GAAE,GAAG,0BAA0B,QAAmC;GAAE;GAAY;EAEnG,MAAM,QAAQ,eAAe,UAAU,aAAa;EACpD,IAAI;EACJ,IAAI;AAEJ,MAAI,OAAO;AACT,gBAAa,MAAM;AACnB,aAAU,MAAM;aACP,UAAU,WAAW,IAAI,EAAE;AACpC,gBAAc,QAAQ,YAAY,aAAa,IAAI;AACnD,aAAU;SACL;AACL,gBAAc,QAAQ,YAAY,aAAa,IAAI;AACnD,aAAU,QAAQ;;EAGpB,IAAI;AACJ,MAAI,eAAe,SAAS,QAAQ,UAAU,QAAQ,WAAW,KAC/D,KAAI;AACF,UAAO,KAAK,MAAM,QAAQ,OAAO;UAC3B;AACN,WAAQ,MAAM,+BAA+B,QAAQ,SAAS;AAC9D,WAAQ,KAAK,EAAE;;EAInB,MAAM,SAAS,MAAM,eAAe,YAAY,SAAS,YAAY,KAAK;AAE1E,MAAI,WAAW,QAAQ,OAAO,GAC5B,SAAQ,IACN,KAAK,UACH,OAAO,KACH,OAAO,OACP;GAAE,OAAO,OAAO;GAAO,QAAQ,OAAO;GAAQ,YAAY,OAAO;GAAY,EACjF,MACA,EACD,CACF;AAGH,MAAI,CAAC,OAAO,IAAI;AACd,OAAI,CAAC,WAAW,KACd,SAAQ,MAAM,0BAA0B,OAAO,MAAM,WAAW,OAAO,OAAO,IAAI,OAAO,WAAW,KAAK;AAE3G,WAAQ,KAAK,EAAE;;GAEjB;AAEF,QAAO"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { init_paths, resolveConfigPath } from "../../../config/paths.js";
|
|
2
|
+
import { addGatewayClientOptions, callGatewayApi, parseGatewayClientOptions } from "../../utils/gateway-client.js";
|
|
3
|
+
import { getContextWithOpts } from "../../index.js";
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
//#region src/cli/commands/gateway/health.ts
|
|
6
|
+
init_paths();
|
|
7
|
+
function formatUptime(seconds) {
|
|
8
|
+
if (!seconds || seconds <= 0) return "unknown";
|
|
9
|
+
const days = Math.floor(seconds / 86400);
|
|
10
|
+
const hours = Math.floor(seconds % 86400 / 3600);
|
|
11
|
+
const minutes = Math.floor(seconds % 3600 / 60);
|
|
12
|
+
const parts = [];
|
|
13
|
+
if (days > 0) parts.push(`${days}d`);
|
|
14
|
+
if (hours > 0) parts.push(`${hours}h`);
|
|
15
|
+
parts.push(`${minutes}m`);
|
|
16
|
+
return parts.join(" ");
|
|
17
|
+
}
|
|
18
|
+
function createHealthCommand() {
|
|
19
|
+
const cmd = new Command("health").description("Check gateway health and channel status");
|
|
20
|
+
addGatewayClientOptions(cmd);
|
|
21
|
+
cmd.action(async (options) => {
|
|
22
|
+
const configPath = getContextWithOpts().configPath || resolveConfigPath();
|
|
23
|
+
const clientOpts = {
|
|
24
|
+
...parseGatewayClientOptions(options),
|
|
25
|
+
configPath
|
|
26
|
+
};
|
|
27
|
+
const healthResult = await callGatewayApi("GET", "/api/health", {
|
|
28
|
+
...clientOpts,
|
|
29
|
+
timeoutMs: clientOpts.timeoutMs ?? 5e3
|
|
30
|
+
});
|
|
31
|
+
if (!healthResult.ok) {
|
|
32
|
+
if (clientOpts.json) console.log(JSON.stringify({
|
|
33
|
+
status: "unreachable",
|
|
34
|
+
error: healthResult.error,
|
|
35
|
+
durationMs: healthResult.durationMs
|
|
36
|
+
}, null, 2));
|
|
37
|
+
else {
|
|
38
|
+
console.error(`❌ Gateway unreachable: ${healthResult.error}`);
|
|
39
|
+
console.error("");
|
|
40
|
+
console.error("💡 Is the gateway running? Try: xopc gateway");
|
|
41
|
+
}
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
const statusResult = await callGatewayApi("GET", "/api/status", clientOpts);
|
|
45
|
+
if (clientOpts.json) {
|
|
46
|
+
console.log(JSON.stringify({
|
|
47
|
+
status: "ok",
|
|
48
|
+
durationMs: healthResult.durationMs,
|
|
49
|
+
health: healthResult.data,
|
|
50
|
+
...statusResult.ok ? { details: statusResult.data } : {}
|
|
51
|
+
}, null, 2));
|
|
52
|
+
process.exit(0);
|
|
53
|
+
}
|
|
54
|
+
console.log(`✅ Gateway Health: OK (${healthResult.durationMs}ms)`);
|
|
55
|
+
console.log("");
|
|
56
|
+
if (healthResult.data?.version) console.log(` Version: ${healthResult.data.version}`);
|
|
57
|
+
if (healthResult.data?.uptime != null) console.log(` Uptime: ${formatUptime(healthResult.data.uptime)}`);
|
|
58
|
+
if (statusResult.ok && statusResult.data?.channels) {
|
|
59
|
+
console.log("");
|
|
60
|
+
console.log("📡 Channels:");
|
|
61
|
+
for (const [name, info] of Object.entries(statusResult.data.channels)) {
|
|
62
|
+
const statusIcon = info.status === "connected" ? "✅" : info.status === "disabled" ? "⚪" : "❌";
|
|
63
|
+
const accountsLabel = info.accounts != null ? ` (${info.accounts} account(s))` : "";
|
|
64
|
+
console.log(` ${statusIcon} ${name}: ${info.status}${accountsLabel}`);
|
|
65
|
+
}
|
|
66
|
+
} else if (statusResult.status === 401) {
|
|
67
|
+
console.log("");
|
|
68
|
+
console.log("🔒 Detailed status requires authentication. Pass --token <token>.");
|
|
69
|
+
}
|
|
70
|
+
process.exit(0);
|
|
71
|
+
});
|
|
72
|
+
return cmd;
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
export { createHealthCommand };
|
|
76
|
+
|
|
77
|
+
//# sourceMappingURL=health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.js","names":[],"sources":["../../../../../src/cli/commands/gateway/health.ts"],"sourcesContent":["import { Command } from 'commander';\n\nimport {\n callGatewayApi,\n addGatewayClientOptions,\n parseGatewayClientOptions,\n} from '../../utils/gateway-client.js';\nimport { getContextWithOpts } from '../../index.js';\nimport { resolveConfigPath } from '../../../config/paths.js';\n\ninterface HealthResponse {\n status: string;\n version?: string;\n uptime?: number;\n}\n\ninterface StatusResponse {\n status: string;\n version?: string;\n channels?: Record<string, { status: string; accounts?: number }>;\n uptime?: number;\n}\n\nfunction formatUptime(seconds?: number): string {\n if (!seconds || seconds <= 0) return 'unknown';\n const days = Math.floor(seconds / 86400);\n const hours = Math.floor((seconds % 86400) / 3600);\n const minutes = Math.floor((seconds % 3600) / 60);\n const parts: string[] = [];\n if (days > 0) parts.push(`${days}d`);\n if (hours > 0) parts.push(`${hours}h`);\n parts.push(`${minutes}m`);\n return parts.join(' ');\n}\n\nexport function createHealthCommand(): Command {\n const cmd = new Command('health').description('Check gateway health and channel status');\n\n addGatewayClientOptions(cmd);\n\n cmd.action(async (options) => {\n const ctx = getContextWithOpts();\n const configPath = ctx.configPath || resolveConfigPath();\n const clientOpts = { ...parseGatewayClientOptions(options as Record<string, unknown>), configPath };\n\n const healthResult = await callGatewayApi<HealthResponse>('GET', '/api/health', {\n ...clientOpts,\n timeoutMs: clientOpts.timeoutMs ?? 5000,\n });\n\n if (!healthResult.ok) {\n if (clientOpts.json) {\n console.log(\n JSON.stringify(\n {\n status: 'unreachable',\n error: healthResult.error,\n durationMs: healthResult.durationMs,\n },\n null,\n 2,\n ),\n );\n } else {\n console.error(`❌ Gateway unreachable: ${healthResult.error}`);\n console.error('');\n console.error('💡 Is the gateway running? Try: xopc gateway');\n }\n process.exit(1);\n }\n\n const statusResult = await callGatewayApi<StatusResponse>('GET', '/api/status', clientOpts);\n\n if (clientOpts.json) {\n console.log(\n JSON.stringify(\n {\n status: 'ok',\n durationMs: healthResult.durationMs,\n health: healthResult.data,\n ...(statusResult.ok ? { details: statusResult.data } : {}),\n },\n null,\n 2,\n ),\n );\n process.exit(0);\n }\n\n console.log(`✅ Gateway Health: OK (${healthResult.durationMs}ms)`);\n console.log('');\n\n if (healthResult.data?.version) {\n console.log(` Version: ${healthResult.data.version}`);\n }\n if (healthResult.data?.uptime != null) {\n console.log(` Uptime: ${formatUptime(healthResult.data.uptime)}`);\n }\n\n if (statusResult.ok && statusResult.data?.channels) {\n console.log('');\n console.log('📡 Channels:');\n for (const [name, info] of Object.entries(statusResult.data.channels)) {\n const statusIcon = info.status === 'connected' ? '✅' : info.status === 'disabled' ? '⚪' : '❌';\n const accountsLabel = info.accounts != null ? ` (${info.accounts} account(s))` : '';\n console.log(` ${statusIcon} ${name}: ${info.status}${accountsLabel}`);\n }\n } else if (statusResult.status === 401) {\n console.log('');\n console.log('🔒 Detailed status requires authentication. Pass --token <token>.');\n }\n\n process.exit(0);\n });\n\n return cmd;\n}\n"],"mappings":";;;;;YAQ6D;AAe7D,SAAS,aAAa,SAA0B;AAC9C,KAAI,CAAC,WAAW,WAAW,EAAG,QAAO;CACrC,MAAM,OAAO,KAAK,MAAM,UAAU,MAAM;CACxC,MAAM,QAAQ,KAAK,MAAO,UAAU,QAAS,KAAK;CAClD,MAAM,UAAU,KAAK,MAAO,UAAU,OAAQ,GAAG;CACjD,MAAM,QAAkB,EAAE;AAC1B,KAAI,OAAO,EAAG,OAAM,KAAK,GAAG,KAAK,GAAG;AACpC,KAAI,QAAQ,EAAG,OAAM,KAAK,GAAG,MAAM,GAAG;AACtC,OAAM,KAAK,GAAG,QAAQ,GAAG;AACzB,QAAO,MAAM,KAAK,IAAI;;AAGxB,SAAgB,sBAA+B;CAC7C,MAAM,MAAM,IAAI,QAAQ,SAAS,CAAC,YAAY,0CAA0C;AAExF,yBAAwB,IAAI;AAE5B,KAAI,OAAO,OAAO,YAAY;EAE5B,MAAM,aADM,oBACU,CAAC,cAAc,mBAAmB;EACxD,MAAM,aAAa;GAAE,GAAG,0BAA0B,QAAmC;GAAE;GAAY;EAEnG,MAAM,eAAe,MAAM,eAA+B,OAAO,eAAe;GAC9E,GAAG;GACH,WAAW,WAAW,aAAa;GACpC,CAAC;AAEF,MAAI,CAAC,aAAa,IAAI;AACpB,OAAI,WAAW,KACb,SAAQ,IACN,KAAK,UACH;IACE,QAAQ;IACR,OAAO,aAAa;IACpB,YAAY,aAAa;IAC1B,EACD,MACA,EACD,CACF;QACI;AACL,YAAQ,MAAM,0BAA0B,aAAa,QAAQ;AAC7D,YAAQ,MAAM,GAAG;AACjB,YAAQ,MAAM,+CAA+C;;AAE/D,WAAQ,KAAK,EAAE;;EAGjB,MAAM,eAAe,MAAM,eAA+B,OAAO,eAAe,WAAW;AAE3F,MAAI,WAAW,MAAM;AACnB,WAAQ,IACN,KAAK,UACH;IACE,QAAQ;IACR,YAAY,aAAa;IACzB,QAAQ,aAAa;IACrB,GAAI,aAAa,KAAK,EAAE,SAAS,aAAa,MAAM,GAAG,EAAE;IAC1D,EACD,MACA,EACD,CACF;AACD,WAAQ,KAAK,EAAE;;AAGjB,UAAQ,IAAI,yBAAyB,aAAa,WAAW,KAAK;AAClE,UAAQ,IAAI,GAAG;AAEf,MAAI,aAAa,MAAM,QACrB,SAAQ,IAAI,eAAe,aAAa,KAAK,UAAU;AAEzD,MAAI,aAAa,MAAM,UAAU,KAC/B,SAAQ,IAAI,eAAe,aAAa,aAAa,KAAK,OAAO,GAAG;AAGtE,MAAI,aAAa,MAAM,aAAa,MAAM,UAAU;AAClD,WAAQ,IAAI,GAAG;AACf,WAAQ,IAAI,eAAe;AAC3B,QAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,aAAa,KAAK,SAAS,EAAE;IACrE,MAAM,aAAa,KAAK,WAAW,cAAc,MAAM,KAAK,WAAW,aAAa,MAAM;IAC1F,MAAM,gBAAgB,KAAK,YAAY,OAAO,KAAK,KAAK,SAAS,gBAAgB;AACjF,YAAQ,IAAI,MAAM,WAAW,GAAG,KAAK,IAAI,KAAK,SAAS,gBAAgB;;aAEhE,aAAa,WAAW,KAAK;AACtC,WAAQ,IAAI,GAAG;AACf,WAAQ,IAAI,oEAAoE;;AAGlF,UAAQ,KAAK,EAAE;GACf;AAEF,QAAO"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export { createTokenCommand } from './token.js';
|
|
2
2
|
export { createStatusCommand } from './status.js';
|
|
3
|
+
export { createHealthCommand } from './health.js';
|
|
4
|
+
export { createCallCommand } from './call.js';
|
|
5
|
+
export { createProbeCommand } from './probe.js';
|
|
3
6
|
export { createStopCommand } from './stop.js';
|
|
4
7
|
export { createRestartCommand } from './restart.js';
|
|
5
8
|
export { createLogsCommand } from './logs.js';
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { createTokenCommand } from "./token.js";
|
|
2
2
|
import { createStatusCommand } from "./status.js";
|
|
3
|
+
import { createHealthCommand } from "./health.js";
|
|
4
|
+
import { createCallCommand } from "./call.js";
|
|
5
|
+
import { createProbeCommand } from "./probe.js";
|
|
3
6
|
import { createStopCommand } from "./stop.js";
|
|
4
7
|
import { createRestartCommand } from "./restart.js";
|
|
5
8
|
import { createLogsCommand } from "./logs.js";
|
|
6
9
|
import { createInstallCommand, createServiceStartCommand, createServiceStatusCommand, createUninstallCommand } from "./service.js";
|
|
7
|
-
export { createInstallCommand, createLogsCommand, createRestartCommand, createServiceStartCommand, createServiceStatusCommand, createStatusCommand, createStopCommand, createTokenCommand, createUninstallCommand };
|
|
10
|
+
export { createCallCommand, createHealthCommand, createInstallCommand, createLogsCommand, createProbeCommand, createRestartCommand, createServiceStartCommand, createServiceStatusCommand, createStatusCommand, createStopCommand, createTokenCommand, createUninstallCommand };
|