@mcoda/mswarm 0.1.134 → 0.1.135-codali.2

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.
Files changed (248) hide show
  1. package/README.md +40 -0
  2. package/dist/codali-executor.d.ts +63 -0
  3. package/dist/codali-executor.d.ts.map +1 -1
  4. package/dist/codali-executor.js +78 -8
  5. package/dist/codali-executor.js.map +1 -1
  6. package/dist/invocation-token.d.ts.map +1 -1
  7. package/dist/invocation-token.js +1 -0
  8. package/dist/invocation-token.js.map +1 -1
  9. package/dist/native-reasoning.d.ts +8 -0
  10. package/dist/native-reasoning.d.ts.map +1 -0
  11. package/dist/native-reasoning.js +18 -0
  12. package/dist/native-reasoning.js.map +1 -0
  13. package/dist/runtime.d.ts +23 -1
  14. package/dist/runtime.d.ts.map +1 -1
  15. package/dist/runtime.js +181 -15
  16. package/dist/runtime.js.map +1 -1
  17. package/dist/server.d.ts +3 -1
  18. package/dist/server.d.ts.map +1 -1
  19. package/dist/server.js +58 -8
  20. package/dist/server.js.map +1 -1
  21. package/dist/vendor/codali/agents/RoleResolution.d.ts.map +1 -1
  22. package/dist/vendor/codali/agents/RoleResolution.js +4 -4
  23. package/dist/vendor/codali/api/CodaliApi.d.ts +16 -0
  24. package/dist/vendor/codali/api/CodaliApi.d.ts.map +1 -1
  25. package/dist/vendor/codali/api/CodaliApi.js +39 -10
  26. package/dist/vendor/codali/cli/AskCommand.d.ts +3 -0
  27. package/dist/vendor/codali/cli/AskCommand.d.ts.map +1 -1
  28. package/dist/vendor/codali/cli/AskCommand.js +76 -13
  29. package/dist/vendor/codali/cli/RunCommand.d.ts +4 -0
  30. package/dist/vendor/codali/cli/RunCommand.d.ts.map +1 -1
  31. package/dist/vendor/codali/cli/RunCommand.js +110 -24
  32. package/dist/vendor/codali/cli/TerminalCommand.d.ts +35 -0
  33. package/dist/vendor/codali/cli/TerminalCommand.d.ts.map +1 -0
  34. package/dist/vendor/codali/cli/TerminalCommand.js +616 -0
  35. package/dist/vendor/codali/cli/TerminalCredentials.d.ts +3 -0
  36. package/dist/vendor/codali/cli/TerminalCredentials.d.ts.map +1 -0
  37. package/dist/vendor/codali/cli/TerminalCredentials.js +89 -0
  38. package/dist/vendor/codali/cli/TerminalInput.d.ts +24 -0
  39. package/dist/vendor/codali/cli/TerminalInput.d.ts.map +1 -0
  40. package/dist/vendor/codali/cli/TerminalInput.js +98 -0
  41. package/dist/vendor/codali/cli/TerminalText.d.ts +10 -0
  42. package/dist/vendor/codali/cli/TerminalText.d.ts.map +1 -0
  43. package/dist/vendor/codali/cli/TerminalText.js +53 -0
  44. package/dist/vendor/codali/cli.d.ts.map +1 -1
  45. package/dist/vendor/codali/cli.js +33 -4
  46. package/dist/vendor/codali/cognitive/ConfiguredPipeline.d.ts +34 -0
  47. package/dist/vendor/codali/cognitive/ConfiguredPipeline.d.ts.map +1 -0
  48. package/dist/vendor/codali/cognitive/ConfiguredPipeline.js +50 -0
  49. package/dist/vendor/codali/cognitive/ValidationRunner.d.ts +4 -0
  50. package/dist/vendor/codali/cognitive/ValidationRunner.d.ts.map +1 -1
  51. package/dist/vendor/codali/cognitive/ValidationRunner.js +18 -41
  52. package/dist/vendor/codali/config/NodeOrchestration.d.ts +21 -0
  53. package/dist/vendor/codali/config/NodeOrchestration.d.ts.map +1 -0
  54. package/dist/vendor/codali/config/NodeOrchestration.js +54 -0
  55. package/dist/vendor/codali/config/OrchestrationConfig.d.ts +100 -0
  56. package/dist/vendor/codali/config/OrchestrationConfig.d.ts.map +1 -0
  57. package/dist/vendor/codali/config/OrchestrationConfig.js +245 -0
  58. package/dist/vendor/codali/connectors/mcp/McpClient.d.ts +3 -1
  59. package/dist/vendor/codali/connectors/mcp/McpClient.d.ts.map +1 -1
  60. package/dist/vendor/codali/connectors/mcp/McpClient.js +3 -2
  61. package/dist/vendor/codali/connectors/mcp/McpServerRegistry.d.ts +2 -2
  62. package/dist/vendor/codali/connectors/mcp/McpServerRegistry.d.ts.map +1 -1
  63. package/dist/vendor/codali/connectors/mcp/McpServerRegistry.js +39 -16
  64. package/dist/vendor/codali/connectors/mcp/McpToolAdapter.js +2 -2
  65. package/dist/vendor/codali/connectors/media/ConfiguredMediaTools.d.ts +6 -0
  66. package/dist/vendor/codali/connectors/media/ConfiguredMediaTools.d.ts.map +1 -0
  67. package/dist/vendor/codali/connectors/media/ConfiguredMediaTools.js +41 -0
  68. package/dist/vendor/codali/connectors/media/ImageGenerationTool.js +3 -3
  69. package/dist/vendor/codali/connectors/media/MediaArtifactReceipt.d.ts +5 -0
  70. package/dist/vendor/codali/connectors/media/MediaArtifactReceipt.d.ts.map +1 -0
  71. package/dist/vendor/codali/connectors/media/MediaArtifactReceipt.js +65 -0
  72. package/dist/vendor/codali/connectors/media/MediaJobStore.d.ts +68 -0
  73. package/dist/vendor/codali/connectors/media/MediaJobStore.d.ts.map +1 -0
  74. package/dist/vendor/codali/connectors/media/MediaJobStore.js +199 -0
  75. package/dist/vendor/codali/connectors/media/MediaJobWorker.d.ts +2 -0
  76. package/dist/vendor/codali/connectors/media/MediaJobWorker.d.ts.map +1 -0
  77. package/dist/vendor/codali/connectors/media/MediaJobWorker.js +65 -0
  78. package/dist/vendor/codali/connectors/media/RemoteMediaJob.d.ts +6 -0
  79. package/dist/vendor/codali/connectors/media/RemoteMediaJob.d.ts.map +1 -0
  80. package/dist/vendor/codali/connectors/media/RemoteMediaJob.js +80 -0
  81. package/dist/vendor/codali/docdex/DocdexClient.d.ts +18 -1
  82. package/dist/vendor/codali/docdex/DocdexClient.d.ts.map +1 -1
  83. package/dist/vendor/codali/docdex/DocdexClient.js +135 -19
  84. package/dist/vendor/codali/docdex/ManagedDocdex.d.ts +29 -0
  85. package/dist/vendor/codali/docdex/ManagedDocdex.d.ts.map +1 -0
  86. package/dist/vendor/codali/docdex/ManagedDocdex.js +215 -0
  87. package/dist/vendor/codali/docdex/ManagedRuntime.d.ts +28 -0
  88. package/dist/vendor/codali/docdex/ManagedRuntime.d.ts.map +1 -0
  89. package/dist/vendor/codali/docdex/ManagedRuntime.js +212 -0
  90. package/dist/vendor/codali/eval/EvaluationProcess.d.ts +13 -0
  91. package/dist/vendor/codali/eval/EvaluationProcess.d.ts.map +1 -0
  92. package/dist/vendor/codali/eval/EvaluationProcess.js +76 -0
  93. package/dist/vendor/codali/eval/LongWorkflowJourney.d.ts +34 -0
  94. package/dist/vendor/codali/eval/LongWorkflowJourney.d.ts.map +1 -0
  95. package/dist/vendor/codali/eval/LongWorkflowJourney.js +243 -0
  96. package/dist/vendor/codali/eval/PlanningCorpus.d.ts +45 -0
  97. package/dist/vendor/codali/eval/PlanningCorpus.d.ts.map +1 -0
  98. package/dist/vendor/codali/eval/PlanningCorpus.js +189 -0
  99. package/dist/vendor/codali/eval/PlanningCorpusRunner.d.ts +13 -0
  100. package/dist/vendor/codali/eval/PlanningCorpusRunner.d.ts.map +1 -0
  101. package/dist/vendor/codali/eval/PlanningCorpusRunner.js +89 -0
  102. package/dist/vendor/codali/eval/TerminalCorpusRunner.d.ts +36 -0
  103. package/dist/vendor/codali/eval/TerminalCorpusRunner.d.ts.map +1 -0
  104. package/dist/vendor/codali/eval/TerminalCorpusRunner.js +222 -0
  105. package/dist/vendor/codali/eval/TerminalTaskCorpus.d.ts +26 -0
  106. package/dist/vendor/codali/eval/TerminalTaskCorpus.d.ts.map +1 -0
  107. package/dist/vendor/codali/eval/TerminalTaskCorpus.js +105 -0
  108. package/dist/vendor/codali/eval/TerminalWorkflowCorpus.d.ts +11 -0
  109. package/dist/vendor/codali/eval/TerminalWorkflowCorpus.d.ts.map +1 -0
  110. package/dist/vendor/codali/eval/TerminalWorkflowCorpus.js +116 -0
  111. package/dist/vendor/codali/eval/fixtures/TerminalRecoveryJourney.d.ts +4 -0
  112. package/dist/vendor/codali/eval/fixtures/TerminalRecoveryJourney.d.ts.map +1 -0
  113. package/dist/vendor/codali/eval/fixtures/TerminalRecoveryJourney.js +132 -0
  114. package/dist/vendor/codali/gateway/CodaliGateway.d.ts +2 -0
  115. package/dist/vendor/codali/gateway/CodaliGateway.d.ts.map +1 -1
  116. package/dist/vendor/codali/gateway/CodaliGateway.js +11 -1
  117. package/dist/vendor/codali/gateway/ConfiguredGateway.d.ts +23 -0
  118. package/dist/vendor/codali/gateway/ConfiguredGateway.d.ts.map +1 -0
  119. package/dist/vendor/codali/gateway/ConfiguredGateway.js +44 -0
  120. package/dist/vendor/codali/gateway/GatewayTracer.d.ts +1 -1
  121. package/dist/vendor/codali/gateway/GatewayTracer.d.ts.map +1 -1
  122. package/dist/vendor/codali/gateway/GatewayTracer.js +2 -27
  123. package/dist/vendor/codali/index.d.ts +23 -0
  124. package/dist/vendor/codali/index.d.ts.map +1 -1
  125. package/dist/vendor/codali/index.js +12 -0
  126. package/dist/vendor/codali/permissions/PermissionGate.d.ts +44 -0
  127. package/dist/vendor/codali/permissions/PermissionGate.d.ts.map +1 -0
  128. package/dist/vendor/codali/permissions/PermissionGate.js +97 -0
  129. package/dist/vendor/codali/providers/ConfiguredEmbeddings.d.ts +43 -0
  130. package/dist/vendor/codali/providers/ConfiguredEmbeddings.d.ts.map +1 -0
  131. package/dist/vendor/codali/providers/ConfiguredEmbeddings.js +87 -0
  132. package/dist/vendor/codali/providers/ConfiguredModelScope.d.ts +69 -0
  133. package/dist/vendor/codali/providers/ConfiguredModelScope.d.ts.map +1 -0
  134. package/dist/vendor/codali/providers/ConfiguredModelScope.js +113 -0
  135. package/dist/vendor/codali/providers/ConfiguredProvider.d.ts +79 -0
  136. package/dist/vendor/codali/providers/ConfiguredProvider.d.ts.map +1 -0
  137. package/dist/vendor/codali/providers/ConfiguredProvider.js +238 -0
  138. package/dist/vendor/codali/providers/ModelServiceError.d.ts +10 -0
  139. package/dist/vendor/codali/providers/ModelServiceError.d.ts.map +1 -0
  140. package/dist/vendor/codali/providers/ModelServiceError.js +45 -0
  141. package/dist/vendor/codali/providers/MswarmWorkerProvider.d.ts.map +1 -1
  142. package/dist/vendor/codali/providers/MswarmWorkerProvider.js +4 -0
  143. package/dist/vendor/codali/providers/OpenAiCompatibleProvider.d.ts.map +1 -1
  144. package/dist/vendor/codali/providers/OpenAiCompatibleProvider.js +91 -50
  145. package/dist/vendor/codali/providers/ProviderTypes.d.ts +12 -0
  146. package/dist/vendor/codali/providers/ProviderTypes.d.ts.map +1 -1
  147. package/dist/vendor/codali/runtime/CodaliJobRuntime.d.ts +6 -0
  148. package/dist/vendor/codali/runtime/CodaliJobRuntime.d.ts.map +1 -1
  149. package/dist/vendor/codali/runtime/CodaliJobRuntime.js +36 -1
  150. package/dist/vendor/codali/runtime/CodaliRuntime.d.ts +28 -0
  151. package/dist/vendor/codali/runtime/CodaliRuntime.d.ts.map +1 -1
  152. package/dist/vendor/codali/runtime/CodaliRuntime.js +69 -1
  153. package/dist/vendor/codali/runtime/CompletionReport.d.ts +5 -0
  154. package/dist/vendor/codali/runtime/CompletionReport.d.ts.map +1 -0
  155. package/dist/vendor/codali/runtime/CompletionReport.js +12 -0
  156. package/dist/vendor/codali/runtime/ProgressTracker.d.ts +17 -0
  157. package/dist/vendor/codali/runtime/ProgressTracker.d.ts.map +1 -0
  158. package/dist/vendor/codali/runtime/ProgressTracker.js +27 -0
  159. package/dist/vendor/codali/runtime/RequestedTestEvidence.d.ts +12 -0
  160. package/dist/vendor/codali/runtime/RequestedTestEvidence.d.ts.map +1 -0
  161. package/dist/vendor/codali/runtime/RequestedTestEvidence.js +16 -0
  162. package/dist/vendor/codali/runtime/RequiredRetrieval.d.ts +13 -0
  163. package/dist/vendor/codali/runtime/RequiredRetrieval.d.ts.map +1 -0
  164. package/dist/vendor/codali/runtime/RequiredRetrieval.js +25 -0
  165. package/dist/vendor/codali/runtime/ReviewSource.d.ts +6 -0
  166. package/dist/vendor/codali/runtime/ReviewSource.d.ts.map +1 -0
  167. package/dist/vendor/codali/runtime/ReviewSource.js +38 -0
  168. package/dist/vendor/codali/runtime/Runner.d.ts +7 -0
  169. package/dist/vendor/codali/runtime/Runner.d.ts.map +1 -1
  170. package/dist/vendor/codali/runtime/Runner.js +215 -171
  171. package/dist/vendor/codali/runtime/SecretRedaction.d.ts +11 -0
  172. package/dist/vendor/codali/runtime/SecretRedaction.d.ts.map +1 -0
  173. package/dist/vendor/codali/runtime/SecretRedaction.js +85 -0
  174. package/dist/vendor/codali/runtime/SessionController.d.ts +148 -0
  175. package/dist/vendor/codali/runtime/SessionController.d.ts.map +1 -0
  176. package/dist/vendor/codali/runtime/SessionController.js +1356 -0
  177. package/dist/vendor/codali/runtime/StructuralEvidence.d.ts +22 -0
  178. package/dist/vendor/codali/runtime/StructuralEvidence.d.ts.map +1 -0
  179. package/dist/vendor/codali/runtime/StructuralEvidence.js +87 -0
  180. package/dist/vendor/codali/runtime/TaskReviewContext.d.ts +34 -0
  181. package/dist/vendor/codali/runtime/TaskReviewContext.d.ts.map +1 -0
  182. package/dist/vendor/codali/runtime/TaskReviewContext.js +34 -0
  183. package/dist/vendor/codali/runtime/ValidationOutput.d.ts +5 -0
  184. package/dist/vendor/codali/runtime/ValidationOutput.d.ts.map +1 -0
  185. package/dist/vendor/codali/runtime/ValidationOutput.js +32 -0
  186. package/dist/vendor/codali/runtime/VerificationCommand.d.ts +3 -0
  187. package/dist/vendor/codali/runtime/VerificationCommand.d.ts.map +1 -0
  188. package/dist/vendor/codali/runtime/VerificationCommand.js +48 -0
  189. package/dist/vendor/codali/runtime/WorkStatusPage.d.ts +15 -0
  190. package/dist/vendor/codali/runtime/WorkStatusPage.d.ts.map +1 -0
  191. package/dist/vendor/codali/runtime/WorkStatusPage.js +58 -0
  192. package/dist/vendor/codali/runtime/WorkspaceLedger.d.ts +13 -0
  193. package/dist/vendor/codali/runtime/WorkspaceLedger.d.ts.map +1 -0
  194. package/dist/vendor/codali/runtime/WorkspaceLedger.js +145 -0
  195. package/dist/vendor/codali/runtime/WorkspaceLock.d.ts.map +1 -1
  196. package/dist/vendor/codali/runtime/WorkspaceLock.js +20 -17
  197. package/dist/vendor/codali/runtime/WorkspaceSnapshot.d.ts +13 -0
  198. package/dist/vendor/codali/runtime/WorkspaceSnapshot.d.ts.map +1 -0
  199. package/dist/vendor/codali/runtime/WorkspaceSnapshot.js +88 -0
  200. package/dist/vendor/codali/session/AtomicState.d.ts +13 -0
  201. package/dist/vendor/codali/session/AtomicState.d.ts.map +1 -0
  202. package/dist/vendor/codali/session/AtomicState.js +109 -0
  203. package/dist/vendor/codali/session/SessionStoragePath.d.ts +15 -0
  204. package/dist/vendor/codali/session/SessionStoragePath.d.ts.map +1 -0
  205. package/dist/vendor/codali/session/SessionStoragePath.js +89 -0
  206. package/dist/vendor/codali/session/SessionStore.d.ts +9 -0
  207. package/dist/vendor/codali/session/SessionStore.d.ts.map +1 -1
  208. package/dist/vendor/codali/session/SessionStore.js +181 -47
  209. package/dist/vendor/codali/session/WorkState.d.ts +23 -0
  210. package/dist/vendor/codali/session/WorkState.d.ts.map +1 -0
  211. package/dist/vendor/codali/session/WorkState.js +367 -0
  212. package/dist/vendor/codali/session/WorkTypes.d.ts +94 -0
  213. package/dist/vendor/codali/session/WorkTypes.d.ts.map +1 -0
  214. package/dist/vendor/codali/session/WorkTypes.js +1 -0
  215. package/dist/vendor/codali/tools/ToolRegistry.d.ts +2 -0
  216. package/dist/vendor/codali/tools/ToolRegistry.d.ts.map +1 -1
  217. package/dist/vendor/codali/tools/ToolRegistry.js +12 -2
  218. package/dist/vendor/codali/tools/ToolTypes.d.ts +16 -0
  219. package/dist/vendor/codali/tools/ToolTypes.d.ts.map +1 -1
  220. package/dist/vendor/codali/tools/docdex/DocdexTools.d.ts +2 -0
  221. package/dist/vendor/codali/tools/docdex/DocdexTools.d.ts.map +1 -1
  222. package/dist/vendor/codali/tools/docdex/DocdexTools.js +17 -2
  223. package/dist/vendor/codali/tools/filesystem/FileTools.d.ts.map +1 -1
  224. package/dist/vendor/codali/tools/filesystem/FileTools.js +30 -10
  225. package/dist/vendor/codali/tools/shell/AsyncProcess.d.ts +16 -0
  226. package/dist/vendor/codali/tools/shell/AsyncProcess.d.ts.map +1 -0
  227. package/dist/vendor/codali/tools/shell/AsyncProcess.js +94 -0
  228. package/dist/vendor/codali/tools/shell/DarwinRuntimeLibraries.d.ts +13 -0
  229. package/dist/vendor/codali/tools/shell/DarwinRuntimeLibraries.d.ts.map +1 -0
  230. package/dist/vendor/codali/tools/shell/DarwinRuntimeLibraries.js +130 -0
  231. package/dist/vendor/codali/tools/shell/HostToolchain.d.ts +19 -0
  232. package/dist/vendor/codali/tools/shell/HostToolchain.d.ts.map +1 -0
  233. package/dist/vendor/codali/tools/shell/HostToolchain.js +264 -0
  234. package/dist/vendor/codali/tools/shell/IsolatedExecutor.d.ts +15 -0
  235. package/dist/vendor/codali/tools/shell/IsolatedExecutor.d.ts.map +1 -0
  236. package/dist/vendor/codali/tools/shell/IsolatedExecutor.js +134 -0
  237. package/dist/vendor/codali/tools/shell/ShellTool.d.ts.map +1 -1
  238. package/dist/vendor/codali/tools/shell/ShellTool.js +9 -29
  239. package/dist/vendor/codali/tools/shell/ShellWorkingDirectory.d.ts +3 -0
  240. package/dist/vendor/codali/tools/shell/ShellWorkingDirectory.d.ts.map +1 -0
  241. package/dist/vendor/codali/tools/shell/ShellWorkingDirectory.js +30 -0
  242. package/package.json +31 -29
  243. package/scripts/backend-http-drain.mjs +152 -0
  244. package/scripts/media_gpu_lock.py +238 -0
  245. package/scripts/stable-audio-3-openai-server.py +45 -14
  246. package/scripts/stable-diffusion-cpp-openai-server.py +34 -4
  247. package/scripts/stable-diffusion-cpp-webm-duration.patch +22 -0
  248. package/scripts/wan22-openai-server.py +97 -18
