@brainervirus/workit-opencode 8.30.0 → 8.31.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/plugin.js +121 -22
- package/package.json +2 -2
package/dist/plugin.js
CHANGED
|
@@ -25721,6 +25721,22 @@ var judgeVerdictText = (root, session, workerContext) => {
|
|
|
25721
25721
|
});
|
|
25722
25722
|
return `If this session verifies or reviews a candidate, record its verdict with exactly this command (pick the result and kind, live when you drove the real surface, name the candidate branch if it differs, say what you ran): \`${line}\`. Your shell already acts as your own Workit session ${childSessionId(session.parentID ?? "", session.id)}: pass no --session or --token, and never set WORKIT_SESSION_ID by hand.`;
|
|
25723
25723
|
};
|
|
25724
|
+
var injectModelSwitch = (root, session, directChildren, system) => {
|
|
25725
|
+
if (!session || !sameWorkspace(root, session.directory))
|
|
25726
|
+
return;
|
|
25727
|
+
const contract = session.parentID ? workerContextFor(root, session.id, session.parentID, directChildren) : getWorkitBootstrap();
|
|
25728
|
+
const taskContext = compactContextFor(root, session.id);
|
|
25729
|
+
const parts = [
|
|
25730
|
+
contract,
|
|
25731
|
+
taskContext && `<workit-task-context>${taskContext}</workit-task-context>`
|
|
25732
|
+
].filter(Boolean);
|
|
25733
|
+
if (parts.length === 0)
|
|
25734
|
+
return;
|
|
25735
|
+
system.push(textPart(`<workit-model-switch>
|
|
25736
|
+
${parts.join(`
|
|
25737
|
+
`)}
|
|
25738
|
+
</workit-model-switch>`));
|
|
25739
|
+
};
|
|
25724
25740
|
var injectHistoryOffer = (root, session, offeredSessions, system) => {
|
|
25725
25741
|
if (!session || session.parentID !== undefined || !sameWorkspace(root, session.directory) || offeredSessions.has(session.id))
|
|
25726
25742
|
return;
|
|
@@ -25804,6 +25820,60 @@ var childDenial = (identity) => `OpenCode child session has no validated Workit
|
|
|
25804
25820
|
|
|
25805
25821
|
// packages/workit-opencode/src/v2/shell.ts
|
|
25806
25822
|
import path44 from "node:path";
|
|
25823
|
+
|
|
25824
|
+
// packages/workit-core/src/hooks/repeat-failure.ts
|
|
25825
|
+
import { createHash as createHash18 } from "node:crypto";
|
|
25826
|
+
var SAME_CALL_FAILED = "Same call failed twice:";
|
|
25827
|
+
var MAX_SESSIONS = 256;
|
|
25828
|
+
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";
|
|
25829
|
+
var hashOf = (call) => createHash18("sha256").update(call).digest("hex").slice(0, 32);
|
|
25830
|
+
var record3 = (memo, sessionId, call, failed, next) => {
|
|
25831
|
+
const previous = memo.get(sessionId);
|
|
25832
|
+
memo.delete(sessionId);
|
|
25833
|
+
if (!failed)
|
|
25834
|
+
return null;
|
|
25835
|
+
const hash = hashOf(call);
|
|
25836
|
+
memo.set(sessionId, hash);
|
|
25837
|
+
if (memo.size > MAX_SESSIONS)
|
|
25838
|
+
memo.delete(memo.keys().next().value);
|
|
25839
|
+
return previous === hash && next ? `${SAME_CALL_FAILED} ${next}` : null;
|
|
25840
|
+
};
|
|
25841
|
+
var isFailure = (result) => result !== null && typeof result === "object" && result.ok === false && typeof result.error === "string";
|
|
25842
|
+
var correctedPayload = (tool, result) => {
|
|
25843
|
+
const example = /Example: (\{.*\})\s*$/.exec(result.error)?.[1];
|
|
25844
|
+
if (example)
|
|
25845
|
+
return `${tool} ${example}`;
|
|
25846
|
+
const guidance = result.details?.guidance;
|
|
25847
|
+
return typeof guidance === "string" && guidance ? guidance : null;
|
|
25848
|
+
};
|
|
25849
|
+
var escalateToolFailure = (memo, sessionId, tool, input, result) => {
|
|
25850
|
+
const failed = isFailure(result);
|
|
25851
|
+
const line = record3(memo, sessionId, `tool\x00${tool}\x00${stable(input)}`, failed, failed ? correctedPayload(tool, result) : null);
|
|
25852
|
+
return line && failed ? { ...result, error: `${result.error}
|
|
25853
|
+
${line}` } : result;
|
|
25854
|
+
};
|
|
25855
|
+
var WORKIT_COMMAND = /^\s*(?:[A-Za-z_][A-Za-z0-9_]*=\S*\s+)*workit\s/;
|
|
25856
|
+
var unblockOf = (output) => {
|
|
25857
|
+
const human = /^\s*unblock: (.+)$/m.exec(output)?.[1];
|
|
25858
|
+
if (human)
|
|
25859
|
+
return human.trim();
|
|
25860
|
+
const json = /"unblock":("(?:[^"\\]|\\.)*")/.exec(output)?.[1];
|
|
25861
|
+
if (!json)
|
|
25862
|
+
return null;
|
|
25863
|
+
try {
|
|
25864
|
+
return JSON.parse(json);
|
|
25865
|
+
} catch {
|
|
25866
|
+
return null;
|
|
25867
|
+
}
|
|
25868
|
+
};
|
|
25869
|
+
var repeatedCliFailure = (memo, sessionId, command, output) => {
|
|
25870
|
+
if (!WORKIT_COMMAND.test(command))
|
|
25871
|
+
return null;
|
|
25872
|
+
const failed = /^workit: /m.test(output) || /"ok":\s*false/.test(output);
|
|
25873
|
+
return record3(memo, sessionId, `cli\x00${command.trim()}`, failed, failed ? unblockOf(output) : null);
|
|
25874
|
+
};
|
|
25875
|
+
|
|
25876
|
+
// packages/workit-opencode/src/v2/shell.ts
|
|
25807
25877
|
var commandOf = (input) => {
|
|
25808
25878
|
if (input === null || typeof input !== "object")
|
|
25809
25879
|
return null;
|
|
@@ -25855,7 +25925,12 @@ var observeShellBefore = (root, event, workdirs) => {
|
|
|
25855
25925
|
noteRawCommit(input, shell.command, callKey(String(event.id), shell.command));
|
|
25856
25926
|
} catch {}
|
|
25857
25927
|
};
|
|
25858
|
-
var
|
|
25928
|
+
var outputText = (content) => typeof content === "string" ? content : Array.isArray(content) ? content.map((part) => typeof part.text === "string" ? part.text : "").join(`
|
|
25929
|
+
`) : "";
|
|
25930
|
+
var appendText = (result, text) => typeof result.content === "string" ? { ...result, content: `${result.content}
|
|
25931
|
+
|
|
25932
|
+
${text}` } : Array.isArray(result.content) ? { ...result, content: [...result.content, { type: "text", text }] } : result;
|
|
25933
|
+
var observeShellResult = (root, event, failures = new Map) => {
|
|
25859
25934
|
try {
|
|
25860
25935
|
if (event.tool !== "shell" || event.status !== "completed")
|
|
25861
25936
|
return;
|
|
@@ -25866,17 +25941,14 @@ var observeShellResult = (root, event) => {
|
|
|
25866
25941
|
rawGitPost(input, shell.command, callKey(String(event.id), shell.command));
|
|
25867
25942
|
const nudge = shellNudge(input, shell.command);
|
|
25868
25943
|
const result = event.result;
|
|
25869
|
-
if (
|
|
25944
|
+
if (!result)
|
|
25870
25945
|
return;
|
|
25871
|
-
|
|
25872
|
-
|
|
25946
|
+
const repeated = repeatedCliFailure(failures, String(event.sessionID), shell.command, outputText(result.content));
|
|
25947
|
+
const extra = [nudge.kind === "context" ? nudge.text : null, repeated].filter((text) => text !== null);
|
|
25948
|
+
if (extra.length > 0)
|
|
25949
|
+
event.result = appendText(result, extra.join(`
|
|
25873
25950
|
|
|
25874
|
-
|
|
25875
|
-
else if (Array.isArray(result.content))
|
|
25876
|
-
event.result = {
|
|
25877
|
-
...result,
|
|
25878
|
-
content: [...result.content, { type: "text", text: nudge.text }]
|
|
25879
|
-
};
|
|
25951
|
+
`));
|
|
25880
25952
|
} catch {}
|
|
25881
25953
|
};
|
|
25882
25954
|
|
|
@@ -25968,15 +26040,15 @@ var injectSkillNudge = (root, session, messages, system) => {
|
|
|
25968
26040
|
};
|
|
25969
26041
|
|
|
25970
26042
|
// packages/workit-opencode/src/v2/stop.ts
|
|
25971
|
-
var
|
|
26043
|
+
var record4 = (value) => typeof value === "object" && value !== null ? value : {};
|
|
25972
26044
|
var lastAssistantText = (messages) => {
|
|
25973
26045
|
for (const message of messages.toReversed()) {
|
|
25974
|
-
if (
|
|
26046
|
+
if (record4(message).type !== "assistant")
|
|
25975
26047
|
continue;
|
|
25976
|
-
const content =
|
|
26048
|
+
const content = record4(message).content;
|
|
25977
26049
|
if (!Array.isArray(content))
|
|
25978
26050
|
return null;
|
|
25979
|
-
const text = content.filter((part) =>
|
|
26051
|
+
const text = content.filter((part) => record4(part).type === "text" && typeof record4(part).text === "string").map((part) => record4(part).text).join(`
|
|
25980
26052
|
`);
|
|
25981
26053
|
return text || null;
|
|
25982
26054
|
}
|
|
@@ -26147,6 +26219,28 @@ var pluginSourceFiles = [
|
|
|
26147
26219
|
])
|
|
26148
26220
|
].filter((file) => existsSync16(file)).toSorted();
|
|
26149
26221
|
|
|
26222
|
+
// packages/workit-core/src/hooks/model-switch.ts
|
|
26223
|
+
var MAX_SESSIONS2 = 256;
|
|
26224
|
+
var modelSwitched = (models, sessionId, model) => {
|
|
26225
|
+
if (!model)
|
|
26226
|
+
return false;
|
|
26227
|
+
const previous = models.get(sessionId);
|
|
26228
|
+
models.delete(sessionId);
|
|
26229
|
+
models.set(sessionId, model);
|
|
26230
|
+
if (models.size > MAX_SESSIONS2)
|
|
26231
|
+
models.delete(models.keys().next().value);
|
|
26232
|
+
return previous !== undefined && previous !== model;
|
|
26233
|
+
};
|
|
26234
|
+
var modelKey = (model) => {
|
|
26235
|
+
if (model === null || typeof model !== "object")
|
|
26236
|
+
return null;
|
|
26237
|
+
const { id, providerID, provider } = model;
|
|
26238
|
+
if (typeof id !== "string" || !id)
|
|
26239
|
+
return null;
|
|
26240
|
+
const source = typeof providerID === "string" ? providerID : provider;
|
|
26241
|
+
return typeof source === "string" && source ? `${source}/${id}` : id;
|
|
26242
|
+
};
|
|
26243
|
+
|
|
26150
26244
|
// packages/workit-opencode/src/v2/plugin.ts
|
|
26151
26245
|
var sessionFacts = async (ctx, sessionID) => {
|
|
26152
26246
|
try {
|
|
@@ -26185,6 +26279,8 @@ var setup = async (ctx) => {
|
|
|
26185
26279
|
const sourceMarker = markSourcesLoaded(pluginSourceFiles);
|
|
26186
26280
|
let staleSourcesWarned = false;
|
|
26187
26281
|
const historyOfferSessions = new Set;
|
|
26282
|
+
const sessionModels = new Map;
|
|
26283
|
+
const failureMemo = new Map;
|
|
26188
26284
|
const lifecycle = createV2Lifecycle({
|
|
26189
26285
|
root,
|
|
26190
26286
|
getSession: async (sessionID) => {
|
|
@@ -26223,9 +26319,10 @@ var setup = async (ctx) => {
|
|
|
26223
26319
|
input: spec.input,
|
|
26224
26320
|
options: { codemode: false },
|
|
26225
26321
|
execute: async (input, tool) => {
|
|
26322
|
+
const respond = (value) => resultContent(escalateToolFailure(failureMemo, String(tool.sessionID), spec.name, input, value));
|
|
26226
26323
|
const session = await sessionFacts(ctx, tool.sessionID);
|
|
26227
26324
|
if (session === null || !sameWorkspace(root, session.directory))
|
|
26228
|
-
return
|
|
26325
|
+
return respond(failure2("permission_denied", "OpenCode session location does not match the plugin checkout"));
|
|
26229
26326
|
if (spec.name === "workit_context")
|
|
26230
26327
|
return {
|
|
26231
26328
|
content: await contextTool.execute(input, { directory: root, sessionID: session.id })
|
|
@@ -26239,19 +26336,19 @@ var setup = async (ctx) => {
|
|
|
26239
26336
|
const directChild = lead !== null && lead.parentID === undefined && sameWorkspace(root, lead.directory);
|
|
26240
26337
|
const inspecting = childMayInspect(family, input);
|
|
26241
26338
|
if (!directChild || family === null || !(inspecting || childMayRecord(family, input)))
|
|
26242
|
-
return
|
|
26339
|
+
return respond(failure2("permission_denied", childDenial(identity)));
|
|
26243
26340
|
if (inspecting)
|
|
26244
|
-
return
|
|
26341
|
+
return respond(runFamily(family, input, { ...session, id: identity }, store, null, true));
|
|
26245
26342
|
if (childTaskMissing(store, input))
|
|
26246
|
-
return
|
|
26247
|
-
return
|
|
26343
|
+
return respond(failure2("not_found", "no task for this branch yet: the lead starts one (workit_task start) before a child records on it, or pass taskId"));
|
|
26344
|
+
return respond(runFamily(family, input, { ...session, id: identity }, store, null));
|
|
26248
26345
|
}
|
|
26249
26346
|
if (family !== null)
|
|
26250
|
-
return
|
|
26347
|
+
return respond(runFamily(family, input, session, store, workerId));
|
|
26251
26348
|
if (spec.name === "workit_init_apply") {
|
|
26252
26349
|
return { content: executeInitApply(input, root, initApplyRuntime) };
|
|
26253
26350
|
}
|
|
26254
|
-
return
|
|
26351
|
+
return respond(failure2("not_found", `unknown Workit tool ${spec.name}`));
|
|
26255
26352
|
}
|
|
26256
26353
|
});
|
|
26257
26354
|
}
|
|
@@ -26286,7 +26383,7 @@ var setup = async (ctx) => {
|
|
|
26286
26383
|
await ctx.tool.hook("execute.after", async (event) => {
|
|
26287
26384
|
if (event.tool === "shell") {
|
|
26288
26385
|
settleShellCall(pendingShells, { sessionID: String(event.sessionID), input: event.input });
|
|
26289
|
-
return observeShellResult(root, event);
|
|
26386
|
+
return observeShellResult(root, event, failureMemo);
|
|
26290
26387
|
}
|
|
26291
26388
|
if (event.tool !== "subagent")
|
|
26292
26389
|
return;
|
|
@@ -26307,6 +26404,8 @@ var setup = async (ctx) => {
|
|
|
26307
26404
|
injectHistoryOffer(root, session, historyOfferSessions, event.system);
|
|
26308
26405
|
if (session)
|
|
26309
26406
|
injectSkillNudge(root, session, event.messages, event.system);
|
|
26407
|
+
if (modelSwitched(sessionModels, String(event.sessionID), modelKey(event.model)))
|
|
26408
|
+
injectModelSwitch(root, session, lifecycle.directChildren, event.system);
|
|
26310
26409
|
if (!staleSourcesWarned) {
|
|
26311
26410
|
const changed = changedSourcesSinceLoad(sourceMarker);
|
|
26312
26411
|
if (changed.length > 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-opencode",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.31.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit OpenCode plugin — native tools, adaptive policy, and sixteen method skills",
|
|
6
6
|
"keywords": [
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"typecheck": "tsc --noEmit"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@brainervirus/workit-core": "^8.
|
|
42
|
+
"@brainervirus/workit-core": "^8.31.0",
|
|
43
43
|
"@opencode/plugin": "2.0.18"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|