opensquid 0.5.441 → 0.5.447
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 +1 -0
- package/dist/functions/arm_scope.d.ts +27 -0
- package/dist/functions/arm_scope.d.ts.map +1 -0
- package/dist/functions/arm_scope.js +52 -0
- package/dist/functions/arm_scope.js.map +1 -0
- package/dist/functions/index.d.ts +1 -0
- package/dist/functions/index.d.ts.map +1 -1
- package/dist/functions/index.js +1 -0
- package/dist/functions/index.js.map +1 -1
- package/dist/runtime/bootstrap.d.ts.map +1 -1
- package/dist/runtime/bootstrap.js +2 -0
- package/dist/runtime/bootstrap.js.map +1 -1
- package/dist/runtime/handoff/render.d.ts +5 -4
- package/dist/runtime/handoff/render.d.ts.map +1 -1
- package/dist/runtime/handoff/render.js +7 -7
- package/dist/runtime/handoff/render.js.map +1 -1
- package/dist/runtime/hooks/active_task_mirror.js +0 -0
- package/dist/runtime/hooks/apply_patch.js +0 -0
- package/dist/runtime/hooks/dispatch.js +0 -0
- package/dist/runtime/hooks/hook_output.js +0 -0
- package/dist/runtime/hooks/memory_reconcile.js +0 -0
- package/dist/runtime/hooks/new_project_detect.js +0 -0
- package/dist/runtime/hooks/profession_resolver.js +0 -0
- package/dist/runtime/hooks/scope_intent.js +0 -0
- package/dist/runtime/hooks/session_id.js +0 -0
- package/dist/runtime/hooks/session_liveness.js +0 -0
- package/dist/runtime/hooks/stop_drive.js +0 -0
- package/dist/runtime/hooks/stop_stream.js +0 -0
- package/dist/runtime/hooks/subagent_guard.js +0 -0
- package/dist/runtime/hooks/transcript.js +0 -0
- package/dist/runtime/hooks/transcript_tasks.js +0 -0
- package/dist/runtime/ralph/orchestrator.d.ts.map +1 -1
- package/dist/runtime/ralph/orchestrator.js +2 -1
- package/dist/runtime/ralph/orchestrator.js.map +1 -1
- package/dist/setup/cli/limits_state.d.ts.map +1 -1
- package/dist/setup/cli/limits_state.js +6 -40
- package/dist/setup/cli/limits_state.js.map +1 -1
- package/dist/setup/cli/pack_walk.d.ts +32 -0
- package/dist/setup/cli/pack_walk.d.ts.map +1 -0
- package/dist/setup/cli/pack_walk.js +76 -0
- package/dist/setup/cli/pack_walk.js.map +1 -0
- package/dist/setup/cli/permissions_state.d.ts.map +1 -1
- package/dist/setup/cli/permissions_state.js +6 -37
- package/dist/setup/cli/permissions_state.js.map +1 -1
- package/dist/setup/cli/triggers_state.d.ts.map +1 -1
- package/dist/setup/cli/triggers_state.js +3 -29
- package/dist/setup/cli/triggers_state.js.map +1 -1
- package/dist/workgraph/events.d.ts.map +1 -1
- package/dist/workgraph/events.js +10 -0
- package/dist/workgraph/events.js.map +1 -1
- package/dist/workgraph/store.d.ts.map +1 -1
- package/dist/workgraph/store.js +5 -0
- package/dist/workgraph/store.js.map +1 -1
- package/dist/workgraph/types.d.ts +2 -1
- package/dist/workgraph/types.d.ts.map +1 -1
- package/docs/ARCHITECTURE.md +268 -0
- package/package.json +5 -3
- package/packs/builtin/coding-flow/skills/entry-and-handoffs/skill.yaml +13 -17
- package/dist/anti-drift/evaluator.d.ts +0 -88
- package/dist/anti-drift/evaluator.d.ts.map +0 -1
- package/dist/anti-drift/evaluator.js +0 -417
- package/dist/anti-drift/evaluator.js.map +0 -1
- package/dist/anti-drift/evaluator.test.js +0 -78
- package/dist/anti-drift/rules.d.ts +0 -80
- package/dist/anti-drift/rules.d.ts.map +0 -1
- package/dist/anti-drift/rules.js +0 -368
- package/dist/anti-drift/rules.js.map +0 -1
- package/dist/anti-drift/rules.test.js +0 -213
- package/dist/anti-drift/state.d.ts +0 -107
- package/dist/anti-drift/state.d.ts.map +0 -1
- package/dist/anti-drift/state.js +0 -177
- package/dist/anti-drift/state.js.map +0 -1
- package/dist/anti-drift/state.test.js +0 -120
- package/dist/chat/adapters/discord.d.ts +0 -41
- package/dist/chat/adapters/discord.d.ts.map +0 -1
- package/dist/chat/adapters/discord.js +0 -176
- package/dist/chat/adapters/discord.js.map +0 -1
- package/dist/chat/adapters/discord.test.js +0 -25
- package/dist/chat/adapters/slack.d.ts +0 -43
- package/dist/chat/adapters/slack.d.ts.map +0 -1
- package/dist/chat/adapters/slack.js +0 -172
- package/dist/chat/adapters/slack.js.map +0 -1
- package/dist/chat/adapters/slack.test.js +0 -30
- package/dist/chat/adapters/telegram.d.ts +0 -148
- package/dist/chat/adapters/telegram.d.ts.map +0 -1
- package/dist/chat/adapters/telegram.js +0 -498
- package/dist/chat/adapters/telegram.js.map +0 -1
- package/dist/chat/adapters/telegram.test.js +0 -94
- package/dist/chat/config.d.ts +0 -98
- package/dist/chat/config.d.ts.map +0 -1
- package/dist/chat/config.js +0 -185
- package/dist/chat/config.js.map +0 -1
- package/dist/chat/daemon/active-project.d.ts +0 -17
- package/dist/chat/daemon/active-project.d.ts.map +0 -1
- package/dist/chat/daemon/active-project.js +0 -23
- package/dist/chat/daemon/active-project.js.map +0 -1
- package/dist/chat/daemon/autospawn.d.ts +0 -40
- package/dist/chat/daemon/autospawn.d.ts.map +0 -1
- package/dist/chat/daemon/autospawn.js +0 -129
- package/dist/chat/daemon/autospawn.js.map +0 -1
- package/dist/chat/daemon/autospawn.test.js +0 -112
- package/dist/chat/daemon/cli.d.ts +0 -18
- package/dist/chat/daemon/cli.d.ts.map +0 -1
- package/dist/chat/daemon/cli.js +0 -71
- package/dist/chat/daemon/cli.js.map +0 -1
- package/dist/chat/daemon/collisions.js +0 -384
- package/dist/chat/daemon/health-check.d.ts +0 -69
- package/dist/chat/daemon/health-check.d.ts.map +0 -1
- package/dist/chat/daemon/health-check.js +0 -112
- package/dist/chat/daemon/health-check.js.map +0 -1
- package/dist/chat/daemon/inbox-read.d.ts +0 -35
- package/dist/chat/daemon/inbox-read.d.ts.map +0 -1
- package/dist/chat/daemon/inbox-read.js +0 -75
- package/dist/chat/daemon/inbox-read.js.map +0 -1
- package/dist/chat/daemon/inbox-read.test.js +0 -97
- package/dist/chat/daemon/inbox.d.ts +0 -63
- package/dist/chat/daemon/inbox.d.ts.map +0 -1
- package/dist/chat/daemon/inbox.js +0 -56
- package/dist/chat/daemon/inbox.js.map +0 -1
- package/dist/chat/daemon/inbox.test.js +0 -110
- package/dist/chat/daemon/lifecycle.d.ts +0 -71
- package/dist/chat/daemon/lifecycle.d.ts.map +0 -1
- package/dist/chat/daemon/lifecycle.js +0 -221
- package/dist/chat/daemon/lifecycle.js.map +0 -1
- package/dist/chat/daemon/lifecycle.test.js +0 -163
- package/dist/chat/daemon/protocol.d.ts +0 -107
- package/dist/chat/daemon/protocol.d.ts.map +0 -1
- package/dist/chat/daemon/protocol.js +0 -54
- package/dist/chat/daemon/protocol.js.map +0 -1
- package/dist/chat/daemon/routing.d.ts +0 -140
- package/dist/chat/daemon/routing.d.ts.map +0 -1
- package/dist/chat/daemon/routing.js +0 -198
- package/dist/chat/daemon/routing.js.map +0 -1
- package/dist/chat/daemon/routing.test.js +0 -259
- package/dist/chat/daemon/rpc-client.d.ts +0 -45
- package/dist/chat/daemon/rpc-client.d.ts.map +0 -1
- package/dist/chat/daemon/rpc-client.js +0 -133
- package/dist/chat/daemon/rpc-client.js.map +0 -1
- package/dist/chat/daemon/rpc-server.d.ts +0 -39
- package/dist/chat/daemon/rpc-server.d.ts.map +0 -1
- package/dist/chat/daemon/rpc-server.js +0 -385
- package/dist/chat/daemon/rpc-server.js.map +0 -1
- package/dist/chat/daemon/rpc.test.js +0 -177
- package/dist/chat/daemon/subscribers.js +0 -257
- package/dist/chat/daemon/worker.d.ts +0 -27
- package/dist/chat/daemon/worker.d.ts.map +0 -1
- package/dist/chat/daemon/worker.js +0 -313
- package/dist/chat/daemon/worker.js.map +0 -1
- package/dist/chat/daemon/workspace-topic.js +0 -324
- package/dist/chat/env-token.d.ts +0 -60
- package/dist/chat/env-token.d.ts.map +0 -1
- package/dist/chat/env-token.js +0 -137
- package/dist/chat/env-token.js.map +0 -1
- package/dist/chat/env-token.test.js +0 -160
- package/dist/chat/factory.d.ts +0 -30
- package/dist/chat/factory.d.ts.map +0 -1
- package/dist/chat/factory.js +0 -50
- package/dist/chat/factory.js.map +0 -1
- package/dist/chat/factory.test.js +0 -55
- package/dist/chat/gateway.d.ts +0 -176
- package/dist/chat/gateway.d.ts.map +0 -1
- package/dist/chat/gateway.js +0 -146
- package/dist/chat/gateway.js.map +0 -1
- package/dist/chat/gateway.test.js +0 -192
- package/dist/claude-md.d.ts +0 -39
- package/dist/claude-md.d.ts.map +0 -1
- package/dist/claude-md.js +0 -113
- package/dist/claude-md.js.map +0 -1
- package/dist/claude-md.test.js +0 -91
- package/dist/codex/activate.d.ts +0 -66
- package/dist/codex/activate.d.ts.map +0 -1
- package/dist/codex/activate.js +0 -329
- package/dist/codex/activate.js.map +0 -1
- package/dist/codex/activate.test.js +0 -229
- package/dist/codex/bundled-default/bundled-default.test.js +0 -161
- package/dist/codex/cli-publish.test.js +0 -133
- package/dist/codex/cli.d.ts +0 -35
- package/dist/codex/cli.d.ts.map +0 -1
- package/dist/codex/cli.js +0 -554
- package/dist/codex/cli.js.map +0 -1
- package/dist/codex/cli.test.js +0 -277
- package/dist/codex/import-skill-md.d.ts +0 -53
- package/dist/codex/import-skill-md.d.ts.map +0 -1
- package/dist/codex/import-skill-md.js +0 -236
- package/dist/codex/import-skill-md.js.map +0 -1
- package/dist/codex/import-skill-md.test.js +0 -225
- package/dist/codex/loader.d.ts +0 -27
- package/dist/codex/loader.d.ts.map +0 -1
- package/dist/codex/loader.js +0 -86
- package/dist/codex/loader.js.map +0 -1
- package/dist/codex/loader.test.js +0 -75
- package/dist/codex/parse.d.ts +0 -28
- package/dist/codex/parse.d.ts.map +0 -1
- package/dist/codex/parse.js +0 -309
- package/dist/codex/parse.js.map +0 -1
- package/dist/codex/parse.test.js +0 -241
- package/dist/codex/store.d.ts +0 -87
- package/dist/codex/store.d.ts.map +0 -1
- package/dist/codex/store.js +0 -205
- package/dist/codex/store.js.map +0 -1
- package/dist/codex/store.test.js +0 -242
- package/dist/codex/types.d.ts +0 -398
- package/dist/codex/types.d.ts.map +0 -1
- package/dist/codex/types.js +0 -21
- package/dist/codex/types.js.map +0 -1
- package/dist/config.d.ts +0 -53
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -202
- package/dist/config.js.map +0 -1
- package/dist/config.test.js +0 -117
- package/dist/engine/cli.d.ts +0 -14
- package/dist/engine/cli.d.ts.map +0 -1
- package/dist/engine/cli.js +0 -171
- package/dist/engine/cli.js.map +0 -1
- package/dist/engine/client.d.ts +0 -219
- package/dist/engine/client.d.ts.map +0 -1
- package/dist/engine/client.js +0 -312
- package/dist/engine/client.js.map +0 -1
- package/dist/engine/config.d.ts +0 -62
- package/dist/engine/config.d.ts.map +0 -1
- package/dist/engine/config.js +0 -223
- package/dist/engine/config.js.map +0 -1
- package/dist/engine/index.d.ts +0 -17
- package/dist/engine/index.d.ts.map +0 -1
- package/dist/engine/index.js +0 -16
- package/dist/engine/index.js.map +0 -1
- package/dist/engine/resolver.d.ts +0 -62
- package/dist/engine/resolver.d.ts.map +0 -1
- package/dist/engine/resolver.js +0 -103
- package/dist/engine/resolver.js.map +0 -1
- package/dist/engine/singleton.d.ts +0 -95
- package/dist/engine/singleton.d.ts.map +0 -1
- package/dist/engine/singleton.js +0 -325
- package/dist/engine/singleton.js.map +0 -1
- package/dist/engine/types.d.ts +0 -402
- package/dist/engine/types.d.ts.map +0 -1
- package/dist/engine/types.js +0 -22
- package/dist/engine/types.js.map +0 -1
- package/dist/engine-binary-resolver.js +0 -110
- package/dist/engine-binary-resolver.test.js +0 -61
- package/dist/engine-cli.js +0 -60
- package/dist/engine-client.js +0 -301
- package/dist/engine-client.test.js +0 -118
- package/dist/functions/chain_state.d.ts +0 -51
- package/dist/functions/chain_state.d.ts.map +0 -1
- package/dist/functions/chain_state.js +0 -59
- package/dist/functions/chain_state.js.map +0 -1
- package/dist/hooks/drift-catalog.d.ts +0 -68
- package/dist/hooks/drift-catalog.d.ts.map +0 -1
- package/dist/hooks/drift-catalog.js +0 -184
- package/dist/hooks/drift-catalog.js.map +0 -1
- package/dist/hooks/drift-catalog.test.js +0 -154
- package/dist/hooks/drift-patterns.d.ts +0 -110
- package/dist/hooks/drift-patterns.d.ts.map +0 -1
- package/dist/hooks/drift-patterns.js +0 -289
- package/dist/hooks/drift-patterns.js.map +0 -1
- package/dist/hooks/drift-patterns.test.js +0 -325
- package/dist/hooks/engine-vocab-gate.d.ts +0 -108
- package/dist/hooks/engine-vocab-gate.d.ts.map +0 -1
- package/dist/hooks/engine-vocab-gate.js +0 -225
- package/dist/hooks/engine-vocab-gate.js.map +0 -1
- package/dist/hooks/engine-vocab-gate.test.js +0 -170
- package/dist/hooks/heartbeat.d.ts +0 -107
- package/dist/hooks/heartbeat.d.ts.map +0 -1
- package/dist/hooks/heartbeat.js +0 -316
- package/dist/hooks/heartbeat.js.map +0 -1
- package/dist/hooks/heartbeat.test.js +0 -393
- package/dist/hooks/honesty-ledger-session-scope.test.js +0 -100
- package/dist/hooks/honesty-ledger.d.ts +0 -123
- package/dist/hooks/honesty-ledger.d.ts.map +0 -1
- package/dist/hooks/honesty-ledger.js +0 -226
- package/dist/hooks/honesty-ledger.js.map +0 -1
- package/dist/hooks/honesty-ledger.test.js +0 -466
- package/dist/hooks/inline-report-check.d.ts +0 -63
- package/dist/hooks/inline-report-check.d.ts.map +0 -1
- package/dist/hooks/inline-report-check.js +0 -88
- package/dist/hooks/inline-report-check.js.map +0 -1
- package/dist/hooks/inline-report-check.test.js +0 -96
- package/dist/hooks/pre-tool-use.d.ts +0 -62
- package/dist/hooks/pre-tool-use.d.ts.map +0 -1
- package/dist/hooks/pre-tool-use.js +0 -342
- package/dist/hooks/pre-tool-use.js.map +0 -1
- package/dist/hooks/pre-tool-use.test.js +0 -134
- package/dist/hooks/session-end.d.ts +0 -15
- package/dist/hooks/session-end.d.ts.map +0 -1
- package/dist/hooks/session-end.js +0 -60
- package/dist/hooks/session-end.js.map +0 -1
- package/dist/hooks/session-end.test.js +0 -52
- package/dist/hooks/stop.d.ts +0 -35
- package/dist/hooks/stop.d.ts.map +0 -1
- package/dist/hooks/stop.js +0 -136
- package/dist/hooks/stop.js.map +0 -1
- package/dist/hooks/transcript-active-task.test.js +0 -342
- package/dist/hooks/transcript.d.ts +0 -26
- package/dist/hooks/transcript.d.ts.map +0 -1
- package/dist/hooks/transcript.js +0 -266
- package/dist/hooks/transcript.js.map +0 -1
- package/dist/hooks/transcript.test.js +0 -103
- package/dist/hooks/user-prompt-submit.d.ts +0 -74
- package/dist/hooks/user-prompt-submit.d.ts.map +0 -1
- package/dist/hooks/user-prompt-submit.js +0 -256
- package/dist/hooks/user-prompt-submit.js.map +0 -1
- package/dist/hooks/user-prompt-submit.test.js +0 -118
- package/dist/hooks/versioning-gate.d.ts +0 -101
- package/dist/hooks/versioning-gate.d.ts.map +0 -1
- package/dist/hooks/versioning-gate.js +0 -245
- package/dist/hooks/versioning-gate.js.map +0 -1
- package/dist/hooks/versioning-gate.test.js +0 -368
- package/dist/hooks/workflow-gate.d.ts +0 -64
- package/dist/hooks/workflow-gate.d.ts.map +0 -1
- package/dist/hooks/workflow-gate.js +0 -152
- package/dist/hooks/workflow-gate.js.map +0 -1
- package/dist/hooks/workflow-gate.test.js +0 -197
- package/dist/hooks-cli.d.ts +0 -25
- package/dist/hooks-cli.d.ts.map +0 -1
- package/dist/hooks-cli.js +0 -286
- package/dist/hooks-cli.js.map +0 -1
- package/dist/hooks-cli.test.js +0 -148
- package/dist/origin.d.ts +0 -16
- package/dist/origin.d.ts.map +0 -1
- package/dist/origin.js +0 -92
- package/dist/origin.js.map +0 -1
- package/dist/packs/seed_lessons_ingest.d.ts +0 -30
- package/dist/packs/seed_lessons_ingest.d.ts.map +0 -1
- package/dist/packs/seed_lessons_ingest.js +0 -107
- package/dist/packs/seed_lessons_ingest.js.map +0 -1
- package/dist/project-cli.d.ts +0 -7
- package/dist/project-cli.d.ts.map +0 -1
- package/dist/project-cli.js +0 -145
- package/dist/project-cli.js.map +0 -1
- package/dist/project.d.ts +0 -127
- package/dist/project.d.ts.map +0 -1
- package/dist/project.js +0 -281
- package/dist/project.js.map +0 -1
- package/dist/project.test.js +0 -287
- package/dist/rag/backends/loop_engine.d.ts +0 -61
- package/dist/rag/backends/loop_engine.d.ts.map +0 -1
- package/dist/rag/backends/loop_engine.js +0 -160
- package/dist/rag/backends/loop_engine.js.map +0 -1
- package/dist/recall.d.ts +0 -82
- package/dist/recall.d.ts.map +0 -1
- package/dist/recall.js +0 -81
- package/dist/recall.js.map +0 -1
- package/dist/runtime/agent_bridge/autospawn.d.ts +0 -131
- package/dist/runtime/agent_bridge/autospawn.d.ts.map +0 -1
- package/dist/runtime/agent_bridge/autospawn.js +0 -251
- package/dist/runtime/agent_bridge/autospawn.js.map +0 -1
- package/dist/runtime/chain_state.d.ts +0 -124
- package/dist/runtime/chain_state.d.ts.map +0 -1
- package/dist/runtime/chain_state.js +0 -189
- package/dist/runtime/chain_state.js.map +0 -1
- package/dist/runtime/hooks/permission_decision.d.ts +0 -34
- package/dist/runtime/hooks/permission_decision.d.ts.map +0 -1
- package/dist/runtime/hooks/permission_decision.js +0 -39
- package/dist/runtime/hooks/permission_decision.js.map +0 -1
- package/dist/runtime/workflow_fsm.d.ts +0 -21
- package/dist/runtime/workflow_fsm.d.ts.map +0 -1
- package/dist/runtime/workflow_fsm.js +0 -25
- package/dist/runtime/workflow_fsm.js.map +0 -1
- package/dist/runtime/workflow_map.d.ts +0 -26
- package/dist/runtime/workflow_map.d.ts.map +0 -1
- package/dist/runtime/workflow_map.js +0 -38
- package/dist/runtime/workflow_map.js.map +0 -1
- package/dist/scope.d.ts +0 -48
- package/dist/scope.d.ts.map +0 -1
- package/dist/scope.js +0 -111
- package/dist/scope.js.map +0 -1
- package/dist/setup/cli/topic_create_step.d.ts +0 -84
- package/dist/setup/cli/topic_create_step.d.ts.map +0 -1
- package/dist/setup/cli/topic_create_step.js +0 -213
- package/dist/setup/cli/topic_create_step.js.map +0 -1
- package/dist/system-export.d.ts +0 -65
- package/dist/system-export.d.ts.map +0 -1
- package/dist/system-export.js +0 -194
- package/dist/system-export.js.map +0 -1
- package/dist/utterance/classifier.d.ts +0 -53
- package/dist/utterance/classifier.d.ts.map +0 -1
- package/dist/utterance/classifier.js +0 -184
- package/dist/utterance/classifier.js.map +0 -1
- package/dist/utterance/classifier.test.js +0 -147
package/dist/chat/config.d.ts
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Chat-connection configuration loaded from
|
|
3
|
-
* `~/.opensquid/config.json` `chat_connections` block. Per-platform
|
|
4
|
-
* blocks are independent — having one configured doesn't require any
|
|
5
|
-
* of the others.
|
|
6
|
-
*
|
|
7
|
-
* Shape:
|
|
8
|
-
* ```json
|
|
9
|
-
* {
|
|
10
|
-
* "version": 1,
|
|
11
|
-
* "chat_connections": {
|
|
12
|
-
* "telegram": { "bot_token": "...", "allowlist_chat_ids": ["8075471258"] },
|
|
13
|
-
* "discord": { "bot_token": "...", "allowlist_user_ids": ["..."] },
|
|
14
|
-
* "slack": { "bot_token": "xoxb-...", "app_token": "xapp-...", "allowlist_user_ids": ["..."] }
|
|
15
|
-
* }
|
|
16
|
-
* }
|
|
17
|
-
* ```
|
|
18
|
-
*
|
|
19
|
-
* Tokens are stored in cleartext in `config.json`; advise users to
|
|
20
|
-
* `chmod 600 ~/.opensquid/config.json` (the file lives in a hidden
|
|
21
|
-
* dir already, so this is a small additional hardening — not a real
|
|
22
|
-
* defense against a compromised user account).
|
|
23
|
-
*/
|
|
24
|
-
import { type EnvSource } from "./env-token.js";
|
|
25
|
-
import type { ChatPlatform } from "./gateway.js";
|
|
26
|
-
export interface TelegramConfig {
|
|
27
|
-
bot_token: string;
|
|
28
|
-
/**
|
|
29
|
-
* Chat ids the bot will accept messages from. Empty = accept from any
|
|
30
|
-
* chat (NOT recommended — the bot is publicly addressable via Telegram).
|
|
31
|
-
*/
|
|
32
|
-
allowlist_chat_ids?: string[];
|
|
33
|
-
}
|
|
34
|
-
export interface DiscordConfig {
|
|
35
|
-
bot_token: string;
|
|
36
|
-
/** User ids whose DMs / @-mentions the bot will respond to. Empty = bot owner only. */
|
|
37
|
-
allowlist_user_ids?: string[];
|
|
38
|
-
}
|
|
39
|
-
export interface SlackConfig {
|
|
40
|
-
/** Bot User OAuth Token — starts with `xoxb-`. Used for Web API calls. */
|
|
41
|
-
bot_token: string;
|
|
42
|
-
/**
|
|
43
|
-
* App-level Token — starts with `xapp-`. Required for Socket Mode
|
|
44
|
-
* (the no-public-ingress connection style we use).
|
|
45
|
-
*/
|
|
46
|
-
app_token: string;
|
|
47
|
-
/** User ids the bot will respond to. Empty = bot owner only. */
|
|
48
|
-
allowlist_user_ids?: string[];
|
|
49
|
-
}
|
|
50
|
-
export interface ChatConnectionsConfig {
|
|
51
|
-
telegram?: TelegramConfig;
|
|
52
|
-
discord?: DiscordConfig;
|
|
53
|
-
slack?: SlackConfig;
|
|
54
|
-
}
|
|
55
|
-
export declare function loadChatConfig(dataRoot?: string): Promise<ChatConnectionsConfig>;
|
|
56
|
-
export interface ChatTokenSources {
|
|
57
|
-
telegram?: EnvSource;
|
|
58
|
-
discord?: EnvSource;
|
|
59
|
-
slack_bot?: EnvSource;
|
|
60
|
-
slack_app?: EnvSource;
|
|
61
|
-
env_file_path?: string;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Like loadChatConfig but also returns which source each token came
|
|
65
|
-
* from. The chat-daemon uses this to log "[chat-daemon] telegram
|
|
66
|
-
* bot_token source: env-file (~/.loop/.env)" so operators can debug
|
|
67
|
-
* "which bot is this daemon actually using" without exposing the
|
|
68
|
-
* secret.
|
|
69
|
-
*/
|
|
70
|
-
export declare function loadChatConfigWithSources(dataRoot?: string): Promise<{
|
|
71
|
-
config: ChatConnectionsConfig;
|
|
72
|
-
sources: ChatTokenSources;
|
|
73
|
-
}>;
|
|
74
|
-
export declare function saveChatConfig(chat: ChatConnectionsConfig, dataRoot?: string): Promise<void>;
|
|
75
|
-
/**
|
|
76
|
-
* Set a single platform's config block. Convenience for the future
|
|
77
|
-
* `opensquid chat setup <platform>` wizard.
|
|
78
|
-
*/
|
|
79
|
-
export declare function setPlatformConfig<P extends ChatPlatform>(platform: P, config: P extends "telegram" ? TelegramConfig : P extends "discord" ? DiscordConfig : SlackConfig, dataRoot?: string): Promise<void>;
|
|
80
|
-
/**
|
|
81
|
-
* Forget a single platform's config block. Reverts that platform to
|
|
82
|
-
* inactive on the next opensquid restart.
|
|
83
|
-
*/
|
|
84
|
-
export declare function forgetPlatformConfig(platform: ChatPlatform, dataRoot?: string): Promise<void>;
|
|
85
|
-
export interface ConfigValidationIssue {
|
|
86
|
-
platform: ChatPlatform;
|
|
87
|
-
field: string;
|
|
88
|
-
problem: string;
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Surface obvious config errors without trying to validate the token
|
|
92
|
-
* against the live API (that happens on adapter start). Catches
|
|
93
|
-
* empty-string / undefined / shape mistakes before opening a connection.
|
|
94
|
-
*/
|
|
95
|
-
export declare function validateChatConfig(config: ChatConnectionsConfig): ConfigValidationIssue[];
|
|
96
|
-
/** Which platforms have any non-empty config block? */
|
|
97
|
-
export declare function configuredPlatforms(config: ChatConnectionsConfig): ChatPlatform[];
|
|
98
|
-
//# sourceMappingURL=config.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src.legacy/chat/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAKH,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAMjD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,uFAAuF;IACvF,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,WAAW;IAC1B,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAcD,wBAAsB,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAQtF;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1E,MAAM,EAAE,qBAAqB,CAAC;IAC9B,OAAO,EAAE,gBAAgB,CAAC;CAC3B,CAAC,CAGD;AA+CD,wBAAsB,cAAc,CAClC,IAAI,EAAE,qBAAqB,EAC3B,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,SAAS,YAAY,EAC5D,QAAQ,EAAE,CAAC,EACX,MAAM,EAAE,CAAC,SAAS,UAAU,GAAG,cAAc,GAAG,CAAC,SAAS,SAAS,GAAG,aAAa,GAAG,WAAW,EACjG,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAKf;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,YAAY,EACtB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAIf;AAMD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,qBAAqB,GAAG,qBAAqB,EAAE,CAyDzF;AAED,uDAAuD;AACvD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,qBAAqB,GAAG,YAAY,EAAE,CAMjF"}
|
package/dist/chat/config.js
DELETED
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Chat-connection configuration loaded from
|
|
3
|
-
* `~/.opensquid/config.json` `chat_connections` block. Per-platform
|
|
4
|
-
* blocks are independent — having one configured doesn't require any
|
|
5
|
-
* of the others.
|
|
6
|
-
*
|
|
7
|
-
* Shape:
|
|
8
|
-
* ```json
|
|
9
|
-
* {
|
|
10
|
-
* "version": 1,
|
|
11
|
-
* "chat_connections": {
|
|
12
|
-
* "telegram": { "bot_token": "...", "allowlist_chat_ids": ["8075471258"] },
|
|
13
|
-
* "discord": { "bot_token": "...", "allowlist_user_ids": ["..."] },
|
|
14
|
-
* "slack": { "bot_token": "xoxb-...", "app_token": "xapp-...", "allowlist_user_ids": ["..."] }
|
|
15
|
-
* }
|
|
16
|
-
* }
|
|
17
|
-
* ```
|
|
18
|
-
*
|
|
19
|
-
* Tokens are stored in cleartext in `config.json`; advise users to
|
|
20
|
-
* `chmod 600 ~/.opensquid/config.json` (the file lives in a hidden
|
|
21
|
-
* dir already, so this is a small additional hardening — not a real
|
|
22
|
-
* defense against a compromised user account).
|
|
23
|
-
*/
|
|
24
|
-
import { loadConfig, saveConfig } from "../config.js";
|
|
25
|
-
import { resolveToken } from "./env-token.js";
|
|
26
|
-
export async function loadChatConfig(dataRoot) {
|
|
27
|
-
const raw = (await loadConfig(dataRoot));
|
|
28
|
-
// 0.7.5 (#148): overlay env-var + .env tokens atop config.json. Lets
|
|
29
|
-
// the user park a Telegram bot token in ~/.loop/.env so opensquid
|
|
30
|
-
// uses a DIFFERENT bot than Claude Code's plugin:telegram (no 409
|
|
31
|
-
// collision possible — they're different bots). Priority is
|
|
32
|
-
// env > .env > config.json (per resolveToken).
|
|
33
|
-
return overlayEnvTokens(raw.chat_connections ?? {});
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Like loadChatConfig but also returns which source each token came
|
|
37
|
-
* from. The chat-daemon uses this to log "[chat-daemon] telegram
|
|
38
|
-
* bot_token source: env-file (~/.loop/.env)" so operators can debug
|
|
39
|
-
* "which bot is this daemon actually using" without exposing the
|
|
40
|
-
* secret.
|
|
41
|
-
*/
|
|
42
|
-
export async function loadChatConfigWithSources(dataRoot) {
|
|
43
|
-
const raw = (await loadConfig(dataRoot));
|
|
44
|
-
return overlayEnvTokensWithSources(raw.chat_connections ?? {});
|
|
45
|
-
}
|
|
46
|
-
async function overlayEnvTokens(base) {
|
|
47
|
-
const { config } = await overlayEnvTokensWithSources(base);
|
|
48
|
-
return config;
|
|
49
|
-
}
|
|
50
|
-
async function overlayEnvTokensWithSources(base) {
|
|
51
|
-
const out = { ...base };
|
|
52
|
-
const sources = {};
|
|
53
|
-
// Telegram
|
|
54
|
-
const tg = await resolveToken("OPENSQUID_TELEGRAM_BOT_TOKEN", base.telegram?.bot_token);
|
|
55
|
-
if (tg.value) {
|
|
56
|
-
out.telegram = { ...(base.telegram ?? {}), bot_token: tg.value };
|
|
57
|
-
sources.telegram = tg.source;
|
|
58
|
-
if (tg.env_file_path)
|
|
59
|
-
sources.env_file_path = tg.env_file_path;
|
|
60
|
-
}
|
|
61
|
-
// Discord
|
|
62
|
-
const dc = await resolveToken("OPENSQUID_DISCORD_BOT_TOKEN", base.discord?.bot_token);
|
|
63
|
-
if (dc.value) {
|
|
64
|
-
out.discord = { ...(base.discord ?? {}), bot_token: dc.value };
|
|
65
|
-
sources.discord = dc.source;
|
|
66
|
-
if (dc.env_file_path && !sources.env_file_path)
|
|
67
|
-
sources.env_file_path = dc.env_file_path;
|
|
68
|
-
}
|
|
69
|
-
// Slack: needs both bot_token + app_token
|
|
70
|
-
const sb = await resolveToken("OPENSQUID_SLACK_BOT_TOKEN", base.slack?.bot_token);
|
|
71
|
-
const sa = await resolveToken("OPENSQUID_SLACK_APP_TOKEN", base.slack?.app_token);
|
|
72
|
-
if (sb.value || sa.value || base.slack) {
|
|
73
|
-
out.slack = {
|
|
74
|
-
...(base.slack ?? { bot_token: "", app_token: "" }),
|
|
75
|
-
bot_token: sb.value ?? base.slack?.bot_token ?? "",
|
|
76
|
-
app_token: sa.value ?? base.slack?.app_token ?? "",
|
|
77
|
-
};
|
|
78
|
-
sources.slack_bot = sb.source;
|
|
79
|
-
sources.slack_app = sa.source;
|
|
80
|
-
if (sb.env_file_path && !sources.env_file_path)
|
|
81
|
-
sources.env_file_path = sb.env_file_path;
|
|
82
|
-
if (sa.env_file_path && !sources.env_file_path)
|
|
83
|
-
sources.env_file_path = sa.env_file_path;
|
|
84
|
-
}
|
|
85
|
-
return { config: out, sources };
|
|
86
|
-
}
|
|
87
|
-
export async function saveChatConfig(chat, dataRoot) {
|
|
88
|
-
const raw = (await loadConfig(dataRoot));
|
|
89
|
-
raw.chat_connections = chat;
|
|
90
|
-
await saveConfig(raw, dataRoot);
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Set a single platform's config block. Convenience for the future
|
|
94
|
-
* `opensquid chat setup <platform>` wizard.
|
|
95
|
-
*/
|
|
96
|
-
export async function setPlatformConfig(platform, config, dataRoot) {
|
|
97
|
-
const chat = await loadChatConfig(dataRoot);
|
|
98
|
-
// Cast narrows correctly per the conditional type above.
|
|
99
|
-
chat[platform] = config;
|
|
100
|
-
await saveChatConfig(chat, dataRoot);
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Forget a single platform's config block. Reverts that platform to
|
|
104
|
-
* inactive on the next opensquid restart.
|
|
105
|
-
*/
|
|
106
|
-
export async function forgetPlatformConfig(platform, dataRoot) {
|
|
107
|
-
const chat = await loadChatConfig(dataRoot);
|
|
108
|
-
delete chat[platform];
|
|
109
|
-
await saveChatConfig(chat, dataRoot);
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Surface obvious config errors without trying to validate the token
|
|
113
|
-
* against the live API (that happens on adapter start). Catches
|
|
114
|
-
* empty-string / undefined / shape mistakes before opening a connection.
|
|
115
|
-
*/
|
|
116
|
-
export function validateChatConfig(config) {
|
|
117
|
-
const issues = [];
|
|
118
|
-
if (config.telegram) {
|
|
119
|
-
if (!config.telegram.bot_token?.trim()) {
|
|
120
|
-
issues.push({
|
|
121
|
-
platform: "telegram",
|
|
122
|
-
field: "bot_token",
|
|
123
|
-
problem: "empty — get one from @BotFather and run `opensquid chat setup telegram`",
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
else if (!/^\d+:[A-Za-z0-9_-]+$/.test(config.telegram.bot_token)) {
|
|
127
|
-
issues.push({
|
|
128
|
-
platform: "telegram",
|
|
129
|
-
field: "bot_token",
|
|
130
|
-
problem: "wrong format — should look like '123456:ABC-DEF...'",
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
if (config.discord) {
|
|
135
|
-
if (!config.discord.bot_token?.trim()) {
|
|
136
|
-
issues.push({
|
|
137
|
-
platform: "discord",
|
|
138
|
-
field: "bot_token",
|
|
139
|
-
problem: "empty — Discord Developer Portal → Application → Bot → Reset Token",
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
if (config.slack) {
|
|
144
|
-
if (!config.slack.bot_token?.trim()) {
|
|
145
|
-
issues.push({
|
|
146
|
-
platform: "slack",
|
|
147
|
-
field: "bot_token",
|
|
148
|
-
problem: "empty — api.slack.com/apps → OAuth & Permissions → Bot User OAuth Token (xoxb-...)",
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
else if (!config.slack.bot_token.startsWith("xoxb-")) {
|
|
152
|
-
issues.push({
|
|
153
|
-
platform: "slack",
|
|
154
|
-
field: "bot_token",
|
|
155
|
-
problem: "should start with 'xoxb-' (Bot User OAuth Token, not Workspace token)",
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
if (!config.slack.app_token?.trim()) {
|
|
159
|
-
issues.push({
|
|
160
|
-
platform: "slack",
|
|
161
|
-
field: "app_token",
|
|
162
|
-
problem: "empty — required for Socket Mode; api.slack.com/apps → Basic Information → App-Level Tokens (xapp-...)",
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
else if (!config.slack.app_token.startsWith("xapp-")) {
|
|
166
|
-
issues.push({
|
|
167
|
-
platform: "slack",
|
|
168
|
-
field: "app_token",
|
|
169
|
-
problem: "should start with 'xapp-' (App-Level Token, NOT Bot User OAuth Token)",
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
return issues;
|
|
174
|
-
}
|
|
175
|
-
/** Which platforms have any non-empty config block? */
|
|
176
|
-
export function configuredPlatforms(config) {
|
|
177
|
-
const out = [];
|
|
178
|
-
if (config.telegram)
|
|
179
|
-
out.push("telegram");
|
|
180
|
-
if (config.discord)
|
|
181
|
-
out.push("discord");
|
|
182
|
-
if (config.slack)
|
|
183
|
-
out.push("slack");
|
|
184
|
-
return out;
|
|
185
|
-
}
|
package/dist/chat/config.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src.legacy/chat/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Resolve the active project's UUID for chat-routing operations
|
|
3
|
-
* (v0.7.1 Phase E).
|
|
4
|
-
*
|
|
5
|
-
* Strategy:
|
|
6
|
-
* 1. If `OPENSQUID_PROJECT_UUID` env var is set, use it verbatim.
|
|
7
|
-
* 2. Walk up from `cwd` looking for `.opensquid/project.json` and
|
|
8
|
-
* return its uuid.
|
|
9
|
-
* 3. Return null — the caller decides whether to error or fall back
|
|
10
|
-
* to the orphan path.
|
|
11
|
-
*
|
|
12
|
-
* Per-tool fallback: tools that need a project uuid surface a clear
|
|
13
|
-
* error message instead of silently routing to orphan; the user can
|
|
14
|
-
* run `opensquid project init` to create a card if missing.
|
|
15
|
-
*/
|
|
16
|
-
export declare function resolveActiveProjectUuid(cwd?: string): Promise<string | null>;
|
|
17
|
-
//# sourceMappingURL=active-project.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"active-project.d.ts","sourceRoot":"","sources":["../../../src.legacy/chat/daemon/active-project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,wBAAsB,wBAAwB,CAC5C,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIxB"}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Resolve the active project's UUID for chat-routing operations
|
|
3
|
-
* (v0.7.1 Phase E).
|
|
4
|
-
*
|
|
5
|
-
* Strategy:
|
|
6
|
-
* 1. If `OPENSQUID_PROJECT_UUID` env var is set, use it verbatim.
|
|
7
|
-
* 2. Walk up from `cwd` looking for `.opensquid/project.json` and
|
|
8
|
-
* return its uuid.
|
|
9
|
-
* 3. Return null — the caller decides whether to error or fall back
|
|
10
|
-
* to the orphan path.
|
|
11
|
-
*
|
|
12
|
-
* Per-tool fallback: tools that need a project uuid surface a clear
|
|
13
|
-
* error message instead of silently routing to orphan; the user can
|
|
14
|
-
* run `opensquid project init` to create a card if missing.
|
|
15
|
-
*/
|
|
16
|
-
import { findProjectCard } from "../../project.js";
|
|
17
|
-
export async function resolveActiveProjectUuid(cwd = process.cwd()) {
|
|
18
|
-
if (process.env.OPENSQUID_PROJECT_UUID)
|
|
19
|
-
return process.env.OPENSQUID_PROJECT_UUID;
|
|
20
|
-
const found = await findProjectCard(cwd);
|
|
21
|
-
return found?.card.uuid ?? null;
|
|
22
|
-
}
|
|
23
|
-
//# sourceMappingURL=active-project.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"active-project.js","sourceRoot":"","sources":["../../../src.legacy/chat/daemon/active-project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,MAAc,OAAO,CAAC,GAAG,EAAE;IAE3B,IAAI,OAAO,CAAC,GAAG,CAAC,sBAAsB;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;IAClF,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,GAAG,CAAC,CAAC;IACzC,OAAO,KAAK,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;AAClC,CAAC"}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Daemon auto-spawn from MCP server (v0.7.1 Phase D).
|
|
3
|
-
*
|
|
4
|
-
* On MCP server boot, we want to opportunistically ensure the chat-
|
|
5
|
-
* daemon is running so chat_send routes through the daemon (Phase B)
|
|
6
|
-
* and inbound messages land in per-project inboxes (Phase C). Without
|
|
7
|
-
* auto-spawn the user has to remember `opensquid chat-daemon start`
|
|
8
|
-
* once per machine after every reboot, which defeats the
|
|
9
|
-
* "unconscious tool" goal.
|
|
10
|
-
*
|
|
11
|
-
* Behavior:
|
|
12
|
-
* - No-op if no chat_connections configured (no point in a daemon
|
|
13
|
-
* with zero adapters).
|
|
14
|
-
* - No-op if daemon already running.
|
|
15
|
-
* - Otherwise try to acquire an atomic spawn lock (fs.open(lock,
|
|
16
|
-
* 'wx') — EEXIST = another MCP server is spawning). If acquired,
|
|
17
|
-
* spawn and release. If not, wait briefly for the other process's
|
|
18
|
-
* pidfile to appear.
|
|
19
|
-
* - Always async fire-and-forget — never blocks MCP server boot.
|
|
20
|
-
*
|
|
21
|
-
* Stale lock handling: a lockfile older than ~15s is assumed stale
|
|
22
|
-
* (longer than the plausible spawn time) and is unlinked before
|
|
23
|
-
* retry. Prevents permanent jam if a previous spawner crashed.
|
|
24
|
-
*/
|
|
25
|
-
export interface AutoSpawnResult {
|
|
26
|
-
status: "spawned" | "already_running" | "waited_for_peer" | "no_config" | "skipped" | "error";
|
|
27
|
-
pid?: number;
|
|
28
|
-
error?: string;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Best-effort: ensure a chat-daemon is running. Returns immediately
|
|
32
|
-
* on the no-op paths (no config, already running, peer-spawning).
|
|
33
|
-
* Never throws — callers can fire-and-forget without try/catch.
|
|
34
|
-
*/
|
|
35
|
-
export declare function ensureDaemonRunning(opts?: {
|
|
36
|
-
dataRoot?: string;
|
|
37
|
-
/** For tests: override the entrypoint passed to startDaemon. */
|
|
38
|
-
entrypoint?: string;
|
|
39
|
-
}): Promise<AutoSpawnResult>;
|
|
40
|
-
//# sourceMappingURL=autospawn.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"autospawn.d.ts","sourceRoot":"","sources":["../../../src.legacy/chat/daemon/autospawn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAaH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,SAAS,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;IAC9F,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,GAAE;IACJ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAC;CAChB,GACL,OAAO,CAAC,eAAe,CAAC,CAyC1B"}
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Daemon auto-spawn from MCP server (v0.7.1 Phase D).
|
|
3
|
-
*
|
|
4
|
-
* On MCP server boot, we want to opportunistically ensure the chat-
|
|
5
|
-
* daemon is running so chat_send routes through the daemon (Phase B)
|
|
6
|
-
* and inbound messages land in per-project inboxes (Phase C). Without
|
|
7
|
-
* auto-spawn the user has to remember `opensquid chat-daemon start`
|
|
8
|
-
* once per machine after every reboot, which defeats the
|
|
9
|
-
* "unconscious tool" goal.
|
|
10
|
-
*
|
|
11
|
-
* Behavior:
|
|
12
|
-
* - No-op if no chat_connections configured (no point in a daemon
|
|
13
|
-
* with zero adapters).
|
|
14
|
-
* - No-op if daemon already running.
|
|
15
|
-
* - Otherwise try to acquire an atomic spawn lock (fs.open(lock,
|
|
16
|
-
* 'wx') — EEXIST = another MCP server is spawning). If acquired,
|
|
17
|
-
* spawn and release. If not, wait briefly for the other process's
|
|
18
|
-
* pidfile to appear.
|
|
19
|
-
* - Always async fire-and-forget — never blocks MCP server boot.
|
|
20
|
-
*
|
|
21
|
-
* Stale lock handling: a lockfile older than ~15s is assumed stale
|
|
22
|
-
* (longer than the plausible spawn time) and is unlinked before
|
|
23
|
-
* retry. Prevents permanent jam if a previous spawner crashed.
|
|
24
|
-
*/
|
|
25
|
-
import { promises as fs } from "node:fs";
|
|
26
|
-
import * as path from "node:path";
|
|
27
|
-
import { resolveDataRoot } from "../../codex/store.js";
|
|
28
|
-
import { loadChatConfig } from "../config.js";
|
|
29
|
-
import { startDaemon, status } from "./lifecycle.js";
|
|
30
|
-
const STALE_LOCK_AGE_MS = 15_000;
|
|
31
|
-
const PIDFILE_WAIT_MS = 8_000;
|
|
32
|
-
const PIDFILE_POLL_INTERVAL_MS = 100;
|
|
33
|
-
/**
|
|
34
|
-
* Best-effort: ensure a chat-daemon is running. Returns immediately
|
|
35
|
-
* on the no-op paths (no config, already running, peer-spawning).
|
|
36
|
-
* Never throws — callers can fire-and-forget without try/catch.
|
|
37
|
-
*/
|
|
38
|
-
export async function ensureDaemonRunning(opts = {}) {
|
|
39
|
-
try {
|
|
40
|
-
const config = await loadChatConfig(opts.dataRoot);
|
|
41
|
-
if (!config.telegram && !config.discord && !config.slack) {
|
|
42
|
-
return { status: "no_config" };
|
|
43
|
-
}
|
|
44
|
-
const s = await status(opts.dataRoot);
|
|
45
|
-
if (s.running)
|
|
46
|
-
return { status: "already_running", pid: s.pid };
|
|
47
|
-
const lockPath = spawnLockPath(opts.dataRoot);
|
|
48
|
-
const acquired = await tryAcquireLock(lockPath);
|
|
49
|
-
if (acquired) {
|
|
50
|
-
try {
|
|
51
|
-
// Re-check after acquiring the lock; a peer might have
|
|
52
|
-
// finished spawning between our first status() and lock
|
|
53
|
-
// acquisition.
|
|
54
|
-
const s2 = await status(opts.dataRoot);
|
|
55
|
-
if (s2.running)
|
|
56
|
-
return { status: "already_running", pid: s2.pid };
|
|
57
|
-
const res = await startDaemon({
|
|
58
|
-
dataRoot: opts.dataRoot,
|
|
59
|
-
entrypoint: opts.entrypoint,
|
|
60
|
-
});
|
|
61
|
-
return res.already_running
|
|
62
|
-
? { status: "already_running", pid: res.pid }
|
|
63
|
-
: { status: "spawned", pid: res.pid };
|
|
64
|
-
}
|
|
65
|
-
finally {
|
|
66
|
-
await releaseLock(lockPath);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
// Another MCP server has the lock — wait for the pidfile to
|
|
70
|
-
// appear, then trust that daemon.
|
|
71
|
-
const pid = await waitForPeerSpawn(opts.dataRoot);
|
|
72
|
-
if (pid !== null)
|
|
73
|
-
return { status: "waited_for_peer", pid };
|
|
74
|
-
return { status: "error", error: "peer spawn timed out" };
|
|
75
|
-
}
|
|
76
|
-
catch (err) {
|
|
77
|
-
return {
|
|
78
|
-
status: "error",
|
|
79
|
-
error: err instanceof Error ? err.message : String(err),
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
function spawnLockPath(dataRoot) {
|
|
84
|
-
return path.join(resolveDataRoot(dataRoot), "chat-daemon.spawn.lock");
|
|
85
|
-
}
|
|
86
|
-
async function tryAcquireLock(lockPath) {
|
|
87
|
-
await fs.mkdir(path.dirname(lockPath), { recursive: true });
|
|
88
|
-
try {
|
|
89
|
-
const fd = await fs.open(lockPath, "wx");
|
|
90
|
-
await fd.write(`${process.pid}\n`);
|
|
91
|
-
await fd.close();
|
|
92
|
-
return true;
|
|
93
|
-
}
|
|
94
|
-
catch (err) {
|
|
95
|
-
if (err.code !== "EEXIST")
|
|
96
|
-
throw err;
|
|
97
|
-
// Lock exists. Check age — if stale, unlink and retry once.
|
|
98
|
-
try {
|
|
99
|
-
const stat = await fs.stat(lockPath);
|
|
100
|
-
if (Date.now() - stat.mtimeMs > STALE_LOCK_AGE_MS) {
|
|
101
|
-
await fs.unlink(lockPath).catch(() => {
|
|
102
|
-
/* race */
|
|
103
|
-
});
|
|
104
|
-
return tryAcquireLock(lockPath);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
catch {
|
|
108
|
-
/* lock vanished between EEXIST and stat — retry */
|
|
109
|
-
return tryAcquireLock(lockPath);
|
|
110
|
-
}
|
|
111
|
-
return false;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
async function releaseLock(lockPath) {
|
|
115
|
-
await fs.unlink(lockPath).catch(() => {
|
|
116
|
-
/* race-tolerant */
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
async function waitForPeerSpawn(dataRoot) {
|
|
120
|
-
const deadline = Date.now() + PIDFILE_WAIT_MS;
|
|
121
|
-
while (Date.now() < deadline) {
|
|
122
|
-
const s = await status(dataRoot);
|
|
123
|
-
if (s.running)
|
|
124
|
-
return s.pid;
|
|
125
|
-
await new Promise((r) => setTimeout(r, PIDFILE_POLL_INTERVAL_MS));
|
|
126
|
-
}
|
|
127
|
-
return null;
|
|
128
|
-
}
|
|
129
|
-
//# sourceMappingURL=autospawn.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"autospawn.js","sourceRoot":"","sources":["../../../src.legacy/chat/daemon/autospawn.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* autospawn.test.ts (v0.7.1 Phase D) — exercises ensureDaemonRunning
|
|
3
|
-
* decision branches against real tmpdirs. Uses the real lifecycle
|
|
4
|
-
* primitives so the spawn behavior is end-to-end realistic.
|
|
5
|
-
*/
|
|
6
|
-
import { promises as fs } from "node:fs";
|
|
7
|
-
import * as os from "node:os";
|
|
8
|
-
import * as path from "node:path";
|
|
9
|
-
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
10
|
-
import { ensureDaemonRunning } from "./autospawn.js";
|
|
11
|
-
import { saveChatConfig } from "../config.js";
|
|
12
|
-
import { stopDaemon } from "./lifecycle.js";
|
|
13
|
-
// Resolve to the built dist/index.js so the spawned worker runs the
|
|
14
|
-
// real chat-daemon-worker subcommand (vitest's runner doesn't have it).
|
|
15
|
-
const REPO_ROOT = path.resolve(__dirname, "../../..");
|
|
16
|
-
const ENTRYPOINT = path.join(REPO_ROOT, "dist", "index.js");
|
|
17
|
-
let tmpRoot;
|
|
18
|
-
let prevHome;
|
|
19
|
-
let prevOsHome;
|
|
20
|
-
beforeEach(async () => {
|
|
21
|
-
tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), "opensquid-autospawn-test-"));
|
|
22
|
-
prevHome = process.env.OPENSQUID_HOME;
|
|
23
|
-
prevOsHome = process.env.HOME;
|
|
24
|
-
process.env.OPENSQUID_HOME = tmpRoot;
|
|
25
|
-
// 0.7.5 (#148): override HOME so the env-token .env candidate paths
|
|
26
|
-
// (~/.loop/.env etc) point at the empty tmpdir, not the real home
|
|
27
|
-
// where a user-saved .env would synthesize a telegram config and
|
|
28
|
-
// turn what should be `no_config` into `spawned`.
|
|
29
|
-
process.env.HOME = tmpRoot;
|
|
30
|
-
});
|
|
31
|
-
afterEach(async () => {
|
|
32
|
-
// Best-effort stop any daemon left behind by a failing test.
|
|
33
|
-
try {
|
|
34
|
-
await stopDaemon({ dataRoot: tmpRoot });
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
37
|
-
/* ignore */
|
|
38
|
-
}
|
|
39
|
-
if (prevHome === undefined)
|
|
40
|
-
delete process.env.OPENSQUID_HOME;
|
|
41
|
-
else
|
|
42
|
-
process.env.OPENSQUID_HOME = prevHome;
|
|
43
|
-
if (prevOsHome === undefined)
|
|
44
|
-
delete process.env.HOME;
|
|
45
|
-
else
|
|
46
|
-
process.env.HOME = prevOsHome;
|
|
47
|
-
await fs.rm(tmpRoot, { recursive: true, force: true });
|
|
48
|
-
});
|
|
49
|
-
describe("ensureDaemonRunning — decision branches", () => {
|
|
50
|
-
it("returns no_config when chat_connections is empty", async () => {
|
|
51
|
-
const res = await ensureDaemonRunning({ dataRoot: tmpRoot, entrypoint: ENTRYPOINT });
|
|
52
|
-
expect(res.status).toBe("no_config");
|
|
53
|
-
});
|
|
54
|
-
// The spawn-success path requires a real Telegram bot token (or the
|
|
55
|
-
// adapter start fails and the worker exits — autospawn correctly
|
|
56
|
-
// reports "error"). The full spawn path is already covered by
|
|
57
|
-
// lifecycle.test.ts (empty config → worker parks idle → spawn
|
|
58
|
-
// succeeds without network) and by manual end-to-end smoke. Here
|
|
59
|
-
// we exercise the autospawn-specific behaviors that DON'T require
|
|
60
|
-
// a real token: lock release, stale-lock cleanup, and decision
|
|
61
|
-
// logic with no config.
|
|
62
|
-
it("releases the spawn lock after the attempt (regardless of spawn outcome)", async () => {
|
|
63
|
-
await saveChatConfig({ telegram: { bot_token: "1234:fake-token-for-test-only-no-network" } }, tmpRoot);
|
|
64
|
-
await ensureDaemonRunning({ dataRoot: tmpRoot, entrypoint: ENTRYPOINT });
|
|
65
|
-
const lockPath = path.join(tmpRoot, "chat-daemon.spawn.lock");
|
|
66
|
-
const lockExists = await fs
|
|
67
|
-
.access(lockPath)
|
|
68
|
-
.then(() => true)
|
|
69
|
-
.catch(() => false);
|
|
70
|
-
expect(lockExists).toBe(false);
|
|
71
|
-
}, 15000);
|
|
72
|
-
it("clears a stale spawn lock (older than threshold) and re-attempts", async () => {
|
|
73
|
-
await saveChatConfig({ telegram: { bot_token: "1234:fake-token-for-test-only-no-network" } }, tmpRoot);
|
|
74
|
-
// Create an aged lockfile by writing it then back-dating its mtime.
|
|
75
|
-
const lockPath = path.join(tmpRoot, "chat-daemon.spawn.lock");
|
|
76
|
-
await fs.writeFile(lockPath, "stale\n");
|
|
77
|
-
const ancient = new Date(Date.now() - 60_000);
|
|
78
|
-
await fs.utimes(lockPath, ancient, ancient);
|
|
79
|
-
const res = await ensureDaemonRunning({ dataRoot: tmpRoot, entrypoint: ENTRYPOINT });
|
|
80
|
-
// Regardless of spawn success (depends on whether the fake token
|
|
81
|
-
// is accepted), the stale lock should be gone afterwards.
|
|
82
|
-
const stillExists = await fs
|
|
83
|
-
.access(lockPath)
|
|
84
|
-
.then(() => true)
|
|
85
|
-
.catch(() => false);
|
|
86
|
-
expect(stillExists).toBe(false);
|
|
87
|
-
// Status must be a real decision outcome, not 'no_config'.
|
|
88
|
-
expect(res.status).not.toBe("no_config");
|
|
89
|
-
}, 15000);
|
|
90
|
-
it("returns already_running when called against a manually-started daemon", async () => {
|
|
91
|
-
// No chat config → empty-config daemon parks idle without a network call.
|
|
92
|
-
// We start the daemon ourselves, then call ensureDaemonRunning
|
|
93
|
-
// with config present to force the autospawn check path.
|
|
94
|
-
const { startDaemon } = await import("./lifecycle.js");
|
|
95
|
-
await startDaemon({ dataRoot: tmpRoot, entrypoint: ENTRYPOINT });
|
|
96
|
-
// Configure chat AFTER spawning so the daemon parks without a
|
|
97
|
-
// token (the empty config at spawn time means no adapter starts,
|
|
98
|
-
// but the post-hoc save lets the autospawn check find a config).
|
|
99
|
-
await saveChatConfig({ telegram: { bot_token: "1234:fake-token-for-test-only-no-network" } }, tmpRoot);
|
|
100
|
-
const res = await ensureDaemonRunning({ dataRoot: tmpRoot, entrypoint: ENTRYPOINT });
|
|
101
|
-
expect(res.status).toBe("already_running");
|
|
102
|
-
expect(res.pid).toBeGreaterThan(0);
|
|
103
|
-
}, 15000);
|
|
104
|
-
it("never throws on a corrupt config — surfaces as status:error", async () => {
|
|
105
|
-
// Write a config.json that loadChatConfig will read OK but with no chat
|
|
106
|
-
// blocks. That triggers the no_config path, not an error.
|
|
107
|
-
await fs.writeFile(path.join(tmpRoot, "config.json"), JSON.stringify({ version: 1 }));
|
|
108
|
-
const res = await ensureDaemonRunning({ dataRoot: tmpRoot, entrypoint: ENTRYPOINT });
|
|
109
|
-
// No chat → no_config (not an error).
|
|
110
|
-
expect(res.status).toBe("no_config");
|
|
111
|
-
});
|
|
112
|
-
});
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Chat-daemon CLI dispatch (v0.7.1 Phase A).
|
|
3
|
-
*
|
|
4
|
-
* Two entry shapes:
|
|
5
|
-
* `opensquid chat-daemon {start|stop|status}` — user-facing
|
|
6
|
-
* `opensquid chat-daemon-worker` — internal, never type
|
|
7
|
-
*
|
|
8
|
-
* `start` spawns the worker as a detached child and exits. The worker
|
|
9
|
-
* subcommand IS the long-running daemon — never invoke it manually
|
|
10
|
-
* unless you want to inspect logs in the foreground.
|
|
11
|
-
*/
|
|
12
|
-
export declare function runChatDaemonCli(subcommand: string, argv: string[]): Promise<number>;
|
|
13
|
-
/**
|
|
14
|
-
* Internal worker entrypoint — not for direct user invocation.
|
|
15
|
-
* Called by the detached child spawned by lifecycle.startDaemon().
|
|
16
|
-
*/
|
|
17
|
-
export declare function runChatDaemonWorker(): Promise<never>;
|
|
18
|
-
//# sourceMappingURL=cli.d.ts.map
|