@gajae-code/coding-agent 0.14.2 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +120 -1
- package/dist/types/async/job-manager.d.ts +4 -1
- package/dist/types/autoresearch/dashboard.d.ts +29 -4
- package/dist/types/autoresearch/data-context.d.ts +25 -0
- package/dist/types/autoresearch/git.d.ts +65 -7
- package/dist/types/autoresearch/harness.d.ts +58 -0
- package/dist/types/autoresearch/prompts.d.ts +51 -0
- package/dist/types/autoresearch/runs.d.ts +173 -0
- package/dist/types/autoresearch/types.d.ts +9 -139
- package/dist/types/capability/types.d.ts +20 -0
- package/dist/types/cli/accounts-cli.d.ts +1 -0
- package/dist/types/commands/{rlm.d.ts → autoresearch.d.ts} +2 -4
- package/dist/types/config/autorouting-contract.d.ts +146 -0
- package/dist/types/config/autorouting-generator.d.ts +40 -0
- package/dist/types/config/autorouting-tier-map.d.ts +16844 -0
- package/dist/types/config/autorouting.d.ts +35 -0
- package/dist/types/config/model-discovery-manager.d.ts +8 -1
- package/dist/types/config/model-registry.d.ts +30 -1
- package/dist/types/config/provider-selection-policy.d.ts +23 -0
- package/dist/types/config/settings-schema.d.ts +61 -3
- package/dist/types/config/settings.d.ts +3 -0
- package/dist/types/coordinator/contract.d.ts +1 -1
- package/dist/types/coordinator-mcp/durability.d.ts +29 -0
- package/dist/types/coordinator-mcp/event-webhook.d.ts +50 -0
- package/dist/types/coordinator-mcp/question-state.d.ts +1 -1
- package/dist/types/coordinator-mcp/server.d.ts +14 -0
- package/dist/types/crash/index-store.d.ts +3 -0
- package/dist/types/crash/record-loader.d.ts +2 -0
- package/dist/types/crash/upstream/relay.d.ts +5 -3
- package/dist/types/cursor.d.ts +12 -0
- package/dist/types/defaults/gjc-defaults.d.ts +35 -1
- package/dist/types/defaults/gjc-skills.generated.d.ts +1 -1
- package/dist/types/discovery/helpers.d.ts +1 -1
- package/dist/types/edit/index.d.ts +2 -1
- package/dist/types/eval/py/executor.d.ts +2 -0
- package/dist/types/extensibility/extensions/loader.d.ts +32 -0
- package/dist/types/extensibility/gjc-plugins/types.d.ts +1 -1
- package/dist/types/extensibility/skills.d.ts +2 -0
- package/dist/types/gjc-runtime/autoresearch-runtime.d.ts +194 -0
- package/dist/types/gjc-runtime/gc-runtime.d.ts +1 -1
- package/dist/types/gjc-runtime/psmux-detect.d.ts +1 -1
- package/dist/types/gjc-runtime/python-transcript.d.ts +19 -0
- package/dist/types/gjc-runtime/ralplan-runtime.d.ts +2 -8
- package/dist/types/gjc-runtime/session-layout.d.ts +6 -3
- package/dist/types/gjc-runtime/state-renderer.d.ts +0 -22
- package/dist/types/gjc-runtime/state-schema.d.ts +7 -7
- package/dist/types/gjc-runtime/tmux-common.d.ts +2 -2
- package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +38 -1
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +2 -24
- package/dist/types/gjc-runtime/ultragoal-validation-policy.d.ts +73 -0
- package/dist/types/gjc-runtime/workflow-recovery-projection.d.ts +100 -0
- package/dist/types/hooks/skill-keywords.d.ts +1 -1
- package/dist/types/main.d.ts +0 -10
- package/dist/types/modes/acp/acp-agent.d.ts +13 -6
- package/dist/types/modes/components/model-selector.d.ts +14 -0
- package/dist/types/modes/components/skill-hud/render.d.ts +6 -1
- package/dist/types/modes/components/smart-routing-panel.d.ts +82 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +14 -0
- package/dist/types/modes/interactive-mode.d.ts +3 -0
- package/dist/types/modes/types.d.ts +9 -0
- package/dist/types/rlm/artifacts.d.ts +4 -4
- package/dist/types/runtime/optional-runtime-services.d.ts +2 -1
- package/dist/types/runtime/workspace-tree-service.d.ts +5 -1
- package/dist/types/runtime-mcp/config.d.ts +6 -0
- package/dist/types/runtime-mcp/manager.d.ts +10 -0
- package/dist/types/sdk/acp/adapter.d.ts +0 -4
- package/dist/types/sdk/broker/broker.d.ts +1 -1
- package/dist/types/sdk/broker/lifecycle.d.ts +57 -2
- package/dist/types/sdk/broker/session-index.d.ts +15 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +6 -0
- package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +4 -0
- package/dist/types/sdk/bus/index.d.ts +8 -0
- package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +2 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -2
- package/dist/types/sdk/client/client.d.ts +39 -4
- package/dist/types/sdk/host/host.d.ts +1 -0
- package/dist/types/sdk/host/internal-autorouting-state.d.ts +3 -0
- package/dist/types/sdk/host/model-pin.d.ts +29 -0
- package/dist/types/sdk/host/session-runtime.d.ts +2 -1
- package/dist/types/sdk/lifecycle-session.d.ts +13 -0
- package/dist/types/sdk/router/session-router.d.ts +27 -1
- package/dist/types/sdk/session.d.ts +11 -1
- package/dist/types/session/agent-session.d.ts +36 -6
- package/dist/types/session/artifacts.d.ts +16 -1
- package/dist/types/session/internal/managed-session-storage.d.ts +7 -0
- package/dist/types/session/session-manager.d.ts +84 -2
- package/dist/types/session/session-staging-paths.d.ts +3 -0
- package/dist/types/skill-state/canonical-skills.d.ts +1 -1
- package/dist/types/skill-state/workflow-hud.d.ts +12 -21
- package/dist/types/skill-state/workflow-mutation-guard.d.ts +1 -0
- package/dist/types/slash-commands/helpers/autorouting-status.d.ts +8 -0
- package/dist/types/system-prompt.d.ts +23 -0
- package/dist/types/task/executor.d.ts +35 -4
- package/dist/types/task/index.d.ts +17 -3
- package/dist/types/task/receipt.d.ts +3 -1
- package/dist/types/task/types.d.ts +144 -0
- package/dist/types/tools/atomic-file-write.d.ts +72 -0
- package/dist/types/tools/descriptors.d.ts +1 -0
- package/dist/types/tools/index.d.ts +36 -1
- package/dist/types/tools/move-session.d.ts +40 -0
- package/dist/types/tools/python.d.ts +12 -0
- package/dist/types/tools/resource-gc.d.ts +0 -3
- package/dist/types/tools/search.d.ts +8 -1
- package/dist/types/tools/skill.d.ts +9 -4
- package/dist/types/tools/subagent.d.ts +33 -3
- package/dist/types/utils/xml-escape.d.ts +2 -0
- package/dist/types/workflow/workflow-intent-diff.d.ts +2 -2
- package/dist/types/workflow/workflow-intent-report-consumer.d.ts +1 -1
- package/package.json +11 -12
- package/scripts/build-sdk-package-smoke.ts +7 -5
- package/scripts/check-autorouting-tier-map.ts +183 -0
- package/scripts/generate-sdk-operation-inventory.ts +12 -0
- package/scripts/generate-tool-catalog.ts +40 -5
- package/src/async/job-manager.ts +5 -2
- package/src/autoresearch/dashboard.ts +134 -314
- package/src/autoresearch/data-context.ts +35 -0
- package/src/autoresearch/git.ts +186 -26
- package/src/autoresearch/{helpers.ts → harness.ts} +65 -40
- package/src/autoresearch/{prompt-setup.md → prompts/prompt-setup.md} +7 -7
- package/src/autoresearch/prompts/prompt.md +103 -0
- package/src/autoresearch/prompts.ts +126 -0
- package/src/autoresearch/runs.ts +708 -0
- package/src/autoresearch/types.ts +9 -150
- package/src/capability/index.ts +4 -4
- package/src/capability/types.ts +20 -0
- package/src/cli/accounts-cli.ts +21 -5
- package/src/cli/config-cli.ts +25 -1
- package/src/cli/fast-help.ts +1 -2
- package/src/cli/list-models.ts +5 -8
- package/src/cli/setup-cli.ts +8 -0
- package/src/cli.ts +2 -21
- package/src/commands/autoresearch.ts +33 -0
- package/src/commands/coordinator.ts +15 -0
- package/src/commands/launch.ts +2 -4
- package/src/commands/quick-lane.ts +1 -1
- package/src/commands/sdk.ts +24 -0
- package/src/commands/state.ts +1 -1
- package/src/config/autorouting-contract.ts +474 -0
- package/src/config/autorouting-generator.ts +238 -0
- package/src/config/autorouting-tier-map.ts +6108 -0
- package/src/config/autorouting.ts +120 -0
- package/src/config/model-discovery-manager.ts +42 -11
- package/src/config/model-registry.ts +348 -68
- package/src/config/provider-selection-policy.ts +60 -9
- package/src/config/settings-schema.ts +195 -6
- package/src/config/settings.ts +62 -1
- package/src/config.ts +2 -3
- package/src/coordinator/contract.ts +0 -1
- package/src/coordinator-mcp/codex-handoff.ts +68 -42
- package/src/coordinator-mcp/durability.ts +200 -0
- package/src/coordinator-mcp/event-webhook.ts +278 -0
- package/src/coordinator-mcp/question-state.ts +109 -46
- package/src/coordinator-mcp/server.ts +932 -504
- package/src/crash/index-store.ts +126 -22
- package/src/crash/record-loader.ts +7 -0
- package/src/crash/upstream/relay.ts +82 -34
- package/src/cursor.ts +84 -1
- package/src/debug/index.ts +26 -0
- package/src/defaults/gjc/skills/autoresearch/SKILL.md +116 -0
- package/src/defaults/gjc/skills/autoresearch/auto-critic.md +46 -0
- package/src/defaults/gjc/skills/autoresearch/auto-iterate.md +42 -0
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +17 -37
- package/src/defaults/gjc/skills/ralplan/SKILL.md +21 -18
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +6 -17
- package/src/defaults/gjc/skills/ultragoal/ai-slop-cleaner.md +2 -2
- package/src/defaults/gjc-defaults.ts +89 -2
- package/src/defaults/gjc-skills.generated.ts +24 -17
- package/src/discovery/builtin.ts +18 -5
- package/src/discovery/helpers.ts +6 -6
- package/src/edit/index.ts +5 -2
- package/src/eval/py/executor.ts +8 -0
- package/src/extensibility/extensions/loader.ts +135 -13
- package/src/extensibility/extensions/wrapper.ts +1 -2
- package/src/extensibility/gjc-plugins/schema.ts +1 -1
- package/src/extensibility/runtime-skill-discovery.ts +2 -2
- package/src/extensibility/skill-management.ts +2 -3
- package/src/extensibility/skills.ts +16 -8
- package/src/gjc-runtime/autoresearch-runtime.ts +1509 -0
- package/src/gjc-runtime/gc-render.ts +0 -1
- package/src/gjc-runtime/gc-runtime.ts +1 -11
- package/src/gjc-runtime/launch-tmux.ts +3 -3
- package/src/gjc-runtime/psmux-detect.ts +2 -2
- package/src/gjc-runtime/python-transcript.ts +58 -0
- package/src/gjc-runtime/ralplan-runtime.ts +6 -18
- package/src/gjc-runtime/session-layout.ts +18 -7
- package/src/gjc-runtime/session-state-sidecar.ts +58 -9
- package/src/gjc-runtime/state-renderer.ts +0 -38
- package/src/gjc-runtime/state-runtime.ts +43 -22
- package/src/gjc-runtime/state-schema.ts +1 -1
- package/src/gjc-runtime/tmux-common.ts +7 -7
- package/src/gjc-runtime/ultragoal-change-set.ts +232 -11
- package/src/gjc-runtime/ultragoal-runtime.ts +309 -114
- package/src/gjc-runtime/ultragoal-validation-policy.ts +247 -0
- package/src/gjc-runtime/workflow-command-ref.ts +15 -11
- package/src/gjc-runtime/workflow-manifest.generated.json +413 -532
- package/src/gjc-runtime/workflow-manifest.ts +43 -83
- package/src/gjc-runtime/workflow-recovery-projection.ts +616 -0
- package/src/hooks/skill-keywords.ts +3 -3
- package/src/hooks/skill-state.ts +2 -2
- package/src/internal-urls/docs-index.generated.ts +26 -24
- package/src/lsp/index.ts +25 -5
- package/src/main.ts +2 -27
- package/src/modes/acp/acp-agent.ts +200 -75
- package/src/modes/components/model-selector.ts +216 -13
- package/src/modes/components/oauth-selector.ts +5 -5
- package/src/modes/components/skill-hud/render.ts +173 -35
- package/src/modes/components/smart-routing-panel.ts +531 -0
- package/src/modes/components/tool-status-header.ts +6 -3
- package/src/modes/controllers/command-controller.ts +17 -7
- package/src/modes/controllers/input-controller.ts +44 -9
- package/src/modes/controllers/runtime-mcp-command-controller.ts +4 -0
- package/src/modes/controllers/selector-controller.ts +298 -65
- package/src/modes/interactive-mode.ts +8 -1
- package/src/modes/shared/agent-wire/workflow-gate-types.ts +1 -1
- package/src/modes/types.ts +9 -1
- package/src/prompts/agents/planner.md +1 -1
- package/src/prompts/system/system-prompt.md +1 -1
- package/src/prompts/system/volatile-project-context.md +2 -1
- package/src/prompts/tools/move-session.md +15 -0
- package/src/prompts/tools/python.md +12 -0
- package/src/prompts/tools/skill-discovery.md +1 -1
- package/src/prompts/tools/skill.md +2 -2
- package/src/prompts/tools/task-summary.md +1 -0
- package/src/prompts/tools/task.md +6 -0
- package/src/rlm/artifacts.ts +12 -10
- package/src/runtime/optional-runtime-services.ts +3 -2
- package/src/runtime/workspace-tree-service.ts +11 -3
- package/src/runtime-mcp/config.ts +8 -1
- package/src/runtime-mcp/manager.ts +33 -0
- package/src/sdk/acp/adapter.ts +48 -1
- package/src/sdk/broker/broker.ts +30 -2
- package/src/sdk/broker/discovery.ts +217 -2
- package/src/sdk/broker/lifecycle.ts +385 -59
- package/src/sdk/broker/session-index.ts +243 -48
- package/src/sdk/broker/transport.ts +1 -0
- package/src/sdk/bus/chat-daemon-control.ts +8 -2
- package/src/sdk/bus/chat-daemon-runtime.ts +5 -0
- package/src/sdk/bus/index.ts +208 -11
- package/src/sdk/bus/kind-aware-reconciliation.ts +16 -0
- package/src/sdk/bus/reconciliation-store.ts +27 -5
- package/src/sdk/bus/telegram-daemon-contract.ts +12 -2
- package/src/sdk/client/client.ts +204 -22
- package/src/sdk/host/host.ts +16 -0
- package/src/sdk/host/internal-autorouting-state.ts +13 -0
- package/src/sdk/host/model-pin.ts +101 -0
- package/src/sdk/host/reverse-leases.ts +2 -1
- package/src/sdk/host/session-runtime.test.ts +224 -1
- package/src/sdk/host/session-runtime.ts +125 -37
- package/src/sdk/lifecycle/service.ts +3 -1
- package/src/sdk/lifecycle-session.ts +42 -1
- package/src/sdk/protocol/operation-inventory.generated.json +66 -0
- package/src/sdk/router/session-router.ts +375 -36
- package/src/sdk/session.ts +547 -47
- package/src/session/account-inventory.ts +1 -1
- package/src/session/agent-session.ts +765 -189
- package/src/session/artifacts.ts +234 -4
- package/src/session/internal/managed-session-storage.ts +91 -4
- package/src/session/provider-safety-stop-hint.ts +3 -2
- package/src/session/session-manager.ts +775 -16
- package/src/session/session-staging-paths.ts +8 -0
- package/src/setup/hermes/templates/operator-instructions.v1.md +0 -1
- package/src/setup/host-plugin-setup.ts +2 -2
- package/src/skill-state/active-state.ts +2 -2
- package/src/skill-state/canonical-skills.ts +1 -1
- package/src/skill-state/initial-phase.ts +1 -1
- package/src/skill-state/workflow-hud.ts +41 -41
- package/src/skill-state/workflow-mutation-guard.ts +26 -7
- package/src/slash-commands/builtin-registry.ts +77 -0
- package/src/slash-commands/helpers/autorouting-status.ts +55 -0
- package/src/system-prompt.ts +102 -5
- package/src/task/discovery.ts +2 -3
- package/src/task/executor.ts +617 -43
- package/src/task/index.ts +262 -15
- package/src/task/receipt.ts +30 -0
- package/src/task/render.ts +11 -1
- package/src/task/types.ts +316 -0
- package/src/tools/atomic-file-write.ts +594 -0
- package/src/tools/bisect.ts +3 -2
- package/src/tools/descriptors.test.ts +3 -0
- package/src/tools/descriptors.ts +24 -0
- package/src/tools/image-gen.ts +5 -1
- package/src/tools/index.ts +62 -5
- package/src/tools/move-session.ts +107 -0
- package/src/tools/python.ts +205 -0
- package/src/tools/read.ts +88 -15
- package/src/tools/renderers.ts +2 -0
- package/src/tools/resource-gc.ts +8 -177
- package/src/tools/search.ts +30 -6
- package/src/tools/skill-discovery.ts +1 -0
- package/src/tools/skill.ts +37 -7
- package/src/tools/subagent-render.ts +119 -13
- package/src/tools/subagent.ts +91 -74
- package/src/tools/tool-catalog.generated.ts +64 -2
- package/src/tools/write.ts +16 -12
- package/src/utils/xml-escape.ts +14 -0
- package/src/web/search/providers/codex.ts +2 -2
- package/src/workflow/workflow-intent-diff.ts +13 -12
- package/src/workflow/workflow-intent-report-consumer.ts +6 -6
- package/dist/types/autoresearch/helpers.d.ts +0 -24
- package/dist/types/autoresearch/index.d.ts +0 -2
- package/dist/types/autoresearch/state.d.ts +0 -17
- package/dist/types/autoresearch/storage.d.ts +0 -142
- package/dist/types/autoresearch/tools/init-experiment.d.ts +0 -31
- package/dist/types/autoresearch/tools/log-experiment.d.ts +0 -23
- package/dist/types/autoresearch/tools/run-experiment.d.ts +0 -8
- package/dist/types/autoresearch/tools/update-notes.d.ts +0 -12
- package/dist/types/commands/team.d.ts +0 -24
- package/dist/types/gjc-runtime/team-gc.d.ts +0 -7
- package/dist/types/gjc-runtime/team-launch.d.ts +0 -61
- package/dist/types/gjc-runtime/team-notify.d.ts +0 -45
- package/dist/types/gjc-runtime/team-runtime.d.ts +0 -336
- package/dist/types/gjc-runtime/team-store.d.ts +0 -168
- package/dist/types/gjc-runtime/team-worker-heartbeat.d.ts +0 -43
- package/dist/types/gjc-runtime/team-worker-memory-guard.d.ts +0 -92
- package/dist/types/gjc-runtime/team-workers.d.ts +0 -83
- package/dist/types/rlm/index.d.ts +0 -47
- package/dist/types/rlm/preset.d.ts +0 -23
- package/dist/types/rlm/python-tool.d.ts +0 -16
- package/src/autoresearch/command-resume.md +0 -14
- package/src/autoresearch/index.ts +0 -536
- package/src/autoresearch/prompt.md +0 -103
- package/src/autoresearch/resume-message.md +0 -10
- package/src/autoresearch/state.ts +0 -273
- package/src/autoresearch/storage.ts +0 -699
- package/src/autoresearch/tools/init-experiment.ts +0 -272
- package/src/autoresearch/tools/log-experiment.ts +0 -524
- package/src/autoresearch/tools/run-experiment.ts +0 -475
- package/src/autoresearch/tools/update-notes.ts +0 -109
- package/src/commands/rlm.ts +0 -19
- package/src/commands/team.ts +0 -238
- package/src/defaults/gjc/skills/deep-interview/auto-research-greenfield.md +0 -42
- package/src/defaults/gjc/skills/team/SKILL.md +0 -467
- package/src/gjc-runtime/team-gc.ts +0 -49
- package/src/gjc-runtime/team-launch.ts +0 -404
- package/src/gjc-runtime/team-notify.ts +0 -326
- package/src/gjc-runtime/team-runtime.ts +0 -5923
- package/src/gjc-runtime/team-store.ts +0 -878
- package/src/gjc-runtime/team-worker-heartbeat.ts +0 -149
- package/src/gjc-runtime/team-worker-memory-guard.ts +0 -363
- package/src/gjc-runtime/team-workers.ts +0 -1123
- package/src/prompts/system/rlm-report-command.md +0 -1
- package/src/prompts/system/rlm-research.md +0 -23
- package/src/rlm/index.ts +0 -365
- package/src/rlm/preset.ts +0 -76
- package/src/rlm/python-tool.ts +0 -68
|
@@ -2,6 +2,12 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import * as fs from "node:fs/promises";
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import { withFileLock } from "../config/file-lock";
|
|
5
|
+
import {
|
|
6
|
+
appendCoordinatorFile,
|
|
7
|
+
ensureCoordinatorDirectory,
|
|
8
|
+
syncCoordinatorDirectory,
|
|
9
|
+
writeCoordinatorAtomic,
|
|
10
|
+
} from "./durability";
|
|
5
11
|
import type { PrivateAskGateCodecV1, PublicReason } from "./question-gate-codec";
|
|
6
12
|
|
|
7
13
|
export type CoordinatorSessionState =
|
|
@@ -183,6 +189,9 @@ export interface OutboxEventV1 {
|
|
|
183
189
|
payload: Record<string, string | number | boolean | null>;
|
|
184
190
|
emitted: boolean;
|
|
185
191
|
}
|
|
192
|
+
function isOutboxEntity(value: unknown): value is OutboxEventV1["entity"] {
|
|
193
|
+
return value === "turn" || value === "question" || value === "report" || value === "session" || value === "deletion";
|
|
194
|
+
}
|
|
186
195
|
export interface CoordinatorSessionTransactionV1 {
|
|
187
196
|
schema_version: 1;
|
|
188
197
|
namespace_id: string;
|
|
@@ -234,7 +243,7 @@ export type CanonicalCreateIntentV1 =
|
|
|
234
243
|
}
|
|
235
244
|
| {
|
|
236
245
|
kind: "delegate";
|
|
237
|
-
workflow: "plan" | "execute"
|
|
246
|
+
workflow: "plan" | "execute";
|
|
238
247
|
session: CanonicalSessionSnapshotV1;
|
|
239
248
|
remote_create_key: string;
|
|
240
249
|
initial_state: CoordinatorSessionState;
|
|
@@ -310,37 +319,38 @@ export function transactionPath(paths: CoordinatorStatePaths, sessionId: string)
|
|
|
310
319
|
export function transactionLockPath(paths: CoordinatorStatePaths, sessionId: string): string {
|
|
311
320
|
return path.join(paths.sessions, safeSessionId(sessionId), "transaction.lock");
|
|
312
321
|
}
|
|
313
|
-
async function fsyncDirectory(directory: string): Promise<void> {
|
|
314
|
-
const handle = await fs.open(directory, "r");
|
|
315
|
-
try {
|
|
316
|
-
await handle.sync();
|
|
317
|
-
} finally {
|
|
318
|
-
await handle.close();
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
322
|
async function ensureNamespaceParents(paths: CoordinatorStatePaths): Promise<void> {
|
|
322
|
-
await
|
|
323
|
+
await ensureCoordinatorDirectory(paths.root);
|
|
323
324
|
}
|
|
324
325
|
|
|
325
|
-
async function
|
|
326
|
-
await fs.mkdir(path.dirname(file), { recursive: true, mode: 0o700 });
|
|
327
|
-
const temp = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
328
|
-
const handle = await fs.open(temp, "wx", 0o600);
|
|
326
|
+
async function removeCoordinatorStateFile(file: string): Promise<void> {
|
|
329
327
|
try {
|
|
330
|
-
await
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
328
|
+
await fs.lstat(file);
|
|
329
|
+
} catch (error) {
|
|
330
|
+
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
|
|
331
|
+
try {
|
|
332
|
+
await fs.stat(path.dirname(file));
|
|
333
|
+
} catch (parentError) {
|
|
334
|
+
if ((parentError as NodeJS.ErrnoException).code === "ENOENT") return;
|
|
335
|
+
throw parentError;
|
|
336
|
+
}
|
|
337
|
+
await syncCoordinatorDirectory(path.dirname(file));
|
|
338
|
+
return;
|
|
334
339
|
}
|
|
335
|
-
await fs.
|
|
336
|
-
await
|
|
340
|
+
await fs.rm(file);
|
|
341
|
+
await syncCoordinatorDirectory(path.dirname(file));
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
async function writeAtomic(file: string, value: unknown): Promise<void> {
|
|
345
|
+
await writeCoordinatorAtomic(file, JSON.stringify(value));
|
|
337
346
|
}
|
|
338
347
|
async function readJson<T>(file: string): Promise<T | null> {
|
|
339
348
|
try {
|
|
340
349
|
return JSON.parse(await fs.readFile(file, "utf8")) as T;
|
|
341
350
|
} catch (error) {
|
|
342
351
|
if ((error as NodeJS.ErrnoException).code === "ENOENT") return null;
|
|
343
|
-
throw new Error("state_corrupt");
|
|
352
|
+
if (error instanceof SyntaxError) throw new Error("state_corrupt");
|
|
353
|
+
throw error;
|
|
344
354
|
}
|
|
345
355
|
}
|
|
346
356
|
function assertTransaction(transaction: CoordinatorSessionTransactionV1, namespaceId: string, sessionId: string): void {
|
|
@@ -356,8 +366,8 @@ function assertTransaction(transaction: CoordinatorSessionTransactionV1, namespa
|
|
|
356
366
|
}
|
|
357
367
|
export async function initializeCoordinatorNamespace(paths: CoordinatorStatePaths): Promise<void> {
|
|
358
368
|
await ensureNamespaceParents(paths);
|
|
359
|
-
await
|
|
360
|
-
await
|
|
369
|
+
await ensureCoordinatorDirectory(paths.sessions);
|
|
370
|
+
await ensureCoordinatorDirectory(path.dirname(paths.journal));
|
|
361
371
|
await withFileLock(paths.registryLock, async () => {
|
|
362
372
|
const existing = await readJson<NamespaceRegistryV1>(paths.registry);
|
|
363
373
|
if (existing === null)
|
|
@@ -391,7 +401,7 @@ export async function withSessionTransaction<T>(
|
|
|
391
401
|
operation: (transaction: CoordinatorSessionTransactionV1) => Promise<T>,
|
|
392
402
|
): Promise<T> {
|
|
393
403
|
const file = transactionPath(paths, sessionId);
|
|
394
|
-
await
|
|
404
|
+
await ensureCoordinatorDirectory(path.dirname(file));
|
|
395
405
|
return await withFileLock(transactionLockPath(paths, sessionId), async () => {
|
|
396
406
|
const transaction = await readJson<CoordinatorSessionTransactionV1>(file);
|
|
397
407
|
if (!transaction) throw new Error("resource_gone");
|
|
@@ -504,7 +514,7 @@ export async function commitCreationWal(
|
|
|
504
514
|
entry.phase === "completed",
|
|
505
515
|
);
|
|
506
516
|
if (!priorDeleted) throw new Error("session_closing");
|
|
507
|
-
await
|
|
517
|
+
await removeCoordinatorStateFile(transactionPath(paths, session.session_id));
|
|
508
518
|
existing = null;
|
|
509
519
|
}
|
|
510
520
|
if (existing) {
|
|
@@ -648,34 +658,87 @@ export async function appendOutboxEvents(
|
|
|
648
658
|
paths: CoordinatorStatePaths,
|
|
649
659
|
transaction: CoordinatorSessionTransactionV1,
|
|
650
660
|
): Promise<void> {
|
|
651
|
-
await
|
|
661
|
+
await ensureCoordinatorDirectory(path.dirname(paths.journal));
|
|
652
662
|
await withFileLock(paths.journalLock, async () => {
|
|
653
663
|
const existing = await fs.readFile(paths.journal, "utf8").catch(error => {
|
|
654
664
|
if ((error as NodeJS.ErrnoException).code === "ENOENT") return "";
|
|
655
665
|
throw error;
|
|
656
666
|
});
|
|
657
|
-
const
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
try {
|
|
663
|
-
return (JSON.parse(line) as { id?: unknown }).id;
|
|
664
|
-
} catch {
|
|
665
|
-
return null;
|
|
666
|
-
}
|
|
667
|
-
})
|
|
668
|
-
.filter((id): id is string => typeof id === "string"),
|
|
669
|
-
);
|
|
670
|
-
const events = Object.values(transaction.outbox).filter(event => !event.emitted && !ids.has(event.id));
|
|
671
|
-
if (events.length > 0) {
|
|
672
|
-
const handle = await fs.open(paths.journal, "a", 0o600);
|
|
667
|
+
const existingEvents = new Map<string, OutboxEventV1>();
|
|
668
|
+
for (const rawLine of existing.split("\n")) {
|
|
669
|
+
const line = rawLine.trim();
|
|
670
|
+
if (!line) continue;
|
|
671
|
+
let parsed: unknown;
|
|
673
672
|
try {
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
await handle.close();
|
|
673
|
+
parsed = JSON.parse(line);
|
|
674
|
+
} catch {
|
|
675
|
+
throw new Error("state_corrupt");
|
|
678
676
|
}
|
|
677
|
+
const candidate = parsed as Partial<OutboxEventV1>;
|
|
678
|
+
const identity = typeof candidate.id === "string" ? candidate.id.split(":") : [];
|
|
679
|
+
const identityRevision = identity.length >= 6 ? Number(identity[2]) : Number.NaN;
|
|
680
|
+
const identityEntity = identity.length >= 6 ? identity[4] : undefined;
|
|
681
|
+
const identityEntityId = identity.length >= 6 ? identity.slice(5).join(":") : "";
|
|
682
|
+
const identitySession = identity.length >= 6 ? identity[1] : "";
|
|
683
|
+
const identityKind = identity.length >= 6 ? identity[3] : "";
|
|
684
|
+
const canonicalIdentity =
|
|
685
|
+
identity.length >= 6 &&
|
|
686
|
+
identity[0] === "txn" &&
|
|
687
|
+
identitySession &&
|
|
688
|
+
Number.isSafeInteger(identityRevision) &&
|
|
689
|
+
identityRevision > 0 &&
|
|
690
|
+
identityKind &&
|
|
691
|
+
isOutboxEntity(identityEntity) &&
|
|
692
|
+
identityEntityId &&
|
|
693
|
+
candidate.id ===
|
|
694
|
+
deterministicOutboxId(identitySession, identityRevision, identityKind, identityEntity, identityEntityId);
|
|
695
|
+
if (
|
|
696
|
+
typeof parsed !== "object" ||
|
|
697
|
+
parsed === null ||
|
|
698
|
+
Array.isArray(parsed) ||
|
|
699
|
+
typeof candidate.id !== "string" ||
|
|
700
|
+
candidate.id.length === 0 ||
|
|
701
|
+
typeof candidate.transaction_revision !== "number" ||
|
|
702
|
+
!Number.isSafeInteger(candidate.transaction_revision) ||
|
|
703
|
+
candidate.transaction_revision <= 0 ||
|
|
704
|
+
typeof candidate.kind !== "string" ||
|
|
705
|
+
!candidate.kind ||
|
|
706
|
+
!isOutboxEntity(candidate.entity) ||
|
|
707
|
+
typeof candidate.entity_id !== "string" ||
|
|
708
|
+
!candidate.entity_id ||
|
|
709
|
+
typeof candidate.payload !== "object" ||
|
|
710
|
+
candidate.payload === null ||
|
|
711
|
+
Array.isArray(candidate.payload) ||
|
|
712
|
+
typeof candidate.emitted !== "boolean" ||
|
|
713
|
+
!canonicalIdentity ||
|
|
714
|
+
candidate.transaction_revision !== identityRevision ||
|
|
715
|
+
existingEvents.has(candidate.id)
|
|
716
|
+
)
|
|
717
|
+
throw new Error("state_corrupt");
|
|
718
|
+
existingEvents.set(candidate.id, candidate as OutboxEventV1);
|
|
719
|
+
}
|
|
720
|
+
for (const event of Object.values(transaction.outbox)) {
|
|
721
|
+
if (
|
|
722
|
+
event.id !==
|
|
723
|
+
deterministicOutboxId(
|
|
724
|
+
transaction.session_id,
|
|
725
|
+
event.transaction_revision,
|
|
726
|
+
event.kind,
|
|
727
|
+
event.entity,
|
|
728
|
+
event.entity_id,
|
|
729
|
+
)
|
|
730
|
+
)
|
|
731
|
+
throw new Error("state_corrupt");
|
|
732
|
+
}
|
|
733
|
+
const events = Object.values(transaction.outbox).filter(event => {
|
|
734
|
+
if (event.emitted) return false;
|
|
735
|
+
const existing = existingEvents.get(event.id);
|
|
736
|
+
if (!existing) return true;
|
|
737
|
+
if (JSON.stringify(existing) !== JSON.stringify(event)) throw new Error("state_corrupt");
|
|
738
|
+
return false;
|
|
739
|
+
});
|
|
740
|
+
if (events.length > 0) {
|
|
741
|
+
await appendCoordinatorFile(paths.journal, `${events.map(event => JSON.stringify(event)).join("\n")}\n`);
|
|
679
742
|
}
|
|
680
743
|
for (const event of Object.values(transaction.outbox)) event.emitted = true;
|
|
681
744
|
transaction.projection.applied_events_revision = transaction.revision;
|