@xopcai/xopc 0.0.83 → 0.0.85
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/README.md +2 -0
- package/README.zh-CN.md +3 -1
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
- package/dist/extensions/feishu/src/plugin.d.ts +2 -0
- package/dist/extensions/feishu/src/plugin.js +10 -0
- package/dist/extensions/feishu/src/plugin.js.map +1 -1
- package/dist/extensions/feishu/src/workflow-progress.d.ts +27 -0
- package/dist/extensions/feishu/src/workflow-progress.js +99 -0
- package/dist/extensions/feishu/src/workflow-progress.js.map +1 -0
- package/dist/extensions/telegram/src/plugin.d.ts +2 -0
- package/dist/extensions/telegram/src/plugin.js +11 -1
- package/dist/extensions/telegram/src/plugin.js.map +1 -1
- package/dist/extensions/telegram/src/routing-integration.js +2 -2
- package/dist/extensions/telegram/src/workflow-progress.d.ts +24 -0
- package/dist/extensions/telegram/src/workflow-progress.js +73 -0
- package/dist/extensions/telegram/src/workflow-progress.js.map +1 -0
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js +158 -0
- package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js.map +1 -0
- package/dist/extensions/weixin/src/api/api.js +2 -2
- package/dist/extensions/weixin/src/auth/accounts.js +1 -1
- package/dist/extensions/weixin/src/cdn/upload.js +1 -1
- package/dist/extensions/weixin/src/media/data-url.js +1 -1
- package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
- package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
- package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
- package/dist/extensions/weixin/src/plugin.d.ts +2 -0
- package/dist/extensions/weixin/src/plugin.js +11 -1
- package/dist/extensions/weixin/src/plugin.js.map +1 -1
- package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
- package/dist/extensions/weixin/src/workflow-progress.d.ts +26 -0
- package/dist/extensions/weixin/src/workflow-progress.js +99 -0
- package/dist/extensions/weixin/src/workflow-progress.js.map +1 -0
- package/dist/gateway/static/root/assets/agents-D3_-kNlZ.js +222 -0
- package/dist/gateway/static/root/assets/apps-page-D7v7649T.js +1 -0
- package/dist/gateway/static/root/assets/channels-settings-nCaMb0a7.js +1 -0
- package/dist/gateway/static/root/assets/channels-status-swr-C1gZBcJV.js +8 -0
- package/dist/gateway/static/root/assets/createLucideIcon-DPHK1VkS.js +1 -0
- package/dist/gateway/static/root/assets/cron-api-CoYK0hlm.js +1 -0
- package/dist/gateway/static/root/assets/cron-page-DeGo-Vjc.js +1 -0
- package/dist/gateway/static/root/assets/dist-BTWC-BTN.js +45 -0
- package/dist/gateway/static/root/assets/{dist-BpQxde0t.js → dist-DaK4dsss.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-CY27wj_p.js → extension-debug-page-BZngZWbO.js} +1 -1
- package/dist/gateway/static/root/assets/extension-page-D6JSyV27.js +1 -0
- package/dist/gateway/static/root/assets/extension-settings-page-8PZcmWI7.js +1 -0
- package/dist/gateway/static/root/assets/fetch-B2MYHbWg.js +1 -0
- package/dist/gateway/static/root/assets/{field-primitives-fa_hiQcX.js → field-primitives-Zzl22MvN.js} +1 -1
- package/dist/gateway/static/root/assets/heartbeat-config-api-BtIcpG0O.js +1 -0
- package/dist/gateway/static/root/assets/index-D4vM3-P7.js +4700 -0
- package/dist/gateway/static/root/assets/index-ew_2L2We.css +1 -0
- package/dist/gateway/static/root/assets/logs-page-_d4UJ-qQ.js +1 -0
- package/dist/gateway/static/root/assets/sessions-page-5N4aF2Wk.js +1 -0
- package/dist/gateway/static/root/assets/settings-form-section-D_tgb8r2.js +1 -0
- package/dist/gateway/static/root/assets/settings-page-C18xBt4X.js +3 -0
- package/dist/gateway/static/root/assets/share-preview-page-D4EG_vM1.js +2 -0
- package/dist/gateway/static/root/assets/skills-page-sPAXhh8w.js +2 -0
- package/dist/gateway/static/root/assets/theme-store-DryYl3qD.js +1 -0
- package/dist/gateway/static/root/assets/url-BwNL6Rgk.js +3 -0
- package/dist/gateway/static/root/assets/utils-CYO9eTCM.js +1 -0
- package/dist/gateway/static/root/assets/voice-api-key-field-Ds51havm.js +1 -0
- package/dist/gateway/static/root/index.html +7 -6
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.js +7 -7
- package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
- package/dist/src/agent/context/workspace-seed.js +3 -3
- package/dist/src/agent/embedded/map-stream-events.js +6 -0
- package/dist/src/agent/embedded/map-stream-events.js.map +1 -1
- package/dist/src/agent/embedded/subscribe-session.js +24 -0
- package/dist/src/agent/embedded/subscribe-session.js.map +1 -1
- package/dist/src/agent/embedded/types.d.ts +19 -0
- package/dist/src/agent/goals/goal-locale.js +2 -2
- package/dist/src/agent/goals/goal-run-store.js +4 -4
- package/dist/src/agent/goals/persistent-goal-service.js +1 -1
- package/dist/src/agent/goals/post-turn.js +2 -2
- package/dist/src/agent/image/load-image-media.js +2 -2
- package/dist/src/agent/ipc/bus.js +1 -1
- package/dist/src/agent/ipc/inbox.js +2 -2
- package/dist/src/agent/ipc/socket.js +1 -1
- package/dist/src/agent/memory/builtin-memory-store.js +1 -1
- package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
- package/dist/src/agent/memory/dreaming/events.js +1 -1
- package/dist/src/agent/memory/dreaming/last-run.js +1 -1
- package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
- package/dist/src/agent/memory/dreaming/preview.js +1 -1
- package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
- package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
- package/dist/src/agent/memory/dreaming/utils.js +1 -1
- package/dist/src/agent/memory/plugin-discovery.js +1 -1
- package/dist/src/agent/models/manager.js +1 -1
- package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
- package/dist/src/agent/reply/post-compaction-context.js +1 -1
- package/dist/src/agent/reply/startup-context.d.ts +3 -0
- package/dist/src/agent/reply/startup-context.js +25 -2
- package/dist/src/agent/reply/startup-context.js.map +1 -1
- package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
- package/dist/src/agent/sandbox/path-policy.js +2 -2
- package/dist/src/agent/service/build-direct-message-content.js +1 -1
- package/dist/src/agent/service.d.ts +1 -0
- package/dist/src/agent/service.js +10 -4
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/session/session-inspector.js +1 -1
- package/dist/src/agent/skills/config.js +1 -1
- package/dist/src/agent/skills/hub-hash.js +2 -2
- package/dist/src/agent/skills/hub-lock.js +1 -1
- package/dist/src/agent/skills/hub-pull.js +3 -3
- package/dist/src/agent/skills/index.js +1 -1
- package/dist/src/agent/skills/managed-store.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/create-share-tool.d.ts +27 -0
- package/dist/src/agent/tools/create-share-tool.js +237 -0
- package/dist/src/agent/tools/create-share-tool.js.map +1 -0
- package/dist/src/agent/tools/dreaming-tool.js +1 -1
- package/dist/src/agent/tools/factory.js +35 -1
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/image-generate-tool.js +1 -1
- package/dist/src/agent/tools/index.d.ts +2 -0
- package/dist/src/agent/tools/index.js +3 -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/workflow-tool.d.ts +41 -0
- package/dist/src/agent/tools/workflow-tool.js +271 -0
- package/dist/src/agent/tools/workflow-tool.js.map +1 -0
- package/dist/src/agent/tools/write.js +1 -1
- package/dist/src/agent/workflow/builtins/audit-repo.d.ts +9 -0
- package/dist/src/agent/workflow/builtins/audit-repo.js +115 -0
- package/dist/src/agent/workflow/builtins/audit-repo.js.map +1 -0
- package/dist/src/agent/workflow/builtins/index.d.ts +15 -0
- package/dist/src/agent/workflow/builtins/index.js +28 -0
- package/dist/src/agent/workflow/builtins/index.js.map +1 -0
- package/dist/src/agent/workflow/builtins/multi-perspective-review.d.ts +9 -0
- package/dist/src/agent/workflow/builtins/multi-perspective-review.js +113 -0
- package/dist/src/agent/workflow/builtins/multi-perspective-review.js.map +1 -0
- package/dist/src/agent/workflow/builtins/research.d.ts +9 -0
- package/dist/src/agent/workflow/builtins/research.js +129 -0
- package/dist/src/agent/workflow/builtins/research.js.map +1 -0
- package/dist/src/agent/workflow/catalog.d.ts +51 -0
- package/dist/src/agent/workflow/catalog.js +155 -0
- package/dist/src/agent/workflow/catalog.js.map +1 -0
- package/dist/src/agent/workflow/channel-capability.d.ts +76 -0
- package/dist/src/agent/workflow/channel-capability.js +1 -0
- package/dist/src/agent/workflow/index.d.ts +11 -0
- package/dist/src/agent/workflow/index.js +10 -0
- package/dist/src/agent/workflow/last-run-memory.d.ts +42 -0
- package/dist/src/agent/workflow/last-run-memory.js +60 -0
- package/dist/src/agent/workflow/last-run-memory.js.map +1 -0
- package/dist/src/agent/workflow/parser.d.ts +20 -0
- package/dist/src/agent/workflow/parser.js +137 -0
- package/dist/src/agent/workflow/parser.js.map +1 -0
- package/dist/src/agent/workflow/progress-broker.d.ts +80 -0
- package/dist/src/agent/workflow/progress-broker.js +263 -0
- package/dist/src/agent/workflow/progress-broker.js.map +1 -0
- package/dist/src/agent/workflow/runtime.d.ts +31 -0
- package/dist/src/agent/workflow/runtime.js +301 -0
- package/dist/src/agent/workflow/runtime.js.map +1 -0
- package/dist/src/agent/workflow/snapshot.d.ts +18 -0
- package/dist/src/agent/workflow/snapshot.js +144 -0
- package/dist/src/agent/workflow/snapshot.js.map +1 -0
- package/dist/src/agent/workflow/structured-output-tool.d.ts +33 -0
- package/dist/src/agent/workflow/structured-output-tool.js +58 -0
- package/dist/src/agent/workflow/structured-output-tool.js.map +1 -0
- package/dist/src/agent/workflow/subagent-runner.d.ts +42 -0
- package/dist/src/agent/workflow/subagent-runner.js +104 -0
- package/dist/src/agent/workflow/subagent-runner.js.map +1 -0
- package/dist/src/agent/workflow/types.d.ts +137 -0
- package/dist/src/agent/workflow/types.js +1 -0
- package/dist/src/auth/credentials.js +3 -3
- package/dist/src/auth/profiles/store.js +1 -1
- package/dist/src/auth/sync-provider-auth.js +1 -1
- package/dist/src/browser/cache-dir-policy.js +1 -1
- package/dist/src/browser/cdp-local-launcher.js +2 -2
- package/dist/src/browser/providers/browser-ext-install.js +4 -4
- package/dist/src/browser/providers/cloakbrowser.js +4 -4
- package/dist/src/browser/providers/playwright-doctor.js +1 -1
- package/dist/src/browser/stealth.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/outbound/persist-store.js +1 -1
- package/dist/src/channels/pairing/allow-from-file.js +1 -1
- package/dist/src/channels/pairing/pairing-store.js +2 -2
- package/dist/src/chat-commands/builtins/config.js +2 -2
- package/dist/src/chat-commands/builtins/model.js +40 -23
- package/dist/src/chat-commands/builtins/model.js.map +1 -1
- package/dist/src/chat-commands/builtins/system.js +30 -15
- package/dist/src/chat-commands/builtins/system.js.map +1 -1
- package/dist/src/chat-commands/builtins/workflow.d.ts +18 -0
- package/dist/src/chat-commands/builtins/workflow.js +167 -0
- package/dist/src/chat-commands/builtins/workflow.js.map +1 -0
- package/dist/src/chat-commands/context.js +1 -1
- package/dist/src/chat-commands/format-output.d.ts +28 -0
- package/dist/src/chat-commands/format-output.js +45 -0
- package/dist/src/chat-commands/format-output.js.map +1 -0
- package/dist/src/chat-commands/index.d.ts +1 -0
- package/dist/src/chat-commands/index.js +3 -1
- package/dist/src/chat-commands/index.js.map +1 -1
- package/dist/src/cli/command-catalog.js +110 -8
- package/dist/src/cli/command-catalog.js.map +1 -1
- package/dist/src/cli/command-loaders.js +2 -0
- package/dist/src/cli/command-loaders.js.map +1 -1
- package/dist/src/cli/command-manifest.js +9 -1
- package/dist/src/cli/command-manifest.js.map +1 -1
- package/dist/src/cli/commands/config.js +71 -20
- package/dist/src/cli/commands/config.js.map +1 -1
- package/dist/src/cli/commands/cron-cli.d.ts +2 -0
- package/dist/src/cli/commands/cron-cli.js +15 -0
- package/dist/src/cli/commands/cron-cli.js.map +1 -0
- package/dist/src/cli/commands/cron.d.ts +4 -1
- package/dist/src/cli/commands/cron.js +76 -41
- package/dist/src/cli/commands/cron.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/channel-config.js +1 -1
- package/dist/src/cli/commands/doctor/checks/channel-config.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/config-health.js +2 -2
- package/dist/src/cli/commands/doctor/checks/config-health.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/cron-health.js +1 -1
- package/dist/src/cli/commands/doctor/checks/cron-health.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/gateway-health.js +2 -2
- package/dist/src/cli/commands/doctor/checks/gateway-health.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/gateway-service.js +2 -2
- package/dist/src/cli/commands/doctor/checks/gateway-service.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
- package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -1
- package/dist/src/cli/commands/doctor/checks/state-integrity.js +2 -2
- package/dist/src/cli/commands/doctor/checks/state-integrity.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/workspace-status.js +4 -4
- package/dist/src/cli/commands/doctor/checks/workspace-status.js.map +1 -1
- package/dist/src/cli/commands/extension-dev.js +1 -1
- package/dist/src/cli/commands/extension-marketplace.js +1 -1
- package/dist/src/cli/commands/extension-pack.js +1 -1
- package/dist/src/cli/commands/gateway/index.d.ts +1 -1
- package/dist/src/cli/commands/gateway/index.js +2 -2
- package/dist/src/cli/commands/gateway/lifecycle.js +10 -4
- package/dist/src/cli/commands/gateway/lifecycle.js.map +1 -1
- package/dist/src/cli/commands/gateway/service.d.ts +4 -0
- package/dist/src/cli/commands/gateway/service.js +17 -2
- package/dist/src/cli/commands/gateway/service.js.map +1 -1
- package/dist/src/cli/commands/gateway/shared.js +1 -1
- package/dist/src/cli/commands/gateway/subcommands.js +1 -4
- package/dist/src/cli/commands/gateway/subcommands.js.map +1 -1
- package/dist/src/cli/commands/image.js +1 -1
- package/dist/src/cli/commands/init.js +31 -4
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/models.d.ts +4 -1
- package/dist/src/cli/commands/models.js +86 -74
- package/dist/src/cli/commands/models.js.map +1 -1
- package/dist/src/cli/commands/onboard.js +4 -2
- package/dist/src/cli/commands/onboard.js.map +1 -1
- package/dist/src/cli/commands/profile.d.ts +3 -5
- package/dist/src/cli/commands/profile.js +31 -31
- package/dist/src/cli/commands/profile.js.map +1 -1
- package/dist/src/cli/commands/setup.js +6 -1
- package/dist/src/cli/commands/setup.js.map +1 -1
- package/dist/src/cli/commands/tunnel.js +2 -2
- package/dist/src/cli/gateway-run-argv.js +15 -5
- package/dist/src/cli/gateway-run-argv.js.map +1 -1
- package/dist/src/cli/utils/gateway-client.js +1 -1
- package/dist/src/cli/utils/init-workspace-core.js +2 -2
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/config/gateway-bind.js +1 -1
- package/dist/src/config/index.js +5 -5
- package/dist/src/config/loader.js +2 -2
- package/dist/src/config/models-json.js +2 -2
- package/dist/src/config/paths-state.js +1 -1
- package/dist/src/config/profile.js +2 -2
- package/dist/src/config/public-url.d.ts +28 -0
- package/dist/src/config/public-url.js +103 -0
- package/dist/src/config/public-url.js.map +1 -0
- package/dist/src/config/schema.d.ts +82 -0
- package/dist/src/config/schema.js +130 -1
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/config/workspace-path.js +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/daemon/constants.js +1 -1
- package/dist/src/daemon/install-plan.js +3 -3
- package/dist/src/daemon/install-plan.js.map +1 -1
- package/dist/src/daemon/launchd.js +2 -2
- package/dist/src/daemon/schtasks.js +38 -1
- package/dist/src/daemon/schtasks.js.map +1 -1
- package/dist/src/daemon/systemd.js +2 -2
- package/dist/src/extensions/bundle-mcp.js +1 -1
- package/dist/src/extensions/discover-extensions.js +1 -1
- package/dist/src/extensions/health.js +1 -1
- package/dist/src/extensions/loader.js +1 -1
- package/dist/src/extensions/lockfile.js +2 -2
- package/dist/src/gateway/agents-admin.js +2 -2
- package/dist/src/gateway/file-path-classifier.js +2 -2
- package/dist/src/gateway/heartbeat/service.js +1 -1
- package/dist/src/gateway/hono/app.js +33 -2
- package/dist/src/gateway/hono/app.js.map +1 -1
- package/dist/src/gateway/hono/lib/config-payload.js +1 -1
- package/dist/src/gateway/hono/lib/extension-store.js +2 -2
- package/dist/src/gateway/hono/lib/static-ui.js +2 -2
- package/dist/src/gateway/hono/oauth.js +1 -1
- package/dist/src/gateway/hono/routes/agents.js +1 -1
- package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
- package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
- package/dist/src/gateway/hono/routes/dreaming.js +1 -1
- package/dist/src/gateway/hono/routes/host-fs.js +2 -2
- package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
- package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
- package/dist/src/gateway/hono/routes/models.js +1 -1
- package/dist/src/gateway/hono/routes/shares.js +631 -34
- package/dist/src/gateway/hono/routes/shares.js.map +1 -1
- package/dist/src/gateway/hono/routes/site-shares.d.ts +3 -0
- package/dist/src/gateway/hono/routes/site-shares.js +228 -0
- package/dist/src/gateway/hono/routes/site-shares.js.map +1 -0
- package/dist/src/gateway/hono/routes/tunnel.js +97 -8
- package/dist/src/gateway/hono/routes/tunnel.js.map +1 -1
- package/dist/src/gateway/hono/routes/workspace.js +5 -5
- package/dist/src/gateway/hono/sse.js +2 -2
- package/dist/src/gateway/host.d.ts +3 -1
- package/dist/src/gateway/host.js +3 -1
- package/dist/src/gateway/host.js.map +1 -1
- package/dist/src/gateway/lock.js +3 -3
- package/dist/src/gateway/ports.d.ts +6 -0
- package/dist/src/gateway/ports.js +38 -2
- package/dist/src/gateway/ports.js.map +1 -1
- package/dist/src/gateway/public-url.d.ts +8 -0
- package/dist/src/gateway/public-url.js +10 -0
- package/dist/src/gateway/public-url.js.map +1 -0
- package/dist/src/gateway/security/origin-check.d.ts +9 -1
- package/dist/src/gateway/security/origin-check.js +4 -0
- package/dist/src/gateway/security/origin-check.js.map +1 -1
- package/dist/src/gateway/server.js +15 -0
- package/dist/src/gateway/server.js.map +1 -1
- package/dist/src/gateway/service/agent-runner.js +2 -2
- package/dist/src/gateway/service/marketplace-service.js +2 -2
- package/dist/src/gateway/service/run-gateway-agent.js +2 -2
- package/dist/src/gateway/service.js +3 -2
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/workspace-fs-file-list.js +1 -1
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/i18n/goals-bundle.js +1 -1
- package/dist/src/i18n/index.d.ts +1 -0
- package/dist/src/i18n/index.js +2 -1
- package/dist/src/i18n/locales/share-tool.en.js +15 -0
- package/dist/src/i18n/locales/share-tool.en.js.map +1 -0
- package/dist/src/i18n/locales/share-tool.zh.js +15 -0
- package/dist/src/i18n/locales/share-tool.zh.js.map +1 -0
- package/dist/src/i18n/share-tool-bundle.d.ts +20 -0
- package/dist/src/i18n/share-tool-bundle.js +56 -0
- package/dist/src/i18n/share-tool-bundle.js.map +1 -0
- package/dist/src/infra/gateway-processes.js +1 -0
- package/dist/src/infra/gateway-processes.js.map +1 -1
- package/dist/src/infra/restart.js +2 -2
- package/dist/src/infra/update-check.js +1 -1
- package/dist/src/infra/update-lock.js +3 -3
- package/dist/src/infra/update-runner.js +1 -1
- package/dist/src/infra/update-startup.js +2 -2
- package/dist/src/infra/write-file-atomic.js +2 -2
- package/dist/src/providers/auth-runtime/auth-profile-store.js +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 +2 -2
- package/dist/src/session/parity/jsonl-transcript-io.js +2 -2
- package/dist/src/session/parity/sessions-json-file.js +1 -1
- package/dist/src/session/parity/transcript-file-lock.js +2 -2
- package/dist/src/session/parity/transcript-paths.js +1 -1
- package/dist/src/session/search-index-cache.js +1 -1
- package/dist/src/session/search-index.js +1 -1
- package/dist/src/session/session-title.js +3 -2
- package/dist/src/session/session-title.js.map +1 -1
- package/dist/src/session/store.js +5 -5
- package/dist/src/share/share-auto.d.ts +74 -0
- package/dist/src/share/share-auto.js +247 -0
- package/dist/src/share/share-auto.js.map +1 -0
- package/dist/src/share/share-config.js +63 -4
- package/dist/src/share/share-config.js.map +1 -1
- package/dist/src/share/share-landing.d.ts +28 -2
- package/dist/src/share/share-landing.js +155 -34
- package/dist/src/share/share-landing.js.map +1 -1
- package/dist/src/share/share-store.d.ts +48 -4
- package/dist/src/share/share-store.js +322 -51
- package/dist/src/share/share-store.js.map +1 -1
- package/dist/src/share/share-thumbnail.d.ts +35 -0
- package/dist/src/share/share-thumbnail.js +277 -0
- package/dist/src/share/share-thumbnail.js.map +1 -0
- package/dist/src/share/share-types.d.ts +68 -10
- package/dist/src/share/share-types.js +18 -1
- package/dist/src/share/share-types.js.map +1 -1
- package/dist/src/share/share-url.js +1 -1
- package/dist/src/share/share-zip.d.ts +35 -0
- package/dist/src/share/share-zip.js +303 -0
- package/dist/src/share/share-zip.js.map +1 -0
- package/dist/src/share/site-proxy.d.ts +35 -0
- package/dist/src/share/site-proxy.js +234 -0
- package/dist/src/share/site-proxy.js.map +1 -0
- package/dist/src/share/site-share-config.d.ts +11 -0
- package/dist/src/share/site-share-config.js +103 -0
- package/dist/src/share/site-share-config.js.map +1 -0
- package/dist/src/share/site-share-router.d.ts +23 -0
- package/dist/src/share/site-share-router.js +147 -0
- package/dist/src/share/site-share-router.js.map +1 -0
- package/dist/src/share/site-share-store.d.ts +53 -0
- package/dist/src/share/site-share-store.js +400 -0
- package/dist/src/share/site-share-store.js.map +1 -0
- package/dist/src/share/site-share-types.d.ts +103 -0
- package/dist/src/share/site-share-types.js +41 -0
- package/dist/src/share/site-share-types.js.map +1 -0
- package/dist/src/share/site-static-serve.d.ts +10 -0
- package/dist/src/share/site-static-serve.js +145 -0
- package/dist/src/share/site-static-serve.js.map +1 -0
- package/dist/src/tui/clipboard-image.js +3 -3
- package/dist/src/tui/theme-manager.js +1 -1
- package/dist/src/tui/tui-commands.js +18 -0
- package/dist/src/tui/tui-commands.js.map +1 -1
- package/dist/src/tui/tui-keybindings-file.js +1 -1
- package/dist/src/tui/tui-scoped-models.js +2 -2
- package/dist/src/tui/tui-settings.js +1 -1
- package/dist/src/tui/tui-workflow-slash.d.ts +32 -0
- package/dist/src/tui/tui-workflow-slash.js +63 -0
- package/dist/src/tui/tui-workflow-slash.js.map +1 -0
- package/dist/src/tui/tui.js +2 -2
- package/dist/src/tunnel/enable-lan-pairing.js +1 -1
- package/dist/src/tunnel/frpc-binary.js +3 -3
- package/dist/src/tunnel/frpc-config.js +1 -1
- package/dist/src/tunnel/frpc-extract.js +1 -1
- package/dist/src/tunnel/index.js +2 -2
- package/dist/src/tunnel/pair-context.d.ts +7 -1
- package/dist/src/tunnel/pair-context.js +25 -9
- package/dist/src/tunnel/pair-context.js.map +1 -1
- package/dist/src/tunnel/pair-url.d.ts +14 -1
- package/dist/src/tunnel/pair-url.js +14 -1
- package/dist/src/tunnel/pair-url.js.map +1 -1
- package/dist/src/tunnel/tunnel-service.js +2 -2
- package/dist/src/tunnel/tunnel-state.js +1 -1
- 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/dist/src/voice/tts/providers/edge-speech.js +2 -2
- package/package.json +3 -2
- package/dist/gateway/static/root/assets/agents-CrpYTHJS.js +0 -222
- package/dist/gateway/static/root/assets/apps-page-1mcKh5Rh.js +0 -1
- package/dist/gateway/static/root/assets/button-KafIU8dx.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-zd6QNKPx.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-uRAuhiUo.js +0 -8
- package/dist/gateway/static/root/assets/cron-api-O2Q_ruV6.js +0 -1
- package/dist/gateway/static/root/assets/cron-page-By09AQD-.js +0 -1
- package/dist/gateway/static/root/assets/dist-C57OMHW8.js +0 -48
- package/dist/gateway/static/root/assets/extension-page-C-Ed5ZmP.js +0 -1
- package/dist/gateway/static/root/assets/extension-settings-page-raLux7E7.js +0 -1
- package/dist/gateway/static/root/assets/fetch-2iRFmd3n.js +0 -3
- package/dist/gateway/static/root/assets/heartbeat-config-api-BVl5VHvL.js +0 -1
- package/dist/gateway/static/root/assets/index-BuFldCsB.css +0 -1
- package/dist/gateway/static/root/assets/index-Y-iqo-gL.js +0 -4693
- package/dist/gateway/static/root/assets/logs-page-BdH2n7ZW.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-Vpchzdp-.js +0 -1
- package/dist/gateway/static/root/assets/settings-form-section-Kk1yAGBl.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-KBm0u6Dz.js +0 -3
- package/dist/gateway/static/root/assets/skills-page-BjeXXaOn.js +0 -2
- package/dist/gateway/static/root/assets/theme-store-D01dJt95.js +0 -1
- package/dist/gateway/static/root/assets/utils-DpTxN4AF.js +0 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-CwO8Cf01.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel-config.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/channel-config.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\n\nimport { loadConfig } from '../../../../config/loader.js';\nimport type { Config } from '../../../../config/schema.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\ntype TelegramCfg = {\n enabled?: boolean;\n accounts?: Record<string, { botToken?: string; dmPolicy?: string; enabled?: boolean }>;\n dmPolicy?: string;\n};\n\ntype WeixinCfg = {\n enabled?: boolean;\n accounts?: Record<string, unknown>;\n};\n\nfunction checkTelegram(cfg: Config): { ok: boolean; messages: string[]; hints: string[] } {\n const tg = cfg.channels?.telegram as TelegramCfg | undefined;\n if (!tg) {\n return { ok: true, messages: [], hints: [] };\n }\n\n const defaultAcc = tg.accounts?.default;\n const token = defaultAcc?.botToken?.trim() ?? '';\n const enabled = tg.enabled === true || token.length > 0;\n\n if (!enabled) {\n return { ok: true, messages: [], hints: [] };\n }\n\n const messages: string[] = [];\n const hints: string[] = [];\n\n if (!token) {\n messages.push('Telegram is enabled but no bot token is set.');\n hints.push('Set channels.telegram.accounts.default.botToken.');\n }\n\n const dm = (defaultAcc?.dmPolicy ?? tg.dmPolicy) || 'pairing';\n if (!['pairing', 'allowlist', 'open', 'disabled'].includes(dm)) {\n messages.push(`Telegram dmPolicy \"${dm}\" is not valid.`);\n }\n if (dm === 'open') {\n messages.push('Telegram DM policy is \"open\" (any user can message the bot).');\n hints.push('Consider \"pairing\" or \"allowlist\" for stricter access.');\n }\n\n return {\n ok: messages.length === 0,\n messages,\n hints,\n };\n}\n\nfunction checkWeixin(cfg: Config): { ok: boolean; messages: string[]; hints: string[] } {\n const wx = cfg.channels?.weixin as WeixinCfg | undefined;\n if (!wx || wx.enabled !== true) {\n return { ok: true, messages: [], hints: [] };\n }\n\n const messages: string[] = [];\n const hints: string[] = [];\n const accountKeys = wx.accounts ? Object.keys(wx.accounts).filter((k) => k.trim()) : [];\n if (accountKeys.length === 0) {\n messages.push('Weixin is enabled but no accounts are defined in config.');\n hints.push('Run: xopc channels weixin
|
|
1
|
+
{"version":3,"file":"channel-config.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/channel-config.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\n\nimport { loadConfig } from '../../../../config/loader.js';\nimport type { Config } from '../../../../config/schema.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\ntype TelegramCfg = {\n enabled?: boolean;\n accounts?: Record<string, { botToken?: string; dmPolicy?: string; enabled?: boolean }>;\n dmPolicy?: string;\n};\n\ntype WeixinCfg = {\n enabled?: boolean;\n accounts?: Record<string, unknown>;\n};\n\nfunction checkTelegram(cfg: Config): { ok: boolean; messages: string[]; hints: string[] } {\n const tg = cfg.channels?.telegram as TelegramCfg | undefined;\n if (!tg) {\n return { ok: true, messages: [], hints: [] };\n }\n\n const defaultAcc = tg.accounts?.default;\n const token = defaultAcc?.botToken?.trim() ?? '';\n const enabled = tg.enabled === true || token.length > 0;\n\n if (!enabled) {\n return { ok: true, messages: [], hints: [] };\n }\n\n const messages: string[] = [];\n const hints: string[] = [];\n\n if (!token) {\n messages.push('Telegram is enabled but no bot token is set.');\n hints.push('Set channels.telegram.accounts.default.botToken.');\n }\n\n const dm = (defaultAcc?.dmPolicy ?? tg.dmPolicy) || 'pairing';\n if (!['pairing', 'allowlist', 'open', 'disabled'].includes(dm)) {\n messages.push(`Telegram dmPolicy \"${dm}\" is not valid.`);\n }\n if (dm === 'open') {\n messages.push('Telegram DM policy is \"open\" (any user can message the bot).');\n hints.push('Consider \"pairing\" or \"allowlist\" for stricter access.');\n }\n\n return {\n ok: messages.length === 0,\n messages,\n hints,\n };\n}\n\nfunction checkWeixin(cfg: Config): { ok: boolean; messages: string[]; hints: string[] } {\n const wx = cfg.channels?.weixin as WeixinCfg | undefined;\n if (!wx || wx.enabled !== true) {\n return { ok: true, messages: [], hints: [] };\n }\n\n const messages: string[] = [];\n const hints: string[] = [];\n const accountKeys = wx.accounts ? Object.keys(wx.accounts).filter((k) => k.trim()) : [];\n if (accountKeys.length === 0) {\n messages.push('Weixin is enabled but no accounts are defined in config.');\n hints.push('Run: xopc channels login --channel weixin (or add channels.weixin.accounts).');\n }\n\n return { ok: messages.length === 0, messages, hints };\n}\n\nexport async function checkChannelConfig(ctx: DoctorContext): Promise<CheckResult> {\n if (!existsSync(ctx.configPath)) {\n return {\n id: 'channel-config',\n label: 'Channels',\n status: 'skip',\n message: 'No config file; skipped.',\n hints: [],\n };\n }\n\n let cfg: Config;\n try {\n cfg = loadConfig(ctx.configPath);\n } catch {\n return {\n id: 'channel-config',\n label: 'Channels',\n status: 'skip',\n message: 'Config could not be loaded; skipped.',\n hints: [],\n };\n }\n\n const tg = checkTelegram(cfg);\n const wx = checkWeixin(cfg);\n const allMsg = [...tg.messages, ...wx.messages];\n const allHints = [...tg.hints, ...wx.hints];\n\n const tgEnabled =\n (cfg.channels?.telegram as TelegramCfg | undefined)?.enabled === true ||\n Boolean((cfg.channels?.telegram as TelegramCfg | undefined)?.accounts?.default?.botToken?.trim());\n const wxOn = (cfg.channels?.weixin as WeixinCfg | undefined)?.enabled === true;\n if (!tgEnabled && !wxOn) {\n return {\n id: 'channel-config',\n label: 'Channels',\n status: 'skip',\n message: 'No channels enabled; skipped.',\n hints: [],\n };\n }\n\n if (allMsg.length === 0) {\n return {\n id: 'channel-config',\n label: 'Channels',\n status: 'pass',\n message: 'Enabled channel configuration looks valid.',\n hints: [],\n };\n }\n\n const hasFail = allMsg.some((m) => m.includes('no bot token') || m.includes('no accounts'));\n return {\n id: 'channel-config',\n label: 'Channels',\n status: hasFail ? 'fail' : 'warn',\n message: allMsg.join(' '),\n hints: allHints,\n };\n}\n"],"mappings":";;;aAE0D;AAe1D,SAAS,cAAc,KAAmE;CACxF,MAAM,KAAK,IAAI,UAAU;AACzB,KAAI,CAAC,GACH,QAAO;EAAE,IAAI;EAAM,UAAU,EAAE;EAAE,OAAO,EAAE;EAAE;CAG9C,MAAM,aAAa,GAAG,UAAU;CAChC,MAAM,QAAQ,YAAY,UAAU,MAAM,IAAI;AAG9C,KAAI,EAFY,GAAG,YAAY,QAAQ,MAAM,SAAS,GAGpD,QAAO;EAAE,IAAI;EAAM,UAAU,EAAE;EAAE,OAAO,EAAE;EAAE;CAG9C,MAAM,WAAqB,EAAE;CAC7B,MAAM,QAAkB,EAAE;AAE1B,KAAI,CAAC,OAAO;AACV,WAAS,KAAK,+CAA+C;AAC7D,QAAM,KAAK,mDAAmD;;CAGhE,MAAM,MAAM,YAAY,YAAY,GAAG,aAAa;AACpD,KAAI,CAAC;EAAC;EAAW;EAAa;EAAQ;EAAW,CAAC,SAAS,GAAG,CAC5D,UAAS,KAAK,sBAAsB,GAAG,iBAAiB;AAE1D,KAAI,OAAO,QAAQ;AACjB,WAAS,KAAK,iEAA+D;AAC7E,QAAM,KAAK,6DAAyD;;AAGtE,QAAO;EACL,IAAI,SAAS,WAAW;EACxB;EACA;EACD;;AAGH,SAAS,YAAY,KAAmE;CACtF,MAAM,KAAK,IAAI,UAAU;AACzB,KAAI,CAAC,MAAM,GAAG,YAAY,KACxB,QAAO;EAAE,IAAI;EAAM,UAAU,EAAE;EAAE,OAAO,EAAE;EAAE;CAG9C,MAAM,WAAqB,EAAE;CAC7B,MAAM,QAAkB,EAAE;AAE1B,MADoB,GAAG,WAAW,OAAO,KAAK,GAAG,SAAS,CAAC,QAAQ,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,EACvE,WAAW,GAAG;AAC5B,WAAS,KAAK,2DAA2D;AACzE,QAAM,KAAK,+EAA+E;;AAG5F,QAAO;EAAE,IAAI,SAAS,WAAW;EAAG;EAAU;EAAO;;AAGvD,eAAsB,mBAAmB,KAA0C;AACjF,KAAI,CAAC,WAAW,IAAI,WAAW,CAC7B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,IAAI;AACJ,KAAI;AACF,QAAM,WAAW,IAAI,WAAW;SAC1B;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,EAAE;GACV;;CAGH,MAAM,KAAK,cAAc,IAAI;CAC7B,MAAM,KAAK,YAAY,IAAI;CAC3B,MAAM,SAAS,CAAC,GAAG,GAAG,UAAU,GAAG,GAAG,SAAS;CAC/C,MAAM,WAAW,CAAC,GAAG,GAAG,OAAO,GAAG,GAAG,MAAM;CAE3C,MAAM,aACH,IAAI,UAAU,WAAsC,YAAY,QACjE,SAAS,IAAI,UAAU,WAAsC,UAAU,SAAS,UAAU,MAAM,CAAC;CACnG,MAAM,QAAQ,IAAI,UAAU,SAAkC,YAAY;AAC1E,KAAI,CAAC,aAAa,CAAC,KACjB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;AAGH,KAAI,OAAO,WAAW,EACpB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;AAIH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAJc,OAAO,MAAM,MAAM,EAAE,SAAS,eAAe,IAAI,EAAE,SAAS,cAAc,CAIzE,GAAG,SAAS;EAC3B,SAAS,OAAO,KAAK,IAAI;EACzB,OAAO;EACR"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ConfigSchema, init_schema } from "../../../../config/schema.js";
|
|
2
2
|
import { init_loader, loadConfig, saveConfig } from "../../../../config/loader.js";
|
|
3
|
-
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
4
3
|
import { dirname } from "node:path";
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
5
5
|
//#region src/cli/commands/doctor/checks/config-health.ts
|
|
6
6
|
init_loader();
|
|
7
7
|
init_schema();
|
|
@@ -33,7 +33,7 @@ async function checkConfigHealth(ctx) {
|
|
|
33
33
|
label: "Config",
|
|
34
34
|
status: "fail",
|
|
35
35
|
message: "Config file not found.",
|
|
36
|
-
hints: [`Run: xopc init`, `Or: xopc doctor --fix`]
|
|
36
|
+
hints: [`Run: xopc init (or xopc setup)`, `Or: xopc doctor --fix`]
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
let raw;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-health.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/config-health.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { mkdirSync } from 'node:fs';\n\nimport { loadConfig, saveConfig } from '../../../../config/loader.js';\nimport { ConfigSchema } from '../../../../config/schema.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nexport async function checkConfigHealth(ctx: DoctorContext): Promise<CheckResult> {\n const path = ctx.configPath;\n\n if (!existsSync(path)) {\n if (ctx.options.fix) {\n try {\n const dir = dirname(path);\n mkdirSync(dir, { recursive: true });\n const defaults = loadConfig(path);\n await saveConfig(defaults, path);\n return {\n id: 'config-health',\n label: 'Config',\n status: 'pass',\n message: 'Created default config file.',\n hints: [path],\n fixed: true,\n };\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return {\n id: 'config-health',\n label: 'Config',\n status: 'fail',\n message: `Config file missing and could not create default: ${msg}`,\n hints: [path],\n };\n }\n }\n return {\n id: 'config-health',\n label: 'Config',\n status: 'fail',\n message: 'Config file not found.',\n hints: [`Run: xopc init`, `Or: xopc doctor --fix`],\n };\n }\n\n let raw: string;\n try {\n raw = readFileSync(path, 'utf-8');\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return {\n id: 'config-health',\n label: 'Config',\n status: 'fail',\n message: `Cannot read config file: ${msg}`,\n hints: [path],\n };\n }\n\n let json: unknown;\n try {\n json = JSON.parse(raw);\n } catch {\n return {\n id: 'config-health',\n label: 'Config',\n status: 'fail',\n message: 'Config file is not valid JSON.',\n hints: ['Fix syntax or restore from backup (.bak).', path],\n };\n }\n\n const parsed = ConfigSchema.safeParse(json);\n if (!parsed.success) {\n return {\n id: 'config-health',\n label: 'Config',\n status: 'fail',\n message: 'Config does not match the expected schema.',\n hints: parsed.error.issues.slice(0, 5).map((i) => `${i.path.join('.') || '(root)'}: ${i.message}`),\n };\n }\n\n return {\n id: 'config-health',\n label: 'Config',\n status: 'pass',\n message: 'Config file exists and validates.',\n hints: [path],\n };\n}\n"],"mappings":";;;;;aAIsE;aACV;AAG5D,eAAsB,kBAAkB,KAA0C;CAChF,MAAM,OAAO,IAAI;AAEjB,KAAI,CAAC,WAAW,KAAK,EAAE;AACrB,MAAI,IAAI,QAAQ,IACd,KAAI;AAEF,aADY,QAAQ,KACP,EAAE,EAAE,WAAW,MAAM,CAAC;AAEnC,SAAM,WADW,WAAW,KACH,EAAE,KAAK;AAChC,UAAO;IACL,IAAI;IACJ,OAAO;IACP,QAAQ;IACR,SAAS;IACT,OAAO,CAAC,KAAK;IACb,OAAO;IACR;WACM,GAAG;AAEV,UAAO;IACL,IAAI;IACJ,OAAO;IACP,QAAQ;IACR,SAAS,qDALC,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;IAMpD,OAAO,CAAC,KAAK;IACd;;AAGL,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"config-health.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/config-health.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { mkdirSync } from 'node:fs';\n\nimport { loadConfig, saveConfig } from '../../../../config/loader.js';\nimport { ConfigSchema } from '../../../../config/schema.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nexport async function checkConfigHealth(ctx: DoctorContext): Promise<CheckResult> {\n const path = ctx.configPath;\n\n if (!existsSync(path)) {\n if (ctx.options.fix) {\n try {\n const dir = dirname(path);\n mkdirSync(dir, { recursive: true });\n const defaults = loadConfig(path);\n await saveConfig(defaults, path);\n return {\n id: 'config-health',\n label: 'Config',\n status: 'pass',\n message: 'Created default config file.',\n hints: [path],\n fixed: true,\n };\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return {\n id: 'config-health',\n label: 'Config',\n status: 'fail',\n message: `Config file missing and could not create default: ${msg}`,\n hints: [path],\n };\n }\n }\n return {\n id: 'config-health',\n label: 'Config',\n status: 'fail',\n message: 'Config file not found.',\n hints: [`Run: xopc init (or xopc setup)`, `Or: xopc doctor --fix`],\n };\n }\n\n let raw: string;\n try {\n raw = readFileSync(path, 'utf-8');\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return {\n id: 'config-health',\n label: 'Config',\n status: 'fail',\n message: `Cannot read config file: ${msg}`,\n hints: [path],\n };\n }\n\n let json: unknown;\n try {\n json = JSON.parse(raw);\n } catch {\n return {\n id: 'config-health',\n label: 'Config',\n status: 'fail',\n message: 'Config file is not valid JSON.',\n hints: ['Fix syntax or restore from backup (.bak).', path],\n };\n }\n\n const parsed = ConfigSchema.safeParse(json);\n if (!parsed.success) {\n return {\n id: 'config-health',\n label: 'Config',\n status: 'fail',\n message: 'Config does not match the expected schema.',\n hints: parsed.error.issues.slice(0, 5).map((i) => `${i.path.join('.') || '(root)'}: ${i.message}`),\n };\n }\n\n return {\n id: 'config-health',\n label: 'Config',\n status: 'pass',\n message: 'Config file exists and validates.',\n hints: [path],\n };\n}\n"],"mappings":";;;;;aAIsE;aACV;AAG5D,eAAsB,kBAAkB,KAA0C;CAChF,MAAM,OAAO,IAAI;AAEjB,KAAI,CAAC,WAAW,KAAK,EAAE;AACrB,MAAI,IAAI,QAAQ,IACd,KAAI;AAEF,aADY,QAAQ,KACP,EAAE,EAAE,WAAW,MAAM,CAAC;AAEnC,SAAM,WADW,WAAW,KACH,EAAE,KAAK;AAChC,UAAO;IACL,IAAI;IACJ,OAAO;IACP,QAAQ;IACR,SAAS;IACT,OAAO,CAAC,KAAK;IACb,OAAO;IACR;WACM,GAAG;AAEV,UAAO;IACL,IAAI;IACJ,OAAO;IACP,QAAQ;IACR,SAAS,qDALC,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;IAMpD,OAAO,CAAC,KAAK;IACd;;AAGL,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,CAAC,kCAAkC,wBAAwB;GACnE;;CAGH,IAAI;AACJ,KAAI;AACF,QAAM,aAAa,MAAM,QAAQ;UAC1B,GAAG;AAEV,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS,4BALC,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;GAMpD,OAAO,CAAC,KAAK;GACd;;CAGH,IAAI;AACJ,KAAI;AACF,SAAO,KAAK,MAAM,IAAI;SAChB;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,CAAC,6CAA6C,KAAK;GAC3D;;CAGH,MAAM,SAAS,aAAa,UAAU,KAAK;AAC3C,KAAI,CAAC,OAAO,QACV,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,OAAO,MAAM,OAAO,MAAM,GAAG,EAAE,CAAC,KAAK,MAAM,GAAG,EAAE,KAAK,KAAK,IAAI,IAAI,SAAS,IAAI,EAAE,UAAU;EACnG;AAGH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,KAAK;EACd"}
|
|
@@ -38,7 +38,7 @@ async function checkCronHealth(ctx) {
|
|
|
38
38
|
label: "Cron",
|
|
39
39
|
status: "warn",
|
|
40
40
|
message: "Cron directory does not exist.",
|
|
41
|
-
hints: [cronDir, "Run: xopc init"]
|
|
41
|
+
hints: [cronDir, "Run: xopc init (creates cron directory)"]
|
|
42
42
|
};
|
|
43
43
|
const jobsPath = resolveCronJobsPath();
|
|
44
44
|
if (!existsSync(jobsPath)) return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cron-health.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/cron-health.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\n\nimport { loadConfig } from '../../../../config/loader.js';\nimport type { Config } from '../../../../config/schema.js';\nimport { resolveCronDir, resolveCronJobsPath } from '../../../../config/paths.js';\nimport { JobDataSchema } from '../../../../cron/validation.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nexport async function checkCronHealth(ctx: DoctorContext): Promise<CheckResult> {\n if (!existsSync(ctx.configPath)) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'skip',\n message: 'No config file; skipped.',\n hints: [],\n };\n }\n\n let cfg: Config;\n try {\n cfg = loadConfig(ctx.configPath);\n } catch {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'skip',\n message: 'Config could not be loaded; skipped.',\n hints: [],\n };\n }\n\n if (cfg.cron?.enabled === false) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'skip',\n message: 'Cron is disabled in config; skipped.',\n hints: [],\n };\n }\n\n const cronDir = resolveCronDir();\n if (!existsSync(cronDir)) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: 'Cron directory does not exist.',\n hints: [cronDir, 'Run: xopc init'],\n };\n }\n\n const jobsPath = resolveCronJobsPath();\n if (!existsSync(jobsPath)) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: 'Cron jobs file is missing.',\n hints: [jobsPath],\n };\n }\n\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(jobsPath, 'utf-8'));\n } catch {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: 'Cron jobs file is not valid JSON.',\n hints: [jobsPath],\n };\n }\n\n if (!raw || typeof raw !== 'object' || !('jobs' in raw) || !Array.isArray((raw as { jobs: unknown }).jobs)) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: 'Cron jobs file has invalid structure (expected { jobs: [] }).',\n hints: [jobsPath],\n };\n }\n\n const jobs = (raw as { jobs: unknown[] }).jobs;\n const hints: string[] = [];\n let valid = 0;\n let enabled = 0;\n let scheduleMissing = 0;\n\n for (const j of jobs) {\n const r = JobDataSchema.safeParse(j);\n if (r.success) {\n valid++;\n if (r.data.enabled) {\n enabled++;\n const sched = r.data.schedule?.trim();\n if (!sched) {\n scheduleMissing++;\n hints.push(`Job \"${r.data.name || r.data.id}\" is enabled but has no schedule.`);\n }\n }\n } else {\n hints.push('One or more job entries failed validation (check jobs.json).');\n break;\n }\n }\n\n if (valid !== jobs.length) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: 'Some cron jobs are invalid or could not be validated.',\n hints: hints.length ? hints.slice(0, 5) : [jobsPath],\n };\n }\n\n if (scheduleMissing > 0) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: `${scheduleMissing} enabled job(s) are missing a schedule.`,\n hints: hints.slice(0, 5),\n };\n }\n\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'pass',\n message: `Cron jobs file is valid (${enabled} enabled, ${jobs.length} total).`,\n hints: [jobsPath],\n };\n}\n"],"mappings":";;;;;aAE0D;YAEwB;AAIlF,eAAsB,gBAAgB,KAA0C;AAC9E,KAAI,CAAC,WAAW,IAAI,WAAW,CAC7B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,IAAI;AACJ,KAAI;AACF,QAAM,WAAW,IAAI,WAAW;SAC1B;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,EAAE;GACV;;AAGH,KAAI,IAAI,MAAM,YAAY,MACxB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,MAAM,UAAU,gBAAgB;AAChC,KAAI,CAAC,WAAW,QAAQ,CACtB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"cron-health.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/cron-health.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\n\nimport { loadConfig } from '../../../../config/loader.js';\nimport type { Config } from '../../../../config/schema.js';\nimport { resolveCronDir, resolveCronJobsPath } from '../../../../config/paths.js';\nimport { JobDataSchema } from '../../../../cron/validation.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nexport async function checkCronHealth(ctx: DoctorContext): Promise<CheckResult> {\n if (!existsSync(ctx.configPath)) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'skip',\n message: 'No config file; skipped.',\n hints: [],\n };\n }\n\n let cfg: Config;\n try {\n cfg = loadConfig(ctx.configPath);\n } catch {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'skip',\n message: 'Config could not be loaded; skipped.',\n hints: [],\n };\n }\n\n if (cfg.cron?.enabled === false) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'skip',\n message: 'Cron is disabled in config; skipped.',\n hints: [],\n };\n }\n\n const cronDir = resolveCronDir();\n if (!existsSync(cronDir)) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: 'Cron directory does not exist.',\n hints: [cronDir, 'Run: xopc init (creates cron directory)'],\n };\n }\n\n const jobsPath = resolveCronJobsPath();\n if (!existsSync(jobsPath)) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: 'Cron jobs file is missing.',\n hints: [jobsPath],\n };\n }\n\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(jobsPath, 'utf-8'));\n } catch {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: 'Cron jobs file is not valid JSON.',\n hints: [jobsPath],\n };\n }\n\n if (!raw || typeof raw !== 'object' || !('jobs' in raw) || !Array.isArray((raw as { jobs: unknown }).jobs)) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: 'Cron jobs file has invalid structure (expected { jobs: [] }).',\n hints: [jobsPath],\n };\n }\n\n const jobs = (raw as { jobs: unknown[] }).jobs;\n const hints: string[] = [];\n let valid = 0;\n let enabled = 0;\n let scheduleMissing = 0;\n\n for (const j of jobs) {\n const r = JobDataSchema.safeParse(j);\n if (r.success) {\n valid++;\n if (r.data.enabled) {\n enabled++;\n const sched = r.data.schedule?.trim();\n if (!sched) {\n scheduleMissing++;\n hints.push(`Job \"${r.data.name || r.data.id}\" is enabled but has no schedule.`);\n }\n }\n } else {\n hints.push('One or more job entries failed validation (check jobs.json).');\n break;\n }\n }\n\n if (valid !== jobs.length) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: 'Some cron jobs are invalid or could not be validated.',\n hints: hints.length ? hints.slice(0, 5) : [jobsPath],\n };\n }\n\n if (scheduleMissing > 0) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: `${scheduleMissing} enabled job(s) are missing a schedule.`,\n hints: hints.slice(0, 5),\n };\n }\n\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'pass',\n message: `Cron jobs file is valid (${enabled} enabled, ${jobs.length} total).`,\n hints: [jobsPath],\n };\n}\n"],"mappings":";;;;;aAE0D;YAEwB;AAIlF,eAAsB,gBAAgB,KAA0C;AAC9E,KAAI,CAAC,WAAW,IAAI,WAAW,CAC7B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,IAAI;AACJ,KAAI;AACF,QAAM,WAAW,IAAI,WAAW;SAC1B;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,EAAE;GACV;;AAGH,KAAI,IAAI,MAAM,YAAY,MACxB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,MAAM,UAAU,gBAAgB;AAChC,KAAI,CAAC,WAAW,QAAQ,CACtB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,SAAS,0CAA0C;EAC5D;CAGH,MAAM,WAAW,qBAAqB;AACtC,KAAI,CAAC,WAAW,SAAS,CACvB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,SAAS;EAClB;CAGH,IAAI;AACJ,KAAI;AACF,QAAM,KAAK,MAAM,aAAa,UAAU,QAAQ,CAAC;SAC3C;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,CAAC,SAAS;GAClB;;AAGH,KAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,EAAE,UAAU,QAAQ,CAAC,MAAM,QAAS,IAA0B,KAAK,CACxG,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,SAAS;EAClB;CAGH,MAAM,OAAQ,IAA4B;CAC1C,MAAM,QAAkB,EAAE;CAC1B,IAAI,QAAQ;CACZ,IAAI,UAAU;CACd,IAAI,kBAAkB;AAEtB,MAAK,MAAM,KAAK,MAAM;EACpB,MAAM,IAAI,cAAc,UAAU,EAAE;AACpC,MAAI,EAAE,SAAS;AACb;AACA,OAAI,EAAE,KAAK,SAAS;AAClB;AAEA,QAAI,CADU,EAAE,KAAK,UAAU,MAAM,EACzB;AACV;AACA,WAAM,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,GAAG,mCAAmC;;;SAG9E;AACL,SAAM,KAAK,+DAA+D;AAC1E;;;AAIJ,KAAI,UAAU,KAAK,OACjB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,MAAM,SAAS,MAAM,MAAM,GAAG,EAAE,GAAG,CAAC,SAAS;EACrD;AAGH,KAAI,kBAAkB,EACpB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS,GAAG,gBAAgB;EAC5B,OAAO,MAAM,MAAM,GAAG,EAAE;EACzB;AAGH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS,4BAA4B,QAAQ,YAAY,KAAK,OAAO;EACrE,OAAO,CAAC,SAAS;EAClB"}
|
|
@@ -46,7 +46,7 @@ async function checkGatewayHealth(ctx) {
|
|
|
46
46
|
label: "Gateway HTTP",
|
|
47
47
|
status: "warn",
|
|
48
48
|
message: `Gateway returned HTTP ${res.status} at ${url}.`,
|
|
49
|
-
hints: ["Start the gateway: xopc gateway start"]
|
|
49
|
+
hints: ["Start the gateway: xopc gateway service start (or xopc gateway for foreground)"]
|
|
50
50
|
};
|
|
51
51
|
} catch (e) {
|
|
52
52
|
clearTimeout(timer);
|
|
@@ -55,7 +55,7 @@ async function checkGatewayHealth(ctx) {
|
|
|
55
55
|
label: "Gateway HTTP",
|
|
56
56
|
status: "warn",
|
|
57
57
|
message: e instanceof Error && e.name === "AbortError" ? `Gateway did not respond within ${FETCH_TIMEOUT_MS / 1e3}s (${url}).` : `Gateway not reachable (${url}).`,
|
|
58
|
-
hints: ["Start the gateway: xopc gateway start", `Configured base: ${base}`]
|
|
58
|
+
hints: ["Start the gateway: xopc gateway service start (or xopc gateway for foreground)", `Configured base: ${base}`]
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
61
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-health.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/gateway-health.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\n\nimport { loadConfig } from '../../../../config/loader.js';\nimport { resolveGatewayLocalClientHost } from '../../../../config/gateway-bind.js';\nimport type { Config } from '../../../../config/schema.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nfunction resolveGatewayBaseUrl(cfg: Config): string {\n const host = resolveGatewayLocalClientHost(cfg);\n const port = cfg.gateway?.port ?? 18790;\n return `http://${host}:${port}`;\n}\n\nconst FETCH_TIMEOUT_MS = 5000;\n\nexport async function checkGatewayHealth(ctx: DoctorContext): Promise<CheckResult> {\n if (!existsSync(ctx.configPath)) {\n return {\n id: 'gateway-health',\n label: 'Gateway HTTP',\n status: 'skip',\n message: 'No config file; skipped.',\n hints: [],\n };\n }\n\n let cfg: Config;\n try {\n cfg = loadConfig(ctx.configPath);\n } catch {\n return {\n id: 'gateway-health',\n label: 'Gateway HTTP',\n status: 'skip',\n message: 'Config could not be loaded; skipped.',\n hints: [],\n };\n }\n\n const base = resolveGatewayBaseUrl(cfg);\n const url = `${base.replace(/\\/$/, '')}/health`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n\n try {\n const res = await fetch(url, { signal: controller.signal });\n clearTimeout(timer);\n if (res.ok) {\n return {\n id: 'gateway-health',\n label: 'Gateway HTTP',\n status: 'pass',\n message: `Gateway responded OK at ${url}.`,\n hints: [],\n };\n }\n return {\n id: 'gateway-health',\n label: 'Gateway HTTP',\n status: 'warn',\n message: `Gateway returned HTTP ${res.status} at ${url}.`,\n hints: ['Start the gateway: xopc gateway start'],\n };\n } catch (e) {\n clearTimeout(timer);\n const isAbort = e instanceof Error && e.name === 'AbortError';\n return {\n id: 'gateway-health',\n label: 'Gateway HTTP',\n status: 'warn',\n message: isAbort\n ? `Gateway did not respond within ${FETCH_TIMEOUT_MS / 1000}s (${url}).`\n : `Gateway not reachable (${url}).`,\n hints: ['Start the gateway: xopc gateway start', `Configured base: ${base}`],\n };\n }\n}\n"],"mappings":";;;;aAE0D;AAK1D,SAAS,sBAAsB,KAAqB;AAGlD,QAAO,UAFM,8BAA8B,IAEtB,CAAC,GADT,IAAI,SAAS,QAAQ;;AAIpC,MAAM,mBAAmB;AAEzB,eAAsB,mBAAmB,KAA0C;AACjF,KAAI,CAAC,WAAW,IAAI,WAAW,CAC7B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,IAAI;AACJ,KAAI;AACF,QAAM,WAAW,IAAI,WAAW;SAC1B;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,EAAE;GACV;;CAGH,MAAM,OAAO,sBAAsB,IAAI;CACvC,MAAM,MAAM,GAAG,KAAK,QAAQ,OAAO,GAAG,CAAC;CACvC,MAAM,aAAa,IAAI,iBAAiB;CACxC,MAAM,QAAQ,iBAAiB,WAAW,OAAO,EAAE,iBAAiB;AAEpE,KAAI;EACF,MAAM,MAAM,MAAM,MAAM,KAAK,EAAE,QAAQ,WAAW,QAAQ,CAAC;AAC3D,eAAa,MAAM;AACnB,MAAI,IAAI,GACN,QAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS,2BAA2B,IAAI;GACxC,OAAO,EAAE;GACV;AAEH,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS,yBAAyB,IAAI,OAAO,MAAM,IAAI;GACvD,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"gateway-health.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/gateway-health.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\n\nimport { loadConfig } from '../../../../config/loader.js';\nimport { resolveGatewayLocalClientHost } from '../../../../config/gateway-bind.js';\nimport type { Config } from '../../../../config/schema.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nfunction resolveGatewayBaseUrl(cfg: Config): string {\n const host = resolveGatewayLocalClientHost(cfg);\n const port = cfg.gateway?.port ?? 18790;\n return `http://${host}:${port}`;\n}\n\nconst FETCH_TIMEOUT_MS = 5000;\n\nexport async function checkGatewayHealth(ctx: DoctorContext): Promise<CheckResult> {\n if (!existsSync(ctx.configPath)) {\n return {\n id: 'gateway-health',\n label: 'Gateway HTTP',\n status: 'skip',\n message: 'No config file; skipped.',\n hints: [],\n };\n }\n\n let cfg: Config;\n try {\n cfg = loadConfig(ctx.configPath);\n } catch {\n return {\n id: 'gateway-health',\n label: 'Gateway HTTP',\n status: 'skip',\n message: 'Config could not be loaded; skipped.',\n hints: [],\n };\n }\n\n const base = resolveGatewayBaseUrl(cfg);\n const url = `${base.replace(/\\/$/, '')}/health`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n\n try {\n const res = await fetch(url, { signal: controller.signal });\n clearTimeout(timer);\n if (res.ok) {\n return {\n id: 'gateway-health',\n label: 'Gateway HTTP',\n status: 'pass',\n message: `Gateway responded OK at ${url}.`,\n hints: [],\n };\n }\n return {\n id: 'gateway-health',\n label: 'Gateway HTTP',\n status: 'warn',\n message: `Gateway returned HTTP ${res.status} at ${url}.`,\n hints: ['Start the gateway: xopc gateway service start (or xopc gateway for foreground)'],\n };\n } catch (e) {\n clearTimeout(timer);\n const isAbort = e instanceof Error && e.name === 'AbortError';\n return {\n id: 'gateway-health',\n label: 'Gateway HTTP',\n status: 'warn',\n message: isAbort\n ? `Gateway did not respond within ${FETCH_TIMEOUT_MS / 1000}s (${url}).`\n : `Gateway not reachable (${url}).`,\n hints: ['Start the gateway: xopc gateway service start (or xopc gateway for foreground)', `Configured base: ${base}`],\n };\n }\n}\n"],"mappings":";;;;aAE0D;AAK1D,SAAS,sBAAsB,KAAqB;AAGlD,QAAO,UAFM,8BAA8B,IAEtB,CAAC,GADT,IAAI,SAAS,QAAQ;;AAIpC,MAAM,mBAAmB;AAEzB,eAAsB,mBAAmB,KAA0C;AACjF,KAAI,CAAC,WAAW,IAAI,WAAW,CAC7B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,IAAI;AACJ,KAAI;AACF,QAAM,WAAW,IAAI,WAAW;SAC1B;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,EAAE;GACV;;CAGH,MAAM,OAAO,sBAAsB,IAAI;CACvC,MAAM,MAAM,GAAG,KAAK,QAAQ,OAAO,GAAG,CAAC;CACvC,MAAM,aAAa,IAAI,iBAAiB;CACxC,MAAM,QAAQ,iBAAiB,WAAW,OAAO,EAAE,iBAAiB;AAEpE,KAAI;EACF,MAAM,MAAM,MAAM,MAAM,KAAK,EAAE,QAAQ,WAAW,QAAQ,CAAC;AAC3D,eAAa,MAAM;AACnB,MAAI,IAAI,GACN,QAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS,2BAA2B,IAAI;GACxC,OAAO,EAAE;GACV;AAEH,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS,yBAAyB,IAAI,OAAO,MAAM,IAAI;GACvD,OAAO,CAAC,iFAAiF;GAC1F;UACM,GAAG;AACV,eAAa,MAAM;AAEnB,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SALc,aAAa,SAAS,EAAE,SAAS,eAM3C,kCAAkC,mBAAmB,IAAK,KAAK,IAAI,MACnE,0BAA0B,IAAI;GAClC,OAAO,CAAC,kFAAkF,oBAAoB,OAAO;GACtH"}
|
|
@@ -40,7 +40,7 @@ async function checkGatewayService(ctx) {
|
|
|
40
40
|
label: "Gateway service",
|
|
41
41
|
status: "warn",
|
|
42
42
|
message: "Gateway is not installed as a system service.",
|
|
43
|
-
hints: ["Install: xopc gateway install
|
|
43
|
+
hints: ["Install: xopc gateway service install"]
|
|
44
44
|
};
|
|
45
45
|
const runtime = await service.readRuntime(env);
|
|
46
46
|
if (runtime.status === "running" && runtime.pid) return {
|
|
@@ -55,7 +55,7 @@ async function checkGatewayService(ctx) {
|
|
|
55
55
|
label: "Gateway service",
|
|
56
56
|
status: "warn",
|
|
57
57
|
message: `Gateway service is installed but not running (status: ${runtime.status}).`,
|
|
58
|
-
hints: ["Start: xopc gateway start"]
|
|
58
|
+
hints: ["Start: xopc gateway service start"]
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
61
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-service.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/gateway-service.ts"],"sourcesContent":["import { loadConfig } from '../../../../config/loader.js';\nimport { existsSync } from 'node:fs';\nimport { resolveGatewayService } from '../../../../daemon/service.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nexport async function checkGatewayService(ctx: DoctorContext): Promise<CheckResult> {\n if (!existsSync(ctx.configPath)) {\n return {\n id: 'gateway-service',\n label: 'Gateway service',\n status: 'skip',\n message: 'No config file; skipped.',\n hints: [],\n };\n }\n\n try {\n loadConfig(ctx.configPath);\n } catch {\n return {\n id: 'gateway-service',\n label: 'Gateway service',\n status: 'skip',\n message: 'Config could not be loaded; skipped.',\n hints: [],\n };\n }\n\n let service;\n try {\n service = await resolveGatewayService();\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return {\n id: 'gateway-service',\n label: 'Gateway service',\n status: 'skip',\n message: `Service backend unavailable: ${msg}`,\n hints: [],\n };\n }\n\n const env: Record<string, string | undefined> = { ...process.env };\n const loaded = await service.isLoaded({ env });\n if (!loaded) {\n return {\n id: 'gateway-service',\n label: 'Gateway service',\n status: 'warn',\n message: 'Gateway is not installed as a system service.',\n hints: ['Install: xopc gateway install
|
|
1
|
+
{"version":3,"file":"gateway-service.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/gateway-service.ts"],"sourcesContent":["import { loadConfig } from '../../../../config/loader.js';\nimport { existsSync } from 'node:fs';\nimport { resolveGatewayService } from '../../../../daemon/service.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nexport async function checkGatewayService(ctx: DoctorContext): Promise<CheckResult> {\n if (!existsSync(ctx.configPath)) {\n return {\n id: 'gateway-service',\n label: 'Gateway service',\n status: 'skip',\n message: 'No config file; skipped.',\n hints: [],\n };\n }\n\n try {\n loadConfig(ctx.configPath);\n } catch {\n return {\n id: 'gateway-service',\n label: 'Gateway service',\n status: 'skip',\n message: 'Config could not be loaded; skipped.',\n hints: [],\n };\n }\n\n let service;\n try {\n service = await resolveGatewayService();\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return {\n id: 'gateway-service',\n label: 'Gateway service',\n status: 'skip',\n message: `Service backend unavailable: ${msg}`,\n hints: [],\n };\n }\n\n const env: Record<string, string | undefined> = { ...process.env };\n const loaded = await service.isLoaded({ env });\n if (!loaded) {\n return {\n id: 'gateway-service',\n label: 'Gateway service',\n status: 'warn',\n message: 'Gateway is not installed as a system service.',\n hints: ['Install: xopc gateway service install'],\n };\n }\n\n const runtime = await service.readRuntime(env);\n if (runtime.status === 'running' && runtime.pid) {\n return {\n id: 'gateway-service',\n label: 'Gateway service',\n status: 'pass',\n message: `Gateway service is running (PID ${runtime.pid}).`,\n hints: [service.label],\n };\n }\n\n return {\n id: 'gateway-service',\n label: 'Gateway service',\n status: 'warn',\n message: `Gateway service is installed but not running (status: ${runtime.status}).`,\n hints: ['Start: xopc gateway service start'],\n };\n}\n"],"mappings":";;;;aAA0D;AAK1D,eAAsB,oBAAoB,KAA0C;AAClF,KAAI,CAAC,WAAW,IAAI,WAAW,CAC7B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;AAGH,KAAI;AACF,aAAW,IAAI,WAAW;SACpB;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,EAAE;GACV;;CAGH,IAAI;AACJ,KAAI;AACF,YAAU,MAAM,uBAAuB;UAChC,GAAG;AAEV,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS,gCALC,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;GAMpD,OAAO,EAAE;GACV;;CAGH,MAAM,MAA0C,EAAE,GAAG,QAAQ,KAAK;AAElE,KAAI,CAAC,MADgB,QAAQ,SAAS,EAAE,KAAK,CAAC,CAE5C,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,wCAAwC;EACjD;CAGH,MAAM,UAAU,MAAM,QAAQ,YAAY,IAAI;AAC9C,KAAI,QAAQ,WAAW,aAAa,QAAQ,IAC1C,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS,mCAAmC,QAAQ,IAAI;EACxD,OAAO,CAAC,QAAQ,MAAM;EACvB;AAGH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS,yDAAyD,QAAQ,OAAO;EACjF,OAAO,CAAC,oCAAoC;EAC7C"}
|
|
@@ -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();
|
|
@@ -2,8 +2,8 @@ import { init_agent_scope, resolveDefaultAgentId } from "../../../../agent/agent
|
|
|
2
2
|
import { init_transcript_paths, resolveSessionFilePath } from "../../../../session/parity/transcript-paths.js";
|
|
3
3
|
import { FILENAMES, init_paths, resolveSessionsDir } from "../../../../config/paths.js";
|
|
4
4
|
import { init_loader, loadConfig } from "../../../../config/loader.js";
|
|
5
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
6
5
|
import { join } from "node:path";
|
|
6
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
7
7
|
//#region src/cli/commands/doctor/checks/session-integrity.ts
|
|
8
8
|
init_agent_scope();
|
|
9
9
|
init_loader();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { accessSync, chmodSync, constants, existsSync, mkdirSync, statSync } from "node:fs";
|
|
2
1
|
import { join } from "node:path";
|
|
2
|
+
import { accessSync, chmodSync, constants, existsSync, mkdirSync, statSync } from "node:fs";
|
|
3
3
|
//#region src/cli/commands/doctor/checks/state-integrity.ts
|
|
4
4
|
function isWritable(dir) {
|
|
5
5
|
try {
|
|
@@ -43,7 +43,7 @@ async function checkStateIntegrity(ctx) {
|
|
|
43
43
|
message: "State directory does not exist.",
|
|
44
44
|
hints: [
|
|
45
45
|
`Expected: ${root}`,
|
|
46
|
-
"Run: xopc init",
|
|
46
|
+
"Run: xopc init (or xopc setup)",
|
|
47
47
|
"Or: xopc doctor --fix"
|
|
48
48
|
]
|
|
49
49
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state-integrity.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/state-integrity.ts"],"sourcesContent":["import { existsSync, mkdirSync, chmodSync, accessSync, constants, statSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nfunction isWritable(dir: string): boolean {\n try {\n accessSync(dir, constants.W_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function checkStateIntegrity(ctx: DoctorContext): Promise<CheckResult> {\n const root = ctx.stateDir;\n const hints: string[] = [];\n\n if (!existsSync(root)) {\n if (ctx.options.fix) {\n try {\n mkdirSync(root, { recursive: true, mode: 0o700 });\n if (process.platform !== 'win32') {\n chmodSync(root, 0o700);\n }\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'pass',\n message: 'Created state directory with safe permissions.',\n hints: [root],\n fixed: true,\n };\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'fail',\n message: `State directory missing and could not create: ${msg}`,\n hints: [root],\n };\n }\n }\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'fail',\n message: 'State directory does not exist.',\n hints: [`Expected: ${root}`, 'Run: xopc init', 'Or: xopc doctor --fix'],\n };\n }\n\n if (!isWritable(root)) {\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'fail',\n message: 'State directory is not writable.',\n hints: [root],\n };\n }\n\n if (process.platform !== 'win32') {\n try {\n const mode = statSync(root).mode & 0o777;\n if (mode !== 0o700) {\n if (ctx.options.fix) {\n chmodSync(root, 0o700);\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'pass',\n message: 'State directory permissions set to 700.',\n hints: [root],\n fixed: true,\n };\n }\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'warn',\n message: 'State directory permissions are not 700 (recommended for privacy).',\n hints: [root, 'Run: xopc doctor --fix'],\n };\n }\n } catch {\n /* ignore stat errors */\n }\n }\n\n const agentsDir = join(root, 'agents');\n if (!existsSync(agentsDir) && ctx.options.fix) {\n try {\n mkdirSync(agentsDir, { recursive: true, mode: 0o700 });\n hints.push(`Created: ${agentsDir}`);\n } catch {\n /* best-effort */\n }\n }\n\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'pass',\n message: 'State directory exists and is usable.',\n hints: hints.length ? hints : [root],\n };\n}\n"],"mappings":";;;AAKA,SAAS,WAAW,KAAsB;AACxC,KAAI;AACF,aAAW,KAAK,UAAU,KAAK;AAC/B,SAAO;SACD;AACN,SAAO;;;AAIX,eAAsB,oBAAoB,KAA0C;CAClF,MAAM,OAAO,IAAI;CACjB,MAAM,QAAkB,EAAE;AAE1B,KAAI,CAAC,WAAW,KAAK,EAAE;AACrB,MAAI,IAAI,QAAQ,IACd,KAAI;AACF,aAAU,MAAM;IAAE,WAAW;IAAM,MAAM;IAAO,CAAC;AACjD,OAAI,QAAQ,aAAa,QACvB,WAAU,MAAM,IAAM;AAExB,UAAO;IACL,IAAI;IACJ,OAAO;IACP,QAAQ;IACR,SAAS;IACT,OAAO,CAAC,KAAK;IACb,OAAO;IACR;WACM,GAAG;AAEV,UAAO;IACL,IAAI;IACJ,OAAO;IACP,QAAQ;IACR,SAAS,iDALC,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;IAMpD,OAAO,CAAC,KAAK;IACd;;AAGL,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO;IAAC,aAAa;IAAQ;
|
|
1
|
+
{"version":3,"file":"state-integrity.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/state-integrity.ts"],"sourcesContent":["import { existsSync, mkdirSync, chmodSync, accessSync, constants, statSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nfunction isWritable(dir: string): boolean {\n try {\n accessSync(dir, constants.W_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function checkStateIntegrity(ctx: DoctorContext): Promise<CheckResult> {\n const root = ctx.stateDir;\n const hints: string[] = [];\n\n if (!existsSync(root)) {\n if (ctx.options.fix) {\n try {\n mkdirSync(root, { recursive: true, mode: 0o700 });\n if (process.platform !== 'win32') {\n chmodSync(root, 0o700);\n }\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'pass',\n message: 'Created state directory with safe permissions.',\n hints: [root],\n fixed: true,\n };\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'fail',\n message: `State directory missing and could not create: ${msg}`,\n hints: [root],\n };\n }\n }\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'fail',\n message: 'State directory does not exist.',\n hints: [`Expected: ${root}`, 'Run: xopc init (or xopc setup)', 'Or: xopc doctor --fix'],\n };\n }\n\n if (!isWritable(root)) {\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'fail',\n message: 'State directory is not writable.',\n hints: [root],\n };\n }\n\n if (process.platform !== 'win32') {\n try {\n const mode = statSync(root).mode & 0o777;\n if (mode !== 0o700) {\n if (ctx.options.fix) {\n chmodSync(root, 0o700);\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'pass',\n message: 'State directory permissions set to 700.',\n hints: [root],\n fixed: true,\n };\n }\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'warn',\n message: 'State directory permissions are not 700 (recommended for privacy).',\n hints: [root, 'Run: xopc doctor --fix'],\n };\n }\n } catch {\n /* ignore stat errors */\n }\n }\n\n const agentsDir = join(root, 'agents');\n if (!existsSync(agentsDir) && ctx.options.fix) {\n try {\n mkdirSync(agentsDir, { recursive: true, mode: 0o700 });\n hints.push(`Created: ${agentsDir}`);\n } catch {\n /* best-effort */\n }\n }\n\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'pass',\n message: 'State directory exists and is usable.',\n hints: hints.length ? hints : [root],\n };\n}\n"],"mappings":";;;AAKA,SAAS,WAAW,KAAsB;AACxC,KAAI;AACF,aAAW,KAAK,UAAU,KAAK;AAC/B,SAAO;SACD;AACN,SAAO;;;AAIX,eAAsB,oBAAoB,KAA0C;CAClF,MAAM,OAAO,IAAI;CACjB,MAAM,QAAkB,EAAE;AAE1B,KAAI,CAAC,WAAW,KAAK,EAAE;AACrB,MAAI,IAAI,QAAQ,IACd,KAAI;AACF,aAAU,MAAM;IAAE,WAAW;IAAM,MAAM;IAAO,CAAC;AACjD,OAAI,QAAQ,aAAa,QACvB,WAAU,MAAM,IAAM;AAExB,UAAO;IACL,IAAI;IACJ,OAAO;IACP,QAAQ;IACR,SAAS;IACT,OAAO,CAAC,KAAK;IACb,OAAO;IACR;WACM,GAAG;AAEV,UAAO;IACL,IAAI;IACJ,OAAO;IACP,QAAQ;IACR,SAAS,iDALC,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;IAMpD,OAAO,CAAC,KAAK;IACd;;AAGL,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO;IAAC,aAAa;IAAQ;IAAkC;IAAwB;GACxF;;AAGH,KAAI,CAAC,WAAW,KAAK,CACnB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,KAAK;EACd;AAGH,KAAI,QAAQ,aAAa,QACvB,KAAI;AAEF,OADa,SAAS,KAAK,CAAC,OAAO,SACtB,KAAO;AAClB,OAAI,IAAI,QAAQ,KAAK;AACnB,cAAU,MAAM,IAAM;AACtB,WAAO;KACL,IAAI;KACJ,OAAO;KACP,QAAQ;KACR,SAAS;KACT,OAAO,CAAC,KAAK;KACb,OAAO;KACR;;AAEH,UAAO;IACL,IAAI;IACJ,OAAO;IACP,QAAQ;IACR,SAAS;IACT,OAAO,CAAC,MAAM,yBAAyB;IACxC;;SAEG;CAKV,MAAM,YAAY,KAAK,MAAM,SAAS;AACtC,KAAI,CAAC,WAAW,UAAU,IAAI,IAAI,QAAQ,IACxC,KAAI;AACF,YAAU,WAAW;GAAE,WAAW;GAAM,MAAM;GAAO,CAAC;AACtD,QAAM,KAAK,YAAY,YAAY;SAC7B;AAKV,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,MAAM,SAAS,QAAQ,CAAC,KAAK;EACrC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { init_agent_scope, resolveAgentProfileDir, resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../../../agent/agent-scope.js";
|
|
2
2
|
import { WORKSPACE_FILES, init_paths } from "../../../../config/paths.js";
|
|
3
3
|
import { init_loader, loadConfig } from "../../../../config/loader.js";
|
|
4
|
-
import { existsSync } from "node:fs";
|
|
5
4
|
import { join } from "node:path";
|
|
5
|
+
import { existsSync } from "node:fs";
|
|
6
6
|
//#region src/cli/commands/doctor/checks/workspace-status.ts
|
|
7
7
|
init_agent_scope();
|
|
8
8
|
init_loader();
|
|
@@ -37,14 +37,14 @@ async function checkWorkspaceStatus(ctx) {
|
|
|
37
37
|
label: "Workspace",
|
|
38
38
|
status: "warn",
|
|
39
39
|
message: "Agent workspace directory is missing.",
|
|
40
|
-
hints: [root, "Run: xopc onboard"]
|
|
40
|
+
hints: [root, "Run: xopc init or xopc onboard"]
|
|
41
41
|
};
|
|
42
42
|
if (!existsSync(profileRoot)) return {
|
|
43
43
|
id: "workspace-status",
|
|
44
44
|
label: "Workspace",
|
|
45
45
|
status: "warn",
|
|
46
46
|
message: "Agent profile directory is missing.",
|
|
47
|
-
hints: [profileRoot, "Run: xopc onboard"]
|
|
47
|
+
hints: [profileRoot, "Run: xopc init or xopc onboard"]
|
|
48
48
|
};
|
|
49
49
|
const missing = [];
|
|
50
50
|
if (!hasProfileFile(WORKSPACE_FILES.SOUL)) missing.push(WORKSPACE_FILES.SOUL);
|
|
@@ -57,7 +57,7 @@ async function checkWorkspaceStatus(ctx) {
|
|
|
57
57
|
hints: [
|
|
58
58
|
profileRoot,
|
|
59
59
|
root,
|
|
60
|
-
"Run: xopc onboard"
|
|
60
|
+
"Run: xopc init or xopc onboard"
|
|
61
61
|
]
|
|
62
62
|
};
|
|
63
63
|
if (!hasProfileFile(WORKSPACE_FILES.USER)) hints.push(`${WORKSPACE_FILES.USER} is optional; add a user profile for better context.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-status.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/workspace-status.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport { resolveDefaultAgentId, resolveAgentProfileDir, resolveAgentWorkspaceDir } from '../../../../agent/agent-scope.js';\nimport { loadConfig } from '../../../../config/loader.js';\nimport { WORKSPACE_FILES } from '../../../../config/paths.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nexport async function checkWorkspaceStatus(ctx: DoctorContext): Promise<CheckResult> {\n if (!existsSync(ctx.configPath)) {\n return {\n id: 'workspace-status',\n label: 'Workspace',\n status: 'skip',\n message: 'No config file; skipped.',\n hints: [],\n };\n }\n\n let config;\n try {\n config = loadConfig(ctx.configPath);\n } catch {\n return {\n id: 'workspace-status',\n label: 'Workspace',\n status: 'skip',\n message: 'Config could not be loaded; skipped.',\n hints: [],\n };\n }\n\n const agentId = resolveDefaultAgentId(config);\n const root = resolveAgentWorkspaceDir(config, agentId);\n const profileRoot = resolveAgentProfileDir(config, agentId);\n const hints: string[] = [];\n\n const hasProfileFile = (name: string): boolean => existsSync(join(profileRoot, name));\n\n if (!existsSync(root)) {\n return {\n id: 'workspace-status',\n label: 'Workspace',\n status: 'warn',\n message: 'Agent workspace directory is missing.',\n hints: [root, 'Run: xopc onboard'],\n };\n }\n\n if (!existsSync(profileRoot)) {\n return {\n id: 'workspace-status',\n label: 'Workspace',\n status: 'warn',\n message: 'Agent profile directory is missing.',\n hints: [profileRoot, 'Run: xopc onboard'],\n };\n }\n\n const missing: string[] = [];\n if (!hasProfileFile(WORKSPACE_FILES.SOUL)) missing.push(WORKSPACE_FILES.SOUL);\n if (!hasProfileFile(WORKSPACE_FILES.IDENTITY)) missing.push(WORKSPACE_FILES.IDENTITY);\n\n if (missing.length > 0) {\n return {\n id: 'workspace-status',\n label: 'Workspace',\n status: 'warn',\n message: `Essential profile files missing: ${missing.join(', ')}.`,\n hints: [profileRoot, root, 'Run: xopc onboard'],\n };\n }\n\n if (!hasProfileFile(WORKSPACE_FILES.USER)) {\n hints.push(`${WORKSPACE_FILES.USER} is optional; add a user profile for better context.`);\n }\n if (!hasProfileFile(WORKSPACE_FILES.TOOLS)) {\n hints.push(`${WORKSPACE_FILES.TOOLS} is optional; add tool notes if you use many tools.`);\n }\n\n if (!existsSync(join(root, '.git'))) {\n hints.push('No .git in workspace; version control is recommended for backup and history.');\n }\n\n if (hints.length > 0) {\n return {\n id: 'workspace-status',\n label: 'Workspace',\n status: 'pass',\n message: 'Markdown workspace and essential profile files are present.',\n hints,\n };\n }\n\n return {\n id: 'workspace-status',\n label: 'Workspace',\n status: 'pass',\n message: 'Markdown workspace and essential profile files look good.',\n hints: [profileRoot, root],\n };\n}\n"],"mappings":";;;;;;kBAG2H;aACjE;YACI;AAG9D,eAAsB,qBAAqB,KAA0C;AACnF,KAAI,CAAC,WAAW,IAAI,WAAW,CAC7B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,IAAI;AACJ,KAAI;AACF,WAAS,WAAW,IAAI,WAAW;SAC7B;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,EAAE;GACV;;CAGH,MAAM,UAAU,sBAAsB,OAAO;CAC7C,MAAM,OAAO,yBAAyB,QAAQ,QAAQ;CACtD,MAAM,cAAc,uBAAuB,QAAQ,QAAQ;CAC3D,MAAM,QAAkB,EAAE;CAE1B,MAAM,kBAAkB,SAA0B,WAAW,KAAK,aAAa,KAAK,CAAC;AAErF,KAAI,CAAC,WAAW,KAAK,CACnB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"workspace-status.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/workspace-status.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport { resolveDefaultAgentId, resolveAgentProfileDir, resolveAgentWorkspaceDir } from '../../../../agent/agent-scope.js';\nimport { loadConfig } from '../../../../config/loader.js';\nimport { WORKSPACE_FILES } from '../../../../config/paths.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nexport async function checkWorkspaceStatus(ctx: DoctorContext): Promise<CheckResult> {\n if (!existsSync(ctx.configPath)) {\n return {\n id: 'workspace-status',\n label: 'Workspace',\n status: 'skip',\n message: 'No config file; skipped.',\n hints: [],\n };\n }\n\n let config;\n try {\n config = loadConfig(ctx.configPath);\n } catch {\n return {\n id: 'workspace-status',\n label: 'Workspace',\n status: 'skip',\n message: 'Config could not be loaded; skipped.',\n hints: [],\n };\n }\n\n const agentId = resolveDefaultAgentId(config);\n const root = resolveAgentWorkspaceDir(config, agentId);\n const profileRoot = resolveAgentProfileDir(config, agentId);\n const hints: string[] = [];\n\n const hasProfileFile = (name: string): boolean => existsSync(join(profileRoot, name));\n\n if (!existsSync(root)) {\n return {\n id: 'workspace-status',\n label: 'Workspace',\n status: 'warn',\n message: 'Agent workspace directory is missing.',\n hints: [root, 'Run: xopc init or xopc onboard'],\n };\n }\n\n if (!existsSync(profileRoot)) {\n return {\n id: 'workspace-status',\n label: 'Workspace',\n status: 'warn',\n message: 'Agent profile directory is missing.',\n hints: [profileRoot, 'Run: xopc init or xopc onboard'],\n };\n }\n\n const missing: string[] = [];\n if (!hasProfileFile(WORKSPACE_FILES.SOUL)) missing.push(WORKSPACE_FILES.SOUL);\n if (!hasProfileFile(WORKSPACE_FILES.IDENTITY)) missing.push(WORKSPACE_FILES.IDENTITY);\n\n if (missing.length > 0) {\n return {\n id: 'workspace-status',\n label: 'Workspace',\n status: 'warn',\n message: `Essential profile files missing: ${missing.join(', ')}.`,\n hints: [profileRoot, root, 'Run: xopc init or xopc onboard'],\n };\n }\n\n if (!hasProfileFile(WORKSPACE_FILES.USER)) {\n hints.push(`${WORKSPACE_FILES.USER} is optional; add a user profile for better context.`);\n }\n if (!hasProfileFile(WORKSPACE_FILES.TOOLS)) {\n hints.push(`${WORKSPACE_FILES.TOOLS} is optional; add tool notes if you use many tools.`);\n }\n\n if (!existsSync(join(root, '.git'))) {\n hints.push('No .git in workspace; version control is recommended for backup and history.');\n }\n\n if (hints.length > 0) {\n return {\n id: 'workspace-status',\n label: 'Workspace',\n status: 'pass',\n message: 'Markdown workspace and essential profile files are present.',\n hints,\n };\n }\n\n return {\n id: 'workspace-status',\n label: 'Workspace',\n status: 'pass',\n message: 'Markdown workspace and essential profile files look good.',\n hints: [profileRoot, root],\n };\n}\n"],"mappings":";;;;;;kBAG2H;aACjE;YACI;AAG9D,eAAsB,qBAAqB,KAA0C;AACnF,KAAI,CAAC,WAAW,IAAI,WAAW,CAC7B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,IAAI;AACJ,KAAI;AACF,WAAS,WAAW,IAAI,WAAW;SAC7B;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,EAAE;GACV;;CAGH,MAAM,UAAU,sBAAsB,OAAO;CAC7C,MAAM,OAAO,yBAAyB,QAAQ,QAAQ;CACtD,MAAM,cAAc,uBAAuB,QAAQ,QAAQ;CAC3D,MAAM,QAAkB,EAAE;CAE1B,MAAM,kBAAkB,SAA0B,WAAW,KAAK,aAAa,KAAK,CAAC;AAErF,KAAI,CAAC,WAAW,KAAK,CACnB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,MAAM,iCAAiC;EAChD;AAGH,KAAI,CAAC,WAAW,YAAY,CAC1B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,aAAa,iCAAiC;EACvD;CAGH,MAAM,UAAoB,EAAE;AAC5B,KAAI,CAAC,eAAe,gBAAgB,KAAK,CAAE,SAAQ,KAAK,gBAAgB,KAAK;AAC7E,KAAI,CAAC,eAAe,gBAAgB,SAAS,CAAE,SAAQ,KAAK,gBAAgB,SAAS;AAErF,KAAI,QAAQ,SAAS,EACnB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS,oCAAoC,QAAQ,KAAK,KAAK,CAAC;EAChE,OAAO;GAAC;GAAa;GAAM;GAAiC;EAC7D;AAGH,KAAI,CAAC,eAAe,gBAAgB,KAAK,CACvC,OAAM,KAAK,GAAG,gBAAgB,KAAK,sDAAsD;AAE3F,KAAI,CAAC,eAAe,gBAAgB,MAAM,CACxC,OAAM,KAAK,GAAG,gBAAgB,MAAM,qDAAqD;AAG3F,KAAI,CAAC,WAAW,KAAK,MAAM,OAAO,CAAC,CACjC,OAAM,KAAK,+EAA+E;AAG5F,KAAI,MAAM,SAAS,EACjB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT;EACD;AAGH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACN,SAAS;EACT,OAAO,CAAC,aAAa,KAAK;EAC7B"}
|
|
@@ -12,8 +12,8 @@ import { runGatewayLoop } from "../../gateway/run-loop.js";
|
|
|
12
12
|
import "../../gateway/index.js";
|
|
13
13
|
import { colors } from "../utils/colors.js";
|
|
14
14
|
import { initWorkspace } from "../utils/init-workspace.js";
|
|
15
|
-
import { existsSync, mkdirSync, readFileSync, symlinkSync, unlinkSync, watch } from "node:fs";
|
|
16
15
|
import { join, resolve } from "node:path";
|
|
16
|
+
import { existsSync, mkdirSync, readFileSync, symlinkSync, unlinkSync, watch } from "node:fs";
|
|
17
17
|
import { Command } from "commander";
|
|
18
18
|
//#region src/cli/commands/extension-dev.ts
|
|
19
19
|
init_loader();
|
|
@@ -7,8 +7,8 @@ import { installExtensionFromStoreZip, installFromLocal, installFromNpm, peekExt
|
|
|
7
7
|
import { fetchRegistry, findExtension, getExtensionMarketplaceStoreBaseUrl, listExtensions, searchExtensions } from "../../extensions/marketplace.js";
|
|
8
8
|
import { downloadExtensionStoreZipBuffer, resolveExtensionZipDownloadUrl, resolveExtensionsStoreBaseUrl } from "../../agent/skills/marketplace/adapters/store/store-api-client.js";
|
|
9
9
|
import { colors } from "../utils/colors.js";
|
|
10
|
-
import { existsSync, readFileSync, rmSync, statSync } from "node:fs";
|
|
11
10
|
import { join, resolve } from "node:path";
|
|
11
|
+
import { existsSync, readFileSync, rmSync, statSync } from "node:fs";
|
|
12
12
|
import { execSync } from "node:child_process";
|
|
13
13
|
import { Command } from "commander";
|
|
14
14
|
import semver from "semver";
|
|
@@ -4,8 +4,8 @@ import { init_logger } from "../../utils/logger.js";
|
|
|
4
4
|
import { normalizeExtensionManifest } from "../../extensions/normalize-manifest.js";
|
|
5
5
|
import { checkEngineCompatibility } from "../../extensions/engine-check.js";
|
|
6
6
|
import { colors } from "../utils/colors.js";
|
|
7
|
-
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync } from "node:fs";
|
|
8
7
|
import { isAbsolute, join, resolve } from "node:path";
|
|
8
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync } from "node:fs";
|
|
9
9
|
import { execSync } from "node:child_process";
|
|
10
10
|
import { Command } from "commander";
|
|
11
11
|
//#region src/cli/commands/extension-pack.ts
|
|
@@ -6,4 +6,4 @@ export { createProbeCommand } from './probe.js';
|
|
|
6
6
|
export { createStopCommand } from './stop.js';
|
|
7
7
|
export { createRestartCommand } from './restart.js';
|
|
8
8
|
export { createLogsCommand } from './logs.js';
|
|
9
|
-
export { createInstallCommand, createUninstallCommand, createServiceStartCommand, createServiceStatusCommand, } from './service.js';
|
|
9
|
+
export { createInstallCommand, createUninstallCommand, createServiceStartCommand, createServiceStatusCommand, createServiceCommand, } from './service.js';
|
|
@@ -6,5 +6,5 @@ import { createProbeCommand } from "./probe.js";
|
|
|
6
6
|
import { createStopCommand } from "./stop.js";
|
|
7
7
|
import { createRestartCommand } from "./restart.js";
|
|
8
8
|
import { createLogsCommand } from "./logs.js";
|
|
9
|
-
import { createInstallCommand, createServiceStartCommand, createServiceStatusCommand, createUninstallCommand } from "./service.js";
|
|
10
|
-
export { createCallCommand, createHealthCommand, createInstallCommand, createLogsCommand, createProbeCommand, createRestartCommand, createServiceStartCommand, createServiceStatusCommand, createStatusCommand, createStopCommand, createTokenCommand, createUninstallCommand };
|
|
9
|
+
import { createInstallCommand, createServiceCommand, createServiceStartCommand, createServiceStatusCommand, createUninstallCommand } from "./service.js";
|
|
10
|
+
export { createCallCommand, createHealthCommand, createInstallCommand, createLogsCommand, createProbeCommand, createRestartCommand, createServiceCommand, createServiceStartCommand, createServiceStatusCommand, createStatusCommand, createStopCommand, createTokenCommand, createUninstallCommand };
|
|
@@ -3,7 +3,7 @@ import { loadConfig } from "../../../config/loader.js";
|
|
|
3
3
|
import "../../../config/index.js";
|
|
4
4
|
import { isRestartEnabled } from "../../../config/commands.flags.js";
|
|
5
5
|
import { resolveGatewayService } from "../../../daemon/service.js";
|
|
6
|
-
import { authorizeGatewaySigusr1Restart } from "../../../infra/restart.js";
|
|
6
|
+
import { authorizeGatewaySigusr1Restart, writeGatewayRestartIntentSync } from "../../../infra/restart.js";
|
|
7
7
|
import { findVerifiedGatewayListenerPidsOnPortSync, formatGatewayPidList, signalVerifiedGatewayPidSync } from "../../../infra/gateway-processes.js";
|
|
8
8
|
import { runServiceRestart, runServiceStop } from "./lifecycle-core.js";
|
|
9
9
|
import { DEFAULT_RESTART_HEALTH_ATTEMPTS, renderGatewayPortHealthDiagnostics, waitForGatewayHealthyListener } from "./restart-health.js";
|
|
@@ -48,11 +48,17 @@ async function restartGatewayWithoutServiceManager(port) {
|
|
|
48
48
|
const pids = resolveVerifiedGatewayListenerPids(port);
|
|
49
49
|
if (pids.length === 0) return null;
|
|
50
50
|
if (pids.length > 1) throw new Error(`multiple gateway processes are listening on port ${port}: ${formatGatewayPidList(pids)}; use "xopc gateway status" before retrying restart`);
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
const targetPid = pids[0];
|
|
52
|
+
if (process.platform === "win32") {
|
|
53
|
+
writeGatewayRestartIntentSync({ targetPid });
|
|
54
|
+
signalVerifiedGatewayPidSync(targetPid, "SIGTERM");
|
|
55
|
+
} else {
|
|
56
|
+
authorizeGatewaySigusr1Restart();
|
|
57
|
+
signalVerifiedGatewayPidSync(targetPid, "SIGUSR1");
|
|
58
|
+
}
|
|
53
59
|
return {
|
|
54
60
|
result: "restarted",
|
|
55
|
-
message: `Gateway restart signal sent to unmanaged process on port ${port}: ${
|
|
61
|
+
message: `Gateway restart signal sent to unmanaged process on port ${port}: ${targetPid}.`
|
|
56
62
|
};
|
|
57
63
|
}
|
|
58
64
|
async function runDaemonStop(options = {}) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle.js","names":[],"sources":["../../../../../src/cli/commands/gateway/lifecycle.ts"],"sourcesContent":["/**\n * Gateway lifecycle orchestration — OpenClaw-aligned service + unmanaged fallback.\n */\n\nimport { isRestartEnabled } from '../../../config/commands.flags.js';\nimport { loadConfig } from '../../../config/index.js';\nimport { resolveConfigPath } from '../../../config/paths.js';\nimport { resolveGatewayService } from '../../../daemon/service.js';\nimport {\n findVerifiedGatewayListenerPidsOnPortSync,\n formatGatewayPidList,\n signalVerifiedGatewayPidSync,\n} from '../../../infra/gateway-processes.js';\nimport { authorizeGatewaySigusr1Restart } from '../../../infra/restart.js';\nimport {\n DEFAULT_RESTART_HEALTH_ATTEMPTS,\n DEFAULT_RESTART_HEALTH_DELAY_MS,\n renderGatewayPortHealthDiagnostics,\n waitForGatewayHealthyListener,\n} from './restart-health.js';\nimport {\n parsePortFromArgs,\n renderGatewayServiceStartHints,\n resolveGatewayPortFromConfig,\n} from './shared.js';\nimport {\n runServiceRestart,\n runServiceStop,\n type ServiceRecoveryResult,\n} from './lifecycle-core.js';\n\nconst POST_RESTART_HEALTH_ATTEMPTS = DEFAULT_RESTART_HEALTH_ATTEMPTS;\nconst POST_RESTART_HEALTH_DELAY_MS = DEFAULT_RESTART_HEALTH_DELAY_MS;\n\nasync function resolveGatewayLifecyclePort(service?: Awaited<ReturnType<typeof resolveGatewayService>>): Promise<number> {\n const resolvedService = service ?? (await resolveGatewayService());\n const command = await resolvedService.readCommand(process.env).catch(() => null);\n const portFromArgs = parsePortFromArgs(command?.programArguments);\n return portFromArgs ?? resolveGatewayPortFromConfig();\n}\n\nfunction resolveVerifiedGatewayListenerPids(port: number): number[] {\n return findVerifiedGatewayListenerPidsOnPortSync(port).filter(\n (pid): pid is number => Number.isFinite(pid) && pid > 0,\n );\n}\n\nasync function assertUnmanagedGatewayRestartEnabled(port: number): Promise<void> {\n const config = loadConfig(resolveConfigPath());\n if (!isRestartEnabled(config)) {\n throw new Error(\n 'Gateway restart is disabled in config (commands.restart=false); unmanaged SIGUSR1 restart would be ignored',\n );\n }\n\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 1000);\n const response = await fetch(`http://127.0.0.1:${port}/api/health`, {\n method: 'GET',\n signal: controller.signal,\n });\n clearTimeout(timeout);\n if (!response.ok) {\n return;\n }\n } catch {\n // Best-effort probe; unmanaged restart may still target a starting gateway.\n }\n}\n\nasync function stopGatewayWithoutServiceManager(port: number): Promise<ServiceRecoveryResult | null> {\n const pids = resolveVerifiedGatewayListenerPids(port);\n if (pids.length === 0) {\n return null;\n }\n for (const pid of pids) {\n signalVerifiedGatewayPidSync(pid, 'SIGTERM');\n }\n return {\n result: 'stopped',\n message: `Gateway stop signal sent to unmanaged process${pids.length === 1 ? '' : 'es'} on port ${port}: ${formatGatewayPidList(pids)}.`,\n };\n}\n\nasync function restartGatewayWithoutServiceManager(port: number): Promise<ServiceRecoveryResult | null> {\n await assertUnmanagedGatewayRestartEnabled(port);\n const pids = resolveVerifiedGatewayListenerPids(port);\n if (pids.length === 0) {\n return null;\n }\n if (pids.length > 1) {\n throw new Error(\n `multiple gateway processes are listening on port ${port}: ${formatGatewayPidList(pids)}; use \"xopc gateway status\" before retrying restart`,\n );\n }\n authorizeGatewaySigusr1Restart();\n
|
|
1
|
+
{"version":3,"file":"lifecycle.js","names":[],"sources":["../../../../../src/cli/commands/gateway/lifecycle.ts"],"sourcesContent":["/**\n * Gateway lifecycle orchestration — OpenClaw-aligned service + unmanaged fallback.\n */\n\nimport { isRestartEnabled } from '../../../config/commands.flags.js';\nimport { loadConfig } from '../../../config/index.js';\nimport { resolveConfigPath } from '../../../config/paths.js';\nimport { resolveGatewayService } from '../../../daemon/service.js';\nimport {\n findVerifiedGatewayListenerPidsOnPortSync,\n formatGatewayPidList,\n signalVerifiedGatewayPidSync,\n} from '../../../infra/gateway-processes.js';\nimport { authorizeGatewaySigusr1Restart, writeGatewayRestartIntentSync } from '../../../infra/restart.js';\nimport {\n DEFAULT_RESTART_HEALTH_ATTEMPTS,\n DEFAULT_RESTART_HEALTH_DELAY_MS,\n renderGatewayPortHealthDiagnostics,\n waitForGatewayHealthyListener,\n} from './restart-health.js';\nimport {\n parsePortFromArgs,\n renderGatewayServiceStartHints,\n resolveGatewayPortFromConfig,\n} from './shared.js';\nimport {\n runServiceRestart,\n runServiceStop,\n type ServiceRecoveryResult,\n} from './lifecycle-core.js';\n\nconst POST_RESTART_HEALTH_ATTEMPTS = DEFAULT_RESTART_HEALTH_ATTEMPTS;\nconst POST_RESTART_HEALTH_DELAY_MS = DEFAULT_RESTART_HEALTH_DELAY_MS;\n\nasync function resolveGatewayLifecyclePort(service?: Awaited<ReturnType<typeof resolveGatewayService>>): Promise<number> {\n const resolvedService = service ?? (await resolveGatewayService());\n const command = await resolvedService.readCommand(process.env).catch(() => null);\n const portFromArgs = parsePortFromArgs(command?.programArguments);\n return portFromArgs ?? resolveGatewayPortFromConfig();\n}\n\nfunction resolveVerifiedGatewayListenerPids(port: number): number[] {\n return findVerifiedGatewayListenerPidsOnPortSync(port).filter(\n (pid): pid is number => Number.isFinite(pid) && pid > 0,\n );\n}\n\nasync function assertUnmanagedGatewayRestartEnabled(port: number): Promise<void> {\n const config = loadConfig(resolveConfigPath());\n if (!isRestartEnabled(config)) {\n throw new Error(\n 'Gateway restart is disabled in config (commands.restart=false); unmanaged SIGUSR1 restart would be ignored',\n );\n }\n\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 1000);\n const response = await fetch(`http://127.0.0.1:${port}/api/health`, {\n method: 'GET',\n signal: controller.signal,\n });\n clearTimeout(timeout);\n if (!response.ok) {\n return;\n }\n } catch {\n // Best-effort probe; unmanaged restart may still target a starting gateway.\n }\n}\n\nasync function stopGatewayWithoutServiceManager(port: number): Promise<ServiceRecoveryResult | null> {\n const pids = resolveVerifiedGatewayListenerPids(port);\n if (pids.length === 0) {\n return null;\n }\n for (const pid of pids) {\n signalVerifiedGatewayPidSync(pid, 'SIGTERM');\n }\n return {\n result: 'stopped',\n message: `Gateway stop signal sent to unmanaged process${pids.length === 1 ? '' : 'es'} on port ${port}: ${formatGatewayPidList(pids)}.`,\n };\n}\n\nasync function restartGatewayWithoutServiceManager(port: number): Promise<ServiceRecoveryResult | null> {\n await assertUnmanagedGatewayRestartEnabled(port);\n const pids = resolveVerifiedGatewayListenerPids(port);\n if (pids.length === 0) {\n return null;\n }\n if (pids.length > 1) {\n throw new Error(\n `multiple gateway processes are listening on port ${port}: ${formatGatewayPidList(pids)}; use \"xopc gateway status\" before retrying restart`,\n );\n }\n const targetPid = pids[0];\n\n if (process.platform === 'win32') {\n // Windows does not support SIGUSR1. Write a restart intent file and send\n // SIGTERM; the gateway run-loop's onSigterm handler checks for the intent\n // and treats it as a restart instead of a stop.\n writeGatewayRestartIntentSync({ targetPid });\n signalVerifiedGatewayPidSync(targetPid, 'SIGTERM');\n } else {\n authorizeGatewaySigusr1Restart();\n signalVerifiedGatewayPidSync(targetPid, 'SIGUSR1');\n }\n\n return {\n result: 'restarted',\n message: `Gateway restart signal sent to unmanaged process on port ${port}: ${targetPid}.`,\n };\n}\n\nexport async function runDaemonStop(options: { json?: boolean; disable?: boolean } = {}): Promise<void> {\n const service = await resolveGatewayService();\n let gatewayPortPromise: Promise<number> | undefined;\n\n await runServiceStop({\n service,\n opts: options,\n onNotLoaded: async () => {\n gatewayPortPromise ??= resolveGatewayLifecyclePort(service);\n return stopGatewayWithoutServiceManager(await gatewayPortPromise);\n },\n });\n}\n\nexport async function runDaemonRestart(options: {\n json?: boolean;\n wait?: string;\n} = {}): Promise<void> {\n const service = await resolveGatewayService();\n let restartedWithoutServiceManager = false;\n const restartPort = await resolveGatewayLifecyclePort(service);\n const restartHealthAttempts = POST_RESTART_HEALTH_ATTEMPTS;\n const restartWaitSeconds = Math.round(\n (restartHealthAttempts * POST_RESTART_HEALTH_DELAY_MS) / 1000,\n );\n\n await runServiceRestart({\n service,\n opts: options,\n renderStartHints: renderGatewayServiceStartHints,\n checkTokenDrift: true,\n onNotLoaded: async () => {\n const handled = await restartGatewayWithoutServiceManager(restartPort);\n if (handled) {\n restartedWithoutServiceManager = true;\n }\n return handled;\n },\n postRestartCheck: async ({ options: opts, fail }) => {\n if (!restartedWithoutServiceManager) {\n return;\n }\n const health = await waitForGatewayHealthyListener({\n port: restartPort,\n attempts: restartHealthAttempts,\n delayMs: POST_RESTART_HEALTH_DELAY_MS,\n });\n if (health.healthy) {\n return;\n }\n const diagnostics = renderGatewayPortHealthDiagnostics(health);\n fail(\n `Gateway restart timed out after ${restartWaitSeconds}s waiting for health checks.`,\n ['xopc gateway status', 'xopc doctor'],\n diagnostics,\n opts,\n );\n },\n });\n}\n"],"mappings":";;;;;;;;;;;;;;YAM6D;AAyB7D,MAAM,+BAA+B;AACrC,MAAM,+BAAA;AAEN,eAAe,4BAA4B,SAA8E;AAIvH,QADqB,mBAAkB,OAFf,WAAY,MAAM,uBAAuB,EAC3B,YAAY,QAAQ,IAAI,CAAC,YAAY,KAAK,GAChC,iBAC7B,IAAI,8BAA8B;;AAGvD,SAAS,mCAAmC,MAAwB;AAClE,QAAO,0CAA0C,KAAK,CAAC,QACpD,QAAuB,OAAO,SAAS,IAAI,IAAI,MAAM,EACvD;;AAGH,eAAe,qCAAqC,MAA6B;AAE/E,KAAI,CAAC,iBADU,WAAW,mBAAmB,CACjB,CAAC,CAC3B,OAAM,IAAI,MACR,6GACD;AAGH,KAAI;EACF,MAAM,aAAa,IAAI,iBAAiB;EACxC,MAAM,UAAU,iBAAiB,WAAW,OAAO,EAAE,IAAK;EAC1D,MAAM,WAAW,MAAM,MAAM,oBAAoB,KAAK,cAAc;GAClE,QAAQ;GACR,QAAQ,WAAW;GACpB,CAAC;AACF,eAAa,QAAQ;AACrB,MAAI,CAAC,SAAS,GACZ;SAEI;;AAKV,eAAe,iCAAiC,MAAqD;CACnG,MAAM,OAAO,mCAAmC,KAAK;AACrD,KAAI,KAAK,WAAW,EAClB,QAAO;AAET,MAAK,MAAM,OAAO,KAChB,8BAA6B,KAAK,UAAU;AAE9C,QAAO;EACL,QAAQ;EACR,SAAS,gDAAgD,KAAK,WAAW,IAAI,KAAK,KAAK,WAAW,KAAK,IAAI,qBAAqB,KAAK,CAAC;EACvI;;AAGH,eAAe,oCAAoC,MAAqD;AACtG,OAAM,qCAAqC,KAAK;CAChD,MAAM,OAAO,mCAAmC,KAAK;AACrD,KAAI,KAAK,WAAW,EAClB,QAAO;AAET,KAAI,KAAK,SAAS,EAChB,OAAM,IAAI,MACR,oDAAoD,KAAK,IAAI,qBAAqB,KAAK,CAAC,qDACzF;CAEH,MAAM,YAAY,KAAK;AAEvB,KAAI,QAAQ,aAAa,SAAS;AAIhC,gCAA8B,EAAE,WAAW,CAAC;AAC5C,+BAA6B,WAAW,UAAU;QAC7C;AACL,kCAAgC;AAChC,+BAA6B,WAAW,UAAU;;AAGpD,QAAO;EACL,QAAQ;EACR,SAAS,4DAA4D,KAAK,IAAI,UAAU;EACzF;;AAGH,eAAsB,cAAc,UAAiD,EAAE,EAAiB;CACtG,MAAM,UAAU,MAAM,uBAAuB;CAC7C,IAAI;AAEJ,OAAM,eAAe;EACnB;EACA,MAAM;EACN,aAAa,YAAY;AACvB,0BAAuB,4BAA4B,QAAQ;AAC3D,UAAO,iCAAiC,MAAM,mBAAmB;;EAEpE,CAAC;;AAGJ,eAAsB,iBAAiB,UAGnC,EAAE,EAAiB;CACrB,MAAM,UAAU,MAAM,uBAAuB;CAC7C,IAAI,iCAAiC;CACrC,MAAM,cAAc,MAAM,4BAA4B,QAAQ;CAC9D,MAAM,wBAAwB;CAC9B,MAAM,qBAAqB,KAAK,MAC7B,wBAAwB,+BAAgC,IAC1D;AAED,OAAM,kBAAkB;EACtB;EACA,MAAM;EACN,kBAAkB;EAClB,iBAAiB;EACjB,aAAa,YAAY;GACvB,MAAM,UAAU,MAAM,oCAAoC,YAAY;AACtE,OAAI,QACF,kCAAiC;AAEnC,UAAO;;EAET,kBAAkB,OAAO,EAAE,SAAS,MAAM,WAAW;AACnD,OAAI,CAAC,+BACH;GAEF,MAAM,SAAS,MAAM,8BAA8B;IACjD,MAAM;IACN,UAAU;IACV,SAAS;IACV,CAAC;AACF,OAAI,OAAO,QACT;GAEF,MAAM,cAAc,mCAAmC,OAAO;AAC9D,QACE,mCAAmC,mBAAmB,+BACtD,CAAC,uBAAuB,cAAc,EACtC,aACA,KACD;;EAEJ,CAAC"}
|
|
@@ -15,3 +15,7 @@ export declare function createServiceStartCommand(): Command;
|
|
|
15
15
|
* Create service status subcommand
|
|
16
16
|
*/
|
|
17
17
|
export declare function createServiceStatusCommand(): Command;
|
|
18
|
+
/**
|
|
19
|
+
* Gateway OS service command group (`xopc gateway service …`).
|
|
20
|
+
*/
|
|
21
|
+
export declare function createServiceCommand(): Command;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { init_paths, resolveConfigPath } from "../../../config/paths.js";
|
|
2
2
|
import { getContextWithOpts } from "../../context.js";
|
|
3
|
+
import { createStopCommand } from "./stop.js";
|
|
4
|
+
import { createRestartCommand } from "./restart.js";
|
|
3
5
|
import { Command } from "commander";
|
|
4
6
|
//#region src/cli/commands/gateway/service.ts
|
|
5
7
|
init_paths();
|
|
@@ -122,7 +124,7 @@ function createServiceStartCommand() {
|
|
|
122
124
|
* Create service status subcommand
|
|
123
125
|
*/
|
|
124
126
|
function createServiceStatusCommand() {
|
|
125
|
-
return new Command("
|
|
127
|
+
return new Command("status").description("Show OS service status").option("--json", "Output JSON").action(async (options) => {
|
|
126
128
|
const [{ resolveGatewayService, isDaemonAvailableAsync, getPlatformName }] = await Promise.all([import("../../../daemon/service.js")]);
|
|
127
129
|
if (!await isDaemonAvailableAsync()) {
|
|
128
130
|
if (options.json) console.log(JSON.stringify({
|
|
@@ -165,7 +167,20 @@ function createServiceStatusCommand() {
|
|
|
165
167
|
}
|
|
166
168
|
});
|
|
167
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* Gateway OS service command group (`xopc gateway service …`).
|
|
172
|
+
*/
|
|
173
|
+
function createServiceCommand() {
|
|
174
|
+
const cmd = new Command("service").description("Manage gateway OS service (LaunchAgent / systemd / Task)");
|
|
175
|
+
cmd.addCommand(createInstallCommand());
|
|
176
|
+
cmd.addCommand(createUninstallCommand());
|
|
177
|
+
cmd.addCommand(createServiceStartCommand());
|
|
178
|
+
cmd.addCommand(createServiceStatusCommand());
|
|
179
|
+
cmd.addCommand(createStopCommand());
|
|
180
|
+
cmd.addCommand(createRestartCommand());
|
|
181
|
+
return cmd;
|
|
182
|
+
}
|
|
168
183
|
//#endregion
|
|
169
|
-
export { createInstallCommand, createServiceStartCommand, createServiceStatusCommand, createUninstallCommand };
|
|
184
|
+
export { createInstallCommand, createServiceCommand, createServiceStartCommand, createServiceStatusCommand, createUninstallCommand };
|
|
170
185
|
|
|
171
186
|
//# sourceMappingURL=service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.js","names":[],"sources":["../../../../../src/cli/commands/gateway/service.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { resolveConfigPath } from '../../../config/paths.js';\nimport { getContextWithOpts } from '../../context.js';\n\n/**\n * Create service install subcommand - actually installs the OS service\n */\nexport function createInstallCommand(): Command {\n return new Command('install')\n .description('Install gateway as OS service (LaunchAgent / systemd / Task)')\n .option('--port <port>', 'Gateway port')\n .option('--token <token>', 'Gateway auth token')\n .option('--force', 'Force reinstall if already installed')\n .option('--json', 'Output JSON')\n .action(async (options) => {\n const ctx = getContextWithOpts();\n const configPath = ctx.configPath || resolveConfigPath();\n\n const [{ loadConfig }, { resolveGatewayService, isDaemonAvailableAsync, getPlatformName }, { buildGatewayInstallArgs }] =\n await Promise.all([\n import('../../../config/index.js'),\n import('../../../daemon/service.js'),\n import('../../../daemon/install-plan.js'),\n ]);\n\n const config = loadConfig(configPath);\n const port = options.port ? parseInt(options.port, 10) : (config?.gateway?.port || 18790);\n const bind = config?.gateway?.bind ?? 'loopback';\n const token = options.token || config?.gateway?.auth?.token;\n\n const available = await isDaemonAvailableAsync();\n if (!available) {\n if (options.json) {\n console.log(JSON.stringify({ ok: false, error: 'Daemon not available' }));\n } else {\n console.error(`❌ OS service not available on ${getPlatformName()}`);\n }\n process.exit(1);\n }\n\n const service = await resolveGatewayService();\n\n // Check if already installed\n const loaded = await service.isLoaded({ env: process.env });\n if (loaded && !options.force) {\n if (options.json) {\n console.log(JSON.stringify({ ok: true, result: 'already-installed' }));\n } else {\n console.log('ℹ️ Service already installed. Use --force to reinstall.');\n }\n return;\n }\n\n // Uninstall first if force\n if (loaded && options.force) {\n try {\n await service.uninstall({ env: process.env });\n } catch {\n // Best-effort\n }\n }\n\n // Build install args and install\n const installArgs = buildGatewayInstallArgs({ port, bind, token });\n installArgs.stdout = process.stdout;\n\n try {\n await service.install(installArgs);\n\n if (options.json) {\n console.log(JSON.stringify({ ok: true, result: 'installed', label: service.label, port }));\n } else {\n console.log('');\n console.log(`✅ Gateway service installed`);\n console.log(` Service: ${service.label}`);\n console.log(` Port: ${port}`);\n console.log('');\n console.log('💡 The service will start automatically on login.');\n console.log(' Use `xopc gateway status` to verify.');\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if (options.json) {\n console.log(JSON.stringify({ ok: false, error: message }));\n } else {\n console.error(`❌ Failed to install service: ${message}`);\n }\n process.exit(1);\n }\n });\n}\n\n/**\n * Create service uninstall subcommand\n */\nexport function createUninstallCommand(): Command {\n return new Command('uninstall')\n .description('Uninstall gateway OS service')\n .option('--json', 'Output JSON')\n .action(async (options) => {\n const { executeDaemonUninstall } = await import('./lifecycle-core.js');\n await executeDaemonUninstall(options);\n });\n}\n\n/**\n * Create service start subcommand - starts via daemon service manager\n */\nexport function createServiceStartCommand(): Command {\n return new Command('start')\n .description('Start gateway via OS service manager')\n .option('--json', 'Output JSON')\n .action(async (options) => {\n const [{ resolveGatewayService, startGatewayService, isDaemonAvailableAsync }] =\n await Promise.all([import('../../../daemon/service.js')]);\n\n const available = await isDaemonAvailableAsync();\n if (!available) {\n console.error('❌ Daemon not available on this platform');\n process.exit(1);\n }\n\n const service = await resolveGatewayService();\n const result = await startGatewayService({ service });\n\n if (options.json) {\n console.log(JSON.stringify({ ok: result.outcome === 'started', outcome: result.outcome }));\n return;\n }\n\n switch (result.outcome) {\n case 'started':\n console.log('✅ Gateway service started');\n break;\n case 'missing-install':\n console.error('❌ Service not installed. Run: xopc gateway service install');\n process.exit(1);\n break;\n case 'repair-required':\n console.error('⚠️ Service needs repair:');\n for (const issue of result.issues || []) {\n console.error(` - ${issue.message}`);\n }\n console.log('💡 Run: xopc gateway service install --force');\n process.exit(1);\n break;\n default:\n console.log(`ℹ️ Service start outcome: ${result.outcome}`);\n }\n });\n}\n\n/**\n * Create service status subcommand\n */\nexport function createServiceStatusCommand(): Command {\n return new Command('service-status')\n .description('Show OS service status')\n .option('--json', 'Output JSON')\n .action(async (options) => {\n const [{ resolveGatewayService, isDaemonAvailableAsync, getPlatformName }] =\n await Promise.all([import('../../../daemon/service.js')]);\n\n const available = await isDaemonAvailableAsync();\n if (!available) {\n if (options.json) {\n console.log(JSON.stringify({ available: false, platform: process.platform }));\n } else {\n console.log(`ℹ️ Daemon not available on ${getPlatformName()}`);\n }\n return;\n }\n\n const service = await resolveGatewayService();\n const [loaded, runtime, command] = await Promise.all([\n service.isLoaded({ env: process.env }),\n service.readRuntime(),\n service.readCommand(),\n ]);\n\n if (options.json) {\n console.log(JSON.stringify({ available: true, loaded, runtime, command, label: service.label }, null, 2));\n return;\n }\n\n console.log('📊 Gateway Service Status');\n console.log('');\n console.log(` Platform: ${getPlatformName()}`);\n console.log(` Service: ${loaded ? service.loadedText : service.notLoadedText}`);\n console.log(` Runtime: ${runtime.status}${runtime.pid ? ` (pid ${runtime.pid})` : ''}`);\n\n if (command) {\n const portMatch = command.programArguments.join(' ').match(/--port\\s+(\\d+)/);\n if (portMatch) {\n console.log(` Port: ${portMatch[1]}`);\n }\n const version = command.environment?.XOPC_SERVICE_VERSION;\n if (version) {\n console.log(` Version: ${version}`);\n }\n }\n\n if (!loaded) {\n console.log('');\n console.log('💡 Install with: xopc gateway service install');\n }\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"service.js","names":[],"sources":["../../../../../src/cli/commands/gateway/service.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { resolveConfigPath } from '../../../config/paths.js';\nimport { getContextWithOpts } from '../../context.js';\nimport { createRestartCommand } from './restart.js';\nimport { createStopCommand } from './stop.js';\n\n/**\n * Create service install subcommand - actually installs the OS service\n */\nexport function createInstallCommand(): Command {\n return new Command('install')\n .description('Install gateway as OS service (LaunchAgent / systemd / Task)')\n .option('--port <port>', 'Gateway port')\n .option('--token <token>', 'Gateway auth token')\n .option('--force', 'Force reinstall if already installed')\n .option('--json', 'Output JSON')\n .action(async (options) => {\n const ctx = getContextWithOpts();\n const configPath = ctx.configPath || resolveConfigPath();\n\n const [{ loadConfig }, { resolveGatewayService, isDaemonAvailableAsync, getPlatformName }, { buildGatewayInstallArgs }] =\n await Promise.all([\n import('../../../config/index.js'),\n import('../../../daemon/service.js'),\n import('../../../daemon/install-plan.js'),\n ]);\n\n const config = loadConfig(configPath);\n const port = options.port ? parseInt(options.port, 10) : (config?.gateway?.port || 18790);\n const bind = config?.gateway?.bind ?? 'loopback';\n const token = options.token || config?.gateway?.auth?.token;\n\n const available = await isDaemonAvailableAsync();\n if (!available) {\n if (options.json) {\n console.log(JSON.stringify({ ok: false, error: 'Daemon not available' }));\n } else {\n console.error(`❌ OS service not available on ${getPlatformName()}`);\n }\n process.exit(1);\n }\n\n const service = await resolveGatewayService();\n\n // Check if already installed\n const loaded = await service.isLoaded({ env: process.env });\n if (loaded && !options.force) {\n if (options.json) {\n console.log(JSON.stringify({ ok: true, result: 'already-installed' }));\n } else {\n console.log('ℹ️ Service already installed. Use --force to reinstall.');\n }\n return;\n }\n\n // Uninstall first if force\n if (loaded && options.force) {\n try {\n await service.uninstall({ env: process.env });\n } catch {\n // Best-effort\n }\n }\n\n // Build install args and install\n const installArgs = buildGatewayInstallArgs({ port, bind, token });\n installArgs.stdout = process.stdout;\n\n try {\n await service.install(installArgs);\n\n if (options.json) {\n console.log(JSON.stringify({ ok: true, result: 'installed', label: service.label, port }));\n } else {\n console.log('');\n console.log(`✅ Gateway service installed`);\n console.log(` Service: ${service.label}`);\n console.log(` Port: ${port}`);\n console.log('');\n console.log('💡 The service will start automatically on login.');\n console.log(' Use `xopc gateway status` to verify.');\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if (options.json) {\n console.log(JSON.stringify({ ok: false, error: message }));\n } else {\n console.error(`❌ Failed to install service: ${message}`);\n }\n process.exit(1);\n }\n });\n}\n\n/**\n * Create service uninstall subcommand\n */\nexport function createUninstallCommand(): Command {\n return new Command('uninstall')\n .description('Uninstall gateway OS service')\n .option('--json', 'Output JSON')\n .action(async (options) => {\n const { executeDaemonUninstall } = await import('./lifecycle-core.js');\n await executeDaemonUninstall(options);\n });\n}\n\n/**\n * Create service start subcommand - starts via daemon service manager\n */\nexport function createServiceStartCommand(): Command {\n return new Command('start')\n .description('Start gateway via OS service manager')\n .option('--json', 'Output JSON')\n .action(async (options) => {\n const [{ resolveGatewayService, startGatewayService, isDaemonAvailableAsync }] =\n await Promise.all([import('../../../daemon/service.js')]);\n\n const available = await isDaemonAvailableAsync();\n if (!available) {\n console.error('❌ Daemon not available on this platform');\n process.exit(1);\n }\n\n const service = await resolveGatewayService();\n const result = await startGatewayService({ service });\n\n if (options.json) {\n console.log(JSON.stringify({ ok: result.outcome === 'started', outcome: result.outcome }));\n return;\n }\n\n switch (result.outcome) {\n case 'started':\n console.log('✅ Gateway service started');\n break;\n case 'missing-install':\n console.error('❌ Service not installed. Run: xopc gateway service install');\n process.exit(1);\n break;\n case 'repair-required':\n console.error('⚠️ Service needs repair:');\n for (const issue of result.issues || []) {\n console.error(` - ${issue.message}`);\n }\n console.log('💡 Run: xopc gateway service install --force');\n process.exit(1);\n break;\n default:\n console.log(`ℹ️ Service start outcome: ${result.outcome}`);\n }\n });\n}\n\n/**\n * Create service status subcommand\n */\nexport function createServiceStatusCommand(): Command {\n return new Command('status')\n .description('Show OS service status')\n .option('--json', 'Output JSON')\n .action(async (options) => {\n const [{ resolveGatewayService, isDaemonAvailableAsync, getPlatformName }] =\n await Promise.all([import('../../../daemon/service.js')]);\n\n const available = await isDaemonAvailableAsync();\n if (!available) {\n if (options.json) {\n console.log(JSON.stringify({ available: false, platform: process.platform }));\n } else {\n console.log(`ℹ️ Daemon not available on ${getPlatformName()}`);\n }\n return;\n }\n\n const service = await resolveGatewayService();\n const [loaded, runtime, command] = await Promise.all([\n service.isLoaded({ env: process.env }),\n service.readRuntime(),\n service.readCommand(),\n ]);\n\n if (options.json) {\n console.log(JSON.stringify({ available: true, loaded, runtime, command, label: service.label }, null, 2));\n return;\n }\n\n console.log('📊 Gateway Service Status');\n console.log('');\n console.log(` Platform: ${getPlatformName()}`);\n console.log(` Service: ${loaded ? service.loadedText : service.notLoadedText}`);\n console.log(` Runtime: ${runtime.status}${runtime.pid ? ` (pid ${runtime.pid})` : ''}`);\n\n if (command) {\n const portMatch = command.programArguments.join(' ').match(/--port\\s+(\\d+)/);\n if (portMatch) {\n console.log(` Port: ${portMatch[1]}`);\n }\n const version = command.environment?.XOPC_SERVICE_VERSION;\n if (version) {\n console.log(` Version: ${version}`);\n }\n }\n\n if (!loaded) {\n console.log('');\n console.log('💡 Install with: xopc gateway service install');\n }\n });\n}\n\n/**\n * Gateway OS service command group (`xopc gateway service …`).\n */\nexport function createServiceCommand(): Command {\n const cmd = new Command('service').description(\n 'Manage gateway OS service (LaunchAgent / systemd / Task)',\n );\n cmd.addCommand(createInstallCommand());\n cmd.addCommand(createUninstallCommand());\n cmd.addCommand(createServiceStartCommand());\n cmd.addCommand(createServiceStatusCommand());\n cmd.addCommand(createStopCommand());\n cmd.addCommand(createRestartCommand());\n return cmd;\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { init_paths, resolveConfigPath } from "../../../config/paths.js";
|
|
2
2
|
import { loadConfig } from "../../../config/loader.js";
|
|
3
|
-
import "../../../config/index.js";
|
|
4
3
|
import { resolveGatewayLaunchAgentLabel, resolveGatewaySystemdServiceName, resolveGatewayWindowsTaskName } from "../../../daemon/constants.js";
|
|
4
|
+
import "../../../config/index.js";
|
|
5
5
|
//#region src/cli/commands/gateway/shared.ts
|
|
6
6
|
init_paths();
|
|
7
7
|
function parsePortFromArgs(programArguments) {
|
|
@@ -10,10 +10,7 @@ const GATEWAY_SUBCOMMAND_LOADERS = {
|
|
|
10
10
|
stop: async () => (await import("./stop.js")).createStopCommand(),
|
|
11
11
|
restart: async () => (await import("./restart.js")).createRestartCommand(),
|
|
12
12
|
logs: async () => (await import("./logs.js")).createLogsCommand(),
|
|
13
|
-
|
|
14
|
-
uninstall: async () => (await import("./service.js")).createUninstallCommand(),
|
|
15
|
-
start: async () => (await import("./service.js")).createServiceStartCommand(),
|
|
16
|
-
"service-status": async () => (await import("./service.js")).createServiceStatusCommand()
|
|
13
|
+
service: async () => (await import("./service.js")).createServiceCommand()
|
|
17
14
|
};
|
|
18
15
|
async function attachAllGatewaySubcommands(cmd, ctx) {
|
|
19
16
|
for (const loader of Object.values(GATEWAY_SUBCOMMAND_LOADERS)) cmd.addCommand(await loader());
|