@pythonluvr/openwar 0.4.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.
Files changed (298) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +297 -0
  3. package/bin/openwar +45 -0
  4. package/dist/adapters/anthropic.d.ts +15 -0
  5. package/dist/adapters/anthropic.d.ts.map +1 -0
  6. package/dist/adapters/anthropic.js +179 -0
  7. package/dist/adapters/anthropic.js.map +1 -0
  8. package/dist/adapters/gemini.d.ts +15 -0
  9. package/dist/adapters/gemini.d.ts.map +1 -0
  10. package/dist/adapters/gemini.js +141 -0
  11. package/dist/adapters/gemini.js.map +1 -0
  12. package/dist/adapters/grok.d.ts +6 -0
  13. package/dist/adapters/grok.d.ts.map +1 -0
  14. package/dist/adapters/grok.js +15 -0
  15. package/dist/adapters/grok.js.map +1 -0
  16. package/dist/adapters/index.d.ts +16 -0
  17. package/dist/adapters/index.d.ts.map +1 -0
  18. package/dist/adapters/index.js +35 -0
  19. package/dist/adapters/index.js.map +1 -0
  20. package/dist/adapters/mock.d.ts +17 -0
  21. package/dist/adapters/mock.d.ts.map +1 -0
  22. package/dist/adapters/mock.js +33 -0
  23. package/dist/adapters/mock.js.map +1 -0
  24. package/dist/adapters/openai-compat.d.ts +6 -0
  25. package/dist/adapters/openai-compat.d.ts.map +1 -0
  26. package/dist/adapters/openai-compat.js +19 -0
  27. package/dist/adapters/openai-compat.js.map +1 -0
  28. package/dist/adapters/openai.d.ts +23 -0
  29. package/dist/adapters/openai.d.ts.map +1 -0
  30. package/dist/adapters/openai.js +176 -0
  31. package/dist/adapters/openai.js.map +1 -0
  32. package/dist/adapters/sse.d.ts +6 -0
  33. package/dist/adapters/sse.d.ts.map +1 -0
  34. package/dist/adapters/sse.js +45 -0
  35. package/dist/adapters/sse.js.map +1 -0
  36. package/dist/adapters/types.d.ts +7 -0
  37. package/dist/adapters/types.d.ts.map +1 -0
  38. package/dist/adapters/types.js +2 -0
  39. package/dist/adapters/types.js.map +1 -0
  40. package/dist/auth/categories.d.ts +13 -0
  41. package/dist/auth/categories.d.ts.map +1 -0
  42. package/dist/auth/categories.js +47 -0
  43. package/dist/auth/categories.js.map +1 -0
  44. package/dist/auth/check.d.ts +31 -0
  45. package/dist/auth/check.d.ts.map +1 -0
  46. package/dist/auth/check.js +59 -0
  47. package/dist/auth/check.js.map +1 -0
  48. package/dist/auth/role-scope.d.ts +18 -0
  49. package/dist/auth/role-scope.d.ts.map +1 -0
  50. package/dist/auth/role-scope.js +62 -0
  51. package/dist/auth/role-scope.js.map +1 -0
  52. package/dist/auth/wildcards.d.ts +5 -0
  53. package/dist/auth/wildcards.d.ts.map +1 -0
  54. package/dist/auth/wildcards.js +36 -0
  55. package/dist/auth/wildcards.js.map +1 -0
  56. package/dist/brief.d.ts +9 -0
  57. package/dist/brief.d.ts.map +1 -0
  58. package/dist/brief.js +514 -0
  59. package/dist/brief.js.map +1 -0
  60. package/dist/cli.d.ts +2 -0
  61. package/dist/cli.d.ts.map +1 -0
  62. package/dist/cli.js +585 -0
  63. package/dist/cli.js.map +1 -0
  64. package/dist/coordinator/cost-tracker.d.ts +14 -0
  65. package/dist/coordinator/cost-tracker.d.ts.map +1 -0
  66. package/dist/coordinator/cost-tracker.js +63 -0
  67. package/dist/coordinator/cost-tracker.js.map +1 -0
  68. package/dist/coordinator/driver.d.ts +37 -0
  69. package/dist/coordinator/driver.d.ts.map +1 -0
  70. package/dist/coordinator/driver.js +644 -0
  71. package/dist/coordinator/driver.js.map +1 -0
  72. package/dist/coordinator/index.d.ts +14 -0
  73. package/dist/coordinator/index.d.ts.map +1 -0
  74. package/dist/coordinator/index.js +8 -0
  75. package/dist/coordinator/index.js.map +1 -0
  76. package/dist/coordinator/plan-parser.d.ts +17 -0
  77. package/dist/coordinator/plan-parser.d.ts.map +1 -0
  78. package/dist/coordinator/plan-parser.js +44 -0
  79. package/dist/coordinator/plan-parser.js.map +1 -0
  80. package/dist/coordinator/result-aggregator.d.ts +21 -0
  81. package/dist/coordinator/result-aggregator.d.ts.map +1 -0
  82. package/dist/coordinator/result-aggregator.js +58 -0
  83. package/dist/coordinator/result-aggregator.js.map +1 -0
  84. package/dist/coordinator/retry-policy.d.ts +7 -0
  85. package/dist/coordinator/retry-policy.d.ts.map +1 -0
  86. package/dist/coordinator/retry-policy.js +17 -0
  87. package/dist/coordinator/retry-policy.js.map +1 -0
  88. package/dist/coordinator/state-machine.d.ts +63 -0
  89. package/dist/coordinator/state-machine.d.ts.map +1 -0
  90. package/dist/coordinator/state-machine.js +242 -0
  91. package/dist/coordinator/state-machine.js.map +1 -0
  92. package/dist/coordinator/types.d.ts +3 -0
  93. package/dist/coordinator/types.d.ts.map +1 -0
  94. package/dist/coordinator/types.js +5 -0
  95. package/dist/coordinator/types.js.map +1 -0
  96. package/dist/detectors/banned-phrases.d.ts +3 -0
  97. package/dist/detectors/banned-phrases.d.ts.map +1 -0
  98. package/dist/detectors/banned-phrases.js +33 -0
  99. package/dist/detectors/banned-phrases.js.map +1 -0
  100. package/dist/detectors/blocker.d.ts +3 -0
  101. package/dist/detectors/blocker.d.ts.map +1 -0
  102. package/dist/detectors/blocker.js +62 -0
  103. package/dist/detectors/blocker.js.map +1 -0
  104. package/dist/detectors/completion.d.ts +3 -0
  105. package/dist/detectors/completion.d.ts.map +1 -0
  106. package/dist/detectors/completion.js +17 -0
  107. package/dist/detectors/completion.js.map +1 -0
  108. package/dist/detectors/confirmation-summary.d.ts +3 -0
  109. package/dist/detectors/confirmation-summary.d.ts.map +1 -0
  110. package/dist/detectors/confirmation-summary.js +76 -0
  111. package/dist/detectors/confirmation-summary.js.map +1 -0
  112. package/dist/detectors/destructive.d.ts +3 -0
  113. package/dist/detectors/destructive.d.ts.map +1 -0
  114. package/dist/detectors/destructive.js +96 -0
  115. package/dist/detectors/destructive.js.map +1 -0
  116. package/dist/detectors/index.d.ts +12 -0
  117. package/dist/detectors/index.d.ts.map +1 -0
  118. package/dist/detectors/index.js +19 -0
  119. package/dist/detectors/index.js.map +1 -0
  120. package/dist/detectors/phase-marker.d.ts +3 -0
  121. package/dist/detectors/phase-marker.d.ts.map +1 -0
  122. package/dist/detectors/phase-marker.js +25 -0
  123. package/dist/detectors/phase-marker.js.map +1 -0
  124. package/dist/framework.d.ts +2 -0
  125. package/dist/framework.d.ts.map +1 -0
  126. package/dist/framework.js +34 -0
  127. package/dist/framework.js.map +1 -0
  128. package/dist/index.d.ts +10 -0
  129. package/dist/index.d.ts.map +1 -0
  130. package/dist/index.js +10 -0
  131. package/dist/index.js.map +1 -0
  132. package/dist/io.d.ts +25 -0
  133. package/dist/io.d.ts.map +1 -0
  134. package/dist/io.js +83 -0
  135. package/dist/io.js.map +1 -0
  136. package/dist/mcp/client.d.ts +22 -0
  137. package/dist/mcp/client.d.ts.map +1 -0
  138. package/dist/mcp/client.js +44 -0
  139. package/dist/mcp/client.js.map +1 -0
  140. package/dist/mcp/index.d.ts +5 -0
  141. package/dist/mcp/index.d.ts.map +1 -0
  142. package/dist/mcp/index.js +6 -0
  143. package/dist/mcp/index.js.map +1 -0
  144. package/dist/mcp/registry.d.ts +16 -0
  145. package/dist/mcp/registry.d.ts.map +1 -0
  146. package/dist/mcp/registry.js +53 -0
  147. package/dist/mcp/registry.js.map +1 -0
  148. package/dist/mcp/transport-stdio.d.ts +26 -0
  149. package/dist/mcp/transport-stdio.d.ts.map +1 -0
  150. package/dist/mcp/transport-stdio.js +138 -0
  151. package/dist/mcp/transport-stdio.js.map +1 -0
  152. package/dist/mcp/types.d.ts +90 -0
  153. package/dist/mcp/types.d.ts.map +1 -0
  154. package/dist/mcp/types.js +23 -0
  155. package/dist/mcp/types.js.map +1 -0
  156. package/dist/orchestration/handoff.d.ts +27 -0
  157. package/dist/orchestration/handoff.d.ts.map +1 -0
  158. package/dist/orchestration/handoff.js +322 -0
  159. package/dist/orchestration/handoff.js.map +1 -0
  160. package/dist/phases/blocker.d.ts +8 -0
  161. package/dist/phases/blocker.d.ts.map +1 -0
  162. package/dist/phases/blocker.js +11 -0
  163. package/dist/phases/blocker.js.map +1 -0
  164. package/dist/phases/completion.d.ts +10 -0
  165. package/dist/phases/completion.d.ts.map +1 -0
  166. package/dist/phases/completion.js +47 -0
  167. package/dist/phases/completion.js.map +1 -0
  168. package/dist/phases/destructive.d.ts +10 -0
  169. package/dist/phases/destructive.d.ts.map +1 -0
  170. package/dist/phases/destructive.js +31 -0
  171. package/dist/phases/destructive.js.map +1 -0
  172. package/dist/phases/execute.d.ts +30 -0
  173. package/dist/phases/execute.d.ts.map +1 -0
  174. package/dist/phases/execute.js +222 -0
  175. package/dist/phases/execute.js.map +1 -0
  176. package/dist/phases/intake.d.ts +16 -0
  177. package/dist/phases/intake.d.ts.map +1 -0
  178. package/dist/phases/intake.js +105 -0
  179. package/dist/phases/intake.js.map +1 -0
  180. package/dist/roles/critic.d.ts +3 -0
  181. package/dist/roles/critic.d.ts.map +1 -0
  182. package/dist/roles/critic.js +35 -0
  183. package/dist/roles/critic.js.map +1 -0
  184. package/dist/roles/executor.d.ts +3 -0
  185. package/dist/roles/executor.d.ts.map +1 -0
  186. package/dist/roles/executor.js +46 -0
  187. package/dist/roles/executor.js.map +1 -0
  188. package/dist/roles/index.d.ts +8 -0
  189. package/dist/roles/index.d.ts.map +1 -0
  190. package/dist/roles/index.js +8 -0
  191. package/dist/roles/index.js.map +1 -0
  192. package/dist/roles/planner.d.ts +3 -0
  193. package/dist/roles/planner.d.ts.map +1 -0
  194. package/dist/roles/planner.js +50 -0
  195. package/dist/roles/planner.js.map +1 -0
  196. package/dist/roles/prompt-overlay.d.ts +9 -0
  197. package/dist/roles/prompt-overlay.d.ts.map +1 -0
  198. package/dist/roles/prompt-overlay.js +25 -0
  199. package/dist/roles/prompt-overlay.js.map +1 -0
  200. package/dist/roles/registry.d.ts +8 -0
  201. package/dist/roles/registry.d.ts.map +1 -0
  202. package/dist/roles/registry.js +45 -0
  203. package/dist/roles/registry.js.map +1 -0
  204. package/dist/roles/reviewer.d.ts +3 -0
  205. package/dist/roles/reviewer.d.ts.map +1 -0
  206. package/dist/roles/reviewer.js +46 -0
  207. package/dist/roles/reviewer.js.map +1 -0
  208. package/dist/roles/types.d.ts +2 -0
  209. package/dist/roles/types.d.ts.map +1 -0
  210. package/dist/roles/types.js +4 -0
  211. package/dist/roles/types.js.map +1 -0
  212. package/dist/runner.d.ts +3 -0
  213. package/dist/runner.d.ts.map +1 -0
  214. package/dist/runner.js +473 -0
  215. package/dist/runner.js.map +1 -0
  216. package/dist/sandbox/host-allowlist.d.ts +13 -0
  217. package/dist/sandbox/host-allowlist.d.ts.map +1 -0
  218. package/dist/sandbox/host-allowlist.js +85 -0
  219. package/dist/sandbox/host-allowlist.js.map +1 -0
  220. package/dist/sandbox/output-cap.d.ts +9 -0
  221. package/dist/sandbox/output-cap.d.ts.map +1 -0
  222. package/dist/sandbox/output-cap.js +66 -0
  223. package/dist/sandbox/output-cap.js.map +1 -0
  224. package/dist/sandbox/timeout.d.ts +7 -0
  225. package/dist/sandbox/timeout.d.ts.map +1 -0
  226. package/dist/sandbox/timeout.js +52 -0
  227. package/dist/sandbox/timeout.js.map +1 -0
  228. package/dist/sandbox/types.d.ts +18 -0
  229. package/dist/sandbox/types.d.ts.map +1 -0
  230. package/dist/sandbox/types.js +27 -0
  231. package/dist/sandbox/types.js.map +1 -0
  232. package/dist/sandbox/workdir.d.ts +9 -0
  233. package/dist/sandbox/workdir.d.ts.map +1 -0
  234. package/dist/sandbox/workdir.js +83 -0
  235. package/dist/sandbox/workdir.js.map +1 -0
  236. package/dist/state/index.d.ts +4 -0
  237. package/dist/state/index.d.ts.map +1 -0
  238. package/dist/state/index.js +4 -0
  239. package/dist/state/index.js.map +1 -0
  240. package/dist/state/paths.d.ts +5 -0
  241. package/dist/state/paths.d.ts.map +1 -0
  242. package/dist/state/paths.js +18 -0
  243. package/dist/state/paths.js.map +1 -0
  244. package/dist/state/persist.d.ts +14 -0
  245. package/dist/state/persist.d.ts.map +1 -0
  246. package/dist/state/persist.js +146 -0
  247. package/dist/state/persist.js.map +1 -0
  248. package/dist/state/transcript.d.ts +9 -0
  249. package/dist/state/transcript.d.ts.map +1 -0
  250. package/dist/state/transcript.js +34 -0
  251. package/dist/state/transcript.js.map +1 -0
  252. package/dist/tools/native/apply_patch.d.ts +18 -0
  253. package/dist/tools/native/apply_patch.d.ts.map +1 -0
  254. package/dist/tools/native/apply_patch.js +245 -0
  255. package/dist/tools/native/apply_patch.js.map +1 -0
  256. package/dist/tools/native/http_fetch.d.ts +6 -0
  257. package/dist/tools/native/http_fetch.d.ts.map +1 -0
  258. package/dist/tools/native/http_fetch.js +168 -0
  259. package/dist/tools/native/http_fetch.js.map +1 -0
  260. package/dist/tools/native/index.d.ts +9 -0
  261. package/dist/tools/native/index.d.ts.map +1 -0
  262. package/dist/tools/native/index.js +22 -0
  263. package/dist/tools/native/index.js.map +1 -0
  264. package/dist/tools/native/list_dir.d.ts +4 -0
  265. package/dist/tools/native/list_dir.d.ts.map +1 -0
  266. package/dist/tools/native/list_dir.js +175 -0
  267. package/dist/tools/native/list_dir.js.map +1 -0
  268. package/dist/tools/native/read_file.d.ts +4 -0
  269. package/dist/tools/native/read_file.d.ts.map +1 -0
  270. package/dist/tools/native/read_file.js +91 -0
  271. package/dist/tools/native/read_file.js.map +1 -0
  272. package/dist/tools/native/shell_exec.d.ts +4 -0
  273. package/dist/tools/native/shell_exec.d.ts.map +1 -0
  274. package/dist/tools/native/shell_exec.js +180 -0
  275. package/dist/tools/native/shell_exec.js.map +1 -0
  276. package/dist/tools/native/write_file.d.ts +4 -0
  277. package/dist/tools/native/write_file.d.ts.map +1 -0
  278. package/dist/tools/native/write_file.js +101 -0
  279. package/dist/tools/native/write_file.js.map +1 -0
  280. package/dist/tools/types.d.ts +48 -0
  281. package/dist/tools/types.d.ts.map +1 -0
  282. package/dist/tools/types.js +10 -0
  283. package/dist/tools/types.js.map +1 -0
  284. package/dist/types.d.ts +385 -0
  285. package/dist/types.d.ts.map +1 -0
  286. package/dist/types.js +9 -0
  287. package/dist/types.js.map +1 -0
  288. package/examples/README.md +73 -0
  289. package/examples/creative-brief.md +34 -0
  290. package/examples/critic-disagreement-brief.md +42 -0
  291. package/examples/engineering-brief.md +35 -0
  292. package/examples/file-editing-brief.md +33 -0
  293. package/examples/mcp-brief.md +34 -0
  294. package/examples/multi-agent-brief.md +43 -0
  295. package/examples/research-brief.md +35 -0
  296. package/openwar.md +248 -0
  297. package/package.json +76 -0
  298. package/templates/brief.md +62 -0
