@gajae-code/coding-agent 0.10.2 → 0.11.1
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/CHANGELOG.md +58 -2
- package/dist/types/append-only-mode.d.ts +1 -1
- package/dist/types/async/job-manager.d.ts +46 -7
- package/dist/types/cli/args.d.ts +4 -5
- package/dist/types/cli/daemon-cli.d.ts +12 -1
- package/dist/types/cli/notify-cli.d.ts +21 -1
- package/dist/types/cli.d.ts +3 -0
- package/dist/types/commands/daemon.d.ts +39 -0
- package/dist/types/commands/launch.d.ts +3 -0
- package/dist/types/commands/notify.d.ts +28 -1
- package/dist/types/commands/sdk.d.ts +33 -0
- package/dist/types/config/atomic-yaml-patch.d.ts +85 -0
- package/dist/types/config/model-profile-activation.d.ts +35 -15
- package/dist/types/config/model-profiles.d.ts +11 -5
- package/dist/types/config/model-registry.d.ts +3 -3
- package/dist/types/config/model-resolver.d.ts +39 -6
- package/dist/types/config/model-selector-value.d.ts +17 -0
- package/dist/types/config/models-config-schema.d.ts +10 -6
- package/dist/types/config/settings-schema.d.ts +133 -6
- package/dist/types/config/settings.d.ts +63 -35
- package/dist/types/coordinator-mcp/model-preset.d.ts +7 -6
- package/dist/types/coordinator-mcp/server.d.ts +6 -49
- package/dist/types/daemon/builtin.d.ts +6 -5
- package/dist/types/daemon/control-types.d.ts +1 -1
- package/dist/types/discovery/mcp-json.d.ts +12 -1
- package/dist/types/extensibility/custom-tools/types.d.ts +1 -1
- package/dist/types/extensibility/extensions/compact-handler.d.ts +4 -2
- package/dist/types/extensibility/extensions/get-commands-handler.d.ts +2 -2
- package/dist/types/extensibility/extensions/loader.d.ts +10 -1
- package/dist/types/extensibility/extensions/runner.d.ts +3 -3
- package/dist/types/extensibility/extensions/types.d.ts +141 -16
- package/dist/types/extensibility/hooks/types.d.ts +1 -1
- package/dist/types/gjc-runtime/launch-tmux.d.ts +3 -2
- package/dist/types/gjc-runtime/psmux-detect.d.ts +3 -0
- package/dist/types/gjc-runtime/session-state-sidecar.d.ts +3 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +3 -4
- package/dist/types/gjc-runtime/tmux-owner-isolation-cli.d.ts +13 -0
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +4 -1
- package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +11 -0
- package/dist/types/gjc-runtime/windows-powershell-command.d.ts +9 -0
- package/dist/types/harness-control-plane/operate.d.ts +5 -5
- package/dist/types/harness-control-plane/owner.d.ts +18 -4
- package/dist/types/harness-control-plane/receipts.d.ts +0 -1
- package/dist/types/harness-control-plane/sdk-transport.d.ts +43 -0
- package/dist/types/harness-control-plane/session-transport.d.ts +48 -0
- package/dist/types/harness-control-plane/types.d.ts +3 -4
- package/dist/types/lsp/index.d.ts +1 -1
- package/dist/types/main.d.ts +32 -38
- package/dist/types/modes/acp/acp-agent.d.ts +224 -53
- package/dist/types/modes/acp/acp-client-bridge.d.ts +1 -0
- package/dist/types/modes/acp/acp-mode.d.ts +6 -15
- package/dist/types/modes/acp/permission-mode.d.ts +4 -0
- package/dist/types/modes/acp/startup-options.d.ts +6 -0
- package/dist/types/modes/components/agent-dashboard.d.ts +3 -0
- package/dist/types/modes/components/model-selector.d.ts +1 -0
- package/dist/types/modes/components/notifications-settings-editor.d.ts +135 -0
- package/dist/types/modes/components/settings-selector.d.ts +6 -4
- package/dist/types/modes/components/welcome.d.ts +1 -1
- package/dist/types/modes/controllers/command-controller.d.ts +2 -2
- package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +35 -1
- package/dist/types/modes/index.d.ts +0 -4
- package/dist/types/modes/interactive-mode.d.ts +5 -2
- package/dist/types/modes/runtime-init.d.ts +2 -2
- package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +6 -9
- package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -6
- package/dist/types/modes/shared/agent-wire/event-contract.d.ts +6 -6
- package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +4 -9
- package/dist/types/modes/shared/agent-wire/event-observation.d.ts +1 -1
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +170 -30
- package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +7 -7
- package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +105 -0
- package/dist/types/modes/types.d.ts +7 -2
- package/dist/types/runtime-mcp/client.d.ts +2 -0
- package/dist/types/runtime-mcp/config.d.ts +5 -1
- package/dist/types/runtime-mcp/manager.d.ts +8 -1
- package/dist/types/runtime-mcp/types.d.ts +4 -0
- package/dist/types/sdk/acp/adapter.d.ts +67 -0
- package/dist/types/sdk/acp/index.d.ts +2 -0
- package/dist/types/sdk/broker/broker.d.ts +53 -0
- package/dist/types/sdk/broker/discovery.d.ts +30 -0
- package/dist/types/sdk/broker/ensure.d.ts +42 -0
- package/dist/types/sdk/broker/identity.d.ts +3 -0
- package/dist/types/sdk/broker/index.d.ts +8 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +95 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +85 -0
- package/dist/types/sdk/broker/process-incarnation.d.ts +14 -0
- package/dist/types/sdk/broker/runtime.d.ts +33 -0
- package/dist/types/sdk/broker/session-index.d.ts +57 -0
- package/dist/types/sdk/broker/state-version.d.ts +8 -0
- package/dist/types/sdk/broker/transport.d.ts +9 -0
- package/dist/types/sdk/bus/chat-command-policy.d.ts +49 -0
- package/dist/types/sdk/bus/chat-daemon-cli.d.ts +21 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +111 -0
- package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +77 -0
- package/dist/types/sdk/bus/chat-effect-journal.d.ts +84 -0
- package/dist/types/{notifications → sdk/bus}/config-commands.d.ts +7 -2
- package/dist/types/sdk/bus/config.d.ts +274 -0
- package/dist/types/sdk/bus/conversation-store.d.ts +72 -0
- package/dist/types/sdk/bus/discord-conversation.d.ts +58 -0
- package/dist/types/sdk/bus/discord-daemon.d.ts +50 -0
- package/dist/types/sdk/bus/discord-live-provider.d.ts +70 -0
- package/dist/types/sdk/bus/discord-provider.d.ts +85 -0
- package/dist/types/{notifications → sdk/bus}/html-format.d.ts +2 -2
- package/dist/types/{notifications → sdk/bus}/index.d.ts +113 -13
- package/dist/types/{notifications → sdk/bus}/lifecycle-control-runtime.d.ts +4 -2
- package/dist/types/{notifications → sdk/bus}/lifecycle-orchestrator.d.ts +18 -21
- package/dist/types/{notifications → sdk/bus}/managed-daemon.d.ts +1 -1
- package/dist/types/sdk/bus/native-runtime-compatibility.d.ts +13 -0
- package/dist/types/sdk/bus/notification-orchestration.d.ts +170 -0
- package/dist/types/{notifications → sdk/bus}/notification-service.d.ts +7 -1
- package/dist/types/sdk/bus/session-control.d.ts +83 -0
- package/dist/types/sdk/bus/slack-conversation.d.ts +56 -0
- package/dist/types/sdk/bus/slack-daemon.d.ts +60 -0
- package/dist/types/sdk/bus/slack-live-provider.d.ts +59 -0
- package/dist/types/sdk/bus/slack-provider.d.ts +55 -0
- package/dist/types/{notifications → sdk/bus}/telegram-cli.d.ts +4 -4
- package/dist/types/{notifications → sdk/bus}/telegram-daemon-cli.d.ts +14 -5
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -0
- package/dist/types/{notifications → sdk/bus}/telegram-daemon-control.d.ts +2 -2
- package/dist/types/{notifications → sdk/bus}/telegram-daemon.d.ts +78 -17
- package/dist/types/{notifications → sdk/bus}/telegram-reference.d.ts +2 -2
- package/dist/types/sdk/bus/telegram-setup.d.ts +128 -0
- package/dist/types/{notifications → sdk/bus}/topic-registry.d.ts +11 -0
- package/dist/types/sdk/cli/index.d.ts +1 -0
- package/dist/types/sdk/cli/session-cli.d.ts +19 -0
- package/dist/types/sdk/client/client.d.ts +1 -0
- package/dist/types/sdk/client/discovery.d.ts +27 -0
- package/dist/types/sdk/client/index.d.ts +2 -0
- package/dist/types/sdk/host/control/dispatch.d.ts +34 -0
- package/dist/types/sdk/host/control/index.d.ts +2 -0
- package/dist/types/sdk/host/control/operations.d.ts +65 -0
- package/dist/types/sdk/host/events.d.ts +35 -0
- package/dist/types/sdk/host/host.d.ts +35 -0
- package/dist/types/sdk/host/index.d.ts +4 -0
- package/dist/types/sdk/host/query/cursor.d.ts +62 -0
- package/dist/types/sdk/host/query/handlers.d.ts +70 -0
- package/dist/types/sdk/host/query/index.d.ts +3 -0
- package/dist/types/sdk/host/query/revision-store.d.ts +60 -0
- package/dist/types/sdk/host/reverse-leases.d.ts +45 -0
- package/dist/types/sdk/host/types.d.ts +32 -0
- package/dist/types/sdk/index.d.ts +6 -0
- package/dist/types/sdk/lifecycle-session.d.ts +14 -0
- package/dist/types/sdk/mcp/index.d.ts +1 -0
- package/dist/types/sdk/mcp/server.d.ts +37 -0
- package/dist/types/sdk/models.d.ts +44 -0
- package/dist/types/sdk/protocol/adapter-validation.d.ts +14 -0
- package/dist/types/sdk/protocol/operation-registry.d.ts +24 -0
- package/dist/types/{sdk.d.ts → sdk/session.d.ts} +44 -38
- package/dist/types/sdk/startup-capability.d.ts +50 -0
- package/dist/types/session/agent-session.d.ts +114 -21
- package/dist/types/session/default-model-selection.d.ts +25 -0
- package/dist/types/session/fallback-chain-controller.d.ts +52 -0
- package/dist/types/session/session-manager.d.ts +58 -1
- package/dist/types/setup/credential-auto-import.d.ts +36 -6
- package/dist/types/tools/ask-answer-registry.d.ts +1 -1
- package/dist/types/tools/browser/benchmark/detector-report.d.ts +63 -0
- package/dist/types/tools/browser/benchmark/run-suite.d.ts +18 -0
- package/dist/types/tools/browser/launch.d.ts +22 -0
- package/dist/types/tools/browser/profile-discovery.d.ts +31 -0
- package/dist/types/tools/browser/profile-posture.d.ts +37 -0
- package/dist/types/tools/browser/profile-reuse.d.ts +39 -0
- package/dist/types/tools/browser/profile-warmup.d.ts +39 -0
- package/dist/types/tools/browser/registry.d.ts +19 -0
- package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
- package/dist/types/tools/index.d.ts +8 -8
- package/dist/types/tools/subagent-render.d.ts +1 -0
- package/dist/types/tools/subagent.d.ts +6 -1
- package/package.json +34 -13
- package/scripts/build-sdk-package-smoke.ts +99 -0
- package/scripts/capture-notifications-settings-showcase.ts +435 -0
- package/scripts/compile-args.ts +4 -2
- package/scripts/g005-daemon-smoke.ts +4 -5
- package/scripts/g011-daemon-path-smoke.ts +5 -5
- package/scripts/generate-sdk-adapter-parity-manifest.ts +163 -0
- package/scripts/generate-sdk-operation-inventory.ts +867 -0
- package/scripts/generate-telegram-baseline-manifest.ts +128 -0
- package/scripts/manifest-schema.ts +124 -0
- package/scripts/run-test-manifest.ts +153 -0
- package/scripts/run-threat-model-check.ts +157 -0
- package/scripts/verify-gjc-sdk-canonicalization.ts +3467 -0
- package/scripts/verify-gjc-sdk-rename.ts +90 -0
- package/src/append-only-mode.ts +1 -1
- package/src/async/job-manager.ts +406 -63
- package/src/cli/args.ts +43 -12
- package/src/cli/auth-gateway-cli.ts +2 -2
- package/src/cli/config-cli.ts +2 -1
- package/src/cli/daemon-cli.ts +63 -14
- package/src/cli/list-models.ts +1 -1
- package/src/cli/notify-cli.ts +288 -286
- package/src/cli.ts +21 -2
- package/src/commands/daemon.ts +50 -6
- package/src/commands/harness.ts +93 -36
- package/src/commands/launch.ts +5 -2
- package/src/commands/mcp-serve.ts +19 -12
- package/src/commands/notify.ts +36 -3
- package/src/commands/sdk.ts +426 -0
- package/src/commit/agentic/agent.ts +1 -0
- package/src/config/atomic-yaml-patch.ts +423 -0
- package/src/config/model-profile-activation.ts +240 -89
- package/src/config/model-profiles.ts +18 -15
- package/src/config/model-registry.ts +51 -26
- package/src/config/model-resolver.ts +138 -51
- package/src/config/model-selector-value.ts +50 -0
- package/src/config/models-config-schema.ts +14 -21
- package/src/config/settings-schema.ts +128 -10
- package/src/config/settings.ts +1120 -158
- package/src/coordinator-mcp/model-preset.ts +74 -20
- package/src/coordinator-mcp/server.ts +1597 -3052
- package/src/daemon/builtin.ts +8 -5
- package/src/daemon/control-types.ts +1 -1
- package/src/defaults/gjc/skills/team/SKILL.md +4 -4
- package/src/discovery/mcp-json.ts +327 -20
- package/src/extensibility/custom-tools/types.ts +1 -1
- package/src/extensibility/extensions/compact-handler.ts +3 -3
- package/src/extensibility/extensions/get-commands-handler.ts +2 -2
- package/src/extensibility/extensions/loader.ts +69 -5
- package/src/extensibility/extensions/runner.ts +112 -4
- package/src/extensibility/extensions/types.ts +176 -17
- package/src/extensibility/hooks/types.ts +1 -1
- package/src/gjc-runtime/launch-tmux.ts +170 -86
- package/src/gjc-runtime/psmux-detect.ts +82 -4
- package/src/gjc-runtime/session-state-sidecar.ts +41 -31
- package/src/gjc-runtime/team-runtime.ts +54 -35
- package/src/gjc-runtime/tmux-owner-isolation-cli.ts +53 -17
- package/src/gjc-runtime/tmux-owner-isolation.ts +1 -1
- package/src/gjc-runtime/tmux-sessions.ts +19 -13
- package/src/gjc-runtime/ultragoal-guard.ts +108 -14
- package/src/gjc-runtime/ultragoal-receipt-freshness.ts +102 -1
- package/src/gjc-runtime/ultragoal-runtime.ts +227 -11
- package/src/gjc-runtime/windows-powershell-command.ts +58 -0
- package/src/harness-control-plane/operate.ts +9 -9
- package/src/harness-control-plane/owner.ts +283 -39
- package/src/harness-control-plane/receipts.ts +0 -1
- package/src/harness-control-plane/sdk-transport.ts +395 -0
- package/src/harness-control-plane/session-transport.ts +94 -0
- package/src/harness-control-plane/types.ts +1 -1
- package/src/internal-urls/docs-index.generated.ts +34 -35
- package/src/lsp/client.ts +42 -6
- package/src/lsp/index.ts +2 -2
- package/src/main.ts +299 -204
- package/src/modes/DESIGN.md +258 -0
- package/src/modes/acp/acp-agent.ts +1228 -2612
- package/src/modes/acp/acp-client-bridge.ts +2 -20
- package/src/modes/acp/acp-event-mapper.ts +18 -2
- package/src/modes/acp/acp-mode.ts +8 -36
- package/src/modes/acp/permission-mode.ts +25 -0
- package/src/modes/acp/startup-options.ts +6 -0
- package/src/modes/components/agent-dashboard.ts +37 -17
- package/src/modes/components/model-selector.ts +93 -35
- package/src/modes/components/notifications-settings-editor.ts +1379 -0
- package/src/modes/components/settings-selector.ts +60 -11
- package/src/modes/components/welcome.ts +4 -4
- package/src/modes/controllers/command-controller.ts +10 -17
- package/src/modes/controllers/event-controller.ts +11 -16
- package/src/modes/controllers/extension-ui-controller.ts +396 -28
- package/src/modes/controllers/selector-controller.ts +674 -36
- package/src/modes/index.ts +0 -22
- package/src/modes/interactive-mode.ts +87 -36
- package/src/modes/runtime-init.ts +298 -6
- package/src/modes/shared/agent-wire/approval-gate.ts +9 -11
- package/src/modes/shared/agent-wire/deep-interview-gate.ts +10 -11
- package/src/modes/shared/agent-wire/event-contract.ts +7 -8
- package/src/modes/shared/agent-wire/event-envelope.ts +9 -17
- package/src/modes/shared/agent-wire/event-observation.ts +16 -7
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +1258 -87
- package/src/modes/shared/agent-wire/workflow-gate-schema.ts +15 -15
- package/src/modes/shared/agent-wire/workflow-gate-types.ts +113 -0
- package/src/modes/types.ts +7 -2
- package/src/runtime-mcp/client.ts +94 -19
- package/src/runtime-mcp/config.ts +27 -15
- package/src/runtime-mcp/manager.ts +343 -105
- package/src/runtime-mcp/oauth-flow.ts +42 -12
- package/src/runtime-mcp/transports/http.ts +49 -19
- package/src/runtime-mcp/transports/stdio.ts +47 -28
- package/src/runtime-mcp/types.ts +10 -0
- package/src/sdk/acp/adapter.ts +418 -0
- package/src/sdk/acp/index.ts +2 -0
- package/src/sdk/broker/broker.ts +642 -0
- package/src/sdk/broker/discovery.ts +113 -0
- package/src/sdk/broker/ensure.ts +307 -0
- package/src/sdk/broker/identity.ts +42 -0
- package/src/sdk/broker/index.ts +8 -0
- package/src/sdk/broker/internal-source-marker-2178.txt +1 -0
- package/src/sdk/broker/internal-source.bunfig.toml +1 -0
- package/src/sdk/broker/lifecycle-ledger.ts +286 -0
- package/src/sdk/broker/lifecycle.ts +2157 -0
- package/src/sdk/broker/process-incarnation.ts +159 -0
- package/src/sdk/broker/runtime.ts +164 -0
- package/src/sdk/broker/session-index.ts +318 -0
- package/src/sdk/broker/state-version.ts +23 -0
- package/src/sdk/broker/transport.ts +125 -0
- package/src/sdk/bus/chat-command-policy.ts +107 -0
- package/src/sdk/bus/chat-daemon-cli.ts +214 -0
- package/src/sdk/bus/chat-daemon-control.ts +713 -0
- package/src/sdk/bus/chat-daemon-runtime.ts +526 -0
- package/src/sdk/bus/chat-effect-journal.ts +355 -0
- package/src/{notifications → sdk/bus}/config-commands.ts +39 -10
- package/src/sdk/bus/config.ts +433 -0
- package/src/sdk/bus/conversation-store.ts +391 -0
- package/src/sdk/bus/discord-conversation.ts +85 -0
- package/src/sdk/bus/discord-daemon.ts +2292 -0
- package/src/sdk/bus/discord-live-provider.ts +521 -0
- package/src/sdk/bus/discord-provider.ts +56 -0
- package/src/{notifications → sdk/bus}/html-format.ts +2 -2
- package/src/sdk/bus/index.ts +3979 -0
- package/src/{notifications → sdk/bus}/lifecycle-commands.ts +2 -0
- package/src/{notifications → sdk/bus}/lifecycle-control-runtime.ts +225 -196
- package/src/{notifications → sdk/bus}/lifecycle-orchestrator.ts +161 -74
- package/src/{notifications → sdk/bus}/managed-daemon.ts +2 -2
- package/src/sdk/bus/native-runtime-compatibility.ts +42 -0
- package/src/sdk/bus/natives-augment.d.ts +38 -0
- package/src/sdk/bus/notification-orchestration.ts +535 -0
- package/src/{notifications → sdk/bus}/notification-service.ts +106 -12
- package/src/sdk/bus/session-control.ts +333 -0
- package/src/sdk/bus/slack-conversation.ts +74 -0
- package/src/sdk/bus/slack-daemon.ts +2144 -0
- package/src/sdk/bus/slack-live-provider.ts +380 -0
- package/src/sdk/bus/slack-provider.ts +76 -0
- package/src/{notifications → sdk/bus}/telegram-cli.ts +8 -8
- package/src/sdk/bus/telegram-daemon-cli.ts +330 -0
- package/src/sdk/bus/telegram-daemon-contract.ts +14 -0
- package/src/{notifications → sdk/bus}/telegram-daemon-control.ts +4 -4
- package/src/{notifications → sdk/bus}/telegram-daemon.ts +603 -63
- package/src/{notifications → sdk/bus}/telegram-reference.ts +2 -2
- package/src/sdk/bus/telegram-setup.ts +663 -0
- package/src/{notifications → sdk/bus}/topic-registry.ts +32 -0
- package/src/sdk/cli/index.ts +1 -0
- package/src/sdk/cli/session-cli.ts +275 -0
- package/src/sdk/client/client.ts +1 -0
- package/src/sdk/client/discovery.ts +108 -0
- package/src/sdk/client/index.ts +2 -0
- package/src/sdk/host/control/dispatch.ts +367 -0
- package/src/sdk/host/control/index.ts +10 -0
- package/src/sdk/host/control/operations.ts +63 -0
- package/src/sdk/host/events.ts +91 -0
- package/src/sdk/host/host.ts +296 -0
- package/src/sdk/host/index.ts +4 -0
- package/src/sdk/host/query/cursor.ts +189 -0
- package/src/sdk/host/query/handlers.ts +533 -0
- package/src/sdk/host/query/index.ts +3 -0
- package/src/sdk/host/query/revision-store.ts +1126 -0
- package/src/sdk/host/reverse-leases.ts +325 -0
- package/src/sdk/host/types.ts +29 -0
- package/src/sdk/index.ts +13 -0
- package/src/sdk/lifecycle-session.ts +39 -0
- package/src/sdk/mcp/index.ts +1 -0
- package/src/sdk/mcp/server.ts +332 -0
- package/src/sdk/models.ts +168 -0
- package/src/sdk/protocol/adapter-validation.ts +48 -0
- package/src/sdk/protocol/operation-inventory.generated.json +5654 -0
- package/src/sdk/protocol/operation-registry.ts +312 -0
- package/src/{sdk.ts → sdk/session.ts} +339 -212
- package/src/sdk/startup-capability.ts +189 -0
- package/src/session/agent-session.ts +2650 -944
- package/src/session/default-model-selection.ts +93 -0
- package/src/session/fallback-chain-controller.ts +136 -0
- package/src/session/session-manager.ts +438 -11
- package/src/session/session-storage.ts +8 -1
- package/src/setup/credential-auto-import.ts +290 -35
- package/src/setup/hermes/templates/operator-instructions.v1.md +3 -5
- package/src/slash-commands/builtin-registry.ts +2 -1
- package/src/task/executor.ts +62 -13
- package/src/task/index.ts +26 -16
- package/src/tools/ask-answer-registry.ts +1 -1
- package/src/tools/ask.ts +13 -8
- package/src/tools/browser/STEALTH-THIRD-PARTY-NOTICES.md +26 -0
- package/src/tools/browser/benchmark/detector-report.ts +157 -0
- package/src/tools/browser/benchmark/run-suite.ts +39 -0
- package/src/tools/browser/launch.ts +124 -19
- package/src/tools/browser/profile-discovery.ts +63 -0
- package/src/tools/browser/profile-posture.ts +59 -0
- package/src/tools/browser/profile-reuse.ts +102 -0
- package/src/tools/browser/profile-warmup.ts +109 -0
- package/src/tools/browser/registry.ts +87 -11
- package/src/tools/browser/tab-protocol.ts +1 -0
- package/src/tools/browser/tab-supervisor.ts +1 -0
- package/src/tools/browser/tab-worker.ts +1 -1
- package/src/tools/browser.ts +6 -0
- package/src/tools/index.ts +8 -8
- package/src/tools/puppeteer/14_stealth_permissions.txt +57 -0
- package/src/tools/puppeteer/15_stealth_webrtc.txt +60 -0
- package/src/tools/subagent-render.ts +19 -8
- package/src/tools/subagent.ts +84 -32
- package/src/tools/telegram-send.ts +2 -2
- package/vendor/insane-search/MANIFEST.json +2 -1
- package/vendor/insane-search/engine/bias_check.py +4 -1
- package/vendor/insane-search/engine/phase0.py +26 -1
- package/dist/types/harness-control-plane/rpc-adapter.d.ts +0 -69
- package/dist/types/modes/bridge/auth.d.ts +0 -12
- package/dist/types/modes/bridge/bridge-client-bridge.d.ts +0 -9
- package/dist/types/modes/bridge/bridge-mode.d.ts +0 -47
- package/dist/types/modes/bridge/bridge-ui-context.d.ts +0 -88
- package/dist/types/modes/bridge/event-stream.d.ts +0 -8
- package/dist/types/modes/rpc/host-tools.d.ts +0 -1
- package/dist/types/modes/rpc/host-uris.d.ts +0 -1
- package/dist/types/modes/rpc/rpc-client.d.ts +0 -299
- package/dist/types/modes/rpc/rpc-mode.d.ts +0 -86
- package/dist/types/modes/rpc/rpc-socket-security.d.ts +0 -10
- package/dist/types/modes/rpc/rpc-types.d.ts +0 -810
- package/dist/types/modes/shared/agent-wire/command-contract.d.ts +0 -18
- package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +0 -37
- package/dist/types/modes/shared/agent-wire/command-validation.d.ts +0 -2
- package/dist/types/modes/shared/agent-wire/handshake.d.ts +0 -56
- package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +0 -16
- package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +0 -17
- package/dist/types/modes/shared/agent-wire/protocol.d.ts +0 -25
- package/dist/types/modes/shared/agent-wire/responses.d.ts +0 -4
- package/dist/types/modes/shared/agent-wire/scopes.d.ts +0 -18
- package/dist/types/modes/shared/agent-wire/session-registry.d.ts +0 -25
- package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +0 -42
- package/dist/types/modes/shared/agent-wire/ui-result.d.ts +0 -27
- package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +0 -29
- package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +0 -68
- package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +0 -166
- package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +0 -127
- package/dist/types/notifications/config.d.ts +0 -132
- package/src/harness-control-plane/rpc-adapter.ts +0 -290
- package/src/modes/bridge/auth.ts +0 -41
- package/src/modes/bridge/bridge-client-bridge.ts +0 -47
- package/src/modes/bridge/bridge-mode.ts +0 -675
- package/src/modes/bridge/bridge-ui-context.ts +0 -200
- package/src/modes/bridge/event-stream.ts +0 -70
- package/src/modes/rpc/host-tools.ts +0 -1
- package/src/modes/rpc/host-uris.ts +0 -1
- package/src/modes/rpc/rpc-client.ts +0 -1166
- package/src/modes/rpc/rpc-mode.ts +0 -1029
- package/src/modes/rpc/rpc-socket-security.ts +0 -115
- package/src/modes/rpc/rpc-types.ts +0 -637
- package/src/modes/shared/agent-wire/command-contract.ts +0 -18
- package/src/modes/shared/agent-wire/command-dispatch.ts +0 -498
- package/src/modes/shared/agent-wire/command-validation.ts +0 -181
- package/src/modes/shared/agent-wire/handshake.ts +0 -157
- package/src/modes/shared/agent-wire/host-tool-bridge.ts +0 -197
- package/src/modes/shared/agent-wire/host-uri-bridge.ts +0 -236
- package/src/modes/shared/agent-wire/protocol.ts +0 -46
- package/src/modes/shared/agent-wire/responses.ts +0 -17
- package/src/modes/shared/agent-wire/scopes.ts +0 -94
- package/src/modes/shared/agent-wire/session-registry.ts +0 -109
- package/src/modes/shared/agent-wire/ui-request-broker.ts +0 -150
- package/src/modes/shared/agent-wire/ui-result.ts +0 -48
- package/src/modes/shared/agent-wire/unattended-action-policy.ts +0 -365
- package/src/modes/shared/agent-wire/unattended-audit.ts +0 -176
- package/src/modes/shared/agent-wire/unattended-run-controller.ts +0 -426
- package/src/modes/shared/agent-wire/unattended-session.ts +0 -528
- package/src/notifications/config.ts +0 -219
- package/src/notifications/index.ts +0 -1835
- package/src/notifications/telegram-daemon-cli.ts +0 -243
- package/src/tools/puppeteer/09_stealth_locale.txt +0 -46
- /package/dist/types/{notifications → sdk/bus}/attachment-registry.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/chat-adapters.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/daemon-paths.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/engine.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/helpers.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/lifecycle-commands.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/operator-runtime.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/rate-limit-pool.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/recent-activity.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/reply-sent-store.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/rich-draft.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/rich-render.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/threaded-inbound.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/threaded-render.d.ts +0 -0
- /package/src/{notifications → sdk/bus}/attachment-registry.ts +0 -0
- /package/src/{notifications → sdk/bus}/chat-adapters.ts +0 -0
- /package/src/{notifications → sdk/bus}/daemon-paths.ts +0 -0
- /package/src/{notifications → sdk/bus}/engine.ts +0 -0
- /package/src/{notifications → sdk/bus}/helpers.ts +0 -0
- /package/src/{notifications → sdk/bus}/operator-runtime.ts +0 -0
- /package/src/{notifications → sdk/bus}/rate-limit-pool.ts +0 -0
- /package/src/{notifications → sdk/bus}/recent-activity.ts +0 -0
- /package/src/{notifications → sdk/bus}/reply-sent-store.ts +0 -0
- /package/src/{notifications → sdk/bus}/rich-draft.ts +0 -0
- /package/src/{notifications → sdk/bus}/rich-render.ts +0 -0
- /package/src/{notifications → sdk/bus}/threaded-inbound.ts +0 -0
- /package/src/{notifications → sdk/bus}/threaded-render.ts +0 -0
package/src/cli/notify-cli.ts
CHANGED
|
@@ -6,8 +6,18 @@
|
|
|
6
6
|
import { createInterface } from "node:readline/promises";
|
|
7
7
|
import { APP_NAME } from "@gajae-code/utils/dirs";
|
|
8
8
|
import chalk from "chalk";
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
9
|
+
import { Settings, type SettingsAtomicPatch } from "../config/settings";
|
|
10
|
+
import { type EnsureChatDaemonResult, ensureDiscordDaemon, ensureSlackDaemon } from "../sdk/bus/chat-daemon-control";
|
|
11
|
+
import { getNotificationConfig, maskToken, tokenFingerprint } from "../sdk/bus/config";
|
|
12
|
+
import {
|
|
13
|
+
clearTelegramActivationMarker,
|
|
14
|
+
createTelegramActivationMarker,
|
|
15
|
+
observedTelegramActivationMarker,
|
|
16
|
+
type ProposedTelegramIdentity,
|
|
17
|
+
persistTelegramActivationMarker,
|
|
18
|
+
proposedTelegramIdentity,
|
|
19
|
+
reconcileCommittedTelegramConfiguration,
|
|
20
|
+
} from "../sdk/bus/notification-orchestration";
|
|
11
21
|
import {
|
|
12
22
|
buildNotificationStatusReport,
|
|
13
23
|
checkNotificationHealth,
|
|
@@ -16,17 +26,36 @@ import {
|
|
|
16
26
|
formatNotificationStatusReport,
|
|
17
27
|
formatNotificationTestResult,
|
|
18
28
|
recoverNotifications,
|
|
29
|
+
sanitizeDiagnostic,
|
|
19
30
|
sendNotificationTest,
|
|
20
|
-
} from "../
|
|
31
|
+
} from "../sdk/bus/notification-service";
|
|
32
|
+
import { ensureTelegramDaemonRunningDetailed, readDaemonState } from "../sdk/bus/telegram-daemon";
|
|
33
|
+
import { runDaemonInternal } from "../sdk/bus/telegram-daemon-cli";
|
|
34
|
+
import {
|
|
35
|
+
runTelegramSetup as runTelegramPairingSetup,
|
|
36
|
+
type TelegramSetupPreflight,
|
|
37
|
+
type TelegramSetupTimers,
|
|
38
|
+
} from "../sdk/bus/telegram-setup";
|
|
21
39
|
|
|
22
40
|
export type NotifyAction = "setup" | "status" | "health" | "test" | "recovery" | "daemon-internal";
|
|
41
|
+
export type NotifySetupProvider = "telegram" | "discord" | "slack";
|
|
23
42
|
|
|
24
43
|
export interface NotifyCommandArgs {
|
|
25
44
|
action: NotifyAction;
|
|
26
45
|
smoke?: boolean;
|
|
27
46
|
rawArgs: string[];
|
|
47
|
+
provider?: NotifySetupProvider;
|
|
28
48
|
token?: string;
|
|
29
49
|
chatId?: string;
|
|
50
|
+
discordBotToken?: string;
|
|
51
|
+
discordApplicationId?: string;
|
|
52
|
+
discordGuildId?: string;
|
|
53
|
+
discordParentChannelId?: string;
|
|
54
|
+
slackBotToken?: string;
|
|
55
|
+
slackAppToken?: string;
|
|
56
|
+
slackWorkspaceId?: string;
|
|
57
|
+
slackChannelId?: string;
|
|
58
|
+
slackAuthorizedUserId?: string;
|
|
30
59
|
redact?: boolean;
|
|
31
60
|
probe?: boolean;
|
|
32
61
|
message?: string;
|
|
@@ -46,45 +75,18 @@ export interface NotifyCommandDeps {
|
|
|
46
75
|
tokenPrompt?: () => Promise<string>;
|
|
47
76
|
setExitCode?: (code: number) => void;
|
|
48
77
|
exitProcess?: (code: number) => void;
|
|
78
|
+
/** Optional daemon ownership facts collected by an embedding host. */
|
|
79
|
+
setupPreflight?: TelegramSetupPreflight;
|
|
80
|
+
/** Injectable timers and cancellation for setup pairing. */
|
|
81
|
+
setupTimers?: TelegramSetupTimers;
|
|
82
|
+
setupAbortSignal?: AbortSignal;
|
|
83
|
+
setupPidAlive?: (pid: number) => boolean;
|
|
84
|
+
ensureProviderDaemon?: (
|
|
85
|
+
provider: "discord" | "slack",
|
|
86
|
+
settings: Settings,
|
|
87
|
+
) => Promise<EnsureChatDaemonResult | "failed">;
|
|
49
88
|
}
|
|
50
89
|
|
|
51
|
-
interface TelegramApiResponse<T> {
|
|
52
|
-
ok: boolean;
|
|
53
|
-
result?: T;
|
|
54
|
-
description?: string;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
interface TelegramUpdate {
|
|
58
|
-
update_id: number;
|
|
59
|
-
message?: {
|
|
60
|
-
chat?: {
|
|
61
|
-
id?: number | string;
|
|
62
|
-
type?: string;
|
|
63
|
-
};
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
interface TelegramUser {
|
|
68
|
-
id: number;
|
|
69
|
-
is_bot?: boolean;
|
|
70
|
-
first_name?: string;
|
|
71
|
-
username?: string;
|
|
72
|
-
has_topics_enabled?: boolean;
|
|
73
|
-
allows_users_to_create_topics?: boolean;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
interface TelegramChat {
|
|
77
|
-
id?: number | string;
|
|
78
|
-
type?: string;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
type ThreadedModeState = "enabled" | "disabled" | "unknown";
|
|
82
|
-
type ThreadedModeFinalLabel = "verified" | "unverified" | "unknown";
|
|
83
|
-
|
|
84
|
-
const DEFAULT_API_BASE = "https://api.telegram.org";
|
|
85
|
-
const DEFAULT_POLL_TIMEOUT_MS = 60_000;
|
|
86
|
-
const DEFAULT_POLL_INTERVAL_MS = 1_000;
|
|
87
|
-
|
|
88
90
|
export function parseNotifyArgs(args: string[]): NotifyCommandArgs | undefined {
|
|
89
91
|
if (args.length === 0 || args[0] !== "notify") {
|
|
90
92
|
return undefined;
|
|
@@ -97,11 +99,27 @@ export function parseNotifyArgs(args: string[]): NotifyCommandArgs | undefined {
|
|
|
97
99
|
const i = rest.indexOf(name);
|
|
98
100
|
return i >= 0 ? rest[i + 1] : undefined;
|
|
99
101
|
};
|
|
102
|
+
const provider = rest[0]?.startsWith("--") ? undefined : rest[0];
|
|
103
|
+
if (provider !== undefined && provider !== "telegram" && provider !== "discord" && provider !== "slack") {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
100
106
|
return {
|
|
101
107
|
action,
|
|
102
108
|
rawArgs: rest,
|
|
109
|
+
...(provider ? { provider } : {}),
|
|
103
110
|
token: flag("--token"),
|
|
104
111
|
chatId: flag("--chat-id"),
|
|
112
|
+
...(flag("--discord-bot-token") ? { discordBotToken: flag("--discord-bot-token") } : {}),
|
|
113
|
+
...(flag("--discord-application-id") ? { discordApplicationId: flag("--discord-application-id") } : {}),
|
|
114
|
+
...(flag("--discord-guild-id") ? { discordGuildId: flag("--discord-guild-id") } : {}),
|
|
115
|
+
...(flag("--discord-parent-channel-id")
|
|
116
|
+
? { discordParentChannelId: flag("--discord-parent-channel-id") }
|
|
117
|
+
: {}),
|
|
118
|
+
...(flag("--slack-bot-token") ? { slackBotToken: flag("--slack-bot-token") } : {}),
|
|
119
|
+
...(flag("--slack-app-token") ? { slackAppToken: flag("--slack-app-token") } : {}),
|
|
120
|
+
...(flag("--slack-workspace-id") ? { slackWorkspaceId: flag("--slack-workspace-id") } : {}),
|
|
121
|
+
...(flag("--slack-channel-id") ? { slackChannelId: flag("--slack-channel-id") } : {}),
|
|
122
|
+
...(flag("--slack-authorized-user-id") ? { slackAuthorizedUserId: flag("--slack-authorized-user-id") } : {}),
|
|
105
123
|
redact: rest.includes("--redact"),
|
|
106
124
|
};
|
|
107
125
|
}
|
|
@@ -132,7 +150,7 @@ export function parseNotifyArgs(args: string[]): NotifyCommandArgs | undefined {
|
|
|
132
150
|
export async function runNotifyCommand(cmd: NotifyCommandArgs, deps: NotifyCommandDeps = {}): Promise<void> {
|
|
133
151
|
switch (cmd.action) {
|
|
134
152
|
case "setup":
|
|
135
|
-
await runSetup({
|
|
153
|
+
await runSetup(cmd, {
|
|
136
154
|
...deps,
|
|
137
155
|
setupToken: deps.setupToken ?? cmd.token,
|
|
138
156
|
setupChatId: deps.setupChatId ?? cmd.chatId,
|
|
@@ -151,15 +169,13 @@ export async function runNotifyCommand(cmd: NotifyCommandArgs, deps: NotifyComma
|
|
|
151
169
|
case "recovery":
|
|
152
170
|
await runRecovery(deps);
|
|
153
171
|
return;
|
|
154
|
-
case "daemon-internal":
|
|
155
|
-
const m = await import("../notifications/telegram-daemon-cli");
|
|
172
|
+
case "daemon-internal":
|
|
156
173
|
if (cmd.smoke) {
|
|
157
|
-
await
|
|
174
|
+
await runDaemonInternal(["--smoke"]);
|
|
158
175
|
} else {
|
|
159
|
-
await
|
|
176
|
+
await runDaemonInternal(cmd.rawArgs);
|
|
160
177
|
}
|
|
161
178
|
return;
|
|
162
|
-
}
|
|
163
179
|
}
|
|
164
180
|
}
|
|
165
181
|
|
|
@@ -171,8 +187,9 @@ export async function runNotifyCliCommand(cmd: NotifyCommandArgs, deps: NotifyCo
|
|
|
171
187
|
throw error;
|
|
172
188
|
}
|
|
173
189
|
|
|
174
|
-
const cancelled =
|
|
175
|
-
|
|
190
|
+
const cancelled =
|
|
191
|
+
error.message === "Telegram bot token prompt cancelled." || error.message === "Telegram setup cancelled.";
|
|
192
|
+
process.stderr.write(cancelled ? "Notify setup cancelled.\n" : `Error: ${error.message}\n`);
|
|
176
193
|
const code = cancelled ? 130 : 1;
|
|
177
194
|
if (deps.setExitCode) {
|
|
178
195
|
deps.setExitCode(code);
|
|
@@ -186,52 +203,230 @@ export async function runNotifyCliCommand(cmd: NotifyCommandArgs, deps: NotifyCo
|
|
|
186
203
|
|
|
187
204
|
async function getSettings(deps: NotifyCommandDeps): Promise<Settings> {
|
|
188
205
|
if (deps.settings) return deps.settings;
|
|
189
|
-
const { Settings } = await import("../config/settings");
|
|
190
206
|
return await Settings.init();
|
|
191
207
|
}
|
|
192
208
|
|
|
193
|
-
async function runSetup(deps: NotifyCommandDeps): Promise<void> {
|
|
209
|
+
async function runSetup(cmd: NotifyCommandArgs, deps: NotifyCommandDeps): Promise<void> {
|
|
210
|
+
const provider = cmd.provider ?? "telegram";
|
|
211
|
+
if (provider === "discord") {
|
|
212
|
+
await runDiscordSetup(cmd, deps);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (provider === "slack") {
|
|
216
|
+
await runSlackSetup(cmd, deps);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
await runTelegramSetup(cmd, deps);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function requiredSetupValue(value: string | undefined, flag: string): string {
|
|
223
|
+
if (!value?.trim()) throw new Error(`${flag} is required for non-interactive setup.`);
|
|
224
|
+
return value.trim();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async function runDiscordSetup(cmd: NotifyCommandArgs, deps: NotifyCommandDeps): Promise<void> {
|
|
228
|
+
const botToken = requiredSetupValue(cmd.discordBotToken, "--discord-bot-token");
|
|
229
|
+
const applicationId = requiredSetupValue(cmd.discordApplicationId, "--discord-application-id");
|
|
230
|
+
const guildId = requiredSetupValue(cmd.discordGuildId, "--discord-guild-id");
|
|
231
|
+
const parentChannelId = requiredSetupValue(cmd.discordParentChannelId, "--discord-parent-channel-id");
|
|
232
|
+
const settings = await getSettings(deps);
|
|
233
|
+
settings.set("notifications.discord.botToken", botToken);
|
|
234
|
+
settings.set("notifications.discord.applicationId", applicationId);
|
|
235
|
+
settings.set("notifications.discord.guildId", guildId);
|
|
236
|
+
settings.set("notifications.discord.parentChannelId", parentChannelId);
|
|
237
|
+
settings.set("notifications.enabled", true);
|
|
238
|
+
if (cmd.redact) settings.set("notifications.redact", true);
|
|
239
|
+
await settings.flushOrThrow();
|
|
240
|
+
const daemon = await ensureConfiguredProviderDaemon("discord", settings, deps);
|
|
241
|
+
process.stdout.write(
|
|
242
|
+
`Discord notifications enabled. botToken=${maskToken(botToken)} applicationId=${applicationId} guildId=${guildId} parentChannelId=${parentChannelId} daemon=${daemon}\n`,
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async function runSlackSetup(cmd: NotifyCommandArgs, deps: NotifyCommandDeps): Promise<void> {
|
|
247
|
+
const botToken = requiredSetupValue(cmd.slackBotToken, "--slack-bot-token");
|
|
248
|
+
const appToken = requiredSetupValue(cmd.slackAppToken, "--slack-app-token");
|
|
249
|
+
const workspaceId = requiredSetupValue(cmd.slackWorkspaceId, "--slack-workspace-id");
|
|
250
|
+
const channelId = requiredSetupValue(cmd.slackChannelId, "--slack-channel-id");
|
|
251
|
+
const authorizedUserId = cmd.slackAuthorizedUserId?.trim() || undefined;
|
|
194
252
|
const settings = await getSettings(deps);
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
253
|
+
settings.set("notifications.slack.botToken", botToken);
|
|
254
|
+
settings.set("notifications.slack.appToken", appToken);
|
|
255
|
+
settings.set("notifications.slack.workspaceId", workspaceId);
|
|
256
|
+
settings.set("notifications.slack.channelId", channelId);
|
|
257
|
+
settings.set("notifications.slack.authorizedUserId", authorizedUserId);
|
|
258
|
+
settings.set("notifications.enabled", true);
|
|
259
|
+
if (cmd.redact) settings.set("notifications.redact", true);
|
|
260
|
+
await settings.flushOrThrow();
|
|
261
|
+
const daemon = await ensureConfiguredProviderDaemon("slack", settings, deps);
|
|
262
|
+
process.stdout.write(
|
|
263
|
+
`Slack notifications enabled. botToken=${maskToken(botToken)} appToken=${maskToken(appToken)} workspaceId=${workspaceId} channelId=${channelId} authorizedUserId=${authorizedUserId ?? "(unset; inbound denied)"} daemon=${daemon}\n`,
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
async function ensureConfiguredProviderDaemon(
|
|
268
|
+
provider: "discord" | "slack",
|
|
269
|
+
settings: Settings,
|
|
270
|
+
deps: NotifyCommandDeps,
|
|
271
|
+
): Promise<EnsureChatDaemonResult | "failed"> {
|
|
272
|
+
try {
|
|
273
|
+
if (deps.ensureProviderDaemon) return await deps.ensureProviderDaemon(provider, settings);
|
|
274
|
+
return provider === "discord" ? await ensureDiscordDaemon(settings) : await ensureSlackDaemon(settings);
|
|
275
|
+
} catch {
|
|
276
|
+
return "failed";
|
|
200
277
|
}
|
|
278
|
+
}
|
|
201
279
|
|
|
202
|
-
|
|
203
|
-
const
|
|
280
|
+
async function runTelegramSetup(cmd: NotifyCommandArgs, deps: NotifyCommandDeps): Promise<void> {
|
|
281
|
+
const settings = await getSettings(deps);
|
|
282
|
+
const token = deps.setupToken ?? cmd.token ?? (await (deps.tokenPrompt ?? promptForToken)());
|
|
283
|
+
if (!token.trim()) throw new Error("Telegram bot token is required.");
|
|
284
|
+
|
|
285
|
+
const result = await runTelegramPairingSetup({
|
|
286
|
+
token,
|
|
287
|
+
preflight: deps.setupPreflight ?? (await resolveSetupPreflight(settings, deps)),
|
|
288
|
+
revalidatePreflight: async () => deps.setupPreflight ?? (await resolveSetupPreflight(settings, deps)),
|
|
289
|
+
chatId: deps.setupChatId,
|
|
204
290
|
interactive: resolveSetupInteractive(deps),
|
|
205
|
-
|
|
291
|
+
threadedModePrompt: deps.threadedModePrompt ?? promptForThreadedMode,
|
|
292
|
+
pollTimeoutMs: deps.pollTimeoutMs,
|
|
293
|
+
pollIntervalMs: deps.pollIntervalMs,
|
|
294
|
+
signal: deps.setupAbortSignal,
|
|
295
|
+
deps: {
|
|
296
|
+
fetchImpl: deps.fetchImpl ?? globalThis.fetch,
|
|
297
|
+
apiBase: deps.apiBase,
|
|
298
|
+
timers: deps.setupTimers,
|
|
299
|
+
},
|
|
300
|
+
onEvent: event => {
|
|
301
|
+
const output = event.kind === "rejected_chat" ? process.stderr : process.stdout;
|
|
302
|
+
output.write(event.message);
|
|
303
|
+
},
|
|
206
304
|
});
|
|
305
|
+
if (!result.ok) throw new Error(result.detail);
|
|
306
|
+
if (result.pairingSource === "provided") {
|
|
307
|
+
process.stdout.write(`Using provided chat id ${result.chatId} (non-interactive).\n`);
|
|
308
|
+
}
|
|
309
|
+
try {
|
|
310
|
+
const proposedIdentity = deps.setupPreflight
|
|
311
|
+
? proposedIdentityFromSetupPreflight(deps.setupPreflight, token.trim(), result.chatId)
|
|
312
|
+
: await proposedTelegramIdentity({
|
|
313
|
+
settings,
|
|
314
|
+
botToken: token.trim(),
|
|
315
|
+
chatId: result.chatId,
|
|
316
|
+
chatDisplay: result.chatId,
|
|
317
|
+
});
|
|
318
|
+
if (proposedIdentity.status === "foreign" || proposedIdentity.status === "unknown") {
|
|
319
|
+
throw new Error(
|
|
320
|
+
"Telegram activation was not saved because the current daemon owner has an untrusted identity.",
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const inactiveMarkerToClear = observedTelegramActivationMarker(settings, token.trim(), result.chatId);
|
|
325
|
+
const patches: SettingsAtomicPatch[] = [
|
|
326
|
+
{ path: "notifications.telegram.botToken", op: "set", value: token.trim() },
|
|
327
|
+
{ path: "notifications.telegram.chatId", op: "set", value: result.chatId },
|
|
328
|
+
{ path: "notifications.enabled", op: "set", value: true },
|
|
329
|
+
];
|
|
330
|
+
if (deps.setupRedact ?? cmd.redact) patches.push({ path: "notifications.redact", op: "set", value: true });
|
|
331
|
+
const receipt = await settings.commitAtomicBatch(patches);
|
|
332
|
+
const activationMarker = createTelegramActivationMarker({
|
|
333
|
+
botToken: token.trim(),
|
|
334
|
+
chatId: result.chatId,
|
|
335
|
+
state: "blocked",
|
|
336
|
+
reason: "identity_mismatch",
|
|
337
|
+
});
|
|
338
|
+
const activation = await reconcileCommittedTelegramConfiguration({
|
|
339
|
+
receipt,
|
|
340
|
+
inactiveMarkerToClear,
|
|
341
|
+
activation: {
|
|
342
|
+
// The CLI does not host a session endpoint. The settings editor supplies
|
|
343
|
+
// its live controller here; a CLI identity block therefore has no local
|
|
344
|
+
// endpoint to stop before the durable rollback below.
|
|
345
|
+
controller: {
|
|
346
|
+
enterBlockedRuntime: async () => undefined,
|
|
347
|
+
clearBlockedRuntime: async () => undefined,
|
|
348
|
+
reconcileCurrentSession: async () => undefined,
|
|
349
|
+
},
|
|
350
|
+
reconnect: async () =>
|
|
351
|
+
await ensureTelegramDaemonRunningDetailed({
|
|
352
|
+
settings,
|
|
353
|
+
cwd: process.cwd(),
|
|
354
|
+
sessionId: `notify-cli-${process.pid}`,
|
|
355
|
+
}),
|
|
356
|
+
persistInactive: async marker => await persistTelegramActivationMarker(settings, marker),
|
|
357
|
+
clearInactive: async marker => await clearTelegramActivationMarker(settings, marker),
|
|
358
|
+
marker: activationMarker,
|
|
359
|
+
},
|
|
360
|
+
});
|
|
361
|
+
if (activation.status === "blocked_identity") {
|
|
362
|
+
const restored = await activation.restore();
|
|
363
|
+
const detail =
|
|
364
|
+
restored.status === "restored"
|
|
365
|
+
? "Telegram activation was blocked by a foreign daemon; previous settings were restored."
|
|
366
|
+
: restored.status === "still_blocked"
|
|
367
|
+
? "Telegram activation remains blocked by a foreign daemon; previous settings were restored."
|
|
368
|
+
: restored.status === "conflict"
|
|
369
|
+
? "Telegram activation was blocked and settings changed concurrently; refusing to report setup success."
|
|
370
|
+
: "Telegram activation was blocked; refusing to report setup success.";
|
|
371
|
+
throw new Error(detail);
|
|
372
|
+
}
|
|
373
|
+
} catch (error) {
|
|
374
|
+
const detail = sanitizeDiagnostic(error instanceof Error ? error.message : "unknown persistence failure", token);
|
|
375
|
+
throw new Error(`Unable to persist and activate Telegram notification settings: ${detail}`);
|
|
376
|
+
}
|
|
207
377
|
process.stdout.write(
|
|
208
|
-
|
|
378
|
+
`Notifications enabled. botToken=${maskToken(token)} chatId=${result.chatId} threaded=${result.threadedLabel}\n`,
|
|
209
379
|
);
|
|
380
|
+
}
|
|
210
381
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
offset,
|
|
221
|
-
pollTimeoutMs: deps.pollTimeoutMs ?? DEFAULT_POLL_TIMEOUT_MS,
|
|
222
|
-
pollIntervalMs: deps.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS,
|
|
223
|
-
});
|
|
382
|
+
function proposedIdentityFromSetupPreflight(
|
|
383
|
+
preflight: TelegramSetupPreflight,
|
|
384
|
+
botToken: string,
|
|
385
|
+
chatId: string,
|
|
386
|
+
): ProposedTelegramIdentity {
|
|
387
|
+
const daemon = preflight.daemon;
|
|
388
|
+
if (!daemon?.live) return { status: "absent" };
|
|
389
|
+
if (typeof daemon.tokenFingerprint !== "string" || typeof daemon.chatId !== "string") {
|
|
390
|
+
return { status: "unknown" };
|
|
224
391
|
}
|
|
392
|
+
return daemon.tokenFingerprint === tokenFingerprint(botToken) && daemon.chatId === chatId
|
|
393
|
+
? { status: "same" }
|
|
394
|
+
: { status: "foreign" };
|
|
395
|
+
}
|
|
225
396
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
settings
|
|
229
|
-
|
|
230
|
-
|
|
397
|
+
async function resolveSetupPreflight(settings: Settings, deps: NotifyCommandDeps): Promise<TelegramSetupPreflight> {
|
|
398
|
+
if (deps.setupPreflight) return deps.setupPreflight;
|
|
399
|
+
const cfg = getNotificationConfig(settings);
|
|
400
|
+
try {
|
|
401
|
+
const state = await readDaemonState(settings);
|
|
402
|
+
if (!state) return { storedChatId: cfg.chatId };
|
|
403
|
+
const validPid = Number.isSafeInteger(state.pid) && state.pid > 0;
|
|
404
|
+
// Owner-proof: only block discovery for a daemon we can positively prove is
|
|
405
|
+
// live (present state with a valid, alive pid). A malformed/no-pid record is
|
|
406
|
+
// not evidence of a live poller, mirroring recoverNotifications' semantics.
|
|
407
|
+
if (!validPid) return { storedChatId: cfg.chatId };
|
|
408
|
+
return {
|
|
409
|
+
storedChatId: cfg.chatId,
|
|
410
|
+
daemon: {
|
|
411
|
+
live: (deps.setupPidAlive ?? daemonPidAlive)(state.pid),
|
|
412
|
+
tokenFingerprint: typeof state.tokenFingerprint === "string" ? state.tokenFingerprint : undefined,
|
|
413
|
+
chatId: typeof state.chatId === "string" ? state.chatId : undefined,
|
|
414
|
+
},
|
|
415
|
+
};
|
|
416
|
+
} catch {
|
|
417
|
+
// A state read failure is not proof of a live daemon; proceed normally. The
|
|
418
|
+
// daemon's own 409 handling remains the backstop against poller contention.
|
|
419
|
+
return { storedChatId: cfg.chatId };
|
|
420
|
+
}
|
|
421
|
+
}
|
|
231
422
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
423
|
+
function daemonPidAlive(pid: number): boolean {
|
|
424
|
+
try {
|
|
425
|
+
process.kill(pid, 0);
|
|
426
|
+
return true;
|
|
427
|
+
} catch (error) {
|
|
428
|
+
return (error as NodeJS.ErrnoException).code === "EPERM";
|
|
429
|
+
}
|
|
235
430
|
}
|
|
236
431
|
|
|
237
432
|
type TokenPromptInput = NodeJS.ReadStream & {
|
|
@@ -308,77 +503,6 @@ export async function promptForToken(
|
|
|
308
503
|
});
|
|
309
504
|
}
|
|
310
505
|
|
|
311
|
-
const THREADED_ENABLED_SUCCESS =
|
|
312
|
-
"Telegram Threaded Mode capability verified for this bot. GJC will request a private-chat topic per session; if Telegram ever refuses topic creation, notifications fall back to this flat chat with inline ask buttons only and a one-time Threaded Mode nudge.\n";
|
|
313
|
-
|
|
314
|
-
const THREADED_MISSING_WARNING =
|
|
315
|
-
"Warning: Telegram getMe did not include has_topics_enabled, so GJC cannot verify private-chat Threaded Mode capability for this bot. Setup will continue; flat private-chat fallback supports outbound notifications and inline ask buttons only. Free-text replies and session commands require Threaded Mode/topic routing.\n";
|
|
316
|
-
|
|
317
|
-
const THREADED_NONINTERACTIVE_WARNING =
|
|
318
|
-
"Warning: Telegram Threaded Mode capability is OFF for this bot. Setup will be saved because this run is non-interactive. Flat private-chat fallback supports outbound notifications and inline ask buttons only; free-text replies and session commands require enabling Threaded Mode in @BotFather > Bot Settings > Threads Settings.\n";
|
|
319
|
-
|
|
320
|
-
const THREADED_DISABLED_GUIDANCE =
|
|
321
|
-
"Telegram Threaded Mode is OFF for this bot. GJC needs Telegram private-chat topics so each session can use its own thread.\n" +
|
|
322
|
-
"GJC cannot enable this through the Bot API. Open @BotFather > Bot Settings > Threads Settings for this bot, enable Threaded Mode / forum topics for private chats, then return here.\n" +
|
|
323
|
-
"Without Threaded Mode, flat private-chat fallback supports outbound notifications and inline ask buttons only; free-text replies and session commands require topic routing.\n";
|
|
324
|
-
|
|
325
|
-
const THREADED_DISABLED_PROMPT =
|
|
326
|
-
"Press Enter after enabling Threaded Mode, or type skip to finish setup with a warning: ";
|
|
327
|
-
|
|
328
|
-
const THREADED_STILL_OFF = "Telegram still reports Threaded Mode OFF for this bot.\n";
|
|
329
|
-
|
|
330
|
-
const THREADED_RETRY_PROMPT = "Press Enter to check again, or type skip to finish setup with a warning: ";
|
|
331
|
-
|
|
332
|
-
const THREADED_SKIP_WARNING =
|
|
333
|
-
"Warning: continuing without verified Telegram Threaded Mode capability. Setup will be saved. Flat private-chat fallback supports outbound notifications and inline ask buttons only; free-text replies and session commands require enabling Threaded Mode in BotFather.\n";
|
|
334
|
-
|
|
335
|
-
const THREADED_INVALID_INPUT = "Type Enter to retry or skip to continue with a warning.\n";
|
|
336
|
-
|
|
337
|
-
const THREADED_RETRY_INPUTS = new Set(["", "y", "yes", "r", "retry"]);
|
|
338
|
-
const THREADED_SKIP_INPUTS = new Set(["s", "skip", "n", "no"]);
|
|
339
|
-
|
|
340
|
-
function isTelegramUser(value: unknown): value is TelegramUser {
|
|
341
|
-
return Boolean(value) && typeof value === "object" && typeof (value as { id?: unknown }).id === "number";
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
async function getMe(fetchImpl: typeof fetch, apiBase: string, token: string): Promise<TelegramUser> {
|
|
345
|
-
const user = await callTelegram<unknown>(fetchImpl, apiBase, token, "getMe", {});
|
|
346
|
-
if (!isTelegramUser(user)) {
|
|
347
|
-
throw new Error("Telegram getMe returned invalid Telegram response: missing valid User result.");
|
|
348
|
-
}
|
|
349
|
-
return user;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
async function verifyPrivateChatId(
|
|
353
|
-
fetchImpl: typeof fetch,
|
|
354
|
-
apiBase: string,
|
|
355
|
-
token: string,
|
|
356
|
-
chatId: string,
|
|
357
|
-
): Promise<void> {
|
|
358
|
-
const chat = (await callTelegram<unknown>(fetchImpl, apiBase, token, "getChat", { chat_id: chatId })) as
|
|
359
|
-
| TelegramChat
|
|
360
|
-
| undefined;
|
|
361
|
-
if (!chat || typeof chat !== "object") {
|
|
362
|
-
throw new Error("Telegram getChat returned invalid Telegram response: missing valid Chat result.");
|
|
363
|
-
}
|
|
364
|
-
if (chat.type !== "private") {
|
|
365
|
-
const type = typeof chat.type === "string" && chat.type ? chat.type : "unknown";
|
|
366
|
-
throw new Error(`Provided chat id ${chatId} is a ${type} chat; pairing requires a private Telegram chat.`);
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
function threadedModeState(user: TelegramUser): ThreadedModeState {
|
|
371
|
-
if (user.has_topics_enabled === true) return "enabled";
|
|
372
|
-
if (user.has_topics_enabled === false) return "disabled";
|
|
373
|
-
return "unknown";
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
function threadedLabel(state: ThreadedModeState): ThreadedModeFinalLabel {
|
|
377
|
-
if (state === "enabled") return "verified";
|
|
378
|
-
if (state === "disabled") return "unverified";
|
|
379
|
-
return "unknown";
|
|
380
|
-
}
|
|
381
|
-
|
|
382
506
|
function resolveSetupInteractive(deps: NotifyCommandDeps): boolean {
|
|
383
507
|
if (deps.setupInteractive !== undefined) return deps.setupInteractive;
|
|
384
508
|
return Boolean(process.stdin.isTTY) && !deps.setupChatId?.trim();
|
|
@@ -394,55 +518,6 @@ async function promptForThreadedMode(message: string): Promise<string> {
|
|
|
394
518
|
}
|
|
395
519
|
}
|
|
396
520
|
|
|
397
|
-
async function verifyThreadedMode(
|
|
398
|
-
fetchImpl: typeof fetch,
|
|
399
|
-
apiBase: string,
|
|
400
|
-
token: string,
|
|
401
|
-
initialUser: TelegramUser,
|
|
402
|
-
opts: { interactive: boolean; prompt: (message: string) => Promise<string> },
|
|
403
|
-
): Promise<ThreadedModeState> {
|
|
404
|
-
const classify = (user: TelegramUser): ThreadedModeState | undefined => {
|
|
405
|
-
const state = threadedModeState(user);
|
|
406
|
-
if (state === "enabled") {
|
|
407
|
-
process.stdout.write(THREADED_ENABLED_SUCCESS);
|
|
408
|
-
return "enabled";
|
|
409
|
-
}
|
|
410
|
-
if (state === "unknown") {
|
|
411
|
-
process.stdout.write(THREADED_MISSING_WARNING);
|
|
412
|
-
return "unknown";
|
|
413
|
-
}
|
|
414
|
-
return undefined;
|
|
415
|
-
};
|
|
416
|
-
|
|
417
|
-
const initial = classify(initialUser);
|
|
418
|
-
if (initial) return initial;
|
|
419
|
-
|
|
420
|
-
if (!opts.interactive) {
|
|
421
|
-
process.stdout.write(THREADED_NONINTERACTIVE_WARNING);
|
|
422
|
-
return "disabled";
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
process.stdout.write(THREADED_DISABLED_GUIDANCE);
|
|
426
|
-
let firstPrompt = true;
|
|
427
|
-
for (;;) {
|
|
428
|
-
const answer = (await opts.prompt(firstPrompt ? THREADED_DISABLED_PROMPT : THREADED_RETRY_PROMPT))
|
|
429
|
-
.trim()
|
|
430
|
-
.toLowerCase();
|
|
431
|
-
firstPrompt = false;
|
|
432
|
-
if (THREADED_SKIP_INPUTS.has(answer)) {
|
|
433
|
-
process.stdout.write(THREADED_SKIP_WARNING);
|
|
434
|
-
return "disabled";
|
|
435
|
-
}
|
|
436
|
-
if (!THREADED_RETRY_INPUTS.has(answer)) {
|
|
437
|
-
process.stdout.write(THREADED_INVALID_INPUT);
|
|
438
|
-
continue;
|
|
439
|
-
}
|
|
440
|
-
const resolved = classify(await getMe(fetchImpl, apiBase, token));
|
|
441
|
-
if (resolved) return resolved;
|
|
442
|
-
process.stdout.write(THREADED_STILL_OFF);
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
|
|
446
521
|
async function runStatus(deps: NotifyCommandDeps): Promise<void> {
|
|
447
522
|
const settings = await getSettings(deps);
|
|
448
523
|
const report = buildNotificationStatusReport(settings);
|
|
@@ -481,101 +556,25 @@ async function runRecovery(deps: NotifyCommandDeps): Promise<void> {
|
|
|
481
556
|
process.stdout.write(`${formatNotificationRecoveryReport(report)}\n`);
|
|
482
557
|
}
|
|
483
558
|
|
|
484
|
-
async function waitForPrivateChat(
|
|
485
|
-
fetchImpl: typeof fetch,
|
|
486
|
-
apiBase: string,
|
|
487
|
-
token: string,
|
|
488
|
-
opts: { offset: number | undefined; pollTimeoutMs: number; pollIntervalMs: number },
|
|
489
|
-
): Promise<string> {
|
|
490
|
-
const deadline = Date.now() + opts.pollTimeoutMs;
|
|
491
|
-
let offset = opts.offset;
|
|
492
|
-
let sawRejectedChatType: string | undefined;
|
|
493
|
-
|
|
494
|
-
while (Date.now() <= deadline) {
|
|
495
|
-
const updates = await getUpdates(fetchImpl, apiBase, token, { offset, timeout: 0, allowed_updates: ["message"] });
|
|
496
|
-
offset = nextOffset(updates, offset);
|
|
497
|
-
for (const update of updates) {
|
|
498
|
-
const chat = update.message?.chat;
|
|
499
|
-
if (!chat) continue;
|
|
500
|
-
if (chat.type === "private" && chat.id !== undefined) {
|
|
501
|
-
return String(chat.id);
|
|
502
|
-
}
|
|
503
|
-
if (chat.type === "group" || chat.type === "supergroup" || chat.type === "channel") {
|
|
504
|
-
sawRejectedChatType = chat.type;
|
|
505
|
-
process.stderr.write(
|
|
506
|
-
`Rejected ${chat.type} chat. Pairing requires a private Telegram chat with the bot.\n`,
|
|
507
|
-
);
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
if (opts.pollIntervalMs > 0) {
|
|
511
|
-
await new Promise(resolve =>
|
|
512
|
-
setTimeout(resolve, Math.min(opts.pollIntervalMs, Math.max(0, deadline - Date.now()))),
|
|
513
|
-
);
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
if (sawRejectedChatType) {
|
|
518
|
-
throw new Error(`Pairing rejected ${sawRejectedChatType} chat; message the bot from a private chat.`);
|
|
519
|
-
}
|
|
520
|
-
throw new Error("Timed out waiting for a private Telegram message to pair notifications.");
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
function nextOffset(updates: TelegramUpdate[], fallback?: number): number | undefined {
|
|
524
|
-
let max = fallback === undefined ? undefined : fallback - 1;
|
|
525
|
-
for (const update of updates) {
|
|
526
|
-
if (typeof update.update_id === "number" && (max === undefined || update.update_id > max)) {
|
|
527
|
-
max = update.update_id;
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
return max === undefined ? fallback : max + 1;
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
async function getUpdates(
|
|
534
|
-
fetchImpl: typeof fetch,
|
|
535
|
-
apiBase: string,
|
|
536
|
-
token: string,
|
|
537
|
-
params: Record<string, unknown>,
|
|
538
|
-
): Promise<TelegramUpdate[]> {
|
|
539
|
-
return await callTelegram<TelegramUpdate[]>(fetchImpl, apiBase, token, "getUpdates", params);
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
async function callTelegram<T>(
|
|
543
|
-
fetchImpl: typeof fetch,
|
|
544
|
-
apiBase: string,
|
|
545
|
-
token: string,
|
|
546
|
-
method: string,
|
|
547
|
-
body: Record<string, unknown>,
|
|
548
|
-
): Promise<T> {
|
|
549
|
-
const response = await fetchImpl(`${apiBase.replace(/\/$/, "")}/bot${token}/${method}`, {
|
|
550
|
-
method: "POST",
|
|
551
|
-
headers: { "content-type": "application/json" },
|
|
552
|
-
body: JSON.stringify(body),
|
|
553
|
-
});
|
|
554
|
-
let payload: TelegramApiResponse<T>;
|
|
555
|
-
try {
|
|
556
|
-
payload = (await response.json()) as TelegramApiResponse<T>;
|
|
557
|
-
} catch {
|
|
558
|
-
throw new Error(`Telegram ${method} returned invalid JSON.`);
|
|
559
|
-
}
|
|
560
|
-
if (!response.ok || !payload.ok) {
|
|
561
|
-
throw new Error(`Telegram ${method} failed: ${payload.description ?? response.statusText}`);
|
|
562
|
-
}
|
|
563
|
-
return payload.result as T;
|
|
564
|
-
}
|
|
565
|
-
|
|
566
559
|
export function printNotifyHelp(): void {
|
|
567
|
-
process.stdout.write(`${chalk.bold(`${APP_NAME} notify`)} - Configure Telegram notifications
|
|
560
|
+
process.stdout.write(`${chalk.bold(`${APP_NAME} notify`)} - Configure Telegram, Discord, or Slack notifications
|
|
561
|
+
|
|
562
|
+
${chalk.bold("Interactive path:")}
|
|
563
|
+
In a running GJC session, use /settings → Notifications for setup, health, test, recovery,
|
|
564
|
+
reconnect, global enable/disable, adapter-local Telegram removal, and session on/off.
|
|
565
|
+
The CLI subcommands below remain the authoritative headless and automation fallback.
|
|
568
566
|
|
|
569
567
|
${chalk.bold("Usage:")}
|
|
570
|
-
${APP_NAME} notify setup
|
|
571
|
-
${APP_NAME} notify setup --token <
|
|
568
|
+
${APP_NAME} notify setup [telegram]
|
|
569
|
+
${APP_NAME} notify setup discord --discord-bot-token <token> --discord-application-id <id> --discord-guild-id <id> --discord-parent-channel-id <id>
|
|
570
|
+
${APP_NAME} notify setup slack --slack-bot-token <token> --slack-app-token <token> --slack-workspace-id <id> --slack-channel-id <id> [--slack-authorized-user-id <id>]
|
|
572
571
|
${APP_NAME} notify status
|
|
573
572
|
${APP_NAME} notify health [--probe]
|
|
574
573
|
${APP_NAME} notify test [--message <text>]
|
|
575
574
|
${APP_NAME} notify recovery
|
|
576
575
|
|
|
577
576
|
${chalk.bold("Subcommands:")}
|
|
578
|
-
setup Pair
|
|
577
|
+
setup Pair Telegram or save complete non-interactive Discord/Slack notification settings
|
|
579
578
|
status Show notification configuration without secrets
|
|
580
579
|
health Report config, daemon-ownership and endpoint health (--probe adds a Telegram reachability check)
|
|
581
580
|
test Send a one-off test notification through the configured Telegram adapter
|
|
@@ -583,6 +582,9 @@ ${chalk.bold("Subcommands:")}
|
|
|
583
582
|
|
|
584
583
|
${chalk.bold("Examples:")}
|
|
585
584
|
${APP_NAME} notify setup
|
|
585
|
+
${APP_NAME} notify setup --token <botToken> --chat-id <chatId> [--redact]
|
|
586
|
+
${APP_NAME} notify setup discord --discord-bot-token <token> --discord-application-id <id> --discord-guild-id <id> --discord-parent-channel-id <id>
|
|
587
|
+
${APP_NAME} notify setup slack --slack-bot-token <token> --slack-app-token <token> --slack-workspace-id <id> --slack-channel-id <id> [--slack-authorized-user-id <id>]
|
|
586
588
|
${APP_NAME} notify status
|
|
587
589
|
${APP_NAME} notify health --probe
|
|
588
590
|
${APP_NAME} notify test --message "hello from gjc"
|