@brainervirus/workit-pi 8.32.0 → 8.34.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/workit.js +78 -29
- package/package.json +1 -1
package/dist/workit.js
CHANGED
|
@@ -7410,10 +7410,11 @@ function invalidOperation(family, input, error) {
|
|
|
7410
7410
|
const request = isObject2(input) ? input : {};
|
|
7411
7411
|
const action = typeof request.action === "string" ? request.action : "";
|
|
7412
7412
|
const actions = OPERATION_ACTIONS[family];
|
|
7413
|
-
if (!actions.includes(action))
|
|
7414
|
-
|
|
7415
|
-
|
|
7416
|
-
});
|
|
7413
|
+
if (!actions.includes(action)) {
|
|
7414
|
+
const common = actions.find((name) => READ_ONLY_ACTIONS.has(name)) ?? actions[0];
|
|
7415
|
+
const example = JSON.stringify(exampleOperation(family, common));
|
|
7416
|
+
return failure2("invalid_input", `${family}: action must be one of ${oneOf(actions)}. Example: ${example}`, { fields: [{ path: "action", reason: `got ${JSON.stringify(request.action ?? null)}` }] });
|
|
7417
|
+
}
|
|
7417
7418
|
const own = actionKeys(family, action);
|
|
7418
7419
|
const fields = [];
|
|
7419
7420
|
const sentence = [];
|
|
@@ -16205,7 +16206,14 @@ var sessionMarkerFile = (input, session, store) => {
|
|
|
16205
16206
|
return path19.join(dir, "hooks", `skills-${name}.json`);
|
|
16206
16207
|
};
|
|
16207
16208
|
var list2 = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
16208
|
-
var EMPTY = {
|
|
16209
|
+
var EMPTY = {
|
|
16210
|
+
nudged: [],
|
|
16211
|
+
loaded: [],
|
|
16212
|
+
raw: [],
|
|
16213
|
+
stops: [],
|
|
16214
|
+
judges: [],
|
|
16215
|
+
model: null
|
|
16216
|
+
};
|
|
16209
16217
|
var readRaw = (file) => {
|
|
16210
16218
|
try {
|
|
16211
16219
|
return fs15.readFileSync(file, "utf8");
|
|
@@ -16221,7 +16229,8 @@ var parseMarker = (text) => {
|
|
|
16221
16229
|
loaded: list2(value.loaded),
|
|
16222
16230
|
raw: list2(value.raw),
|
|
16223
16231
|
stops: list2(value.stops),
|
|
16224
|
-
judges: list2(value.judges)
|
|
16232
|
+
judges: list2(value.judges),
|
|
16233
|
+
model: typeof value.model === "string" ? value.model : null
|
|
16225
16234
|
};
|
|
16226
16235
|
} catch {
|
|
16227
16236
|
return { ...EMPTY };
|
|
@@ -16266,6 +16275,18 @@ var trackJudge = (input, agentId, running) => {
|
|
|
16266
16275
|
return { ...marker, judges: running ? [...rest, agentId] : rest };
|
|
16267
16276
|
});
|
|
16268
16277
|
};
|
|
16278
|
+
var modelSwitchedOnDisk = (input) => {
|
|
16279
|
+
const session = input.session.id;
|
|
16280
|
+
const model = input.model;
|
|
16281
|
+
const file = session && model ? sessionMarkerFile(input, session) : null;
|
|
16282
|
+
if (!file || !model)
|
|
16283
|
+
return false;
|
|
16284
|
+
const previous = readSessionMarker(file).model;
|
|
16285
|
+
if (previous === model)
|
|
16286
|
+
return false;
|
|
16287
|
+
updateSessionMarker(file, (marker) => ({ ...marker, model }));
|
|
16288
|
+
return previous !== null;
|
|
16289
|
+
};
|
|
16269
16290
|
|
|
16270
16291
|
// packages/workit-core/src/hooks/shell-words.ts
|
|
16271
16292
|
class ShellAnalysisError extends Error {
|
|
@@ -24561,7 +24582,9 @@ function decide(input, deps) {
|
|
|
24561
24582
|
if (!usable2(descriptor.context.perTurn))
|
|
24562
24583
|
return NONE6;
|
|
24563
24584
|
const current = turnContextText(input, descriptor);
|
|
24564
|
-
const
|
|
24585
|
+
const turn = resendsOnChange(descriptor) ? changedTurnContext(input, current) : current;
|
|
24586
|
+
const text = input.model && modelSwitchedOnDisk(input) ? [invariantBootstrap(), turn].filter(Boolean).join(`
|
|
24587
|
+
`) : turn;
|
|
24565
24588
|
return withContextLine(text ? { kind: "context", text } : NONE6, promptNudge(input, event.prompt));
|
|
24566
24589
|
}
|
|
24567
24590
|
case "shell.pre": {
|
|
@@ -24767,17 +24790,6 @@ var PI_DESCRIPTOR = {
|
|
|
24767
24790
|
]
|
|
24768
24791
|
};
|
|
24769
24792
|
// packages/workit-core/src/hooks/model-switch.ts
|
|
24770
|
-
var MAX_SESSIONS = 256;
|
|
24771
|
-
var modelSwitched = (models, sessionId, model) => {
|
|
24772
|
-
if (!model)
|
|
24773
|
-
return false;
|
|
24774
|
-
const previous = models.get(sessionId);
|
|
24775
|
-
models.delete(sessionId);
|
|
24776
|
-
models.set(sessionId, model);
|
|
24777
|
-
if (models.size > MAX_SESSIONS)
|
|
24778
|
-
models.delete(models.keys().next().value);
|
|
24779
|
-
return previous !== undefined && previous !== model;
|
|
24780
|
-
};
|
|
24781
24793
|
var modelKey = (model) => {
|
|
24782
24794
|
if (model === null || typeof model !== "object")
|
|
24783
24795
|
return null;
|
|
@@ -24813,13 +24825,15 @@ var taskTurnContext = (ctx) => {
|
|
|
24813
24825
|
return null;
|
|
24814
24826
|
}
|
|
24815
24827
|
};
|
|
24816
|
-
var
|
|
24817
|
-
var
|
|
24818
|
-
const
|
|
24819
|
-
const
|
|
24820
|
-
|
|
24821
|
-
|
|
24828
|
+
var switchedSessions = new Set;
|
|
24829
|
+
var noteModelSelect = (event, ctx) => {
|
|
24830
|
+
const next = modelKey(event.model);
|
|
24831
|
+
const previous = modelKey(event.previousModel);
|
|
24832
|
+
if (next && previous && next !== previous)
|
|
24833
|
+
switchedSessions.add(ctx.sessionManager.getSessionId());
|
|
24822
24834
|
};
|
|
24835
|
+
var modelSwitchContract = (ctx) => switchedSessions.delete(ctx.sessionManager.getSessionId()) && ctx.isProjectTrusted() ? invariantBootstrap() : null;
|
|
24836
|
+
var turnContext = (ctx) => taskTurnContext(ctx);
|
|
24823
24837
|
var turnInput = (ctx) => ({
|
|
24824
24838
|
host: "pi",
|
|
24825
24839
|
cwd: ctx.cwd,
|
|
@@ -24866,7 +24880,7 @@ var unfinishedTaskOffer2 = (ctx) => {
|
|
|
24866
24880
|
// packages/workit-core/src/hooks/repeat-failure.ts
|
|
24867
24881
|
import { createHash as createHash18 } from "node:crypto";
|
|
24868
24882
|
var SAME_CALL_FAILED = "Same call failed twice:";
|
|
24869
|
-
var
|
|
24883
|
+
var MAX_SESSIONS = 256;
|
|
24870
24884
|
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";
|
|
24871
24885
|
var hashOf = (call) => createHash18("sha256").update(call).digest("hex").slice(0, 32);
|
|
24872
24886
|
var record2 = (memo, sessionId, call, failed, next) => {
|
|
@@ -24876,7 +24890,7 @@ var record2 = (memo, sessionId, call, failed, next) => {
|
|
|
24876
24890
|
return null;
|
|
24877
24891
|
const hash = hashOf(call);
|
|
24878
24892
|
memo.set(sessionId, hash);
|
|
24879
|
-
if (memo.size >
|
|
24893
|
+
if (memo.size > MAX_SESSIONS)
|
|
24880
24894
|
memo.delete(memo.keys().next().value);
|
|
24881
24895
|
return previous === hash && next ? `${SAME_CALL_FAILED} ${next}` : null;
|
|
24882
24896
|
};
|
|
@@ -24894,6 +24908,26 @@ var escalateToolFailure = (memo, sessionId, tool, input, result) => {
|
|
|
24894
24908
|
return line && failed ? { ...result, error: `${result.error}
|
|
24895
24909
|
${line}` } : result;
|
|
24896
24910
|
};
|
|
24911
|
+
var WORKIT_COMMAND = /^\s*(?:[A-Za-z_][A-Za-z0-9_]*=\S*\s+)*workit\s/;
|
|
24912
|
+
var unblockOf = (output) => {
|
|
24913
|
+
const human = /^\s*unblock: (.+)$/m.exec(output)?.[1];
|
|
24914
|
+
if (human)
|
|
24915
|
+
return human.trim();
|
|
24916
|
+
const json = /"unblock":("(?:[^"\\]|\\.)*")/.exec(output)?.[1];
|
|
24917
|
+
if (!json)
|
|
24918
|
+
return null;
|
|
24919
|
+
try {
|
|
24920
|
+
return JSON.parse(json);
|
|
24921
|
+
} catch {
|
|
24922
|
+
return null;
|
|
24923
|
+
}
|
|
24924
|
+
};
|
|
24925
|
+
var repeatedCliFailure = (memo, sessionId, command, output) => {
|
|
24926
|
+
if (!WORKIT_COMMAND.test(command))
|
|
24927
|
+
return null;
|
|
24928
|
+
const failed = /^workit: /m.test(output) || /"ok":\s*false/.test(output);
|
|
24929
|
+
return record2(memo, sessionId, `cli\x00${command.trim()}`, failed, failed ? unblockOf(output) : null);
|
|
24930
|
+
};
|
|
24897
24931
|
|
|
24898
24932
|
// packages/workit-pi/src/tools.ts
|
|
24899
24933
|
var readOnlyActions = new Set(["list", "inspect", "preview", "explain", "export"]);
|
|
@@ -25013,11 +25047,17 @@ var enforceToolPolicy = (event, ctx) => {
|
|
|
25013
25047
|
};
|
|
25014
25048
|
var observeToolResult = (event, ctx) => {
|
|
25015
25049
|
try {
|
|
25016
|
-
if (event.toolName !== "bash"
|
|
25050
|
+
if (event.toolName !== "bash")
|
|
25017
25051
|
return;
|
|
25018
25052
|
const command = event.input?.command;
|
|
25019
25053
|
if (typeof command !== "string")
|
|
25020
25054
|
return;
|
|
25055
|
+
const shown = event.content.map((part) => part.type === "text" ? part.text : "").join(`
|
|
25056
|
+
`);
|
|
25057
|
+
const session = piContext(ctx).caller.actor;
|
|
25058
|
+
const repeated = repeatedCliFailure(failures, session, command, shown);
|
|
25059
|
+
if (event.isError)
|
|
25060
|
+
return repeated ? { content: [...event.content, { type: "text", text: repeated }] } : undefined;
|
|
25021
25061
|
const post = hookInput(ctx, {
|
|
25022
25062
|
kind: "shell.post",
|
|
25023
25063
|
command,
|
|
@@ -25029,7 +25069,10 @@ var observeToolResult = (event, ctx) => {
|
|
|
25029
25069
|
const named = process.env.WORKIT_PI_WORKER_ROLE;
|
|
25030
25070
|
const role = named === "implementer" ? "implementer" : named ? "judge" : null;
|
|
25031
25071
|
const nudge = process.env.WORKIT_PI_WORKER_SESSION ? rawGitPre(post, command, { nudge: roleSteering(role, false).nudges }) : shellNudge(post, command);
|
|
25032
|
-
|
|
25072
|
+
const extra = [nudge.kind === "context" ? nudge.text : null, repeated].filter((text) => text !== null);
|
|
25073
|
+
return extra.length > 0 ? { content: [...event.content, { type: "text", text: extra.join(`
|
|
25074
|
+
|
|
25075
|
+
`) }] } : undefined;
|
|
25033
25076
|
} catch {
|
|
25034
25077
|
return;
|
|
25035
25078
|
}
|
|
@@ -25953,6 +25996,7 @@ function extension(pi) {
|
|
|
25953
25996
|
sessions.delete(ctx.sessionManager.getSessionId());
|
|
25954
25997
|
reconcileLostWorkers(ctx);
|
|
25955
25998
|
});
|
|
25999
|
+
pi.on("model_select", (event, ctx) => noteModelSelect(event, ctx));
|
|
25956
26000
|
pi.on("before_agent_start", (event, ctx) => {
|
|
25957
26001
|
if (event.messageType !== "user")
|
|
25958
26002
|
return;
|
|
@@ -25961,7 +26005,8 @@ function extension(pi) {
|
|
|
25961
26005
|
const trusted = ctx.isProjectTrusted();
|
|
25962
26006
|
const task = turnContext(ctx);
|
|
25963
26007
|
let content;
|
|
25964
|
-
|
|
26008
|
+
const firstTurn = !sessions.has(id);
|
|
26009
|
+
if (!firstTurn) {
|
|
25965
26010
|
content = trusted ? changedTurnContext(turnInput(ctx), task) : null;
|
|
25966
26011
|
} else {
|
|
25967
26012
|
sessions.add(id);
|
|
@@ -25973,6 +26018,10 @@ function extension(pi) {
|
|
|
25973
26018
|
|
|
25974
26019
|
${offer}` : ""}`;
|
|
25975
26020
|
}
|
|
26021
|
+
const contract = modelSwitchContract(ctx);
|
|
26022
|
+
if (contract && !firstTurn)
|
|
26023
|
+
content = content ? `${contract}
|
|
26024
|
+
${content}` : contract;
|
|
25976
26025
|
if (content)
|
|
25977
26026
|
return { message: contextMessage(ctx, nudge ? `${content}
|
|
25978
26027
|
|