@codexhost/cli-win32-arm64 0.16.0 → 0.17.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.
Files changed (39) hide show
  1. package/README.md +2 -2
  2. package/THIRD_PARTY_NOTICES.txt +6 -2
  3. package/app/codexhost-distribution.json +1 -1
  4. package/app/console-server.mjs +59 -21
  5. package/app/console-web.js +49 -18
  6. package/app/desktop-controller.mjs +554 -34
  7. package/app/host-runtime.mjs +3436 -1846
  8. package/app/plugins/antigravity/plugin.mjs +39 -3
  9. package/app/plugins/claude-code/plugin.mjs +16 -7
  10. package/app/plugins/codebuddy/plugin.mjs +14 -1
  11. package/app/plugins/codex-usage/plugin.mjs +4 -1
  12. package/app/plugins/copilot/plugin.mjs +4 -1
  13. package/app/plugins/cursor-cli/plugin.mjs +13 -6
  14. package/app/plugins/deepseek-harness/plugin.mjs +463 -47
  15. package/app/plugins/devin/assets/icon.svg +1 -0
  16. package/app/plugins/devin/manifest.json +30 -0
  17. package/app/plugins/devin/plugin.mjs +23363 -0
  18. package/app/plugins/enabled.json +2 -0
  19. package/app/plugins/grok/plugin.mjs +476 -392
  20. package/app/plugins/hermes/plugin.mjs +457 -197
  21. package/app/plugins/kimi-code/plugin.mjs +4 -1
  22. package/app/plugins/kiro-cli/plugin.mjs +4 -1
  23. package/app/plugins/omp/plugin.mjs +4 -1
  24. package/app/plugins/opencode/plugin.mjs +4 -1
  25. package/app/plugins/pi/plugin.mjs +1464 -412
  26. package/app/plugins/qoder/plugin.mjs +9528 -8655
  27. package/app/plugins/qoder-cn/plugin.mjs +9528 -8655
  28. package/app/plugins/qwen-code/assets/icon.svg +1 -0
  29. package/app/plugins/qwen-code/manifest.json +29 -0
  30. package/app/plugins/qwen-code/plugin.mjs +29298 -0
  31. package/app/plugins/workbuddy/plugin.mjs +14 -1
  32. package/app/plugins/zcode/plugin.mjs +4 -1
  33. package/app/renderer-extension.js +510 -114
  34. package/bin/codexhost.exe +0 -0
  35. package/libexec/codexhost-node-repl.exe +0 -0
  36. package/libexec/codexhost-shim.exe +0 -0
  37. package/libexec/codexhost-updater.exe +0 -0
  38. package/licenses/Qwen-Code-SDK-LICENSE.txt +203 -0
  39. package/package.json +2 -2
@@ -528,9 +528,9 @@ async function jsonlHeader(file2, match, signal, maxLines = 4) {
528
528
  continue;
529
529
  }
530
530
  if (typeof value === "object" && value !== null && !Array.isArray(value)) {
531
- const record7 = value;
532
- if (match(record7))
533
- return record7;
531
+ const record9 = value;
532
+ if (match(record9))
533
+ return record9;
534
534
  }
535
535
  }
536
536
  return null;