@@ -1,21 +1,59 @@
1
1
  import { randomUUID } from "node:crypto";
2
- import { promises as fs } from "node:fs";
2
+ import { constants, promises as fs } from "node:fs";
3
3
  import path from "node:path";
4
+ import { atomicWriteJson, withStateLock } from "./AtomicState.js";
5
+ import { createWorkState, validateWorkState } from "./WorkState.js";
6
+ import { readStateFile, sessionStoragePath } from "./SessionStoragePath.js";
4
7
  const DEFAULT_SESSION_STORAGE_DIR = ".mcoda/codali/sessions";
5
8
  const safeId = (value) => {
6
- const safe = value.replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 120);
7
- if (!safe)
8
- throw new Error("Session id must contain at least one safe character");
9
- return safe;
9
+ if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,119}$/.test(value))
10
+ throw new Error("Invalid session id");
11
+ return value;
12
+ };
13
+ const safeSummaryRef = (value) => {
14
+ const normalized = typeof value === "string" ? value.replace(/\\/g, "/") : "";
15
+ if (!/^summaries\/[A-Za-z0-9._-]+\.json$/.test(normalized))
16
+ throw new Error("Unsafe session summary reference");
17
+ return normalized;
18
+ };
19
+ const validateMetadata = (value, sessionId) => {
20
+ if (!value || value.schemaVersion !== 1)
21
+ throw new Error("Unsupported session metadata schema; use a compatible client");
22
+ if (value.sessionId !== sessionId || typeof value.repoRoot !== "string" || typeof value.task !== "string" || !["active", "paused", "completed", "failed"].includes(value.status))
23
+ throw new Error("Invalid session metadata identity/status");
24
+ for (const key of ["runIds", "transcriptRefs", "summaryRefs", "contextLaneRefs", "instructionSources"]) {
25
+ if (!Array.isArray(value[key]) || value[key].some(item => typeof item !== "string"))
26
+ throw new Error(`Invalid session ${key}`);
27
+ }
28
+ value.summaryRefs.forEach(safeSummaryRef);
29
+ return value;
10
30
  };
