@oharness/engine 0.6.0 → 0.7.1

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 (90) hide show
  1. package/dist/agent/agent.d.ts +83 -0
  2. package/dist/agent/agent.js +112 -1
  3. package/dist/agent/agent.js.map +1 -1
  4. package/dist/agent/memory-backup.d.ts +2 -0
  5. package/dist/agent/memory-backup.js +9 -1
  6. package/dist/agent/memory-backup.js.map +1 -1
  7. package/dist/agent/memory-limits.js +8 -1
  8. package/dist/agent/memory-limits.js.map +1 -1
  9. package/dist/agent/memory-usage.d.ts +1 -1
  10. package/dist/agent/memory-usage.js +2 -3
  11. package/dist/agent/memory-usage.js.map +1 -1
  12. package/dist/agent/memory.d.ts +3 -0
  13. package/dist/agent/memory.js +6 -18
  14. package/dist/agent/memory.js.map +1 -1
  15. package/dist/agent/session.d.ts +9 -0
  16. package/dist/agent/session.js +14 -2
  17. package/dist/agent/session.js.map +1 -1
  18. package/dist/agent/settings.js +3 -2
  19. package/dist/agent/settings.js.map +1 -1
  20. package/dist/agent/store.d.ts +45 -4
  21. package/dist/agent/store.js +198 -25
  22. package/dist/agent/store.js.map +1 -1
  23. package/dist/artifacts/files.d.ts +52 -0
  24. package/dist/artifacts/files.js +169 -0
  25. package/dist/artifacts/files.js.map +1 -0
  26. package/dist/auth/store.js +3 -2
  27. package/dist/auth/store.js.map +1 -1
  28. package/dist/config-files.js +3 -2
  29. package/dist/config-files.js.map +1 -1
  30. package/dist/config.d.ts +6 -1
  31. package/dist/config.js +10 -2
  32. package/dist/config.js.map +1 -1
  33. package/dist/harness.d.ts +62 -1
  34. package/dist/harness.js +174 -12
  35. package/dist/harness.js.map +1 -1
  36. package/dist/paths.d.ts +5 -0
  37. package/dist/paths.js +21 -3
  38. package/dist/paths.js.map +1 -1
  39. package/dist/providers/builtin.d.ts +2 -0
  40. package/dist/providers/builtin.js +38 -24
  41. package/dist/providers/builtin.js.map +1 -1
  42. package/dist/providers/catalog.d.ts +5 -0
  43. package/dist/providers/catalog.js +32 -1
  44. package/dist/providers/catalog.js.map +1 -1
  45. package/dist/providers/catalog.json +241 -123
  46. package/dist/providers/discovery.js +17 -0
  47. package/dist/providers/discovery.js.map +1 -1
  48. package/dist/providers/models-dev.d.ts +89 -0
  49. package/dist/providers/models-dev.js +160 -0
  50. package/dist/providers/models-dev.js.map +1 -0
  51. package/dist/providers/models-dev.json +821 -0
  52. package/dist/providers/registry.d.ts +12 -0
  53. package/dist/providers/registry.js +33 -1
  54. package/dist/providers/registry.js.map +1 -1
  55. package/dist/providers/types.d.ts +21 -0
  56. package/dist/providers/types.js +16 -0
  57. package/dist/providers/types.js.map +1 -1
  58. package/dist/runtime-plugins/builtin/memory-migrate.d.ts +5 -21
  59. package/dist/runtime-plugins/builtin/memory-migrate.js +5 -125
  60. package/dist/runtime-plugins/builtin/memory-migrate.js.map +1 -1
  61. package/dist/runtime-plugins/builtin/memory.d.ts +3 -0
  62. package/dist/runtime-plugins/builtin/memory.js +12 -10
  63. package/dist/runtime-plugins/builtin/memory.js.map +1 -1
  64. package/dist/schedule/clock.d.ts +76 -0
  65. package/dist/schedule/clock.js +147 -0
  66. package/dist/schedule/clock.js.map +1 -0
  67. package/dist/schedule/cron.d.ts +9 -0
  68. package/dist/schedule/cron.js +18 -0
  69. package/dist/schedule/cron.js.map +1 -1
  70. package/dist/schedule/lock.d.ts +38 -0
  71. package/dist/schedule/lock.js +100 -0
  72. package/dist/schedule/lock.js.map +1 -0
  73. package/dist/schedule/runner.d.ts +67 -0
  74. package/dist/schedule/runner.js +100 -0
  75. package/dist/schedule/runner.js.map +1 -0
  76. package/dist/schedule/scheduler.d.ts +56 -15
  77. package/dist/schedule/scheduler.js +80 -107
  78. package/dist/schedule/scheduler.js.map +1 -1
  79. package/dist/storage/kv.js +3 -2
  80. package/dist/storage/kv.js.map +1 -1
  81. package/dist/storage/project.d.ts +26 -0
  82. package/dist/storage/project.js +74 -15
  83. package/dist/storage/project.js.map +1 -1
  84. package/dist/tools/builtin/routine.d.ts +31 -0
  85. package/dist/tools/builtin/routine.js +70 -0
  86. package/dist/tools/builtin/routine.js.map +1 -0
  87. package/dist/util/fs.d.ts +6 -0
  88. package/dist/util/fs.js +22 -0
  89. package/dist/util/fs.js.map +1 -0
  90. package/package.json +3 -3
@@ -3,15 +3,37 @@ import { appendFile, mkdir, readFile } from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { ConfigError, errorMessage } from "../core/errors.js";
5
5
  import { messageText } from "../core/types.js";
6
- import { createLogger } from "../util/logger.js";
7
6
  import { parseJson } from "../util/json.js";
8
7
  import { nextRun, parseCron } from "./cron.js";
9
8
  const MAX_OUTPUT_CHARS = 4_000;
10
9
  /**
11
- * Runs prompts on a cron schedule.
10
+ * Minutes a routine starts after its scheduled time, the same every time for
11
+ * the same routine.
12
12
  *
13
- * Each firing gets its own session rather than appending to a long-lived one:
14
- * a nightly job that shares context with every previous night would compact
13
+ * "Every day at 9" is what most people write, and every copy firing at 9:00:00
14
+ * is a queue at the gateway at 9:00:00. A few minutes, fixed by the name so a
15
+ * routine keeps its own slot rather than wandering, and none at all for one
16
+ * that fires more than once an hour, where a few minutes is most of its
17
+ * interval.
18
+ */
19
+ export function staggerMinutes(def, fields) {
20
+ if (fields.minute.size !== 1)
21
+ return 0;
22
+ let hash = 2166136261;
23
+ for (const char of def.name) {
24
+ hash ^= char.charCodeAt(0);
25
+ hash = Math.imul(hash, 16777619);
26
+ }
27
+ return (hash >>> 0) % 5;
28
+ }
29
+ /**
30
+ * Holds routines, runs them, and keeps their history.
31
+ *
32
+ * It does not watch the clock: RoutineClock does, for every project at once,
33
+ * and asks the scheduler of each routine's own project to run it.
34
+ *
35
+ * Each run gets its own session rather than appending to a long-lived one: a
36
+ * nightly job that shares context with every previous night would compact
15
37
  * itself into uselessness within a week, and a failure would poison every
16
38
  * subsequent run.
17
39
  */
