strom-research 1.1.1 → 1.3.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 (50) hide show
  1. package/README.md +6 -1
  2. package/assets/lang/cs.json +177 -6
  3. package/assets/lang/de.json +177 -6
  4. package/assets/method/core.md +6 -2
  5. package/assets/method/reading.md +2 -1
  6. package/assets/plugins/README.md +16 -2
  7. package/assets/plugins/gates/README.md +95 -0
  8. package/assets/plugins/gates/claude-usage/gate.json +10 -0
  9. package/assets/plugins/gates/claude-usage/gate.ts +125 -0
  10. package/assets/plugins/hooks/README.md +91 -0
  11. package/dist/agents/global.js +10 -0
  12. package/dist/agents/launch.js +1 -1
  13. package/dist/brief/brief.js +2 -0
  14. package/dist/cli/main.js +43 -2
  15. package/dist/cli/menu-parts.js +140 -0
  16. package/dist/cli/menu-research.js +194 -0
  17. package/dist/cli/menu-settings.js +273 -0
  18. package/dist/cli/menu-waiting.js +79 -0
  19. package/dist/cli/menu.js +113 -99
  20. package/dist/cli/ui.js +175 -5
  21. package/dist/cli/wizard.js +48 -2
  22. package/dist/commands/browse.js +4 -3
  23. package/dist/commands/connectors.js +25 -2
  24. package/dist/commands/gates.js +58 -0
  25. package/dist/commands/hooks.js +141 -0
  26. package/dist/commands/index.js +2 -0
  27. package/dist/commands/intake.js +2 -2
  28. package/dist/commands/research.js +60 -17
  29. package/dist/commands/session.js +161 -18
  30. package/dist/commands/setup.js +57 -1
  31. package/dist/commands/sources.js +24 -0
  32. package/dist/commands/start.js +5 -1
  33. package/dist/commands/tasks.js +41 -4
  34. package/dist/core/browser.js +50 -0
  35. package/dist/core/clock.js +55 -0
  36. package/dist/core/config.js +18 -0
  37. package/dist/core/gate.js +175 -0
  38. package/dist/core/hooks.js +210 -0
  39. package/dist/core/media.js +21 -7
  40. package/dist/core/overview.js +2 -0
  41. package/dist/core/phrases.js +1 -0
  42. package/dist/core/relocate.js +111 -0
  43. package/dist/core/tree.js +19 -2
  44. package/dist/runners/antigravity.js +2 -1
  45. package/dist/runners/claude.js +160 -114
  46. package/dist/runners/codex.js +14 -1
  47. package/dist/runners/jsonl.js +63 -37
  48. package/dist/runners/opencode.js +7 -2
  49. package/dist/runners/script.js +56 -47
  50. package/package.json +1 -1