11
31
  const parseJsonLines = (content) => {
12
32
  if (!content.trim())
13
33
  return [];
14
- return content
15
- .split("\n")
16
- .map((line) => line.trim())
17
- .filter(Boolean)
18
- .map((line) => JSON.parse(line));
34
+ const lines = content.split("\n");
35
+ const result = [];
36
+ for (let index = 0; index < lines.length; index += 1) {
37
+ const line = lines[index].trim();
38
+ if (!line)
39
+ continue;
40
+ try {
41
+ result.push(JSON.parse(line));
42
+ }
43
+ catch (error) {
44
+ // Only an unterminated final record may be a crash tail. Never hide middle corruption.
45
+ if (index === lines.length - 1 && !content.endsWith("\n"))
46
+ break;
47
+ throw error;
48
+ }
49
+ }
50
+ return result;
51
+ };
52
+ const parseTranscript = (content, sessionId) => {
53
+ const events = parseJsonLines(content);
54
+ if (events.some(event => !event || event.schemaVersion !== 1 || event.sessionId !== sessionId))
55
+ throw new Error("Unsupported/invalid session transcript schema");
56
+ return events;
19
57
  };
20
58
  const nowIso = () => new Date().toISOString();
21
59
  const shortJson = (value, maxLength = 400) => {
@@ -63,15 +101,20 @@ export class SessionStore {
63
101
  this.lastTimestampMs = 0;
64
102
  this.workspaceRoot = path.resolve(options.workspaceRoot);
65
103
  this.storageDir = options.storageDir ?? DEFAULT_SESSION_STORAGE_DIR;
104
+ this.allowExternalStorage = options.allowExternalStorage === true;
66
105
  }
67
106
  rootDir() {
68
107
  const resolved = path.resolve(this.workspaceRoot, this.storageDir);
69
108
  const relative = path.relative(this.workspaceRoot, resolved);
70
- if (relative.startsWith("..") || path.isAbsolute(relative)) {
109
+ if (!this.allowExternalStorage && (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative))) {
71
110
  throw new Error("Session storage path is outside workspace root");
72
111
  }
73
112
  return resolved;
74
113
  }
114
+ checkedPath(file, createParents = false, directory = false) {
115
+ return sessionStoragePath({ workspaceRoot: this.workspaceRoot, storageRoot: this.rootDir(), file,
116
+ allowExternal: this.allowExternalStorage, createParents, directory });
117
+ }
75
118
  sessionDir(sessionId) {
76
119
  return path.join(this.rootDir(), safeId(sessionId));
77
120
  }
@@ -109,13 +152,23 @@ export class SessionStore {
109
152
  createdAt,
110
153
  updatedAt: createdAt,
111
154
  };
112
- await fs.mkdir(this.sessionDir(sessionId), { recursive: true });
113
- await fs.writeFile(this.metadataPath(sessionId), `${JSON.stringify(metadata, null, 2)}\n`, "utf8");
155
+ const metadataPath = await this.checkedPath(this.metadataPath(sessionId), true);
156
+ await withStateLock(metadataPath, async () => {
157
+ try {
158
+ await fs.stat(metadataPath);
159
+ throw new Error("Session already exists");
160
+ }
161
+ catch (error) {
162
+ if (error.code !== "ENOENT")
163
+ throw error;
164
+ }
165
+ await atomicWriteJson(metadataPath, metadata);
166
+ });
114
167
  return metadata;
115
168
  }