@@ -0,0 +1,85 @@
1
+ // HTTP host allowlist. When ~/.openwar/http-allow.json exists, http_fetch
2
+ // rejects any host not in the list before opening a socket. When the file
3
+ // is missing, the http tool is unrestricted (default behavior).
4
+ //
5
+ // File format: a JSON array of strings. Each entry is either an exact host
6
+ // or a wildcard like "*.example.com" (matches example.com AND any subdomain).
7
+ // Comparison is case-insensitive.
8
+ import { readFile } from "node:fs/promises";
9
+ export class HostAllowlistError extends Error {
10
+ code = "HOST_ALLOWLIST_MALFORMED";
11
+ constructor(message) {
12
+ super(message);
13
+ this.name = "HostAllowlistError";
14
+ }
15
+ }
16
+ // Load from a JSON file. Returns null when the file does not exist.
17
+ // Throws HostAllowlistError when the file exists but is malformed; callers
18
+ // should treat that as fail-closed (deny everything).
19
+ export async function loadHostAllowlist(path) {
20
+ let content;
21
+ try {
22
+ content = await readFile(path, "utf8");
23
+ }
24
+ catch (err) {
25
+ const code = err.code;
26
+ if (code === "ENOENT")
27
+ return null;
28
+ throw err;
29
+ }
30
+ let parsed;
31
+ try {
32
+ parsed = JSON.parse(content);
33
+ }
34
+ catch (err) {
35
+ throw new HostAllowlistError(`invalid JSON in ${path}: ${err.message}`);
36
+ }
37
+ if (!Array.isArray(parsed)) {
38
+ throw new HostAllowlistError(`${path} must contain a JSON array of host strings`);
39
+ }
40
+ return buildAllowlist(parsed);
41
+ }
42
+ // Construct an allowlist from an array of strings. Exposed for tests and
43
+ // for callers that load the list from somewhere other than disk.
44
+ export function buildAllowlist(entries) {
45
+ const hosts = new Set();
46
+ const wildcardSuffixes = [];
47
+ const wildcardBases = new Set();
48
+ for (const entry of entries) {
49
+ if (typeof entry !== "string") {
50
+ throw new HostAllowlistError(`non-string entry in allowlist: ${JSON.stringify(entry)}`);
51
+ }
52
+ const trimmed = entry.trim().toLowerCase();
53
+ if (trimmed.length === 0)
54
+ continue;
55
+ if (trimmed.startsWith("*.")) {
56
+ const base = trimmed.slice(2);
57
+ if (base.length === 0) {
58
+ throw new HostAllowlistError(`wildcard entry "${entry}" has no base host`);
59
+ }
60
+ wildcardSuffixes.push("." + base);
61
+ wildcardBases.add(base);
62
+ }
63
+ else {
64
+ hosts.add(trimmed);
65
+ }
66
+ }
67
+ return { hosts, wildcardSuffixes, wildcardBases };
68
+ }
69
+ // Returns true when the hostname is permitted. A null allowlist (file
70
+ // missing) is permissive by design.
71
+ export function isHostAllowed(allowlist, hostname) {
72
+ if (!allowlist)
73
+ return true;
74
+ const host = hostname.toLowerCase();
75
+ if (allowlist.hosts.has(host))
76
+ return true;
77
+ if (allowlist.wildcardBases.has(host))
78
+ return true;
79
+ for (const suffix of allowlist.wildcardSuffixes) {
80
+ if (host.endsWith(suffix))
81
+ return true;
82
+ }
83
+ return false;
84
+ }
85
+ //# sourceMappingURL=host-allowlist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-allowlist.js","sourceRoot":"","sources":["../../src/sandbox/host-allowlist.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { Readable } from "node:stream";
2
+ export interface CapResult {
3
+ content: Buffer;
4
+ truncated: boolean;
5
+ totalBytesSeen: number;
6
+ }
7
+ export declare function capStream(stream: Readable, maxBytes: number): Promise<CapResult>;
8
+ export declare function capChunks(chunks: Iterable<Buffer | string>, maxBytes: number): CapResult;
9
+ //# sourceMappingURL=output-cap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-cap.d.ts","sourceRoot":"","sources":["../../src/sandbox/output-cap.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CA8BtF;AAID,wBAAgB,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,CAwBxF"}
@@ -0,0 +1,66 @@
1
+ // Output cap for stream-producing tools. Reads from a readable stream,
2
+ // accumulating bytes up to maxBytes, then continues draining without
3
+ // storing further data so the producer can finish cleanly.
4
+ //
5
+ // Used by shell_exec for stdout/stderr and http_fetch for response body.
6
+ export async function capStream(stream, maxBytes) {
7
+ if (maxBytes < 0)
8
+ throw new Error(`maxBytes must be >= 0 (got ${maxBytes})`);
9
+ const chunks = [];
10
+ let stored = 0;
11
+ let totalSeen = 0;
12
+ let truncated = false;
13
+ for await (const chunk of stream) {
14
+ const buf = Buffer.isBuffer(chunk)
15
+ ? chunk
16
+ : typeof chunk === "string"
17
+ ? Buffer.from(chunk)
18
+ : Buffer.from(chunk);
19
+ totalSeen += buf.length;
20
+ if (stored >= maxBytes) {
21
+ truncated = true;
22
+ continue;
23
+ }
24
+ const remaining = maxBytes - stored;
25
+ if (buf.length <= remaining) {
26
+ chunks.push(buf);
27
+ stored += buf.length;
28
+ }
29
+ else {
30
+ chunks.push(buf.subarray(0, remaining));
31
+ stored = maxBytes;
32
+ truncated = true;
33
+ }
34
+ }
35
+ return { content: Buffer.concat(chunks), truncated, totalBytesSeen: totalSeen };
36
+ }
37
+ // Same shape but for an iterable of Buffer chunks (no stream backpressure).
38
+ // Useful for tests and synchronous-ish producers.
39
+ export function capChunks(chunks, maxBytes) {
40
+ if (maxBytes < 0)
41
+ throw new Error(`maxBytes must be >= 0 (got ${maxBytes})`);
42
+ const out = [];
43
+ let stored = 0;
44
+ let totalSeen = 0;
45
+ let truncated = false;
46
+ for (const chunk of chunks) {
47
+ const buf = typeof chunk === "string" ? Buffer.from(chunk) : chunk;
48
+ totalSeen += buf.length;
49
+ if (stored >= maxBytes) {
50
+ truncated = true;
51
+ continue;
52
+ }
53
+ const remaining = maxBytes - stored;
54
+ if (buf.length <= remaining) {
55
+ out.push(buf);
56
+ stored += buf.length;
57
+ }
58
+ else {
59
+ out.push(buf.subarray(0, remaining));
60
+ stored = maxBytes;
61
+ truncated = true;
62
+ }
63
+ }
64
+ return { content: Buffer.concat(out), truncated, totalBytesSeen: totalSeen };
65
+ }
66
+ //# sourceMappingURL=output-cap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-cap.js","sourceRoot":"","sources":["../../src/sandbox/output-cap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export declare class TimeoutError extends Error {
2
+ readonly afterMs: number;
3
+ readonly code: "TIMEOUT";
4
+ constructor(afterMs: number);
5
+ }
6
+ export declare function withTimeout<T>(promise: Promise<T>, ms: number, signal?: AbortSignal): Promise<T>;
7
+ //# sourceMappingURL=timeout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeout.d.ts","sourceRoot":"","sources":["../../src/sandbox/timeout.ts"],"names":[],"mappings":"AAOA,qBAAa,YAAa,SAAQ,KAAK;aAET,OAAO,EAAE,MAAM;IAD3C,QAAQ,CAAC,IAAI,EAAG,SAAS,CAAU;gBACP,OAAO,EAAE,MAAM;CAI5C;AAID,wBAAgB,WAAW,CAAC,CAAC,EAC3B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,EAAE,EAAE,MAAM,EACV,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,CAAC,CAAC,CA0CZ"}
@@ -0,0 +1,52 @@
1
+ // Generic timeout wrapper for any async tool operation. Wraps a promise with
2
+ // a deadline; rejects with TimeoutError if exceeded.
3
+ //
4
+ // For child_process kills, see src/sandbox/proc-kill.ts (separate concern:
5
+ // timing out a process is more than just rejecting a promise; the process
6
+ // needs SIGTERM then SIGKILL).
7
+ export class TimeoutError extends Error {
8
+ afterMs;
9
+ code = "TIMEOUT";
10
+ constructor(afterMs) {
11
+ super(`operation exceeded ${afterMs}ms`);
12
+ this.afterMs = afterMs;
13
+ this.name = "TimeoutError";
14
+ }
15
+ }
16
+ // Wrap a promise with a timeout. Optional AbortSignal lets callers cancel
17
+ // independently. ms <= 0 disables the timeout (returns the promise as-is).
18
+ export function withTimeout(promise, ms, signal) {
19
+ if (ms <= 0)
20
+ return promise;
21
+ return new Promise((resolveOuter, rejectOuter) => {
22
+ let timer = setTimeout(() => {
23
+ timer = null;
24
+ rejectOuter(new TimeoutError(ms));
25
+ }, ms);
26
+ const clearTimer = () => {
27
+ if (timer) {
28
+ clearTimeout(timer);
29
+ timer = null;
30
+ }
31
+ };
32
+ if (signal) {
33
+ if (signal.aborted) {
34
+ clearTimer();
35
+ rejectOuter(signal.reason ?? new Error("aborted"));
36
+ return;
37
+ }
38
+ signal.addEventListener("abort", () => {
39
+ clearTimer();
40
+ rejectOuter(signal.reason ?? new Error("aborted"));
41
+ }, { once: true });
42
+ }
43
+ promise.then((value) => {
44
+ clearTimer();
45
+ resolveOuter(value);
46
+ }, (err) => {
47
+ clearTimer();
48
+ rejectOuter(err);
49
+ });
50
+ });
51
+ }
52
+ //# sourceMappingURL=timeout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeout.js","sourceRoot":"","sources":["../../src/sandbox/timeout.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,qDAAqD;AACrD,EAAE;AACF,2EAA2E;AAC3E,0EAA0E;AAC1E,+BAA+B;AAE/B,MAAM,OAAO,YAAa,SAAQ,KAAK;IAET;IADnB,IAAI,GAAG,SAAkB,CAAC;IACnC,YAA4B,OAAe;QACzC,KAAK,CAAC,sBAAsB,OAAO,IAAI,CAAC,CAAC;QADf,YAAO,GAAP,OAAO,CAAQ;QAEzC,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED,0EAA0E;AAC1E,2EAA2E;AAC3E,MAAM,UAAU,WAAW,CACzB,OAAmB,EACnB,EAAU,EACV,MAAoB;IAEpB,IAAI,EAAE,IAAI,CAAC;QAAE,OAAO,OAAO,CAAC;IAC5B,OAAO,IAAI,OAAO,CAAI,CAAC,YAAY,EAAE,WAAW,EAAE,EAAE;QAClD,IAAI,KAAK,GAA0B,UAAU,CAAC,GAAG,EAAE;YACjD,KAAK,GAAG,IAAI,CAAC;YACb,WAAW,CAAC,IAAI,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC;QACpC,CAAC,EAAE,EAAE,CAAC,CAAC;QAEP,MAAM,UAAU,GAAG,GAAG,EAAE;YACtB,IAAI,KAAK,EAAE,CAAC;gBACV,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,UAAU,EAAE,CAAC;gBACb,WAAW,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;gBACnD,OAAO;YACT,CAAC;YACD,MAAM,CAAC,gBAAgB,CACrB,OAAO,EACP,GAAG,EAAE;gBACH,UAAU,EAAE,CAAC;gBACb,WAAW,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;YACrD,CAAC,EACD,EAAE,IAAI,EAAE,IAAI,EAAE,CACf,CAAC;QACJ,CAAC;QAED,OAAO,CAAC,IAAI,CACV,CAAC,KAAK,EAAE,EAAE;YACR,UAAU,EAAE,CAAC;YACb,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC,EACD,CAAC,GAAG,EAAE,EAAE;YACN,UAAU,EAAE,CAAC;YACb,WAAW,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { HostAllowlist } from "./host-allowlist.js";
2
+ export interface SandboxContextFields {
3
+ workdir: string;
4
+ defaultTimeoutMs: number;
5
+ defaultMaxOutputBytes: number;
6
+ httpAllowlist: HostAllowlist | null;
7
+ shellEnabled: boolean;
8
+ }
9
+ export declare class SandboxContext {
10
+ readonly workdir: string;
11
+ readonly defaultTimeoutMs: number;
12
+ readonly defaultMaxOutputBytes: number;
13
+ readonly httpAllowlist: HostAllowlist | null;
14
+ readonly shellEnabled: boolean;
15
+ private constructor();
16
+ static _create(fields: SandboxContextFields): SandboxContext;
17
+ }
18
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sandbox/types.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,WAAW,oBAAoB;IAEnC,OAAO,EAAE,MAAM,CAAC;IAEhB,gBAAgB,EAAE,MAAM,CAAC;IAEzB,qBAAqB,EAAE,MAAM,CAAC;IAE9B,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IAGpC,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,qBAAa,cAAc;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7C,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAE/B,OAAO;IAYP,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,oBAAoB,GAAG,cAAc;CAG7D"}
@@ -0,0 +1,27 @@
1
+ // SandboxContext. Carried by every tool execution. Holds the workdir,
2
+ // timeout defaults, output caps, and HTTP allowlist. Tools take this as
3
+ // an argument and cannot construct one themselves: the constructor is
4
+ // private and the factory is named with a leading underscore to mark it
5
+ // as runtime-internal.
6
+ export class SandboxContext {
7
+ workdir;
8
+ defaultTimeoutMs;
9
+ defaultMaxOutputBytes;
10
+ httpAllowlist;
11
+ shellEnabled;
12
+ constructor(fields) {
13
+ this.workdir = fields.workdir;
14
+ this.defaultTimeoutMs = fields.defaultTimeoutMs;
15
+ this.defaultMaxOutputBytes = fields.defaultMaxOutputBytes;
16
+ this.httpAllowlist = fields.httpAllowlist;
17
+ this.shellEnabled = fields.shellEnabled;
18
+ Object.freeze(this);
19
+ }
20
+ // Runtime-internal factory. Not re-exported from src/index.ts. Tools that
21
+ // call this are reaching into sandbox internals on purpose; the convention
22
+ // is "if you find yourself importing _create, you are no longer a tool."
23
+ static _create(fields) {
24
+ return new SandboxContext(fields);
25
+ }
26
+ }
27
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/sandbox/types.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,wEAAwE;AACxE,sEAAsE;AACtE,wEAAwE;AACxE,uBAAuB;AAkBvB,MAAM,OAAO,cAAc;IAChB,OAAO,CAAS;IAChB,gBAAgB,CAAS;IACzB,qBAAqB,CAAS;IAC9B,aAAa,CAAuB;IACpC,YAAY,CAAU;IAE/B,YAAoB,MAA4B;QAC9C,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAC9B,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC;QAChD,IAAI,CAAC,qBAAqB,GAAG,MAAM,CAAC,qBAAqB,CAAC;QAC1D,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;QAC1C,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IAED,0EAA0E;IAC1E,2EAA2E;IAC3E,yEAAyE;IACzE,MAAM,CAAC,OAAO,CAAC,MAA4B;QACzC,OAAO,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;CACF"}
@@ -0,0 +1,9 @@
1
+ export declare class PathEscapeError extends Error {
2
+ readonly attempted: string;
3
+ readonly workdir: string;
4
+ readonly code: "PATH_ESCAPE";
5
+ constructor(attempted: string, workdir: string);
6
+ }
7
+ export declare function resolvePathInWorkdir(workdir: string, requested: string): string;
8
+ export declare function resolveAndRealpathInWorkdir(workdir: string, requested: string): Promise<string>;
9
+ //# sourceMappingURL=workdir.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workdir.d.ts","sourceRoot":"","sources":["../../src/sandbox/workdir.ts"],"names":[],"mappings":"AAYA,qBAAa,eAAgB,SAAQ,KAAK;aAGtB,SAAS,EAAE,MAAM;aACjB,OAAO,EAAE,MAAM;IAHjC,QAAQ,CAAC,IAAI,EAAG,aAAa,CAAU;gBAErB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM;CAKlC;AAqBD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAY/E;AAMD,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CAmBjB"}
@@ -0,0 +1,83 @@
1
+ // Workdir path resolution. Every filesystem-touching tool calls into this
2
+ // before opening, reading, writing, or listing anything. Tools never resolve
3
+ // paths themselves; they always go through resolvePathInWorkdir.
4
+ //
5
+ // Rejection rules:
6
+ // 1. Absolute paths outside the workdir.
7
+ // 2. Relative paths that resolve outside the workdir via ".." traversal.
8
+ // 3. Symlinks whose realpath escapes the workdir.
9
+ import { resolve, relative, isAbsolute, normalize, sep } from "node:path";
10
+ import { realpath } from "node:fs/promises";
11
+ export class PathEscapeError extends Error {
12
+ attempted;
13
+ workdir;
14
+ code = "PATH_ESCAPE";
15
+ constructor(attempted, workdir) {
16
+ super(`path "${attempted}" escapes workdir "${workdir}"`);
17
+ this.attempted = attempted;
18
+ this.workdir = workdir;
19
+ this.name = "PathEscapeError";
20
+ }
21
+ }
22
+ // On Windows, path comparison is case-insensitive. relative() handles this
23
+ // correctly when both paths are absolute, but we double-check by examining
24
+ // whether the relative path starts with "..".
25
+ function escapesWorkdir(workdirAbs, resolvedAbs) {
26
+ const rel = relative(workdirAbs, resolvedAbs);
27
+ if (rel === "")
28
+ return false;
29
+ if (rel.startsWith(".."))
30
+ return true;
31
+ if (isAbsolute(rel))
32
+ return true;
33
+ // Defensive: a single "." segment can't escape, but a relative that
34
+ // somehow contains a leading separator should be rejected.
35
+ if (rel.startsWith(sep))
36
+ return true;
37
+ return false;
38
+ }
39
+ // Synchronous, no filesystem access. Resolves the requested path against the
40
+ // workdir and rejects ".." traversal and absolute paths outside.
41
+ //
42
+ // Does NOT resolve symlinks; callers that need symlink protection use
43
+ // resolveAndRealpathInWorkdir.
44
+ export function resolvePathInWorkdir(workdir, requested) {
45
+ if (requested.indexOf("\0") !== -1) {
46
+ throw new PathEscapeError(requested, workdir);
47
+ }
48
+ const workdirAbs = resolve(workdir);
49
+ const resolved = isAbsolute(requested)
50
+ ? normalize(requested)
51
+ : resolve(workdirAbs, requested);
52
+ if (escapesWorkdir(workdirAbs, resolved)) {
53
+ throw new PathEscapeError(requested, workdir);
54
+ }
55
+ return resolved;
56
+ }
57
+ // Symlink-aware variant. Resolves the candidate path, then realpath's it
58
+ // (and the workdir) to defeat symlink-based escapes. Returns the realpath
59
+ // if the target exists; returns the non-realpath candidate (already inside
60
+ // the workdir) if the target does not exist yet (caller may be creating it).
61
+ export async function resolveAndRealpathInWorkdir(workdir, requested) {
62
+ const candidate = resolvePathInWorkdir(workdir, requested);
63
+ const workdirReal = await realpath(workdir).catch(() => resolve(workdir));
64
+ try {
65
+ const candidateReal = await realpath(candidate);
66
+ if (escapesWorkdir(workdirReal, candidateReal)) {
67
+ throw new PathEscapeError(requested, workdir);
68
+ }
69
+ return candidateReal;
70
+ }
71
+ catch (err) {
72
+ if (err instanceof PathEscapeError)
73
+ throw err;
74
+ const code = err.code;
75
+ if (code === "ENOENT") {
76
+ // Target does not exist yet. The candidate already passed the
77
+ // non-symlink check; let the caller create the file at that path.
78
+ return candidate;
79
+ }
80
+ throw err;
81
+ }
82
+ }
83
+ //# sourceMappingURL=workdir.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workdir.js","sourceRoot":"","sources":["../../src/sandbox/workdir.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export * from "./paths.js";
2
+ export * from "./persist.js";
3
+ export * from "./transcript.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from "./paths.js";
2
+ export * from "./persist.js";
3
+ export * from "./transcript.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function openwarHome(): string;
2
+ export declare function sessionsDir(): string;
3
+ export declare function sessionFile(briefId: string): string;
4
+ export declare function transcriptFile(briefId: string): string;
5
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/state/paths.ts"],"names":[],"mappings":"AAGA,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtD"}
@@ -0,0 +1,18 @@
1
+ import { homedir } from "node:os";
2
+ import { join } from "node:path";
3
+ export function openwarHome() {
4
+ return process.env.OPENWAR_HOME ?? join(homedir(), ".openwar");
5
+ }
6
+ export function sessionsDir() {
7
+ return join(openwarHome(), "sessions");
8
+ }
9
+ export function sessionFile(briefId) {
10
+ return join(sessionsDir(), `${sanitize(briefId)}.json`);
11
+ }
12
+ export function transcriptFile(briefId) {
13
+ return join(sessionsDir(), `${sanitize(briefId)}.transcript.jsonl`);
14
+ }
15
+ function sanitize(id) {
16
+ return id.replace(/[^A-Za-z0-9._-]/g, "_");
17
+ }
18
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/state/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,WAAW;IACzB,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,IAAI,CAAC,WAAW,EAAE,EAAE,UAAU,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,OAAO,IAAI,CAAC,WAAW,EAAE,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,OAAO,IAAI,CAAC,WAAW,EAAE,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;AACtE,CAAC;AAED,SAAS,QAAQ,CAAC,EAAU;IAC1B,OAAO,EAAE,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { SessionState } from "../types.js";
2
+ export declare function ensureSessionsDir(): string;
3
+ export declare function writeSession(state: SessionState): void;
4
+ export declare function readSession(briefId: string): SessionState | null;
5
+ export interface SessionIndexEntry {
6
+ brief_id: string;
7
+ project: string;
8
+ phase: string;
9
+ updated_at: string;
10
+ path: string;
11
+ }
12
+ export declare function listSessions(): SessionIndexEntry[];
13
+ export declare function sessionExists(briefId: string): boolean;
14
+ //# sourceMappingURL=persist.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persist.d.ts","sourceRoot":"","sources":["../../src/state/persist.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA8EhD,wBAAgB,iBAAiB,IAAI,MAAM,CAI1C;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CActD;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAehE;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,YAAY,IAAI,iBAAiB,EAAE,CAuBlD;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAQtD"}
@@ -0,0 +1,146 @@
1
+ import { mkdirSync, readFileSync, writeFileSync, existsSync, readdirSync, statSync, renameSync, } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { sessionsDir, sessionFile } from "./paths.js";
4
+ const SCHEMA_VERSION = 3;
5
+ // In-place migrations. Each `migrateVNtoVN+1` is idempotent on already-current
6
+ // data and pure: it mutates the parsed object in place but returns the same
7
+ // reference so callers can chain. v1 was pre-0.3 (no schema_version), v2 is
8
+ // v0.3 (tool calls + session approvals on SessionMeta), v3 is v0.4
9
+ // (coordinator state, plan, subtask states, role transcripts, cost, budgets).
10
+ function migrateV1toV2(parsed) {
11
+ if ((parsed.schema_version ?? 1) >= 2)
12
+ return parsed;
13
+ if (!parsed.meta.session_approved_categories)
14
+ parsed.meta.session_approved_categories = [];
15
+ if (!parsed.meta.tool_calls)
16
+ parsed.meta.tool_calls = [];
17
+ parsed.schema_version = 2;
18
+ parsed.meta.schema_version = 2;
19
+ return parsed;
20
+ }
21
+ function migrateV2toV3(parsed) {
22
+ if ((parsed.schema_version ?? 2) >= 3)
23
+ return parsed;
24
+ const meta = parsed.meta;
25
+ if (meta.coordinator_state === undefined)
26
+ meta.coordinator_state = "init";
27
+ if (meta.plan === undefined)
28
+ meta.plan = null;
29
+ if (!meta.subtask_states)
30
+ meta.subtask_states = {};
31
+ if (!meta.role_transcripts)
32
+ meta.role_transcripts = {};
33
+ if (!meta.cost) {
34
+ meta.cost = {
35
+ tokens_used: 0,
36
+ wall_clock_ms: 0,
37
+ tool_calls: 0,
38
+ tool_calls_by_subtask: {},
39
+ started_at: meta.started_at ?? new Date().toISOString(),
40
+ };
41
+ }
42
+ // v2 sessions are single-agent; v3 default for a migrated v2 session is
43
+ // single-agent (active_roles: []). Multi-agent sessions started fresh on v3
44
+ // have this field populated by the runner.
45
+ if (!meta.active_roles)
46
+ meta.active_roles = [];
47
+ if (!meta.budgets) {
48
+ meta.budgets = {
49
+ max_tokens: 50_000,
50
+ max_wall_clock_minutes: 20,
51
+ max_tool_calls_per_subtask: 15,
52
+ max_retries_per_subtask: 3,
53
+ };
54
+ }
55
+ if (!meta.coordinator_events)
56
+ meta.coordinator_events = [];
57
+ parsed.schema_version = 3;
58
+ meta.schema_version = 3;
59
+ return parsed;
60
+ }
61
+ function migrate(parsed) {
62
+ if ((parsed.schema_version ?? 1) > SCHEMA_VERSION) {
63
+ throw new Error(`Session schema version ${parsed.schema_version} is newer than this runtime (expects ${SCHEMA_VERSION}). Upgrade openwar.`);
64
+ }
65
+ parsed = migrateV1toV2(parsed);
66
+ parsed = migrateV2toV3(parsed);
67
+ return parsed;
68
+ }
69
+ export function ensureSessionsDir() {
70
+ const dir = sessionsDir();
71
+ mkdirSync(dir, { recursive: true });
72
+ return dir;
73
+ }
74
+ export function writeSession(state) {
75
+ ensureSessionsDir();
76
+ const path = sessionFile(state.meta.brief_id);
77
+ const payload = { schema_version: SCHEMA_VERSION, ...state };
78
+ // Write atomically: write to .tmp then rename.
79
+ const tmp = `${path}.tmp`;
80
+ writeFileSync(tmp, JSON.stringify(payload, null, 2), "utf8");
81
+ // On Windows rename over an existing file is supported when the target is closed.
82
+ // Fall back to a plain write on EPERM.
83
+ try {
84
+ renameSync(tmp, path);
85
+ }
86
+ catch {
87
+ writeFileSync(path, JSON.stringify(payload, null, 2), "utf8");
88
+ }
89
+ }
90
+ export function readSession(briefId) {
91
+ const path = sessionFile(briefId);
92
+ if (!existsSync(path))
93
+ return null;
94
+ const raw = readFileSync(path, "utf8");
95
+ let parsed;
96
+ try {
97
+ parsed = JSON.parse(raw);
98
+ }
99
+ catch (err) {
100
+ throw new Error(`Session file at ${path} is not valid JSON: ${err.message}`);
101
+ }
102
+ parsed = migrate(parsed);
103
+ // Discard the schema_version field at the API boundary.
104
+ const { schema_version: _v, ...rest } = parsed;
105
+ void _v;
106
+ return rest;
107
+ }
108
+ export function listSessions() {
109
+ const dir = sessionsDir();
110
+ if (!existsSync(dir))
111
+ return [];
112
+ const entries = [];
113
+ for (const file of readdirSync(dir)) {
114
+ if (!file.endsWith(".json"))
115
+ continue;
116
+ const path = join(dir, file);
117
+ try {
118
+ const raw = readFileSync(path, "utf8");
119
+ const parsed = JSON.parse(raw);
120
+ entries.push({
121
+ brief_id: parsed.meta.brief_id,
122
+ project: parsed.meta.project,
123
+ phase: parsed.meta.phase,
124
+ updated_at: parsed.meta.updated_at,
125
+ path,
126
+ });
127
+ }
128
+ catch {
129
+ // Skip unreadable files; do not abort the listing.
130
+ }
131
+ }
132
+ entries.sort((a, b) => b.updated_at.localeCompare(a.updated_at));
133
+ return entries;
134
+ }
135
+ export function sessionExists(briefId) {
136
+ const path = sessionFile(briefId);
137
+ if (!existsSync(path))
138
+ return false;
139
+ try {
140
+ return statSync(path).isFile();
141
+ }
142
+ catch {
143
+ return false;
144
+ }
145
+ }
146
+ //# sourceMappingURL=persist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persist.js","sourceRoot":"","sources":["../../src/state/persist.ts"],"names":[],"mappings":"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"}