@brainervirus/workit-pi 8.30.0 → 8.31.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/workit.js +89 -10
  2. package/package.json +1 -1
package/dist/workit.js CHANGED
@@ -14144,6 +14144,18 @@ function diffHash(cwd, base, head) {
14144
14144
  }
14145
14145
  return `sha256:${hash.digest("hex")}`;
14146
14146
  }
14147
+ function cleanRebase(cwd, range) {
14148
+ if (!Object.values(range).every(safeRef2))
14149
+ return false;
14150
+ const fromFork = git4(cwd, ["merge-base", range.fromBase, range.from]);
14151
+ const toFork = git4(cwd, ["merge-base", range.toBase, range.to]);
14152
+ if (!fromFork || !toFork || fromFork === toFork)
14153
+ return false;
14154
+ const merged = gitRun2(cwd, ["merge-tree", "--write-tree", "--no-messages", `--merge-base=${fromFork}`, toFork, range.from], GIT_TIMEOUTS.worktree);
14155
+ const tree = merged.ok ? merged.stdout.split(`
14156
+ `)[0]?.trim() : null;
14157
+ return Boolean(tree) && tree === git4(cwd, ["rev-parse", "--verify", "-q", `${range.to}^{tree}`]);
14158
+ }
14147
14159
  function storeRoot(cwd) {
14148
14160
  const location = resolveStore(path16.resolve(cwd));
14149
14161
  if (location instanceof Error)
@@ -14807,23 +14819,24 @@ function checkVerdicts(cwd, branch, ledgerRows) {
14807
14819
  return drift;
14808
14820
  };
14809
14821
  const exactCache = new Map;
14810
- const exactCarry = (row) => {
14811
- if (FAILING.has(String(row.result)))
14812
- return true;
14822
+ const exactMatch = (row) => {
14813
14823
  let exact = exactCache.get(row);
14814
14824
  if (exact === undefined) {
14815
14825
  const toBase = row.base ?? fallbackBase;
14816
14826
  const toBaseSha = toBase ? resolveCommit(cwd, toBase) : null;
14817
14827
  const fromBase = row.baseSha ?? toBaseSha;
14818
- exact = Boolean(row.head && head && toBaseSha && fromBase && sameOwnChange(cwd, { from: row.head, to: head, fromBase, toBase: toBaseSha }));
14828
+ const range = row.head && head && toBaseSha && fromBase ? { from: row.head, to: head, fromBase, toBase: toBaseSha } : null;
14829
+ exact = !range ? null : sameOwnChange(cwd, range) ? "same" : cleanRebase(cwd, range) ? "rebase" : null;
14819
14830
  exactCache.set(row, exact);
14820
14831
  }
14821
14832
  return exact;
14822
14833
  };
14834
+ const exactCarry = (row) => FAILING.has(String(row.result)) || exactMatch(row) !== null;
14823
14835
  const keyBasis = (row) => {
14824
14836
  const basis = verdictBasis(row, { head, ...keyFor(row.base ?? fallbackBase) });
14825
14837
  return basis === "carried" && !exactCarry(row) ? "stale" : basis;
14826
14838
  };
14839
+ const rebaseNote = (row) => row.head && head && row.head !== head && !FAILING.has(String(row.result)) && keyBasis(row) === "carried" && exactMatch(row) === "rebase" ? { rule: "rebase", since: row.head, files: [] } : null;
14827
14840
  const restacked = (row) => restackCarries(FAILING.has(String(row.result)) ? null : cwd, rows, branch, row.head, head);
14828
14841
  const carryOf = (row) => {
14829
14842
  if (keyBasis(row) !== "stale")
@@ -14901,7 +14914,7 @@ function checkVerdicts(cwd, branch, ledgerRows) {
14901
14914
  independent: independence.length === 0,
14902
14915
  accepted: reasons.length === 0,
14903
14916
  reasons,
14904
- carry: basis === "carried" ? carryOf(row) : null,
14917
+ carry: basis === "carried" ? rebaseNote(row) ?? carryOf(row) : null,
14905
14918
  verdict: row
14906
14919
  });
14907
14920
  if (reasons.length === 0) {
@@ -24752,6 +24765,28 @@ var PI_DESCRIPTOR = {
24752
24765
  }
24753
24766
  ]
24754
24767
  };
24768
+ // packages/workit-core/src/hooks/model-switch.ts
24769
+ var MAX_SESSIONS = 256;
24770
+ var modelSwitched = (models, sessionId, model) => {
24771
+ if (!model)
24772
+ return false;
24773
+ const previous = models.get(sessionId);
24774
+ models.delete(sessionId);
24775
+ models.set(sessionId, model);
24776
+ if (models.size > MAX_SESSIONS)
24777
+ models.delete(models.keys().next().value);
24778
+ return previous !== undefined && previous !== model;
24779
+ };
24780
+ var modelKey = (model) => {
24781
+ if (model === null || typeof model !== "object")
24782
+ return null;
24783
+ const { id, providerID, provider } = model;
24784
+ if (typeof id !== "string" || !id)
24785
+ return null;
24786
+ const source = typeof providerID === "string" ? providerID : provider;
24787
+ return typeof source === "string" && source ? `${source}/${id}` : id;
24788
+ };
24789
+
24755
24790
  // packages/workit-pi/src/context.ts
24756
24791
  var piCapabilities = (ctx) => capabilitiesFor(PI_DESCRIPTOR, { ui: ctx?.hasUI === true });
24757
24792
  var piContext = (ctx) => ({
@@ -24767,7 +24802,7 @@ var piContext = (ctx) => ({
24767
24802
  constraints: [],
24768
24803
  now: () => new Date().toISOString().replace(/\.\d{3}Z$/, "Z")
24769
24804
  });
24770
- var turnContext = (ctx) => {
24805
+ var taskTurnContext = (ctx) => {
24771
24806
  if (!ctx.isProjectTrusted())
24772
24807
  return null;
24773
24808
  try {
@@ -24777,6 +24812,13 @@ var turnContext = (ctx) => {
24777
24812
  return null;
24778
24813
  }
24779
24814
  };
24815
+ var sessionModels = new Map;
24816
+ var turnContext = (ctx) => {
24817
+ const task = taskTurnContext(ctx);
24818
+ const switched = modelSwitched(sessionModels, ctx.sessionManager.getSessionId(), modelKey(ctx.model));
24819
+ return switched && ctx.isProjectTrusted() ? `${invariantBootstrap()}${task ? `
24820
+ ${task}` : ""}` : task;
24821
+ };
24780
24822
  var turnInput = (ctx) => ({
24781
24823
  host: "pi",
24782
24824
  cwd: ctx.cwd,
@@ -24797,7 +24839,7 @@ var standingNotice = (ctx) => {
24797
24839
  const input = turnInput(ctx);
24798
24840
  return standingDelta(worker ? { ...input, session: { ...input.session, id: worker } } : input);
24799
24841
  };
24800
- var workitContext = (ctx, taskContext = turnContext(ctx)) => {
24842
+ var workitContext = (ctx, taskContext = taskTurnContext(ctx)) => {
24801
24843
  const session = ctx.sessionManager.getSessionId();
24802
24844
  if (!ctx.isProjectTrusted())
24803
24845
  return `${invariantBootstrap()}
@@ -24820,6 +24862,38 @@ var unfinishedTaskOffer2 = (ctx) => {
24820
24862
  }
24821
24863
  };
24822
24864
 
24865
+ // packages/workit-core/src/hooks/repeat-failure.ts
24866
+ import { createHash as createHash18 } from "node:crypto";
24867
+ var SAME_CALL_FAILED = "Same call failed twice:";
24868
+ var MAX_SESSIONS2 = 256;
24869
+ 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";
24870
+ var hashOf = (call) => createHash18("sha256").update(call).digest("hex").slice(0, 32);
24871
+ var record2 = (memo, sessionId, call, failed, next) => {
24872
+ const previous = memo.get(sessionId);
24873
+ memo.delete(sessionId);
24874
+ if (!failed)
24875
+ return null;
24876
+ const hash = hashOf(call);
24877
+ memo.set(sessionId, hash);
24878
+ if (memo.size > MAX_SESSIONS2)
24879
+ memo.delete(memo.keys().next().value);
24880
+ return previous === hash && next ? `${SAME_CALL_FAILED} ${next}` : null;
24881
+ };
24882
+ var isFailure = (result) => result !== null && typeof result === "object" && result.ok === false && typeof result.error === "string";
24883
+ var correctedPayload = (tool, result) => {
24884
+ const example = /Example: (\{.*\})\s*$/.exec(result.error)?.[1];
24885
+ if (example)
24886
+ return `${tool} ${example}`;
24887
+ const guidance = result.details?.guidance;
24888
+ return typeof guidance === "string" && guidance ? guidance : null;
24889
+ };
24890
+ var escalateToolFailure = (memo, sessionId, tool, input, result) => {
24891
+ const failed = isFailure(result);
24892
+ const line = record2(memo, sessionId, `tool\x00${tool}\x00${stable(input)}`, failed, failed ? correctedPayload(tool, result) : null);
24893
+ return line && failed ? { ...result, error: `${result.error}
24894
+ ${line}` } : result;
24895
+ };
24896
+
24823
24897
  // packages/workit-pi/src/tools.ts
24824
24898
  var readOnlyActions = new Set(["list", "inspect", "preview", "explain", "export"]);
24825
24899
  var output = (result) => ({
@@ -24847,18 +24921,23 @@ var trustedForMutation = (ctx, action) => {
24847
24921
  return success(null, null, null);
24848
24922
  return failure2("permission_denied", "Pi project is not trusted for Workit mutations");
24849
24923
  };
24924
+ var failures = new Map;
24850
24925
  var executeFamily = async (family, input, ctx) => {
24926
+ const result = runFamily(family, input, ctx);
24927
+ return output(escalateToolFailure(failures, piContext(ctx).caller.actor, `workit_${family}`, input, result));
24928
+ };
24929
+ var runFamily = (family, input, ctx) => {
24851
24930
  const parsed = parseAdvertisedOperation(family, input, "pi");
24852
24931
  if (!parsed.ok)
24853
- return output(parsed);
24932
+ return parsed;
24854
24933
  const trust = trustedForMutation(ctx, parsed.data.action);
24855
24934
  if (!trust.ok)
24856
- return output(trust);
24935
+ return trust;
24857
24936
  const context = piContext(ctx);
24858
24937
  const core = new WorkitCore(new TaskStore(ctx.cwd), context);
24859
24938
  const run = core[family];
24860
24939
  const result = run.call(core, parsed.data);
24861
- return output(family === "task" && (context.workerId ?? null) !== null ? briefInspectResult(parsed.data, result) : result);
24940
+ return family === "task" && (context.workerId ?? null) !== null ? briefInspectResult(parsed.data, result) : result;
24862
24941
  };
24863
24942
  var registerWorkitTools = (pi, options = {}) => {
24864
24943
  for (const family of OPERATION_FAMILIES)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-pi",
3
- "version": "8.30.0",
3
+ "version": "8.31.1",
4
4
  "description": "Workit native extension for Pi — tools, method skills, and session continuity",
5
5
  "keywords": [
6
6
  "agentic-coding",