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
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Chat-daemon lifecycle — start / stop / status (v0.7.1 Phase A).
|
|
3
|
-
*
|
|
4
|
-
* The daemon owns the single long-poll connection per chat platform so
|
|
5
|
-
* multiple Claude Code projects sharing the same machine can run their
|
|
6
|
-
* own opensquid MCP servers without colliding on the bot token (Telegram
|
|
7
|
-
* returns 409 Conflict when two consumers long-poll the same token —
|
|
8
|
-
* the v0.7 cause of "last-connected wins" behavior).
|
|
9
|
-
*
|
|
10
|
-
* Lifecycle is single-instance per machine: PID file at
|
|
11
|
-
* ~/.opensquid/chat-daemon.pid, log at ~/.opensquid/chat-daemon.log.
|
|
12
|
-
* A `start` call against a running daemon is a no-op (idempotent);
|
|
13
|
-
* `stop` is also idempotent. `status` is read-only.
|
|
14
|
-
*
|
|
15
|
-
* Outbound RPC (Unix socket) lands in Phase B; routing config + inbox
|
|
16
|
-
* write-out in Phase C; auto-spawn from MCP server in Phase D.
|
|
17
|
-
*/
|
|
18
|
-
import { spawn } from "node:child_process";
|
|
19
|
-
import { promises as fs } from "node:fs";
|
|
20
|
-
import { existsSync } from "node:fs";
|
|
21
|
-
import * as os from "node:os";
|
|
22
|
-
import * as path from "node:path";
|
|
23
|
-
import { resolveDataRoot } from "../../codex/store.js";
|
|
24
|
-
export function daemonPaths(dataRoot) {
|
|
25
|
-
const root = resolveDataRoot(dataRoot);
|
|
26
|
-
return {
|
|
27
|
-
pidFile: path.join(root, "chat-daemon.pid"),
|
|
28
|
-
logFile: path.join(root, "chat-daemon.log"),
|
|
29
|
-
sockFile: path.join(root, "chat-daemon.sock"),
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Read the pidfile and check whether the recorded process is alive.
|
|
34
|
-
* A pidfile that points at a dead pid is treated as not-running (the
|
|
35
|
-
* caller should clean it up if they want; status itself is read-only).
|
|
36
|
-
*/
|
|
37
|
-
export async function status(dataRoot) {
|
|
38
|
-
const paths = daemonPaths(dataRoot);
|
|
39
|
-
if (!existsSync(paths.pidFile))
|
|
40
|
-
return { running: false };
|
|
41
|
-
let raw;
|
|
42
|
-
try {
|
|
43
|
-
raw = await fs.readFile(paths.pidFile, "utf8");
|
|
44
|
-
}
|
|
45
|
-
catch {
|
|
46
|
-
return { running: false };
|
|
47
|
-
}
|
|
48
|
-
const pid = parseInt(raw.trim(), 10);
|
|
49
|
-
if (!Number.isFinite(pid) || pid <= 0)
|
|
50
|
-
return { running: false };
|
|
51
|
-
if (!isProcessAlive(pid))
|
|
52
|
-
return { running: false, stale_pid: pid };
|
|
53
|
-
let uptime_ms = null;
|
|
54
|
-
try {
|
|
55
|
-
const stat = await fs.stat(paths.pidFile);
|
|
56
|
-
uptime_ms = Date.now() - stat.mtimeMs;
|
|
57
|
-
}
|
|
58
|
-
catch {
|
|
59
|
-
/* keep null */
|
|
60
|
-
}
|
|
61
|
-
return { running: true, pid, uptime_ms };
|
|
62
|
-
}
|
|
63
|
-
/** `kill -0 <pid>` portable check — throws ESRCH if dead, EPERM if alive-but-foreign. */
|
|
64
|
-
function isProcessAlive(pid) {
|
|
65
|
-
try {
|
|
66
|
-
process.kill(pid, 0);
|
|
67
|
-
return true;
|
|
68
|
-
}
|
|
69
|
-
catch (err) {
|
|
70
|
-
const code = err.code;
|
|
71
|
-
return code === "EPERM"; // alive but owned by another user (still counts)
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Start the daemon by spawning a detached child that runs
|
|
76
|
-
* `node dist/index.js chat-daemon-worker` (the actual long-poll loop
|
|
77
|
-
* lives in worker.ts). Returns immediately once the child has either
|
|
78
|
-
* forked successfully or failed.
|
|
79
|
-
*
|
|
80
|
-
* Idempotent: a start against an already-running daemon returns
|
|
81
|
-
* `{ already_running: true, pid }` without launching a second process.
|
|
82
|
-
*
|
|
83
|
-
* Stale pidfile handling: if the pidfile points at a dead pid, it's
|
|
84
|
-
* silently removed so this call can succeed.
|
|
85
|
-
*/
|
|
86
|
-
export async function startDaemon(options = {}) {
|
|
87
|
-
const cur = await status(options.dataRoot);
|
|
88
|
-
if (cur.running)
|
|
89
|
-
return { already_running: true, pid: cur.pid };
|
|
90
|
-
const paths = daemonPaths(options.dataRoot);
|
|
91
|
-
if (cur.stale_pid !== undefined) {
|
|
92
|
-
await fs.unlink(paths.pidFile).catch(() => {
|
|
93
|
-
/* race-tolerant */
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
// The log file is opened append-mode by both the parent (header
|
|
97
|
-
// line) and the child (stdout/stderr). fs.open with 'a' is atomic
|
|
98
|
-
// append on POSIX, which is what we want here — no race between
|
|
99
|
-
// start runs.
|
|
100
|
-
await fs.mkdir(path.dirname(paths.logFile), { recursive: true });
|
|
101
|
-
const logFd = await fs.open(paths.logFile, "a");
|
|
102
|
-
try {
|
|
103
|
-
await logFd.write(`\n=== chat-daemon start @ ${new Date().toISOString()} ===\n` +
|
|
104
|
-
`host=${os.hostname()} node=${process.version} platform=${process.platform}\n`);
|
|
105
|
-
}
|
|
106
|
-
finally {
|
|
107
|
-
await logFd.close();
|
|
108
|
-
}
|
|
109
|
-
// Reopen the log file for the child's stdio. spawn() wants raw FDs,
|
|
110
|
-
// not FileHandles, so we open via the sync API.
|
|
111
|
-
const fsSync = await import("node:fs");
|
|
112
|
-
const childLogFd = fsSync.openSync(paths.logFile, "a");
|
|
113
|
-
const nodeBin = options.nodeBin ?? process.execPath;
|
|
114
|
-
const entrypoint = options.entrypoint ?? defaultEntrypoint();
|
|
115
|
-
// Pass dataRoot through to the worker via OPENSQUID_HOME so the
|
|
116
|
-
// worker's resolveDataRoot() lands in the same tree the parent
|
|
117
|
-
// selected. Tests pass a tmpdir here; production uses the default
|
|
118
|
-
// ~/.opensquid resolution.
|
|
119
|
-
const childEnv = {
|
|
120
|
-
...process.env,
|
|
121
|
-
OPENSQUID_CHAT_DAEMON: "1",
|
|
122
|
-
};
|
|
123
|
-
if (options.dataRoot)
|
|
124
|
-
childEnv.OPENSQUID_HOME = options.dataRoot;
|
|
125
|
-
const child = spawn(nodeBin, [entrypoint, "chat-daemon-worker"], {
|
|
126
|
-
detached: true,
|
|
127
|
-
stdio: ["ignore", childLogFd, childLogFd],
|
|
128
|
-
env: childEnv,
|
|
129
|
-
});
|
|
130
|
-
// unref so the parent (this process) can exit without waiting for the
|
|
131
|
-
// child. The child is now an independent process group leader because
|
|
132
|
-
// of detached:true.
|
|
133
|
-
child.unref();
|
|
134
|
-
fsSync.closeSync(childLogFd);
|
|
135
|
-
if (!child.pid) {
|
|
136
|
-
throw new Error("chat-daemon: spawn returned no pid");
|
|
137
|
-
}
|
|
138
|
-
// The worker writes its OWN pidfile on startup (so the recorded pid
|
|
139
|
-
// is the worker's, not a stale spawn-only value). Wait briefly for
|
|
140
|
-
// the pidfile to appear; if it doesn't, the worker died on startup.
|
|
141
|
-
// The timeout is generous (8s) because a cold-start of `node
|
|
142
|
-
// dist/index.js chat-daemon-worker` with the optional grammy /
|
|
143
|
-
// discord.js / @slack/* SDKs in the import graph can exceed 3s on
|
|
144
|
-
// first invocation. Subsequent starts hit OS file cache and complete
|
|
145
|
-
// in <500ms.
|
|
146
|
-
const workerPid = await waitForPidfile(paths.pidFile, 8000);
|
|
147
|
-
return { already_running: false, pid: workerPid };
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Stop a running daemon by sending SIGTERM, then waiting briefly for
|
|
151
|
-
* the process to exit and the pidfile to disappear. Falls back to
|
|
152
|
-
* SIGKILL after the grace period. Idempotent — a stop against a
|
|
153
|
-
* not-running daemon returns `{ stopped: false }` without error.
|
|
154
|
-
*/
|
|
155
|
-
export async function stopDaemon(options = {}) {
|
|
156
|
-
const cur = await status(options.dataRoot);
|
|
157
|
-
if (!cur.running) {
|
|
158
|
-
// Clean up stale pidfile if present.
|
|
159
|
-
if (cur.stale_pid !== undefined) {
|
|
160
|
-
await fs.unlink(daemonPaths(options.dataRoot).pidFile).catch(() => {
|
|
161
|
-
/* race-tolerant */
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
return { stopped: false };
|
|
165
|
-
}
|
|
166
|
-
const grace = options.graceMs ?? 3000;
|
|
167
|
-
try {
|
|
168
|
-
process.kill(cur.pid, "SIGTERM");
|
|
169
|
-
}
|
|
170
|
-
catch {
|
|
171
|
-
/* already gone */
|
|
172
|
-
}
|
|
173
|
-
const deadline = Date.now() + grace;
|
|
174
|
-
while (Date.now() < deadline) {
|
|
175
|
-
if (!isProcessAlive(cur.pid))
|
|
176
|
-
break;
|
|
177
|
-
await sleep(100);
|
|
178
|
-
}
|
|
179
|
-
if (isProcessAlive(cur.pid)) {
|
|
180
|
-
try {
|
|
181
|
-
process.kill(cur.pid, "SIGKILL");
|
|
182
|
-
}
|
|
183
|
-
catch {
|
|
184
|
-
/* already gone */
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
// Pidfile cleanup is the worker's job on graceful shutdown — but
|
|
188
|
-
// best-effort here for the SIGKILL path.
|
|
189
|
-
await fs.unlink(daemonPaths(options.dataRoot).pidFile).catch(() => {
|
|
190
|
-
/* race-tolerant */
|
|
191
|
-
});
|
|
192
|
-
return { stopped: true, pid: cur.pid };
|
|
193
|
-
}
|
|
194
|
-
function sleep(ms) {
|
|
195
|
-
return new Promise((r) => setTimeout(r, ms));
|
|
196
|
-
}
|
|
197
|
-
async function waitForPidfile(pidFile, timeoutMs) {
|
|
198
|
-
const deadline = Date.now() + timeoutMs;
|
|
199
|
-
while (Date.now() < deadline) {
|
|
200
|
-
try {
|
|
201
|
-
const raw = await fs.readFile(pidFile, "utf8");
|
|
202
|
-
const pid = parseInt(raw.trim(), 10);
|
|
203
|
-
if (Number.isFinite(pid) && pid > 0 && isProcessAlive(pid))
|
|
204
|
-
return pid;
|
|
205
|
-
}
|
|
206
|
-
catch {
|
|
207
|
-
/* not yet written */
|
|
208
|
-
}
|
|
209
|
-
await sleep(50);
|
|
210
|
-
}
|
|
211
|
-
throw new Error(`chat-daemon: worker did not write pidfile within ${timeoutMs}ms`);
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* Find the on-disk path of the running opensquid binary so the child
|
|
215
|
-
* can re-invoke the same module. Defaults to argv[1] (the script Node
|
|
216
|
-
* was invoked with) which is `dist/index.js` for normal usage.
|
|
217
|
-
*/
|
|
218
|
-
function defaultEntrypoint() {
|
|
219
|
-
// process.argv[1] may be a relative path when launched via npx; resolve.
|
|
220
|
-
return path.resolve(process.argv[1] ?? "dist/index.js");
|
|
221
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../../src.legacy/chat/daemon/lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* chat-daemon lifecycle tests (v0.7.1 Phase A).
|
|
3
|
-
*
|
|
4
|
-
* Exercise the start/stop/status surface against REAL detached child
|
|
5
|
-
* processes — the lifecycle logic IS the contract (fork-detach +
|
|
6
|
-
* pidfile + signal handling), so synthetic stubs would prove nothing.
|
|
7
|
-
*
|
|
8
|
-
* Each test uses a tmpdir as the data root so multiple test runs don't
|
|
9
|
-
* collide on the shared ~/.opensquid/chat-daemon.pid path, and so a
|
|
10
|
-
* crashed test doesn't poison a real chat-daemon install.
|
|
11
|
-
*/
|
|
12
|
-
import { promises as fs } from "node:fs";
|
|
13
|
-
import * as os from "node:os";
|
|
14
|
-
import * as path from "node:path";
|
|
15
|
-
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
16
|
-
import { daemonPaths, startDaemon, status, stopDaemon } from "./lifecycle.js";
|
|
17
|
-
// Resolve to a real on-disk dist/index.js so the spawned worker can
|
|
18
|
-
// actually run. Tests assume `npm run build` has been done; vitest's
|
|
19
|
-
// suite runner triggers tsc when the build step is wired upstream.
|
|
20
|
-
const REPO_ROOT = path.resolve(__dirname, "../../..");
|
|
21
|
-
const ENTRYPOINT = path.join(REPO_ROOT, "dist", "index.js");
|
|
22
|
-
let tmpDataRoot;
|
|
23
|
-
beforeEach(async () => {
|
|
24
|
-
tmpDataRoot = await fs.mkdtemp(path.join(os.tmpdir(), "opensquid-daemon-test-"));
|
|
25
|
-
});
|
|
26
|
-
afterEach(async (ctx) => {
|
|
27
|
-
// On failure, dump the log + tmpdir contents before cleanup so we can
|
|
28
|
-
// see what the daemon was up to. Vitest exposes the task state on ctx.
|
|
29
|
-
if (ctx.task.result?.state === "fail") {
|
|
30
|
-
try {
|
|
31
|
-
const entries = await fs.readdir(tmpDataRoot);
|
|
32
|
-
// eslint-disable-next-line no-console
|
|
33
|
-
console.log(`[test debug] ${tmpDataRoot} entries: ${JSON.stringify(entries)}`);
|
|
34
|
-
}
|
|
35
|
-
catch {
|
|
36
|
-
// eslint-disable-next-line no-console
|
|
37
|
-
console.log(`[test debug] tmpDataRoot ${tmpDataRoot} missing`);
|
|
38
|
-
}
|
|
39
|
-
try {
|
|
40
|
-
const log = await fs.readFile(path.join(tmpDataRoot, "chat-daemon.log"), "utf8");
|
|
41
|
-
// eslint-disable-next-line no-console
|
|
42
|
-
console.log(`[test debug] ${tmpDataRoot}/chat-daemon.log:\n${log}`);
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
// eslint-disable-next-line no-console
|
|
46
|
-
console.log(`[test debug] no chat-daemon.log in ${tmpDataRoot}`);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
// Best-effort: stop any daemon that's still running from a failed
|
|
50
|
-
// test, then rm the tmp root.
|
|
51
|
-
try {
|
|
52
|
-
await stopDaemon({ dataRoot: tmpDataRoot });
|
|
53
|
-
}
|
|
54
|
-
catch {
|
|
55
|
-
/* ignore */
|
|
56
|
-
}
|
|
57
|
-
await fs.rm(tmpDataRoot, { recursive: true, force: true });
|
|
58
|
-
});
|
|
59
|
-
function dataRootEnv() {
|
|
60
|
-
return { dataRoot: tmpDataRoot, entrypoint: ENTRYPOINT };
|
|
61
|
-
}
|
|
62
|
-
describe("daemonPaths", () => {
|
|
63
|
-
it("derives pid/log/sock paths from the data root", () => {
|
|
64
|
-
const p = daemonPaths(tmpDataRoot);
|
|
65
|
-
expect(p.pidFile).toBe(path.join(tmpDataRoot, "chat-daemon.pid"));
|
|
66
|
-
expect(p.logFile).toBe(path.join(tmpDataRoot, "chat-daemon.log"));
|
|
67
|
-
expect(p.sockFile).toBe(path.join(tmpDataRoot, "chat-daemon.sock"));
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
describe("status (before any start)", () => {
|
|
71
|
-
it("reports not-running when pidfile is absent", async () => {
|
|
72
|
-
const s = await status(tmpDataRoot);
|
|
73
|
-
expect(s.running).toBe(false);
|
|
74
|
-
expect("stale_pid" in s ? s.stale_pid : undefined).toBeUndefined();
|
|
75
|
-
});
|
|
76
|
-
it("reports stale_pid when pidfile points at a dead pid", async () => {
|
|
77
|
-
// pid 999999 is overwhelmingly unlikely to be a live process.
|
|
78
|
-
const paths = daemonPaths(tmpDataRoot);
|
|
79
|
-
await fs.mkdir(path.dirname(paths.pidFile), { recursive: true });
|
|
80
|
-
await fs.writeFile(paths.pidFile, "999999\n");
|
|
81
|
-
const s = await status(tmpDataRoot);
|
|
82
|
-
expect(s.running).toBe(false);
|
|
83
|
-
expect("stale_pid" in s ? s.stale_pid : undefined).toBe(999999);
|
|
84
|
-
});
|
|
85
|
-
it("reports not-running on a malformed pidfile (not a number)", async () => {
|
|
86
|
-
const paths = daemonPaths(tmpDataRoot);
|
|
87
|
-
await fs.mkdir(path.dirname(paths.pidFile), { recursive: true });
|
|
88
|
-
await fs.writeFile(paths.pidFile, "garbage\n");
|
|
89
|
-
const s = await status(tmpDataRoot);
|
|
90
|
-
expect(s.running).toBe(false);
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
describe("stopDaemon (idempotency)", () => {
|
|
94
|
-
it("returns stopped:false when no daemon is running", async () => {
|
|
95
|
-
const res = await stopDaemon({ dataRoot: tmpDataRoot });
|
|
96
|
-
expect(res.stopped).toBe(false);
|
|
97
|
-
});
|
|
98
|
-
it("cleans up a stale pidfile during stop()", async () => {
|
|
99
|
-
const paths = daemonPaths(tmpDataRoot);
|
|
100
|
-
await fs.mkdir(path.dirname(paths.pidFile), { recursive: true });
|
|
101
|
-
await fs.writeFile(paths.pidFile, "999999\n");
|
|
102
|
-
await stopDaemon({ dataRoot: tmpDataRoot });
|
|
103
|
-
// Pidfile should be gone.
|
|
104
|
-
await expect(fs.access(paths.pidFile)).rejects.toThrow();
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
describe("startDaemon + stopDaemon (end-to-end)", () => {
|
|
108
|
-
it("starts, reports running, then stops cleanly", async () => {
|
|
109
|
-
const env = dataRootEnv();
|
|
110
|
-
const startRes = await startDaemon(env);
|
|
111
|
-
expect(startRes.already_running).toBe(false);
|
|
112
|
-
expect(startRes.pid).toBeGreaterThan(0);
|
|
113
|
-
const s = await status(env.dataRoot);
|
|
114
|
-
expect(s.running).toBe(true);
|
|
115
|
-
if (s.running) {
|
|
116
|
-
expect(s.pid).toBe(startRes.pid);
|
|
117
|
-
}
|
|
118
|
-
const stopRes = await stopDaemon({ dataRoot: env.dataRoot });
|
|
119
|
-
expect(stopRes.stopped).toBe(true);
|
|
120
|
-
expect(stopRes.pid).toBe(startRes.pid);
|
|
121
|
-
// Pidfile cleaned up.
|
|
122
|
-
const after = await status(env.dataRoot);
|
|
123
|
-
expect(after.running).toBe(false);
|
|
124
|
-
}, 15000);
|
|
125
|
-
it("is idempotent: a second start() returns already_running:true with the same pid", async () => {
|
|
126
|
-
const env = dataRootEnv();
|
|
127
|
-
const first = await startDaemon(env);
|
|
128
|
-
expect(first.already_running).toBe(false);
|
|
129
|
-
const second = await startDaemon(env);
|
|
130
|
-
expect(second.already_running).toBe(true);
|
|
131
|
-
expect(second.pid).toBe(first.pid);
|
|
132
|
-
await stopDaemon({ dataRoot: env.dataRoot });
|
|
133
|
-
}, 15000);
|
|
134
|
-
it("writes daemon boot lines to the log file", async () => {
|
|
135
|
-
const env = dataRootEnv();
|
|
136
|
-
await startDaemon(env);
|
|
137
|
-
// Give the worker a beat to emit its boot lines.
|
|
138
|
-
await new Promise((r) => setTimeout(r, 600));
|
|
139
|
-
const log = await fs.readFile(daemonPaths(env.dataRoot).logFile, "utf8");
|
|
140
|
-
expect(log).toContain("=== chat-daemon start @");
|
|
141
|
-
expect(log).toContain("worker booted pid=");
|
|
142
|
-
await stopDaemon({ dataRoot: env.dataRoot });
|
|
143
|
-
}, 15000);
|
|
144
|
-
it("survives a stop on a daemon spawned from a different test (stale handling)", async () => {
|
|
145
|
-
const env = dataRootEnv();
|
|
146
|
-
// First start, then kill the process behind status's back so the
|
|
147
|
-
// pidfile becomes stale. Real-world: daemon crashed.
|
|
148
|
-
const first = await startDaemon(env);
|
|
149
|
-
try {
|
|
150
|
-
process.kill(first.pid, "SIGKILL");
|
|
151
|
-
}
|
|
152
|
-
catch {
|
|
153
|
-
/* race */
|
|
154
|
-
}
|
|
155
|
-
// Wait briefly for the kill to take effect.
|
|
156
|
-
await new Promise((r) => setTimeout(r, 200));
|
|
157
|
-
const s = await status(env.dataRoot);
|
|
158
|
-
expect(s.running).toBe(false);
|
|
159
|
-
// Should NOT throw and should report not-stopped (since it wasn't).
|
|
160
|
-
const stopRes = await stopDaemon({ dataRoot: env.dataRoot });
|
|
161
|
-
expect(stopRes.stopped).toBe(false);
|
|
162
|
-
}, 15000);
|
|
163
|
-
});
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* chat-daemon ↔ MCP server wire protocol (v0.7.1 Phase B).
|
|
3
|
-
*
|
|
4
|
-
* Shape: JSON-RPC 2.0 over newline-delimited JSON. One JSON object per
|
|
5
|
-
* line; both directions use the same framing. Stateless — the daemon
|
|
6
|
-
* doesn't track client connections beyond the lifetime of a single
|
|
7
|
-
* request/response pair.
|
|
8
|
-
*
|
|
9
|
-
* Transport address (set by `daemonPaths().sockFile`):
|
|
10
|
-
* - macOS/Linux: ~/.opensquid/chat-daemon.sock (AF_UNIX)
|
|
11
|
-
* - Windows: \\.\pipe\opensquid-chat-daemon (named pipe)
|
|
12
|
-
* Node's `net.createServer({path})` accepts both shapes transparently;
|
|
13
|
-
* `daemonSockAddress()` below returns the right form for the host OS.
|
|
14
|
-
*
|
|
15
|
-
* Why not gRPC / HTTP / MCP-style stdio? gRPC drags in a 3 MB grpc-js
|
|
16
|
-
* dependency that we already explicitly avoided in the engine's
|
|
17
|
-
* subprocess design. HTTP needs port allocation + firewall coordination.
|
|
18
|
-
* MCP stdio needs a parent-child relationship — but the daemon is
|
|
19
|
-
* grandparent / orphan to the MCP servers (it outlives them). Local
|
|
20
|
-
* socket + JSON-RPC is the smallest correct surface.
|
|
21
|
-
*/
|
|
22
|
-
/** Send a chat message via the daemon's owned adapter. */
|
|
23
|
-
export interface SendParams {
|
|
24
|
-
channel: string;
|
|
25
|
-
text: string;
|
|
26
|
-
replyTo?: string;
|
|
27
|
-
/** Telegram forum topic id (v0.7.2). Ignored by adapters that don't support threading. */
|
|
28
|
-
threadId?: string;
|
|
29
|
-
}
|
|
30
|
-
/** v0.7.2 — Create a Telegram forum topic via the daemon's owned bot. */
|
|
31
|
-
export interface CreateTopicParams {
|
|
32
|
-
platform: "telegram";
|
|
33
|
-
chat_id: string;
|
|
34
|
-
name: string;
|
|
35
|
-
icon_color?: number;
|
|
36
|
-
icon_custom_emoji_id?: string;
|
|
37
|
-
}
|
|
38
|
-
export interface CreateTopicResult {
|
|
39
|
-
message_thread_id: number;
|
|
40
|
-
name: string;
|
|
41
|
-
}
|
|
42
|
-
export interface SendResult {
|
|
43
|
-
ok: boolean;
|
|
44
|
-
platform: string;
|
|
45
|
-
message_id: string;
|
|
46
|
-
delivered_at: string;
|
|
47
|
-
}
|
|
48
|
-
/** List the platforms the daemon currently has active adapters for. */
|
|
49
|
-
export interface ListChannelsParams {
|
|
50
|
-
}
|
|
51
|
-
export interface ListChannelsResult {
|
|
52
|
-
active_platforms: string[];
|
|
53
|
-
uptime_ms: number | null;
|
|
54
|
-
/**
|
|
55
|
-
* 0.7.4 (#147): platforms whose long-poll lost to a 409 Conflict
|
|
56
|
-
* and degraded to outbound-only mode. Surfaced via
|
|
57
|
-
* `chat_daemon_status` so operators can diagnose "where did my
|
|
58
|
-
* inbound message go?"
|
|
59
|
-
*/
|
|
60
|
-
outbound_only_platforms?: string[];
|
|
61
|
-
}
|
|
62
|
-
/** Liveness probe for the auto-spawn path. */
|
|
63
|
-
export interface PingParams {
|
|
64
|
-
}
|
|
65
|
-
export interface PingResult {
|
|
66
|
-
pong: true;
|
|
67
|
-
pid: number;
|
|
68
|
-
version: string;
|
|
69
|
-
}
|
|
70
|
-
export type DaemonMethod = "send" | "list_channels" | "ping" | "create_topic";
|
|
71
|
-
export interface JsonRpcRequest<P = unknown> {
|
|
72
|
-
jsonrpc: "2.0";
|
|
73
|
-
id: number | string;
|
|
74
|
-
method: DaemonMethod;
|
|
75
|
-
params?: P;
|
|
76
|
-
}
|
|
77
|
-
export interface JsonRpcSuccess<R = unknown> {
|
|
78
|
-
jsonrpc: "2.0";
|
|
79
|
-
id: number | string;
|
|
80
|
-
result: R;
|
|
81
|
-
}
|
|
82
|
-
export interface JsonRpcFailure {
|
|
83
|
-
jsonrpc: "2.0";
|
|
84
|
-
id: number | string | null;
|
|
85
|
-
error: {
|
|
86
|
-
code: number;
|
|
87
|
-
message: string;
|
|
88
|
-
data?: unknown;
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
export type JsonRpcResponse<R = unknown> = JsonRpcSuccess<R> | JsonRpcFailure;
|
|
92
|
-
export declare const JSON_RPC_PARSE_ERROR = -32700;
|
|
93
|
-
export declare const JSON_RPC_INVALID_REQUEST = -32600;
|
|
94
|
-
export declare const JSON_RPC_METHOD_NOT_FOUND = -32601;
|
|
95
|
-
export declare const JSON_RPC_INVALID_PARAMS = -32602;
|
|
96
|
-
export declare const JSON_RPC_INTERNAL_ERROR = -32603;
|
|
97
|
-
/**
|
|
98
|
-
* Return the platform-correct socket address for `net.createServer` /
|
|
99
|
-
* `net.connect`. On Unix this is a path on disk; on Windows this is a
|
|
100
|
-
* named-pipe path. Node accepts both behind the same `{path}` API.
|
|
101
|
-
*
|
|
102
|
-
* On Windows we don't actually have a filesystem path to use, so the
|
|
103
|
-
* pidfile name (without the .pid suffix) drives the pipe name to keep
|
|
104
|
-
* dataRoot isolation working across multiple installs.
|
|
105
|
-
*/
|
|
106
|
-
export declare function daemonSockAddress(dataRoot?: string): string;
|
|
107
|
-
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../src.legacy/chat/daemon/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAWH,0DAA0D;AAC1D,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,yEAAyE;AACzE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,UAAU,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IAChC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,uEAAuE;AACvE,MAAM,WAAW,kBAAkB;CAElC;AAED,MAAM,WAAW,kBAAkB;IACjC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB;;;;;OAKG;IACH,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;CACpC;AAED,8CAA8C;AAC9C,MAAM,WAAW,UAAU;CAE1B;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,IAAI,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,eAAe,GAAG,MAAM,GAAG,cAAc,CAAC;AAM9E,MAAM,WAAW,cAAc,CAAC,CAAC,GAAG,OAAO;IACzC,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,CAAC,EAAE,CAAC,CAAC;CACZ;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,GAAG,OAAO;IACzC,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,MAAM,EAAE,CAAC,CAAC;CACX;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC1D;AAED,MAAM,MAAM,eAAe,CAAC,CAAC,GAAG,OAAO,IAAI,cAAc,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC;AAG9E,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAC3C,eAAO,MAAM,wBAAwB,SAAS,CAAC;AAC/C,eAAO,MAAM,yBAAyB,SAAS,CAAC;AAChD,eAAO,MAAM,uBAAuB,SAAS,CAAC;AAC9C,eAAO,MAAM,uBAAuB,SAAS,CAAC;AAM9C;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAW3D"}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* chat-daemon ↔ MCP server wire protocol (v0.7.1 Phase B).
|
|
3
|
-
*
|
|
4
|
-
* Shape: JSON-RPC 2.0 over newline-delimited JSON. One JSON object per
|
|
5
|
-
* line; both directions use the same framing. Stateless — the daemon
|
|
6
|
-
* doesn't track client connections beyond the lifetime of a single
|
|
7
|
-
* request/response pair.
|
|
8
|
-
*
|
|
9
|
-
* Transport address (set by `daemonPaths().sockFile`):
|
|
10
|
-
* - macOS/Linux: ~/.opensquid/chat-daemon.sock (AF_UNIX)
|
|
11
|
-
* - Windows: \\.\pipe\opensquid-chat-daemon (named pipe)
|
|
12
|
-
* Node's `net.createServer({path})` accepts both shapes transparently;
|
|
13
|
-
* `daemonSockAddress()` below returns the right form for the host OS.
|
|
14
|
-
*
|
|
15
|
-
* Why not gRPC / HTTP / MCP-style stdio? gRPC drags in a 3 MB grpc-js
|
|
16
|
-
* dependency that we already explicitly avoided in the engine's
|
|
17
|
-
* subprocess design. HTTP needs port allocation + firewall coordination.
|
|
18
|
-
* MCP stdio needs a parent-child relationship — but the daemon is
|
|
19
|
-
* grandparent / orphan to the MCP servers (it outlives them). Local
|
|
20
|
-
* socket + JSON-RPC is the smallest correct surface.
|
|
21
|
-
*/
|
|
22
|
-
import * as os from "node:os";
|
|
23
|
-
import * as path from "node:path";
|
|
24
|
-
import { daemonPaths } from "./lifecycle.js";
|
|
25
|
-
// Standard JSON-RPC error codes (we use the public-rage subset).
|
|
26
|
-
export const JSON_RPC_PARSE_ERROR = -32700;
|
|
27
|
-
export const JSON_RPC_INVALID_REQUEST = -32600;
|
|
28
|
-
export const JSON_RPC_METHOD_NOT_FOUND = -32601;
|
|
29
|
-
export const JSON_RPC_INVALID_PARAMS = -32602;
|
|
30
|
-
export const JSON_RPC_INTERNAL_ERROR = -32603;
|
|
31
|
-
// ---------------------------------------------------------------------
|
|
32
|
-
// Socket address — cross-platform
|
|
33
|
-
// ---------------------------------------------------------------------
|
|
34
|
-
/**
|
|
35
|
-
* Return the platform-correct socket address for `net.createServer` /
|
|
36
|
-
* `net.connect`. On Unix this is a path on disk; on Windows this is a
|
|
37
|
-
* named-pipe path. Node accepts both behind the same `{path}` API.
|
|
38
|
-
*
|
|
39
|
-
* On Windows we don't actually have a filesystem path to use, so the
|
|
40
|
-
* pidfile name (without the .pid suffix) drives the pipe name to keep
|
|
41
|
-
* dataRoot isolation working across multiple installs.
|
|
42
|
-
*/
|
|
43
|
-
export function daemonSockAddress(dataRoot) {
|
|
44
|
-
const paths = daemonPaths(dataRoot);
|
|
45
|
-
if (os.platform() === "win32") {
|
|
46
|
-
// Windows named pipe — derive a stable name from the data root so
|
|
47
|
-
// tests with tmpdirs and prod with ~/.opensquid don't collide.
|
|
48
|
-
// Pipe names live in a flat namespace; hash the dataRoot to a
|
|
49
|
-
// short suffix.
|
|
50
|
-
const fingerprint = path.basename(path.dirname(paths.sockFile));
|
|
51
|
-
return `\\\\.\\pipe\\opensquid-chat-daemon-${fingerprint}`;
|
|
52
|
-
}
|
|
53
|
-
return paths.sockFile;
|
|
54
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../src.legacy/chat/daemon/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AA2F7C,iEAAiE;AACjE,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,KAAK,CAAC;AAC3C,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,KAAK,CAAC;AAC/C,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,KAAK,CAAC;AAChD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,KAAK,CAAC;AAC9C,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,KAAK,CAAC;AAE9C,wEAAwE;AACxE,kCAAkC;AAClC,wEAAwE;AAExE;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAiB;IACjD,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IACpC,IAAI,EAAE,CAAC,QAAQ,EAAE,KAAK,OAAO,EAAE,CAAC;QAC9B,kEAAkE;QAClE,+DAA+D;QAC/D,8DAA8D;QAC9D,gBAAgB;QAChB,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;QAChE,OAAO,sCAAsC,WAAW,EAAE,CAAC;IAC7D,CAAC;IACD,OAAO,KAAK,CAAC,QAAQ,CAAC;AACxB,CAAC"}
|