116
169
  async readSession(sessionId) {
117
- const content = await fs.readFile(this.metadataPath(sessionId), "utf8");
118
- return JSON.parse(content);
170
+ const content = await readStateFile(await this.checkedPath(this.metadataPath(sessionId)));
171
+ return validateMetadata(JSON.parse(content), sessionId);
119
172
  }
120
173
  async getOrCreateSession(input) {
121
174
  if (input.sessionId) {
@@ -131,25 +184,30 @@ export class SessionStore {
131
184
  return this.createSession(input);
132
185
  }
133
186
  async updateSession(sessionId, patch) {
134
- const current = await this.readSession(sessionId);
135
- const next = {
136
- ...current,
137
- ...patch,
138
- runIds: patch.runIds ?? current.runIds,
139
- transcriptRefs: patch.transcriptRefs ?? current.transcriptRefs,
140
- summaryRefs: patch.summaryRefs ?? current.summaryRefs,
141
- contextLaneRefs: patch.contextLaneRefs ?? current.contextLaneRefs,
142
- instructionSources: patch.instructionSources ?? current.instructionSources,
143
- updatedAt: this.nextTimestampIso(current.updatedAt),
144
- };
145
- await fs.writeFile(this.metadataPath(sessionId), `${JSON.stringify(next, null, 2)}\n`, "utf8");
146
- return next;
187
+ return this.mutateSession(sessionId, current => ({ ...current, ...patch }));
188
+ }
189
+ async mutateSession(sessionId, mutate) {
190
+ const metadataPath = await this.checkedPath(this.metadataPath(sessionId));
191
+ return withStateLock(metadataPath, async () => {
192
+ const current = await this.readSession(sessionId);
193
+ const patch = mutate(structuredClone(current));
194
+ const next = {
195
+ ...current,
196
+ ...patch,
197
+ runIds: patch.runIds ?? current.runIds,
198
+ transcriptRefs: patch.transcriptRefs ?? current.transcriptRefs,
199
+ summaryRefs: patch.summaryRefs ?? current.summaryRefs,
200
+ contextLaneRefs: patch.contextLaneRefs ?? current.contextLaneRefs,
201
+ instructionSources: patch.instructionSources ?? current.instructionSources,
202
+ updatedAt: this.nextTimestampIso(current.updatedAt),
203
+ };
204
+ validateMetadata(next, sessionId);
205
+ await atomicWriteJson(metadataPath, next);
206
+ return next;
207
+ });
147
208
  }
148
209
  async addRun(sessionId, runId) {
149
- const current = await this.readSession(sessionId);
150
- if (current.runIds.includes(runId))
151
- return current;
152
- return this.updateSession(sessionId, { runIds: [...current.runIds, runId] });
210
+ return this.mutateSession(sessionId, current => ({ ...current, runIds: [...new Set([...current.runIds, runId])] }));
153
211
  }
154
212
  async appendTranscript(sessionId, event) {
155
213
  const record = {
@@ -160,16 +218,53 @@ export class SessionStore {
160
218
  runId: event.runId,
161
219
  data: event.data,
162
220
  };
163
- const transcriptPath = this.transcriptPath(sessionId);
164
- await fs.mkdir(path.dirname(transcriptPath), { recursive: true });
165
- await fs.appendFile(transcriptPath, `${JSON.stringify(record)}\n`, "utf8");
221
+ await this.readSession(sessionId); // Refuse future schemas before appending anything.
222
+ const transcriptPath = await this.checkedPath(this.transcriptPath(sessionId));
223
+ await withStateLock(transcriptPath, async () => {
224
+ try {
225
+ const contents = await readStateFile(transcriptPath);
226
+ parseTranscript(contents, sessionId);
227
+ if (contents && !contents.endsWith("\n")) {
228
+ const lastNewline = contents.lastIndexOf("\n");
229
+ let complete = false;
230
+ try {
231
+ JSON.parse(contents.slice(lastNewline + 1));
232
+ complete = true;
233
+ }
234
+ catch { /* Incomplete crash tail. */ }
235
+ // Windows append-only handles cannot truncate an incomplete record.
236
+ const repair = await fs.open(transcriptPath, constants.O_WRONLY | constants.O_NOFOLLOW | (complete ? constants.O_APPEND : 0));
237
+ try {
238
+ if (complete)
239
+ await repair.writeFile("\n");
240
+ else
241
+ await repair.truncate(Buffer.byteLength(contents.slice(0, lastNewline + 1)));
242
+ }
243
+ finally {
244
+ await repair.close();
245
+ }
246
+ }
247
+ }
248
+ catch (error) {
249
+ if (error.code !== "ENOENT")
250
+ throw error;
251
+ }
252
+ const handle = await fs.open(transcriptPath, constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT | constants.O_NOFOLLOW, 0o600);
253
+ try {
254
+ await handle.writeFile(`${JSON.stringify(record)}\n`, "utf8");
255
+ await handle.sync();
256
+ }
257
+ finally {
258
+ await handle.close();
259
+ }
260
+ });
166
261
  await this.updateSession(sessionId, {});
167
262
  return record;
168
263
  }
169
264
  async readTranscript(sessionId) {
170
265
  try {
171
- const content = await fs.readFile(this.transcriptPath(sessionId), "utf8");
172
- return parseJsonLines(content);
266
+ const content = await readStateFile(await this.checkedPath(this.transcriptPath(sessionId)));
267
+ return parseTranscript(content, sessionId);
173
268
  }
174
269
  catch (error) {
175
270
  if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
@@ -181,7 +276,7 @@ export class SessionStore {
181
276
  async listSessions() {
182
277
  let entries;
183
278
  try {
184
- entries = await fs.readdir(this.rootDir());
279
+ entries = await fs.readdir(await this.checkedPath(this.rootDir(), false, true));
185
280
  }
186
281
  catch (error) {
187
282
  if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
@@ -212,15 +307,12 @@ export class SessionStore {
212
307
  eventCount: events.length,
213
308
  ...compacted,
214
309
  };
215
- const summariesDir = this.summariesDir(sessionId);
216
- await fs.mkdir(summariesDir, { recursive: true });
310
+ const summariesDir = await this.checkedPath(this.summariesDir(sessionId), true, true);
217
311
  const fileName = `${createdAt.replace(/[^0-9T]/g, "").slice(0, 15)}-${events.length}.json`;
218
312
  const filePath = path.join(summariesDir, fileName);
219
- await fs.writeFile(filePath, `${JSON.stringify(summary, null, 2)}\n`, "utf8");
220
- const relativeRef = path.relative(this.sessionDir(sessionId), filePath);
221
- await this.updateSession(sessionId, {
222
- summaryRefs: [...metadata.summaryRefs, relativeRef],
223
- });
313
+ await atomicWriteJson(filePath, summary);
314
+ const relativeRef = path.posix.join("summaries", fileName);
315
+ await this.mutateSession(sessionId, current => ({ ...current, summaryRefs: [...new Set([...current.summaryRefs, relativeRef])] }));
224
316
  return summary;
225
317
  }
226
318
  async readLatestSummary(sessionId) {
@@ -228,8 +320,11 @@ export class SessionStore {
228
320
  const latest = metadata.summaryRefs.at(-1);
229
321
  if (!latest)
230
322
  return undefined;
231
- const content = await fs.readFile(path.join(this.sessionDir(sessionId), latest), "utf8");
232
- return JSON.parse(content);
323
+ const content = await readStateFile(await this.checkedPath(path.join(this.sessionDir(sessionId), safeSummaryRef(latest))));
324
+ const summary = JSON.parse(content);
325
+ if (!summary || summary.schemaVersion !== 1 || summary.sessionId !== sessionId)
326
+ throw new Error("Unsupported/invalid session summary schema");
327
+ return summary;
233
328
  }
234
329
  async buildResumeBundle(sessionId, options = {}) {
235
330
  const metadata = await this.readSession(sessionId);
@@ -241,4 +336,43 @@ export class SessionStore {
241
336
  recentEvents: recentCount ? transcript.slice(-recentCount) : [],
242
337
  };
243
338
  }
339
+ async initializeWork(sessionId, objective) {
340
+ await this.readSession(sessionId);
341
+ const file = await this.checkedPath(path.join(this.sessionDir(sessionId), "work.json"));
342
+ return withStateLock(file, async () => {
343
+ try {
344
+ return await this.readWork(sessionId);
345
+ }
346
+ catch (error) {
347
+ if (error.code !== "ENOENT")
348
+ throw error;
349
+ }
350
+ const state = createWorkState(objective);
351
+ await atomicWriteJson(file, state);
352
+ return state;
353
+ });
354
+ }
355
+ async readWork(sessionId) {
356
+ const state = JSON.parse(await readStateFile(await this.checkedPath(path.join(this.sessionDir(sessionId), "work.json"))));
357
+ validateWorkState(state);
358
+ return state;
359
+ }
360
+ async updateWork(sessionId, expectedRevision, mutate) {
361
+ await this.readSession(sessionId);
362
+ const file = await this.checkedPath(path.join(this.sessionDir(sessionId), "work.json"));
363
+ return withStateLock(file, async () => {
364
+ const state = await this.readWork(sessionId);
365
+ if (state.revision !== expectedRevision)
366
+ throw new Error("Work revision conflict; reload before retrying");
367
+ const identity = [state.goalId, state.originalObjective, state.createdAt];
368
+ mutate(state);
369
+ if (JSON.stringify(identity) !== JSON.stringify([state.goalId, state.originalObjective, state.createdAt]))
370
+ throw new Error("Original goal identity is immutable");
371
+ state.revision += 1;
372
+ state.updatedAt = nowIso();
373
+ validateWorkState(state);
374
+ await atomicWriteJson(file, state);
375
+ return state;
376
+ });
377
+ }
244
378
  }
@@ -0,0 +1,23 @@
1
+ import type { DecisionRecord, EvidenceReceipt, Requirement, WorkState, WorkTask, WorkPhase } from "./WorkTypes.js";
2
+ export declare const createWorkState: (objective: string, requirements?: Requirement[]) => WorkState;
3
+ export declare const validateWorkState: (state: WorkState) => void;
4
+ export declare const refreshReadyTasks: (state: WorkState) => void;
5
+ export declare const replaceWorkPlan: (state: WorkState, tasks: Array<Pick<WorkTask, "id" | "title" | "requirementIds" | "dependsOn" | "allowedPaths" | "phaseId">>, phases?: WorkPhase[], reason?: string) => void;
6
+ /** Update named contracts while retaining every unmentioned task and phase. */
7
+ export declare const updateWorkPlan: (state: WorkState, updates: Parameters<typeof replaceWorkPlan>[1], phaseUpdates?: WorkPhase[], reason?: string) => void;
8
+ export declare const claimWorkTask: (state: WorkState, taskId: string, leaseMs?: number) => WorkTask;
9
+ export declare const releaseWorkTask: (state: WorkState, taskId: string, attemptId: string, note: string) => void;
10
+ /** Withdraw a disproven verification and fence all dependent attempts without rewriting the plan. */
11
+ export declare const reopenVerifiedTask: (state: WorkState, taskId: string, reason: string) => string[];
12
+ export declare const assertWorkAttempt: (state: WorkState, taskId: string, attemptId: string) => WorkTask;
13
+ export declare const recordWorkEvidence: (state: WorkState, taskId: string, attemptId: string, evidence: EvidenceReceipt) => void;
14
+ export declare const verifyWorkTask: (state: WorkState, taskId: string, attemptId: string, currentHashes: Record<string, string>) => void;
15
+ /** Reopen stale proofs and their dependent tasks without discarding audit history. */
16
+ export declare const refreshStaleEvidence: (state: WorkState, currentHashes: Record<string, string>) => string[];
17
+ export declare const amendWorkGoal: (state: WorkState, objective: string, reason: string) => void;
18
+ export declare const recordDecision: (state: WorkState, decision: DecisionRecord) => void;
19
+ export declare const completeWorkGoal: (state: WorkState, currentHashes: Record<string, string>, uncertainInvocationIds?: string[]) => void;
20
+ export declare const workContext: (state: WorkState) => string;
21
+ /** Keep the active contract intact while paging unrelated backlog out of context. */
22
+ export declare const activeWorkContext: (state: WorkState, maxChars: number) => string;
23
+ //# sourceMappingURL=WorkState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkState.d.ts","sourceRoot":"","sources":["../../src/session/WorkState.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAiBnH,eAAO,MAAM,eAAe,GAAI,WAAW,MAAM,EAAE,eAAe,WAAW,EAAE,KAAG,SAYjF,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,OAAO,SAAS,KAAG,IAiDpD,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,OAAO,SAAS,KAAG,IAIpD,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,OAAO,SAAS,EAAE,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,GAAG,OAAO,GAAG,gBAAgB,GAAG,WAAW,GAAG,cAAc,GAAG,SAAS,CAAC,CAAC,EAAE,oBAA2B,EAAE,eAA4B,KAAG,IAgCzN,CAAC;AAEF,+EAA+E;AAC/E,eAAO,MAAM,cAAc,GAAI,OAAO,SAAS,EAAE,SAAS,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE,eAAc,SAAS,EAAO,EAAE,eAA4B,KAAG,IAiB/J,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO,SAAS,EAAE,QAAQ,MAAM,EAAE,gBAAiB,KAAG,QAWnF,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,OAAO,SAAS,EAAE,QAAQ,MAAM,EAAE,WAAW,MAAM,EAAE,MAAM,MAAM,KAAG,IAOnG,CAAC;AAEF,qGAAqG;AACrG,eAAO,MAAM,kBAAkB,GAAI,OAAO,SAAS,EAAE,QAAQ,MAAM,EAAE,QAAQ,MAAM,KAAG,MAAM,EAkB3F,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,OAAO,SAAS,EAAE,QAAQ,MAAM,EAAE,WAAW,MAAM,KAAG,QAOvF,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,OAAO,SAAS,EAAE,QAAQ,MAAM,EAAE,WAAW,MAAM,EAAE,UAAU,eAAe,KAAG,IAOnH,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,OAAO,SAAS,EAAE,QAAQ,MAAM,EAAE,WAAW,MAAM,EAAE,eAAe,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAG,IAK3H,CAAC;AAEF,sFAAsF;AACtF,eAAO,MAAM,oBAAoB,GAAI,OAAO,SAAS,EAAE,eAAe,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAG,MAAM,EAepG,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO,SAAS,EAAE,WAAW,MAAM,EAAE,QAAQ,MAAM,KAAG,IAWnF,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,OAAO,SAAS,EAAE,UAAU,cAAc,KAAG,IAuB3E,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,OAAO,SAAS,EAAE,eAAe,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,yBAAwB,MAAM,EAAO,KAAG,IASjI,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,OAAO,SAAS,KAAG,MAK7C,CAAC;AAEH,qFAAqF;AACrF,eAAO,MAAM,iBAAiB,GAAI,OAAO,SAAS,EAAE,UAAU,MAAM,KAAG,MAoCtE,CAAC"}