@@ -7,52 +7,61 @@ import { appendLog, looksLikeLimit, stopTree } from "./runner.js";
7
7
  export const scriptRunner = {
8
8
  id: "script",
9
9
  command: process.execPath,
10
- run(opts) {
11
- const script = opts.env.STROM_RUNNER_SCRIPT;
12
- return new Promise((resolve) => {
13
- if (!script)
14
- return resolve({ exitCode: 2, outcome: "error", text: "STROM_RUNNER_SCRIPT is not set", metrics: {} });
15
- const child = spawn(process.execPath, [script, ...(opts.extraArgs ?? [])], {
16
- cwd: opts.cwd,
17
- env: { ...opts.env, STROM_PROMPT: opts.prompt },
18
- stdio: ["pipe", "pipe", "pipe"],
19
- });
20
- child.stdin.end(opts.prompt);
21
- let timedOut = false;
22
- const timer = opts.timeoutMs
23
- ? setTimeout(() => {
24
- timedOut = true;
25
- stopTree(child);
26
- }, opts.timeoutMs)
27
- : undefined;
28
- opts.signal?.addEventListener("abort", () => stopTree(child), { once: true });
29
- let out = "";
30
- const denied = [];
31
- const on = (d) => {
32
- for (const l of d.toString("utf8").split("\n"))
33
- if (l.startsWith("denied: "))
34
- denied.push(l.slice(8).trim());
35
- out += d.toString("utf8");
36
- appendLog(opts.logFile, d.toString("utf8"));
37
- for (const l of d.toString("utf8").split("\n"))
38
- if (l.trim())
39
- opts.onProgress?.(l.trim().slice(0, 160));
40
- };
41
- child.stdout.on("data", on);
42
- child.stderr.on("data", on);
43
- child.on("close", (code) => {
44
- if (timer)
45
- clearTimeout(timer);
46
- const limit = looksLikeLimit(out);
47
- resolve({
48
- exitCode: code ?? 1,
49
- outcome: opts.signal?.aborted ? "stopped" : timedOut ? "timeout" : limit.limit ? "limit" : code === 0 ? "ok" : "error",
50
- text: out.trim().split("\n").slice(-5).join("\n"),
51
- metrics: { turns: 1, ...(denied.length ? { denied: denied.length } : {}) },
52
- ...(limit.resumeAt ? { resumeAt: limit.resumeAt } : {}),
53
- ...(denied.length ? { denied } : {}),
54
- });
55
- });
56
- });
10
+ async run(opts) {
11
+ const first = await once(opts, opts.prompt, opts.timeoutMs, false);
12
+ if (first.outcome !== "timeout" || !opts.wrapUp || opts.signal?.aborted)
13
+ return first;
14
+ // Stopped at its limit: resumed with the message to write down what it found (STROM_WRAP_UP=1).
15
+ opts.onProgress?.("time limit reached — the agent gets time to write down what it found");
16
+ const more = await once(opts, opts.wrapUp.prompt, opts.wrapUp.ms, true);
17
+ return { ...more, outcome: "timeout" };
57
18
  },
58
19
  };
20
+ function once(opts, prompt, timeoutMs, wrapUp) {
21
+ const script = opts.env.STROM_RUNNER_SCRIPT;
22
+ return new Promise((resolve) => {
23
+ if (!script)
24
+ return resolve({ exitCode: 2, outcome: "error", text: "STROM_RUNNER_SCRIPT is not set", metrics: {} });
25
+ const child = spawn(process.execPath, [script, ...(opts.extraArgs ?? [])], {
26
+ cwd: opts.cwd,
27
+ env: { ...opts.env, STROM_PROMPT: prompt, ...(wrapUp ? { STROM_WRAP_UP: "1" } : {}) },
28
+ stdio: ["pipe", "pipe", "pipe"],
29
+ });
30
+ child.stdin.end(prompt);
31
+ let timedOut = false;
32
+ const timer = timeoutMs
33
+ ? setTimeout(() => {
34
+ timedOut = true;
35
+ stopTree(child);
36
+ }, timeoutMs)
37
+ : undefined;
38
+ opts.signal?.addEventListener("abort", () => stopTree(child), { once: true });
39
+ let out = "";
40
+ const denied = [];
41
+ const on = (d) => {
42
+ for (const l of d.toString("utf8").split("\n"))
43
+ if (l.startsWith("denied: "))
44
+ denied.push(l.slice(8).trim());
45
+ out += d.toString("utf8");
46
+ appendLog(opts.logFile, d.toString("utf8"));
47
+ for (const l of d.toString("utf8").split("\n"))
48
+ if (l.trim())
49
+ opts.onProgress?.(l.trim().slice(0, 160));
50
+ };
51
+ child.stdout.on("data", on);
52
+ child.stderr.on("data", on);
53
+ child.on("close", (code) => {
54
+ if (timer)
55
+ clearTimeout(timer);
56
+ const limit = looksLikeLimit(out);
57
+ resolve({
58
+ exitCode: code ?? 1,
59
+ outcome: opts.signal?.aborted ? "stopped" : timedOut ? "timeout" : limit.limit ? "limit" : code === 0 ? "ok" : "error",
60
+ text: out.trim().split("\n").slice(-5).join("\n"),
61
+ metrics: { turns: 1, ...(denied.length ? { denied: denied.length } : {}) },
62
+ ...(limit.resumeAt ? { resumeAt: limit.resumeAt } : {}),
63
+ ...(denied.length ? { denied } : {}),
64
+ });
65
+ });
66
+ });
67
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "strom-research",
3
- "version": "1.1.1",
3
+ "version": "1.3.0",
4
4
  "description": "Genealogical research toolkit for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {