@inetafrica/open-claudia 3.5.20 → 3.5.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +8 -3
- package/CHANGELOG.md +37 -0
- package/README.md +5 -4
- package/core/actions.js +4 -0
- package/core/agent-browser-cli.js +98 -0
- package/core/auth-flow.js +7 -2
- package/core/browser-address.js +171 -0
- package/core/browser-control.js +113 -24
- package/core/browser-teach.js +59 -44
- package/core/browser-view.js +65 -4
- package/core/dream.js +132 -10
- package/core/handlers.js +16 -2
- package/core/limit-pickup.js +24 -20
- package/core/providers/claude.js +15 -8
- package/core/providers/env.js +17 -0
- package/core/providers/events.js +25 -1
- package/core/providers/utility-policy.js +31 -6
- package/core/runner.js +203 -10
- package/core/scheduler.js +57 -0
- package/core/state.js +14 -0
- package/core/system-prompt.js +15 -2
- package/core/turn-journal.js +55 -2
- package/core/usage-limits.js +110 -0
- package/core/utility-agent.js +109 -15
- package/package.json +2 -2
- package/test-fixtures/fake-agent-cli.js +46 -2
- package/test-provider-boot-matrix.js +6 -2
- package/test-provider-capabilities.js +1 -1
- package/test-provider-claude.js +7 -5
- package/test-provider-env-isolation.js +24 -0
- package/test-provider-events.js +43 -1
- package/test-provider-language.js +16 -1
- package/web.js +7 -2
package/core/system-prompt.js
CHANGED
|
@@ -241,6 +241,18 @@ ${listing}`;
|
|
|
241
241
|
|
|
242
242
|
// Kazee Chat's Browser app (core/bot-apps.js): only on a bot that offers it, so a bot without
|
|
243
243
|
// Agent Space is never told to send an Open Browser button that cannot open.
|
|
244
|
+
// How this bot's Chrome runs. With AGENT_BROWSER_CDP set (Agent Space's browser container), Chrome
|
|
245
|
+
// lives in its own container without the bot's files or keys and every agent-browser call attaches
|
|
246
|
+
// to it; otherwise it is the image's own Chrome. Only describe what this environment really does.
|
|
247
|
+
function browserRuntimeNote(env = process.env) {
|
|
248
|
+
if (!String(env.AGENT_BROWSER_CDP || "").trim()) return "Chrome is bundled in the image and runs headless.";
|
|
249
|
+
const downloads = String(env.AGENT_BROWSER_DOWNLOAD_PATH || "").trim();
|
|
250
|
+
const files = downloads
|
|
251
|
+
? ` To upload a file, copy it under ${path.dirname(downloads)} first (that folder is shared with the browser's container); downloads land in ${downloads}.`
|
|
252
|
+
: "";
|
|
253
|
+
return `Chrome runs headless in its own container, apart from your files and keys, and every agent-browser command attaches to it. Never pass --cdp, --args, --executable-path, --idle-timeout or --no-sandbox yourself.${files} \`agent-browser close\` only disconnects: the page stays open in that container.`;
|
|
254
|
+
}
|
|
255
|
+
|
|
244
256
|
function buildBrowserAppBlock() {
|
|
245
257
|
let apps = null;
|
|
246
258
|
try { apps = require("./bot-apps").appsToRegister(process.env); } catch (_) { apps = null; }
|
|
@@ -367,7 +379,7 @@ Sub-agents (spawn a fresh provider-isolated agent for focused research — outpu
|
|
|
367
379
|
- The sub-agent has Read/Glob/Grep/Bash but no access to your chat session or send-* tools.
|
|
368
380
|
|
|
369
381
|
## Browser automation
|
|
370
|
-
You can drive a real web browser via the \`agent-browser\` CLI (vercel-labs). It is a plain command you run through Bash — NOT an MCP tool, so there is nothing to enable; just call it.
|
|
382
|
+
You can drive a real web browser via the \`agent-browser\` CLI (vercel-labs). It is a plain command you run through Bash — NOT an MCP tool, so there is nothing to enable; just call it. ${browserRuntimeNote()} Use it to read pages, fill forms, click through flows, scrape content, or capture screenshots of how something renders.
|
|
371
383
|
|
|
372
384
|
Core workflow — open, snapshot to get element refs, then act on those refs:
|
|
373
385
|
- \`agent-browser open <url>\` — navigate (also: \`goto\`, \`back\`, \`forward\`, \`reload\`).
|
|
@@ -382,7 +394,7 @@ Notes: a background daemon persists between commands, so navigation state carrie
|
|
|
382
394
|
|
|
383
395
|
If you tell the user "I'll check back in N minutes" or "I'll run this every morning", you MUST schedule it with one of the commands above in the same turn. Otherwise nothing happens.
|
|
384
396
|
|
|
385
|
-
Interrupted turns: when a restart cuts a turn short, the agent CLI resumes the conversation by writing two lines into your history, "Continue from where you left off." and the reply "No response requested.". Neither came from the user or from you, and the user never saw them. Never mention or apologise for them, and never reply "No response requested." yourself: finish the interrupted work if it still matters, then act on the current message.
|
|
397
|
+
Interrupted turns: when a restart cuts a turn short, the agent CLI resumes the conversation by writing two lines into your history, "Continue from where you left off." and the reply "No response requested.". Neither came from the user or from you, and the user never saw them. Never mention or apologise for them, and never reply "No response requested." yourself: finish the interrupted work if it still matters, then act on the current message. A /stop leaves the same two lines, but then your next message starts with a note that the person stopped that turn: the stopped request is cancelled, so never resume, redo or re-offer it unless they ask.
|
|
386
398
|
|
|
387
399
|
## Guidelines
|
|
388
400
|
- Keep responses concise — many users are on mobile.
|
|
@@ -1500,6 +1512,7 @@ async function promptWithDynamicContext(prompt, opts = {}) {
|
|
|
1500
1512
|
const buildSystemPrompt = buildCoreInstructions;
|
|
1501
1513
|
|
|
1502
1514
|
module.exports = {
|
|
1515
|
+
browserRuntimeNote,
|
|
1503
1516
|
PromptConstructionError,
|
|
1504
1517
|
buildCoreInstructions,
|
|
1505
1518
|
buildOptionalRecallContext,
|
package/core/turn-journal.js
CHANGED
|
@@ -25,6 +25,9 @@
|
|
|
25
25
|
// (6) on SIGTERM, whose sender kills soon after; whatever is still
|
|
26
26
|
// running stays journaled.
|
|
27
27
|
// - /stop offers each dropped queued message back with a "Run it" button.
|
|
28
|
+
// - /stop marks the conversation "stopped" (kept across a restart): its next
|
|
29
|
+
// turn is told the stopped request is cancelled, not cut off (see
|
|
30
|
+
// markStopped).
|
|
28
31
|
// Scheduled runs (wake-ups, crons, watches) are not journaled: jobs.json keeps
|
|
29
32
|
// their own retry, so they are never resumed twice.
|
|
30
33
|
|
|
@@ -78,7 +81,7 @@ function remove(file) { try { fs.unlinkSync(file); } catch (_) {} }
|
|
|
78
81
|
|
|
79
82
|
// Persist the record, or drop the file when nothing is left in it.
|
|
80
83
|
function store(file, record) {
|
|
81
|
-
if (!record.turn && !(record.queued || []).length) return remove(file);
|
|
84
|
+
if (!record.turn && !(record.queued || []).length && !record.stopped) return remove(file);
|
|
82
85
|
write(file, record);
|
|
83
86
|
}
|
|
84
87
|
|
|
@@ -164,6 +167,8 @@ function begin(runContext, opts = {}) {
|
|
|
164
167
|
},
|
|
165
168
|
queued: (existing.queued || []).filter((q) => q.runId !== runContext.runId),
|
|
166
169
|
};
|
|
170
|
+
// A stop this turn has not taken yet stays for the turn that does.
|
|
171
|
+
if (existing.stopped) record.stopped = existing.stopped;
|
|
167
172
|
try { write(file, record); } catch (error) { console.warn(`[turn-journal] could not journal ${runContext.laneKey}: ${error.message}`); return false; }
|
|
168
173
|
active.set(runContext.laneKey, file);
|
|
169
174
|
ensureHeartbeat();
|
|
@@ -205,6 +210,52 @@ function dropQueued(laneKey, runIds) {
|
|
|
205
210
|
store(file, record);
|
|
206
211
|
}
|
|
207
212
|
|
|
213
|
+
// ── /stop: a cancel, not a cut ─────────────────────────────────────────
|
|
214
|
+
// /stop kills the provider mid-turn. On the next message Claude Code resumes
|
|
215
|
+
// the session and writes the cut turn into the history the same way a
|
|
216
|
+
// restart's cut reads ("[Request interrupted by user for tool use]", then
|
|
217
|
+
// "Continue from where you left off." / "No response requested."), and the
|
|
218
|
+
// system prompt says to finish work a restart cut off. So a stopped request
|
|
219
|
+
// came back on the next message (home pi, 9 Oct: "/stop" on "ok play big
|
|
220
|
+
// bang", then "Big Bang didn't start … just say if you still want it"). The
|
|
221
|
+
// stop is kept in the conversation's file until its next turn takes it.
|
|
222
|
+
function markStopped(laneKey, opts = {}) {
|
|
223
|
+
if (!journalOn() || !laneKey) return false;
|
|
224
|
+
const file = fileFor(laneKey);
|
|
225
|
+
const record = read(file) || { v: 1, conversation: null, turn: null, queued: [] };
|
|
226
|
+
if (!record.conversation && opts.runContext?.origin) record.conversation = conversationOf(opts.runContext);
|
|
227
|
+
record.stopped = {
|
|
228
|
+
at: Number.isFinite(opts.now) ? opts.now : Date.now(),
|
|
229
|
+
runId: opts.runContext?.runId || null,
|
|
230
|
+
};
|
|
231
|
+
try { write(file, record); } catch (_) { return false; }
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// The conversation's stop, once: the turn that takes it carries the note.
|
|
236
|
+
function takeStopped(laneKey) {
|
|
237
|
+
if (!journalOn() || !laneKey) return null;
|
|
238
|
+
const file = fileFor(laneKey);
|
|
239
|
+
const record = read(file);
|
|
240
|
+
if (!record?.stopped) return null;
|
|
241
|
+
const stopped = record.stopped;
|
|
242
|
+
delete record.stopped;
|
|
243
|
+
try { store(file, record); } catch (_) {}
|
|
244
|
+
return stopped;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// /new, /end or a project change: the stopped turn's history is gone.
|
|
248
|
+
function clearStopped(laneKey) {
|
|
249
|
+
takeStopped(laneKey);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// What the turn after a /stop reads before the person's message.
|
|
253
|
+
function stoppedNote(stopped) {
|
|
254
|
+
const at = Number(stopped?.at);
|
|
255
|
+
const when = Number.isFinite(at) && at > 0 ? `At ${hhmm(at)} the person` : "The person";
|
|
256
|
+
return `[${when} stopped your previous turn with /stop, so that request is cancelled. Your history may still show it unfinished, followed by "Continue from where you left off." from the agent CLI (not from them). Don't resume it, redo it or offer to do it again unless they ask; just answer the message below.]`;
|
|
257
|
+
}
|
|
258
|
+
|
|
208
259
|
function list() {
|
|
209
260
|
if (!journalOn()) return [];
|
|
210
261
|
let names = [];
|
|
@@ -337,7 +388,8 @@ async function resumeInterrupted(adapters, overrides = {}) {
|
|
|
337
388
|
if (!turn) {
|
|
338
389
|
const queued = record.queued || [];
|
|
339
390
|
record.queued = [];
|
|
340
|
-
|
|
391
|
+
// A stop not yet taken stays (the restored messages' turn takes it).
|
|
392
|
+
store(file, record);
|
|
341
393
|
runQueued({ ...record, queued }, adapter, deps);
|
|
342
394
|
out.restored += queued.length;
|
|
343
395
|
continue;
|
|
@@ -502,6 +554,7 @@ module.exports = {
|
|
|
502
554
|
conversationOf, chatScope, findAdapter, defaultDeps,
|
|
503
555
|
resumeInterrupted, handleResumeAction, RESUME_PROMPT,
|
|
504
556
|
rememberDropped, droppedKeyboard, handleRunDropped,
|
|
557
|
+
markStopped, takeStopped, clearStopped, stoppedNote,
|
|
505
558
|
drain, exitAfterDrain, isDraining, markShuttingDown,
|
|
506
559
|
resumeEnabled, maxAgeMs, drainTimeoutMs, sigtermDrainTimeoutMs, MAX_ATTEMPTS, HEARTBEAT_MS,
|
|
507
560
|
_resetForTests,
|
package/core/usage-limits.js
CHANGED
|
@@ -302,9 +302,119 @@ function limitHitDetails({ provider, error, rateLimit = null, windows = [], now
|
|
|
302
302
|
};
|
|
303
303
|
}
|
|
304
304
|
|
|
305
|
+
// ---------------------------------------------------------------------------
|
|
306
|
+
// Waiting for a reset: one rule and one record for every kind of work
|
|
307
|
+
// (Sumeet, 9 Oct 2026: a used-up limit is handled the same way everywhere,
|
|
308
|
+
// as a runtime concept, not a fix per feature).
|
|
309
|
+
//
|
|
310
|
+
// - limitRetryAt() is when work a limit stopped runs again: a chat message
|
|
311
|
+
// (core/limit-pickup), a scheduled run (core/scheduler), the dream's AI
|
|
312
|
+
// step (core/dream). Never another provider: the other one may not be
|
|
313
|
+
// signed in or may be used up too.
|
|
314
|
+
// - noteLimitHit() records that a provider is used up until its reset,
|
|
315
|
+
// from any run a limit stopped; a run that works clears it
|
|
316
|
+
// (clearLimitBlock). Background calls read it (limitBlock) and do not
|
|
317
|
+
// start a used-up provider again and again. Chat turns never read it:
|
|
318
|
+
// they always try, so the provider stays the judge.
|
|
319
|
+
|
|
320
|
+
function setting(name) {
|
|
321
|
+
if (process.env[name] !== undefined) return process.env[name];
|
|
322
|
+
return config[name];
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Wait this long after the reset, so the provider's window has turned over.
|
|
326
|
+
function limitRetryDelayMs() {
|
|
327
|
+
const n = Number(setting("LIMIT_PICKUP_DELAY_S"));
|
|
328
|
+
return (Number.isFinite(n) && n >= 0 ? n : 120) * 1000;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// A reset further out than this (a monthly spend cap) is not waited for.
|
|
332
|
+
function limitMaxWaitMs() {
|
|
333
|
+
const n = Number(setting("LIMIT_PICKUP_MAX_WAIT_H"));
|
|
334
|
+
return (Number.isFinite(n) && n > 0 ? n : 192) * 3600000;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/** When work a limit stopped should run again; null when the reset is not known. */
|
|
338
|
+
function limitRetryAt(resetsAt, { now = Date.now() } = {}) {
|
|
339
|
+
if (!Number.isFinite(resetsAt) || resetsAt <= now - 6 * 3600000) return null;
|
|
340
|
+
return Math.max(resetsAt, now) + limitRetryDelayMs();
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/** Whether a wait until `runAt` is short enough to wait for. */
|
|
344
|
+
function canWaitFor(runAt, { now = Date.now() } = {}) {
|
|
345
|
+
return Number.isFinite(runAt) && runAt - now <= limitMaxWaitMs();
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function liveFile(file) {
|
|
349
|
+
// A test run that did not point the config dir somewhere else never touches
|
|
350
|
+
// the live bot's file.
|
|
351
|
+
return !(file === DEFAULT_FILE && process.env.OPEN_CLAUDIA_TEST === "1" && !process.env.OPEN_CLAUDIA_CONFIG_DIR);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// A model-family limit (Claude's weekly Opus or Sonnet limit) stops only that
|
|
355
|
+
// family; an unknown model counts as stopped.
|
|
356
|
+
function blocksModel(limitType, model) {
|
|
357
|
+
const family = /opus|sonnet|fable|haiku/i.exec(String(limitType || ""));
|
|
358
|
+
if (!family || !model) return true;
|
|
359
|
+
return String(model).toLowerCase().includes(family[0].toLowerCase());
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/** Record that `provider` is used up until `resetsAt` (a run hit its limit). */
|
|
363
|
+
function noteLimitHit({ provider, limitType = null, resetsAt, file = DEFAULT_FILE, now = Date.now() } = {}) {
|
|
364
|
+
if (!provider || !Number.isFinite(resetsAt) || resetsAt <= now || !liveFile(file)) return null;
|
|
365
|
+
return withFileLock(file, () => {
|
|
366
|
+
const state = readState(file);
|
|
367
|
+
if (!state.blocks || typeof state.blocks !== "object") state.blocks = {};
|
|
368
|
+
const previous = state.blocks[provider];
|
|
369
|
+
const block = {
|
|
370
|
+
limitType: limitType || null,
|
|
371
|
+
resetsAt,
|
|
372
|
+
since: previous && previous.resetsAt > now ? previous.since : new Date(now).toISOString(),
|
|
373
|
+
updatedAt: new Date(now).toISOString(),
|
|
374
|
+
};
|
|
375
|
+
state.blocks[provider] = block;
|
|
376
|
+
atomicWriteFileSync(file, JSON.stringify(state, null, 2) + "\n");
|
|
377
|
+
return { provider, ...block };
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/** The limit `provider` is used up on now, or null. `model` narrows a model-family limit. */
|
|
382
|
+
function limitBlock(provider, { model = null, file = DEFAULT_FILE, now = Date.now() } = {}) {
|
|
383
|
+
if (!provider || !liveFile(file)) return null;
|
|
384
|
+
const block = readState(file).blocks?.[provider];
|
|
385
|
+
if (!block || !Number.isFinite(block.resetsAt) || block.resetsAt <= now) return null;
|
|
386
|
+
if (!blocksModel(block.limitType, model)) return null;
|
|
387
|
+
return { provider, ...block };
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* A run on `provider` worked: it is not used up (any more). A run on a model
|
|
392
|
+
* a model-family limit does not cover proves nothing about that limit.
|
|
393
|
+
*/
|
|
394
|
+
function clearLimitBlock(provider, { model = null, file = DEFAULT_FILE } = {}) {
|
|
395
|
+
if (!provider || !liveFile(file)) return false;
|
|
396
|
+
// Read first: almost every run finds nothing to clear and writes nothing.
|
|
397
|
+
const found = readState(file).blocks?.[provider];
|
|
398
|
+
if (!found || !blocksModel(found.limitType, model)) return false;
|
|
399
|
+
return withFileLock(file, () => {
|
|
400
|
+
const state = readState(file);
|
|
401
|
+
if (!state.blocks?.[provider]) return false;
|
|
402
|
+
delete state.blocks[provider];
|
|
403
|
+
atomicWriteFileSync(file, JSON.stringify(state, null, 2) + "\n");
|
|
404
|
+
return true;
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
|
|
305
408
|
module.exports = {
|
|
306
409
|
DEFAULT_FILE,
|
|
307
410
|
DEFAULT_WARN_PERCENTS,
|
|
411
|
+
limitRetryDelayMs,
|
|
412
|
+
limitMaxWaitMs,
|
|
413
|
+
limitRetryAt,
|
|
414
|
+
canWaitFor,
|
|
415
|
+
noteLimitHit,
|
|
416
|
+
limitBlock,
|
|
417
|
+
clearLimitBlock,
|
|
308
418
|
warnPercents,
|
|
309
419
|
providerLabel,
|
|
310
420
|
windowLabel,
|
package/core/utility-agent.js
CHANGED
|
@@ -9,7 +9,7 @@ const { MAX_PROCESS_TIMEOUT } = require("./config");
|
|
|
9
9
|
const { killProcessTree } = require("./process-tree");
|
|
10
10
|
const { redactSensitive } = require("./redact");
|
|
11
11
|
const { validateInvocation } = require("./providers/contract");
|
|
12
|
-
const { selectTerminalText } = require("./providers/events");
|
|
12
|
+
const { providerFailureCode, selectTerminalText } = require("./providers/events");
|
|
13
13
|
const { createUtilityPolicy, normalizePurpose } = require("./providers/utility-policy");
|
|
14
14
|
|
|
15
15
|
const DEFAULT_TIMEOUT_MS = 10 * 60 * 1000;
|
|
@@ -20,6 +20,11 @@ const DEFAULT_KILL_GRACE_MS = 500;
|
|
|
20
20
|
const DEFAULT_GLOBAL_CONCURRENCY = 6;
|
|
21
21
|
const DEFAULT_PURPOSE_CONCURRENCY = 3;
|
|
22
22
|
const DEFAULT_RECURSION_DEPTH = 2;
|
|
23
|
+
// Claude Code's refresh-lock race passes in seconds: one more try after this,
|
|
24
|
+
// for work nobody waits on. A chat's own checks (recall, a passive reply, a
|
|
25
|
+
// title, the guard) go without instead of holding the reply up.
|
|
26
|
+
const DEFAULT_TRANSIENT_RETRY_MS = 20 * 1000;
|
|
27
|
+
const TRANSIENT_RETRY_PURPOSES = new Set(["dream", "introspection", "review", "dedup", "subagent"]);
|
|
23
28
|
const DEFAULT_SYSTEM_PROMPT = [
|
|
24
29
|
"You are a bounded Open Claudia utility agent.",
|
|
25
30
|
"Follow the supplied task and return only the requested result.",
|
|
@@ -62,8 +67,22 @@ function appendBounded(current, addition, maxBytes) {
|
|
|
62
67
|
return clipUtf8(joined, maxBytes);
|
|
63
68
|
}
|
|
64
69
|
|
|
65
|
-
function stableError(code, message) {
|
|
66
|
-
return {
|
|
70
|
+
function stableError(code, message, details = null) {
|
|
71
|
+
return {
|
|
72
|
+
code,
|
|
73
|
+
message: redactSensitive(String(message || "Utility agent failed")),
|
|
74
|
+
...(details ? { details } : {}),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// A limit's reset as the provider reported it (Claude: the rate_limit_event);
|
|
79
|
+
// usage-limits.limitHitDetails reads it, else the wording of the message.
|
|
80
|
+
function failureDetails(event, code) {
|
|
81
|
+
if (code !== "PROVIDER_USAGE_LIMIT") return null;
|
|
82
|
+
return {
|
|
83
|
+
limitResetsAt: Number.isFinite(event?.limitResetsAt) ? event.limitResetsAt : null,
|
|
84
|
+
limitType: event?.limitType || null,
|
|
85
|
+
};
|
|
67
86
|
}
|
|
68
87
|
|
|
69
88
|
function extractJson(text) {
|
|
@@ -298,10 +317,10 @@ function executeUtilityInvocation(options) {
|
|
|
298
317
|
else if (cancelled) failure = stableError("UTILITY_CANCELLED", "Utility agent was cancelled");
|
|
299
318
|
else if (timedOut) failure = stableError("UTILITY_TIMEOUT", "Utility agent timed out");
|
|
300
319
|
else if (outputLimit) failure = stableError("UTILITY_OUTPUT_LIMIT", "Utility provider stdout exceeded its hard limit");
|
|
301
|
-
else if (normalizedFailure)
|
|
302
|
-
|
|
303
|
-
normalizedFailure.message || "Utility provider failed",
|
|
304
|
-
|
|
320
|
+
else if (normalizedFailure) {
|
|
321
|
+
const code = providerFailureCode(normalizedFailure, "UTILITY_PROVIDER_ERROR");
|
|
322
|
+
failure = stableError(code, normalizedFailure.message || "Utility provider failed", failureDetails(normalizedFailure, code));
|
|
323
|
+
}
|
|
305
324
|
else if (closeInfo?.code !== 0) failure = stableError(
|
|
306
325
|
"UTILITY_PROCESS_FAILED",
|
|
307
326
|
safeStderr || `Utility provider exited with code ${closeInfo?.code == null ? "unknown" : closeInfo.code}`,
|
|
@@ -423,6 +442,21 @@ function executeUtilityInvocation(options) {
|
|
|
423
442
|
});
|
|
424
443
|
}
|
|
425
444
|
|
|
445
|
+
// Wait `ms`, or less when the call is cancelled meanwhile.
|
|
446
|
+
function pause(ms, signal) {
|
|
447
|
+
return new Promise((resolve) => {
|
|
448
|
+
if (signal?.aborted || !(ms > 0)) return resolve();
|
|
449
|
+
let timer = null;
|
|
450
|
+
const done = () => {
|
|
451
|
+
clearTimeout(timer);
|
|
452
|
+
signal?.removeEventListener?.("abort", done);
|
|
453
|
+
resolve();
|
|
454
|
+
};
|
|
455
|
+
timer = setTimeout(done, ms);
|
|
456
|
+
signal?.addEventListener?.("abort", done, { once: true });
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
|
|
426
460
|
function fallbackEligible(errorCode) {
|
|
427
461
|
return new Set([
|
|
428
462
|
"PROVIDER_UNAVAILABLE",
|
|
@@ -438,6 +472,12 @@ function createUtilityAgentService(options = {}) {
|
|
|
438
472
|
const registry = options.registry || require("./providers");
|
|
439
473
|
const env = options.env || require("./config").config;
|
|
440
474
|
const policy = options.policy || createUtilityPolicy({ registry, env, activeProvider: options.activeProvider });
|
|
475
|
+
// The limit record (core/usage-limits.js): a used-up provider is not
|
|
476
|
+
// started; a limit hit is recorded; a call that worked clears it.
|
|
477
|
+
const limitsLib = options.limits || require("./usage-limits");
|
|
478
|
+
const transientRetryMs = Number.isFinite(Number(options.transientRetryMs)) && Number(options.transientRetryMs) >= 0
|
|
479
|
+
? Number(options.transientRetryMs)
|
|
480
|
+
: DEFAULT_TRANSIENT_RETRY_MS;
|
|
441
481
|
const spawnProcess = options.spawnProcess || spawn;
|
|
442
482
|
const killTree = options.killTree || killProcessTree;
|
|
443
483
|
const killGraceMs = positiveInteger(options.killGraceMs, DEFAULT_KILL_GRACE_MS, "killGraceMs");
|
|
@@ -490,6 +530,20 @@ function createUtilityAgentService(options = {}) {
|
|
|
490
530
|
else activeByPurpose.set(purpose, activePurpose - 1);
|
|
491
531
|
}
|
|
492
532
|
|
|
533
|
+
function usedUpFor(selection) {
|
|
534
|
+
try { return limitsLib.limitBlock(selection.providerId, { model: selection.model }); }
|
|
535
|
+
catch (_) { return null; }
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
function noteLimits(providerId, result) {
|
|
539
|
+
try {
|
|
540
|
+
if (result.ok) { limitsLib.clearLimitBlock(providerId, { model: result.model || null }); return; }
|
|
541
|
+
if (result.error?.code !== "PROVIDER_USAGE_LIMIT" || result.notStarted) return;
|
|
542
|
+
const hit = limitsLib.limitHitDetails({ provider: providerId, error: result.error });
|
|
543
|
+
if (hit?.resetsAt) limitsLib.noteLimitHit({ provider: providerId, limitType: hit.limitType, resetsAt: hit.resetsAt });
|
|
544
|
+
} catch (_) { /* the record is best effort */ }
|
|
545
|
+
}
|
|
546
|
+
|
|
493
547
|
function stats() {
|
|
494
548
|
return {
|
|
495
549
|
activeGlobal,
|
|
@@ -567,18 +621,48 @@ function createUtilityAgentService(options = {}) {
|
|
|
567
621
|
...(effort ? { effort } : {}),
|
|
568
622
|
};
|
|
569
623
|
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
624
|
+
// A provider used up until its reset is not started: the caller waits
|
|
625
|
+
// for the reset (the dream) or goes without (recall, a title).
|
|
626
|
+
const block = usedUpFor(selection);
|
|
627
|
+
if (block) {
|
|
628
|
+
const result = {
|
|
629
|
+
ok: false,
|
|
630
|
+
status: "failed",
|
|
631
|
+
text: "",
|
|
632
|
+
provider: selection.providerId,
|
|
633
|
+
model: selection.model,
|
|
634
|
+
tier: selection.tier,
|
|
635
|
+
purpose,
|
|
636
|
+
preferredProvider: selection.preferredProviderId,
|
|
637
|
+
fallbackUsed: selection.fallbackUsed,
|
|
638
|
+
effort,
|
|
639
|
+
notStarted: "usage limit",
|
|
640
|
+
error: stableError(
|
|
641
|
+
"PROVIDER_USAGE_LIMIT",
|
|
642
|
+
`${limitsLib.providerLabel(selection.providerId)}'s ${limitsLib.windowLabel(block.limitType)} is used up until ${new Date(block.resetsAt).toISOString()}`,
|
|
643
|
+
{ limitResetsAt: block.resetsAt, limitType: block.limitType || null },
|
|
644
|
+
),
|
|
645
|
+
};
|
|
646
|
+
lastResult = result;
|
|
647
|
+
if (index + 1 < candidates.length && fallbackEligible(result.error.code)) continue;
|
|
648
|
+
throw new UtilityAgentError(result.error.code, result.error.message, result);
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
const buildInvocation = () => {
|
|
652
|
+
const built = validateInvocation(provider.buildUtilityInvocation(invocationContext));
|
|
653
|
+
return validateInvocation({
|
|
654
|
+
...built,
|
|
575
655
|
env: {
|
|
576
|
-
...
|
|
656
|
+
...built.env,
|
|
577
657
|
OC_PROVIDER: selection.providerId,
|
|
578
658
|
OC_UTILITY_DEPTH: String(depth + 1),
|
|
579
659
|
OC_UTILITY_PURPOSE: purpose,
|
|
580
660
|
},
|
|
581
661
|
});
|
|
662
|
+
};
|
|
663
|
+
let invocation;
|
|
664
|
+
try {
|
|
665
|
+
invocation = buildInvocation();
|
|
582
666
|
} catch (error) {
|
|
583
667
|
const result = {
|
|
584
668
|
ok: false,
|
|
@@ -598,9 +682,9 @@ function createUtilityAgentService(options = {}) {
|
|
|
598
682
|
throw new UtilityAgentError(result.error.code, result.error.message, result);
|
|
599
683
|
}
|
|
600
684
|
|
|
601
|
-
const
|
|
685
|
+
const execute = (built) => context.run({ depth: depth + 1, purpose }, () => executeUtilityInvocation({
|
|
602
686
|
provider,
|
|
603
|
-
invocation,
|
|
687
|
+
invocation: built,
|
|
604
688
|
cwd: request.cwd || process.cwd(),
|
|
605
689
|
spawnProcess,
|
|
606
690
|
killTree,
|
|
@@ -612,6 +696,15 @@ function createUtilityAgentService(options = {}) {
|
|
|
612
696
|
maxStdoutBytes,
|
|
613
697
|
outputSchema: request.outputSchema || null,
|
|
614
698
|
}));
|
|
699
|
+
let result = await execute(invocation);
|
|
700
|
+
// Claude Code's refresh-lock race passes: one more try, a little later.
|
|
701
|
+
if (!result.ok && result.error?.code === "PROVIDER_TRANSIENT" && TRANSIENT_RETRY_PURPOSES.has(purpose) && !request.signal?.aborted) {
|
|
702
|
+
await pause(transientRetryMs, request.signal);
|
|
703
|
+
if (!request.signal?.aborted) {
|
|
704
|
+
try { result = await execute(buildInvocation()); }
|
|
705
|
+
catch (_) { /* keep the first failure */ }
|
|
706
|
+
}
|
|
707
|
+
}
|
|
615
708
|
Object.assign(result, {
|
|
616
709
|
provider: selection.providerId,
|
|
617
710
|
model: selection.model,
|
|
@@ -624,6 +717,7 @@ function createUtilityAgentService(options = {}) {
|
|
|
624
717
|
noProductSideEffects: readOnlyMetadata(provider, request.readOnly !== false),
|
|
625
718
|
});
|
|
626
719
|
lastResult = result;
|
|
720
|
+
noteLimits(selection.providerId, result);
|
|
627
721
|
if (result.ok) return result;
|
|
628
722
|
if (index + 1 < candidates.length && fallbackEligible(result.error?.code)) continue;
|
|
629
723
|
throw new UtilityAgentError(result.error?.code || "UTILITY_AGENT_FAILED", result.error?.message || "Utility agent failed", result);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inetafrica/open-claudia",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.24",
|
|
4
4
|
"description": "An always-on, provider-agnostic coding-agent harness for Claude Code and OpenAI Codex via chat",
|
|
5
5
|
"main": "bot.js",
|
|
6
6
|
"bin": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"setup": "node setup.js",
|
|
12
12
|
"start": "node bot.js",
|
|
13
13
|
"pretest": "node test-provider-fixture.js && node test-provider-core-prompt.js && node test-turn-observer.js && node test-provider-prompt-parity.js && node test-provider-env-isolation.js && node test-provider-resume-parity.js && node test-provider-bootstrap.js && node test-provider-registry.js && node test-provider-stream-decoder.js && node test-provider-events.js && node test-provider-claude.js && node test-provider-codex.js && node test-codex-output-schema.js && node test-codex-device-login.js && node test-provider-runner.js && node test-provider-refusal-recovery.js && node test-provider-run-lifecycle.js && node test-provider-gateway.js && node test-provider-side-chat.js && node test-single-runtime.js && node test-provider-migration-backup.js && node test-provider-state-migration.js && node test-provider-session-history.js && node test-provider-session-commands.js && node test-provider-compaction.js && node test-provider-scheduler.js && node test-credential-capture.js && node test-cursor-removal.js && node test-utility-provider-policy.js && node test-provider-subagent.js && node test-provider-recall.js && node test-provider-pack-review.js && node test-memory-mutation-queue.js && node test-provider-dream.js && node test-provider-enforcer.js && node test-provider-tool-hooks.js && node test-provider-boot-matrix.js && node test-provider-capabilities.js && node test-provider-language.js && node test-upgrade-path.js && node test-provider-coupling-audit.js && node test-provider-parity-e2e.js && node test-kazee-channel-health.js && node test-kazee-media-caption.js && node test-kazee-context-media.js && node test-kazee-typing-join.js && node test-kazee-inbound-dedup.js && node test-typing-phase-push.js && node test-socket-reconnect.js && node test-speech-loopback.js && node test-prompt-budget.js && node test-agency-ledger.js && node test-agency-deliberate.js && node test-guardrail.js && node test-group-status-notes.js && node test-spaces-comment-content.js && node test-boot-health.js && node test-lexical-floor.js && node test-safe-mode.js && node test-logout.js && node test-kazee-call-audio.js && node test-kazee-call-janus.js && node test-kazee-call-webrtc.js && node test-kazee-call-speech.js && node test-kazee-call-manager.js && node test-call-speech.js && node test-kazee-call-session.js",
|
|
14
|
-
"test": "OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node -e \"require('./vault'); console.log('OK')\" && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-runner-watchdog-static.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-usage-accounting.js && node test-codex-rollout.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-engine.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-graph.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-discoverer.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-query.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-walker-score.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-score-gate.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-cokept-warming.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-project-transcripts-smoke.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-transcript-room-scope.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-abilities.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-ability-extraction.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-ability-couse.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-ability-transfer.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-ability-tiers.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-ability-merge-guard.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-learning-e2e.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-pack-nesting.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-pack-search.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-extractive-injection.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-journal-dedupe.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-read-signal.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tools.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tool-graph.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tool-guard.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-read-guard.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tooling-mode.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tool-manifest.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-evolution.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-approval-async.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-unified-identity.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-persona-packs.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-speaker-persona.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-persona-pipeline.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-relationship-gate.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-relationship.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-enforcer.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-mandate-hygiene.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-external-rule-scopes.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-approval-cards.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-identity-prune.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-kazee-message-id.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-kazee-group-gate.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-kazee-group-context.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-kazee-threads.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-people-owner-seed.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-delivery-contract.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-run-lock.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-thread-lanes.js && node test-thread-titles.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-thread-stop.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-typing-heartbeat.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-web-sessions.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-telegram-poll-recovery.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-telegram-409-grace.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-telegram-conflict-heal-guard.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-single-instance.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-streaming-split.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-stream-preview-purpose.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-spaces-autoenable.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-say-loopback.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-loopback-threads.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-transcript-threads.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-journal-union.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-subst-score.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-section-budgets.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-dedup-adjudicator.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-prospective.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-regressions.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-cost-report.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-speaker-context.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-approval-mining.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tool-certification.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-apprenticeship.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-speaker-attest.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-run-attest.js && node test-sandbox-probe.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-bot-endpoint.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tool-gate.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-cli-owner-gates.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-verify-contact.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-loopback-owner-gate.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-watch-check-env.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-intro-adoption.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-grants.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-room-provider-settings.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-store-durability.js && node test-kazee-cards.js && node test-decision-upkeep.js && node test-passive-replies.js && node test-kazee-bot-loops.js && node test-kazee-bot-handoffs.js && node test-placeholder-reply.js && node test-media-speech.js && node test-passive-replies-router.js && node test-loopback-cards.js && node test-task-injection.js && node test-speaker-extras.js && node test-token-diet.js && node test-dream-tasks.js && node test-task-archive.js && node test-cron-tolerance.js && node test-dream-schedule.js && node test-job-failures.js && node test-scheduled-placeholder.js && node test-lessons-since.js && node test-pack-reinject.js && node test-turn-journal.js && node test-usage-limits.js && node test-limit-pickup.js && node test-browser-view.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test node test-web-browser-view.js && node test-browser-control.js && node test-browser-teach.js && node test-kazee-bot-apps.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test node test-web-browser-app.js && node test-safe-filename.js && node test-media-filename-paths.js && node test-router-document-guard.js && OPEN_CLAUDIA_TEST=1 node test-web-dashboard-escape.js && OPEN_CLAUDIA_TEST=1 node test-web-bad-requests.js && OPEN_CLAUDIA_TEST=1 node test-kazee-download-limit.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test node test-web-auth-routes.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test node test-web-otp-link-preview.js"
|
|
14
|
+
"test": "OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node -e \"require('./vault'); console.log('OK')\" && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-runner-watchdog-static.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-usage-accounting.js && node test-codex-rollout.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-engine.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-graph.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-discoverer.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-query.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-walker-score.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-score-gate.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-cokept-warming.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-project-transcripts-smoke.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-transcript-room-scope.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-abilities.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-ability-extraction.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-ability-couse.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-ability-transfer.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-ability-tiers.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-ability-merge-guard.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-learning-e2e.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-pack-nesting.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-pack-search.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-extractive-injection.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-journal-dedupe.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-read-signal.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tools.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tool-graph.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tool-guard.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-read-guard.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tooling-mode.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tool-manifest.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-evolution.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-approval-async.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-unified-identity.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-persona-packs.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-speaker-persona.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-persona-pipeline.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-relationship-gate.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-relationship.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-enforcer.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-mandate-hygiene.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-external-rule-scopes.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-approval-cards.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-identity-prune.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-kazee-message-id.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-kazee-group-gate.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-kazee-group-context.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-kazee-threads.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-people-owner-seed.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-delivery-contract.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-run-lock.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-thread-lanes.js && node test-thread-titles.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-thread-stop.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-stop-queue.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-typing-heartbeat.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-web-sessions.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-telegram-poll-recovery.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-telegram-409-grace.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-telegram-conflict-heal-guard.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-single-instance.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-streaming-split.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-stream-preview-purpose.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-spaces-autoenable.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-say-loopback.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-loopback-threads.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-transcript-threads.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-journal-union.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-subst-score.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-section-budgets.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-dedup-adjudicator.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-prospective.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-regressions.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-cost-report.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-speaker-context.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-approval-mining.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tool-certification.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-apprenticeship.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-speaker-attest.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-run-attest.js && node test-sandbox-probe.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-bot-endpoint.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tool-gate.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-cli-owner-gates.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-verify-contact.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-loopback-owner-gate.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-watch-check-env.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-intro-adoption.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-grants.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-room-provider-settings.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-store-durability.js && node test-kazee-cards.js && node test-decision-upkeep.js && node test-passive-replies.js && node test-kazee-bot-loops.js && node test-kazee-bot-handoffs.js && node test-placeholder-reply.js && node test-media-speech.js && node test-passive-replies-router.js && node test-loopback-cards.js && node test-task-injection.js && node test-speaker-extras.js && node test-token-diet.js && node test-dream-tasks.js && node test-task-archive.js && node test-cron-tolerance.js && node test-dream-schedule.js && node test-job-failures.js && node test-scheduled-placeholder.js && node test-lessons-since.js && node test-pack-reinject.js && node test-turn-journal.js && node test-usage-limits.js && node test-limit-waits.js && node test-limit-pickup.js && node test-browser-view.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test node test-web-browser-view.js && node test-browser-address.js && node test-browser-control.js && node test-browser-teach.js && node test-kazee-bot-apps.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test node test-web-browser-app.js && node test-safe-filename.js && node test-media-filename-paths.js && node test-router-document-guard.js && OPEN_CLAUDIA_TEST=1 node test-web-dashboard-escape.js && OPEN_CLAUDIA_TEST=1 node test-web-bad-requests.js && OPEN_CLAUDIA_TEST=1 node test-kazee-download-limit.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test node test-web-auth-routes.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test node test-web-otp-link-preview.js"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
17
|
"bot.js",
|