@@ -1317,10 +1317,10 @@ function mergeDefs(...defs) {
1317
1317
  function cloneDef(schema) {
1318
1318
  return mergeDefs(schema._zod.def);
1319
1319
  }
1320
- function getElementAtPath(obj, path16) {
1321
- if (!path16)
1320
+ function getElementAtPath(obj, path17) {
1321
+ if (!path17)
1322
1322
  return obj;
1323
- return path16.reduce((acc, key) => acc?.[key], obj);
1323
+ return path17.reduce((acc, key) => acc?.[key], obj);
1324
1324
  }
1325
1325
  function promiseAllObject(promisesObj) {
1326
1326
  const keys = Object.keys(promisesObj);
@@ -1729,11 +1729,11 @@ function explicitlyAborted(x, startIndex = 0) {
1729
1729
  }
1730
1730
  return false;
1731
1731
  }
1732
- function prefixIssues(path16, issues) {
1732
+ function prefixIssues(path17, issues) {
1733
1733
  return issues.map((iss) => {
1734
1734
  var _a3;
1735
1735
  (_a3 = iss).path ?? (_a3.path = []);
1736
- iss.path.unshift(path16);
1736
+ iss.path.unshift(path17);
1737
1737
  return iss;
1738
1738
  });
1739
1739
  }
@@ -1880,16 +1880,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
1880
1880
  }
1881
1881
  function formatError(error51, mapper = (issue2) => issue2.message) {
1882
1882
  const fieldErrors = { _errors: [] };
1883
- const processError = (error52, path16 = []) => {
1883
+ const processError = (error52, path17 = []) => {
1884
1884
  for (const issue2 of error52.issues) {
1885
1885
  if (issue2.code === "invalid_union" && issue2.errors.length) {
1886
- issue2.errors.map((issues) => processError({ issues }, [...path16, ...issue2.path]));
1886
+ issue2.errors.map((issues) => processError({ issues }, [...path17, ...issue2.path]));
1887
1887
  } else if (issue2.code === "invalid_key") {
1888
- processError({ issues: issue2.issues }, [...path16, ...issue2.path]);
1888
+ processError({ issues: issue2.issues }, [...path17, ...issue2.path]);
1889
1889
  } else if (issue2.code === "invalid_element") {
1890
- processError({ issues: issue2.issues }, [...path16, ...issue2.path]);
1890
+ processError({ issues: issue2.issues }, [...path17, ...issue2.path]);
1891
1891
  } else {
1892
- const fullpath = [...path16, ...issue2.path];
1892
+ const fullpath = [...path17, ...issue2.path];
1893
1893
  if (fullpath.length === 0) {
1894
1894
  fieldErrors._errors.push(mapper(issue2));
1895
1895
  } else {
@@ -1916,17 +1916,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
1916
1916
  }
1917
1917
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
1918
1918
  const result = { errors: [] };
1919
- const processError = (error52, path16 = []) => {
1919
+ const processError = (error52, path17 = []) => {
1920
1920
  var _a3, _b;
1921
1921
  for (const issue2 of error52.issues) {
1922
1922
  if (issue2.code === "invalid_union" && issue2.errors.length) {
1923
- issue2.errors.map((issues) => processError({ issues }, [...path16, ...issue2.path]));
1923
+ issue2.errors.map((issues) => processError({ issues }, [...path17, ...issue2.path]));
1924
1924
  } else if (issue2.code === "invalid_key") {
1925
- processError({ issues: issue2.issues }, [...path16, ...issue2.path]);
1925
+ processError({ issues: issue2.issues }, [...path17, ...issue2.path]);
1926
1926
  } else if (issue2.code === "invalid_element") {
1927
- processError({ issues: issue2.issues }, [...path16, ...issue2.path]);
1927
+ processError({ issues: issue2.issues }, [...path17, ...issue2.path]);
1928
1928
  } else {
1929
- const fullpath = [...path16, ...issue2.path];
1929
+ const fullpath = [...path17, ...issue2.path];
1930
1930
  if (fullpath.length === 0) {
1931
1931
  result.errors.push(mapper(issue2));
1932
1932
  continue;
@@ -1958,8 +1958,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
1958
1958
  }
1959
1959
  function toDotPath(_path) {
1960
1960
  const segs = [];
1961
- const path16 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1962
- for (const seg of path16) {
1961
+ const path17 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1962
+ for (const seg of path17) {
1963
1963
  if (typeof seg === "number")
1964
1964
  segs.push(`[${seg}]`);
1965
1965
  else if (typeof seg === "symbol")
@@ -8189,8 +8189,8 @@ function ko_default() {
8189
8189
  }
8190
8190
 
8191
8191
  // ../../../node_modules/zod/v4/locales/lt.js
8192
- var capitalizeFirstCharacter = (text2) => {
8193
- return text2.charAt(0).toUpperCase() + text2.slice(1);
8192
+ var capitalizeFirstCharacter = (text3) => {
8193
+ return text3.charAt(0).toUpperCase() + text3.slice(1);
8194
8194
  };
8195
8195
  function getUnitTypeFromNumber(number4) {
8196
8196
  const abs = Math.abs(number4);
@@ -14651,13 +14651,13 @@ function resolveRef(ref, ctx) {
14651
14651
  if (!ref.startsWith("#")) {
14652
14652
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
14653
14653
  }
14654
- const path16 = ref.slice(1).split("/").filter(Boolean);
14655
- if (path16.length === 0) {
14654
+ const path17 = ref.slice(1).split("/").filter(Boolean);
14655
+ if (path17.length === 0) {
14656
14656
  return ctx.rootSchema;
14657
14657
  }
14658
14658
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
14659
- if (path16[0] === defsKey) {
14660
- const key = path16[1];
14659
+ if (path17[0] === defsKey) {
14660
+ const key = path17[1];
14661
14661
  if (!key || !ctx.defs[key]) {
14662
14662
  throw new Error(`Reference not found: ${ref}`);
14663
14663
  }
@@ -15146,7 +15146,7 @@ var harnessDisplaySetSchema = external_exports.strictObject({
15146
15146
 
15147
15147
  // ../../shared-contracts/dist/harness-presentation.js
15148
15148
  var localeSchema = external_exports.string().max(64).regex(/^[a-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$/u);
15149
- var displayText = (maximum) => external_exports.string().min(1).max(maximum).refine((text2) => text2.trim().length > 0);
15149
+ var displayText = (maximum) => external_exports.string().min(1).max(maximum).refine((text3) => text3.trim().length > 0);
15150
15150
  var harnessLocalizationsSchema = external_exports.record(localeSchema, external_exports.object({
15151
15151
  label: displayText(256).optional(),
15152
15152
  description: displayText(1024).optional()
@@ -15474,7 +15474,7 @@ var threadManualCompactionStartedSchema = external_exports.strictObject({
15474
15474
  var nonNegativeSafeIntegerSchema = external_exports.number().int().safe().nonnegative();
15475
15475
  var finiteNonNegativeNumberSchema = external_exports.number().finite().nonnegative();
15476
15476
  var cacheHitRatePercentSchema = external_exports.number().finite().min(0).max(100);
15477
- var indicatorTextSchema = (maximum) => harnessLocalizedTextSchema.refine((entries) => Object.values(entries).every((text2) => text2.length <= maximum));
15477
+ var indicatorTextSchema = (maximum) => harnessLocalizedTextSchema.refine((entries) => Object.values(entries).every((text3) => text3.length <= maximum));
15478
15478
  var composerIndicatorsSchema = external_exports.array(external_exports.object({
15479
15479
  kind: external_exports.literal("countdown"),
15480
15480
  id: external_exports.string().min(1).max(64),
@@ -16111,7 +16111,10 @@ var harnessPluginRouteSchema = external_exports.object({
16111
16111
  harnessId: harnessPluginIdSchema,
16112
16112
  model: harnessModelRefSchema.optional(),
16113
16113
  thinkingOptionId: harnessThinkingOptionIdSchema.optional(),
16114
- permissionModeId: harnessPermissionModeIdSchema.optional()
16114
+ permissionModeId: harnessPermissionModeIdSchema.optional(),
16115
+ /** A draft prewarm create: stays unsubmitted until the user's first Turn.
16116
+ * Desktop forwards only the Model of a main-process prewarm to thread/start. */
16117
+ prewarm: external_exports.literal(true).optional()
16115
16118
  }).strict();
16116
16119
 
16117
16120
  // ../../shared-contracts/dist/harness-launch-settings.js
@@ -16716,8 +16719,8 @@ async function readCandidate(file2, signal) {
16716
16719
  const message3 = isRecord(entry.message) ? entry.message : null;
16717
16720
  if (!firstMessage && entry.type === "message" && message3?.role === "user") {
16718
16721
  const content = message3.content;
16719
- const text2 = typeof content === "string" ? content : Array.isArray(content) ? content.filter((block) => isRecord(block) && block.type === "text" && typeof block.text === "string").map((block) => block.text).join(" ") : "";
16720
- firstMessage = sessionImportTitle(text2);
16722
+ const text3 = typeof content === "string" ? content : Array.isArray(content) ? content.filter((block) => isRecord(block) && block.type === "text" && typeof block.text === "string").map((block) => block.text).join(" ") : "";
16723
+ firstMessage = sessionImportTitle(text3);
16721
16724
  }
16722
16725
  hasUser = entry.type === "message" && message3?.role === "user" || typeof entry.parentId === "string" && entries.get(entry.parentId) === true;
16723
16726
  entries.set(entry.id, hasUser);
@@ -17230,8 +17233,8 @@ function liveHarnessCommandPrompt(catalog, idPrefix, commandId, argumentText) {
17230
17233
  const descriptor = catalog.commands.find(({ id }) => id === commandId);
17231
17234
  if (!descriptor)
17232
17235
  return null;
17233
- const text2 = typeof argumentText === "string" ? argumentText.trim() : "";
17234
- return text2 ? `${descriptor.invocation} ${text2}` : descriptor.invocation;
17236
+ const text3 = typeof argumentText === "string" ? argumentText.trim() : "";
17237
+ return text3 ? `${descriptor.invocation} ${text3}` : descriptor.invocation;
17235
17238
  }
17236
17239
  function mergeLiveHarnessCommands(builtIns, idPrefix, live, exclusions = {}) {
17237
17240
  if (!live)
@@ -17367,16 +17370,16 @@ var Diff = class {
17367
17370
  }
17368
17371
  }
17369
17372
  }
17370
- addToPath(path16, added, removed, oldPosInc, options) {
17371
- const last = path16.lastComponent;
17373
+ addToPath(path17, added, removed, oldPosInc, options) {
17374
+ const last = path17.lastComponent;
17372
17375
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
17373
17376
  return {
17374
- oldPos: path16.oldPos + oldPosInc,
17377
+ oldPos: path17.oldPos + oldPosInc,
17375
17378
  lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
17376
17379
  };
17377
17380
  } else {
17378
17381
  return {
17379
- oldPos: path16.oldPos + oldPosInc,
17382
+ oldPos: path17.oldPos + oldPosInc,
17380
17383
  lastComponent: { count: 1, added, removed, previousComponent: last }
17381
17384
  };
17382
17385
  }
@@ -17776,9 +17779,9 @@ function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader
17776
17779
  } }));
17777
17780
  }
17778
17781
  }
17779
- function splitLines(text2) {
17780
- const hasTrailingNl = text2.endsWith("\n");
17781
- const result = text2.split("\n").map((line) => line + "\n");
17782
+ function splitLines(text3) {
17783
+ const hasTrailingNl = text3.endsWith("\n");
17784
+ const result = text3.split("\n").map((line) => line + "\n");
17782
17785
  if (hasTrailingNl) {
17783
17786
  result.pop();
17784
17787
  } else {
@@ -18012,11 +18015,344 @@ function piNestedCallFileChanges(nestedCalls, cwd) {
18012
18015
  return projected;
18013
18016
  }
18014
18017
 
18015
- // dist/pi-subagents.js
18018
+ // dist/pi-message-item-id.js
18016
18019
  import { createHash } from "node:crypto";
18020
+ function piMessageIdentity(sessionId, message3, timestampCounts) {
18021
+ if (typeof message3 !== "object" || message3 === null || !("role" in message3) || message3.role !== "assistant")
18022
+ return void 0;
18023
+ if ("timestamp" in message3 && typeof message3.timestamp === "number" && Number.isSafeInteger(message3.timestamp) && message3.timestamp >= 0) {
18024
+ const occurrence = timestampCounts.get(message3.timestamp) ?? 0;
18025
+ timestampCounts.set(message3.timestamp, occurrence + 1);
18026
+ return { sessionId, timestamp: message3.timestamp, occurrence };
18027
+ }
18028
+ if ("responseId" in message3 && typeof message3.responseId === "string" && message3.responseId.trim().length > 0)
18029
+ return { responseId: message3.responseId };
18030
+ return void 0;
18031
+ }
18032
+ function piHistoryMessageIdentities(sessionId, entries) {
18033
+ const timestampCounts = /* @__PURE__ */ new Map();
18034
+ const identities = /* @__PURE__ */ new Map();
18035
+ for (const entry of entries) {
18036
+ const identity = piMessageIdentity(sessionId, entry.message, timestampCounts);
18037
+ if (identity)
18038
+ identities.set(entry.id, identity);
18039
+ }
18040
+ return { identities, timestampCounts };
18041
+ }
18042
+ function piMessageItemId(identity, kind) {
18043
+ if (!identity)
18044
+ return null;
18045
+ const timestampIdentity = "timestamp" in identity;
18046
+ const value = timestampIdentity ? JSON.stringify([identity.sessionId, identity.timestamp, identity.occurrence]) : identity.responseId;
18047
+ const digest = createHash("sha256").update(value).digest("hex");
18048
+ return hostItemIdSchema.parse(`pi-${timestampIdentity ? "message" : "response"}-v1-${digest}-${kind}`);
18049
+ }
18050
+
18051
+ // dist/pi-assistant-outcome.js
18052
+ function piAssistantWasAborted(value) {
18053
+ if (typeof value !== "object" || value === null || Array.isArray(value))
18054
+ return false;
18055
+ const message3 = value;
18056
+ return message3.role === "assistant" && (message3.stopReason === "aborted" || message3.stopReason === "error" && message3.errorMessage === "This operation was aborted");
18057
+ }
18058
+ function piAssistantPhase(value) {
18059
+ if (typeof value !== "object" || value === null || Array.isArray(value))
18060
+ return void 0;
18061
+ const message3 = value;
18062
+ if (message3.role !== "assistant")
18063
+ return void 0;
18064
+ const lastText = Array.isArray(message3.content) ? message3.content.findLast((part) => typeof part === "object" && part !== null && !Array.isArray(part) && "type" in part && part.type === "text" && "text" in part && typeof part.text === "string" && part.text.trim().length > 0) : void 0;
18065
+ if (!lastText && !(typeof message3.content === "string" && message3.content.trim()))
18066
+ return void 0;
18067
+ if (typeof lastText?.textSignature === "string") {
18068
+ try {
18069
+ const signature = JSON.parse(lastText.textSignature);
18070
+ if (typeof signature === "object" && signature !== null && !Array.isArray(signature) && "v" in signature && signature.v === 1 && "id" in signature && typeof signature.id === "string" && "phase" in signature && (signature.phase === "commentary" || signature.phase === "final_answer"))
18071
+ return signature.phase;
18072
+ } catch {
18073
+ }
18074
+ }
18075
+ if (message3.stopReason === "toolUse")
18076
+ return "commentary";
18077
+ if (message3.stopReason === "stop")
18078
+ return "final_answer";
18079
+ return void 0;
18080
+ }
18081
+
18082
+ // dist/pi-subagents.js
18083
+ import { createHash as createHash3 } from "node:crypto";
18084
+
18085
+ // dist/pi-gotgenes-extension.js
18086
+ import { createHash as createHash2, randomUUID } from "node:crypto";
18087
+ import { mkdir, readFile, rename, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
18088
+ import { homedir as homedir2 } from "node:os";
18089
+ import path7 from "node:path";
18090
+ var GOTGENES_WIDGET = "codexhost-gotgenes-subagents";
18091
+ var GOTGENES_PREFIX = "CODEXHOST_GOTGENES_SUBAGENTS_V1:";
18092
+ var GOTGENES_EXTENSION = `export default function(pi) {
18093
+ let ctx, timer, service, previous = "";
18094
+ const publish = () => {
18095
+ if (!ctx) return;
18096
+ // Child SDK sessions can publish their own process-global service. Bind this parent once.
18097
+ if (!service) {
18098
+ const candidate = globalThis[Symbol.for("@gotgenes/pi-subagents:service")];
18099
+ if (typeof candidate?.listAgents !== "function") return;
18100
+ service = candidate;
18101
+ }
18102
+ const agents = service.listAgents().slice(0, 128).map((r) => ({
18103
+ id: r.id, type: r.type, description: r.description?.slice(0, 2048),
18104
+ status: r.status, isBackground: r.isBackground, outputFile: r.outputFile,
18105
+ toolUses: r.toolUses, startedAt: r.startedAt, completedAt: r.completedAt,
18106
+ result: r.result?.slice(0, 2048), error: r.error?.slice(0, 2048),
18107
+ turnBudget: r.turnBudget, lifetimeUsage: r.lifetimeUsage,
18108
+ }));
18109
+ const payload = JSON.stringify({version: 1, agents});
18110
+ if (payload === previous) return;
18111
+ previous = payload;
18112
+ ctx.ui.setWidget("${GOTGENES_WIDGET}", ["${GOTGENES_PREFIX}" + payload]);
18113
+ };
18114
+ const schedule = () => queueMicrotask(publish);
18115
+ for (const name of ["created", "started", "completed", "failed", "resuming", "resumed", "compacted", "steered", "update"]) {
18116
+ pi.events.on("subagents:" + name, schedule);
18117
+ }
18118
+ pi.on("session_start", (_event, context) => {
18119
+ // A session switch keeps this extension's manager/service; only reload creates a new instance.
18120
+ ctx = context; previous = ""; clearInterval(timer);
18121
+ schedule();
18122
+ // The public service publishes outputFile only after queued session creation and has no progress event.
18123
+ timer = setInterval(publish, 1000);
18124
+ timer.unref?.();
18125
+ });
18126
+ pi.on("session_shutdown", () => { clearInterval(timer); timer = undefined; ctx = undefined; service = undefined; });
18127
+ }
18128
+ `;
18129
+ async function ensureGotgenesExtension(environment) {
18130
+ const digest = createHash2("sha256").update(GOTGENES_EXTENSION).digest("hex").slice(0, 16);
18131
+ const root = environment.CODEXHOST_DATA_DIR ?? path7.join(environment.HOME ?? environment.USERPROFILE ?? homedir2(), ".codexhost");
18132
+ const directory = path7.resolve(root, "extensions", "pi-subagent-observer");
18133
+ const file2 = path7.join(directory, `${digest}.mjs`);
18134
+ if (await readFile(file2, "utf8").catch(() => "") === GOTGENES_EXTENSION)
18135
+ return file2;
18136
+ await mkdir(directory, { recursive: true });
18137
+ const temporary = `${file2}.${randomUUID()}.tmp`;
18138
+ try {
18139
+ await writeFile2(temporary, GOTGENES_EXTENSION, { mode: 384 });
18140
+ try {
18141
+ await rename(temporary, file2);
18142
+ } catch (error51) {
18143
+ if (await readFile(file2, "utf8").catch(() => "") !== GOTGENES_EXTENSION)
18144
+ throw error51;
18145
+ }
18146
+ } finally {
18147
+ await rm2(temporary, { force: true });
18148
+ }
18149
+ return file2;
18150
+ }
18151
+
18152
+ // dist/pi-gotgenes-subagents.js
18153
+ var PREFIX = "pi-gotgenes-v1:";
18154
+ var STATUSES = {
18155
+ queued: "pending",
18156
+ running: "running",
18157
+ background: "pending",
18158
+ completed: "completed",
18159
+ aborted: "interrupted",
18160
+ stopped: "interrupted",
18161
+ error: "failed"
18162
+ };
18163
+ function isRecord4(value) {
18164
+ return typeof value === "object" && value !== null && !Array.isArray(value);
18165
+ }
18166
+ function text(value, limit = 2048) {
18167
+ return typeof value === "string" && value.length > 0 && value.length <= limit;
18168
+ }
18169
+ function gotgenesId(id) {
18170
+ return PREFIX + Buffer.from(id).toString("base64url");
18171
+ }
18172
+ function parseGotgenesId(value) {
18173
+ if (!value.startsWith(PREFIX))
18174
+ return null;
18175
+ const id = Buffer.from(value.slice(PREFIX.length), "base64url").toString("utf8");
18176
+ if (!text(id, 256) || /[\s/\\]/u.test(id) || gotgenesId(id) !== value)
18177
+ throw new Error("Invalid gotgenes subagent identity");
18178
+ return id;
18179
+ }
18180
+ function gotgenesRecord(value) {
18181
+ if (!isRecord4(value) || !text(value.id, 256) || /[\s/\\]/u.test(value.id) || !text(value.type) || !text(value.description) || typeof value.status !== "string" || !Object.hasOwn(STATUSES, value.status))
18182
+ return null;
18183
+ const status = STATUSES[value.status];
18184
+ if (!status)
18185
+ return null;
18186
+ const id = gotgenesId(value.id);
18187
+ const progress = typeof value.toolUses === "number" ? `${value.toolUses} tool uses` : void 0;
18188
+ const result = typeof value.error === "string" ? value.error : typeof value.result === "string" ? value.result : progress;
18189
+ return {
18190
+ id: value.id,
18191
+ roleKnown: value.roleKnown !== false,
18192
+ backgroundKnown: typeof value.isBackground === "boolean",
18193
+ child: {
18194
+ subagentId: id,
18195
+ nativeSubagentId: id,
18196
+ description: value.description,
18197
+ role: value.type,
18198
+ status,
18199
+ background: value.isBackground === true,
18200
+ ...text(value.modelName) ? { model: value.modelName } : {},
18201
+ ...result ? { resultSummary: result.slice(0, 2048) } : {}
18202
+ },
18203
+ ...text(value.outputFile, 8192) ? { outputFile: value.outputFile } : {},
18204
+ revision: JSON.stringify([
18205
+ value.toolUses,
18206
+ value.turnBudget,
18207
+ value.lifetimeUsage,
18208
+ value.outputFile
18209
+ ])
18210
+ };
18211
+ }
18212
+ function gotgenesToolRecord(toolName, result) {
18213
+ if (!["subagent", "get_subagent_result"].includes(toolName) || !isRecord4(result) || !isRecord4(result.details))
18214
+ return null;
18215
+ const d = result.details;
18216
+ if (!text(d.agentId, 256) || !text(d.displayName) || !text(d.description))
18217
+ return null;
18218
+ return gotgenesRecord({
18219
+ ...d,
18220
+ id: d.agentId,
18221
+ type: d.subagentType ?? d.displayName,
18222
+ roleKnown: text(d.subagentType),
18223
+ isBackground: toolName === "subagent" ? d.status === "background" || Array.isArray(d.tags) && d.tags.includes("background") : void 0,
18224
+ outputFile: d.transcriptPath,
18225
+ result: d.preview
18226
+ });
18227
+ }
18228
+ function parseGotgenesWidget(value) {
18229
+ if (!isRecord4(value) || value.type !== "extension_ui_request" || value.method !== "setWidget" || value.widgetKey !== GOTGENES_WIDGET || !Array.isArray(value.widgetLines))
18230
+ return null;
18231
+ const line = value.widgetLines.find((x) => typeof x === "string" && x.startsWith(GOTGENES_PREFIX));
18232
+ if (!line || Buffer.byteLength(line) > 1024 * 1024)
18233
+ return null;
18234
+ try {
18235
+ const payload = JSON.parse(line.slice(GOTGENES_PREFIX.length));
18236
+ if (!isRecord4(payload) || payload.version !== 1 || !Array.isArray(payload.agents) || payload.agents.length > 128)
18237
+ return null;
18238
+ const records = payload.agents.map(gotgenesRecord);
18239
+ return records.every((r) => r !== null) ? records : null;
18240
+ } catch {
18241
+ return null;
18242
+ }
18243
+ }
18244
+ function mergeGotgenesRecord(previous, record9) {
18245
+ const model2 = record9.child.model ?? previous?.child.model;
18246
+ const role = record9.roleKnown ? record9.child.role : previous?.child.role ?? record9.child.role;
18247
+ return {
18248
+ ...previous,
18249
+ ...record9,
18250
+ roleKnown: record9.roleKnown || previous?.roleKnown === true,
18251
+ backgroundKnown: record9.backgroundKnown || previous?.backgroundKnown === true,
18252
+ outputFile: record9.outputFile ?? previous?.outputFile,
18253
+ child: {
18254
+ ...previous?.child,
18255
+ ...record9.child,
18256
+ ...model2 ? { model: model2 } : {},
18257
+ ...role ? { role } : {},
18258
+ background: record9.backgroundKnown ? record9.child.background : previous?.child.background ?? record9.child.background
18259
+ }
18260
+ };
18261
+ }
18262
+ var GotgenesSubagents = class {
18263
+ emit;
18264
+ records = /* @__PURE__ */ new Map();
18265
+ #nativeObserved = /* @__PURE__ */ new Set();
18266
+ #active = /* @__PURE__ */ new Map();
18267
+ constructor(emit) {
18268
+ this.emit = emit;
18269
+ }
18270
+ observe(records, publish = true, activeTurn, nativeObservation = false) {
18271
+ for (const record9 of records) {
18272
+ if (!publish && this.#nativeObserved.has(record9.id))
18273
+ continue;
18274
+ if (nativeObservation)
18275
+ this.#nativeObserved.add(record9.id);
18276
+ const previous = this.records.get(record9.id);
18277
+ const merged = mergeGotgenesRecord(previous, record9);
18278
+ this.records.set(record9.id, merged);
18279
+ if (publish && !previous && activeTurn && !this.#active.has(record9.id)) {
18280
+ const item = {
18281
+ type: "subagentDelegation",
18282
+ itemId: activeTurn.nextItemId(),
18283
+ operation: "spawn",
18284
+ subagents: [merged.child]
18285
+ };
18286
+ this.#active.set(record9.id, { turnId: activeTurn.turnId, item });
18287
+ this.emit({ type: "item.started", turnId: activeTurn.turnId, item });
18288
+ }
18289
+ if (!publish || JSON.stringify(previous) === JSON.stringify(merged))
18290
+ continue;
18291
+ const active = this.#active.get(record9.id);
18292
+ if (active) {
18293
+ active.item = { ...active.item, subagents: [merged.child] };
18294
+ this.emit({
18295
+ type: "item.updated",
18296
+ turnId: active.turnId,
18297
+ itemId: active.item.itemId,
18298
+ update: { type: "subagents.replace", subagents: [merged.child] }
18299
+ });
18300
+ }
18301
+ this.emit({
18302
+ type: "subagent.state.changed",
18303
+ nativeSubagentId: merged.child.subagentId,
18304
+ status: merged.child.status
18305
+ });
18306
+ this.emit({ type: "subagent.transcript.changed", nativeSubagentId: merged.child.subagentId });
18307
+ }
18308
+ }
18309
+ project(toolName, result, itemId2) {
18310
+ const parsed = gotgenesToolRecord(toolName, result);
18311
+ if (!parsed || toolName !== "subagent")
18312
+ return null;
18313
+ const child = this.records.get(parsed.id)?.child ?? parsed.child;
18314
+ return { type: "subagentDelegation", itemId: itemId2, operation: "spawn", subagents: [child] };
18315
+ }
18316
+ start(turnId, toolName, result, itemId2) {
18317
+ const parsed = gotgenesToolRecord(toolName, result);
18318
+ if (!parsed)
18319
+ return false;
18320
+ const prior = this.records.get(parsed.id);
18321
+ if (!prior || !this.#nativeObserved.has(parsed.id))
18322
+ this.observe([parsed]);
18323
+ else {
18324
+ this.observe([
18325
+ {
18326
+ ...prior,
18327
+ child: { ...prior.child, ...parsed.child.model ? { model: parsed.child.model } : {} }
18328
+ }
18329
+ ]);
18330
+ }
18331
+ if (toolName === "subagent" && !this.#active.has(parsed.id)) {
18332
+ const item = this.project(toolName, result, itemId2);
18333
+ if (!item)
18334
+ return false;
18335
+ this.#active.set(parsed.id, { turnId, item });
18336
+ this.emit({ type: "item.started", turnId, item });
18337
+ }
18338
+ return true;
18339
+ }
18340
+ finish(turnId) {
18341
+ for (const [id, active] of this.#active) {
18342
+ if (active.turnId !== turnId)
18343
+ continue;
18344
+ this.#active.delete(id);
18345
+ this.emit({
18346
+ type: "item.completed",
18347
+ turnId,
18348
+ snapshot: { item: active.item, outcome: { status: "succeeded" } }
18349
+ });
18350
+ }
18351
+ }
18352
+ };
18017
18353
 
18018
18354
  // dist/pi-subagent-workflow.js
18019
- var PREFIX = "pi-subagents-workflow-v1:";
18355
+ var PREFIX2 = "pi-subagents-workflow-v1:";
18020
18356
  var STATES = {
18021
18357
  pending: "pending",
18022
18358
  running: "running",
@@ -18030,7 +18366,7 @@ var STATES = {
18030
18366
  function record2(value) {
18031
18367
  return typeof value === "object" && value !== null && !Array.isArray(value);
18032
18368
  }
18033
- function text(value, limit = 256) {
18369
+ function text2(value, limit = 256) {
18034
18370
  return typeof value === "string" && value.length > 0 && value.length <= limit;
18035
18371
  }
18036
18372
  function piWorkflowSummary(result) {
@@ -18038,15 +18374,15 @@ function piWorkflowSummary(result) {
18038
18374
  return null;
18039
18375
  const details = result.details;
18040
18376
  const summary = details.workflowChildren;
18041
- if (!record2(summary) || summary.version !== 1 || !text(summary.workflowRunId) || summary.workflowRunId !== details.runId || !text(summary.parentToolCallId) || typeof summary.inventoryComplete !== "boolean" || !Array.isArray(summary.children) || summary.children.length > 256)
18377
+ if (!record2(summary) || summary.version !== 1 || !text2(summary.workflowRunId) || summary.workflowRunId !== details.runId || !text2(summary.parentToolCallId) || typeof summary.inventoryComplete !== "boolean" || !Array.isArray(summary.children) || summary.children.length > 256)
18042
18378
  return null;
18043
18379
  const children = [];
18044
18380
  const seen = /* @__PURE__ */ new Set();
18045
18381
  for (const child of summary.children) {
18046
- if (!record2(child) || !text(child.childId) || seen.has(child.childId) || typeof child.state !== "string" || !Object.hasOwn(STATES, child.state))
18382
+ if (!record2(child) || !text2(child.childId) || seen.has(child.childId) || typeof child.state !== "string" || !Object.hasOwn(STATES, child.state))
18047
18383
  return null;
18048
18384
  for (const key of ["agent", "sessionName", "model", "thinking"]) {
18049
- if (child[key] !== void 0 && !text(child[key], 2048))
18385
+ if (child[key] !== void 0 && !text2(child[key], 2048))
18050
18386
  return null;
18051
18387
  }
18052
18388
  const mappedState = STATES[child.state];
@@ -18070,15 +18406,15 @@ function piWorkflowSummary(result) {
18070
18406
  };
18071
18407
  }
18072
18408
  function piWorkflowSubagentId(address) {
18073
- return PREFIX + Buffer.from(JSON.stringify([address.workflowRunId, address.childId])).toString("base64url");
18409
+ return PREFIX2 + Buffer.from(JSON.stringify([address.workflowRunId, address.childId])).toString("base64url");
18074
18410
  }
18075
18411
  function parsePiWorkflowSubagentId(id) {
18076
- if (!id.startsWith(PREFIX))
18412
+ if (!id.startsWith(PREFIX2))
18077
18413
  return null;
18078
18414
  if (id.length > 3e3)
18079
18415
  throw new Error("Invalid Pi workflow child identity");
18080
- const value = JSON.parse(Buffer.from(id.slice(PREFIX.length), "base64url").toString("utf8"));
18081
- if (!Array.isArray(value) || value.length !== 2 || !text(value[0]) || !text(value[1]))
18416
+ const value = JSON.parse(Buffer.from(id.slice(PREFIX2.length), "base64url").toString("utf8"));
18417
+ if (!Array.isArray(value) || value.length !== 2 || !text2(value[0]) || !text2(value[1]))
18082
18418
  throw new Error("Invalid Pi workflow child identity");
18083
18419
  const address = { workflowRunId: value[0], childId: value[1] };
18084
18420
  if (piWorkflowSubagentId(address) !== id)
@@ -18236,8 +18572,13 @@ var PiSubagents = class {
18236
18572
  #children = /* @__PURE__ */ new Map();
18237
18573
  #active = /* @__PURE__ */ new Map();
18238
18574
  #waiting = /* @__PURE__ */ new Map();
18575
+ gotgenes;
18239
18576
  constructor(emit) {
18240
18577
  this.emit = emit;
18578
+ this.gotgenes = new GotgenesSubagents(emit);
18579
+ }
18580
+ observeGotgenes(records, activeTurn) {
18581
+ this.gotgenes.observe(records, true, activeTurn, true);
18241
18582
  }
18242
18583
  observe(runs) {
18243
18584
  this.#apply(runs, true);
@@ -18291,6 +18632,9 @@ var PiSubagents = class {
18291
18632
  }
18292
18633
  }
18293
18634
  project(toolName, result, itemId2, callId) {
18635
+ const gotgenes = this.gotgenes.project(toolName, result, itemId2);
18636
+ if (gotgenes)
18637
+ return gotgenes;
18294
18638
  const workflow = toolName === "subagent" ? piWorkflowSummary(result) : null;
18295
18639
  if (workflow && (!callId || workflow.parentToolCallId === callId))
18296
18640
  return projectPiWorkflow(workflow, itemId2);
@@ -18301,6 +18645,8 @@ var PiSubagents = class {
18301
18645
  return children.length ? { type: "subagentDelegation", itemId: itemId2, operation: "spawn", subagents: children } : null;
18302
18646
  }
18303
18647
  start(turnId, toolName, result, itemId2, callId) {
18648
+ if (this.gotgenes.start(turnId, toolName, result, itemId2))
18649
+ return;
18304
18650
  const workflow = toolName === "subagent" ? piWorkflowSummary(result) : null;
18305
18651
  if (workflow && (!callId || workflow.parentToolCallId === callId)) {
18306
18652
  const key = `workflow:${workflow.workflowRunId}`;
@@ -18346,6 +18692,7 @@ var PiSubagents = class {
18346
18692
  this.emit({ type: "item.started", turnId, item });
18347
18693
  }
18348
18694
  finish(turnId) {
18695
+ this.gotgenes.finish(turnId);
18349
18696
  for (const [runId, waiting] of this.#waiting) {
18350
18697
  if (waiting.turnId === turnId)
18351
18698
  this.#waiting.delete(runId);
@@ -18393,15 +18740,15 @@ ${entry.text}`);
18393
18740
  nativeTurnRef: nativeTurnRefSchema.parse({
18394
18741
  harnessId: "pi",
18395
18742
  nativeSessionId: parentSessionId,
18396
- nativeTurnKey: `pi-subagent-${createHash("sha256").update(id).digest("hex")}`,
18743
+ nativeTurnKey: `pi-subagent-${createHash3("sha256").update(id).digest("hex")}`,
18397
18744
  formatVersion: 1
18398
18745
  }),
18399
18746
  input: reply.task ? [{ type: "text", text: reply.task }] : [],
18400
- items: texts.map((text2, index) => ({
18747
+ items: texts.map((text3, index) => ({
18401
18748
  item: {
18402
18749
  type: "agentMessage",
18403
- text: text2,
18404
- itemId: hostItemIdSchema.parse(`pi-subagent-${createHash("sha256").update(`${id}:${index}:${text2}`).digest("hex")}`)
18750
+ text: text3,
18751
+ itemId: hostItemIdSchema.parse(`pi-subagent-${createHash3("sha256").update(`${id}:${index}:${text3}`).digest("hex")}`)
18405
18752
  },
18406
18753
  outcome: { status: "succeeded" }
18407
18754
  })),
@@ -18549,22 +18896,149 @@ function normalizePiModelCatalog(nativeModels, effectiveModel, thinkingLevels, e
18549
18896
  });
18550
18897
  }
18551
18898
 
18899
+ // dist/pi-progress.js
18900
+ import { createHash as createHash4 } from "node:crypto";
18901
+ function record4(value) {
18902
+ return typeof value === "object" && value !== null && !Array.isArray(value);
18903
+ }
18904
+ function textContent(content) {
18905
+ if (typeof content === "string")
18906
+ return content;
18907
+ if (!Array.isArray(content))
18908
+ return "";
18909
+ return content.filter((part) => record4(part) && part.type === "text" && typeof part.text === "string").map((part) => part.text).join("");
18910
+ }
18911
+ function boundedPiProgress(text3) {
18912
+ const limit = 64e3;
18913
+ return text3.length <= limit ? text3 : `${text3.slice(0, limit)}
18914
+ [Pi notification truncated]`;
18915
+ }
18916
+ function visibleText(text3) {
18917
+ return text3.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
18918
+ }
18919
+ function noticeDisplay(value, fallback) {
18920
+ if (!record4(value) || !record4(value.details) || typeof value.details.summary !== "string")
18921
+ return visibleText(fallback);
18922
+ const details = value.details;
18923
+ const parts = [visibleText(details.summary)];
18924
+ if (typeof details.exitCode === "number")
18925
+ parts.push(`Exit code: ${details.exitCode}`);
18926
+ for (const key of ["signal", "error", "errorMessage"])
18927
+ if (typeof details[key] === "string" && details[key])
18928
+ parts.push(`${key}: ${visibleText(details[key])}`);
18929
+ if (record4(details.logMatch) && typeof details.logMatch.line === "string")
18930
+ parts.push(`Log: ${visibleText(details.logMatch.line)}`);
18931
+ if (typeof details.command === "string" && details.command)
18932
+ parts.push(`Command: ${visibleText(details.command)}`);
18933
+ return parts.join("\n\n");
18934
+ }
18935
+ function piCustomNoticeKey(value) {
18936
+ if (!record4(value) || value.type !== "custom_message" && value.role !== "custom" || value.display !== true || typeof value.customType !== "string")
18937
+ return null;
18938
+ const text3 = textContent(value.content);
18939
+ if (text3.trim().length === 0)
18940
+ return null;
18941
+ return JSON.stringify([value.customType, text3]);
18942
+ }
18943
+ function piCustomNotice(value, sessionId, occurrences) {
18944
+ const key = piCustomNoticeKey(value);
18945
+ if (!key)
18946
+ return null;
18947
+ const occurrence = occurrences.get(key) ?? 0;
18948
+ occurrences.set(key, occurrence + 1);
18949
+ const digest = createHash4("sha256").update(JSON.stringify([sessionId, key, occurrence])).digest("hex");
18950
+ const [customType, text3] = JSON.parse(key);
18951
+ return {
18952
+ type: "progress.message",
18953
+ itemId: hostItemIdSchema.parse(`pi-notice-v1-${digest}`),
18954
+ text: boundedPiProgress(`Pi notification (${visibleText(customType)})
18955
+
18956
+ ${noticeDisplay(value, text3)}`)
18957
+ };
18958
+ }
18959
+ function piHistoryNotices(sessionId, entries) {
18960
+ const occurrences = /* @__PURE__ */ new Map();
18961
+ const notices = /* @__PURE__ */ new Map();
18962
+ for (const entry of entries) {
18963
+ const notice = piCustomNotice(entry.message ?? entry, sessionId, occurrences);
18964
+ if (notice)
18965
+ notices.set(entry.id, notice);
18966
+ }
18967
+ return { notices, occurrences };
18968
+ }
18969
+ function piStatusText(value) {
18970
+ if (value.type === "auto_retry_start") {
18971
+ const attempt = typeof value.attempt === "number" ? ` ${value.attempt}` : "";
18972
+ const maximum = typeof value.maxAttempts === "number" ? `/${value.maxAttempts}` : "";
18973
+ const delay2 = typeof value.delayMs === "number" && value.delayMs >= 0 ? ` Waiting ${value.delayMs / 1e3} s before retrying.` : "";
18974
+ const reason = typeof value.errorMessage === "string" ? `
18975
+
18976
+ ${visibleText(value.errorMessage)}` : "";
18977
+ return boundedPiProgress(`Pi retry${attempt}${maximum}.${delay2}${reason}`);
18978
+ }
18979
+ if (value.type === "auto_retry_end") {
18980
+ if (typeof value.success !== "boolean")
18981
+ return null;
18982
+ const reason = typeof value.finalError === "string" ? `
18983
+
18984
+ ${visibleText(value.finalError)}` : "";
18985
+ return boundedPiProgress(`Pi retry ${value.success ? "succeeded" : "ended without success"}.${reason}`);
18986
+ }
18987
+ if (value.type !== "extension_ui_request")
18988
+ return null;
18989
+ if (value.method === "notify" && typeof value.message === "string" && value.message.trim()) {
18990
+ const level = typeof value.notifyType === "string" ? ` (${value.notifyType})` : "";
18991
+ return boundedPiProgress(`Pi notification${level}
18992
+
18993
+ ${visibleText(value.message)}`);
18994
+ }
18995
+ if (value.method === "setStatus" && typeof value.statusKey === "string") {
18996
+ return typeof value.statusText === "string" && value.statusText.trim() ? boundedPiProgress(`Pi status (${visibleText(value.statusKey)})
18997
+
18998
+ ${visibleText(value.statusText)}`) : `Pi status (${visibleText(value.statusKey)}) cleared.`;
18999
+ }
19000
+ return null;
19001
+ }
19002
+
19003
+ // dist/pi-tool-command.js
19004
+ function record5(value) {
19005
+ return typeof value === "object" && value !== null && !Array.isArray(value);
19006
+ }
19007
+ function stringField(value, key) {
19008
+ if (!record5(value))
19009
+ return void 0;
19010
+ for (const source of [value, value.input, value.arguments]) {
19011
+ if (record5(source) && typeof source[key] === "string" && source[key].length > 0)
19012
+ return source[key];
19013
+ }
19014
+ return void 0;
19015
+ }
19016
+ function piToolCommand(name, arguments_) {
19017
+ if (!["bash", "exec", "terminal", "run"].includes(name.toLowerCase()))
19018
+ return null;
19019
+ const command = ["command", "cmd", "script", "commandLine", "command_line"].map((key) => stringField(arguments_, key)).find((value) => value !== void 0);
19020
+ if (!command)
19021
+ return null;
19022
+ const cwd = stringField(arguments_, "cwd");
19023
+ return { command, ...cwd ? { cwd } : {} };
19024
+ }
19025
+
18552
19026
  // dist/pi-history.js
18553
19027
  var piHarnessId = harnessIdSchema.parse("pi");
18554
- function isRecord4(value) {
19028
+ function isRecord5(value) {
18555
19029
  return typeof value === "object" && value !== null && !Array.isArray(value);
18556
19030
  }
18557
- function textContent(value) {
19031
+ function textContent2(value) {
18558
19032
  if (typeof value === "string")
18559
19033
  return value;
18560
19034
  if (!Array.isArray(value))
18561
19035
  return "";
18562
- return value.filter((part) => isRecord4(part) && part.type === "text" && typeof part.text === "string").map((part) => part.text).join("");
19036
+ return value.filter((part) => isRecord5(part) && part.type === "text" && typeof part.text === "string").map((part) => part.text).join("");
18563
19037
  }
18564
19038
  function thinkingContent(value) {
18565
19039
  if (!Array.isArray(value))
18566
19040
  return "";
18567
- return value.filter((part) => isRecord4(part) && part.type === "thinking" && typeof part.thinking === "string").map((part) => part.thinking).join("");
19041
+ return value.filter((part) => isRecord5(part) && part.type === "thinking" && typeof part.thinking === "string").map((part) => part.thinking).join("");
18568
19042
  }
18569
19043
  function validatedEntry(value) {
18570
19044
  if (typeof value.id !== "string" || value.id.length === 0 || value.parentId !== null && typeof value.parentId !== "string" || typeof value.type !== "string") {
@@ -18595,7 +19069,7 @@ function activePiEntries(history) {
18595
19069
  return reversed.reverse();
18596
19070
  }
18597
19071
  function message(entry) {
18598
- return entry.type === "message" && isRecord4(entry.message) ? entry.message : null;
19072
+ return entry.type === "message" && isRecord5(entry.message) ? entry.message : null;
18599
19073
  }
18600
19074
  function messageRole(entry) {
18601
19075
  const value = message(entry)?.role;
@@ -18610,7 +19084,7 @@ function assistantOutcome(entries) {
18610
19084
  if (!final)
18611
19085
  return { status: "unknown", reason: "Pi history has no Assistant terminal" };
18612
19086
  const stopReason = final.stopReason;
18613
- if (stopReason === "aborted") {
19087
+ if (piAssistantWasAborted(final)) {
18614
19088
  return { status: "cancelled", reason: "Pi Assistant was aborted" };
18615
19089
  }
18616
19090
  if (stopReason === "error") {
@@ -18623,7 +19097,7 @@ function assistantOutcome(entries) {
18623
19097
  }
18624
19098
  };
18625
19099
  }
18626
- if (typeof stopReason === "string" || textContent(final.content).length > 0) {
19100
+ if (typeof stopReason === "string" || textContent2(final.content).length > 0) {
18627
19101
  return { status: "succeeded" };
18628
19102
  }
18629
19103
  return { status: "unknown", reason: "Pi Assistant terminal is not classifiable" };
@@ -18640,8 +19114,8 @@ function itemOutcome(outcome) {
18640
19114
  return { status: "succeeded" };
18641
19115
  }
18642
19116
  function toolOutput(value) {
18643
- const text2 = textContent(value);
18644
- return text2.length > 0 ? { content: [{ type: "text", text: text2 }] } : void 0;
19117
+ const text3 = textContent2(value);
19118
+ return text3.length > 0 ? { content: [{ type: "text", text: text3 }] } : void 0;
18645
19119
  }
18646
19120
  function historicalFileChanges(call, nativeMessage, toolItemId, cwd) {
18647
19121
  const items = [];
@@ -18664,37 +19138,52 @@ function historicalFileChanges(call, nativeMessage, toolItemId, cwd) {
18664
19138
  }
18665
19139
  return items;
18666
19140
  }
18667
- function snapshotItems(entries, outcome, subagents, cwd) {
19141
+ function snapshotItems(entries, messageIdentities, notices, outcome, subagents, cwd) {
18668
19142
  const snapshots = [];
18669
19143
  const toolCalls = /* @__PURE__ */ new Map();
18670
19144
  for (const entry of entries) {
19145
+ const notice = notices.get(entry.id);
19146
+ if (notice) {
19147
+ snapshots.push({
19148
+ item: {
19149
+ type: "agentMessage",
19150
+ itemId: notice.itemId,
19151
+ text: notice.text,
19152
+ phase: "commentary"
19153
+ },
19154
+ outcome: { status: "succeeded" }
19155
+ });
19156
+ continue;
19157
+ }
18671
19158
  const nativeMessage = message(entry);
18672
19159
  if (!nativeMessage)
18673
19160
  continue;
18674
19161
  const content = Array.isArray(nativeMessage.content) ? nativeMessage.content : [];
18675
19162
  if (nativeMessage.role === "assistant") {
18676
- const text2 = textContent(content);
19163
+ const text3 = textContent2(content);
18677
19164
  const reasoning = thinkingContent(content);
18678
19165
  let projectedText = false;
18679
19166
  let projectedReasoning = false;
18680
19167
  for (const [ordinal, part] of content.entries()) {
18681
- if (!isRecord4(part))
19168
+ if (!isRecord5(part))
18682
19169
  continue;
18683
19170
  if (part.type === "thinking" && !projectedReasoning && reasoning.length > 0) {
18684
19171
  const item2 = {
18685
19172
  type: "reasoning",
18686
- itemId: itemId(entry.id, "reasoning", 0),
19173
+ itemId: piMessageItemId(messageIdentities.get(entry.id), "reasoning") ?? itemId(entry.id, "reasoning", 0),
18687
19174
  text: reasoning
18688
19175
  };
18689
19176
  snapshots.push({ item: item2, outcome: itemOutcome(outcome) });
18690
19177
  projectedReasoning = true;
18691
19178
  continue;
18692
19179
  }
18693
- if (part.type === "text" && !projectedText && text2.length > 0) {
19180
+ if (part.type === "text" && !projectedText && text3.length > 0) {
19181
+ const phase = piAssistantPhase(nativeMessage);
18694
19182
  const item2 = {
18695
19183
  type: "agentMessage",
18696
- itemId: itemId(entry.id, "assistant", 0),
18697
- text: text2
19184
+ itemId: piMessageItemId(messageIdentities.get(entry.id), "assistant") ?? itemId(entry.id, "assistant", 0),
19185
+ text: text3,
19186
+ ...phase ? { phase } : {}
18698
19187
  };
18699
19188
  snapshots.push({ item: item2, outcome: itemOutcome(outcome) });
18700
19189
  projectedText = true;
@@ -18722,9 +19211,24 @@ function snapshotItems(entries, outcome, subagents, cwd) {
18722
19211
  if (!call || call.name !== nativeMessage.toolName)
18723
19212
  continue;
18724
19213
  const output = toolOutput(nativeMessage.content);
18725
- const item = {
18726
- type: "toolExecution",
19214
+ const shell = piToolCommand(call.name, call.arguments);
19215
+ const commandCwd = shell?.cwd ?? cwd;
19216
+ const durationMs = typeof nativeMessage.durationMs === "number" && Number.isFinite(nativeMessage.durationMs) && nativeMessage.durationMs >= 0 ? nativeMessage.durationMs : void 0;
19217
+ const base = {
18727
19218
  itemId: itemId(call.entryId, "tool", call.ordinal),
19219
+ ...durationMs !== void 0 ? { durationMs } : {}
19220
+ };
19221
+ const exitCode = typeof nativeMessage.exitCode === "number" && Number.isInteger(nativeMessage.exitCode) ? nativeMessage.exitCode : void 0;
19222
+ const item = shell ? {
19223
+ ...base,
19224
+ type: "commandExecution",
19225
+ command: shell.command,
19226
+ ...commandCwd ? { cwd: commandCwd } : {},
19227
+ ...output ? { output: textContent2(nativeMessage.content) } : {},
19228
+ ...exitCode !== void 0 ? { exitCode } : {}
19229
+ } : {
19230
+ ...base,
19231
+ type: "toolExecution",
18728
19232
  toolName: call.name,
18729
19233
  arguments: call.arguments,
18730
19234
  ...output ? { output } : {}
@@ -18755,6 +19259,10 @@ function snapshotItems(entries, outcome, subagents, cwd) {
18755
19259
  function modelChange(entry) {
18756
19260
  return entry.type === "model_change" && typeof entry.provider === "string" && typeof entry.modelId === "string" ? { provider: entry.provider, id: entry.modelId } : null;
18757
19261
  }
19262
+ function isEmptyWakeup(entry) {
19263
+ const content = message(entry)?.content;
19264
+ return content === "" || Array.isArray(content) && content.every((part) => isRecord5(part) && part.type === "text" && part.text === "");
19265
+ }
18758
19266
  function turnStarts(active) {
18759
19267
  const starts = [];
18760
19268
  let terminal = true;
@@ -18762,6 +19270,8 @@ function turnStarts(active) {
18762
19270
  for (const [index, entry] of active.entries()) {
18763
19271
  const role = messageRole(entry);
18764
19272
  if (role === "user") {
19273
+ if (pending && isEmptyWakeup(entry))
19274
+ continue;
18765
19275
  starts.push({ entry, index });
18766
19276
  pending = null;
18767
19277
  terminal = false;
@@ -18778,6 +19288,8 @@ function turnStarts(active) {
18778
19288
  }
18779
19289
  function mapPiSnapshot(history, state2, subagents = new PiSubagents(() => void 0)) {
18780
19290
  const active = activePiEntries(history);
19291
+ const { identities } = piHistoryMessageIdentities(state2.sessionId, active);
19292
+ const { notices } = piHistoryNotices(state2.sessionId, active);
18781
19293
  const turns = [];
18782
19294
  const starts = turnStarts(active);
18783
19295
  const byIndex = new Map(starts.map((start, ordinal) => [start.index, ordinal]));
@@ -18799,7 +19311,7 @@ function mapPiSnapshot(history, state2, subagents = new PiSubagents(() => void 0
18799
19311
  const end = next?.index ?? active.length;
18800
19312
  const entries = active.slice(index, end);
18801
19313
  const outcome = assistantOutcome(entries);
18802
- const userText = textContent(message(user)?.content);
19314
+ const userText = textContent2(message(user)?.content);
18803
19315
  const nativeTurnRef = nativeTurnRefSchema.parse({
18804
19316
  harnessId: piHarnessId,
18805
19317
  nativeSessionId: state2.sessionId,
@@ -18816,7 +19328,7 @@ function mapPiSnapshot(history, state2, subagents = new PiSubagents(() => void 0
18816
19328
  nativeTurnRef,
18817
19329
  ...!next || messageRole(next.entry) === "user" ? { checkpoint } : {},
18818
19330
  input: messageRole(user) === "user" ? [{ type: "text", text: userText }] : [],
18819
- items: snapshotItems(entries, outcome, subagents, state2.cwd),
19331
+ items: snapshotItems(entries, identities, notices, outcome, subagents, state2.cwd),
18820
19332
  outcome,
18821
19333
  ...effectiveModel ? { model: encodePiModelRef(effectiveModel) } : {}
18822
19334
  });
@@ -18851,14 +19363,14 @@ function resolvePiForkBoundary(history, checkpointId) {
18851
19363
  }
18852
19364
 
18853
19365
  // dist/pi-usage.js
18854
- function isRecord5(value) {
19366
+ function isRecord6(value) {
18855
19367
  return typeof value === "object" && value !== null && !Array.isArray(value);
18856
19368
  }
18857
19369
  function nonNegativeSafeInteger(value) {
18858
19370
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : null;
18859
19371
  }
18860
19372
  function optionalPiCacheHitRatePercent(value) {
18861
- if (!isRecord5(value) || value.role !== "assistant" || !isRecord5(value.usage))
19373
+ if (!isRecord6(value) || value.role !== "assistant" || !isRecord6(value.usage))
18862
19374
  return null;
18863
19375
  const input = nonNegativeSafeInteger(value.usage.input);
18864
19376
  const cacheRead = nonNegativeSafeInteger(value.usage.cacheRead);
@@ -18871,20 +19383,20 @@ function optionalPiCacheHitRatePercent(value) {
18871
19383
  function latestPiCacheHitRatePercent(history) {
18872
19384
  let latest = null;
18873
19385
  for (const entry of activePiEntries(history)) {
18874
- if (entry.type === "message" && isRecord5(entry.message) && entry.message.role === "assistant") {
19386
+ if (entry.type === "message" && isRecord6(entry.message) && entry.message.role === "assistant") {
18875
19387
  latest = optionalPiCacheHitRatePercent(entry.message);
18876
19388
  }
18877
19389
  }
18878
19390
  return latest;
18879
19391
  }
18880
19392
  function responseData(response, operation) {
18881
- if (!isRecord5(response.data)) {
19393
+ if (!isRecord6(response.data)) {
18882
19394
  throw new Error(`Pi RPC ${operation} response has no data`);
18883
19395
  }
18884
19396
  return response.data;
18885
19397
  }
18886
19398
  function contextUsage(value) {
18887
- if (!isRecord5(value))
19399
+ if (!isRecord6(value))
18888
19400
  throw new Error("Pi RPC context Usage is invalid");
18889
19401
  return parseHostUsage({
18890
19402
  contextUsedTokens: value.tokens,
@@ -18894,15 +19406,15 @@ function contextUsage(value) {
18894
19406
  function parsePiSessionUsage(response) {
18895
19407
  const data = responseData(response, "Session stats");
18896
19408
  const tokens = data.tokens;
18897
- if (tokens !== void 0 && !isRecord5(tokens)) {
19409
+ if (tokens !== void 0 && !isRecord6(tokens)) {
18898
19410
  throw new Error("Pi RPC Session stats tokens are invalid");
18899
19411
  }
18900
19412
  return parseHostUsage({
18901
- ...isRecord5(tokens) && tokens.input !== void 0 ? { inputTokens: tokens.input } : {},
18902
- ...isRecord5(tokens) && tokens.cacheRead !== void 0 ? { cachedInputTokens: tokens.cacheRead } : {},
18903
- ...isRecord5(tokens) && tokens.cacheWrite !== void 0 ? { cacheWriteInputTokens: tokens.cacheWrite } : {},
18904
- ...isRecord5(tokens) && tokens.output !== void 0 ? { outputTokens: tokens.output } : {},
18905
- ...isRecord5(tokens) && tokens.total !== void 0 ? { totalTokens: tokens.total } : {},
19413
+ ...isRecord6(tokens) && tokens.input !== void 0 ? { inputTokens: tokens.input } : {},
19414
+ ...isRecord6(tokens) && tokens.cacheRead !== void 0 ? { cachedInputTokens: tokens.cacheRead } : {},
19415
+ ...isRecord6(tokens) && tokens.cacheWrite !== void 0 ? { cacheWriteInputTokens: tokens.cacheWrite } : {},
19416
+ ...isRecord6(tokens) && tokens.output !== void 0 ? { outputTokens: tokens.output } : {},
19417
+ ...isRecord6(tokens) && tokens.total !== void 0 ? { totalTokens: tokens.total } : {},
18906
19418
  ...data.cost !== void 0 ? { totalCostUsd: data.cost } : {},
18907
19419
  ...data.contextUsage !== void 0 ? contextUsage(data.contextUsage) : {}
18908
19420
  });
@@ -18921,9 +19433,9 @@ function optionalPiStateContextUsage(value) {
18921
19433
  }
18922
19434
  }
18923
19435
  function piUsageRecord(message3, extra = {}) {
18924
- if (!isRecord5(message3) || message3.role !== "assistant")
19436
+ if (!isRecord6(message3) || message3.role !== "assistant")
18925
19437
  return null;
18926
- const usage = isRecord5(message3.usage) ? message3.usage : null;
19438
+ const usage = isRecord6(message3.usage) ? message3.usage : null;
18927
19439
  const input = nonNegativeSafeInteger(usage?.input);
18928
19440
  const output = nonNegativeSafeInteger(usage?.output);
18929
19441
  const requestId = typeof message3.responseId === "string" && message3.responseId.length > 0 ? message3.responseId : typeof message3.timestamp === "number" && Number.isSafeInteger(message3.timestamp) ? `t${message3.timestamp}` : null;
@@ -18960,17 +19472,17 @@ function piUsageHistory(history) {
18960
19472
  for (const entry of history.entries) {
18961
19473
  if (entry.type !== "message")
18962
19474
  continue;
18963
- const record7 = piUsageRecord(entry.message, { historical: true });
18964
- if (record7?.kind === "request")
18965
- requests.push(record7.request);
18966
- else if (record7?.kind === "missing")
19475
+ const record9 = piUsageRecord(entry.message, { historical: true });
19476
+ if (record9?.kind === "request")
19477
+ requests.push(record9.request);
19478
+ else if (record9?.kind === "missing")
18967
19479
  complete = false;
18968
19480
  }
18969
19481
  return { requests, complete };
18970
19482
  }
18971
19483
 
18972
19484
  // dist/pi-usage-statistics.js
18973
- function isRecord6(value) {
19485
+ function isRecord7(value) {
18974
19486
  return typeof value === "object" && value !== null && !Array.isArray(value);
18975
19487
  }
18976
19488
  function piUserText(content) {
@@ -18978,11 +19490,11 @@ function piUserText(content) {
18978
19490
  return content;
18979
19491
  if (!Array.isArray(content))
18980
19492
  return void 0;
18981
- return content.filter((block) => isRecord6(block) && block.type === "text" && typeof block.text === "string").map((block) => String(block.text)).join(" ");
19493
+ return content.filter((block) => isRecord7(block) && block.type === "text" && typeof block.text === "string").map((block) => String(block.text)).join(" ");
18982
19494
  }
18983
19495
  async function readPiUsage(file2, signal) {
18984
19496
  const entries = [];
18985
- const header = await jsonlHeader(file2, (record7) => record7.type === "session", signal);
19497
+ const header = await jsonlHeader(file2, (record9) => record9.type === "session", signal);
18986
19498
  let name;
18987
19499
  const session = {
18988
19500
  sessionId: typeof header?.id === "string" ? header.id : void 0,
@@ -18999,11 +19511,11 @@ async function readPiUsage(file2, signal) {
18999
19511
  if (!name && message3?.role === "user") {
19000
19512
  name = usageSessionTitle(piUserText(message3.content));
19001
19513
  }
19002
- const record7 = piUsageRecord(line.message);
19003
- if (record7?.kind !== "request")
19514
+ const record9 = piUsageRecord(line.message);
19515
+ if (record9?.kind !== "request")
19004
19516
  continue;
19005
19517
  const at = nativeTimeMs(message3.timestamp) ?? nativeTimeMs(line.timestamp);
19006
- const entry = at !== null && usageEntryFromRequest(record7.request, at);
19518
+ const entry = at !== null && usageEntryFromRequest(record9.request, at);
19007
19519
  if (!entry)
19008
19520
  continue;
19009
19521
  if (!(typeof message3.responseId === "string" && message3.responseId.length > 0)) {
@@ -19024,9 +19536,9 @@ function createPiUsageStatistics(environment) {
19024
19536
  }
19025
19537
 
19026
19538
  // dist/account-balance.js
19027
- import { readFile } from "node:fs/promises";
19028
- import { homedir as homedir2 } from "node:os";
19029
- import path7 from "node:path";
19539
+ import { readFile as readFile2 } from "node:fs/promises";
19540
+ import { homedir as homedir3 } from "node:os";
19541
+ import path8 from "node:path";
19030
19542
  var DEEPSEEK_BALANCE_ENDPOINT = "https://api.deepseek.com/user/balance";
19031
19543
  var SUB2API_USAGE_PATH = "/v1/usage";
19032
19544
  var REQUEST_TIMEOUT_MS = 1e4;
@@ -19035,18 +19547,18 @@ function agentDirectory(environment) {
19035
19547
  const configured = environment.PI_CODING_AGENT_DIR?.trim();
19036
19548
  if (configured)
19037
19549
  return configured;
19038
- return path7.join(environment.HOME ?? environment.USERPROFILE ?? homedir2(), ".pi", "agent");
19550
+ return path8.join(environment.HOME ?? environment.USERPROFILE ?? homedir3(), ".pi", "agent");
19039
19551
  }
19040
- var record4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
19552
+ var record6 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
19041
19553
  async function deepSeekApiKey(environment) {
19042
- const auth = record4(JSON.parse(await readFile(path7.join(agentDirectory(environment), "auth.json"), "utf8")));
19043
- const deepseek = record4(auth.deepseek);
19554
+ const auth = record6(JSON.parse(await readFile2(path8.join(agentDirectory(environment), "auth.json"), "utf8")));
19555
+ const deepseek = record6(auth.deepseek);
19044
19556
  if (deepseek.type !== "api_key")
19045
19557
  return void 0;
19046
19558
  return typeof deepseek.key === "string" && deepseek.key.trim() ? deepseek.key : void 0;
19047
19559
  }
19048
19560
  function projectSub2ApiUsage(payload, providerId) {
19049
- const data = record4(payload);
19561
+ const data = record6(payload);
19050
19562
  if (data.isValid === false)
19051
19563
  return null;
19052
19564
  if (data.mode !== "unrestricted" && data.mode !== "quota_limited")
@@ -19056,7 +19568,7 @@ function projectSub2ApiUsage(payload, providerId) {
19056
19568
  return null;
19057
19569
  const wallet = finiteAmount(data.balance);
19058
19570
  const remaining = finiteAmount(data.remaining);
19059
- const quotaRemaining = finiteAmount(record4(data.quota).remaining);
19571
+ const quotaRemaining = finiteAmount(record6(data.quota).remaining);
19060
19572
  const amount = wallet ?? remaining ?? quotaRemaining;
19061
19573
  if (amount === null)
19062
19574
  return null;
@@ -19076,10 +19588,10 @@ function finiteAmount(value) {
19076
19588
  return Number.isFinite(amount) && amount >= 0 ? amount : null;
19077
19589
  }
19078
19590
  function projectDeepSeekBalance(payload) {
19079
- const data = record4(payload);
19591
+ const data = record6(payload);
19080
19592
  if (!Array.isArray(data.balance_infos))
19081
19593
  return null;
19082
- const first = record4(data.balance_infos[0]);
19594
+ const first = record6(data.balance_infos[0]);
19083
19595
  const amount = finiteAmount(first.total_balance);
19084
19596
  const currency = typeof first.currency === "string" ? first.currency.trim() : "";
19085
19597
  if (amount === null || !currency)
@@ -19108,11 +19620,11 @@ function usageEndpoint(baseUrl) {
19108
19620
  }
19109
19621
  async function configuredSub2ApiProviders(environment) {
19110
19622
  try {
19111
- const models = record4(JSON.parse(await readFile(path7.join(agentDirectory(environment), "models.json"), "utf8")));
19112
- const providers = record4(models.providers);
19623
+ const models = record6(JSON.parse(await readFile2(path8.join(agentDirectory(environment), "models.json"), "utf8")));
19624
+ const providers = record6(models.providers);
19113
19625
  const found = [];
19114
19626
  for (const [id, definition] of Object.entries(providers)) {
19115
- const provider = record4(definition);
19627
+ const provider = record6(definition);
19116
19628
  const apiKey = typeof provider.apiKey === "string" ? provider.apiKey.trim() : "";
19117
19629
  const baseUrl = typeof provider.baseUrl === "string" ? provider.baseUrl.trim() : "";
19118
19630
  if (!id.trim() || id.length > 128 || !apiKey || !usageEndpoint(baseUrl))
@@ -19170,21 +19682,21 @@ async function fetchPiAccountBalance(input) {
19170
19682
  }
19171
19683
 
19172
19684
  // dist/pi-credential-imports.js
19173
- import { randomUUID } from "node:crypto";
19685
+ import { randomUUID as randomUUID2 } from "node:crypto";
19174
19686
  import { execFile as execFile2 } from "node:child_process";
19175
19687
  import { promisify } from "node:util";
19176
19688
  import { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync, readdirSync, lstatSync, renameSync, rmdirSync } from "node:fs";
19177
19689
  import { realpath as realpath2 } from "node:fs/promises";
19178
19690
  import os4 from "node:os";
19179
- import path9 from "node:path";
19691
+ import path10 from "node:path";
19180
19692
  import { pathToFileURL } from "node:url";
19181
19693
 
19182
19694
  // dist/command.js
19183
19695
  import fs2 from "node:fs";
19184
- import { homedir as homedir3, tmpdir as tmpdir2 } from "node:os";
19185
- import path8 from "node:path";
19696
+ import { homedir as homedir4, tmpdir as tmpdir2 } from "node:os";
19697
+ import path9 from "node:path";
19186
19698
  var PI_PACKAGE_NAME = "@earendil-works/pi-coding-agent";
19187
- var PI_PACKAGE_PATH = path8.join("node_modules", "@earendil-works", "pi-coding-agent");
19699
+ var PI_PACKAGE_PATH = path9.join("node_modules", "@earendil-works", "pi-coding-agent");
19188
19700
  var piDiscoverySpec = {
19189
19701
  id: "pi",
19190
19702
  command: "pi",
@@ -19210,18 +19722,18 @@ function resolvePiExecutable(input, dependencies = {}) {
19210
19722
  return resolution?.executable ?? input.command ?? input.environment.PI_COMMAND ?? "pi";
19211
19723
  }
19212
19724
  function findPiPackageDirectory(executable) {
19213
- let directory = path8.dirname(executable);
19725
+ let directory = path9.dirname(executable);
19214
19726
  while (true) {
19215
- for (const candidate of [directory, path8.join(directory, PI_PACKAGE_PATH)]) {
19727
+ for (const candidate of [directory, path9.join(directory, PI_PACKAGE_PATH)]) {
19216
19728
  try {
19217
- const manifest = JSON.parse(fs2.readFileSync(path8.join(candidate, "package.json"), "utf8"));
19729
+ const manifest = JSON.parse(fs2.readFileSync(path9.join(candidate, "package.json"), "utf8"));
19218
19730
  if (typeof manifest === "object" && manifest !== null && "name" in manifest && manifest.name === PI_PACKAGE_NAME) {
19219
19731
  return candidate;
19220
19732
  }
19221
19733
  } catch {
19222
19734
  }
19223
19735
  }
19224
- const parent = path8.dirname(directory);
19736
+ const parent = path9.dirname(directory);
19225
19737
  if (parent === directory)
19226
19738
  return void 0;
19227
19739
  directory = parent;
@@ -19229,16 +19741,16 @@ function findPiPackageDirectory(executable) {
19229
19741
  }
19230
19742
  function findPiCliEntry(packageDirectory) {
19231
19743
  try {
19232
- const manifest = JSON.parse(fs2.readFileSync(path8.join(packageDirectory, "package.json"), "utf8"));
19744
+ const manifest = JSON.parse(fs2.readFileSync(path9.join(packageDirectory, "package.json"), "utf8"));
19233
19745
  if (typeof manifest !== "object" || manifest === null || !("bin" in manifest))
19234
19746
  return void 0;
19235
19747
  const bin = manifest.bin;
19236
19748
  const entry = typeof bin === "string" ? bin : typeof bin === "object" && bin !== null && "pi" in bin ? bin.pi : void 0;
19237
19749
  if (typeof entry !== "string" || !entry.trim())
19238
19750
  return void 0;
19239
- const resolved = path8.resolve(packageDirectory, entry);
19240
- const relative = path8.relative(packageDirectory, resolved);
19241
- if (relative === ".." || relative.startsWith(`..${path8.sep}`) || path8.isAbsolute(relative) || !fs2.statSync(resolved).isFile()) {
19751
+ const resolved = path9.resolve(packageDirectory, entry);
19752
+ const relative = path9.relative(packageDirectory, resolved);
19753
+ if (relative === ".." || relative.startsWith(`..${path9.sep}`) || path9.isAbsolute(relative) || !fs2.statSync(resolved).isFile()) {
19242
19754
  return void 0;
19243
19755
  }
19244
19756
  return resolved;
@@ -19247,11 +19759,11 @@ function findPiCliEntry(packageDirectory) {
19247
19759
  }
19248
19760
  }
19249
19761
  function isFilesystemRoot(cwd) {
19250
- const resolved = path8.resolve(cwd);
19251
- return resolved === path8.parse(resolved).root;
19762
+ const resolved = path9.resolve(cwd);
19763
+ return resolved === path9.parse(resolved).root;
19252
19764
  }
19253
19765
  function writableDirectory(candidate) {
19254
- if (!candidate || !path8.isAbsolute(candidate) || isFilesystemRoot(candidate))
19766
+ if (!candidate || !path9.isAbsolute(candidate) || isFilesystemRoot(candidate))
19255
19767
  return void 0;
19256
19768
  try {
19257
19769
  if (!fs2.statSync(candidate).isDirectory())
@@ -19264,19 +19776,19 @@ function writableDirectory(candidate) {
19264
19776
  }
19265
19777
  function resolvePiInspectCwd(inputCwd, environment = process.env) {
19266
19778
  if (typeof inputCwd === "string" && inputCwd.length > 0 && !isFilesystemRoot(inputCwd)) {
19267
- return path8.resolve(inputCwd);
19779
+ return path9.resolve(inputCwd);
19268
19780
  }
19269
- const candidates = [environment.USERPROFILE, environment.HOME, homedir3(), tmpdir2()];
19781
+ const candidates = [environment.USERPROFILE, environment.HOME, homedir4(), tmpdir2()];
19270
19782
  for (const candidate of candidates) {
19271
19783
  const usable = writableDirectory(candidate);
19272
19784
  if (usable)
19273
19785
  return usable;
19274
19786
  }
19275
- return inputCwd && inputCwd.length > 0 ? path8.resolve(inputCwd) : process.cwd();
19787
+ return inputCwd && inputCwd.length > 0 ? path9.resolve(inputCwd) : process.cwd();
19276
19788
  }
19277
19789
 
19278
19790
  // dist/pi-credential-imports.js
19279
- var PREFIX2 = "codexhost-account-";
19791
+ var PREFIX3 = "codexhost-account-";
19280
19792
  function object2(value) {
19281
19793
  return typeof value === "object" && value !== null && !Array.isArray(value);
19282
19794
  }
@@ -19317,7 +19829,7 @@ function describeOauth(credential) {
19317
19829
  };
19318
19830
  }
19319
19831
  function writeAuth(filename, content) {
19320
- const temporary = `${filename}.${randomUUID()}.tmp`;
19832
+ const temporary = `${filename}.${randomUUID2()}.tmp`;
19321
19833
  try {
19322
19834
  writeFileSync(temporary, content, { flag: "wx", mode: 384 });
19323
19835
  renameSync(temporary, filename);
@@ -19326,8 +19838,8 @@ function writeAuth(filename, content) {
19326
19838
  }
19327
19839
  }
19328
19840
  function removeOwnedFiles(dir) {
19329
- rmSync(path9.join(dir, "index.ts"), { force: true });
19330
- rmSync(path9.join(dir, "import.json"), { force: true });
19841
+ rmSync(path10.join(dir, "index.ts"), { force: true });
19842
+ rmSync(path10.join(dir, "import.json"), { force: true });
19331
19843
  try {
19332
19844
  rmdirSync(dir);
19333
19845
  } catch {
@@ -19339,13 +19851,13 @@ async function installation(command, environment, authPath) {
19339
19851
  const cliEntry = directory ? findPiCliEntry(directory) : void 0;
19340
19852
  if (!directory || !cliEntry)
19341
19853
  throw new Error("Pi credential import requires a supported npm Pi installation");
19342
- const storage = await import(pathToFileURL(path9.join(directory, "dist/core/auth-storage.js")).href);
19343
- const ai = path9.join(directory, "node_modules/@earendil-works/pi-ai/dist");
19344
- const all = await import(pathToFileURL(path9.join(ai, "providers/all.js")).href);
19854
+ const storage = await import(pathToFileURL(path10.join(directory, "dist/core/auth-storage.js")).href);
19855
+ const ai = path10.join(directory, "node_modules/@earendil-works/pi-ai/dist");
19856
+ const all = await import(pathToFileURL(path10.join(ai, "providers/all.js")).href);
19345
19857
  const providers = all.getBuiltinProviders();
19346
19858
  const providerModules = {
19347
- "openai-codex": pathToFileURL(path9.join(ai, "providers/openai-codex.js")).href,
19348
- xai: pathToFileURL(path9.join(ai, "providers/xai.js")).href
19859
+ "openai-codex": pathToFileURL(path10.join(ai, "providers/openai-codex.js")).href,
19860
+ xai: pathToFileURL(path10.join(ai, "providers/xai.js")).href
19349
19861
  };
19350
19862
  for (const [id, url2] of Object.entries(providerModules)) {
19351
19863
  const module = await import(url2);
@@ -19359,8 +19871,8 @@ async function installation(command, environment, authPath) {
19359
19871
  reservedNames: providers.map((p) => typeof p === "string" ? p : p.id),
19360
19872
  async configuredProviderNames() {
19361
19873
  const { stdout } = await promisify(execFile2)(process.execPath, [cliEntry, "--offline", "--no-approve", "--list-models"], {
19362
- cwd: existsSync(path9.dirname(authPath)) ? path9.dirname(authPath) : os4.homedir(),
19363
- env: { ...environment, PI_CODING_AGENT_DIR: path9.dirname(authPath), PI_OFFLINE: "1" },
19874
+ cwd: existsSync(path10.dirname(authPath)) ? path10.dirname(authPath) : os4.homedir(),
19875
+ env: { ...environment, PI_CODING_AGENT_DIR: path10.dirname(authPath), PI_OFFLINE: "1" },
19364
19876
  timeout: 15e3,
19365
19877
  maxBuffer: 4 * 1024 * 1024
19366
19878
  });
@@ -19390,26 +19902,26 @@ export default async function (pi) {
19390
19902
  }
19391
19903
  function createPiCredentialImports(options = {}) {
19392
19904
  const env = { ...process.env, ...options.environment };
19393
- const agentDir = env.PI_CODING_AGENT_DIR ?? path9.join(env.HOME ?? os4.homedir(), ".pi/agent");
19394
- const authPath = path9.join(agentDir, "auth.json");
19395
- const extensionsDir = path9.join(agentDir, "extensions");
19905
+ const agentDir = env.PI_CODING_AGENT_DIR ?? path10.join(env.HOME ?? os4.homedir(), ".pi/agent");
19906
+ const authPath = path10.join(agentDir, "auth.json");
19907
+ const extensionsDir = path10.join(agentDir, "extensions");
19396
19908
  const saveAuth = (auth) => (options.writeAuth ?? writeAuth)(authPath, JSON.stringify(auth, null, 2) + "\n");
19397
19909
  const resolve = () => options.resolveInstallation?.(authPath) ?? installation(options.command, env, authPath);
19398
- const location = (name) => path9.join(extensionsDir, `${PREFIX2}${credentialImportNameSchema.parse(name)}`);
19910
+ const location = (name) => path10.join(extensionsDir, `${PREFIX3}${credentialImportNameSchema.parse(name)}`);
19399
19911
  const readRecord = (name) => {
19400
19912
  const dir = location(name);
19401
19913
  if (lstatSync(dir).isSymbolicLink())
19402
19914
  throw new Error("Imported configuration was changed; manage it in Pi");
19403
- const value = JSON.parse(readFileSync(path9.join(dir, "import.json"), "utf8"));
19915
+ const value = JSON.parse(readFileSync(path10.join(dir, "import.json"), "utf8"));
19404
19916
  if (value.version !== 1 || typeof value.owner !== "string" || typeof value.extension !== "string")
19405
19917
  throw new Error("Invalid import metadata");
19406
- const record7 = value.record;
19407
- if (!object2(record7))
19918
+ const record9 = value.record;
19919
+ if (!object2(record9))
19408
19920
  throw new Error("Invalid import metadata");
19409
19921
  value.record = credentialImportRecordSchema.parse({
19410
- name: record7.name,
19411
- source: record7.source,
19412
- importedAt: record7.importedAt
19922
+ name: record9.name,
19923
+ source: record9.source,
19924
+ importedAt: record9.importedAt
19413
19925
  });
19414
19926
  if (value.record.name !== name)
19415
19927
  throw new Error("Import identity mismatch");
@@ -19417,7 +19929,7 @@ function createPiCredentialImports(options = {}) {
19417
19929
  };
19418
19930
  const owned = (meta3, auth) => {
19419
19931
  const credential = auth[meta3.record.name];
19420
- const file2 = path9.join(location(meta3.record.name), "index.ts");
19932
+ const file2 = path10.join(location(meta3.record.name), "index.ts");
19421
19933
  return existsSync(file2) && !lstatSync(file2).isSymbolicLink() && readFileSync(file2, "utf8") === meta3.extension && object2(credential) && credential.type === "oauth" && credential.codexhostImportId === meta3.owner;
19422
19934
  };
19423
19935
  const readAuth = () => existsSync(authPath) ? parseAuth(readFileSync(authPath, "utf8")) : {};
@@ -19426,12 +19938,12 @@ function createPiCredentialImports(options = {}) {
19426
19938
  return [];
19427
19939
  const result = [];
19428
19940
  for (const entry of readdirSync(extensionsDir)) {
19429
- if (!entry.startsWith(PREFIX2))
19941
+ if (!entry.startsWith(PREFIX3))
19430
19942
  continue;
19431
- const name = entry.slice(PREFIX2.length);
19943
+ const name = entry.slice(PREFIX3.length);
19432
19944
  if (!credentialImportNameSchema.safeParse(name).success)
19433
19945
  continue;
19434
- if (!existsSync(path9.join(location(name), "import.json")))
19946
+ if (!existsSync(path10.join(location(name), "import.json")))
19435
19947
  continue;
19436
19948
  try {
19437
19949
  const meta3 = readRecord(name);
@@ -19452,7 +19964,7 @@ function createPiCredentialImports(options = {}) {
19452
19964
  },
19453
19965
  async listOthers() {
19454
19966
  const auth = readAuth();
19455
- const ours = new Set(ownedRecords(auth).map((record7) => record7.name));
19967
+ const ours = new Set(ownedRecords(auth).map((record9) => record9.name));
19456
19968
  const result = /* @__PURE__ */ new Map();
19457
19969
  const usable = (provider) => Boolean(provider) && provider.length <= 128 && !ours.has(provider) && !result.has(provider);
19458
19970
  for (const [provider, credential] of Object.entries(auth)) {
@@ -19465,7 +19977,7 @@ function createPiCredentialImports(options = {}) {
19465
19977
  ...describeOauth(credential)
19466
19978
  });
19467
19979
  }
19468
- const modelsPath = path9.join(agentDir, "models.json");
19980
+ const modelsPath = path10.join(agentDir, "models.json");
19469
19981
  if (existsSync(modelsPath)) {
19470
19982
  const models = JSON.parse(readFileSync(modelsPath, "utf8"));
19471
19983
  const providers = object2(models) && object2(models.providers) ? models.providers : {};
@@ -19486,8 +19998,8 @@ function createPiCredentialImports(options = {}) {
19486
19998
  throw new Error("Unsupported credential source");
19487
19999
  if (sdk.reservedNames.includes(name) || (await sdk.configuredProviderNames?.())?.includes(name))
19488
20000
  throw new Error("Provider name already exists; choose another name");
19489
- const owner = randomUUID();
19490
- const record7 = credentialImportRecordSchema.parse({
20001
+ const owner = randomUUID2();
20002
+ const record9 = credentialImportRecordSchema.parse({
19491
20003
  name,
19492
20004
  source: transfer.source,
19493
20005
  importedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -19499,15 +20011,15 @@ function createPiCredentialImports(options = {}) {
19499
20011
  try {
19500
20012
  sdk.backend.withLock((current) => {
19501
20013
  const auth = parseAuth(current);
19502
- const modelsPath = path9.join(agentDir, "models.json");
20014
+ const modelsPath = path10.join(agentDir, "models.json");
19503
20015
  const models = existsSync(modelsPath) ? JSON.parse(readFileSync(modelsPath, "utf8")) : {};
19504
- if (Object.hasOwn(auth, name) || Object.hasOwn(models.providers ?? {}, name) || existsSync(dir) || existsSync(path9.join(extensionsDir, `${name}-provider.ts`)))
20016
+ if (Object.hasOwn(auth, name) || Object.hasOwn(models.providers ?? {}, name) || existsSync(dir) || existsSync(path10.join(extensionsDir, `${name}-provider.ts`)))
19505
20017
  throw new Error("Provider name already exists; choose another name");
19506
20018
  mkdirSync(extensionsDir, { recursive: true, mode: 448 });
19507
20019
  mkdirSync(dir, { mode: 448 });
19508
20020
  created = true;
19509
- writeFileSync(path9.join(dir, "import.json"), JSON.stringify({ version: 1, owner, record: record7, extension }), { flag: "wx", mode: 384 });
19510
- writeFileSync(path9.join(dir, "index.ts"), extension, { flag: "wx", mode: 384 });
20021
+ writeFileSync(path10.join(dir, "import.json"), JSON.stringify({ version: 1, owner, record: record9, extension }), { flag: "wx", mode: 384 });
20022
+ writeFileSync(path10.join(dir, "index.ts"), extension, { flag: "wx", mode: 384 });
19511
20023
  auth[name] = { type: "oauth", ...transfer.oauth, codexhostImportId: owner };
19512
20024
  saveAuth(auth);
19513
20025
  committed = true;
@@ -19526,7 +20038,7 @@ function createPiCredentialImports(options = {}) {
19526
20038
  const auth = parseAuth(current);
19527
20039
  if (!owned(meta3, auth) || meta3.record.source.id !== transfer.source.id || meta3.record.source.provider !== transfer.source.provider)
19528
20040
  throw new Error("Import ownership or source account changed; refusing replacement");
19529
- const metadataPath = path9.join(location(name), "import.json");
20041
+ const metadataPath = path10.join(location(name), "import.json");
19530
20042
  const previous = readFileSync(metadataPath, "utf8");
19531
20043
  const updated = {
19532
20044
  ...meta3,
@@ -19561,10 +20073,10 @@ function createPiCredentialImports(options = {}) {
19561
20073
  }
19562
20074
 
19563
20075
  // dist/pi-fast-mode.js
19564
- import { createHash as createHash2, randomUUID as randomUUID2 } from "node:crypto";
19565
- import { mkdir, readFile as readFile2, rename, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
19566
- import { homedir as homedir4 } from "node:os";
19567
- import path10 from "node:path";
20076
+ import { createHash as createHash5, randomUUID as randomUUID3 } from "node:crypto";
20077
+ import { mkdir as mkdir2, readFile as readFile3, rename as rename2, rm as rm3, writeFile as writeFile3 } from "node:fs/promises";
20078
+ import { homedir as homedir5 } from "node:os";
20079
+ import path11 from "node:path";
19568
20080
  var PI_FAST_COMMAND = "codexhost-fast-mode";
19569
20081
  var PI_FAST_ACK = "codexhost-fast-mode:";
19570
20082
  var PI_FAST_EXTENSION = `export default function(pi) {
@@ -19614,24 +20126,24 @@ var PI_FAST_EXTENSION = `export default function(pi) {
19614
20126
  }
19615
20127
  `;
19616
20128
  async function ensurePiFastExtension(environment) {
19617
- const digest = createHash2("sha256").update(PI_FAST_EXTENSION).digest("hex").slice(0, 16);
19618
- const dataDirectory = environment.CODEXHOST_DATA_DIR ?? path10.join(environment.HOME ?? environment.USERPROFILE ?? homedir4(), ".codexhost");
19619
- const directory = path10.resolve(dataDirectory, "extensions", "pi-codex-fast");
19620
- const file2 = path10.join(directory, `${digest}.mjs`);
19621
- if (await readFile2(file2, "utf8").catch(() => "") === PI_FAST_EXTENSION)
20129
+ const digest = createHash5("sha256").update(PI_FAST_EXTENSION).digest("hex").slice(0, 16);
20130
+ const dataDirectory = environment.CODEXHOST_DATA_DIR ?? path11.join(environment.HOME ?? environment.USERPROFILE ?? homedir5(), ".codexhost");
20131
+ const directory = path11.resolve(dataDirectory, "extensions", "pi-codex-fast");
20132
+ const file2 = path11.join(directory, `${digest}.mjs`);
20133
+ if (await readFile3(file2, "utf8").catch(() => "") === PI_FAST_EXTENSION)
19622
20134
  return file2;
19623
- await mkdir(directory, { recursive: true });
19624
- const temporary = `${file2}.${randomUUID2()}.tmp`;
20135
+ await mkdir2(directory, { recursive: true });
20136
+ const temporary = `${file2}.${randomUUID3()}.tmp`;
19625
20137
  try {
19626
- await writeFile2(temporary, PI_FAST_EXTENSION, { mode: 384 });
20138
+ await writeFile3(temporary, PI_FAST_EXTENSION, { mode: 384 });
19627
20139
  try {
19628
- await rename(temporary, file2);
20140
+ await rename2(temporary, file2);
19629
20141
  } catch (error51) {
19630
- if (await readFile2(file2, "utf8").catch(() => "") !== PI_FAST_EXTENSION)
20142
+ if (await readFile3(file2, "utf8").catch(() => "") !== PI_FAST_EXTENSION)
19631
20143
  throw error51;
19632
20144
  }
19633
20145
  } finally {
19634
- await rm2(temporary, { force: true });
20146
+ await rm3(temporary, { force: true });
19635
20147
  }
19636
20148
  return file2;
19637
20149
  }
@@ -19648,15 +20160,15 @@ function withPiFast(catalog, supported) {
19648
20160
  // dist/pi-empty-session.js
19649
20161
  import { createReadStream as createReadStream3 } from "node:fs";
19650
20162
  import { createInterface as createInterface3 } from "node:readline";
19651
- import { randomUUID as randomUUID3 } from "node:crypto";
19652
- import { link, open as open2, rm as rm3 } from "node:fs/promises";
19653
- import path11 from "node:path";
20163
+ import { randomUUID as randomUUID4 } from "node:crypto";
20164
+ import { link, open as open2, rm as rm4 } from "node:fs/promises";
20165
+ import path12 from "node:path";
19654
20166
 
19655
20167
  // dist/pi-session-file.js
19656
20168
  import { open, realpath as realpath3 } from "node:fs/promises";
19657
20169
  var MAX_SESSION_HEADER_BYTES = 64 * 1024;
19658
20170
  var utf8Decoder = new TextDecoder("utf-8", { fatal: true });
19659
- function isRecord7(value) {
20171
+ function isRecord8(value) {
19660
20172
  return typeof value === "object" && value !== null && !Array.isArray(value);
19661
20173
  }
19662
20174
  async function readPiSessionHeader(sessionFile) {
@@ -19676,7 +20188,7 @@ async function readPiSessionHeader(sessionFile) {
19676
20188
  } catch {
19677
20189
  throw new Error("Pi Session header is not valid JSON");
19678
20190
  }
19679
- if (!isRecord7(parsed) || parsed.type !== "session" || typeof parsed.id !== "string" || parsed.id.length === 0 || typeof parsed.cwd !== "string" || parsed.cwd.length === 0) {
20191
+ if (!isRecord8(parsed) || parsed.type !== "session" || typeof parsed.id !== "string" || parsed.id.length === 0 || typeof parsed.cwd !== "string" || parsed.cwd.length === 0) {
19680
20192
  throw new Error("Pi Session header is invalid");
19681
20193
  }
19682
20194
  return {
@@ -19709,7 +20221,7 @@ async function verifyPiSessionCwd(input) {
19709
20221
  async function persistEmptyPiSession(input) {
19710
20222
  const { state: state2, history, sourceSessionFile, sourceSessionId, cwd } = input;
19711
20223
  const destination = state2.sessionFile;
19712
- if (!destination || !path11.isAbsolute(destination) || path11.resolve(destination) === path11.resolve(sourceSessionFile) || state2.sessionId === sourceSessionId || mapPiSnapshot(history, { sessionId: state2.sessionId, model: null }).turns.length !== 0)
20224
+ if (!destination || !path12.isAbsolute(destination) || path12.resolve(destination) === path12.resolve(sourceSessionFile) || state2.sessionId === sourceSessionId || mapPiSnapshot(history, { sessionId: state2.sessionId, model: null }).turns.length !== 0)
19713
20225
  throw new Error("Pi empty Session is not an independent empty native fork");
19714
20226
  await verifyPiSessionCwd({
19715
20227
  sessionFile: sourceSessionFile,
@@ -19733,7 +20245,7 @@ async function persistEmptyPiSession(input) {
19733
20245
  cwd,
19734
20246
  parentSession: sourceSessionFile
19735
20247
  };
19736
- const temporary = path11.join(path11.dirname(destination), `.codexhost-${randomUUID3()}.tmp`);
20248
+ const temporary = path12.join(path12.dirname(destination), `.codexhost-${randomUUID4()}.tmp`);
19737
20249
  try {
19738
20250
  const file2 = await open2(temporary, "wx", 384);
19739
20251
  try {
@@ -19744,7 +20256,7 @@ async function persistEmptyPiSession(input) {
19744
20256
  }
19745
20257
  await link(temporary, destination);
19746
20258
  if (process.platform !== "win32") {
19747
- const directory = await open2(path11.dirname(destination), "r");
20259
+ const directory = await open2(path12.dirname(destination), "r");
19748
20260
  try {
19749
20261
  await directory.sync();
19750
20262
  } finally {
@@ -19752,7 +20264,7 @@ async function persistEmptyPiSession(input) {
19752
20264
  }
19753
20265
  }
19754
20266
  } finally {
19755
- await rm3(temporary, { force: true });
20267
+ await rm4(temporary, { force: true });
19756
20268
  }
19757
20269
  }
19758
20270
  async function readPiEmptySessionConfiguration(sessionFile) {
@@ -19808,20 +20320,20 @@ async function readPiEmptySessionConfiguration(sessionFile) {
19808
20320
  }
19809
20321
 
19810
20322
  // dist/pi-adapter.js
19811
- import { randomUUID as randomUUID6 } from "node:crypto";
19812
- import path15 from "node:path";
20323
+ import { randomUUID as randomUUID7 } from "node:crypto";
20324
+ import path16 from "node:path";
19813
20325
 
19814
20326
  // dist/pi-workflow-child-history.js
19815
- import { createHash as createHash3 } from "node:crypto";
20327
+ import { createHash as createHash6 } from "node:crypto";
19816
20328
  import { constants } from "node:fs";
19817
20329
  import { open as open3 } from "node:fs/promises";
19818
- import path12 from "node:path";
19819
- function record5(value) {
20330
+ import path13 from "node:path";
20331
+ function record7(value) {
19820
20332
  return typeof value === "object" && value !== null && !Array.isArray(value);
19821
20333
  }
19822
20334
  var MAX_SESSION_BYTES = 8 * 1024 * 1024;
19823
- async function childHistory(file2, parentSessionId, identity) {
19824
- if (!path12.isAbsolute(file2))
20335
+ async function childHistory(file2, parentSessionId, identity, validateParent = false) {
20336
+ if (!path13.isAbsolute(file2))
19825
20337
  throw new Error("Pi child Session path is not absolute");
19826
20338
  const handle = await open3(file2, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0));
19827
20339
  try {
@@ -19834,12 +20346,14 @@ async function childHistory(file2, parentSessionId, identity) {
19834
20346
  throw new Error("Pi child Session exceeds read bounds");
19835
20347
  const values = buffer.subarray(0, bytesRead).toString("utf8").split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
19836
20348
  const header = values[0];
19837
- if (!record5(header) || header.type !== "session" || typeof header.id !== "string" || header.version !== 3)
20349
+ if (!record7(header) || header.type !== "session" || typeof header.id !== "string" || header.version !== 3)
19838
20350
  throw new Error("Unsupported Pi child Session header");
20351
+ if (validateParent && header.parentSession !== parentSessionId)
20352
+ throw new Error("Pi child Session parent identity mismatch");
19839
20353
  const entries = [];
19840
20354
  for (const entry of values.slice(1)) {
19841
20355
  const parsed = jsonValueSchema.safeParse(entry);
19842
- if (!parsed.success || !record5(parsed.data) || typeof parsed.data.id !== "string")
20356
+ if (!parsed.success || !record7(parsed.data) || typeof parsed.data.id !== "string")
19843
20357
  throw new Error("Malformed Pi child Session entry");
19844
20358
  entries.push(parsed.data);
19845
20359
  }
@@ -19849,7 +20363,7 @@ async function childHistory(file2, parentSessionId, identity) {
19849
20363
  model: null,
19850
20364
  ...typeof header.cwd === "string" ? { cwd: header.cwd } : {}
19851
20365
  });
19852
- const prefix = createHash3("sha256").update(identity).digest("hex");
20366
+ const prefix = createHash6("sha256").update(identity).digest("hex");
19853
20367
  return {
19854
20368
  turns: snapshot.turns.map((turn) => {
19855
20369
  const readonlyTurn = {
@@ -19870,7 +20384,7 @@ async function childHistory(file2, parentSessionId, identity) {
19870
20384
  async function readPiWorkflowChild(history, parentSessionId, address) {
19871
20385
  for (const entry of activePiEntries(history).reverse()) {
19872
20386
  const message3 = entry.message;
19873
- if (!record5(message3) || message3.role !== "toolResult" || message3.toolName !== "subagent")
20387
+ if (!record7(message3) || message3.role !== "toolResult" || message3.toolName !== "subagent")
19874
20388
  continue;
19875
20389
  const summary = piWorkflowSummary(message3);
19876
20390
  if (!summary || summary.workflowRunId !== address.workflowRunId || summary.parentToolCallId !== message3.toolCallId)
@@ -19879,10 +20393,10 @@ async function readPiWorkflowChild(history, parentSessionId, address) {
19879
20393
  if (!child)
19880
20394
  break;
19881
20395
  const details = message3.details;
19882
- if (!record5(details) || !Array.isArray(details.results))
20396
+ if (!record7(details) || !Array.isArray(details.results))
19883
20397
  break;
19884
- const result = details.results.findLast((candidate) => record5(candidate) && candidate.workflowKey === address.childId);
19885
- if (!record5(result))
20398
+ const result = details.results.findLast((candidate) => record7(candidate) && candidate.workflowKey === address.childId);
20399
+ if (!record7(result))
19886
20400
  break;
19887
20401
  const id = piWorkflowSubagentId(address);
19888
20402
  if (typeof result.sessionFile === "string") {
@@ -19925,25 +20439,69 @@ ${output}`,
19925
20439
  };
19926
20440
  }
19927
20441
 
20442
+ // dist/pi-gotgenes-history.js
20443
+ function gotgenesHistory(history) {
20444
+ const records = /* @__PURE__ */ new Map();
20445
+ for (const entry of activePiEntries(history)) {
20446
+ const message3 = entry.message;
20447
+ const parsed = entry.type === "custom" && entry.customType === "subagents:record" ? gotgenesRecord(entry.data) : isRecord4(message3) && message3.role === "toolResult" && typeof message3.toolName === "string" ? gotgenesToolRecord(message3.toolName, message3) : null;
20448
+ if (!parsed)
20449
+ continue;
20450
+ records.set(parsed.id, mergeGotgenesRecord(records.get(parsed.id), parsed));
20451
+ }
20452
+ return [...records.values()];
20453
+ }
20454
+ function restoreGotgenes(history, observer) {
20455
+ observer.observe(gotgenesHistory(history), false);
20456
+ }
20457
+ async function readGotgenesChild(history, parentSessionId, id, live) {
20458
+ const saved = gotgenesHistory(history).find((entry) => entry.id === id);
20459
+ const record9 = live?.outputFile ? live : saved;
20460
+ if (!record9?.outputFile)
20461
+ return {
20462
+ ok: false,
20463
+ error: {
20464
+ code: "sessionNotFound",
20465
+ message: "Pi subagent has not published its Session transcript path",
20466
+ retryable: true
20467
+ }
20468
+ };
20469
+ try {
20470
+ return {
20471
+ ok: true,
20472
+ value: await childHistory(record9.outputFile, parentSessionId, gotgenesId(id), true)
20473
+ };
20474
+ } catch (error51) {
20475
+ return {
20476
+ ok: false,
20477
+ error: {
20478
+ code: "unavailable",
20479
+ message: error51 instanceof Error ? error51.message : "Pi child transcript unavailable",
20480
+ retryable: true
20481
+ }
20482
+ };
20483
+ }
20484
+ }
20485
+
19928
20486
  // dist/pi-subagent-history.js
19929
20487
  import { constants as constants2 } from "node:fs";
19930
20488
  import { open as open4 } from "node:fs/promises";
19931
- import path13 from "node:path";
19932
- function record6(value) {
20489
+ import path14 from "node:path";
20490
+ function record8(value) {
19933
20491
  return typeof value === "object" && value !== null && !Array.isArray(value);
19934
20492
  }
19935
20493
  function state(value) {
19936
20494
  return value === "pending" ? "queued" : value === "completed" ? "complete" : value;
19937
20495
  }
19938
20496
  function piSubagentArtifact(value, runId, parentSessionId) {
19939
- if (!record6(value) || value.lifecycleArtifactVersion !== 3 || value.runId !== runId || value.sessionId !== parentSessionId || !["single", "parallel", "chain", "workflow"].includes(String(value.mode)))
20497
+ if (!record8(value) || value.lifecycleArtifactVersion !== 3 || value.runId !== runId || value.sessionId !== parentSessionId || !["single", "parallel", "chain", "workflow"].includes(String(value.mode)))
19940
20498
  return null;
19941
20499
  if (value.steps !== void 0 && (!Array.isArray(value.steps) || value.steps.length > 128))
19942
20500
  return null;
19943
20501
  const steps = Array.isArray(value.steps) ? value.steps : [];
19944
20502
  const children = [];
19945
20503
  for (const [index, step] of steps.entries()) {
19946
- if (!record6(step) || typeof step.agent !== "string")
20504
+ if (!record8(step) || typeof step.agent !== "string")
19947
20505
  return null;
19948
20506
  children.push({
19949
20507
  id: step.workflowKey ?? step.runId ?? `step:${index}`,
@@ -19974,19 +20532,20 @@ function piSubagentArtifact(value, runId, parentSessionId) {
19974
20532
  });
19975
20533
  }
19976
20534
  async function restorePiSubagents(history, parentSessionId, observer) {
20535
+ restoreGotgenes(history, observer.gotgenes);
19977
20536
  const receipts = /* @__PURE__ */ new Map();
19978
20537
  for (const entry of activePiEntries(history)) {
19979
- if (!record6(entry.message) || entry.message.role !== "toolResult" || entry.message.toolName !== "subagent" || entry.message.isError !== false || !record6(entry.message.details))
20538
+ if (!record8(entry.message) || entry.message.role !== "toolResult" || entry.message.toolName !== "subagent" || entry.message.isError !== false || !record8(entry.message.details))
19980
20539
  continue;
19981
20540
  const details = entry.message.details;
19982
- if (!["single", "parallel", "chain", "workflow"].includes(String(details.mode)) || typeof details.asyncId !== "string" || typeof details.asyncDir !== "string" || !path13.isAbsolute(details.asyncDir) || path13.basename(details.asyncDir) !== details.asyncId)
20541
+ if (!["single", "parallel", "chain", "workflow"].includes(String(details.mode)) || typeof details.asyncId !== "string" || typeof details.asyncDir !== "string" || !path14.isAbsolute(details.asyncDir) || path14.basename(details.asyncDir) !== details.asyncId)
19983
20542
  continue;
19984
20543
  receipts.set(details.asyncId, details.asyncDir);
19985
20544
  }
19986
20545
  for (const [id, directory] of [...receipts].slice(-128)) {
19987
20546
  let file2;
19988
20547
  try {
19989
- file2 = await open4(path13.join(directory, "status.json"), constants2.O_RDONLY | (constants2.O_NOFOLLOW ?? 0));
20548
+ file2 = await open4(path14.join(directory, "status.json"), constants2.O_RDONLY | (constants2.O_NOFOLLOW ?? 0));
19990
20549
  const stat2 = await file2.stat();
19991
20550
  if (!stat2.isFile() || stat2.size > 1024 * 1024)
19992
20551
  continue;
@@ -20068,8 +20627,8 @@ async function rollbackPiLastTurn(transport, sourceSessionId, cwd) {
20068
20627
 
20069
20628
  // dist/pi-rpc-session.js
20070
20629
  import { spawn, spawnSync } from "node:child_process";
20071
- import { randomUUID as randomUUID5 } from "node:crypto";
20072
- import path14 from "node:path";
20630
+ import { randomUUID as randomUUID6 } from "node:crypto";
20631
+ import path15 from "node:path";
20073
20632
 
20074
20633
  // dist/pi-slash-commands.js
20075
20634
  var DYNAMIC_ID_PREFIX = "pi.slash.";
@@ -20091,15 +20650,15 @@ function parsePiNativeCommands(response) {
20091
20650
  return data.commands.flatMap((entry) => {
20092
20651
  if (typeof entry !== "object" || entry === null)
20093
20652
  return [];
20094
- const record7 = entry;
20095
- const name = typeof record7.name === "string" ? record7.name.trim().replace(/^\//u, "") : "";
20653
+ const record9 = entry;
20654
+ const name = typeof record9.name === "string" ? record9.name.trim().replace(/^\//u, "") : "";
20096
20655
  if (!name)
20097
20656
  return [];
20098
20657
  return [
20099
20658
  {
20100
20659
  name,
20101
- ...typeof record7.description === "string" ? { description: record7.description } : {},
20102
- ...typeof record7.source === "string" ? { source: record7.source } : {}
20660
+ ...typeof record9.description === "string" ? { description: record9.description } : {},
20661
+ ...typeof record9.source === "string" ? { source: record9.source } : {}
20103
20662
  }
20104
20663
  ];
20105
20664
  });
@@ -20115,8 +20674,97 @@ function piDynamicCommandPrompt(catalog, commandId, argumentText) {
20115
20674
  return liveHarnessCommandPrompt(catalog, DYNAMIC_ID_PREFIX, commandId, argumentText);
20116
20675
  }
20117
20676
 
20677
+ // dist/pi-content-stream.js
20678
+ var PiContentStreamConflictError = class extends Error {
20679
+ };
20680
+ var PiContentStream = class {
20681
+ kind;
20682
+ #blocks = /* @__PURE__ */ new Map();
20683
+ #indexed;
20684
+ #legacyBlockIndex = 0;
20685
+ #lastEmittedIndex = -Infinity;
20686
+ constructor(kind) {
20687
+ this.kind = kind;
20688
+ }
20689
+ append(index, delta) {
20690
+ const block = this.#block(this.#key(index));
20691
+ if (block.ended && delta.length > 0)
20692
+ this.#conflict();
20693
+ block.received += delta;
20694
+ return this.#flush();
20695
+ }
20696
+ complete(index, content) {
20697
+ this.#finish(this.#key(index), content);
20698
+ if (this.#indexed === false)
20699
+ this.#legacyBlockIndex += 1;
20700
+ return this.#flush();
20701
+ }
20702
+ finalize(blocks) {
20703
+ if (this.#indexed !== true) {
20704
+ blocks = this.#legacyBlockIndex > 0 ? blocks.map(({ text: text3 }, index) => ({ index, text: text3 })) : [{ index: 0, text: blocks.map(({ text: text3 }) => text3).join("") }];
20705
+ }
20706
+ const indices = new Set(blocks.map(({ index }) => index));
20707
+ for (const [index, block] of this.#blocks) {
20708
+ if (indices.has(index))
20709
+ continue;
20710
+ if (block.emitted.length > 0)
20711
+ this.#conflict();
20712
+ this.#blocks.delete(index);
20713
+ }
20714
+ for (const { index, text: text3 } of blocks)
20715
+ this.#finish(index, text3);
20716
+ return this.#flush();
20717
+ }
20718
+ #key(index) {
20719
+ const indexed = typeof index === "number" && Number.isInteger(index) && index >= 0;
20720
+ this.#indexed ??= indexed;
20721
+ if (!this.#indexed)
20722
+ return this.#legacyBlockIndex;
20723
+ if (!indexed)
20724
+ this.#conflict();
20725
+ return index;
20726
+ }
20727
+ #block(index) {
20728
+ let block = this.#blocks.get(index);
20729
+ if (!block) {
20730
+ block = { received: "", emitted: "", ended: false };
20731
+ this.#blocks.set(index, block);
20732
+ }
20733
+ return block;
20734
+ }
20735
+ #finish(index, content) {
20736
+ const block = this.#block(index);
20737
+ if (!content.startsWith(block.emitted))
20738
+ this.#conflict();
20739
+ block.received = content;
20740
+ block.ended = true;
20741
+ }
20742
+ #flush() {
20743
+ let delta = "";
20744
+ for (const [index, block] of [...this.#blocks].sort(([left], [right]) => left - right)) {
20745
+ const visible = this.kind === "reasoning" && !block.ended ? block.received.replace(/[\r\n]+$/u, "") : block.received;
20746
+ if (!visible.startsWith(block.emitted))
20747
+ this.#conflict();
20748
+ const suffix = visible.slice(block.emitted.length);
20749
+ if (suffix.length > 0) {
20750
+ if (index < this.#lastEmittedIndex)
20751
+ this.#conflict();
20752
+ this.#lastEmittedIndex = index;
20753
+ block.emitted = visible;
20754
+ delta += suffix;
20755
+ }
20756
+ if (!block.ended)
20757
+ break;
20758
+ }
20759
+ return delta;
20760
+ }
20761
+ #conflict() {
20762
+ throw new PiContentStreamConflictError(`Pi ${this.kind} final content conflicts with already streamed content`);
20763
+ }
20764
+ };
20765
+
20118
20766
  // dist/pi-subagent-rpc.js
20119
- import { randomUUID as randomUUID4 } from "node:crypto";
20767
+ import { randomUUID as randomUUID5 } from "node:crypto";
20120
20768
  var PiSubagentRpc = class {
20121
20769
  send;
20122
20770
  timeoutMs;
@@ -20158,7 +20806,7 @@ var PiSubagentRpc = class {
20158
20806
  if (!Array.isArray(data?.commands) || !data.commands.some((command) => command?.name === "subagents-inspect-rpc" && command.source === "extension")) {
20159
20807
  throw new Error("Installed Pi has no pi-subagents Host inspection command");
20160
20808
  }
20161
- const requestId = randomUUID4();
20809
+ const requestId = randomUUID5();
20162
20810
  const reply = new Promise((resolve, reject) => {
20163
20811
  const timer = setTimeout(() => {
20164
20812
  this.#pending.delete(requestId);
@@ -20192,6 +20840,12 @@ var PiSubagentRpc = class {
20192
20840
  };
20193
20841
 
20194
20842
  // dist/pi-rpc-session.js
20843
+ var PiRpcBusyError = class extends Error {
20844
+ constructor() {
20845
+ super("Pi is still running a native Turn; wait for completion or use the active Turn's stop/steer action");
20846
+ this.name = "PiRpcBusyError";
20847
+ }
20848
+ };
20195
20849
  var PiRpcFaultError = class extends Error {
20196
20850
  kind;
20197
20851
  diagnostic;
@@ -20219,8 +20873,11 @@ var READ_ONLY_COMMANDS = /* @__PURE__ */ new Set([
20219
20873
  "get_available_thinking_levels"
20220
20874
  ]);
20221
20875
  var MAX_EXPIRED_IDS = 64;
20876
+ function nativeMessageIdentity(active) {
20877
+ return active.assistantNativeMessageIdentity ? { nativeMessageIdentity: active.assistantNativeMessageIdentity } : {};
20878
+ }
20222
20879
  var textDecoder = new TextDecoder("utf-8", { fatal: true });
20223
- function isRecord8(value) {
20880
+ function isRecord9(value) {
20224
20881
  return typeof value === "object" && value !== null && !Array.isArray(value);
20225
20882
  }
20226
20883
  function message2(value) {
@@ -20232,13 +20889,13 @@ function nonBlankString(value) {
20232
20889
  function parseNativeModel(value, context) {
20233
20890
  if (value === null || value === void 0)
20234
20891
  return null;
20235
- if (!isRecord8(value) || !nonBlankString(value.provider) || !nonBlankString(value.id)) {
20892
+ if (!isRecord9(value) || !nonBlankString(value.provider) || !nonBlankString(value.id)) {
20236
20893
  throw new PiRpcFaultError("protocolError", `Pi RPC returned an invalid ${context} Model`);
20237
20894
  }
20238
20895
  return { provider: value.provider, id: value.id };
20239
20896
  }
20240
20897
  function sessionStateData(response) {
20241
- const data = isRecord8(response.data) ? response.data : null;
20898
+ const data = isRecord9(response.data) ? response.data : null;
20242
20899
  if (!data)
20243
20900
  throw new PiRpcFaultError("protocolError", "Pi RPC state response has no data");
20244
20901
  return data;
@@ -20246,7 +20903,7 @@ function sessionStateData(response) {
20246
20903
  function parseSessionState(response) {
20247
20904
  const data = sessionStateData(response);
20248
20905
  const model2 = parseNativeModel(data.model, "state");
20249
- const modelReasoning = isRecord8(data.model) && typeof data.model.reasoning === "boolean" ? data.model.reasoning : null;
20906
+ const modelReasoning = isRecord9(data.model) && typeof data.model.reasoning === "boolean" ? data.model.reasoning : null;
20250
20907
  if (!nonBlankString(data.sessionId)) {
20251
20908
  throw new PiRpcFaultError("protocolError", "Pi RPC state has no stable Session identity");
20252
20909
  }
@@ -20272,13 +20929,13 @@ function parseSessionStreaming(response) {
20272
20929
  return isStreaming;
20273
20930
  }
20274
20931
  function parseSessionHistory(response) {
20275
- const data = isRecord8(response.data) ? response.data : null;
20932
+ const data = isRecord9(response.data) ? response.data : null;
20276
20933
  if (!data || !Array.isArray(data.entries)) {
20277
20934
  throw new PiRpcFaultError("protocolError", "Pi RPC entries response has no Entries");
20278
20935
  }
20279
20936
  const entries = data.entries.map((entry) => {
20280
20937
  const parsed = jsonValueSchema.safeParse(entry);
20281
- if (!parsed.success || !isRecord8(parsed.data)) {
20938
+ if (!parsed.success || !isRecord9(parsed.data)) {
20282
20939
  throw new PiRpcFaultError("protocolError", "Pi RPC entries response contains an invalid Entry");
20283
20940
  }
20284
20941
  return parsed.data;
@@ -20289,7 +20946,7 @@ function parseSessionHistory(response) {
20289
20946
  return { entries, leafId: data.leafId };
20290
20947
  }
20291
20948
  function parseAvailableThinkingLevels(response) {
20292
- const data = isRecord8(response.data) ? response.data : null;
20949
+ const data = isRecord9(response.data) ? response.data : null;
20293
20950
  if (!data || !Array.isArray(data.levels) || data.levels.length === 0) {
20294
20951
  throw new PiRpcFaultError("protocolError", "Pi RPC Thinking catalog response has no levels");
20295
20952
  }
@@ -20306,13 +20963,13 @@ function parseAvailableThinkingLevels(response) {
20306
20963
  return levels;
20307
20964
  }
20308
20965
  function parseAvailableModels(response) {
20309
- const data = isRecord8(response.data) ? response.data : null;
20966
+ const data = isRecord9(response.data) ? response.data : null;
20310
20967
  if (!data || !Array.isArray(data.models)) {
20311
20968
  throw new PiRpcFaultError("protocolError", "Pi RPC Model catalog response has no models");
20312
20969
  }
20313
20970
  return data.models.map((model2) => {
20314
20971
  const parsed = parseNativeModel(model2, "catalog");
20315
- if (!parsed || !isRecord8(model2) || typeof model2.reasoning !== "boolean") {
20972
+ if (!parsed || !isRecord9(model2) || typeof model2.reasoning !== "boolean") {
20316
20973
  throw new PiRpcFaultError("protocolError", "Pi RPC catalog contains a Model without reasoning capability");
20317
20974
  }
20318
20975
  return {
@@ -20323,32 +20980,32 @@ function parseAvailableModels(response) {
20323
20980
  });
20324
20981
  }
20325
20982
  function assistantText(value) {
20326
- if (!isRecord8(value) || value.role !== "assistant" || !Array.isArray(value.content))
20983
+ if (!isRecord9(value) || value.role !== "assistant" || !Array.isArray(value.content))
20327
20984
  return null;
20328
- return value.content.filter((content) => isRecord8(content) && content.type === "text" && typeof content.text === "string").map((content) => content.text).join("");
20985
+ return value.content.filter((content) => isRecord9(content) && content.type === "text" && typeof content.text === "string").map((content) => content.text).join("");
20329
20986
  }
20330
20987
  function assistantMessageId(value) {
20331
- if (!isRecord8(value) || value.role !== "assistant")
20988
+ if (!isRecord9(value) || value.role !== "assistant")
20332
20989
  return null;
20333
20990
  return nonBlankString(value.responseId) ? value.responseId : null;
20334
20991
  }
20335
20992
  function extractReasoningText(content) {
20336
- if (!isRecord8(content))
20993
+ if (!isRecord9(content))
20337
20994
  return null;
20338
20995
  const type = String(content.type ?? "");
20339
20996
  if (type === "thinking" || type === "reasoning" || type === "thought") {
20340
- const text2 = content.thinking ?? content.reasoning ?? content.text ?? content.delta;
20341
- return typeof text2 === "string" ? text2 : null;
20997
+ const text3 = content.thinking ?? content.reasoning ?? content.text ?? content.delta;
20998
+ return typeof text3 === "string" ? text3 : null;
20342
20999
  }
20343
21000
  return null;
20344
21001
  }
20345
21002
  function assistantReasoning(value) {
20346
- if (!isRecord8(value) || value.role !== "assistant" || !Array.isArray(value.content))
21003
+ if (!isRecord9(value) || value.role !== "assistant" || !Array.isArray(value.content))
20347
21004
  return null;
20348
- return value.content.map(extractReasoningText).filter((text2) => typeof text2 === "string").join("");
21005
+ return value.content.map(extractReasoningText).filter((text3) => typeof text3 === "string").join("");
20349
21006
  }
20350
21007
  function assistantFailure(value) {
20351
- if (!isRecord8(value) || value.role !== "assistant")
21008
+ if (!isRecord9(value) || value.role !== "assistant")
20352
21009
  return void 0;
20353
21010
  if (value.stopReason !== "error" && value.stopReason !== "aborted")
20354
21011
  return null;
@@ -20368,7 +21025,7 @@ function signalProcessTree(child, signal) {
20368
21025
  try {
20369
21026
  process.kill(-child.pid, signal);
20370
21027
  } catch (error51) {
20371
- if (!isRecord8(error51) || error51.code !== "ESRCH")
21028
+ if (!isRecord9(error51) || error51.code !== "ESRCH")
20372
21029
  throw error51;
20373
21030
  }
20374
21031
  }
@@ -20405,13 +21062,14 @@ function piRpcProcessCommand(options, dependencies = {}) {
20405
21062
  const thinkingArguments = options.emptySessionConfiguration ? ["--thinking", options.emptySessionConfiguration.thinkingLevel] : [];
20406
21063
  const arguments_ = [
20407
21064
  ...options.fastExtension ? ["--extension", options.fastExtension] : [],
21065
+ ...options.subagentExtension ? ["--extension", options.subagentExtension] : [],
20408
21066
  "--mode",
20409
21067
  "rpc",
20410
21068
  ...modelArguments,
20411
21069
  ...thinkingArguments,
20412
21070
  ...sessionArguments
20413
21071
  ];
20414
- const extension = path14.win32.extname(command).toLowerCase();
21072
+ const extension = path15.win32.extname(command).toLowerCase();
20415
21073
  if (platform !== "win32" || ![".cmd", ".bat"].includes(extension)) {
20416
21074
  return { command, arguments: arguments_, windowsVerbatimArguments: false };
20417
21075
  }
@@ -20440,7 +21098,13 @@ var PiRpcSession = class {
20440
21098
  #options;
20441
21099
  #processAdapter;
20442
21100
  #activeTurn = null;
21101
+ #runGeneration = 0;
21102
+ #deferredRunFrames = [];
21103
+ #deferredRunBytes = 0;
21104
+ #runWaiters = /* @__PURE__ */ new Set();
21105
+ #messageTimestampCounts = /* @__PURE__ */ new Map();
20443
21106
  #autonomousTurnHandler = null;
21107
+ #autonomousLifecycleHandler = null;
20444
21108
  #usageHandler = null;
20445
21109
  #usageRequestStartedAtMs = null;
20446
21110
  // Pieces of the unterminated frame; joined once at its newline so a large frame (a long
@@ -20460,8 +21124,15 @@ var PiRpcSession = class {
20460
21124
  #fastAcknowledgement = null;
20461
21125
  #latestCacheHitRatePercent;
20462
21126
  #manualCompaction = null;
21127
+ #noticeOccurrences = /* @__PURE__ */ new Map();
21128
+ #seenNoticeFrames = /* @__PURE__ */ new Set();
21129
+ #pendingProgress = [];
21130
+ #omittedProgress = 0;
21131
+ #extensionStatuses = /* @__PURE__ */ new Map();
20463
21132
  #stderrTail = "";
20464
21133
  #subagents;
21134
+ #gotgenesHandler;
21135
+ #gotgenesLatest;
20465
21136
  constructor(options, processAdapter = nodeProcessAdapter) {
20466
21137
  if (options.sessionFile && options.forkSessionFile) {
20467
21138
  throw new Error("Pi RPC cannot combine Session resume and Fork startup");
@@ -20491,9 +21162,17 @@ var PiRpcSession = class {
20491
21162
  get stderrTail() {
20492
21163
  return this.#stderrTail;
20493
21164
  }
21165
+ get isBusy() {
21166
+ return this.#activeTurn !== null || this.#manualCompaction !== null || this.#compactionActive || this.#deferredRunFrames.length > 0;
21167
+ }
20494
21168
  setSubagentStatusHandler(handler) {
20495
21169
  this.#subagents.setHandler(handler);
20496
21170
  }
21171
+ setGotgenesStatusHandler(handler) {
21172
+ this.#gotgenesHandler = handler;
21173
+ if (this.#gotgenesLatest)
21174
+ handler(this.#gotgenesLatest, "idle");
21175
+ }
20497
21176
  inspectSubagent(id) {
20498
21177
  return this.#subagents.inspect(id);
20499
21178
  }
@@ -20503,17 +21182,18 @@ var PiRpcSession = class {
20503
21182
  /** Every finished assistant message is one model request, with or without an active Turn. */
20504
21183
  #observeUsage(value) {
20505
21184
  if (value.type === "message_start") {
20506
- this.#usageRequestStartedAtMs = null;
21185
+ if (isRecord9(value.message) && value.message.role === "assistant")
21186
+ this.#usageRequestStartedAtMs = null;
20507
21187
  return;
20508
21188
  }
20509
21189
  if (value.type === "message_update") {
20510
21190
  const event = value.assistantMessageEvent;
20511
- if (this.#usageRequestStartedAtMs === null && isRecord8(event) && typeof event.type === "string" && /^(text|thinking|reasoning|thought|toolcall)_(start|delta)$/u.test(event.type)) {
21191
+ if (this.#usageRequestStartedAtMs === null && isRecord9(event) && typeof event.type === "string" && /^(text|thinking|reasoning|thought|toolcall)_(start|delta)$/u.test(event.type)) {
20512
21192
  this.#usageRequestStartedAtMs = Date.now();
20513
21193
  }
20514
21194
  return;
20515
21195
  }
20516
- if (value.type === "message_end" && isRecord8(value.message)) {
21196
+ if (value.type === "message_end" && isRecord9(value.message)) {
20517
21197
  if (value.message.role !== "assistant")
20518
21198
  return;
20519
21199
  const startedAtMs = this.#usageRequestStartedAtMs;
@@ -20527,14 +21207,21 @@ var PiRpcSession = class {
20527
21207
  }
20528
21208
  setAutonomousTurnHandler(handler) {
20529
21209
  this.#autonomousTurnHandler = handler;
21210
+ this.#autonomousLifecycleHandler = null;
21211
+ }
21212
+ setAutonomousTurnLifecycleHandler(handler) {
21213
+ this.#autonomousLifecycleHandler = handler;
21214
+ this.#autonomousTurnHandler = null;
20530
21215
  }
20531
21216
  async start() {
20532
21217
  if (this.#child || this.#closed)
20533
21218
  throw new Error("Pi RPC Session cannot be started twice");
20534
21219
  const fastExtension = this.#processAdapter === nodeProcessAdapter ? await ensurePiFastExtension({ ...process.env, ...this.#options.environment }) : void 0;
21220
+ const subagentExtension = this.#processAdapter === nodeProcessAdapter ? await ensureGotgenesExtension({ ...process.env, ...this.#options.environment }) : void 0;
20535
21221
  const child = this.#processAdapter.spawn({
20536
21222
  cwd: this.#options.cwd,
20537
21223
  ...fastExtension ? { fastExtension } : {},
21224
+ ...subagentExtension ? { subagentExtension } : {},
20538
21225
  ...this.#options.command ? { command: this.#options.command } : {},
20539
21226
  environment: withNodeRuntimeOnPath({
20540
21227
  ...process.env,
@@ -20558,7 +21245,7 @@ var PiRpcSession = class {
20558
21245
  this.#stderrTail = sanitizeDiagnosticTail(`${this.#stderrTail}${chunk.toString()}`);
20559
21246
  });
20560
21247
  child.once("error", (error51) => {
20561
- const kind = isRecord8(error51) && error51.code === "ENOENT" ? "notInstalled" : "unavailable";
21248
+ const kind = isRecord9(error51) && error51.code === "ENOENT" ? "notInstalled" : "unavailable";
20562
21249
  this.#fail(new PiRpcFaultError(kind, `Pi RPC failed to start: ${error51.message}`, this.stderrTail));
20563
21250
  });
20564
21251
  child.once("exit", (code, signal) => {
@@ -20575,6 +21262,7 @@ var PiRpcSession = class {
20575
21262
  ]);
20576
21263
  try {
20577
21264
  this.#state = parseSessionState(await this.#send("get_state", {}));
21265
+ await this.getEntries();
20578
21266
  } catch (error51) {
20579
21267
  const fault = error51 instanceof PiRpcFaultError ? error51 : new PiRpcFaultError("unavailable", `Pi RPC state unavailable: ${message2(error51)}`);
20580
21268
  this.#fail(fault);
@@ -20588,7 +21276,12 @@ var PiRpcSession = class {
20588
21276
  }
20589
21277
  async getEntries() {
20590
21278
  try {
20591
- return parseSessionHistory(await this.#send("get_entries", {}));
21279
+ const history = parseSessionHistory(await this.#send("get_entries", {}));
21280
+ if (!this.#activeTurn && this.#state) {
21281
+ this.#messageTimestampCounts = piHistoryMessageIdentities(this.state.sessionId, activePiEntries(history)).timestampCounts;
21282
+ this.#noticeOccurrences = piHistoryNotices(this.state.sessionId, activePiEntries(history)).occurrences;
21283
+ }
21284
+ return history;
20592
21285
  } catch (error51) {
20593
21286
  if (error51 instanceof PiRpcFaultError)
20594
21287
  this.#fail(error51);
@@ -20648,11 +21341,15 @@ var PiRpcSession = class {
20648
21341
  if (entryId.length === 0)
20649
21342
  throw new Error("Pi Fork Entry ID must not be empty");
20650
21343
  await this.#send("fork", { entryId });
20651
- return this.#refreshState("Fork");
21344
+ const state2 = await this.#refreshState("Fork");
21345
+ await this.getEntries();
21346
+ return state2;
20652
21347
  }
20653
21348
  async clone() {
20654
21349
  await this.#send("clone", {});
20655
- return this.#refreshState("Clone");
21350
+ const state2 = await this.#refreshState("Clone");
21351
+ await this.getEntries();
21352
+ return state2;
20656
21353
  }
20657
21354
  verifySessionCwd(expectedCwd) {
20658
21355
  return verifyPiSessionCwd({
@@ -20689,7 +21386,7 @@ var PiRpcSession = class {
20689
21386
  return this.state;
20690
21387
  if (!await this.supportsFastMode())
20691
21388
  throw new Error("Installed Pi does not support the Host Fast extension");
20692
- const nonce = randomUUID5();
21389
+ const nonce = randomUUID6();
20693
21390
  const mode = enabled ? "on" : "off";
20694
21391
  const acknowledgement = { message: `${PI_FAST_ACK}${nonce}:${mode}`, received: false };
20695
21392
  this.#fastAcknowledgement = acknowledgement;
@@ -20729,22 +21426,27 @@ var PiRpcSession = class {
20729
21426
  throw fault;
20730
21427
  }
20731
21428
  }
20732
- async runTurn(text2, onEvent) {
21429
+ async runTurn(text3, onEvent) {
20733
21430
  if (!this.#child || !this.#state || this.#closed || this.#failed) {
20734
21431
  throw new Error("Pi RPC Session is unavailable");
20735
21432
  }
20736
- if (this.#activeTurn)
20737
- throw new Error("Pi RPC Session already has an active Turn");
20738
- if (text2.length === 0)
21433
+ if (this.isBusy)
21434
+ throw new PiRpcBusyError();
21435
+ if (text3.length === 0)
20739
21436
  throw new Error("Pi text Turn must not be empty");
20740
21437
  const settled = new Promise((resolve, reject) => {
20741
21438
  this.#activeTurn = {
20742
21439
  origin: "requested",
21440
+ autonomousRunId: null,
21441
+ runGeneration: this.#runGeneration,
20743
21442
  autonomousEvents: null,
20744
21443
  nativeTurnKey: null,
20745
21444
  nativeCancellationObserved: false,
20746
21445
  text: "",
20747
21446
  assistantMessageId: null,
21447
+ assistantNativeMessageIdentity: void 0,
21448
+ textStream: new PiContentStream("text"),
21449
+ reasoningStream: new PiContentStream("reasoning"),
20748
21450
  sawStreamedMessageText: false,
20749
21451
  sawStreamedMessageReasoning: false,
20750
21452
  lastFinalizedMessageText: null,
@@ -20764,7 +21466,8 @@ var PiRpcSession = class {
20764
21466
  };
20765
21467
  });
20766
21468
  try {
20767
- await this.#send("prompt", { message: text2 });
21469
+ this.#drainProgress(onEvent);
21470
+ await this.#send("prompt", { message: text3 });
20768
21471
  } catch (error51) {
20769
21472
  this.#rejectActiveTurn(error51 instanceof Error ? error51 : new Error(message2(error51)));
20770
21473
  }
@@ -20836,6 +21539,10 @@ var PiRpcSession = class {
20836
21539
  void this.close().catch(() => void 0);
20837
21540
  }
20838
21541
  close() {
21542
+ this.#pendingProgress = [];
21543
+ this.#omittedProgress = 0;
21544
+ this.#seenNoticeFrames.clear();
21545
+ this.#extensionStatuses.clear();
20839
21546
  if (!this.#closed) {
20840
21547
  this.#closed = true;
20841
21548
  this.#rejectAll(new Error("Pi RPC Session closed"));
@@ -20869,19 +21576,25 @@ var PiRpcSession = class {
20869
21576
  rest = rest.subarray(newline + 1);
20870
21577
  try {
20871
21578
  const value = JSON.parse(textDecoder.decode(frame));
20872
- if (!isRecord8(value) || typeof value.type !== "string") {
21579
+ if (!isRecord9(value) || typeof value.type !== "string") {
20873
21580
  throw new PiRpcFaultError("protocolError", "Pi RPC returned an invalid envelope");
20874
21581
  }
20875
21582
  this.#handle(value);
20876
21583
  } catch (error51) {
20877
- this.#fail(error51 instanceof PiRpcFaultError ? error51 : new PiRpcFaultError("protocolError", `Pi RPC returned invalid JSONL: ${message2(error51)}`));
21584
+ this.#fail(error51 instanceof PiRpcFaultError ? error51 : new PiRpcFaultError("protocolError", error51 instanceof PiContentStreamConflictError ? error51.message : `Pi RPC returned invalid JSONL: ${message2(error51)}`));
20878
21585
  }
20879
21586
  newline = rest.indexOf(10);
20880
21587
  }
20881
21588
  if (rest.length !== 0)
20882
21589
  this.#buffer.push(rest);
20883
21590
  }
20884
- #handle(value) {
21591
+ #handle(value, observedGeneration) {
21592
+ if (observedGeneration === void 0 && value.type === "agent_start") {
21593
+ this.#runGeneration += 1;
21594
+ for (const waiter of this.#runWaiters)
21595
+ waiter.check();
21596
+ }
21597
+ const generation = observedGeneration ?? this.#runGeneration;
20885
21598
  if (value.type === "extension_ui_request" && value.method === "notify" && typeof value.message === "string" && value.message.startsWith(PI_FAST_ACK)) {
20886
21599
  if (this.#fastAcknowledgement?.message === value.message)
20887
21600
  this.#fastAcknowledgement.received = true;
@@ -20895,6 +21608,33 @@ var PiRpcSession = class {
20895
21608
  }
20896
21609
  if (this.#subagents.handle(value))
20897
21610
  return;
21611
+ const settling = this.#activeTurn;
21612
+ if (settling && settling.settlement !== "pending" && generation > settling.runGeneration) {
21613
+ this.#deferredRunBytes += Buffer.byteLength(JSON.stringify(value));
21614
+ if (this.#deferredRunBytes > 8 * 1024 * 1024) {
21615
+ this.#fail(new PiRpcFaultError("protocolError", "Pi deferred run exceeded its event buffer bound"));
21616
+ return;
21617
+ }
21618
+ this.#deferredRunFrames.push({ value, generation });
21619
+ return;
21620
+ }
21621
+ if (value.type === "agent_start") {
21622
+ if (this.#activeTurn)
21623
+ this.#activeTurn.runGeneration = generation;
21624
+ else if (!this.#manualCompaction && !this.#compactionActive && (this.#autonomousTurnHandler || this.#autonomousLifecycleHandler))
21625
+ this.#startAutonomousTurn(void 0, generation);
21626
+ return;
21627
+ }
21628
+ if (value.type === "extension_ui_request" && value.method === "setWidget" && value.widgetKey === GOTGENES_WIDGET) {
21629
+ const records = parseGotgenesWidget(value);
21630
+ if (records) {
21631
+ this.#gotgenesLatest = records;
21632
+ this.#gotgenesHandler?.(records, this.#activeTurn?.origin ?? "idle");
21633
+ }
21634
+ return;
21635
+ }
21636
+ if (this.#handleProgress(value))
21637
+ return;
20898
21638
  this.#observeUsage(value);
20899
21639
  if (value.type === "compaction_start") {
20900
21640
  this.#compactionActive = true;
@@ -20918,7 +21658,7 @@ var PiRpcSession = class {
20918
21658
  this.#armCommandTimeout(id, pending);
20919
21659
  }
20920
21660
  }
20921
- const outcome = value.aborted === true ? "cancelled" : isRecord8(value.result) ? "succeeded" : "failed";
21661
+ const outcome = value.aborted === true ? "cancelled" : isRecord9(value.result) ? "succeeded" : "failed";
20922
21662
  const event = {
20923
21663
  type: "compaction.completed",
20924
21664
  outcome,
@@ -20935,8 +21675,8 @@ var PiRpcSession = class {
20935
21675
  return;
20936
21676
  }
20937
21677
  let active = this.#activeTurn;
20938
- if (!active && !this.#manualCompaction && !this.#compactionActive && this.#autonomousTurnHandler && value.type === "message_start" && assistantText(value.message) !== null) {
20939
- active = this.#startAutonomousTurn(value.message);
21678
+ if (!active && !this.#manualCompaction && !this.#compactionActive && (this.#autonomousTurnHandler || this.#autonomousLifecycleHandler) && value.type === "message_start" && assistantText(value.message) !== null) {
21679
+ active = this.#startAutonomousTurn(value.message, generation);
20940
21680
  }
20941
21681
  if (!active) {
20942
21682
  if (value.type === "extension_ui_request" && this.#isBlockingInteraction(value)) {
@@ -20956,22 +21696,26 @@ var PiRpcSession = class {
20956
21696
  this.#startAssistantMessage(active, value.message);
20957
21697
  return;
20958
21698
  }
20959
- if (value.type === "message_update" && isRecord8(value.assistantMessageEvent)) {
21699
+ if (value.type === "message_update" && isRecord9(value.assistantMessageEvent)) {
20960
21700
  const event = value.assistantMessageEvent;
20961
21701
  const eventType = String(event.type ?? "");
20962
21702
  const isThinking = eventType === "thinking_delta" || eventType === "reasoning_delta" || eventType === "thought_delta" || eventType === "thinking" || eventType === "reasoning";
20963
21703
  const isText = eventType === "text_delta" || eventType === "text" || eventType === "content_block_delta";
20964
- const delta = typeof event.delta === "string" ? event.delta : typeof event.thinking === "string" ? event.thinking : typeof event.reasoning === "string" ? event.reasoning : typeof event.text === "string" ? event.text : isRecord8(event.delta) && typeof event.delta.thinking === "string" ? event.delta.thinking : isRecord8(event.delta) && typeof event.delta.text === "string" ? event.delta.text : null;
20965
- if (isThinking && delta !== null && delta.length > 0) {
20966
- const messageId = this.#ensureAssistantMessage(active, value.message);
20967
- active.reasoningMessageOpen = true;
20968
- active.sawStreamedMessageReasoning = true;
20969
- active.onEvent({ type: "reasoning.delta", messageId, delta });
20970
- } else if (isText && delta !== null && delta.length > 0) {
20971
- const messageId = this.#ensureAssistantMessage(active, value.message);
20972
- active.text += delta;
20973
- active.sawStreamedMessageText = true;
20974
- active.onEvent({ type: "text.delta", messageId, delta });
21704
+ const delta = typeof event.delta === "string" ? event.delta : typeof event.thinking === "string" ? event.thinking : typeof event.reasoning === "string" ? event.reasoning : typeof event.text === "string" ? event.text : isRecord9(event.delta) && typeof event.delta.thinking === "string" ? event.delta.thinking : isRecord9(event.delta) && typeof event.delta.text === "string" ? event.delta.text : null;
21705
+ const endingReasoning = eventType === "thinking_end" || eventType === "reasoning_end";
21706
+ const endingText = eventType === "text_end";
21707
+ if ((endingReasoning || endingText) && typeof event.content === "string") {
21708
+ this.#ensureAssistantMessage(active, value.message);
21709
+ const stream = endingReasoning ? active.reasoningStream : active.textStream;
21710
+ this.#emitContent(active, endingReasoning, stream.complete(event.contentIndex, event.content));
21711
+ } else if ((isThinking || isText) && delta !== null && delta.length > 0) {
21712
+ this.#ensureAssistantMessage(active, value.message);
21713
+ if (isThinking)
21714
+ active.sawStreamedMessageReasoning = true;
21715
+ else
21716
+ active.sawStreamedMessageText = true;
21717
+ const stream = isThinking ? active.reasoningStream : active.textStream;
21718
+ this.#emitContent(active, isThinking, stream.append(event.contentIndex, delta));
20975
21719
  } else if (event.type === "error") {
20976
21720
  this.#ensureAssistantMessage(active, value.message);
20977
21721
  active.failure = assistantFailure(event.error) ?? assistantFailure(value.message) ?? new Error("Pi assistant message failed");
@@ -21002,25 +21746,36 @@ var PiRpcSession = class {
21002
21746
  if (active.settlement !== "pending")
21003
21747
  return;
21004
21748
  active.settlement = "confirming";
21005
- void this.#confirmSettledTurn(active);
21749
+ void this.#confirmSettledTurn(active, active.runGeneration);
21006
21750
  }
21007
21751
  }
21008
- #startAutonomousTurn(value) {
21752
+ #startAutonomousTurn(value, generation) {
21009
21753
  const events = [];
21754
+ const runId = randomUUID6();
21010
21755
  const active = {
21011
21756
  origin: "autonomous",
21757
+ autonomousRunId: runId,
21758
+ runGeneration: generation,
21012
21759
  autonomousEvents: events,
21013
- ...isRecord8(value) ? { autonomousMessage: value } : {},
21760
+ ...isRecord9(value) ? { autonomousMessage: value } : {},
21014
21761
  nativeTurnKey: null,
21015
21762
  nativeCancellationObserved: false,
21016
21763
  text: "",
21017
21764
  assistantMessageId: null,
21765
+ assistantNativeMessageIdentity: void 0,
21766
+ textStream: new PiContentStream("text"),
21767
+ reasoningStream: new PiContentStream("reasoning"),
21018
21768
  sawStreamedMessageText: false,
21019
21769
  sawStreamedMessageReasoning: false,
21020
21770
  lastFinalizedMessageText: null,
21021
21771
  lastFinalizedMessageReasoning: null,
21022
21772
  reasoningMessageOpen: false,
21023
- onEvent: (event) => events.push(event),
21773
+ onEvent: (event) => {
21774
+ if (this.#autonomousLifecycleHandler)
21775
+ this.#autonomousLifecycleHandler({ type: "event", runId, event });
21776
+ else
21777
+ events.push(event);
21778
+ },
21024
21779
  resolve: () => void 0,
21025
21780
  reject: () => void 0,
21026
21781
  failure: null,
@@ -21033,19 +21788,108 @@ var PiRpcSession = class {
21033
21788
  abortPromise: null
21034
21789
  };
21035
21790
  this.#activeTurn = active;
21791
+ this.#autonomousLifecycleHandler?.({ type: "started", runId });
21792
+ this.#drainProgress(active.onEvent);
21036
21793
  return active;
21037
21794
  }
21795
+ #handleProgress(value) {
21796
+ if ((value.type === "message_start" || value.type === "message_end") && isRecord9(value.message) && value.message.role === "custom") {
21797
+ if (value.type !== "message_end" || !this.#state)
21798
+ return true;
21799
+ const key = piCustomNoticeKey(value.message);
21800
+ if (!key)
21801
+ return true;
21802
+ const timestamp = value.message.timestamp;
21803
+ if ((typeof timestamp === "number" || typeof timestamp === "string") && !this.#acceptNoticeFrame(JSON.stringify([key, timestamp])))
21804
+ return true;
21805
+ const progress = piCustomNotice(value.message, this.state.sessionId, this.#noticeOccurrences);
21806
+ if (progress)
21807
+ this.#publishProgress(progress);
21808
+ return true;
21809
+ }
21810
+ if (value.type === "extension_ui_request" && value.method === "setStatus") {
21811
+ if (typeof value.statusKey !== "string")
21812
+ return true;
21813
+ if (typeof value.statusText !== "string" || !value.statusText.trim()) {
21814
+ if (!this.#extensionStatuses.has(value.statusKey))
21815
+ return true;
21816
+ this.#extensionStatuses.delete(value.statusKey);
21817
+ } else {
21818
+ if (this.#extensionStatuses.get(value.statusKey) === value.statusText)
21819
+ return true;
21820
+ this.#extensionStatuses.set(value.statusKey, value.statusText);
21821
+ }
21822
+ }
21823
+ const text3 = piStatusText(value);
21824
+ if (!text3)
21825
+ return false;
21826
+ if (value.type === "extension_ui_request" && typeof value.id === "string" && !this.#acceptNoticeFrame(JSON.stringify([value.type, value.id])))
21827
+ return true;
21828
+ this.#publishProgress({
21829
+ type: "progress.message",
21830
+ itemId: hostItemIdSchema.parse(`pi-progress-${randomUUID6()}`),
21831
+ text: text3
21832
+ }, value.method === "setStatus" && typeof value.statusKey === "string" ? value.statusKey : void 0);
21833
+ return true;
21834
+ }
21835
+ #acceptNoticeFrame(key) {
21836
+ if (this.#seenNoticeFrames.has(key))
21837
+ return false;
21838
+ this.#seenNoticeFrames.add(key);
21839
+ if (this.#seenNoticeFrames.size > 512)
21840
+ this.#seenNoticeFrames.delete(this.#seenNoticeFrames.values().next().value);
21841
+ return true;
21842
+ }
21843
+ #publishProgress(progress, statusKey) {
21844
+ if (this.#activeTurn?.settlement === "pending") {
21845
+ this.#activeTurn.onEvent(progress);
21846
+ return;
21847
+ }
21848
+ if (statusKey !== void 0) {
21849
+ const previous = this.#pendingProgress.findIndex((pending) => pending.statusKey === statusKey);
21850
+ if (previous >= 0)
21851
+ this.#pendingProgress.splice(previous, 1);
21852
+ }
21853
+ if (this.#pendingProgress.length >= 128) {
21854
+ this.#pendingProgress.shift();
21855
+ this.#omittedProgress += 1;
21856
+ }
21857
+ this.#pendingProgress.push({
21858
+ event: progress,
21859
+ ...statusKey !== void 0 ? { statusKey } : {}
21860
+ });
21861
+ }
21862
+ #drainProgress(onEvent) {
21863
+ if (this.#omittedProgress > 0) {
21864
+ onEvent({
21865
+ type: "progress.message",
21866
+ itemId: hostItemIdSchema.parse(`pi-progress-${randomUUID6()}`),
21867
+ text: `Pi notifications: ${this.#omittedProgress} earlier updates were not retained while idle. Persisted notifications remain available in conversation history.`
21868
+ });
21869
+ this.#omittedProgress = 0;
21870
+ }
21871
+ for (const pending of this.#pendingProgress.splice(0))
21872
+ onEvent(pending.event);
21873
+ }
21038
21874
  #emitAutonomousTurn(active, result) {
21039
21875
  const handler = this.#autonomousTurnHandler;
21040
- if (active.origin !== "autonomous" || !active.autonomousEvents || !handler) {
21876
+ if (active.origin !== "autonomous" || !active.autonomousEvents || !active.autonomousRunId) {
21041
21877
  return;
21042
21878
  }
21043
21879
  try {
21044
- handler({
21880
+ const turn = {
21045
21881
  nativeTurnKey: active.nativeTurnKey,
21046
21882
  events: [...active.autonomousEvents],
21047
21883
  result
21048
- });
21884
+ };
21885
+ if (this.#autonomousLifecycleHandler)
21886
+ this.#autonomousLifecycleHandler({
21887
+ type: "completed",
21888
+ runId: active.autonomousRunId,
21889
+ turn
21890
+ });
21891
+ else
21892
+ handler?.(turn);
21049
21893
  } catch (error51) {
21050
21894
  this.#fail(new PiRpcFaultError("protocolError", `Pi autonomous Turn handler failed: ${message2(error51)}`));
21051
21895
  }
@@ -21192,31 +22036,73 @@ var PiRpcSession = class {
21192
22036
  isError: value.isError
21193
22037
  });
21194
22038
  }
21195
- async #confirmSettledTurn(active) {
22039
+ #isSettlementCurrent(active, generation) {
22040
+ return this.#activeTurn === active && active.runGeneration === generation && active.settlement === "confirming";
22041
+ }
22042
+ #waitForNextRun(generation) {
22043
+ if (this.#runGeneration > generation)
22044
+ return Promise.resolve();
22045
+ return new Promise((resolve, reject) => {
22046
+ const finish = (error51) => {
22047
+ clearTimeout(timer);
22048
+ this.#runWaiters.delete(waiter);
22049
+ if (error51)
22050
+ reject(error51);
22051
+ else
22052
+ resolve();
22053
+ };
22054
+ const waiter = {
22055
+ check: () => {
22056
+ if (this.#runGeneration > generation)
22057
+ finish();
22058
+ },
22059
+ reject: (error51) => finish(error51)
22060
+ };
22061
+ const timer = setTimeout(() => finish(new PiRpcFaultError("protocolError", "Pi RPC agent_settled state is still Streaming without a subsequent agent_start")), this.#options.commandTimeoutMs);
22062
+ this.#runWaiters.add(waiter);
22063
+ });
22064
+ }
22065
+ #drainDeferredRunFrames() {
22066
+ const frames = this.#deferredRunFrames;
22067
+ this.#deferredRunFrames = [];
22068
+ this.#deferredRunBytes = 0;
22069
+ for (const frame of frames) {
22070
+ if (this.#closed || this.#failed)
22071
+ break;
22072
+ this.#handle(frame.value, frame.generation);
22073
+ }
22074
+ }
22075
+ async #confirmSettledTurn(active, generation) {
21196
22076
  try {
21197
22077
  const response = await this.#send("get_state", {});
21198
22078
  const state2 = parseSessionState(response);
21199
- if (parseSessionStreaming(response)) {
21200
- throw new PiRpcFaultError("protocolError", "Pi RPC agent_settled state is still Streaming");
21201
- }
21202
- if (this.#activeTurn !== active)
22079
+ if (!this.#isSettlementCurrent(active, generation))
22080
+ return;
22081
+ if (parseSessionStreaming(response))
22082
+ await this.#waitForNextRun(generation);
22083
+ if (!this.#isSettlementCurrent(active, generation))
21203
22084
  return;
21204
- if (active.origin === "autonomous") {
22085
+ if (active.origin === "autonomous" && active.autonomousMessage) {
21205
22086
  const history = await this.getEntries();
21206
22087
  const snapshot = mapPiSnapshot(history, { sessionId: state2.sessionId, model: null });
21207
- const turn = snapshot.turns.at(-1);
22088
+ if (!this.#isSettlementCurrent(active, generation))
22089
+ return;
21208
22090
  const entries = activePiEntries(history);
21209
- const start = entries.findIndex((entry) => entry.id === turn?.nativeTurnRef.nativeTurnKey);
21210
- const firstAssistant = entries.slice(start + 1).find((entry) => isRecord8(entry.message) && entry.message.role === "assistant")?.message;
21211
22091
  const live = active.autonomousMessage;
21212
22092
  const responseId = assistantMessageId(live);
21213
- const matches = isRecord8(firstAssistant) && (responseId ? assistantMessageId(firstAssistant) === responseId : typeof live?.timestamp === "number" && firstAssistant.timestamp === live.timestamp);
21214
- if (!turn || turn.input.length !== 0 || !matches) {
22093
+ const matches = snapshot.turns.filter((turn2) => {
22094
+ if (turn2.input.length !== 0)
22095
+ return false;
22096
+ const start = entries.findIndex((entry) => entry.id === turn2.nativeTurnRef.nativeTurnKey);
22097
+ const firstAssistant = entries.slice(start + 1).find((entry) => isRecord9(entry.message) && entry.message.role === "assistant")?.message;
22098
+ return isRecord9(firstAssistant) && (responseId ? assistantMessageId(firstAssistant) === responseId : typeof live?.timestamp === "number" && firstAssistant.timestamp === live.timestamp);
22099
+ });
22100
+ const turn = matches.length === 1 ? matches[0] : void 0;
22101
+ if (!turn)
21215
22102
  throw new PiRpcFaultError("protocolError", "Pi autonomous Turn has no matching persisted custom Entry");
21216
- }
21217
22103
  active.nativeTurnKey = turn.nativeTurnRef.nativeTurnKey;
21218
22104
  }
21219
- if (this.#activeTurn !== active)
22105
+ if (!this.#isSettlementCurrent(active, generation))
21220
22106
  return;
21221
22107
  this.#state = state2;
21222
22108
  active.settlement = "confirmed";
@@ -21242,7 +22128,13 @@ var PiRpcSession = class {
21242
22128
  }
21243
22129
  this.#activeTurn = null;
21244
22130
  if (active.origin === "autonomous") {
21245
- if (active.failure) {
22131
+ if (active.cancellation === "accepted") {
22132
+ this.#emitAutonomousTurn(active, {
22133
+ status: "cancelled",
22134
+ text: active.text,
22135
+ reason: "Cancelled by user"
22136
+ });
22137
+ } else if (active.failure) {
21246
22138
  this.#emitAutonomousTurn(active, active.nativeCancellationObserved ? {
21247
22139
  status: "cancelled",
21248
22140
  text: active.text,
@@ -21257,6 +22149,7 @@ var PiRpcSession = class {
21257
22149
  } else {
21258
22150
  this.#emitAutonomousTurn(active, { status: "succeeded", text: active.text });
21259
22151
  }
22152
+ this.#drainDeferredRunFrames();
21260
22153
  return;
21261
22154
  }
21262
22155
  if (active.cancellation === "accepted") {
@@ -21268,20 +22161,56 @@ var PiRpcSession = class {
21268
22161
  } else {
21269
22162
  active.resolve({ text: active.text, cancelled: false });
21270
22163
  }
22164
+ this.#drainDeferredRunFrames();
22165
+ }
22166
+ #emitContent(active, reasoning, delta) {
22167
+ if (delta.length === 0)
22168
+ return;
22169
+ const messageId = active.assistantMessageId;
22170
+ if (messageId === null)
22171
+ throw new Error("Pi content arrived outside an Assistant message");
22172
+ if (reasoning) {
22173
+ active.reasoningMessageOpen = true;
22174
+ active.sawStreamedMessageReasoning = true;
22175
+ } else {
22176
+ active.text += delta;
22177
+ active.sawStreamedMessageText = true;
22178
+ }
22179
+ active.onEvent({
22180
+ type: reasoning ? "reasoning.delta" : "text.delta",
22181
+ messageId,
22182
+ ...nativeMessageIdentity(active),
22183
+ delta
22184
+ });
21271
22185
  }
21272
22186
  #startAssistantMessage(active, value) {
22187
+ if (active.origin === "autonomous" && !active.autonomousMessage && isRecord9(value))
22188
+ active.autonomousMessage = value;
21273
22189
  if (active.assistantMessageId !== null && active.reasoningMessageOpen) {
21274
22190
  active.onEvent({ type: "reasoning.completed", messageId: active.assistantMessageId });
21275
22191
  }
21276
- const messageId = assistantMessageId(value) ?? randomUUID5();
22192
+ const nativeResponseId = assistantMessageId(value);
22193
+ const messageId = nativeResponseId ?? randomUUID6();
21277
22194
  active.assistantMessageId = messageId;
22195
+ active.assistantNativeMessageIdentity = piMessageIdentity(this.state.sessionId, value, this.#messageTimestampCounts);
22196
+ active.textStream = new PiContentStream("text");
22197
+ active.reasoningStream = new PiContentStream("reasoning");
21278
22198
  active.sawStreamedMessageText = false;
21279
22199
  active.sawStreamedMessageReasoning = false;
21280
22200
  active.reasoningMessageOpen = false;
21281
22201
  return messageId;
21282
22202
  }
21283
22203
  #ensureAssistantMessage(active, value) {
21284
- return active.assistantMessageId ?? this.#startAssistantMessage(active, value);
22204
+ if (active.assistantMessageId === null)
22205
+ return this.#startAssistantMessage(active, value);
22206
+ if (!active.sawStreamedMessageText && !active.sawStreamedMessageReasoning) {
22207
+ const nativeResponseId = assistantMessageId(value);
22208
+ if (nativeResponseId) {
22209
+ active.assistantMessageId = nativeResponseId;
22210
+ active.assistantNativeMessageIdentity ??= { responseId: nativeResponseId };
22211
+ }
22212
+ }
22213
+ return active.assistantMessageId;
21285
22214
  }
21286
22215
  #finalizeAssistantMessage(active, value) {
21287
22216
  const finalText = assistantText(value);
@@ -21294,29 +22223,33 @@ var PiRpcSession = class {
21294
22223
  return;
21295
22224
  }
21296
22225
  active.failure = failure;
21297
- if (active.origin === "autonomous" && isRecord8(value) && value.stopReason === "aborted") {
22226
+ if (active.origin === "autonomous" && piAssistantWasAborted(value)) {
21298
22227
  active.nativeCancellationObserved = true;
21299
22228
  }
21300
22229
  this.#latestCacheHitRatePercent = cacheHitRatePercent;
21301
22230
  const messageId = this.#ensureAssistantMessage(active, value);
21302
- if (!active.sawStreamedMessageReasoning && finalReasoning.length > 0) {
21303
- active.reasoningMessageOpen = true;
21304
- active.onEvent({ type: "reasoning.delta", messageId, delta: finalReasoning });
22231
+ const content = value.content;
22232
+ if (failure === null || !active.sawStreamedMessageReasoning) {
22233
+ this.#emitContent(active, true, active.reasoningStream.finalize(content.flatMap((part, index) => {
22234
+ const text3 = extractReasoningText(part);
22235
+ return text3 === null ? [] : [{ index, text: text3 }];
22236
+ })));
21305
22237
  }
21306
22238
  if (active.reasoningMessageOpen && active.failure === null) {
21307
22239
  active.onEvent({ type: "reasoning.completed", messageId });
21308
22240
  }
21309
- if (!active.sawStreamedMessageText && finalText.length > 0) {
21310
- active.text += finalText;
21311
- active.onEvent({ type: "text.delta", messageId, delta: finalText });
22241
+ if (failure === null || !active.sawStreamedMessageText) {
22242
+ this.#emitContent(active, false, active.textStream.finalize(content.flatMap((part, index) => isRecord9(part) && part.type === "text" && typeof part.text === "string" ? [{ index, text: part.text }] : [])));
21312
22243
  }
21313
22244
  active.assistantMessageId = null;
22245
+ active.assistantNativeMessageIdentity = void 0;
21314
22246
  active.sawStreamedMessageText = false;
21315
22247
  active.sawStreamedMessageReasoning = false;
21316
22248
  active.reasoningMessageOpen = false;
21317
22249
  active.lastFinalizedMessageText = finalText;
21318
22250
  active.lastFinalizedMessageReasoning = finalReasoning;
21319
- active.onEvent({ type: "message.completed", messageId });
22251
+ const phase = piAssistantPhase(value);
22252
+ active.onEvent({ type: "message.completed", messageId, ...phase ? { phase } : {} });
21320
22253
  }
21321
22254
  #write(value) {
21322
22255
  const child = this.#child;
@@ -21334,7 +22267,7 @@ var PiRpcSession = class {
21334
22267
  if (!child?.stdin.writable || this.#closed || this.#failed) {
21335
22268
  return Promise.reject(new Error("Pi RPC stdin is unavailable"));
21336
22269
  }
21337
- const id = `codexhost-${randomUUID5()}`;
22270
+ const id = `codexhost-${randomUUID6()}`;
21338
22271
  return new Promise((resolve, reject) => {
21339
22272
  const pending = {
21340
22273
  command: type,
@@ -21424,9 +22357,16 @@ var PiRpcSession = class {
21424
22357
  } else {
21425
22358
  active.reject(error51);
21426
22359
  }
22360
+ this.#drainDeferredRunFrames();
21427
22361
  }
21428
22362
  #rejectAll(error51) {
22363
+ for (const waiter of this.#runWaiters)
22364
+ waiter.reject(error51);
22365
+ this.#deferredRunFrames = [];
22366
+ this.#deferredRunBytes = 0;
21429
22367
  this.#subagents.close(error51);
22368
+ this.#gotgenesHandler = void 0;
22369
+ this.#gotgenesLatest = void 0;
21430
22370
  for (const pending of this.#pending.values()) {
21431
22371
  if (pending.timeout)
21432
22372
  clearTimeout(pending.timeout);
@@ -21462,7 +22402,7 @@ var piCommandCatalog = harnessCommandCatalogSchema.parse({
21462
22402
  ]
21463
22403
  });
21464
22404
  var DEFAULT_TOOL_OUTPUT_LIMIT = 64e3;
21465
- function isRecord9(value) {
22405
+ function isRecord10(value) {
21466
22406
  return typeof value === "object" && value !== null && !Array.isArray(value);
21467
22407
  }
21468
22408
  function errorMessage(error51) {
@@ -21477,7 +22417,9 @@ var PiAdapterFaultError = class extends Error {
21477
22417
  }
21478
22418
  };
21479
22419
  function normalizedError(error51, fallbackCode) {
21480
- if (isRecord9(error51) && error51.code === "ENOENT") {
22420
+ if (error51 instanceof PiRpcBusyError)
22421
+ return { code: "sessionBusy", message: error51.message, retryable: true };
22422
+ if (isRecord10(error51) && error51.code === "ENOENT") {
21481
22423
  return { code: "notInstalled", message: errorMessage(error51), retryable: false };
21482
22424
  }
21483
22425
  if (error51 instanceof PiAdapterFaultError)
@@ -21540,7 +22482,7 @@ function nativeModelForHistory(state2) {
21540
22482
  return nativeModelFromState(state2);
21541
22483
  }
21542
22484
  function sessionFileFromRef(ref) {
21543
- if (ref.harnessId !== piHarnessId2 || !isRecord9(ref.locator) || typeof ref.locator.sessionFile !== "string" || ref.locator.sessionFile.length === 0) {
22485
+ if (ref.harnessId !== piHarnessId2 || !isRecord10(ref.locator) || typeof ref.locator.sessionFile !== "string" || ref.locator.sessionFile.length === 0) {
21544
22486
  throw new Error("Pi Native Session Ref has no resumable Session file");
21545
22487
  }
21546
22488
  return ref.locator.sessionFile;
@@ -21555,83 +22497,29 @@ function toolFailure(toolName) {
21555
22497
  function nativeText(value) {
21556
22498
  if (typeof value === "string")
21557
22499
  return value;
21558
- if (!isRecord9(value) || !Array.isArray(value.content))
22500
+ if (!isRecord10(value) || !Array.isArray(value.content))
21559
22501
  return "";
21560
- return value.content.filter((content) => isRecord9(content) && content.type === "text" && typeof content.text === "string").map(({ text: text2 }) => text2).join("");
22502
+ return value.content.filter((content) => isRecord10(content) && content.type === "text" && typeof content.text === "string").map(({ text: text3 }) => text3).join("");
21561
22503
  }
21562
22504
  function boundedOutput(value, limit) {
21563
- const text2 = nativeText(value);
21564
- if (text2.length === 0)
22505
+ const text3 = nativeText(value);
22506
+ if (text3.length === 0)
21565
22507
  return void 0;
21566
- const truncated = text2.length > limit;
22508
+ const truncated = text3.length > limit;
21567
22509
  return {
21568
- content: [{ type: "text", text: truncated ? text2.slice(0, limit) : text2 }],
22510
+ content: [{ type: "text", text: truncated ? text3.slice(0, limit) : text3 }],
21569
22511
  ...truncated ? { truncated: true } : {}
21570
22512
  };
21571
22513
  }
21572
22514
  function outputText(output) {
21573
- return output?.content.filter((content) => content.type === "text").map(({ text: text2 }) => text2).join("") ?? "";
21574
- }
21575
- function stringField(value, key) {
21576
- if (!isRecord9(value))
21577
- return void 0;
21578
- const field2 = value[key];
21579
- if (typeof field2 === "string" && field2.length > 0)
21580
- return field2;
21581
- if (isRecord9(value.input)) {
21582
- const nested = value.input[key];
21583
- if (typeof nested === "string" && nested.length > 0)
21584
- return nested;
21585
- }
21586
- if (isRecord9(value.arguments)) {
21587
- const nested = value.arguments[key];
21588
- if (typeof nested === "string" && nested.length > 0)
21589
- return nested;
21590
- }
21591
- return void 0;
22515
+ return output?.content.filter((content) => content.type === "text").map(({ text: text3 }) => text3).join("") ?? "";
21592
22516
  }
21593
22517
  function numberField(value, key) {
21594
- if (!isRecord9(value))
22518
+ if (!isRecord10(value))
21595
22519
  return void 0;
21596
22520
  const field2 = value[key];
21597
22521
  return typeof field2 === "number" || field2 === null ? field2 : void 0;
21598
22522
  }
21599
- function normalizeToolName(name) {
21600
- const lower = name.toLowerCase();
21601
- switch (lower) {
21602
- case "bash":
21603
- case "exec":
21604
- case "terminal":
21605
- case "run":
21606
- return "bash";
21607
- case "read":
21608
- case "read_file":
21609
- case "fileread":
21610
- return "Read";
21611
- case "edit":
21612
- case "edit_file":
21613
- case "fileedit":
21614
- return "Edit";
21615
- case "write":
21616
- case "write_file":
21617
- case "filewrite":
21618
- return "Write";
21619
- case "grep":
21620
- case "grep_search":
21621
- return "Grep";
21622
- case "find":
21623
- case "glob":
21624
- case "find_files":
21625
- return "Glob";
21626
- case "todo":
21627
- return "Todo";
21628
- case "web_search":
21629
- case "websearch":
21630
- return "WebSearch";
21631
- default:
21632
- return name.length > 0 ? `${name[0]?.toUpperCase() ?? ""}${name.slice(1)}` : name;
21633
- }
21634
- }
21635
22523
  function delay(milliseconds) {
21636
22524
  return new Promise((resolve) => setTimeout(resolve, milliseconds));
21637
22525
  }
@@ -21659,6 +22547,8 @@ var PiHarnessSession = class {
21659
22547
  #configuring = false;
21660
22548
  #phase = "open";
21661
22549
  #pendingAutonomousTurns = [];
22550
+ #pendingAutonomousLifecycle = [];
22551
+ #pendingAutonomousLifecycleBytes = 0;
21662
22552
  #starting = null;
21663
22553
  #state = {};
21664
22554
  #transport = null;
@@ -21707,13 +22597,20 @@ var PiHarnessSession = class {
21707
22597
  return this.#transport?.state.sessionId === id;
21708
22598
  }
21709
22599
  async readSubagentHistory(cwd) {
21710
- if (this.#phase !== "open" || path15.resolve(cwd) !== path15.resolve(this.#cwd)) {
22600
+ if (this.#phase !== "open" || path16.resolve(cwd) !== path16.resolve(this.#cwd)) {
21711
22601
  throw new Error("Pi Subagent parent workspace or Session is unavailable");
21712
22602
  }
21713
22603
  return (await this.#ensureTransport()).getEntries();
21714
22604
  }
22605
+ async readGotgenesChild(id, cwd) {
22606
+ const history = await this.readSubagentHistory(cwd);
22607
+ const transport = this.#transport;
22608
+ if (!transport)
22609
+ throw new Error("Pi parent Session is closed");
22610
+ return readGotgenesChild(history, transport.state.sessionId, id, this.#subagents.gotgenes.records.get(id));
22611
+ }
21715
22612
  async inspectSubagent(id, cwd) {
21716
- if (this.#phase !== "open" || path15.resolve(cwd) !== path15.resolve(this.#cwd)) {
22613
+ if (this.#phase !== "open" || path16.resolve(cwd) !== path16.resolve(this.#cwd)) {
21717
22614
  throw new Error("Pi Subagent parent workspace or Session is unavailable");
21718
22615
  }
21719
22616
  const transport = await this.#ensureTransport();
@@ -21781,7 +22678,7 @@ var PiHarnessSession = class {
21781
22678
  }
21782
22679
  };
21783
22680
  }
21784
- if (this.#acceptingTurn || this.#active || this.#configuring) {
22681
+ if (this.#acceptingTurn || this.#active || this.#configuring || this.#transport?.isBusy) {
21785
22682
  return {
21786
22683
  ok: false,
21787
22684
  error: {
@@ -21791,8 +22688,8 @@ var PiHarnessSession = class {
21791
22688
  }
21792
22689
  };
21793
22690
  }
21794
- const text2 = command.input.map((input) => input.text).join("\n");
21795
- if (text2.length === 0) {
22691
+ const text3 = command.input.map((input) => input.text).join("\n");
22692
+ if (text3.length === 0) {
21796
22693
  return {
21797
22694
  ok: false,
21798
22695
  error: {
@@ -21822,6 +22719,9 @@ var PiHarnessSession = class {
21822
22719
  } catch (error51) {
21823
22720
  return { ok: false, error: normalizedError(error51, "protocolError") };
21824
22721
  }
22722
+ if (this.#active || transport.isBusy || this.#pendingAutonomousLifecycle.length > 0 || this.#pendingAutonomousTurns.length > 0) {
22723
+ return { ok: false, error: normalizedError(new PiRpcBusyError(), "sessionBusy") };
22724
+ }
21825
22725
  let resolveCompletion = () => void 0;
21826
22726
  const completion = new Promise((resolve) => {
21827
22727
  resolveCompletion = resolve;
@@ -21842,21 +22742,27 @@ var PiHarnessSession = class {
21842
22742
  interactions: /* @__PURE__ */ new Map(),
21843
22743
  interactionByNativeId: /* @__PURE__ */ new Map(),
21844
22744
  cancellationRequested: false,
22745
+ settling: false,
21845
22746
  beforeNativeTurnKeys: new Set(beforeHistory.turns.map((turn) => turn.nativeTurnRef.nativeTurnKey)),
22747
+ progressItems: /* @__PURE__ */ new Set(),
21846
22748
  completion,
21847
22749
  resolveCompletion
21848
22750
  };
21849
22751
  this.#active = active;
21850
22752
  this.#event({ type: "turn.started", turnId: command.turnId });
21851
22753
  this.#event({ type: "item.started", turnId: command.turnId, item });
21852
- void transport.runTurn(text2, (event) => this.#handleTurnEvent(active, event)).then(async (result) => {
22754
+ void transport.runTurn(text3, (event) => this.#handleTurnEvent(active, event)).then(async (result) => {
22755
+ active.settling = true;
21853
22756
  try {
21854
22757
  const identity = await this.#completedTurnIdentity(active, transport);
21855
22758
  this.#completeTurn(active, result.cancelled ? {
21856
22759
  status: "cancelled",
21857
22760
  reason: "Cancelled by user",
21858
- checkpoint: identity.checkpoint
21859
- } : { status: "succeeded", checkpoint: identity.checkpoint }, result.text, identity.nativeTurnRef);
22761
+ ...identity.checkpoint ? { checkpoint: identity.checkpoint } : {}
22762
+ } : {
22763
+ status: "succeeded",
22764
+ ...identity.checkpoint ? { checkpoint: identity.checkpoint } : {}
22765
+ }, result.text, identity.nativeTurnRef);
21860
22766
  } catch (error51) {
21861
22767
  this.#completeTurn(active, {
21862
22768
  status: "failed",
@@ -21864,6 +22770,7 @@ var PiHarnessSession = class {
21864
22770
  });
21865
22771
  }
21866
22772
  }).catch(async (error51) => {
22773
+ active.settling = true;
21867
22774
  let identity;
21868
22775
  try {
21869
22776
  identity = await this.#completedTurnIdentity(active, transport);
@@ -21872,12 +22779,14 @@ var PiHarnessSession = class {
21872
22779
  this.#completeTurn(active, {
21873
22780
  status: "failed",
21874
22781
  error: normalizedError(error51, "nativeFailure"),
21875
- ...identity ? { checkpoint: identity.checkpoint } : {}
22782
+ ...identity?.checkpoint ? { checkpoint: identity.checkpoint } : {}
21876
22783
  }, void 0, identity?.nativeTurnRef);
21877
22784
  });
21878
22785
  return { ok: true, value: { turnId: command.turnId } };
21879
22786
  } finally {
21880
22787
  this.#acceptingTurn = false;
22788
+ if (this.#transport)
22789
+ this.#drainPendingAutonomousTurns(this.#transport);
21881
22790
  }
21882
22791
  }
21883
22792
  close() {
@@ -22005,6 +22914,8 @@ var PiHarnessSession = class {
22005
22914
  return { ok: true, value: { completed: true } };
22006
22915
  } finally {
22007
22916
  this.#configuring = false;
22917
+ if (this.#transport)
22918
+ this.#drainPendingAutonomousTurns(this.#transport);
22008
22919
  }
22009
22920
  }
22010
22921
  async #selectThinking(command) {
@@ -22079,6 +22990,8 @@ var PiHarnessSession = class {
22079
22990
  return { ok: true, value: { completed: true } };
22080
22991
  } finally {
22081
22992
  this.#configuring = false;
22993
+ if (this.#transport)
22994
+ this.#drainPendingAutonomousTurns(this.#transport);
22082
22995
  }
22083
22996
  }
22084
22997
  async #cancel(command) {
@@ -22089,6 +23002,12 @@ var PiHarnessSession = class {
22089
23002
  error: invalidState("Pi Turn Cancel must reference the active Turn")
22090
23003
  };
22091
23004
  }
23005
+ if (active.settling) {
23006
+ return {
23007
+ ok: false,
23008
+ error: invalidState("Pi Turn has finished native execution and is recording its completion")
23009
+ };
23010
+ }
22092
23011
  if (active.cancellationRequested) {
22093
23012
  return { ok: true, value: { cancellationRequested: true } };
22094
23013
  }
@@ -22203,7 +23122,9 @@ var PiHarnessSession = class {
22203
23122
  interactions: /* @__PURE__ */ new Map(),
22204
23123
  interactionByNativeId: /* @__PURE__ */ new Map(),
22205
23124
  cancellationRequested: false,
23125
+ settling: false,
22206
23126
  beforeNativeTurnKeys: /* @__PURE__ */ new Set(),
23127
+ progressItems: /* @__PURE__ */ new Set(),
22207
23128
  completion,
22208
23129
  resolveCompletion
22209
23130
  };
@@ -22236,6 +23157,8 @@ var PiHarnessSession = class {
22236
23157
  return { ok: true, value: { turnId: command.turnId } };
22237
23158
  } finally {
22238
23159
  this.#acceptingTurn = false;
23160
+ if (this.#transport)
23161
+ this.#drainPendingAutonomousTurns(this.#transport);
22239
23162
  }
22240
23163
  }
22241
23164
  async #ensureTransport() {
@@ -22286,6 +23209,8 @@ var PiHarnessSession = class {
22286
23209
  return transport;
22287
23210
  }).catch(async (error51) => {
22288
23211
  this.#pendingAutonomousTurns = this.#pendingAutonomousTurns.filter((pending) => pending.transport !== transport);
23212
+ this.#pendingAutonomousLifecycle = this.#pendingAutonomousLifecycle.filter((pending) => pending.transport !== transport);
23213
+ this.#pendingAutonomousLifecycleBytes = this.#pendingAutonomousLifecycle.reduce((total, pending) => total + pending.bytes, 0);
22289
23214
  await transport.close().catch(() => void 0);
22290
23215
  if (this.#phase === "open")
22291
23216
  this.#fault(error51);
@@ -22298,6 +23223,11 @@ var PiHarnessSession = class {
22298
23223
  return starting;
22299
23224
  }
22300
23225
  #bindAutonomousTurnHandler(transport) {
23226
+ transport.setGotgenesStatusHandler?.((records, owner) => {
23227
+ if (this.#phase !== "open")
23228
+ return;
23229
+ this.#subagents.observeGotgenes(records, owner === "requested" && this.#active && !this.#active.settling ? { turnId: this.#active.command.turnId, nextItemId: () => this.#newItemId() } : void 0);
23230
+ });
22301
23231
  transport.setSubagentStatusHandler?.((runs) => {
22302
23232
  if (this.#phase !== "open")
22303
23233
  return;
@@ -22309,12 +23239,16 @@ var PiHarnessSession = class {
22309
23239
  transport.setUsageHandler?.((observation) => {
22310
23240
  if (this.#phase !== "open")
22311
23241
  return;
22312
- const record7 = piUsageRecord(observation.message, observation);
22313
- if (record7?.kind === "request")
22314
- this.#event({ type: "usage.request", request: record7.request });
22315
- else if (record7?.kind === "missing")
23242
+ const record9 = piUsageRecord(observation.message, observation);
23243
+ if (record9?.kind === "request")
23244
+ this.#event({ type: "usage.request", request: record9.request });
23245
+ else if (record9?.kind === "missing")
22316
23246
  this.#event({ type: "usage.history", complete: false });
22317
23247
  });
23248
+ if (transport.setAutonomousTurnLifecycleHandler) {
23249
+ transport.setAutonomousTurnLifecycleHandler((update) => this.#handleAutonomousLifecycle(transport, update));
23250
+ return;
23251
+ }
22318
23252
  transport.setAutonomousTurnHandler((turn) => {
22319
23253
  if (this.#phase !== "open")
22320
23254
  return;
@@ -22326,6 +23260,20 @@ var PiHarnessSession = class {
22326
23260
  });
22327
23261
  }
22328
23262
  #drainPendingAutonomousTurns(transport) {
23263
+ if (this.#phase !== "open" || this.#acceptingTurn || this.#configuring)
23264
+ return;
23265
+ for (; ; ) {
23266
+ const pending2 = this.#pendingAutonomousLifecycle[0];
23267
+ if (!pending2 || pending2.transport !== transport || this.#active && this.#active.autonomousRunId !== pending2.update.runId)
23268
+ break;
23269
+ this.#pendingAutonomousLifecycle.shift();
23270
+ this.#pendingAutonomousLifecycleBytes -= pending2.bytes;
23271
+ this.#applyAutonomousLifecycle(transport, pending2.update);
23272
+ if (this.#phase !== "open")
23273
+ return;
23274
+ }
23275
+ if (this.#active)
23276
+ return;
22329
23277
  if (this.#pendingSubagentStatus) {
22330
23278
  this.#subagents.observe(this.#pendingSubagentStatus);
22331
23279
  this.#pendingSubagentStatus = null;
@@ -22338,6 +23286,52 @@ var PiHarnessSession = class {
22338
23286
  this.#handleAutonomousTurn(transport, candidate.turn);
22339
23287
  }
22340
23288
  }
23289
+ #handleAutonomousLifecycle(transport, update) {
23290
+ if (this.#phase === "closing" && this.#transport === transport && update.type !== "started" && this.#active?.autonomousRunId === update.runId) {
23291
+ this.#applyAutonomousLifecycle(transport, update);
23292
+ return;
23293
+ }
23294
+ if (this.#phase !== "open")
23295
+ return;
23296
+ if (this.#transport !== transport || this.#acceptingTurn || this.#configuring || this.#pendingAutonomousLifecycle.length > 0 || this.#active && this.#active.autonomousRunId !== update.runId) {
23297
+ const bytes = Buffer.byteLength(JSON.stringify(update));
23298
+ if (this.#pendingAutonomousLifecycleBytes + bytes > 8 * 1024 * 1024) {
23299
+ this.#fault(new PiAdapterFaultError({
23300
+ code: "protocolError",
23301
+ message: "Pi autonomous lifecycle exceeded its ordered event buffer bound",
23302
+ retryable: false
23303
+ }));
23304
+ return;
23305
+ }
23306
+ this.#pendingAutonomousLifecycle.push({ transport, update, bytes });
23307
+ this.#pendingAutonomousLifecycleBytes += bytes;
23308
+ if (this.#transport === transport)
23309
+ this.#drainPendingAutonomousTurns(transport);
23310
+ return;
23311
+ }
23312
+ this.#applyAutonomousLifecycle(transport, update);
23313
+ }
23314
+ #applyAutonomousLifecycle(transport, update) {
23315
+ if (update.type === "started" && !this.#active) {
23316
+ this.#startAutonomousHostTurn(update.runId);
23317
+ return;
23318
+ }
23319
+ const active = this.#active;
23320
+ if (!active || active.autonomousRunId !== update.runId || update.type === "started") {
23321
+ this.#fault(new PiAdapterFaultError({
23322
+ code: "protocolError",
23323
+ message: "Pi autonomous event has no matching active run",
23324
+ retryable: false
23325
+ }));
23326
+ return;
23327
+ }
23328
+ if (update.type === "event")
23329
+ this.#handleTurnEvent(active, update.event);
23330
+ else {
23331
+ active.settling = true;
23332
+ this.#finishAutonomousHostTurn(transport, active, update.turn);
23333
+ }
23334
+ }
22341
23335
  #handleAutonomousTurn(transport, turn) {
22342
23336
  if (this.#phase !== "open")
22343
23337
  return;
@@ -22349,7 +23343,7 @@ var PiHarnessSession = class {
22349
23343
  }));
22350
23344
  return;
22351
23345
  }
22352
- if (this.#active || this.#acceptingTurn || this.#configuring) {
23346
+ if (this.#active && !this.#active.settling) {
22353
23347
  this.#fault(new PiAdapterFaultError({
22354
23348
  code: "protocolError",
22355
23349
  message: "Pi autonomous Turn overlapped another Host operation",
@@ -22357,7 +23351,22 @@ var PiHarnessSession = class {
22357
23351
  }));
22358
23352
  return;
22359
23353
  }
22360
- const turnId = hostTurnIdSchema.parse(randomUUID6());
23354
+ if (this.#active || this.#acceptingTurn || this.#configuring) {
23355
+ if (this.#pendingAutonomousTurns.length >= 128) {
23356
+ this.#fault(new PiAdapterFaultError({
23357
+ code: "protocolError",
23358
+ message: "Pi autonomous completion queue exceeded its bound",
23359
+ retryable: false
23360
+ }));
23361
+ } else
23362
+ this.#pendingAutonomousTurns.push({ transport, turn });
23363
+ return;
23364
+ }
23365
+ const active = this.#startAutonomousHostTurn();
23366
+ this.#finishAutonomousHostTurn(transport, active, turn);
23367
+ }
23368
+ #startAutonomousHostTurn(runId) {
23369
+ const turnId = hostTurnIdSchema.parse(randomUUID7());
22361
23370
  let resolveCompletion = () => void 0;
22362
23371
  const completion = new Promise((resolve) => {
22363
23372
  resolveCompletion = resolve;
@@ -22369,6 +23378,7 @@ var PiHarnessSession = class {
22369
23378
  };
22370
23379
  const active = {
22371
23380
  command: { type: "turn.start", turnId, input: [] },
23381
+ ...runId ? { autonomousRunId: runId } : {},
22372
23382
  agentItem: item,
22373
23383
  agentMessageId: null,
22374
23384
  compactionItem: null,
@@ -22378,10 +23388,19 @@ var PiHarnessSession = class {
22378
23388
  interactions: /* @__PURE__ */ new Map(),
22379
23389
  interactionByNativeId: /* @__PURE__ */ new Map(),
22380
23390
  cancellationRequested: false,
23391
+ settling: false,
22381
23392
  beforeNativeTurnKeys: /* @__PURE__ */ new Set(),
23393
+ progressItems: /* @__PURE__ */ new Set(),
22382
23394
  completion,
22383
23395
  resolveCompletion
22384
23396
  };
23397
+ this.#active = active;
23398
+ this.#event({ type: "turn.autonomous.started", turnId, input: [] });
23399
+ this.#event({ type: "turn.started", turnId });
23400
+ this.#event({ type: "item.started", turnId, item });
23401
+ return active;
23402
+ }
23403
+ #finishAutonomousHostTurn(transport, active, turn) {
22385
23404
  const nativeTurnRef = turn.nativeTurnKey ? nativeTurnRefSchema.parse({
22386
23405
  harnessId: this.harnessId,
22387
23406
  nativeSessionId: transport.state.sessionId,
@@ -22394,10 +23413,6 @@ var PiHarnessSession = class {
22394
23413
  checkpointId: nativeTurnRef.nativeTurnKey,
22395
23414
  formatVersion: 1
22396
23415
  }) : void 0;
22397
- this.#active = active;
22398
- this.#event({ type: "turn.autonomous.started", turnId, input: [] });
22399
- this.#event({ type: "turn.started", turnId });
22400
- this.#event({ type: "item.started", turnId, item });
22401
23416
  try {
22402
23417
  for (const event of turn.events)
22403
23418
  this.#handleTurnEvent(active, event);
@@ -22467,17 +23482,35 @@ var PiHarnessSession = class {
22467
23482
  if (this.#active !== active || this.#phase === "closed" || this.#phase === "faulted")
22468
23483
  return;
22469
23484
  switch (event.type) {
23485
+ case "progress.message": {
23486
+ if (active.progressItems.has(event.itemId))
23487
+ return;
23488
+ active.progressItems.add(event.itemId);
23489
+ const item = {
23490
+ type: "agentMessage",
23491
+ itemId: event.itemId,
23492
+ text: event.text,
23493
+ phase: "commentary"
23494
+ };
23495
+ this.#event({ type: "item.started", turnId: active.command.turnId, item });
23496
+ this.#completeItem(active, item, { status: "succeeded" });
23497
+ return;
23498
+ }
22470
23499
  case "text.delta":
22471
- this.#activateAgentMessage(active, event.messageId);
23500
+ this.#activateAgentMessage(active, event.messageId, event.nativeMessageIdentity);
23501
+ active.sawAssistantMessage = true;
22472
23502
  this.#appendText(active, event.delta);
22473
23503
  return;
22474
23504
  case "reasoning.delta":
22475
- this.#appendReasoning(active, event.delta);
23505
+ this.#activateAgentMessage(active, event.messageId, event.nativeMessageIdentity);
23506
+ this.#appendReasoning(active, event.delta, event.nativeMessageIdentity);
22476
23507
  return;
22477
23508
  case "reasoning.completed":
22478
23509
  this.#completeReasoning(active, { status: "succeeded" });
22479
23510
  return;
22480
23511
  case "message.completed":
23512
+ if (event.phase && active.agentMessageId === event.messageId && active.agentItem)
23513
+ active.agentItem = { ...active.agentItem, phase: event.phase };
22481
23514
  void this.#refreshUsage(active.command.turnId);
22482
23515
  return;
22483
23516
  case "compaction.started":
@@ -22535,7 +23568,7 @@ var PiHarnessSession = class {
22535
23568
  if (active.interactionByNativeId.has(request.requestId)) {
22536
23569
  throw new Error("Pi Interaction started more than once");
22537
23570
  }
22538
- const interactionId = hostInteractionIdSchema.parse(randomUUID6());
23571
+ const interactionId = hostInteractionIdSchema.parse(randomUUID7());
22539
23572
  const question = request.method === "select" ? {
22540
23573
  id: "answer",
22541
23574
  type: "choice",
@@ -22592,17 +23625,21 @@ var PiHarnessSession = class {
22592
23625
  reason
22593
23626
  });
22594
23627
  }
22595
- #activateAgentMessage(active, messageId) {
23628
+ #activateAgentMessage(active, messageId, nativeMessageIdentity2) {
22596
23629
  if (active.agentMessageId === messageId)
22597
23630
  return;
23631
+ const nativeItemId = piMessageItemId(nativeMessageIdentity2, "assistant");
23632
+ if (nativeItemId && active.agentMessageId === null && active.agentItem?.text === "") {
23633
+ this.#completeAgentItem(active, { status: "succeeded" }, true);
23634
+ }
22598
23635
  if (active.agentMessageId !== null) {
22599
23636
  this.#completeReasoning(active, { status: "succeeded" });
22600
- this.#completeAgentItem(active, { status: "succeeded" }, false);
23637
+ this.#completeAgentItem(active, { status: "succeeded" }, true);
22601
23638
  }
22602
23639
  if (!active.agentItem) {
22603
23640
  active.agentItem = {
22604
23641
  type: "agentMessage",
22605
- itemId: this.#newItemId(),
23642
+ itemId: nativeItemId ?? this.#newItemId(),
22606
23643
  text: ""
22607
23644
  };
22608
23645
  this.#event({
@@ -22612,18 +23649,17 @@ var PiHarnessSession = class {
22612
23649
  });
22613
23650
  }
22614
23651
  active.agentMessageId = messageId;
22615
- active.sawAssistantMessage = true;
22616
23652
  }
22617
- #appendText(active, text2) {
23653
+ #appendText(active, text3) {
22618
23654
  if (active.agentMessageId === null || !active.agentItem) {
22619
23655
  throw new Error("Pi Assistant text arrived outside an active message");
22620
23656
  }
22621
- active.agentItem = { ...active.agentItem, text: active.agentItem.text + text2 };
23657
+ active.agentItem = { ...active.agentItem, text: active.agentItem.text + text3 };
22622
23658
  this.#event({
22623
23659
  type: "item.updated",
22624
23660
  turnId: active.command.turnId,
22625
23661
  itemId: active.agentItem.itemId,
22626
- update: { type: "text.append", text: text2 }
23662
+ update: { type: "text.append", text: text3 }
22627
23663
  });
22628
23664
  }
22629
23665
  #completeAgentItem(active, outcome, completeEmpty) {
@@ -22634,13 +23670,13 @@ var PiHarnessSession = class {
22634
23670
  active.agentItem = null;
22635
23671
  this.#completeItem(active, item, outcome);
22636
23672
  }
22637
- #appendReasoning(active, text2) {
22638
- if (text2.length === 0)
23673
+ #appendReasoning(active, text3, nativeMessageIdentity2) {
23674
+ if (text3.length === 0)
22639
23675
  return;
22640
23676
  if (!active.reasoningItem) {
22641
23677
  active.reasoningItem = {
22642
23678
  type: "reasoning",
22643
- itemId: this.#newItemId(),
23679
+ itemId: piMessageItemId(nativeMessageIdentity2, "reasoning") ?? this.#newItemId(),
22644
23680
  text: ""
22645
23681
  };
22646
23682
  this.#event({
@@ -22651,13 +23687,13 @@ var PiHarnessSession = class {
22651
23687
  }
22652
23688
  active.reasoningItem = {
22653
23689
  ...active.reasoningItem,
22654
- text: active.reasoningItem.text + text2
23690
+ text: active.reasoningItem.text + text3
22655
23691
  };
22656
23692
  this.#event({
22657
23693
  type: "item.updated",
22658
23694
  turnId: active.command.turnId,
22659
23695
  itemId: active.reasoningItem.itemId,
22660
- update: { type: "text.append", text: text2 }
23696
+ update: { type: "text.append", text: text3 }
22661
23697
  });
22662
23698
  }
22663
23699
  #completeReasoning(active, outcome) {
@@ -22670,13 +23706,12 @@ var PiHarnessSession = class {
22670
23706
  #startTool(active, event) {
22671
23707
  if (active.tools.has(event.callId))
22672
23708
  throw new Error("Pi Tool started more than once");
22673
- const normalizedName = normalizeToolName(event.toolName);
22674
- const command = normalizedName === "bash" ? stringField(event.arguments, "command") ?? stringField(event.arguments, "cmd") ?? stringField(event.arguments, "script") ?? stringField(event.arguments, "commandLine") ?? stringField(event.arguments, "command_line") : void 0;
22675
- const item = command ? {
23709
+ const shell = piToolCommand(event.toolName, event.arguments);
23710
+ const item = shell ? {
22676
23711
  type: "commandExecution",
22677
23712
  itemId: this.#newItemId(),
22678
- command,
22679
- cwd: stringField(event.arguments, "cwd") ?? this.#cwd
23713
+ command: shell.command,
23714
+ cwd: shell.cwd ?? this.#cwd
22680
23715
  } : {
22681
23716
  type: "toolExecution",
22682
23717
  itemId: this.#newItemId(),
@@ -22794,14 +23829,17 @@ var PiHarnessSession = class {
22794
23829
  sessionId: transport.state.sessionId,
22795
23830
  model: nativeModelForHistory(transport.state)
22796
23831
  });
22797
- const created = snapshot.turns.filter((turn2) => !active.beforeNativeTurnKeys.has(turn2.nativeTurnRef.nativeTurnKey));
23832
+ const created = snapshot.turns.filter((turn2) => turn2.input.length > 0 && !active.beforeNativeTurnKeys.has(turn2.nativeTurnRef.nativeTurnKey));
22798
23833
  if (created.length !== 1) {
22799
23834
  throw new Error(`Pi Turn persisted ${created.length} new User Entries; exactly one is required`);
22800
23835
  }
22801
23836
  const turn = created[0];
22802
- if (!turn?.checkpoint)
22803
- throw new Error("Pi Turn has no terminal Checkpoint identity");
22804
- return { nativeTurnRef: turn.nativeTurnRef, checkpoint: turn.checkpoint };
23837
+ if (!turn)
23838
+ throw new Error("Pi Turn has no persisted User identity");
23839
+ return {
23840
+ nativeTurnRef: turn.nativeTurnRef,
23841
+ ...turn.checkpoint ? { checkpoint: turn.checkpoint } : {}
23842
+ };
22805
23843
  }
22806
23844
  #completeTurn(active, outcome, finalText, nativeTurnRef) {
22807
23845
  if (this.#active !== active)
@@ -22830,14 +23868,20 @@ var PiHarnessSession = class {
22830
23868
  });
22831
23869
  active.resolveCompletion();
22832
23870
  queueMicrotask(() => {
22833
- if (this.#phase === "open")
22834
- void this.#refreshUsage(active.command.turnId);
23871
+ if (this.#phase !== "open")
23872
+ return;
23873
+ if (this.#transport)
23874
+ this.#drainPendingAutonomousTurns(this.#transport);
23875
+ void this.#refreshUsage(active.command.turnId);
22835
23876
  });
22836
23877
  }
22837
23878
  #fault(error51) {
22838
23879
  if (this.#phase === "closed" || this.#phase === "faulted")
22839
23880
  return;
22840
23881
  const normalized = normalizedError(error51, "internalError");
23882
+ this.#pendingAutonomousTurns = [];
23883
+ this.#pendingAutonomousLifecycle = [];
23884
+ this.#pendingAutonomousLifecycleBytes = 0;
22841
23885
  if (this.#active) {
22842
23886
  this.#completeTurn(this.#active, { status: "failed", error: normalized });
22843
23887
  }
@@ -22846,6 +23890,9 @@ var PiHarnessSession = class {
22846
23890
  this.#channel.end();
22847
23891
  }
22848
23892
  async #close() {
23893
+ this.#pendingAutonomousTurns = [];
23894
+ this.#pendingAutonomousLifecycle = [];
23895
+ this.#pendingAutonomousLifecycleBytes = 0;
22849
23896
  if (this.#phase === "closed")
22850
23897
  return;
22851
23898
  const wasFaulted = this.#phase === "faulted";
@@ -22878,7 +23925,7 @@ var PiHarnessSession = class {
22878
23925
  this.#channel.emit({ kind: "event", event });
22879
23926
  }
22880
23927
  #newItemId() {
22881
- return hostItemIdSchema.parse(randomUUID6());
23928
+ return hostItemIdSchema.parse(randomUUID7());
22882
23929
  }
22883
23930
  };
22884
23931
  var PiAdapter = class {
@@ -22893,12 +23940,15 @@ var PiAdapter = class {
22893
23940
  if (this.#closePromise || parent.harnessId !== this.harnessId) {
22894
23941
  return { ok: false, error: invalidState("Pi Subagent parent is unavailable") };
22895
23942
  }
23943
+ const gotgenes = parseGotgenesId(nativeSubagentId);
22896
23944
  const workflow = parsePiWorkflowSubagentId(nativeSubagentId);
22897
- if (!workflow)
23945
+ if (!workflow && !gotgenes)
22898
23946
  parsePiSubagentId(nativeSubagentId);
22899
23947
  const live = [...this.#sessions].find((session) => session.ownsNativeSession(parent.nativeSessionId));
22900
23948
  let reply;
22901
23949
  if (live) {
23950
+ if (gotgenes)
23951
+ return await live.readGotgenesChild(gotgenes, cwd);
22902
23952
  if (workflow)
22903
23953
  return await readPiWorkflowChild(await live.readSubagentHistory(cwd), parent.nativeSessionId, workflow);
22904
23954
  reply = await live.inspectSubagent(nativeSubagentId, cwd);
@@ -22910,6 +23960,8 @@ var PiAdapter = class {
22910
23960
  if (transport.state.sessionId !== parent.nativeSessionId)
22911
23961
  throw new Error("Pi Subagent parent identity mismatch");
22912
23962
  await transport.verifySessionCwd(cwd);
23963
+ if (gotgenes)
23964
+ return await readGotgenesChild(await transport.getEntries(), parent.nativeSessionId, gotgenes);
22913
23965
  if (workflow)
22914
23966
  return await readPiWorkflowChild(await transport.getEntries(), parent.nativeSessionId, workflow);
22915
23967
  if (!transport.inspectSubagent)