@brainervirus/workit-pi 8.36.0 → 8.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/worker.js +45 -4
- package/dist/workit.js +113 -11
- package/package.json +1 -1
package/dist/worker.js
CHANGED
|
@@ -8209,21 +8209,60 @@ var uniformImplementerModel = (cwd, host, dir) => {
|
|
|
8209
8209
|
};
|
|
8210
8210
|
var ROLE_SELECTORS = MODEL_ROLES.flatMap((role) => role === "implementer" ? MODEL_TIERS.map((tier) => ({ role, tier })) : [{ role }]);
|
|
8211
8211
|
|
|
8212
|
-
// packages/workit-core/src/hooks/
|
|
8212
|
+
// packages/workit-core/src/hooks/budget-signal.ts
|
|
8213
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
8213
8214
|
import fs4 from "node:fs";
|
|
8214
8215
|
import path7 from "node:path";
|
|
8216
|
+
var hash = (text) => createHash4("sha256").update(text).digest("hex").slice(0, 32);
|
|
8217
|
+
var budgetDir = (store) => path7.join(store, "budget");
|
|
8218
|
+
var agentBase = (store, session, agentId) => path7.join(budgetDir(store), hash(`${session}\x00${agentId ?? ""}`));
|
|
8219
|
+
var spawnBudget = (prompt) => {
|
|
8220
|
+
const found = /^TIMEBOX:[^\n]*?\b(\d+)\s+tool calls\b/mu.exec(prompt);
|
|
8221
|
+
const n = found ? Number(found[1]) : NaN;
|
|
8222
|
+
return Number.isInteger(n) && n > 0 ? n : null;
|
|
8223
|
+
};
|
|
8224
|
+
var startBudget = (store, session, agentId, n) => {
|
|
8225
|
+
const dir = budgetDir(store);
|
|
8226
|
+
fs4.mkdirSync(dir, { recursive: true });
|
|
8227
|
+
const cutoff = Date.now() - 604800000;
|
|
8228
|
+
for (const name of fs4.readdirSync(dir))
|
|
8229
|
+
try {
|
|
8230
|
+
if (fs4.statSync(path7.join(dir, name)).mtimeMs < cutoff)
|
|
8231
|
+
fs4.rmSync(path7.join(dir, name));
|
|
8232
|
+
} catch {}
|
|
8233
|
+
const base = agentBase(store, session, agentId);
|
|
8234
|
+
fs4.writeFileSync(`${base}.json`, JSON.stringify({ limit: n, told: 0 }));
|
|
8235
|
+
fs4.rmSync(`${base}.calls`, { force: true });
|
|
8236
|
+
};
|
|
8237
|
+
var bindBudget = (cwd, session, agentId, prompt) => {
|
|
8238
|
+
try {
|
|
8239
|
+
const n = spawnBudget(prompt);
|
|
8240
|
+
const store = n && session ? gitStoreDir(cwd) : null;
|
|
8241
|
+
if (!n || !store)
|
|
8242
|
+
return null;
|
|
8243
|
+
startBudget(store, session, agentId, n);
|
|
8244
|
+
return n;
|
|
8245
|
+
} catch {
|
|
8246
|
+
return null;
|
|
8247
|
+
}
|
|
8248
|
+
};
|
|
8249
|
+
var CODEX_GATED = new Set(["bash", "unifiedexec", "shell", "applypatch", "edit", "write"]);
|
|
8250
|
+
|
|
8251
|
+
// packages/workit-core/src/hooks/standing.ts
|
|
8252
|
+
import fs5 from "node:fs";
|
|
8253
|
+
import path8 from "node:path";
|
|
8215
8254
|
var readPlans = (store) => {
|
|
8216
|
-
const dir =
|
|
8255
|
+
const dir = path8.join(store, "fanouts");
|
|
8217
8256
|
let names;
|
|
8218
8257
|
try {
|
|
8219
|
-
names =
|
|
8258
|
+
names = fs5.readdirSync(dir).filter((name) => name.endsWith(".json"));
|
|
8220
8259
|
} catch {
|
|
8221
8260
|
return [];
|
|
8222
8261
|
}
|
|
8223
8262
|
const plans = [];
|
|
8224
8263
|
for (const name of names) {
|
|
8225
8264
|
try {
|
|
8226
|
-
const raw = JSON.parse(
|
|
8265
|
+
const raw = JSON.parse(fs5.readFileSync(path8.join(dir, name), "utf8"));
|
|
8227
8266
|
if (typeof raw.name !== "string" || !Array.isArray(raw.slices))
|
|
8228
8267
|
continue;
|
|
8229
8268
|
const texts = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string" && item !== "") : [];
|
|
@@ -8454,6 +8493,8 @@ function launchWorker(assignment, options) {
|
|
|
8454
8493
|
transcriptPath: null,
|
|
8455
8494
|
event: { kind: "session.start", source: "startup" }
|
|
8456
8495
|
});
|
|
8496
|
+
bindBudget(spec.cwd, env.WORKIT_SESSION_ID, null, `${options.pendingPrompt ?? ""}
|
|
8497
|
+
${assignment.objective}`);
|
|
8457
8498
|
try {
|
|
8458
8499
|
const spawn = options.spawn ?? ((command, args, spawnOptions) => nodeSpawn(command, args, spawnOptions));
|
|
8459
8500
|
handle.spec = { ...spec, env };
|
package/dist/workit.js
CHANGED
|
@@ -24609,7 +24609,8 @@ function handleHook(input, deps) {
|
|
|
24609
24609
|
const decision = decide(input, deps);
|
|
24610
24610
|
if (deps.descriptor.transport !== "hook-process" || !PRE_TOOL.has(input.event.kind) || decision.kind === "deny" || decision.kind === "ask")
|
|
24611
24611
|
return decision;
|
|
24612
|
-
const delta = standingDelta(input)
|
|
24612
|
+
const delta = [standingDelta(input), deps.budget?.line(input) ?? null].filter(Boolean).join(`
|
|
24613
|
+
`) || null;
|
|
24613
24614
|
if (!delta)
|
|
24614
24615
|
return decision;
|
|
24615
24616
|
return decision.kind === "rewrite" || decision.kind === "update-input" ? { ...decision, text: [decision.text, delta].filter(Boolean).join(`
|
|
@@ -24719,7 +24720,11 @@ function decide(input, deps) {
|
|
|
24719
24720
|
case "subagent.start":
|
|
24720
24721
|
if (workitRole(descriptor, event.agentType) === "judge")
|
|
24721
24722
|
trackJudge(input, event.agentId, true);
|
|
24722
|
-
seedStanding({
|
|
24723
|
+
seedStanding({
|
|
24724
|
+
...input,
|
|
24725
|
+
session: { ...input.session, agentId: event.agentId }
|
|
24726
|
+
});
|
|
24727
|
+
deps.budget?.start(input, event.agentId, event.agentType);
|
|
24723
24728
|
return {
|
|
24724
24729
|
kind: "context",
|
|
24725
24730
|
text: subagentStartText(input, descriptor, event)
|
|
@@ -24732,13 +24737,19 @@ function decide(input, deps) {
|
|
|
24732
24737
|
case "tool.pre":
|
|
24733
24738
|
if (event.skill)
|
|
24734
24739
|
recordSkillLoad(input, event.skill, "tool");
|
|
24735
|
-
if (event.agentInput && input.host === "claude_code")
|
|
24736
|
-
|
|
24740
|
+
if (event.agentInput && input.host === "claude_code") {
|
|
24741
|
+
const spawn = spawnDecision(descriptor, input.cwd, event.agentInput);
|
|
24742
|
+
if (spawn.kind !== "deny")
|
|
24743
|
+
deps.budget?.spawn(input, event.agentInput);
|
|
24744
|
+
return spawn;
|
|
24745
|
+
}
|
|
24737
24746
|
return NONE6;
|
|
24738
24747
|
case "stop":
|
|
24739
24748
|
return usable2(descriptor.events.stop.support) ? stopDecision(input, descriptor) : NONE6;
|
|
24740
24749
|
case "subagent.stop":
|
|
24741
24750
|
trackJudge(input, event.agentId, false);
|
|
24751
|
+
if (event.agentId)
|
|
24752
|
+
deps.budget?.stop(input, event.agentId);
|
|
24742
24753
|
return NONE6;
|
|
24743
24754
|
case "prompt.submit":
|
|
24744
24755
|
return NONE6;
|
|
@@ -24856,6 +24867,88 @@ var modelKey = (model) => {
|
|
|
24856
24867
|
return typeof source === "string" && source ? `${source}/${id}` : id;
|
|
24857
24868
|
};
|
|
24858
24869
|
|
|
24870
|
+
// packages/workit-core/src/hooks/budget-signal.ts
|
|
24871
|
+
import { createHash as createHash18 } from "node:crypto";
|
|
24872
|
+
import fs26 from "node:fs";
|
|
24873
|
+
import path35 from "node:path";
|
|
24874
|
+
var hash2 = (text) => createHash18("sha256").update(text).digest("hex").slice(0, 32);
|
|
24875
|
+
var budgetDir = (store) => path35.join(store, "budget");
|
|
24876
|
+
var agentBase = (store, session, agentId) => path35.join(budgetDir(store), hash2(`${session}\x00${agentId ?? ""}`));
|
|
24877
|
+
var spawnBudget = (prompt) => {
|
|
24878
|
+
const found = /^TIMEBOX:[^\n]*?\b(\d+)\s+tool calls\b/mu.exec(prompt);
|
|
24879
|
+
const n = found ? Number(found[1]) : NaN;
|
|
24880
|
+
return Number.isInteger(n) && n > 0 ? n : null;
|
|
24881
|
+
};
|
|
24882
|
+
var readBudget = (file) => {
|
|
24883
|
+
try {
|
|
24884
|
+
const { limit, told } = JSON.parse(fs26.readFileSync(file, "utf8"));
|
|
24885
|
+
return typeof limit === "number" && limit > 0 ? { limit, told: Number(told) || 0 } : null;
|
|
24886
|
+
} catch {
|
|
24887
|
+
return null;
|
|
24888
|
+
}
|
|
24889
|
+
};
|
|
24890
|
+
var startBudget = (store, session, agentId, n) => {
|
|
24891
|
+
const dir = budgetDir(store);
|
|
24892
|
+
fs26.mkdirSync(dir, { recursive: true });
|
|
24893
|
+
const cutoff = Date.now() - 604800000;
|
|
24894
|
+
for (const name of fs26.readdirSync(dir))
|
|
24895
|
+
try {
|
|
24896
|
+
if (fs26.statSync(path35.join(dir, name)).mtimeMs < cutoff)
|
|
24897
|
+
fs26.rmSync(path35.join(dir, name));
|
|
24898
|
+
} catch {}
|
|
24899
|
+
const base = agentBase(store, session, agentId);
|
|
24900
|
+
fs26.writeFileSync(`${base}.json`, JSON.stringify({ limit: n, told: 0 }));
|
|
24901
|
+
fs26.rmSync(`${base}.calls`, { force: true });
|
|
24902
|
+
};
|
|
24903
|
+
var bindBudget = (cwd, session, agentId, prompt) => {
|
|
24904
|
+
try {
|
|
24905
|
+
const n = spawnBudget(prompt);
|
|
24906
|
+
const store = n && session ? gitStoreDir(cwd) : null;
|
|
24907
|
+
if (!n || !store)
|
|
24908
|
+
return null;
|
|
24909
|
+
startBudget(store, session, agentId, n);
|
|
24910
|
+
return n;
|
|
24911
|
+
} catch {
|
|
24912
|
+
return null;
|
|
24913
|
+
}
|
|
24914
|
+
};
|
|
24915
|
+
var tickBudget = (cwd, session, agentId) => {
|
|
24916
|
+
try {
|
|
24917
|
+
const store = session ? gitStoreDir(cwd) : null;
|
|
24918
|
+
if (!store)
|
|
24919
|
+
return false;
|
|
24920
|
+
const base = agentBase(store, session, agentId);
|
|
24921
|
+
const budget = readBudget(`${base}.json`);
|
|
24922
|
+
if (!budget)
|
|
24923
|
+
return false;
|
|
24924
|
+
fs26.appendFileSync(`${base}.calls`, ".");
|
|
24925
|
+
return fs26.statSync(`${base}.calls`).size >= budget.limit * (budget.told + 1);
|
|
24926
|
+
} catch {
|
|
24927
|
+
return false;
|
|
24928
|
+
}
|
|
24929
|
+
};
|
|
24930
|
+
var lineFor = (calls) => `Tool-call budget reached (${calls}): commit your work, write your report, stop.`;
|
|
24931
|
+
var reachedOf = (cwd, session, agentId) => {
|
|
24932
|
+
const store = session ? gitStoreDir(cwd) : null;
|
|
24933
|
+
const base = store && agentBase(store, session, agentId);
|
|
24934
|
+
const budget = base && readBudget(`${base}.json`);
|
|
24935
|
+
if (!budget)
|
|
24936
|
+
return null;
|
|
24937
|
+
return { base, budget, reached: Math.floor(fs26.statSync(`${base}.calls`).size / budget.limit) };
|
|
24938
|
+
};
|
|
24939
|
+
var budgetLine = (cwd, session, agentId) => {
|
|
24940
|
+
try {
|
|
24941
|
+
const at = reachedOf(cwd, session, agentId);
|
|
24942
|
+
if (!at || at.reached <= at.budget.told)
|
|
24943
|
+
return null;
|
|
24944
|
+
fs26.writeFileSync(`${at.base}.json`, JSON.stringify({ ...at.budget, told: at.reached }));
|
|
24945
|
+
return lineFor(at.budget.limit * at.reached);
|
|
24946
|
+
} catch {
|
|
24947
|
+
return null;
|
|
24948
|
+
}
|
|
24949
|
+
};
|
|
24950
|
+
var CODEX_GATED = new Set(["bash", "unifiedexec", "shell", "applypatch", "edit", "write"]);
|
|
24951
|
+
|
|
24859
24952
|
// packages/workit-pi/src/context.ts
|
|
24860
24953
|
var piCapabilities = (ctx) => capabilitiesFor(PI_DESCRIPTOR, { ui: ctx?.hasUI === true });
|
|
24861
24954
|
var piContext = (ctx) => ({
|
|
@@ -24910,6 +25003,12 @@ var standingNotice = (ctx) => {
|
|
|
24910
25003
|
const input = turnInput(ctx);
|
|
24911
25004
|
return standingDelta(worker ? { ...input, session: { ...input.session, id: worker } } : input);
|
|
24912
25005
|
};
|
|
25006
|
+
var budgetNotice = (ctx) => {
|
|
25007
|
+
if (!ctx.isProjectTrusted())
|
|
25008
|
+
return null;
|
|
25009
|
+
const session = process.env.WORKIT_PI_WORKER_SESSION && process.env.WORKIT_SESSION_ID?.trim() || ctx.sessionManager.getSessionId();
|
|
25010
|
+
return tickBudget(ctx.cwd, session, null) ? budgetLine(ctx.cwd, session, null) : null;
|
|
25011
|
+
};
|
|
24913
25012
|
var workitContext = (ctx, taskContext = taskTurnContext(ctx)) => {
|
|
24914
25013
|
const session = ctx.sessionManager.getSessionId();
|
|
24915
25014
|
if (!ctx.isProjectTrusted())
|
|
@@ -24934,11 +25033,11 @@ var unfinishedTaskOffer2 = (ctx) => {
|
|
|
24934
25033
|
};
|
|
24935
25034
|
|
|
24936
25035
|
// packages/workit-core/src/hooks/repeat-failure.ts
|
|
24937
|
-
import { createHash as
|
|
25036
|
+
import { createHash as createHash19 } from "node:crypto";
|
|
24938
25037
|
var SAME_CALL_FAILED = "Same call failed twice:";
|
|
24939
25038
|
var MAX_SESSIONS = 256;
|
|
24940
25039
|
var stable = (value) => JSON.stringify(value, (_key, entry) => entry && typeof entry === "object" && !Array.isArray(entry) ? Object.fromEntries(Object.entries(entry).toSorted(([a], [b]) => a.localeCompare(b))) : entry) ?? "null";
|
|
24941
|
-
var hashOf = (call) =>
|
|
25040
|
+
var hashOf = (call) => createHash19("sha256").update(call).digest("hex").slice(0, 32);
|
|
24942
25041
|
var record2 = (memo, sessionId, call, failed, next) => {
|
|
24943
25042
|
const previous = memo.get(sessionId);
|
|
24944
25043
|
memo.delete(sessionId);
|
|
@@ -25138,12 +25237,12 @@ var skillPromptNudge = (prompt, ctx) => process.env.WORKIT_PI_WORKER_SESSION ? n
|
|
|
25138
25237
|
// packages/workit-pi/src/launches.ts
|
|
25139
25238
|
import { mkdirSync as mkdirSync3, readFileSync as readFileSync7, readdirSync as readdirSync5, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
25140
25239
|
import os11 from "node:os";
|
|
25141
|
-
import
|
|
25240
|
+
import path36 from "node:path";
|
|
25142
25241
|
var launchDir = (root) => {
|
|
25143
25242
|
const location = resolveStore(root);
|
|
25144
|
-
return location instanceof Error ? null :
|
|
25243
|
+
return location instanceof Error ? null : path36.join(location.dir, "pi-launches");
|
|
25145
25244
|
};
|
|
25146
|
-
var fileFor = (dir, workerId) =>
|
|
25245
|
+
var fileFor = (dir, workerId) => path36.join(dir, `${workerId.replace(/[^A-Za-z0-9-]/g, "_")}.json`);
|
|
25147
25246
|
var recordLaunch = (root, attempt) => {
|
|
25148
25247
|
const dir = launchDir(root);
|
|
25149
25248
|
if (!dir)
|
|
@@ -25189,7 +25288,7 @@ var abandonedLaunches = (root) => {
|
|
|
25189
25288
|
const found = [];
|
|
25190
25289
|
for (const name of names) {
|
|
25191
25290
|
try {
|
|
25192
|
-
const attempt = JSON.parse(readFileSync7(
|
|
25291
|
+
const attempt = JSON.parse(readFileSync7(path36.join(dir, name), "utf8"));
|
|
25193
25292
|
if (typeof attempt.workerId === "string" && typeof attempt.session === "string") {
|
|
25194
25293
|
if (!alive(attempt))
|
|
25195
25294
|
found.push(attempt);
|
|
@@ -25379,6 +25478,8 @@ function launchWorker(assignment, options) {
|
|
|
25379
25478
|
transcriptPath: null,
|
|
25380
25479
|
event: { kind: "session.start", source: "startup" }
|
|
25381
25480
|
});
|
|
25481
|
+
bindBudget(spec.cwd, env.WORKIT_SESSION_ID, null, `${options.pendingPrompt ?? ""}
|
|
25482
|
+
${assignment.objective}`);
|
|
25382
25483
|
try {
|
|
25383
25484
|
const spawn = options.spawn ?? ((command, args, spawnOptions) => nodeSpawn(command, args, spawnOptions));
|
|
25384
25485
|
handle.spec = { ...spec, env };
|
|
@@ -26129,7 +26230,8 @@ ${nudge}` : content) };
|
|
|
26129
26230
|
const observed = observeResult(event, ctx);
|
|
26130
26231
|
let standing = null;
|
|
26131
26232
|
try {
|
|
26132
|
-
standing = standingNotice(ctx)
|
|
26233
|
+
standing = [standingNotice(ctx), budgetNotice(ctx)].filter(Boolean).join(`
|
|
26234
|
+
`) || null;
|
|
26133
26235
|
} catch {}
|
|
26134
26236
|
if (!standing)
|
|
26135
26237
|
return observed;
|