@@ -20,8 +42,6 @@ export class Scheduler {
20
42
  logger;
21
43
  schedules = new Map();
22
44
  runDir;
23
- timer;
24
- running = false;
25
45
  /** Names currently executing, so a slow job cannot overlap itself. */
26
46
  inFlight = new Set();
27
47
  constructor(harness, definitions = [], opts = {}) {
@@ -50,11 +70,14 @@ export class Scheduler {
50
70
  const out = [];
51
71
  for (const { def, fields } of this.schedules.values()) {
52
72
  const enabled = def.enabled !== false;
73
+ const next = enabled ? nextRun(fields)?.getTime() : undefined;
53
74
  out.push({
54
75
  name: def.name,
55
76
  cron: def.cron,
56
77
  enabled,
57
- nextRunAt: enabled ? nextRun(fields)?.getTime() : undefined,
78
+ // When it will actually start, stagger included: the panel saying
79
+ // 9:00 for a run that begins at 9:03 is a small lie told daily.
80
+ nextRunAt: next === undefined ? undefined : next + staggerMinutes(def, fields) * 60_000,
58
81
  lastRun: await this.lastRun(def.name),
59
82
  });
60
83
  }
@@ -73,62 +96,31 @@ export class Scheduler {
73
96
  return this.execute(entry.def);
74
97
  }
75
98
  /**
76
- * Start firing on schedule.
99
+ * Run a definition in this harness, whether or not this scheduler holds it.
77
100
  *
78
- * Wakes every 30s and fires anything whose minute has arrived, rather than
79
- * sleeping until the exact next occurrence: a laptop that suspends would
80
- * otherwise wake with a timer scheduled for a moment that has passed.
101
+ * For the clock, which watches routines across projects: it decides what is
102
+ * due, and each routine runs in the harness of the directory it names — the
103
+ * project's instructions, MCP servers and permission rules — rather than in
104
+ * whichever project happened to notice the minute arrive.
81
105
  */
82
- start() {
83
- if (this.running)
84
- return;
85
- this.running = true;
86
- let lastMinute = -1;
87
- const tick = () => {
88
- const now = new Date();
89
- const minute = Math.floor(now.getTime() / 60_000);
90
- // Only evaluate once per wall-clock minute, however often we wake.
91
- if (minute === lastMinute)
92
- return;
93
- lastMinute = minute;
94
- for (const { def, fields } of this.schedules.values()) {
95
- if (def.enabled === false)
96
- continue;
97
- if (!matchesNow(fields, now))
98
- continue;
99
- if (this.inFlight.has(def.name)) {
100
- // A run still going when the next occurrence arrives means the job
101
- // is slower than its interval; skipping is safer than piling up.
102
- this.logger.warn("skipping overlapping run", { schedule: def.name });
103
- continue;
104
- }
105
- void this.execute(def);
106
- }
107
- };
108
- this.timer = setInterval(tick, 30_000);
109
- // Do not hold the process open on our account; the CLI daemon decides.
110
- this.timer.unref?.();
111
- tick();
112
- }
113
- stop() {
114
- this.running = false;
115
- if (this.timer)
116
- clearInterval(this.timer);
117
- this.timer = undefined;
118
- }
119
- /** Resolves when every in-flight run has finished. */
120
- async drain() {
121
- while (this.inFlight.size > 0) {
122
- await new Promise((resolve) => setTimeout(resolve, 50));
106
+ async runDefinition(def, meta = {}) {
107
+ if (this.inFlight.has(def.name)) {
108
+ this.logger.warn("skipping overlapping run", { schedule: def.name });
109
+ return undefined;
123
110
  }
111
+ return this.execute(def, meta);
124
112
  }
125
- async execute(def) {
113
+ isRunning(name) {
114
+ return this.inFlight.has(name);
115
+ }
116
+ async execute(def, meta = {}) {
126
117
  this.inFlight.add(def.name);
127
118
  const startedAt = Date.now();
128
- this.logger.info("running schedule", { schedule: def.name });
119
+ this.logger.info("running schedule", { schedule: def.name, ...meta });
129
120
  const session = this.harness.createSession({
130
121
  model: def.model,
131
- title: `schedule: ${def.name}`,
122
+ title: def.name,
123
+ routine: def.name,
132
124
  });
133
125
  const agent = this.harness.agent(session, {
134
126
  // Nobody is at the keyboard to approve anything.
@@ -168,70 +160,51 @@ export class Scheduler {
168
160
  costUsd: session.costUsd,
169
161
  output: output.slice(0, MAX_OUTPUT_CHARS),
170
162
  ...(error ? { error } : {}),
163
+ ...(meta.scheduledFor !== undefined ? { scheduledFor: meta.scheduledFor } : {}),
164
+ ...(meta.catchUp ? { catchUp: true } : {}),
171
165
  };
172
- await this.recordRun(run).catch((err) => this.logger.warn("could not record the run", { error: String(err) }));
166
+ await appendRun(this.runDir, run).catch((err) => this.logger.warn("could not record the run", { error: String(err) }));
173
167
  return run;
174
168
  }
175
- async recordRun(run) {
176
- await mkdir(this.runDir, { recursive: true });
177
- await appendFile(path.join(this.runDir, `${safeName(run.schedule)}.jsonl`), `${JSON.stringify(run)}\n`, "utf8");
178
- }
179
169
  async lastRun(name) {
180
- let raw;
181
- try {
182
- raw = await readFile(path.join(this.runDir, `${safeName(name)}.jsonl`), "utf8");
183
- }
184
- catch {
185
- return undefined;
186
- }
187
- const lines = raw.split("\n").filter((line) => line.trim() !== "");
188
- for (let i = lines.length - 1; i >= 0; i--) {
189
- const parsed = parseJson(lines[i]);
190
- if (parsed.ok)
191
- return parsed.value;
170
+ const runs = await readRuns(this.runDir, name);
171
+ for (let i = runs.length - 1; i >= 0; i--) {
172
+ if (!runs[i].skipped)
173
+ return runs[i];
192
174
  }
193
175
  return undefined;
194
176
  }
195
- /** Past runs, newest first. */
177
+ /** Past runs and skipped times, newest first. */
196
178
  async history(name, limit = 20) {
197
- let raw;
198
- try {
199
- raw = await readFile(path.join(this.runDir, `${safeName(name)}.jsonl`), "utf8");
200
- }
201
- catch {
202
- return [];
203
- }
204
- const runs = [];
205
- for (const line of raw.split("\n")) {
206
- if (line.trim() === "")
207
- continue;
208
- const parsed = parseJson(line);
209
- if (parsed.ok)
210
- runs.push(parsed.value);
211
- }
212
- return runs.reverse().slice(0, limit);
179
+ return (await readRuns(this.runDir, name)).reverse().slice(0, limit);
213
180
  }
214
181
  }
182
+ /** Add one line to a routine's history. */
183
+ export async function appendRun(runDir, run) {
184
+ await mkdir(runDir, { recursive: true });
185
+ await appendFile(path.join(runDir, `${safeName(run.schedule)}.jsonl`), `${JSON.stringify(run)}\n`, "utf8");
186
+ }
187
+ /** A routine's history, oldest first. Lines that do not parse are passed over. */
188
+ export async function readRuns(runDir, name) {
189
+ let raw;
190
+ try {
191
+ raw = await readFile(path.join(runDir, `${safeName(name)}.jsonl`), "utf8");
192
+ }
193
+ catch {
194
+ return [];
195
+ }
196
+ const runs = [];
197
+ for (const line of raw.split("\n")) {
198
+ if (line.trim() === "")
199
+ continue;
200
+ const parsed = parseJson(line);
201
+ if (parsed.ok)
202
+ runs.push(parsed.value);
203
+ }
204
+ return runs;
205
+ }
215
206
  /** A schedule name becomes a filename, so keep it to safe characters. */
216
207
  function safeName(name) {
217
208
  return name.replace(/[^A-Za-z0-9._-]/g, "_");
218
209
  }
219
- function matchesNow(fields, now) {
220
- // `matches` is minute-granular and `now` carries seconds; zero them so a
221
- // tick at 12:00:37 still counts as 12:00.
222
- const minute = new Date(now.getTime());
223
- minute.setSeconds(0, 0);
224
- return matchesMinute(fields, minute);
225
- }
226
- function matchesMinute(fields, date) {
227
- if (!fields.minute.has(date.getMinutes()))
228
- return false;
229
- if (!fields.hour.has(date.getHours()))
230
- return false;
231
- if (!fields.month.has(date.getMonth() + 1))
232
- return false;
233
- const dom = fields.dayOfMonth.has(date.getDate());
234
- const dow = fields.dayOfWeek.has(date.getDay());
235
- return fields.dayFieldsAreOr ? dom || dow : dom && dow;
236
- }
237
210
  //# sourceMappingURL=scheduler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/schedule/scheduler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/schedule/scheduler.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
- import { appendFile, mkdir, open, readFile, readdir, rename, rm, writeFile } from "node:fs/promises";
1
+ import { appendFile, mkdir, open, readFile, readdir, rm, writeFile } from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { parseJson } from "../util/json.js";
4
+ import { renameWithRetry } from "../util/fs.js";
4
5
  /**
5
6
  * A directory of JSON files, addressed by key.
6
7
  *
@@ -50,7 +51,7 @@ export class JsonStore {
50
51
  await mkdir(path.dirname(target), { recursive: true });
51
52
  const temp = `${target}.${process.pid}.${(tempSeq += 1)}.tmp`;
52
53
  await writeFile(temp, `${JSON.stringify(value, null, 2)}\n`, "utf8");
53
- await rename(temp, target);
54
+ await renameWithRetry(temp, target);
54
55
  }
55
56
  async remove(key) {
56
57
  await rm(this.file(key), { force: true });
@@ -1 +1 @@
1
- {"version":3,"file":"kv.js","sourceRoot":"","sources":["../../src/storage/kv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrG,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,SAAS;IACX,IAAI,CAAS;IAEtB,YAAY,IAAY;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,8BAA8B;IAC9B,IAAI,CAAC,GAAa;QAChB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,GAAG,OAAO,CAAC;IAChD,CAAC;IAED,yBAAyB;IACzB,GAAG,CAAC,GAAa;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,GAAG,QAAQ,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,IAAI,CAAI,GAAa;QACzB,IAAI,GAAW,CAAC;QAChB,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,MAAM,GAAG,SAAS,CAAI,GAAG,CAAC,CAAC;QACjC,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9C,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,KAAK,CAAC,GAAa,EAAE,KAAc;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,MAAM,CAAC;QAC9D,MAAM,SAAS,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACrE,MAAM,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAa;QACxB,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,GAAa;QAC3B,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,8DAA8D;IAC9D,KAAK,CAAC,IAAI,CAAC,MAAgB;QACzB,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,QAAQ,CAAC,MAAgB;QAC7B,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,MAAgB,EAAE,GAAW;QACnD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC;QAC7C,MAAM,GAAG,GAAe,EAAE,CAAC;QAE3B,MAAM,IAAI,GAAG,KAAK,EAAE,GAAW,EAAE,KAAe,EAAiB,EAAE;YACjE,IAAI,OAAO,CAAC;YACZ,IAAI,CAAC;gBACH,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YACxD,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO;YACT,CAAC;YACD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;oBACxB,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;gBACjE,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;oBACpC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;gBACpE,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACrB,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAa,EAAE,KAAgB;QAC1C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,MAAM,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;IAChG,CAAC;IAED,gFAAgF;IAChF,KAAK,CAAC,UAAU,CAAC,GAAa,EAAE,KAAgB;QAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClE,MAAM,SAAS,CAAC,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,MAAM,CAAC,CAAC;IAClE,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,OAAO,CAAI,GAAa,EAAE,QAAiB;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,GAAW,CAAC;QAEhB,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACvC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,MAAM,CAAC;YACX,IAAI,CAAC;gBACH,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YACnC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBACrC,MAAM,KAAK,GAAG,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;gBACpD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;gBACtD,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;gBACnD,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAC9B,kEAAkE;gBAClE,qDAAqD;gBACrD,IAAI,KAAK,GAAG,CAAC;oBAAE,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YACxD,CAAC;oBAAS,CAAC;gBACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACvB,CAAC;QACH,CAAC;QAED,MAAM,GAAG,GAAQ,EAAE,CAAC;QACpB,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;gBAAE,SAAS;YACjC,MAAM,MAAM,GAAG,SAAS,CAAI,IAAI,CAAC,CAAC;YAClC,IAAI,MAAM,CAAC,EAAE;gBAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;CACF;AAED;;;;;GAKG;AACH,IAAI,OAAO,GAAG,CAAC,CAAC"}
1
+ {"version":3,"file":"kv.js","sourceRoot":"","sources":["../../src/storage/kv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7F,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,SAAS;IACX,IAAI,CAAS;IAEtB,YAAY,IAAY;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,8BAA8B;IAC9B,IAAI,CAAC,GAAa;QAChB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,GAAG,OAAO,CAAC;IAChD,CAAC;IAED,yBAAyB;IACzB,GAAG,CAAC,GAAa;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,GAAG,QAAQ,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,IAAI,CAAI,GAAa;QACzB,IAAI,GAAW,CAAC;QAChB,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,MAAM,GAAG,SAAS,CAAI,GAAG,CAAC,CAAC;QACjC,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9C,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,KAAK,CAAC,GAAa,EAAE,KAAc;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,MAAM,CAAC;QAC9D,MAAM,SAAS,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACrE,MAAM,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAa;QACxB,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,GAAa;QAC3B,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,8DAA8D;IAC9D,KAAK,CAAC,IAAI,CAAC,MAAgB;QACzB,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,QAAQ,CAAC,MAAgB;QAC7B,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,MAAgB,EAAE,GAAW;QACnD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC;QAC7C,MAAM,GAAG,GAAe,EAAE,CAAC;QAE3B,MAAM,IAAI,GAAG,KAAK,EAAE,GAAW,EAAE,KAAe,EAAiB,EAAE;YACjE,IAAI,OAAO,CAAC;YACZ,IAAI,CAAC;gBACH,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YACxD,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO;YACT,CAAC;YACD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;oBACxB,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;gBACjE,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;oBACpC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;gBACpE,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACrB,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAa,EAAE,KAAgB;QAC1C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,MAAM,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;IAChG,CAAC;IAED,gFAAgF;IAChF,KAAK,CAAC,UAAU,CAAC,GAAa,EAAE,KAAgB;QAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClE,MAAM,SAAS,CAAC,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,MAAM,CAAC,CAAC;IAClE,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,OAAO,CAAI,GAAa,EAAE,QAAiB;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,GAAW,CAAC;QAEhB,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACvC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,MAAM,CAAC;YACX,IAAI,CAAC;gBACH,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YACnC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBACrC,MAAM,KAAK,GAAG,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;gBACpD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;gBACtD,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;gBACnD,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAC9B,kEAAkE;gBAClE,qDAAqD;gBACrD,IAAI,KAAK,GAAG,CAAC;oBAAE,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YACxD,CAAC;oBAAS,CAAC;gBACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACvB,CAAC;QACH,CAAC;QAED,MAAM,GAAG,GAAQ,EAAE,CAAC;QACpB,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;gBAAE,SAAS;YACjC,MAAM,MAAM,GAAG,SAAS,CAAI,IAAI,CAAC,CAAC;YAClC,IAAI,MAAM,CAAC,EAAE;gBAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;CACF;AAED;;;;;GAKG;AACH,IAAI,OAAO,GAAG,CAAC,CAAC"}
@@ -1,4 +1,30 @@
1
+ /**
2
+ * The identity of a project, as something other than its path.
3
+ *
4
+ * Sessions have to belong to something stable. A working directory is not:
5
+ * clones land in different places, worktrees multiply, and a renamed folder
6
+ * would orphan every transcript recorded under the old name — which is exactly
7
+ * how a session list "loses" work that is still on disk.
8
+ *
9
+ * Registered projects carry that identity in `.oharness/project.json`. Git
10
+ * repositories use their root commit when the manifest is first created, so
11
+ * separately opened clones still meet as one project. Other directories get
12
+ * a random id. The path hash remains only as a read-only fallback for callers
13
+ * that inspect a directory before it has been registered.
14
+ */
15
+ export interface ProjectManifest {
16
+ version: 1;
17
+ id: string;
18
+ name: string;
19
+ createdAt: number;
20
+ }
1
21
  export declare function projectId(cwd: string): Promise<string>;
22
+ /** Read the small, non-executable identity document carried by a project. */
23
+ export declare function readProjectManifest(cwd: string): Promise<ProjectManifest | undefined>;
24
+ /** Ensure a registered project has an identity that survives moves and exports. */
25
+ export declare function ensureProjectManifest(cwd: string): Promise<ProjectManifest>;
26
+ /** Change only the display name; identity and creation time never change. */
27
+ export declare function renameProjectManifest(cwd: string, name: string): Promise<ProjectManifest>;
2
28
  export interface ProjectRecord {
3
29
  id: string;
4
30
  vcs: "git" | "none";
@@ -1,20 +1,11 @@
1
1
  import { execFile } from "node:child_process";
2
- import { createHash } from "node:crypto";
3
- import { realpath } from "node:fs/promises";
2
+ import { createHash, randomUUID } from "node:crypto";
3
+ import { mkdir, readFile, realpath, rm, writeFile } from "node:fs/promises";
4
4
  import path from "node:path";
5
- /**
6
- * The identity of a project, as something other than its path.
7
- *
8
- * Sessions have to belong to something stable. A working directory is not:
9
- * clones land in different places, worktrees multiply, and a renamed folder
10
- * would orphan every transcript recorded under the old name — which is exactly
11
- * how a session list "loses" work that is still on disk.
12
- *
13
- * So a git repository is identified by its root commit, which every clone and
14
- * every worktree of that repository shares and which nothing can rename.
15
- * Anything else falls back to a hash of the resolved path, which at least
16
- * survives symlinks and trailing slashes.
17
- */
5
+ import { projectPath } from "../paths.js";
6
+ import { renameWithRetry } from "../util/fs.js";
7
+ const MANIFEST = "project.json";
8
+ const PROJECT_ID = /^(?:project_[a-f0-9]{32}|[a-f0-9]{40,64})$/;
18
9
  const cache = new Map();
19
10
  export function projectId(cwd) {
20
11
  const key = path.resolve(cwd);
@@ -26,12 +17,80 @@ export function projectId(cwd) {
26
17
  return pending;
27
18
  }
28
19
  async function resolve(cwd) {
20
+ const manifest = await readProjectManifest(cwd);
21
+ if (manifest)
22
+ return manifest.id;
29
23
  const root = await rootCommit(cwd);
30
24
  if (root)
31
25
  return root;
32
26
  const real = await realpath(cwd).catch(() => cwd);
33
27
  return `dir-${createHash("sha256").update(real).digest("hex").slice(0, 16)}`;
34
28
  }
29
+ /** Read the small, non-executable identity document carried by a project. */
30
+ export async function readProjectManifest(cwd) {
31
+ let value;
32
+ try {
33
+ value = JSON.parse(await readFile(projectPath(cwd, MANIFEST), "utf8"));
34
+ }
35
+ catch {
36
+ return undefined;
37
+ }
38
+ if (!value || typeof value !== "object" || Array.isArray(value))
39
+ return undefined;
40
+ const one = value;
41
+ if (one.version !== 1 || typeof one.id !== "string" || !PROJECT_ID.test(one.id))
42
+ return undefined;
43
+ if (typeof one.name !== "string" || !one.name.trim() || !Number.isSafeInteger(one.createdAt))
44
+ return undefined;
45
+ return { version: 1, id: one.id, name: one.name.trim(), createdAt: one.createdAt };
46
+ }
47
+ /** Ensure a registered project has an identity that survives moves and exports. */
48
+ export async function ensureProjectManifest(cwd) {
49
+ const resolved = path.resolve(cwd);
50
+ await Promise.all([
51
+ mkdir(path.join(resolved, "MEMORY"), { recursive: true }),
52
+ mkdir(path.join(resolved, "ARTIFACTS"), { recursive: true }),
53
+ ]);
54
+ const existing = await readProjectManifest(resolved);
55
+ if (existing) {
56
+ cache.set(resolved, Promise.resolve(existing.id));
57
+ return existing;
58
+ }
59
+ const root = await rootCommit(resolved);
60
+ const manifest = {
61
+ version: 1,
62
+ id: root ?? `project_${randomUUID().replaceAll("-", "")}`,
63
+ name: path.basename(resolved) || resolved,
64
+ createdAt: Date.now(),
65
+ };
66
+ await writeManifest(resolved, manifest);
67
+ cache.set(resolved, Promise.resolve(manifest.id));
68
+ return manifest;
69
+ }
70
+ /** Change only the display name; identity and creation time never change. */
71
+ export async function renameProjectManifest(cwd, name) {
72
+ const current = await ensureProjectManifest(cwd);
73
+ const next = { ...current, name: name.trim() };
74
+ if (!next.name)
75
+ throw new Error("project name is required");
76
+ await writeManifest(cwd, next);
77
+ return next;
78
+ }
79
+ function asyncTemp(file) {
80
+ return `${file}.${process.pid}.${randomUUID()}.tmp`;
81
+ }
82
+ async function writeManifest(cwd, manifest) {
83
+ const file = projectPath(cwd, MANIFEST);
84
+ await mkdir(path.dirname(file), { recursive: true });
85
+ const temp = asyncTemp(file);
86
+ try {
87
+ await writeFile(temp, `${JSON.stringify(manifest, null, 2)}\n`, { encoding: "utf8", flag: "wx" });
88
+ await renameWithRetry(temp, file);
89
+ }
90
+ finally {
91
+ await rm(temp, { force: true });
92
+ }
93
+ }
35
94
  /**
36
95
  * The repository's first commit.
37
96
  *
@@ -1 +1 @@
1
- {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/storage/project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;;;;;;;;;GAYG;AAEH,MAAM,KAAK,GAAG,IAAI,GAAG,EAA2B,CAAC;AAEjD,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QACvB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,GAAW;IAChC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IACtB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IAClD,OAAO,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;AAC/E,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,IAAI,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QAC1B,QAAQ,CACN,KAAK,EACL,CAAC,UAAU,EAAE,iBAAiB,EAAE,OAAO,CAAC,EACxC,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,EACzC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;YACd,IAAI,GAAG;gBAAE,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC;YAChC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC;iBACvB,KAAK,CAAC,IAAI,CAAC;iBACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;iBAC1B,MAAM,CAAC,OAAO,CAAC;iBACf,IAAI,EAAE,CAAC;YACV,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACf,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/storage/project.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { Tool } from "../types.ts";
2
+ /** One routine as the tool reports it. */
3
+ export interface RoutineSummary {
4
+ name: string;
5
+ cron: string;
6
+ enabled: boolean;
7
+ nextRunAt?: number;
8
+ }
9
+ /**
10
+ * What the routine tool needs from the harness. An interface so the tool
11
+ * layer never imports the harness, which imports tools.
12
+ */
13
+ export interface RoutineHost {
14
+ list(): Promise<RoutineSummary[]>;
15
+ add(input: {
16
+ name: string;
17
+ cron: string;
18
+ prompt: string;
19
+ cwd: string;
20
+ }): Promise<unknown>;
21
+ remove(name: string): Promise<void>;
22
+ }
23
+ /**
24
+ * Create, list and delete routines — prompts that run on a schedule.
25
+ *
26
+ * A tool rather than "edit the config file": the file the agent would reach
27
+ * for is the project's, which is the repository's and fires on every clone,
28
+ * and a hand-written cron nobody parsed is found broken at 9am, not now. This
29
+ * writes the user's own config and refuses an expression that does not parse.
30
+ */
31
+ export declare function createRoutineTool(host: RoutineHost): Tool;
@@ -0,0 +1,70 @@
1
+ import { z } from "zod";
2
+ import { errorMessage } from "../../core/errors.js";
3
+ import { defineTool } from "../define.js";
4
+ import { toolError, toolText } from "../types.js";
5
+ /**
6
+ * Create, list and delete routines — prompts that run on a schedule.
7
+ *
8
+ * A tool rather than "edit the config file": the file the agent would reach
9
+ * for is the project's, which is the repository's and fires on every clone,
10
+ * and a hand-written cron nobody parsed is found broken at 9am, not now. This
11
+ * writes the user's own config and refuses an expression that does not parse.
12
+ */
13
+ export function createRoutineTool(host) {
14
+ return defineTool({
15
+ name: "routine",
16
+ description: [
17
+ "Manage routines: prompts that run by themselves on a schedule, each in a fresh session in this project.",
18
+ "Use when the user asks for something to happen regularly or at a set time (\"every weekday at 9\", \"each Monday morning\").",
19
+ "`add` takes a short kebab-case name, a five-field cron in the user's local time (minute hour day-of-month month day-of-week; `0 9 * * 1-5` is weekdays at 9:00), and the prompt each run sends.",
20
+ "Translate the user's words into the cron yourself; ask only if the time is genuinely unclear.",
21
+ "Write the prompt to stand on its own: the run has no memory of this conversation and nobody is there to answer questions or approve anything.",
22
+ "After adding, tell the user in plain words when it will run.",
23
+ "It runs in this session's project unless `cwd` names another one.",
24
+ "`list` shows existing routines; `remove` deletes one by name.",
25
+ ].join(" "),
26
+ parameters: z.object({
27
+ action: z.enum(["add", "list", "remove"]),
28
+ name: z.string().optional().describe("Routine name. Required for add and remove."),
29
+ cron: z.string().optional().describe("Five-field cron, local time. Required for add."),
30
+ prompt: z.string().optional().describe("What each run asks. Required for add."),
31
+ cwd: z
32
+ .string()
33
+ .optional()
34
+ .describe("Absolute path of the project directory the routine runs in. Defaults to this session's project; set it only when the user names another project."),
35
+ }),
36
+ renderTitle: (input) => `Routine(${input.action}${input.name ? " " + input.name : ""})`,
37
+ async execute(input, ctx) {
38
+ try {
39
+ if (input.action === "list") {
40
+ const routines = await host.list();
41
+ if (!routines.length)
42
+ return toolText("No routines yet.");
43
+ return toolText(routines
44
+ .map((one) => `${one.name} ${one.cron}` +
45
+ (one.enabled ? "" : " (disabled)") +
46
+ (one.nextRunAt ? ` next ${new Date(one.nextRunAt).toString()}` : ""))
47
+ .join("\n"));
48
+ }
49
+ if (!input.name)
50
+ return toolError(`${input.action} needs a name`);
51
+ if (input.action === "remove") {
52
+ await host.remove(input.name);
53
+ return toolText(`Removed routine "${input.name}".`);
54
+ }
55
+ if (!input.cron || !input.prompt)
56
+ return toolError("add needs a name, a cron and a prompt");
57
+ await host.add({ name: input.name, cron: input.cron, prompt: input.prompt, cwd: input.cwd ?? ctx.cwd });
58
+ const added = (await host.list()).find((one) => one.name === input.name);
59
+ const next = added?.nextRunAt ? ` Next run: ${new Date(added.nextRunAt).toString()}.` : "";
60
+ return toolText(`Added routine "${input.name}" (${input.cron}).${next} ` +
61
+ "It fires while the OHarness desktop app or the TUI is open, or while `oharness schedule daemon` runs; " +
62
+ "a time missed while none was running is caught up once when one next starts. Say this if the user may not know it.", { routine: input.name });
63
+ }
64
+ catch (err) {
65
+ return toolError(errorMessage(err));
66
+ }
67
+ },
68
+ });
69
+ }
70
+ //# sourceMappingURL=routine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routine.js","sourceRoot":"","sources":["../../../src/tools/builtin/routine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Rename a file or directory, tolerating the short locks produced by Windows
3
+ * Defender, Search Indexer and editors. POSIX failures are returned at once;
4
+ * retrying them would only hide a real error.
5
+ */
6
+ export declare function renameWithRetry(from: string, to: string): Promise<void>;
@@ -0,0 +1,22 @@
1
+ import { rename } from "node:fs/promises";
2
+ const WINDOWS_RENAME_ERRORS = new Set(["EPERM", "EBUSY", "EACCES"]);
3
+ /**
4
+ * Rename a file or directory, tolerating the short locks produced by Windows
5
+ * Defender, Search Indexer and editors. POSIX failures are returned at once;
6
+ * retrying them would only hide a real error.
7
+ */
8
+ export async function renameWithRetry(from, to) {
9
+ for (let attempt = 0;; attempt++) {
10
+ try {
11
+ await rename(from, to);
12
+ return;
13
+ }
14
+ catch (error) {
15
+ const code = error.code ?? "";
16
+ if (process.platform !== "win32" || attempt >= 5 || !WINDOWS_RENAME_ERRORS.has(code))
17
+ throw error;
18
+ await new Promise((resolve) => setTimeout(resolve, 25 * (attempt + 1)));
19
+ }
20
+ }
21
+ }
22
+ //# sourceMappingURL=fs.js.map