@codexhost/cli-darwin-arm64 0.16.1 → 0.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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, path18) {
1321
+ if (!path18)
1322
1322
  return obj;
1323
- return path16.reduce((acc, key) => acc?.[key], obj);
1323
+ return path18.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(path18, 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(path18);
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, path18 = []) => {
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 }, [...path18, ...issue2.path]));
1887
1887
  } else if (issue2.code === "invalid_key") {
1888
- processError({ issues: issue2.issues }, [...path16, ...issue2.path]);
1888
+ processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
1889
1889
  } else if (issue2.code === "invalid_element") {
1890
- processError({ issues: issue2.issues }, [...path16, ...issue2.path]);
1890
+ processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
1891
1891
  } else {
1892
- const fullpath = [...path16, ...issue2.path];
1892
+ const fullpath = [...path18, ...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, path18 = []) => {
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 }, [...path18, ...issue2.path]));
1924
1924
  } else if (issue2.code === "invalid_key") {
1925
- processError({ issues: issue2.issues }, [...path16, ...issue2.path]);
1925
+ processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
1926
1926
  } else if (issue2.code === "invalid_element") {
1927
- processError({ issues: issue2.issues }, [...path16, ...issue2.path]);
1927
+ processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
1928
1928
  } else {
1929
- const fullpath = [...path16, ...issue2.path];
1929
+ const fullpath = [...path18, ...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 path18 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1962
+ for (const seg of path18) {
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 = (text4) => {
8193
+ return text4.charAt(0).toUpperCase() + text4.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 path18 = ref.slice(1).split("/").filter(Boolean);
14655
+ if (path18.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 (path18[0] === defsKey) {
14660
+ const key = path18[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((text4) => text4.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((text4) => text4.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),
@@ -16719,8 +16719,8 @@ async function readCandidate(file2, signal) {
16719
16719
  const message3 = isRecord(entry.message) ? entry.message : null;
16720
16720
  if (!firstMessage && entry.type === "message" && message3?.role === "user") {
16721
16721
  const content = message3.content;
16722
- 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(" ") : "";
16723
- firstMessage = sessionImportTitle(text2);
16722
+ const text4 = 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(text4);
16724
16724
  }
16725
16725
  hasUser = entry.type === "message" && message3?.role === "user" || typeof entry.parentId === "string" && entries.get(entry.parentId) === true;
16726
16726
  entries.set(entry.id, hasUser);
@@ -17233,8 +17233,8 @@ function liveHarnessCommandPrompt(catalog, idPrefix, commandId, argumentText) {
17233
17233
  const descriptor = catalog.commands.find(({ id }) => id === commandId);
17234
17234
  if (!descriptor)
17235
17235
  return null;
17236
- const text2 = typeof argumentText === "string" ? argumentText.trim() : "";
17237
- return text2 ? `${descriptor.invocation} ${text2}` : descriptor.invocation;
17236
+ const text4 = typeof argumentText === "string" ? argumentText.trim() : "";
17237
+ return text4 ? `${descriptor.invocation} ${text4}` : descriptor.invocation;
17238
17238
  }
17239
17239
  function mergeLiveHarnessCommands(builtIns, idPrefix, live, exclusions = {}) {
17240
17240
  if (!live)
@@ -17370,16 +17370,16 @@ var Diff = class {
17370
17370
  }
17371
17371
  }
17372
17372
  }
17373
- addToPath(path16, added, removed, oldPosInc, options) {
17374
- const last = path16.lastComponent;
17373
+ addToPath(path18, added, removed, oldPosInc, options) {
17374
+ const last = path18.lastComponent;
17375
17375
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
17376
17376
  return {
17377
- oldPos: path16.oldPos + oldPosInc,
17377
+ oldPos: path18.oldPos + oldPosInc,
17378
17378
  lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
17379
17379
  };
17380
17380
  } else {
17381
17381
  return {
17382
- oldPos: path16.oldPos + oldPosInc,
17382
+ oldPos: path18.oldPos + oldPosInc,
17383
17383
  lastComponent: { count: 1, added, removed, previousComponent: last }
17384
17384
  };
17385
17385
  }
@@ -17779,9 +17779,9 @@ function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader
17779
17779
  } }));
17780
17780
  }
17781
17781
  }
17782
- function splitLines(text2) {
17783
- const hasTrailingNl = text2.endsWith("\n");
17784
- const result = text2.split("\n").map((line) => line + "\n");
17782
+ function splitLines(text4) {
17783
+ const hasTrailingNl = text4.endsWith("\n");
17784
+ const result = text4.split("\n").map((line) => line + "\n");
17785
17785
  if (hasTrailingNl) {
17786
17786
  result.pop();
17787
17787
  } else {
@@ -18015,11 +18015,344 @@ function piNestedCallFileChanges(nestedCalls, cwd) {
18015
18015
  return projected;
18016
18016
  }
18017
18017
 
18018
- // dist/pi-subagents.js
18018
+ // dist/pi-message-item-id.js
18019
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
+ };
18020
18353
 
18021
18354
  // dist/pi-subagent-workflow.js
18022
- var PREFIX = "pi-subagents-workflow-v1:";
18355
+ var PREFIX2 = "pi-subagents-workflow-v1:";
18023
18356
  var STATES = {
18024
18357
  pending: "pending",
18025
18358
  running: "running",
@@ -18033,7 +18366,7 @@ var STATES = {
18033
18366
  function record2(value) {
18034
18367
  return typeof value === "object" && value !== null && !Array.isArray(value);
18035
18368
  }
18036
- function text(value, limit = 256) {
18369
+ function text2(value, limit = 256) {
18037
18370
  return typeof value === "string" && value.length > 0 && value.length <= limit;
18038
18371
  }
18039
18372
  function piWorkflowSummary(result) {
@@ -18041,15 +18374,15 @@ function piWorkflowSummary(result) {
18041
18374
  return null;
18042
18375
  const details = result.details;
18043
18376
  const summary = details.workflowChildren;
18044
- 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)
18045
18378
  return null;
18046
18379
  const children = [];
18047
18380
  const seen = /* @__PURE__ */ new Set();
18048
18381
  for (const child of summary.children) {
18049
- 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))
18050
18383
  return null;
18051
18384
  for (const key of ["agent", "sessionName", "model", "thinking"]) {
18052
- if (child[key] !== void 0 && !text(child[key], 2048))
18385
+ if (child[key] !== void 0 && !text2(child[key], 2048))
18053
18386
  return null;
18054
18387
  }
18055
18388
  const mappedState = STATES[child.state];
@@ -18073,15 +18406,15 @@ function piWorkflowSummary(result) {
18073
18406
  };
18074
18407
  }
18075
18408
  function piWorkflowSubagentId(address) {
18076
- 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");
18077
18410
  }
18078
18411
  function parsePiWorkflowSubagentId(id) {
18079
- if (!id.startsWith(PREFIX))
18412
+ if (!id.startsWith(PREFIX2))
18080
18413
  return null;
18081
18414
  if (id.length > 3e3)
18082
18415
  throw new Error("Invalid Pi workflow child identity");
18083
- const value = JSON.parse(Buffer.from(id.slice(PREFIX.length), "base64url").toString("utf8"));
18084
- 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]))
18085
18418
  throw new Error("Invalid Pi workflow child identity");
18086
18419
  const address = { workflowRunId: value[0], childId: value[1] };
18087
18420
  if (piWorkflowSubagentId(address) !== id)
@@ -18239,8 +18572,13 @@ var PiSubagents = class {
18239
18572
  #children = /* @__PURE__ */ new Map();
18240
18573
  #active = /* @__PURE__ */ new Map();
18241
18574
  #waiting = /* @__PURE__ */ new Map();
18575
+ gotgenes;
18242
18576
  constructor(emit) {
18243
18577
  this.emit = emit;
18578
+ this.gotgenes = new GotgenesSubagents(emit);
18579
+ }
18580
+ observeGotgenes(records, activeTurn) {
18581
+ this.gotgenes.observe(records, true, activeTurn, true);
18244
18582
  }
18245
18583
  observe(runs) {
18246
18584
  this.#apply(runs, true);
@@ -18294,6 +18632,9 @@ var PiSubagents = class {
18294
18632
  }
18295
18633
  }
18296
18634
  project(toolName, result, itemId2, callId) {
18635
+ const gotgenes = this.gotgenes.project(toolName, result, itemId2);
18636
+ if (gotgenes)
18637
+ return gotgenes;
18297
18638
  const workflow = toolName === "subagent" ? piWorkflowSummary(result) : null;
18298
18639
  if (workflow && (!callId || workflow.parentToolCallId === callId))
18299
18640
  return projectPiWorkflow(workflow, itemId2);
@@ -18304,6 +18645,8 @@ var PiSubagents = class {
18304
18645
  return children.length ? { type: "subagentDelegation", itemId: itemId2, operation: "spawn", subagents: children } : null;
18305
18646
  }
18306
18647
  start(turnId, toolName, result, itemId2, callId) {
18648
+ if (this.gotgenes.start(turnId, toolName, result, itemId2))
18649
+ return;
18307
18650
  const workflow = toolName === "subagent" ? piWorkflowSummary(result) : null;
18308
18651
  if (workflow && (!callId || workflow.parentToolCallId === callId)) {
18309
18652
  const key = `workflow:${workflow.workflowRunId}`;
@@ -18349,6 +18692,7 @@ var PiSubagents = class {
18349
18692
  this.emit({ type: "item.started", turnId, item });
18350
18693
  }
18351
18694
  finish(turnId) {
18695
+ this.gotgenes.finish(turnId);
18352
18696
  for (const [runId, waiting] of this.#waiting) {
18353
18697
  if (waiting.turnId === turnId)
18354
18698
  this.#waiting.delete(runId);
@@ -18396,15 +18740,15 @@ ${entry.text}`);
18396
18740
  nativeTurnRef: nativeTurnRefSchema.parse({
18397
18741
  harnessId: "pi",
18398
18742
  nativeSessionId: parentSessionId,
18399
- nativeTurnKey: `pi-subagent-${createHash("sha256").update(id).digest("hex")}`,
18743
+ nativeTurnKey: `pi-subagent-${createHash3("sha256").update(id).digest("hex")}`,
18400
18744
  formatVersion: 1
18401
18745
  }),
18402
18746
  input: reply.task ? [{ type: "text", text: reply.task }] : [],
18403
- items: texts.map((text2, index) => ({
18747
+ items: texts.map((text4, index) => ({
18404
18748
  item: {
18405
18749
  type: "agentMessage",
18406
- text: text2,
18407
- itemId: hostItemIdSchema.parse(`pi-subagent-${createHash("sha256").update(`${id}:${index}:${text2}`).digest("hex")}`)
18750
+ text: text4,
18751
+ itemId: hostItemIdSchema.parse(`pi-subagent-${createHash3("sha256").update(`${id}:${index}:${text4}`).digest("hex")}`)
18408
18752
  },
18409
18753
  outcome: { status: "succeeded" }
18410
18754
  })),
@@ -18552,22 +18896,149 @@ function normalizePiModelCatalog(nativeModels, effectiveModel, thinkingLevels, e
18552
18896
  });
18553
18897
  }
18554
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(text4) {
18912
+ const limit = 64e3;
18913
+ return text4.length <= limit ? text4 : `${text4.slice(0, limit)}
18914
+ [Pi notification truncated]`;
18915
+ }
18916
+ function visibleText(text4) {
18917
+ return text4.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 text4 = textContent(value.content);
18939
+ if (text4.trim().length === 0)
18940
+ return null;
18941
+ return JSON.stringify([value.customType, text4]);
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, text4] = 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, text4)}`)
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
+
18555
19026
  // dist/pi-history.js
18556
19027
  var piHarnessId = harnessIdSchema.parse("pi");
18557
- function isRecord4(value) {
19028
+ function isRecord5(value) {
18558
19029
  return typeof value === "object" && value !== null && !Array.isArray(value);
18559
19030
  }
18560
- function textContent(value) {
19031
+ function textContent2(value) {
18561
19032
  if (typeof value === "string")
18562
19033
  return value;
18563
19034
  if (!Array.isArray(value))
18564
19035
  return "";
18565
- 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("");
18566
19037
  }
18567
19038
  function thinkingContent(value) {
18568
19039
  if (!Array.isArray(value))
18569
19040
  return "";
18570
- 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("");
18571
19042
  }
18572
19043
  function validatedEntry(value) {
18573
19044
  if (typeof value.id !== "string" || value.id.length === 0 || value.parentId !== null && typeof value.parentId !== "string" || typeof value.type !== "string") {
@@ -18598,7 +19069,7 @@ function activePiEntries(history) {
18598
19069
  return reversed.reverse();
18599
19070
  }
18600
19071
  function message(entry) {
18601
- return entry.type === "message" && isRecord4(entry.message) ? entry.message : null;
19072
+ return entry.type === "message" && isRecord5(entry.message) ? entry.message : null;
18602
19073
  }
18603
19074
  function messageRole(entry) {
18604
19075
  const value = message(entry)?.role;
@@ -18613,7 +19084,7 @@ function assistantOutcome(entries) {
18613
19084
  if (!final)
18614
19085
  return { status: "unknown", reason: "Pi history has no Assistant terminal" };
18615
19086
  const stopReason = final.stopReason;
18616
- if (stopReason === "aborted") {
19087
+ if (piAssistantWasAborted(final)) {
18617
19088
  return { status: "cancelled", reason: "Pi Assistant was aborted" };
18618
19089
  }
18619
19090
  if (stopReason === "error") {
@@ -18626,7 +19097,7 @@ function assistantOutcome(entries) {
18626
19097
  }
18627
19098
  };
18628
19099
  }
18629
- if (typeof stopReason === "string" || textContent(final.content).length > 0) {
19100
+ if (typeof stopReason === "string" || textContent2(final.content).length > 0) {
18630
19101
  return { status: "succeeded" };
18631
19102
  }
18632
19103
  return { status: "unknown", reason: "Pi Assistant terminal is not classifiable" };
@@ -18643,8 +19114,8 @@ function itemOutcome(outcome) {
18643
19114
  return { status: "succeeded" };
18644
19115
  }
18645
19116
  function toolOutput(value) {
18646
- const text2 = textContent(value);
18647
- return text2.length > 0 ? { content: [{ type: "text", text: text2 }] } : void 0;
19117
+ const text4 = textContent2(value);
19118
+ return text4.length > 0 ? { content: [{ type: "text", text: text4 }] } : void 0;
18648
19119
  }
18649
19120
  function historicalFileChanges(call, nativeMessage, toolItemId, cwd) {
18650
19121
  const items = [];
@@ -18667,37 +19138,52 @@ function historicalFileChanges(call, nativeMessage, toolItemId, cwd) {
18667
19138
  }
18668
19139
  return items;
18669
19140
  }
18670
- function snapshotItems(entries, outcome, subagents, cwd) {
19141
+ function snapshotItems(entries, messageIdentities, notices, outcome, subagents, cwd) {
18671
19142
  const snapshots = [];
18672
19143
  const toolCalls = /* @__PURE__ */ new Map();
18673
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
+ }
18674
19158
  const nativeMessage = message(entry);
18675
19159
  if (!nativeMessage)
18676
19160
  continue;
18677
19161
  const content = Array.isArray(nativeMessage.content) ? nativeMessage.content : [];
18678
19162
  if (nativeMessage.role === "assistant") {
18679
- const text2 = textContent(content);
19163
+ const text4 = textContent2(content);
18680
19164
  const reasoning = thinkingContent(content);
18681
19165
  let projectedText = false;
18682
19166
  let projectedReasoning = false;
18683
19167
  for (const [ordinal, part] of content.entries()) {
18684
- if (!isRecord4(part))
19168
+ if (!isRecord5(part))
18685
19169
  continue;
18686
19170
  if (part.type === "thinking" && !projectedReasoning && reasoning.length > 0) {
18687
19171
  const item2 = {
18688
19172
  type: "reasoning",
18689
- itemId: itemId(entry.id, "reasoning", 0),
19173
+ itemId: piMessageItemId(messageIdentities.get(entry.id), "reasoning") ?? itemId(entry.id, "reasoning", 0),
18690
19174
  text: reasoning
18691
19175
  };
18692
19176
  snapshots.push({ item: item2, outcome: itemOutcome(outcome) });
18693
19177
  projectedReasoning = true;
18694
19178
  continue;
18695
19179
  }
18696
- if (part.type === "text" && !projectedText && text2.length > 0) {
19180
+ if (part.type === "text" && !projectedText && text4.length > 0) {
19181
+ const phase = piAssistantPhase(nativeMessage);
18697
19182
  const item2 = {
18698
19183
  type: "agentMessage",
18699
- itemId: itemId(entry.id, "assistant", 0),
18700
- text: text2
19184
+ itemId: piMessageItemId(messageIdentities.get(entry.id), "assistant") ?? itemId(entry.id, "assistant", 0),
19185
+ text: text4,
19186
+ ...phase ? { phase } : {}
18701
19187
  };
18702
19188
  snapshots.push({ item: item2, outcome: itemOutcome(outcome) });
18703
19189
  projectedText = true;
@@ -18725,9 +19211,24 @@ function snapshotItems(entries, outcome, subagents, cwd) {
18725
19211
  if (!call || call.name !== nativeMessage.toolName)
18726
19212
  continue;
18727
19213
  const output = toolOutput(nativeMessage.content);
18728
- const item = {
18729
- 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 = {
18730
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",
18731
19232
  toolName: call.name,
18732
19233
  arguments: call.arguments,
18733
19234
  ...output ? { output } : {}
@@ -18758,6 +19259,10 @@ function snapshotItems(entries, outcome, subagents, cwd) {
18758
19259
  function modelChange(entry) {
18759
19260
  return entry.type === "model_change" && typeof entry.provider === "string" && typeof entry.modelId === "string" ? { provider: entry.provider, id: entry.modelId } : null;
18760
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
+ }
18761
19266
  function turnStarts(active) {
18762
19267
  const starts = [];
18763
19268
  let terminal = true;
@@ -18765,6 +19270,8 @@ function turnStarts(active) {
18765
19270
  for (const [index, entry] of active.entries()) {
18766
19271
  const role = messageRole(entry);
18767
19272
  if (role === "user") {
19273
+ if (pending && isEmptyWakeup(entry))
19274
+ continue;
18768
19275
  starts.push({ entry, index });
18769
19276
  pending = null;
18770
19277
  terminal = false;
@@ -18781,6 +19288,8 @@ function turnStarts(active) {
18781
19288
  }
18782
19289
  function mapPiSnapshot(history, state2, subagents = new PiSubagents(() => void 0)) {
18783
19290
  const active = activePiEntries(history);
19291
+ const { identities } = piHistoryMessageIdentities(state2.sessionId, active);
19292
+ const { notices } = piHistoryNotices(state2.sessionId, active);
18784
19293
  const turns = [];
18785
19294
  const starts = turnStarts(active);
18786
19295
  const byIndex = new Map(starts.map((start, ordinal) => [start.index, ordinal]));
@@ -18802,7 +19311,7 @@ function mapPiSnapshot(history, state2, subagents = new PiSubagents(() => void 0
18802
19311
  const end = next?.index ?? active.length;
18803
19312
  const entries = active.slice(index, end);
18804
19313
  const outcome = assistantOutcome(entries);
18805
- const userText = textContent(message(user)?.content);
19314
+ const userText = textContent2(message(user)?.content);
18806
19315
  const nativeTurnRef = nativeTurnRefSchema.parse({
18807
19316
  harnessId: piHarnessId,
18808
19317
  nativeSessionId: state2.sessionId,
@@ -18819,7 +19328,7 @@ function mapPiSnapshot(history, state2, subagents = new PiSubagents(() => void 0
18819
19328
  nativeTurnRef,
18820
19329
  ...!next || messageRole(next.entry) === "user" ? { checkpoint } : {},
18821
19330
  input: messageRole(user) === "user" ? [{ type: "text", text: userText }] : [],
18822
- items: snapshotItems(entries, outcome, subagents, state2.cwd),
19331
+ items: snapshotItems(entries, identities, notices, outcome, subagents, state2.cwd),
18823
19332
  outcome,
18824
19333
  ...effectiveModel ? { model: encodePiModelRef(effectiveModel) } : {}
18825
19334
  });
@@ -18854,14 +19363,14 @@ function resolvePiForkBoundary(history, checkpointId) {
18854
19363
  }
18855
19364
 
18856
19365
  // dist/pi-usage.js
18857
- function isRecord5(value) {
19366
+ function isRecord6(value) {
18858
19367
  return typeof value === "object" && value !== null && !Array.isArray(value);
18859
19368
  }
18860
19369
  function nonNegativeSafeInteger(value) {
18861
19370
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : null;
18862
19371
  }
18863
19372
  function optionalPiCacheHitRatePercent(value) {
18864
- if (!isRecord5(value) || value.role !== "assistant" || !isRecord5(value.usage))
19373
+ if (!isRecord6(value) || value.role !== "assistant" || !isRecord6(value.usage))
18865
19374
  return null;
18866
19375
  const input = nonNegativeSafeInteger(value.usage.input);
18867
19376
  const cacheRead = nonNegativeSafeInteger(value.usage.cacheRead);
@@ -18874,20 +19383,20 @@ function optionalPiCacheHitRatePercent(value) {
18874
19383
  function latestPiCacheHitRatePercent(history) {
18875
19384
  let latest = null;
18876
19385
  for (const entry of activePiEntries(history)) {
18877
- if (entry.type === "message" && isRecord5(entry.message) && entry.message.role === "assistant") {
19386
+ if (entry.type === "message" && isRecord6(entry.message) && entry.message.role === "assistant") {
18878
19387
  latest = optionalPiCacheHitRatePercent(entry.message);
18879
19388
  }
18880
19389
  }
18881
19390
  return latest;
18882
19391
  }
18883
19392
  function responseData(response, operation) {
18884
- if (!isRecord5(response.data)) {
19393
+ if (!isRecord6(response.data)) {
18885
19394
  throw new Error(`Pi RPC ${operation} response has no data`);
18886
19395
  }
18887
19396
  return response.data;
18888
19397
  }
18889
19398
  function contextUsage(value) {
18890
- if (!isRecord5(value))
19399
+ if (!isRecord6(value))
18891
19400
  throw new Error("Pi RPC context Usage is invalid");
18892
19401
  return parseHostUsage({
18893
19402
  contextUsedTokens: value.tokens,
@@ -18897,15 +19406,15 @@ function contextUsage(value) {
18897
19406
  function parsePiSessionUsage(response) {
18898
19407
  const data = responseData(response, "Session stats");
18899
19408
  const tokens = data.tokens;
18900
- if (tokens !== void 0 && !isRecord5(tokens)) {
19409
+ if (tokens !== void 0 && !isRecord6(tokens)) {
18901
19410
  throw new Error("Pi RPC Session stats tokens are invalid");
18902
19411
  }
18903
19412
  return parseHostUsage({
18904
- ...isRecord5(tokens) && tokens.input !== void 0 ? { inputTokens: tokens.input } : {},
18905
- ...isRecord5(tokens) && tokens.cacheRead !== void 0 ? { cachedInputTokens: tokens.cacheRead } : {},
18906
- ...isRecord5(tokens) && tokens.cacheWrite !== void 0 ? { cacheWriteInputTokens: tokens.cacheWrite } : {},
18907
- ...isRecord5(tokens) && tokens.output !== void 0 ? { outputTokens: tokens.output } : {},
18908
- ...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 } : {},
18909
19418
  ...data.cost !== void 0 ? { totalCostUsd: data.cost } : {},
18910
19419
  ...data.contextUsage !== void 0 ? contextUsage(data.contextUsage) : {}
18911
19420
  });
@@ -18924,9 +19433,9 @@ function optionalPiStateContextUsage(value) {
18924
19433
  }
18925
19434
  }
18926
19435
  function piUsageRecord(message3, extra = {}) {
18927
- if (!isRecord5(message3) || message3.role !== "assistant")
19436
+ if (!isRecord6(message3) || message3.role !== "assistant")
18928
19437
  return null;
18929
- const usage = isRecord5(message3.usage) ? message3.usage : null;
19438
+ const usage = isRecord6(message3.usage) ? message3.usage : null;
18930
19439
  const input = nonNegativeSafeInteger(usage?.input);
18931
19440
  const output = nonNegativeSafeInteger(usage?.output);
18932
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;
@@ -18963,17 +19472,17 @@ function piUsageHistory(history) {
18963
19472
  for (const entry of history.entries) {
18964
19473
  if (entry.type !== "message")
18965
19474
  continue;
18966
- const record7 = piUsageRecord(entry.message, { historical: true });
18967
- if (record7?.kind === "request")
18968
- requests.push(record7.request);
18969
- 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")
18970
19479
  complete = false;
18971
19480
  }
18972
19481
  return { requests, complete };
18973
19482
  }
18974
19483
 
18975
19484
  // dist/pi-usage-statistics.js
18976
- function isRecord6(value) {
19485
+ function isRecord7(value) {
18977
19486
  return typeof value === "object" && value !== null && !Array.isArray(value);
18978
19487
  }
18979
19488
  function piUserText(content) {
@@ -18981,11 +19490,11 @@ function piUserText(content) {
18981
19490
  return content;
18982
19491
  if (!Array.isArray(content))
18983
19492
  return void 0;
18984
- 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(" ");
18985
19494
  }
18986
19495
  async function readPiUsage(file2, signal) {
18987
19496
  const entries = [];
18988
- const header = await jsonlHeader(file2, (record7) => record7.type === "session", signal);
19497
+ const header = await jsonlHeader(file2, (record9) => record9.type === "session", signal);
18989
19498
  let name;
18990
19499
  const session = {
18991
19500
  sessionId: typeof header?.id === "string" ? header.id : void 0,
@@ -19002,11 +19511,11 @@ async function readPiUsage(file2, signal) {
19002
19511
  if (!name && message3?.role === "user") {
19003
19512
  name = usageSessionTitle(piUserText(message3.content));
19004
19513
  }
19005
- const record7 = piUsageRecord(line.message);
19006
- if (record7?.kind !== "request")
19514
+ const record9 = piUsageRecord(line.message);
19515
+ if (record9?.kind !== "request")
19007
19516
  continue;
19008
19517
  const at = nativeTimeMs(message3.timestamp) ?? nativeTimeMs(line.timestamp);
19009
- const entry = at !== null && usageEntryFromRequest(record7.request, at);
19518
+ const entry = at !== null && usageEntryFromRequest(record9.request, at);
19010
19519
  if (!entry)
19011
19520
  continue;
19012
19521
  if (!(typeof message3.responseId === "string" && message3.responseId.length > 0)) {
@@ -19027,9 +19536,9 @@ function createPiUsageStatistics(environment) {
19027
19536
  }
19028
19537
 
19029
19538
  // dist/account-balance.js
19030
- import { readFile } from "node:fs/promises";
19031
- import { homedir as homedir2 } from "node:os";
19032
- 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";
19033
19542
  var DEEPSEEK_BALANCE_ENDPOINT = "https://api.deepseek.com/user/balance";
19034
19543
  var SUB2API_USAGE_PATH = "/v1/usage";
19035
19544
  var REQUEST_TIMEOUT_MS = 1e4;
@@ -19038,18 +19547,18 @@ function agentDirectory(environment) {
19038
19547
  const configured = environment.PI_CODING_AGENT_DIR?.trim();
19039
19548
  if (configured)
19040
19549
  return configured;
19041
- return path7.join(environment.HOME ?? environment.USERPROFILE ?? homedir2(), ".pi", "agent");
19550
+ return path8.join(environment.HOME ?? environment.USERPROFILE ?? homedir3(), ".pi", "agent");
19042
19551
  }
19043
- 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 : {};
19044
19553
  async function deepSeekApiKey(environment) {
19045
- const auth = record4(JSON.parse(await readFile(path7.join(agentDirectory(environment), "auth.json"), "utf8")));
19046
- 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);
19047
19556
  if (deepseek.type !== "api_key")
19048
19557
  return void 0;
19049
19558
  return typeof deepseek.key === "string" && deepseek.key.trim() ? deepseek.key : void 0;
19050
19559
  }
19051
19560
  function projectSub2ApiUsage(payload, providerId) {
19052
- const data = record4(payload);
19561
+ const data = record6(payload);
19053
19562
  if (data.isValid === false)
19054
19563
  return null;
19055
19564
  if (data.mode !== "unrestricted" && data.mode !== "quota_limited")
@@ -19059,7 +19568,7 @@ function projectSub2ApiUsage(payload, providerId) {
19059
19568
  return null;
19060
19569
  const wallet = finiteAmount(data.balance);
19061
19570
  const remaining = finiteAmount(data.remaining);
19062
- const quotaRemaining = finiteAmount(record4(data.quota).remaining);
19571
+ const quotaRemaining = finiteAmount(record6(data.quota).remaining);
19063
19572
  const amount = wallet ?? remaining ?? quotaRemaining;
19064
19573
  if (amount === null)
19065
19574
  return null;
@@ -19079,10 +19588,10 @@ function finiteAmount(value) {
19079
19588
  return Number.isFinite(amount) && amount >= 0 ? amount : null;
19080
19589
  }
19081
19590
  function projectDeepSeekBalance(payload) {
19082
- const data = record4(payload);
19591
+ const data = record6(payload);
19083
19592
  if (!Array.isArray(data.balance_infos))
19084
19593
  return null;
19085
- const first = record4(data.balance_infos[0]);
19594
+ const first = record6(data.balance_infos[0]);
19086
19595
  const amount = finiteAmount(first.total_balance);
19087
19596
  const currency = typeof first.currency === "string" ? first.currency.trim() : "";
19088
19597
  if (amount === null || !currency)
@@ -19111,11 +19620,11 @@ function usageEndpoint(baseUrl) {
19111
19620
  }
19112
19621
  async function configuredSub2ApiProviders(environment) {
19113
19622
  try {
19114
- const models = record4(JSON.parse(await readFile(path7.join(agentDirectory(environment), "models.json"), "utf8")));
19115
- 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);
19116
19625
  const found = [];
19117
19626
  for (const [id, definition] of Object.entries(providers)) {
19118
- const provider = record4(definition);
19627
+ const provider = record6(definition);
19119
19628
  const apiKey = typeof provider.apiKey === "string" ? provider.apiKey.trim() : "";
19120
19629
  const baseUrl = typeof provider.baseUrl === "string" ? provider.baseUrl.trim() : "";
19121
19630
  if (!id.trim() || id.length > 128 || !apiKey || !usageEndpoint(baseUrl))
@@ -19173,21 +19682,21 @@ async function fetchPiAccountBalance(input) {
19173
19682
  }
19174
19683
 
19175
19684
  // dist/pi-credential-imports.js
19176
- import { randomUUID } from "node:crypto";
19685
+ import { randomUUID as randomUUID2 } from "node:crypto";
19177
19686
  import { execFile as execFile2 } from "node:child_process";
19178
19687
  import { promisify } from "node:util";
19179
19688
  import { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync, readdirSync, lstatSync, renameSync, rmdirSync } from "node:fs";
19180
19689
  import { realpath as realpath2 } from "node:fs/promises";
19181
19690
  import os4 from "node:os";
19182
- import path9 from "node:path";
19691
+ import path10 from "node:path";
19183
19692
  import { pathToFileURL } from "node:url";
19184
19693
 
19185
19694
  // dist/command.js
19186
19695
  import fs2 from "node:fs";
19187
- import { homedir as homedir3, tmpdir as tmpdir2 } from "node:os";
19188
- import path8 from "node:path";
19696
+ import { homedir as homedir4, tmpdir as tmpdir2 } from "node:os";
19697
+ import path9 from "node:path";
19189
19698
  var PI_PACKAGE_NAME = "@earendil-works/pi-coding-agent";
19190
- 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");
19191
19700
  var piDiscoverySpec = {
19192
19701
  id: "pi",
19193
19702
  command: "pi",
@@ -19213,18 +19722,18 @@ function resolvePiExecutable(input, dependencies = {}) {
19213
19722
  return resolution?.executable ?? input.command ?? input.environment.PI_COMMAND ?? "pi";
19214
19723
  }
19215
19724
  function findPiPackageDirectory(executable) {
19216
- let directory = path8.dirname(executable);
19725
+ let directory = path9.dirname(executable);
19217
19726
  while (true) {
19218
- for (const candidate of [directory, path8.join(directory, PI_PACKAGE_PATH)]) {
19727
+ for (const candidate of [directory, path9.join(directory, PI_PACKAGE_PATH)]) {
19219
19728
  try {
19220
- 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"));
19221
19730
  if (typeof manifest === "object" && manifest !== null && "name" in manifest && manifest.name === PI_PACKAGE_NAME) {
19222
19731
  return candidate;
19223
19732
  }
19224
19733
  } catch {
19225
19734
  }
19226
19735
  }
19227
- const parent = path8.dirname(directory);
19736
+ const parent = path9.dirname(directory);
19228
19737
  if (parent === directory)
19229
19738
  return void 0;
19230
19739
  directory = parent;
@@ -19232,16 +19741,16 @@ function findPiPackageDirectory(executable) {
19232
19741
  }
19233
19742
  function findPiCliEntry(packageDirectory) {
19234
19743
  try {
19235
- 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"));
19236
19745
  if (typeof manifest !== "object" || manifest === null || !("bin" in manifest))
19237
19746
  return void 0;
19238
19747
  const bin = manifest.bin;
19239
19748
  const entry = typeof bin === "string" ? bin : typeof bin === "object" && bin !== null && "pi" in bin ? bin.pi : void 0;
19240
19749
  if (typeof entry !== "string" || !entry.trim())
19241
19750
  return void 0;
19242
- const resolved = path8.resolve(packageDirectory, entry);
19243
- const relative = path8.relative(packageDirectory, resolved);
19244
- 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()) {
19245
19754
  return void 0;
19246
19755
  }
19247
19756
  return resolved;
@@ -19250,11 +19759,11 @@ function findPiCliEntry(packageDirectory) {
19250
19759
  }
19251
19760
  }
19252
19761
  function isFilesystemRoot(cwd) {
19253
- const resolved = path8.resolve(cwd);
19254
- return resolved === path8.parse(resolved).root;
19762
+ const resolved = path9.resolve(cwd);
19763
+ return resolved === path9.parse(resolved).root;
19255
19764
  }
19256
19765
  function writableDirectory(candidate) {
19257
- if (!candidate || !path8.isAbsolute(candidate) || isFilesystemRoot(candidate))
19766
+ if (!candidate || !path9.isAbsolute(candidate) || isFilesystemRoot(candidate))
19258
19767
  return void 0;
19259
19768
  try {
19260
19769
  if (!fs2.statSync(candidate).isDirectory())
@@ -19267,19 +19776,19 @@ function writableDirectory(candidate) {
19267
19776
  }
19268
19777
  function resolvePiInspectCwd(inputCwd, environment = process.env) {
19269
19778
  if (typeof inputCwd === "string" && inputCwd.length > 0 && !isFilesystemRoot(inputCwd)) {
19270
- return path8.resolve(inputCwd);
19779
+ return path9.resolve(inputCwd);
19271
19780
  }
19272
- const candidates = [environment.USERPROFILE, environment.HOME, homedir3(), tmpdir2()];
19781
+ const candidates = [environment.USERPROFILE, environment.HOME, homedir4(), tmpdir2()];
19273
19782
  for (const candidate of candidates) {
19274
19783
  const usable = writableDirectory(candidate);
19275
19784
  if (usable)
19276
19785
  return usable;
19277
19786
  }
19278
- return inputCwd && inputCwd.length > 0 ? path8.resolve(inputCwd) : process.cwd();
19787
+ return inputCwd && inputCwd.length > 0 ? path9.resolve(inputCwd) : process.cwd();
19279
19788
  }
19280
19789
 
19281
19790
  // dist/pi-credential-imports.js
19282
- var PREFIX2 = "codexhost-account-";
19791
+ var PREFIX3 = "codexhost-account-";
19283
19792
  function object2(value) {
19284
19793
  return typeof value === "object" && value !== null && !Array.isArray(value);
19285
19794
  }
@@ -19320,7 +19829,7 @@ function describeOauth(credential) {
19320
19829
  };
19321
19830
  }
19322
19831
  function writeAuth(filename, content) {
19323
- const temporary = `${filename}.${randomUUID()}.tmp`;
19832
+ const temporary = `${filename}.${randomUUID2()}.tmp`;
19324
19833
  try {
19325
19834
  writeFileSync(temporary, content, { flag: "wx", mode: 384 });
19326
19835
  renameSync(temporary, filename);
@@ -19329,8 +19838,8 @@ function writeAuth(filename, content) {
19329
19838
  }
19330
19839
  }
19331
19840
  function removeOwnedFiles(dir) {
19332
- rmSync(path9.join(dir, "index.ts"), { force: true });
19333
- 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 });
19334
19843
  try {
19335
19844
  rmdirSync(dir);
19336
19845
  } catch {
@@ -19342,13 +19851,13 @@ async function installation(command, environment, authPath) {
19342
19851
  const cliEntry = directory ? findPiCliEntry(directory) : void 0;
19343
19852
  if (!directory || !cliEntry)
19344
19853
  throw new Error("Pi credential import requires a supported npm Pi installation");
19345
- const storage = await import(pathToFileURL(path9.join(directory, "dist/core/auth-storage.js")).href);
19346
- const ai = path9.join(directory, "node_modules/@earendil-works/pi-ai/dist");
19347
- 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);
19348
19857
  const providers = all.getBuiltinProviders();
19349
19858
  const providerModules = {
19350
- "openai-codex": pathToFileURL(path9.join(ai, "providers/openai-codex.js")).href,
19351
- 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
19352
19861
  };
19353
19862
  for (const [id, url2] of Object.entries(providerModules)) {
19354
19863
  const module = await import(url2);
@@ -19362,8 +19871,8 @@ async function installation(command, environment, authPath) {
19362
19871
  reservedNames: providers.map((p) => typeof p === "string" ? p : p.id),
19363
19872
  async configuredProviderNames() {
19364
19873
  const { stdout } = await promisify(execFile2)(process.execPath, [cliEntry, "--offline", "--no-approve", "--list-models"], {
19365
- cwd: existsSync(path9.dirname(authPath)) ? path9.dirname(authPath) : os4.homedir(),
19366
- 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" },
19367
19876
  timeout: 15e3,
19368
19877
  maxBuffer: 4 * 1024 * 1024
19369
19878
  });
@@ -19393,26 +19902,26 @@ export default async function (pi) {
19393
19902
  }
19394
19903
  function createPiCredentialImports(options = {}) {
19395
19904
  const env = { ...process.env, ...options.environment };
19396
- const agentDir = env.PI_CODING_AGENT_DIR ?? path9.join(env.HOME ?? os4.homedir(), ".pi/agent");
19397
- const authPath = path9.join(agentDir, "auth.json");
19398
- 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");
19399
19908
  const saveAuth = (auth) => (options.writeAuth ?? writeAuth)(authPath, JSON.stringify(auth, null, 2) + "\n");
19400
19909
  const resolve = () => options.resolveInstallation?.(authPath) ?? installation(options.command, env, authPath);
19401
- const location = (name) => path9.join(extensionsDir, `${PREFIX2}${credentialImportNameSchema.parse(name)}`);
19910
+ const location = (name) => path10.join(extensionsDir, `${PREFIX3}${credentialImportNameSchema.parse(name)}`);
19402
19911
  const readRecord = (name) => {
19403
19912
  const dir = location(name);
19404
19913
  if (lstatSync(dir).isSymbolicLink())
19405
19914
  throw new Error("Imported configuration was changed; manage it in Pi");
19406
- const value = JSON.parse(readFileSync(path9.join(dir, "import.json"), "utf8"));
19915
+ const value = JSON.parse(readFileSync(path10.join(dir, "import.json"), "utf8"));
19407
19916
  if (value.version !== 1 || typeof value.owner !== "string" || typeof value.extension !== "string")
19408
19917
  throw new Error("Invalid import metadata");
19409
- const record7 = value.record;
19410
- if (!object2(record7))
19918
+ const record9 = value.record;
19919
+ if (!object2(record9))
19411
19920
  throw new Error("Invalid import metadata");
19412
19921
  value.record = credentialImportRecordSchema.parse({
19413
- name: record7.name,
19414
- source: record7.source,
19415
- importedAt: record7.importedAt
19922
+ name: record9.name,
19923
+ source: record9.source,
19924
+ importedAt: record9.importedAt
19416
19925
  });
19417
19926
  if (value.record.name !== name)
19418
19927
  throw new Error("Import identity mismatch");
@@ -19420,7 +19929,7 @@ function createPiCredentialImports(options = {}) {
19420
19929
  };
19421
19930
  const owned = (meta3, auth) => {
19422
19931
  const credential = auth[meta3.record.name];
19423
- const file2 = path9.join(location(meta3.record.name), "index.ts");
19932
+ const file2 = path10.join(location(meta3.record.name), "index.ts");
19424
19933
  return existsSync(file2) && !lstatSync(file2).isSymbolicLink() && readFileSync(file2, "utf8") === meta3.extension && object2(credential) && credential.type === "oauth" && credential.codexhostImportId === meta3.owner;
19425
19934
  };
19426
19935
  const readAuth = () => existsSync(authPath) ? parseAuth(readFileSync(authPath, "utf8")) : {};
@@ -19429,12 +19938,12 @@ function createPiCredentialImports(options = {}) {
19429
19938
  return [];
19430
19939
  const result = [];
19431
19940
  for (const entry of readdirSync(extensionsDir)) {
19432
- if (!entry.startsWith(PREFIX2))
19941
+ if (!entry.startsWith(PREFIX3))
19433
19942
  continue;
19434
- const name = entry.slice(PREFIX2.length);
19943
+ const name = entry.slice(PREFIX3.length);
19435
19944
  if (!credentialImportNameSchema.safeParse(name).success)
19436
19945
  continue;
19437
- if (!existsSync(path9.join(location(name), "import.json")))
19946
+ if (!existsSync(path10.join(location(name), "import.json")))
19438
19947
  continue;
19439
19948
  try {
19440
19949
  const meta3 = readRecord(name);
@@ -19455,7 +19964,7 @@ function createPiCredentialImports(options = {}) {
19455
19964
  },
19456
19965
  async listOthers() {
19457
19966
  const auth = readAuth();
19458
- const ours = new Set(ownedRecords(auth).map((record7) => record7.name));
19967
+ const ours = new Set(ownedRecords(auth).map((record9) => record9.name));
19459
19968
  const result = /* @__PURE__ */ new Map();
19460
19969
  const usable = (provider) => Boolean(provider) && provider.length <= 128 && !ours.has(provider) && !result.has(provider);
19461
19970
  for (const [provider, credential] of Object.entries(auth)) {
@@ -19468,7 +19977,7 @@ function createPiCredentialImports(options = {}) {
19468
19977
  ...describeOauth(credential)
19469
19978
  });
19470
19979
  }
19471
- const modelsPath = path9.join(agentDir, "models.json");
19980
+ const modelsPath = path10.join(agentDir, "models.json");
19472
19981
  if (existsSync(modelsPath)) {
19473
19982
  const models = JSON.parse(readFileSync(modelsPath, "utf8"));
19474
19983
  const providers = object2(models) && object2(models.providers) ? models.providers : {};
@@ -19489,8 +19998,8 @@ function createPiCredentialImports(options = {}) {
19489
19998
  throw new Error("Unsupported credential source");
19490
19999
  if (sdk.reservedNames.includes(name) || (await sdk.configuredProviderNames?.())?.includes(name))
19491
20000
  throw new Error("Provider name already exists; choose another name");
19492
- const owner = randomUUID();
19493
- const record7 = credentialImportRecordSchema.parse({
20001
+ const owner = randomUUID2();
20002
+ const record9 = credentialImportRecordSchema.parse({
19494
20003
  name,
19495
20004
  source: transfer.source,
19496
20005
  importedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -19502,15 +20011,15 @@ function createPiCredentialImports(options = {}) {
19502
20011
  try {
19503
20012
  sdk.backend.withLock((current) => {
19504
20013
  const auth = parseAuth(current);
19505
- const modelsPath = path9.join(agentDir, "models.json");
20014
+ const modelsPath = path10.join(agentDir, "models.json");
19506
20015
  const models = existsSync(modelsPath) ? JSON.parse(readFileSync(modelsPath, "utf8")) : {};
19507
- 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`)))
19508
20017
  throw new Error("Provider name already exists; choose another name");
19509
20018
  mkdirSync(extensionsDir, { recursive: true, mode: 448 });
19510
20019
  mkdirSync(dir, { mode: 448 });
19511
20020
  created = true;
19512
- writeFileSync(path9.join(dir, "import.json"), JSON.stringify({ version: 1, owner, record: record7, extension }), { flag: "wx", mode: 384 });
19513
- 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 });
19514
20023
  auth[name] = { type: "oauth", ...transfer.oauth, codexhostImportId: owner };
19515
20024
  saveAuth(auth);
19516
20025
  committed = true;
@@ -19529,7 +20038,7 @@ function createPiCredentialImports(options = {}) {
19529
20038
  const auth = parseAuth(current);
19530
20039
  if (!owned(meta3, auth) || meta3.record.source.id !== transfer.source.id || meta3.record.source.provider !== transfer.source.provider)
19531
20040
  throw new Error("Import ownership or source account changed; refusing replacement");
19532
- const metadataPath = path9.join(location(name), "import.json");
20041
+ const metadataPath = path10.join(location(name), "import.json");
19533
20042
  const previous = readFileSync(metadataPath, "utf8");
19534
20043
  const updated = {
19535
20044
  ...meta3,
@@ -19564,10 +20073,10 @@ function createPiCredentialImports(options = {}) {
19564
20073
  }
19565
20074
 
19566
20075
  // dist/pi-fast-mode.js
19567
- import { createHash as createHash2, randomUUID as randomUUID2 } from "node:crypto";
19568
- import { mkdir, readFile as readFile2, rename, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
19569
- import { homedir as homedir4 } from "node:os";
19570
- 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";
19571
20080
  var PI_FAST_COMMAND = "codexhost-fast-mode";
19572
20081
  var PI_FAST_ACK = "codexhost-fast-mode:";
19573
20082
  var PI_FAST_EXTENSION = `export default function(pi) {
@@ -19617,24 +20126,24 @@ var PI_FAST_EXTENSION = `export default function(pi) {
19617
20126
  }
19618
20127
  `;
19619
20128
  async function ensurePiFastExtension(environment) {
19620
- const digest = createHash2("sha256").update(PI_FAST_EXTENSION).digest("hex").slice(0, 16);
19621
- const dataDirectory = environment.CODEXHOST_DATA_DIR ?? path10.join(environment.HOME ?? environment.USERPROFILE ?? homedir4(), ".codexhost");
19622
- const directory = path10.resolve(dataDirectory, "extensions", "pi-codex-fast");
19623
- const file2 = path10.join(directory, `${digest}.mjs`);
19624
- 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)
19625
20134
  return file2;
19626
- await mkdir(directory, { recursive: true });
19627
- const temporary = `${file2}.${randomUUID2()}.tmp`;
20135
+ await mkdir2(directory, { recursive: true });
20136
+ const temporary = `${file2}.${randomUUID3()}.tmp`;
19628
20137
  try {
19629
- await writeFile2(temporary, PI_FAST_EXTENSION, { mode: 384 });
20138
+ await writeFile3(temporary, PI_FAST_EXTENSION, { mode: 384 });
19630
20139
  try {
19631
- await rename(temporary, file2);
20140
+ await rename2(temporary, file2);
19632
20141
  } catch (error51) {
19633
- if (await readFile2(file2, "utf8").catch(() => "") !== PI_FAST_EXTENSION)
20142
+ if (await readFile3(file2, "utf8").catch(() => "") !== PI_FAST_EXTENSION)
19634
20143
  throw error51;
19635
20144
  }
19636
20145
  } finally {
19637
- await rm2(temporary, { force: true });
20146
+ await rm3(temporary, { force: true });
19638
20147
  }
19639
20148
  return file2;
19640
20149
  }
@@ -19651,15 +20160,15 @@ function withPiFast(catalog, supported) {
19651
20160
  // dist/pi-empty-session.js
19652
20161
  import { createReadStream as createReadStream3 } from "node:fs";
19653
20162
  import { createInterface as createInterface3 } from "node:readline";
19654
- import { randomUUID as randomUUID3 } from "node:crypto";
19655
- import { link, open as open2, rm as rm3 } from "node:fs/promises";
19656
- 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";
19657
20166
 
19658
20167
  // dist/pi-session-file.js
19659
20168
  import { open, realpath as realpath3 } from "node:fs/promises";
19660
20169
  var MAX_SESSION_HEADER_BYTES = 64 * 1024;
19661
20170
  var utf8Decoder = new TextDecoder("utf-8", { fatal: true });
19662
- function isRecord7(value) {
20171
+ function isRecord8(value) {
19663
20172
  return typeof value === "object" && value !== null && !Array.isArray(value);
19664
20173
  }
19665
20174
  async function readPiSessionHeader(sessionFile) {
@@ -19679,7 +20188,7 @@ async function readPiSessionHeader(sessionFile) {
19679
20188
  } catch {
19680
20189
  throw new Error("Pi Session header is not valid JSON");
19681
20190
  }
19682
- 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) {
19683
20192
  throw new Error("Pi Session header is invalid");
19684
20193
  }
19685
20194
  return {
@@ -19712,7 +20221,7 @@ async function verifyPiSessionCwd(input) {
19712
20221
  async function persistEmptyPiSession(input) {
19713
20222
  const { state: state2, history, sourceSessionFile, sourceSessionId, cwd } = input;
19714
20223
  const destination = state2.sessionFile;
19715
- 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)
19716
20225
  throw new Error("Pi empty Session is not an independent empty native fork");
19717
20226
  await verifyPiSessionCwd({
19718
20227
  sessionFile: sourceSessionFile,
@@ -19736,7 +20245,7 @@ async function persistEmptyPiSession(input) {
19736
20245
  cwd,
19737
20246
  parentSession: sourceSessionFile
19738
20247
  };
19739
- const temporary = path11.join(path11.dirname(destination), `.codexhost-${randomUUID3()}.tmp`);
20248
+ const temporary = path12.join(path12.dirname(destination), `.codexhost-${randomUUID4()}.tmp`);
19740
20249
  try {
19741
20250
  const file2 = await open2(temporary, "wx", 384);
19742
20251
  try {
@@ -19747,7 +20256,7 @@ async function persistEmptyPiSession(input) {
19747
20256
  }
19748
20257
  await link(temporary, destination);
19749
20258
  if (process.platform !== "win32") {
19750
- const directory = await open2(path11.dirname(destination), "r");
20259
+ const directory = await open2(path12.dirname(destination), "r");
19751
20260
  try {
19752
20261
  await directory.sync();
19753
20262
  } finally {
@@ -19755,7 +20264,7 @@ async function persistEmptyPiSession(input) {
19755
20264
  }
19756
20265
  }
19757
20266
  } finally {
19758
- await rm3(temporary, { force: true });
20267
+ await rm4(temporary, { force: true });
19759
20268
  }
19760
20269
  }
19761
20270
  async function readPiEmptySessionConfiguration(sessionFile) {
@@ -19811,20 +20320,20 @@ async function readPiEmptySessionConfiguration(sessionFile) {
19811
20320
  }
19812
20321
 
19813
20322
  // dist/pi-adapter.js
19814
- import { randomUUID as randomUUID6 } from "node:crypto";
19815
- import path15 from "node:path";
20323
+ import { randomUUID as randomUUID7 } from "node:crypto";
20324
+ import path17 from "node:path";
19816
20325
 
19817
20326
  // dist/pi-workflow-child-history.js
19818
- import { createHash as createHash3 } from "node:crypto";
20327
+ import { createHash as createHash6 } from "node:crypto";
19819
20328
  import { constants } from "node:fs";
19820
20329
  import { open as open3 } from "node:fs/promises";
19821
- import path12 from "node:path";
19822
- function record5(value) {
20330
+ import path13 from "node:path";
20331
+ function record7(value) {
19823
20332
  return typeof value === "object" && value !== null && !Array.isArray(value);
19824
20333
  }
19825
20334
  var MAX_SESSION_BYTES = 8 * 1024 * 1024;
19826
- async function childHistory(file2, parentSessionId, identity) {
19827
- if (!path12.isAbsolute(file2))
20335
+ async function childHistory(file2, parentSessionId, identity, validateParent = false) {
20336
+ if (!path13.isAbsolute(file2))
19828
20337
  throw new Error("Pi child Session path is not absolute");
19829
20338
  const handle = await open3(file2, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0));
19830
20339
  try {
@@ -19837,12 +20346,14 @@ async function childHistory(file2, parentSessionId, identity) {
19837
20346
  throw new Error("Pi child Session exceeds read bounds");
19838
20347
  const values = buffer.subarray(0, bytesRead).toString("utf8").split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
19839
20348
  const header = values[0];
19840
- 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)
19841
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");
19842
20353
  const entries = [];
19843
20354
  for (const entry of values.slice(1)) {
19844
20355
  const parsed = jsonValueSchema.safeParse(entry);
19845
- if (!parsed.success || !record5(parsed.data) || typeof parsed.data.id !== "string")
20356
+ if (!parsed.success || !record7(parsed.data) || typeof parsed.data.id !== "string")
19846
20357
  throw new Error("Malformed Pi child Session entry");
19847
20358
  entries.push(parsed.data);
19848
20359
  }
@@ -19852,7 +20363,7 @@ async function childHistory(file2, parentSessionId, identity) {
19852
20363
  model: null,
19853
20364
  ...typeof header.cwd === "string" ? { cwd: header.cwd } : {}
19854
20365
  });
19855
- const prefix = createHash3("sha256").update(identity).digest("hex");
20366
+ const prefix = createHash6("sha256").update(identity).digest("hex");
19856
20367
  return {
19857
20368
  turns: snapshot.turns.map((turn) => {
19858
20369
  const readonlyTurn = {
@@ -19873,7 +20384,7 @@ async function childHistory(file2, parentSessionId, identity) {
19873
20384
  async function readPiWorkflowChild(history, parentSessionId, address) {
19874
20385
  for (const entry of activePiEntries(history).reverse()) {
19875
20386
  const message3 = entry.message;
19876
- if (!record5(message3) || message3.role !== "toolResult" || message3.toolName !== "subagent")
20387
+ if (!record7(message3) || message3.role !== "toolResult" || message3.toolName !== "subagent")
19877
20388
  continue;
19878
20389
  const summary = piWorkflowSummary(message3);
19879
20390
  if (!summary || summary.workflowRunId !== address.workflowRunId || summary.parentToolCallId !== message3.toolCallId)
@@ -19882,10 +20393,10 @@ async function readPiWorkflowChild(history, parentSessionId, address) {
19882
20393
  if (!child)
19883
20394
  break;
19884
20395
  const details = message3.details;
19885
- if (!record5(details) || !Array.isArray(details.results))
20396
+ if (!record7(details) || !Array.isArray(details.results))
19886
20397
  break;
19887
- const result = details.results.findLast((candidate) => record5(candidate) && candidate.workflowKey === address.childId);
19888
- if (!record5(result))
20398
+ const result = details.results.findLast((candidate) => record7(candidate) && candidate.workflowKey === address.childId);
20399
+ if (!record7(result))
19889
20400
  break;
19890
20401
  const id = piWorkflowSubagentId(address);
19891
20402
  if (typeof result.sessionFile === "string") {
@@ -19928,25 +20439,69 @@ ${output}`,
19928
20439
  };
19929
20440
  }
19930
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
+
19931
20486
  // dist/pi-subagent-history.js
19932
20487
  import { constants as constants2 } from "node:fs";
19933
20488
  import { open as open4 } from "node:fs/promises";
19934
- import path13 from "node:path";
19935
- function record6(value) {
20489
+ import path14 from "node:path";
20490
+ function record8(value) {
19936
20491
  return typeof value === "object" && value !== null && !Array.isArray(value);
19937
20492
  }
19938
20493
  function state(value) {
19939
20494
  return value === "pending" ? "queued" : value === "completed" ? "complete" : value;
19940
20495
  }
19941
20496
  function piSubagentArtifact(value, runId, parentSessionId) {
19942
- 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)))
19943
20498
  return null;
19944
20499
  if (value.steps !== void 0 && (!Array.isArray(value.steps) || value.steps.length > 128))
19945
20500
  return null;
19946
20501
  const steps = Array.isArray(value.steps) ? value.steps : [];
19947
20502
  const children = [];
19948
20503
  for (const [index, step] of steps.entries()) {
19949
- if (!record6(step) || typeof step.agent !== "string")
20504
+ if (!record8(step) || typeof step.agent !== "string")
19950
20505
  return null;
19951
20506
  children.push({
19952
20507
  id: step.workflowKey ?? step.runId ?? `step:${index}`,
@@ -19977,19 +20532,20 @@ function piSubagentArtifact(value, runId, parentSessionId) {
19977
20532
  });
19978
20533
  }
19979
20534
  async function restorePiSubagents(history, parentSessionId, observer) {
20535
+ restoreGotgenes(history, observer.gotgenes);
19980
20536
  const receipts = /* @__PURE__ */ new Map();
19981
20537
  for (const entry of activePiEntries(history)) {
19982
- 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))
19983
20539
  continue;
19984
20540
  const details = entry.message.details;
19985
- 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)
19986
20542
  continue;
19987
20543
  receipts.set(details.asyncId, details.asyncDir);
19988
20544
  }
19989
20545
  for (const [id, directory] of [...receipts].slice(-128)) {
19990
20546
  let file2;
19991
20547
  try {
19992
- 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));
19993
20549
  const stat2 = await file2.stat();
19994
20550
  if (!stat2.isFile() || stat2.size > 1024 * 1024)
19995
20551
  continue;
@@ -20071,8 +20627,8 @@ async function rollbackPiLastTurn(transport, sourceSessionId, cwd) {
20071
20627
 
20072
20628
  // dist/pi-rpc-session.js
20073
20629
  import { spawn, spawnSync } from "node:child_process";
20074
- import { randomUUID as randomUUID5 } from "node:crypto";
20075
- import path14 from "node:path";
20630
+ import { randomUUID as randomUUID6 } from "node:crypto";
20631
+ import path16 from "node:path";
20076
20632
 
20077
20633
  // dist/pi-slash-commands.js
20078
20634
  var DYNAMIC_ID_PREFIX = "pi.slash.";
@@ -20094,15 +20650,15 @@ function parsePiNativeCommands(response) {
20094
20650
  return data.commands.flatMap((entry) => {
20095
20651
  if (typeof entry !== "object" || entry === null)
20096
20652
  return [];
20097
- const record7 = entry;
20098
- 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, "") : "";
20099
20655
  if (!name)
20100
20656
  return [];
20101
20657
  return [
20102
20658
  {
20103
20659
  name,
20104
- ...typeof record7.description === "string" ? { description: record7.description } : {},
20105
- ...typeof record7.source === "string" ? { source: record7.source } : {}
20660
+ ...typeof record9.description === "string" ? { description: record9.description } : {},
20661
+ ...typeof record9.source === "string" ? { source: record9.source } : {}
20106
20662
  }
20107
20663
  ];
20108
20664
  });
@@ -20118,8 +20674,209 @@ function piDynamicCommandPrompt(catalog, commandId, argumentText) {
20118
20674
  return liveHarnessCommandPrompt(catalog, DYNAMIC_ID_PREFIX, commandId, argumentText);
20119
20675
  }
20120
20676
 
20677
+ // dist/pi-unc-launch.js
20678
+ import fs3 from "node:fs";
20679
+ import path15 from "node:path";
20680
+ function isWindowsUncDirectory(directory) {
20681
+ return /^\\\\(?:\?\\UNC\\)?(?![?.]\\)[^\\]+\\[^\\]+(?:\\|$)/iu.test(path15.win32.normalize(directory));
20682
+ }
20683
+ function text3(file2) {
20684
+ try {
20685
+ return fs3.readFileSync(file2, "utf8").replace(/^\uFEFF/u, "").replaceAll("\r\n", "\n").trim();
20686
+ } catch {
20687
+ return void 0;
20688
+ }
20689
+ }
20690
+ function isFile(file2) {
20691
+ try {
20692
+ return fs3.statSync(file2).isFile();
20693
+ } catch {
20694
+ return false;
20695
+ }
20696
+ }
20697
+ function nodeOnPath(environment) {
20698
+ for (const directory of pathDirectories(environment, "win32")) {
20699
+ for (const extension of executableExtensions("node", "win32", environment)) {
20700
+ const suffix = extension.toLowerCase();
20701
+ const candidate = path15.join(directory, `node${suffix}`);
20702
+ if (!isFile(candidate))
20703
+ continue;
20704
+ if (suffix !== ".exe" && suffix !== ".com") {
20705
+ throw new Error("Pi PATH Node launcher cannot safely bypass CMD in a UNC directory");
20706
+ }
20707
+ return candidate;
20708
+ }
20709
+ }
20710
+ return process.execPath;
20711
+ }
20712
+ function npmShim(target, pathExtFix = false) {
20713
+ return `@ECHO off
20714
+ GOTO start
20715
+ :find_dp0
20716
+ SET dp0=%~dp0
20717
+ EXIT /b
20718
+ :start
20719
+ SETLOCAL
20720
+ CALL :find_dp0
20721
+
20722
+ IF EXIST "%dp0%\\node.exe" (
20723
+ SET "_prog=%dp0%\\node.exe"
20724
+ ) ELSE (
20725
+ SET "_prog=node"
20726
+ ${pathExtFix ? "" : " SET PATHEXT=%PATHEXT:;.JS;=;%\n"})
20727
+
20728
+ endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & ${pathExtFix ? "set PATHEXT=%PATHEXT:;.JS;=;% & " : ""}"%_prog%" "%dp0%\\${target}" %*`;
20729
+ }
20730
+ var standaloneNodeSetup = 'IF EXIST "%LOCALAPPDATA%\\pi-node\\current\\node.exe" SET "node=%LOCALAPPDATA%\\pi-node\\current\\node.exe"';
20731
+ function managedShim(standalone) {
20732
+ return `@ECHO off
20733
+ SETLOCAL
20734
+ SET "node=node"
20735
+ ${standalone ? `${standaloneNodeSetup}
20736
+ ` : ""}"%node%" "%~dp0pi-launcher.js" %*
20737
+ SET "pi_exit_code=%ERRORLEVEL%"
20738
+ IF "%pi_exit_code%"=="9009" (
20739
+ IF "%node%"=="node" (
20740
+ "%SystemRoot%\\System32\\where.exe" /Q node
20741
+ IF ERRORLEVEL 1 GOTO node_missing
20742
+ ) ELSE IF NOT EXIST "%node%" GOTO node_missing
20743
+ )
20744
+ EXIT /B %pi_exit_code%
20745
+ :node_missing
20746
+ ECHO Pi could not find Node.js. Install Node.js 22.19.0 or newer, or rerun the installer at https://pi.dev. 1>&2
20747
+ EXIT /B %pi_exit_code%`;
20748
+ }
20749
+ function piUncNodeInvocation(command, arguments_, environment) {
20750
+ const directory = path15.dirname(command);
20751
+ const source = text3(command);
20752
+ if (path15.isAbsolute(command) && path15.win32.basename(command).toLowerCase() === "pi.cmd" && source !== void 0) {
20753
+ const packageDirectory = path15.join(directory, "node_modules", "@earendil-works", "pi-coding-agent");
20754
+ try {
20755
+ const manifest = JSON.parse(text3(path15.join(packageDirectory, "package.json")) ?? "");
20756
+ if (typeof manifest === "object" && manifest !== null && "name" in manifest && manifest.name === "@earendil-works/pi-coding-agent") {
20757
+ const entry = findPiCliEntry(packageDirectory);
20758
+ const target = entry && path15.relative(directory, entry).replaceAll("/", "\\");
20759
+ if (entry && target && [npmShim(target), npmShim(target, true)].includes(source)) {
20760
+ const localNode = path15.join(directory, "node.exe");
20761
+ return {
20762
+ command: isFile(localNode) ? localNode : nodeOnPath(environment),
20763
+ arguments: [entry, ...arguments_],
20764
+ windowsVerbatimArguments: false
20765
+ };
20766
+ }
20767
+ }
20768
+ } catch {
20769
+ }
20770
+ const launcher = path15.join(directory, "pi-launcher.js");
20771
+ try {
20772
+ const marker = JSON.parse(text3(path15.join(path15.dirname(directory), "install", "managed-install.json")) ?? "");
20773
+ if (typeof marker === "object" && marker !== null && "kind" in marker && marker.kind === "pi-managed-install" && "schemaVersion" in marker && marker.schemaVersion === 1 && "layout" in marker && marker.layout === "releases-v1" && "entrypoint" in marker && typeof marker.entrypoint === "object" && marker.entrypoint !== null && "type" in marker.entrypoint && marker.entrypoint.type === "script" && "path" in marker.entrypoint && typeof marker.entrypoint.path === "string" && path15.isAbsolute(marker.entrypoint.path) && path15.resolve(marker.entrypoint.path).toLowerCase() === path15.resolve(command).toLowerCase() && isFile(launcher) && (source === managedShim(false) || source === managedShim(true))) {
20774
+ const localAppData = environmentValue(environment, "LOCALAPPDATA");
20775
+ const standaloneNode = localAppData ? path15.join(localAppData, "pi-node", "current", "node.exe") : void 0;
20776
+ return {
20777
+ command: source === managedShim(true) && standaloneNode && isFile(standaloneNode) ? standaloneNode : nodeOnPath(environment),
20778
+ // The native launcher reads current-version and sets PI_MANAGED_INSTALL_ROOT itself.
20779
+ arguments: [launcher, ...arguments_],
20780
+ windowsVerbatimArguments: false
20781
+ };
20782
+ }
20783
+ } catch {
20784
+ }
20785
+ }
20786
+ throw new Error("Pi batch launcher cannot safely start in a UNC working directory. Use a standard npm or managed Pi installation, a native Pi executable, or a Host running inside WSL; custom Pi or PATH Node batch launchers are not bypassed.");
20787
+ }
20788
+
20789
+ // dist/pi-content-stream.js
20790
+ var PiContentStreamConflictError = class extends Error {
20791
+ };
20792
+ var PiContentStream = class {
20793
+ kind;
20794
+ #blocks = /* @__PURE__ */ new Map();
20795
+ #indexed;
20796
+ #legacyBlockIndex = 0;
20797
+ #lastEmittedIndex = -Infinity;
20798
+ constructor(kind) {
20799
+ this.kind = kind;
20800
+ }
20801
+ append(index, delta) {
20802
+ const block = this.#block(this.#key(index));
20803
+ if (block.ended && delta.length > 0)
20804
+ this.#conflict();
20805
+ block.received += delta;
20806
+ return this.#flush();
20807
+ }
20808
+ complete(index, content) {
20809
+ this.#finish(this.#key(index), content);
20810
+ if (this.#indexed === false)
20811
+ this.#legacyBlockIndex += 1;
20812
+ return this.#flush();
20813
+ }
20814
+ finalize(blocks) {
20815
+ if (this.#indexed !== true) {
20816
+ blocks = this.#legacyBlockIndex > 0 ? blocks.map(({ text: text4 }, index) => ({ index, text: text4 })) : [{ index: 0, text: blocks.map(({ text: text4 }) => text4).join("") }];
20817
+ }
20818
+ const indices = new Set(blocks.map(({ index }) => index));
20819
+ for (const [index, block] of this.#blocks) {
20820
+ if (indices.has(index))
20821
+ continue;
20822
+ if (block.emitted.length > 0)
20823
+ this.#conflict();
20824
+ this.#blocks.delete(index);
20825
+ }
20826
+ for (const { index, text: text4 } of blocks)
20827
+ this.#finish(index, text4);
20828
+ return this.#flush();
20829
+ }
20830
+ #key(index) {
20831
+ const indexed = typeof index === "number" && Number.isInteger(index) && index >= 0;
20832
+ this.#indexed ??= indexed;
20833
+ if (!this.#indexed)
20834
+ return this.#legacyBlockIndex;
20835
+ if (!indexed)
20836
+ this.#conflict();
20837
+ return index;
20838
+ }
20839
+ #block(index) {
20840
+ let block = this.#blocks.get(index);
20841
+ if (!block) {
20842
+ block = { received: "", emitted: "", ended: false };
20843
+ this.#blocks.set(index, block);
20844
+ }
20845
+ return block;
20846
+ }
20847
+ #finish(index, content) {
20848
+ const block = this.#block(index);
20849
+ if (!content.startsWith(block.emitted))
20850
+ this.#conflict();
20851
+ block.received = content;
20852
+ block.ended = true;
20853
+ }
20854
+ #flush() {
20855
+ let delta = "";
20856
+ for (const [index, block] of [...this.#blocks].sort(([left], [right]) => left - right)) {
20857
+ const visible = this.kind === "reasoning" && !block.ended ? block.received.replace(/[\r\n]+$/u, "") : block.received;
20858
+ if (!visible.startsWith(block.emitted))
20859
+ this.#conflict();
20860
+ const suffix = visible.slice(block.emitted.length);
20861
+ if (suffix.length > 0) {
20862
+ if (index < this.#lastEmittedIndex)
20863
+ this.#conflict();
20864
+ this.#lastEmittedIndex = index;
20865
+ block.emitted = visible;
20866
+ delta += suffix;
20867
+ }
20868
+ if (!block.ended)
20869
+ break;
20870
+ }
20871
+ return delta;
20872
+ }
20873
+ #conflict() {
20874
+ throw new PiContentStreamConflictError(`Pi ${this.kind} final content conflicts with already streamed content`);
20875
+ }
20876
+ };
20877
+
20121
20878
  // dist/pi-subagent-rpc.js
20122
- import { randomUUID as randomUUID4 } from "node:crypto";
20879
+ import { randomUUID as randomUUID5 } from "node:crypto";
20123
20880
  var PiSubagentRpc = class {
20124
20881
  send;
20125
20882
  timeoutMs;
@@ -20161,7 +20918,7 @@ var PiSubagentRpc = class {
20161
20918
  if (!Array.isArray(data?.commands) || !data.commands.some((command) => command?.name === "subagents-inspect-rpc" && command.source === "extension")) {
20162
20919
  throw new Error("Installed Pi has no pi-subagents Host inspection command");
20163
20920
  }
20164
- const requestId = randomUUID4();
20921
+ const requestId = randomUUID5();
20165
20922
  const reply = new Promise((resolve, reject) => {
20166
20923
  const timer = setTimeout(() => {
20167
20924
  this.#pending.delete(requestId);
@@ -20195,6 +20952,12 @@ var PiSubagentRpc = class {
20195
20952
  };
20196
20953
 
20197
20954
  // dist/pi-rpc-session.js
20955
+ var PiRpcBusyError = class extends Error {
20956
+ constructor() {
20957
+ super("Pi is still running a native Turn; wait for completion or use the active Turn's stop/steer action");
20958
+ this.name = "PiRpcBusyError";
20959
+ }
20960
+ };
20198
20961
  var PiRpcFaultError = class extends Error {
20199
20962
  kind;
20200
20963
  diagnostic;
@@ -20222,8 +20985,11 @@ var READ_ONLY_COMMANDS = /* @__PURE__ */ new Set([
20222
20985
  "get_available_thinking_levels"
20223
20986
  ]);
20224
20987
  var MAX_EXPIRED_IDS = 64;
20988
+ function nativeMessageIdentity(active) {
20989
+ return active.assistantNativeMessageIdentity ? { nativeMessageIdentity: active.assistantNativeMessageIdentity } : {};
20990
+ }
20225
20991
  var textDecoder = new TextDecoder("utf-8", { fatal: true });
20226
- function isRecord8(value) {
20992
+ function isRecord9(value) {
20227
20993
  return typeof value === "object" && value !== null && !Array.isArray(value);
20228
20994
  }
20229
20995
  function message2(value) {
@@ -20235,13 +21001,13 @@ function nonBlankString(value) {
20235
21001
  function parseNativeModel(value, context) {
20236
21002
  if (value === null || value === void 0)
20237
21003
  return null;
20238
- if (!isRecord8(value) || !nonBlankString(value.provider) || !nonBlankString(value.id)) {
21004
+ if (!isRecord9(value) || !nonBlankString(value.provider) || !nonBlankString(value.id)) {
20239
21005
  throw new PiRpcFaultError("protocolError", `Pi RPC returned an invalid ${context} Model`);
20240
21006
  }
20241
21007
  return { provider: value.provider, id: value.id };
20242
21008
  }
20243
21009
  function sessionStateData(response) {
20244
- const data = isRecord8(response.data) ? response.data : null;
21010
+ const data = isRecord9(response.data) ? response.data : null;
20245
21011
  if (!data)
20246
21012
  throw new PiRpcFaultError("protocolError", "Pi RPC state response has no data");
20247
21013
  return data;
@@ -20249,7 +21015,7 @@ function sessionStateData(response) {
20249
21015
  function parseSessionState(response) {
20250
21016
  const data = sessionStateData(response);
20251
21017
  const model2 = parseNativeModel(data.model, "state");
20252
- const modelReasoning = isRecord8(data.model) && typeof data.model.reasoning === "boolean" ? data.model.reasoning : null;
21018
+ const modelReasoning = isRecord9(data.model) && typeof data.model.reasoning === "boolean" ? data.model.reasoning : null;
20253
21019
  if (!nonBlankString(data.sessionId)) {
20254
21020
  throw new PiRpcFaultError("protocolError", "Pi RPC state has no stable Session identity");
20255
21021
  }
@@ -20275,13 +21041,13 @@ function parseSessionStreaming(response) {
20275
21041
  return isStreaming;
20276
21042
  }
20277
21043
  function parseSessionHistory(response) {
20278
- const data = isRecord8(response.data) ? response.data : null;
21044
+ const data = isRecord9(response.data) ? response.data : null;
20279
21045
  if (!data || !Array.isArray(data.entries)) {
20280
21046
  throw new PiRpcFaultError("protocolError", "Pi RPC entries response has no Entries");
20281
21047
  }
20282
21048
  const entries = data.entries.map((entry) => {
20283
21049
  const parsed = jsonValueSchema.safeParse(entry);
20284
- if (!parsed.success || !isRecord8(parsed.data)) {
21050
+ if (!parsed.success || !isRecord9(parsed.data)) {
20285
21051
  throw new PiRpcFaultError("protocolError", "Pi RPC entries response contains an invalid Entry");
20286
21052
  }
20287
21053
  return parsed.data;
@@ -20292,7 +21058,7 @@ function parseSessionHistory(response) {
20292
21058
  return { entries, leafId: data.leafId };
20293
21059
  }
20294
21060
  function parseAvailableThinkingLevels(response) {
20295
- const data = isRecord8(response.data) ? response.data : null;
21061
+ const data = isRecord9(response.data) ? response.data : null;
20296
21062
  if (!data || !Array.isArray(data.levels) || data.levels.length === 0) {
20297
21063
  throw new PiRpcFaultError("protocolError", "Pi RPC Thinking catalog response has no levels");
20298
21064
  }
@@ -20309,13 +21075,13 @@ function parseAvailableThinkingLevels(response) {
20309
21075
  return levels;
20310
21076
  }
20311
21077
  function parseAvailableModels(response) {
20312
- const data = isRecord8(response.data) ? response.data : null;
21078
+ const data = isRecord9(response.data) ? response.data : null;
20313
21079
  if (!data || !Array.isArray(data.models)) {
20314
21080
  throw new PiRpcFaultError("protocolError", "Pi RPC Model catalog response has no models");
20315
21081
  }
20316
21082
  return data.models.map((model2) => {
20317
21083
  const parsed = parseNativeModel(model2, "catalog");
20318
- if (!parsed || !isRecord8(model2) || typeof model2.reasoning !== "boolean") {
21084
+ if (!parsed || !isRecord9(model2) || typeof model2.reasoning !== "boolean") {
20319
21085
  throw new PiRpcFaultError("protocolError", "Pi RPC catalog contains a Model without reasoning capability");
20320
21086
  }
20321
21087
  return {
@@ -20326,32 +21092,32 @@ function parseAvailableModels(response) {
20326
21092
  });
20327
21093
  }
20328
21094
  function assistantText(value) {
20329
- if (!isRecord8(value) || value.role !== "assistant" || !Array.isArray(value.content))
21095
+ if (!isRecord9(value) || value.role !== "assistant" || !Array.isArray(value.content))
20330
21096
  return null;
20331
- return value.content.filter((content) => isRecord8(content) && content.type === "text" && typeof content.text === "string").map((content) => content.text).join("");
21097
+ return value.content.filter((content) => isRecord9(content) && content.type === "text" && typeof content.text === "string").map((content) => content.text).join("");
20332
21098
  }
20333
21099
  function assistantMessageId(value) {
20334
- if (!isRecord8(value) || value.role !== "assistant")
21100
+ if (!isRecord9(value) || value.role !== "assistant")
20335
21101
  return null;
20336
21102
  return nonBlankString(value.responseId) ? value.responseId : null;
20337
21103
  }
20338
21104
  function extractReasoningText(content) {
20339
- if (!isRecord8(content))
21105
+ if (!isRecord9(content))
20340
21106
  return null;
20341
21107
  const type = String(content.type ?? "");
20342
21108
  if (type === "thinking" || type === "reasoning" || type === "thought") {
20343
- const text2 = content.thinking ?? content.reasoning ?? content.text ?? content.delta;
20344
- return typeof text2 === "string" ? text2 : null;
21109
+ const text4 = content.thinking ?? content.reasoning ?? content.text ?? content.delta;
21110
+ return typeof text4 === "string" ? text4 : null;
20345
21111
  }
20346
21112
  return null;
20347
21113
  }
20348
21114
  function assistantReasoning(value) {
20349
- if (!isRecord8(value) || value.role !== "assistant" || !Array.isArray(value.content))
21115
+ if (!isRecord9(value) || value.role !== "assistant" || !Array.isArray(value.content))
20350
21116
  return null;
20351
- return value.content.map(extractReasoningText).filter((text2) => typeof text2 === "string").join("");
21117
+ return value.content.map(extractReasoningText).filter((text4) => typeof text4 === "string").join("");
20352
21118
  }
20353
21119
  function assistantFailure(value) {
20354
- if (!isRecord8(value) || value.role !== "assistant")
21120
+ if (!isRecord9(value) || value.role !== "assistant")
20355
21121
  return void 0;
20356
21122
  if (value.stopReason !== "error" && value.stopReason !== "aborted")
20357
21123
  return null;
@@ -20371,7 +21137,7 @@ function signalProcessTree(child, signal) {
20371
21137
  try {
20372
21138
  process.kill(-child.pid, signal);
20373
21139
  } catch (error51) {
20374
- if (!isRecord8(error51) || error51.code !== "ESRCH")
21140
+ if (!isRecord9(error51) || error51.code !== "ESRCH")
20375
21141
  throw error51;
20376
21142
  }
20377
21143
  }
@@ -20408,16 +21174,24 @@ function piRpcProcessCommand(options, dependencies = {}) {
20408
21174
  const thinkingArguments = options.emptySessionConfiguration ? ["--thinking", options.emptySessionConfiguration.thinkingLevel] : [];
20409
21175
  const arguments_ = [
20410
21176
  ...options.fastExtension ? ["--extension", options.fastExtension] : [],
21177
+ ...options.subagentExtension ? ["--extension", options.subagentExtension] : [],
20411
21178
  "--mode",
20412
21179
  "rpc",
20413
21180
  ...modelArguments,
20414
21181
  ...thinkingArguments,
20415
21182
  ...sessionArguments
20416
21183
  ];
20417
- const extension = path14.win32.extname(command).toLowerCase();
21184
+ const extension = path16.win32.extname(command).toLowerCase();
20418
21185
  if (platform !== "win32" || ![".cmd", ".bat"].includes(extension)) {
20419
21186
  return { command, arguments: arguments_, windowsVerbatimArguments: false };
20420
21187
  }
21188
+ if (isWindowsUncDirectory(options.cwd)) {
21189
+ try {
21190
+ return piUncNodeInvocation(command, arguments_, options.environment);
21191
+ } catch (error51) {
21192
+ throw new PiRpcFaultError("unavailable", message2(error51));
21193
+ }
21194
+ }
20421
21195
  const quote = (value) => `"${value.replaceAll("%", "%%").replaceAll('"', '""')}"`;
20422
21196
  const commandLine = [command, ...arguments_].map(quote).join(" ");
20423
21197
  return {
@@ -20443,7 +21217,13 @@ var PiRpcSession = class {
20443
21217
  #options;
20444
21218
  #processAdapter;
20445
21219
  #activeTurn = null;
21220
+ #runGeneration = 0;
21221
+ #deferredRunFrames = [];
21222
+ #deferredRunBytes = 0;
21223
+ #runWaiters = /* @__PURE__ */ new Set();
21224
+ #messageTimestampCounts = /* @__PURE__ */ new Map();
20446
21225
  #autonomousTurnHandler = null;
21226
+ #autonomousLifecycleHandler = null;
20447
21227
  #usageHandler = null;
20448
21228
  #usageRequestStartedAtMs = null;
20449
21229
  // Pieces of the unterminated frame; joined once at its newline so a large frame (a long
@@ -20463,8 +21243,15 @@ var PiRpcSession = class {
20463
21243
  #fastAcknowledgement = null;
20464
21244
  #latestCacheHitRatePercent;
20465
21245
  #manualCompaction = null;
21246
+ #noticeOccurrences = /* @__PURE__ */ new Map();
21247
+ #seenNoticeFrames = /* @__PURE__ */ new Set();
21248
+ #pendingProgress = [];
21249
+ #omittedProgress = 0;
21250
+ #extensionStatuses = /* @__PURE__ */ new Map();
20466
21251
  #stderrTail = "";
20467
21252
  #subagents;
21253
+ #gotgenesHandler;
21254
+ #gotgenesLatest;
20468
21255
  constructor(options, processAdapter = nodeProcessAdapter) {
20469
21256
  if (options.sessionFile && options.forkSessionFile) {
20470
21257
  throw new Error("Pi RPC cannot combine Session resume and Fork startup");
@@ -20494,9 +21281,17 @@ var PiRpcSession = class {
20494
21281
  get stderrTail() {
20495
21282
  return this.#stderrTail;
20496
21283
  }
21284
+ get isBusy() {
21285
+ return this.#activeTurn !== null || this.#manualCompaction !== null || this.#compactionActive || this.#deferredRunFrames.length > 0;
21286
+ }
20497
21287
  setSubagentStatusHandler(handler) {
20498
21288
  this.#subagents.setHandler(handler);
20499
21289
  }
21290
+ setGotgenesStatusHandler(handler) {
21291
+ this.#gotgenesHandler = handler;
21292
+ if (this.#gotgenesLatest)
21293
+ handler(this.#gotgenesLatest, "idle");
21294
+ }
20500
21295
  inspectSubagent(id) {
20501
21296
  return this.#subagents.inspect(id);
20502
21297
  }
@@ -20506,17 +21301,18 @@ var PiRpcSession = class {
20506
21301
  /** Every finished assistant message is one model request, with or without an active Turn. */
20507
21302
  #observeUsage(value) {
20508
21303
  if (value.type === "message_start") {
20509
- this.#usageRequestStartedAtMs = null;
21304
+ if (isRecord9(value.message) && value.message.role === "assistant")
21305
+ this.#usageRequestStartedAtMs = null;
20510
21306
  return;
20511
21307
  }
20512
21308
  if (value.type === "message_update") {
20513
21309
  const event = value.assistantMessageEvent;
20514
- if (this.#usageRequestStartedAtMs === null && isRecord8(event) && typeof event.type === "string" && /^(text|thinking|reasoning|thought|toolcall)_(start|delta)$/u.test(event.type)) {
21310
+ if (this.#usageRequestStartedAtMs === null && isRecord9(event) && typeof event.type === "string" && /^(text|thinking|reasoning|thought|toolcall)_(start|delta)$/u.test(event.type)) {
20515
21311
  this.#usageRequestStartedAtMs = Date.now();
20516
21312
  }
20517
21313
  return;
20518
21314
  }
20519
- if (value.type === "message_end" && isRecord8(value.message)) {
21315
+ if (value.type === "message_end" && isRecord9(value.message)) {
20520
21316
  if (value.message.role !== "assistant")
20521
21317
  return;
20522
21318
  const startedAtMs = this.#usageRequestStartedAtMs;
@@ -20530,14 +21326,21 @@ var PiRpcSession = class {
20530
21326
  }
20531
21327
  setAutonomousTurnHandler(handler) {
20532
21328
  this.#autonomousTurnHandler = handler;
21329
+ this.#autonomousLifecycleHandler = null;
21330
+ }
21331
+ setAutonomousTurnLifecycleHandler(handler) {
21332
+ this.#autonomousLifecycleHandler = handler;
21333
+ this.#autonomousTurnHandler = null;
20533
21334
  }
20534
21335
  async start() {
20535
21336
  if (this.#child || this.#closed)
20536
21337
  throw new Error("Pi RPC Session cannot be started twice");
20537
21338
  const fastExtension = this.#processAdapter === nodeProcessAdapter ? await ensurePiFastExtension({ ...process.env, ...this.#options.environment }) : void 0;
21339
+ const subagentExtension = this.#processAdapter === nodeProcessAdapter ? await ensureGotgenesExtension({ ...process.env, ...this.#options.environment }) : void 0;
20538
21340
  const child = this.#processAdapter.spawn({
20539
21341
  cwd: this.#options.cwd,
20540
21342
  ...fastExtension ? { fastExtension } : {},
21343
+ ...subagentExtension ? { subagentExtension } : {},
20541
21344
  ...this.#options.command ? { command: this.#options.command } : {},
20542
21345
  environment: withNodeRuntimeOnPath({
20543
21346
  ...process.env,
@@ -20561,7 +21364,7 @@ var PiRpcSession = class {
20561
21364
  this.#stderrTail = sanitizeDiagnosticTail(`${this.#stderrTail}${chunk.toString()}`);
20562
21365
  });
20563
21366
  child.once("error", (error51) => {
20564
- const kind = isRecord8(error51) && error51.code === "ENOENT" ? "notInstalled" : "unavailable";
21367
+ const kind = isRecord9(error51) && error51.code === "ENOENT" ? "notInstalled" : "unavailable";
20565
21368
  this.#fail(new PiRpcFaultError(kind, `Pi RPC failed to start: ${error51.message}`, this.stderrTail));
20566
21369
  });
20567
21370
  child.once("exit", (code, signal) => {
@@ -20578,6 +21381,7 @@ var PiRpcSession = class {
20578
21381
  ]);
20579
21382
  try {
20580
21383
  this.#state = parseSessionState(await this.#send("get_state", {}));
21384
+ await this.getEntries();
20581
21385
  } catch (error51) {
20582
21386
  const fault = error51 instanceof PiRpcFaultError ? error51 : new PiRpcFaultError("unavailable", `Pi RPC state unavailable: ${message2(error51)}`);
20583
21387
  this.#fail(fault);
@@ -20591,7 +21395,12 @@ var PiRpcSession = class {
20591
21395
  }
20592
21396
  async getEntries() {
20593
21397
  try {
20594
- return parseSessionHistory(await this.#send("get_entries", {}));
21398
+ const history = parseSessionHistory(await this.#send("get_entries", {}));
21399
+ if (!this.#activeTurn && this.#state) {
21400
+ this.#messageTimestampCounts = piHistoryMessageIdentities(this.state.sessionId, activePiEntries(history)).timestampCounts;
21401
+ this.#noticeOccurrences = piHistoryNotices(this.state.sessionId, activePiEntries(history)).occurrences;
21402
+ }
21403
+ return history;
20595
21404
  } catch (error51) {
20596
21405
  if (error51 instanceof PiRpcFaultError)
20597
21406
  this.#fail(error51);
@@ -20651,11 +21460,15 @@ var PiRpcSession = class {
20651
21460
  if (entryId.length === 0)
20652
21461
  throw new Error("Pi Fork Entry ID must not be empty");
20653
21462
  await this.#send("fork", { entryId });
20654
- return this.#refreshState("Fork");
21463
+ const state2 = await this.#refreshState("Fork");
21464
+ await this.getEntries();
21465
+ return state2;
20655
21466
  }
20656
21467
  async clone() {
20657
21468
  await this.#send("clone", {});
20658
- return this.#refreshState("Clone");
21469
+ const state2 = await this.#refreshState("Clone");
21470
+ await this.getEntries();
21471
+ return state2;
20659
21472
  }
20660
21473
  verifySessionCwd(expectedCwd) {
20661
21474
  return verifyPiSessionCwd({
@@ -20692,7 +21505,7 @@ var PiRpcSession = class {
20692
21505
  return this.state;
20693
21506
  if (!await this.supportsFastMode())
20694
21507
  throw new Error("Installed Pi does not support the Host Fast extension");
20695
- const nonce = randomUUID5();
21508
+ const nonce = randomUUID6();
20696
21509
  const mode = enabled ? "on" : "off";
20697
21510
  const acknowledgement = { message: `${PI_FAST_ACK}${nonce}:${mode}`, received: false };
20698
21511
  this.#fastAcknowledgement = acknowledgement;
@@ -20732,22 +21545,27 @@ var PiRpcSession = class {
20732
21545
  throw fault;
20733
21546
  }
20734
21547
  }
20735
- async runTurn(text2, onEvent) {
21548
+ async runTurn(text4, onEvent) {
20736
21549
  if (!this.#child || !this.#state || this.#closed || this.#failed) {
20737
21550
  throw new Error("Pi RPC Session is unavailable");
20738
21551
  }
20739
- if (this.#activeTurn)
20740
- throw new Error("Pi RPC Session already has an active Turn");
20741
- if (text2.length === 0)
21552
+ if (this.isBusy)
21553
+ throw new PiRpcBusyError();
21554
+ if (text4.length === 0)
20742
21555
  throw new Error("Pi text Turn must not be empty");
20743
21556
  const settled = new Promise((resolve, reject) => {
20744
21557
  this.#activeTurn = {
20745
21558
  origin: "requested",
21559
+ autonomousRunId: null,
21560
+ runGeneration: this.#runGeneration,
20746
21561
  autonomousEvents: null,
20747
21562
  nativeTurnKey: null,
20748
21563
  nativeCancellationObserved: false,
20749
21564
  text: "",
20750
21565
  assistantMessageId: null,
21566
+ assistantNativeMessageIdentity: void 0,
21567
+ textStream: new PiContentStream("text"),
21568
+ reasoningStream: new PiContentStream("reasoning"),
20751
21569
  sawStreamedMessageText: false,
20752
21570
  sawStreamedMessageReasoning: false,
20753
21571
  lastFinalizedMessageText: null,
@@ -20767,7 +21585,8 @@ var PiRpcSession = class {
20767
21585
  };
20768
21586
  });
20769
21587
  try {
20770
- await this.#send("prompt", { message: text2 });
21588
+ this.#drainProgress(onEvent);
21589
+ await this.#send("prompt", { message: text4 });
20771
21590
  } catch (error51) {
20772
21591
  this.#rejectActiveTurn(error51 instanceof Error ? error51 : new Error(message2(error51)));
20773
21592
  }
@@ -20839,6 +21658,10 @@ var PiRpcSession = class {
20839
21658
  void this.close().catch(() => void 0);
20840
21659
  }
20841
21660
  close() {
21661
+ this.#pendingProgress = [];
21662
+ this.#omittedProgress = 0;
21663
+ this.#seenNoticeFrames.clear();
21664
+ this.#extensionStatuses.clear();
20842
21665
  if (!this.#closed) {
20843
21666
  this.#closed = true;
20844
21667
  this.#rejectAll(new Error("Pi RPC Session closed"));
@@ -20872,19 +21695,25 @@ var PiRpcSession = class {
20872
21695
  rest = rest.subarray(newline + 1);
20873
21696
  try {
20874
21697
  const value = JSON.parse(textDecoder.decode(frame));
20875
- if (!isRecord8(value) || typeof value.type !== "string") {
21698
+ if (!isRecord9(value) || typeof value.type !== "string") {
20876
21699
  throw new PiRpcFaultError("protocolError", "Pi RPC returned an invalid envelope");
20877
21700
  }
20878
21701
  this.#handle(value);
20879
21702
  } catch (error51) {
20880
- this.#fail(error51 instanceof PiRpcFaultError ? error51 : new PiRpcFaultError("protocolError", `Pi RPC returned invalid JSONL: ${message2(error51)}`));
21703
+ this.#fail(error51 instanceof PiRpcFaultError ? error51 : new PiRpcFaultError("protocolError", error51 instanceof PiContentStreamConflictError ? error51.message : `Pi RPC returned invalid JSONL: ${message2(error51)}`));
20881
21704
  }
20882
21705
  newline = rest.indexOf(10);
20883
21706
  }
20884
21707
  if (rest.length !== 0)
20885
21708
  this.#buffer.push(rest);
20886
21709
  }
20887
- #handle(value) {
21710
+ #handle(value, observedGeneration) {
21711
+ if (observedGeneration === void 0 && value.type === "agent_start") {
21712
+ this.#runGeneration += 1;
21713
+ for (const waiter of this.#runWaiters)
21714
+ waiter.check();
21715
+ }
21716
+ const generation = observedGeneration ?? this.#runGeneration;
20888
21717
  if (value.type === "extension_ui_request" && value.method === "notify" && typeof value.message === "string" && value.message.startsWith(PI_FAST_ACK)) {
20889
21718
  if (this.#fastAcknowledgement?.message === value.message)
20890
21719
  this.#fastAcknowledgement.received = true;
@@ -20898,6 +21727,33 @@ var PiRpcSession = class {
20898
21727
  }
20899
21728
  if (this.#subagents.handle(value))
20900
21729
  return;
21730
+ const settling = this.#activeTurn;
21731
+ if (settling && settling.settlement !== "pending" && generation > settling.runGeneration) {
21732
+ this.#deferredRunBytes += Buffer.byteLength(JSON.stringify(value));
21733
+ if (this.#deferredRunBytes > 8 * 1024 * 1024) {
21734
+ this.#fail(new PiRpcFaultError("protocolError", "Pi deferred run exceeded its event buffer bound"));
21735
+ return;
21736
+ }
21737
+ this.#deferredRunFrames.push({ value, generation });
21738
+ return;
21739
+ }
21740
+ if (value.type === "agent_start") {
21741
+ if (this.#activeTurn)
21742
+ this.#activeTurn.runGeneration = generation;
21743
+ else if (!this.#manualCompaction && !this.#compactionActive && (this.#autonomousTurnHandler || this.#autonomousLifecycleHandler))
21744
+ this.#startAutonomousTurn(void 0, generation);
21745
+ return;
21746
+ }
21747
+ if (value.type === "extension_ui_request" && value.method === "setWidget" && value.widgetKey === GOTGENES_WIDGET) {
21748
+ const records = parseGotgenesWidget(value);
21749
+ if (records) {
21750
+ this.#gotgenesLatest = records;
21751
+ this.#gotgenesHandler?.(records, this.#activeTurn?.origin ?? "idle");
21752
+ }
21753
+ return;
21754
+ }
21755
+ if (this.#handleProgress(value))
21756
+ return;
20901
21757
  this.#observeUsage(value);
20902
21758
  if (value.type === "compaction_start") {
20903
21759
  this.#compactionActive = true;
@@ -20921,7 +21777,7 @@ var PiRpcSession = class {
20921
21777
  this.#armCommandTimeout(id, pending);
20922
21778
  }
20923
21779
  }
20924
- const outcome = value.aborted === true ? "cancelled" : isRecord8(value.result) ? "succeeded" : "failed";
21780
+ const outcome = value.aborted === true ? "cancelled" : isRecord9(value.result) ? "succeeded" : "failed";
20925
21781
  const event = {
20926
21782
  type: "compaction.completed",
20927
21783
  outcome,
@@ -20938,8 +21794,8 @@ var PiRpcSession = class {
20938
21794
  return;
20939
21795
  }
20940
21796
  let active = this.#activeTurn;
20941
- if (!active && !this.#manualCompaction && !this.#compactionActive && this.#autonomousTurnHandler && value.type === "message_start" && assistantText(value.message) !== null) {
20942
- active = this.#startAutonomousTurn(value.message);
21797
+ if (!active && !this.#manualCompaction && !this.#compactionActive && (this.#autonomousTurnHandler || this.#autonomousLifecycleHandler) && value.type === "message_start" && assistantText(value.message) !== null) {
21798
+ active = this.#startAutonomousTurn(value.message, generation);
20943
21799
  }
20944
21800
  if (!active) {
20945
21801
  if (value.type === "extension_ui_request" && this.#isBlockingInteraction(value)) {
@@ -20959,22 +21815,26 @@ var PiRpcSession = class {
20959
21815
  this.#startAssistantMessage(active, value.message);
20960
21816
  return;
20961
21817
  }
20962
- if (value.type === "message_update" && isRecord8(value.assistantMessageEvent)) {
21818
+ if (value.type === "message_update" && isRecord9(value.assistantMessageEvent)) {
20963
21819
  const event = value.assistantMessageEvent;
20964
21820
  const eventType = String(event.type ?? "");
20965
21821
  const isThinking = eventType === "thinking_delta" || eventType === "reasoning_delta" || eventType === "thought_delta" || eventType === "thinking" || eventType === "reasoning";
20966
21822
  const isText = eventType === "text_delta" || eventType === "text" || eventType === "content_block_delta";
20967
- 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;
20968
- if (isThinking && delta !== null && delta.length > 0) {
20969
- const messageId = this.#ensureAssistantMessage(active, value.message);
20970
- active.reasoningMessageOpen = true;
20971
- active.sawStreamedMessageReasoning = true;
20972
- active.onEvent({ type: "reasoning.delta", messageId, delta });
20973
- } else if (isText && delta !== null && delta.length > 0) {
20974
- const messageId = this.#ensureAssistantMessage(active, value.message);
20975
- active.text += delta;
20976
- active.sawStreamedMessageText = true;
20977
- active.onEvent({ type: "text.delta", messageId, delta });
21823
+ 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;
21824
+ const endingReasoning = eventType === "thinking_end" || eventType === "reasoning_end";
21825
+ const endingText = eventType === "text_end";
21826
+ if ((endingReasoning || endingText) && typeof event.content === "string") {
21827
+ this.#ensureAssistantMessage(active, value.message);
21828
+ const stream = endingReasoning ? active.reasoningStream : active.textStream;
21829
+ this.#emitContent(active, endingReasoning, stream.complete(event.contentIndex, event.content));
21830
+ } else if ((isThinking || isText) && delta !== null && delta.length > 0) {
21831
+ this.#ensureAssistantMessage(active, value.message);
21832
+ if (isThinking)
21833
+ active.sawStreamedMessageReasoning = true;
21834
+ else
21835
+ active.sawStreamedMessageText = true;
21836
+ const stream = isThinking ? active.reasoningStream : active.textStream;
21837
+ this.#emitContent(active, isThinking, stream.append(event.contentIndex, delta));
20978
21838
  } else if (event.type === "error") {
20979
21839
  this.#ensureAssistantMessage(active, value.message);
20980
21840
  active.failure = assistantFailure(event.error) ?? assistantFailure(value.message) ?? new Error("Pi assistant message failed");
@@ -21005,25 +21865,36 @@ var PiRpcSession = class {
21005
21865
  if (active.settlement !== "pending")
21006
21866
  return;
21007
21867
  active.settlement = "confirming";
21008
- void this.#confirmSettledTurn(active);
21868
+ void this.#confirmSettledTurn(active, active.runGeneration);
21009
21869
  }
21010
21870
  }
21011
- #startAutonomousTurn(value) {
21871
+ #startAutonomousTurn(value, generation) {
21012
21872
  const events = [];
21873
+ const runId = randomUUID6();
21013
21874
  const active = {
21014
21875
  origin: "autonomous",
21876
+ autonomousRunId: runId,
21877
+ runGeneration: generation,
21015
21878
  autonomousEvents: events,
21016
- ...isRecord8(value) ? { autonomousMessage: value } : {},
21879
+ ...isRecord9(value) ? { autonomousMessage: value } : {},
21017
21880
  nativeTurnKey: null,
21018
21881
  nativeCancellationObserved: false,
21019
21882
  text: "",
21020
21883
  assistantMessageId: null,
21884
+ assistantNativeMessageIdentity: void 0,
21885
+ textStream: new PiContentStream("text"),
21886
+ reasoningStream: new PiContentStream("reasoning"),
21021
21887
  sawStreamedMessageText: false,
21022
21888
  sawStreamedMessageReasoning: false,
21023
21889
  lastFinalizedMessageText: null,
21024
21890
  lastFinalizedMessageReasoning: null,
21025
21891
  reasoningMessageOpen: false,
21026
- onEvent: (event) => events.push(event),
21892
+ onEvent: (event) => {
21893
+ if (this.#autonomousLifecycleHandler)
21894
+ this.#autonomousLifecycleHandler({ type: "event", runId, event });
21895
+ else
21896
+ events.push(event);
21897
+ },
21027
21898
  resolve: () => void 0,
21028
21899
  reject: () => void 0,
21029
21900
  failure: null,
@@ -21036,19 +21907,109 @@ var PiRpcSession = class {
21036
21907
  abortPromise: null
21037
21908
  };
21038
21909
  this.#activeTurn = active;
21910
+ this.#autonomousLifecycleHandler?.({ type: "started", runId });
21911
+ this.#drainProgress(active.onEvent);
21039
21912
  return active;
21040
21913
  }
21914
+ #handleProgress(value) {
21915
+ if ((value.type === "message_start" || value.type === "message_end") && isRecord9(value.message) && value.message.role === "custom") {
21916
+ if (value.type !== "message_end" || !this.#state)
21917
+ return true;
21918
+ const key = piCustomNoticeKey(value.message);
21919
+ if (!key)
21920
+ return true;
21921
+ const timestamp = value.message.timestamp;
21922
+ if ((typeof timestamp === "number" || typeof timestamp === "string") && !this.#acceptNoticeFrame(JSON.stringify([key, timestamp])))
21923
+ return true;
21924
+ const progress = piCustomNotice(value.message, this.state.sessionId, this.#noticeOccurrences);
21925
+ if (progress)
21926
+ this.#publishProgress(progress);
21927
+ return true;
21928
+ }
21929
+ if (value.type === "extension_ui_request" && value.method === "setStatus") {
21930
+ if (typeof value.statusKey !== "string")
21931
+ return true;
21932
+ if (typeof value.statusText !== "string" || !value.statusText.trim()) {
21933
+ if (!this.#extensionStatuses.has(value.statusKey))
21934
+ return true;
21935
+ this.#extensionStatuses.delete(value.statusKey);
21936
+ } else {
21937
+ if (this.#extensionStatuses.get(value.statusKey) === value.statusText)
21938
+ return true;
21939
+ this.#extensionStatuses.set(value.statusKey, value.statusText);
21940
+ }
21941
+ return true;
21942
+ }
21943
+ const text4 = piStatusText(value);
21944
+ if (!text4)
21945
+ return false;
21946
+ if (value.type === "extension_ui_request" && typeof value.id === "string" && !this.#acceptNoticeFrame(JSON.stringify([value.type, value.id])))
21947
+ return true;
21948
+ this.#publishProgress({
21949
+ type: "progress.message",
21950
+ itemId: hostItemIdSchema.parse(`pi-progress-${randomUUID6()}`),
21951
+ text: text4
21952
+ }, value.method === "setStatus" && typeof value.statusKey === "string" ? value.statusKey : void 0);
21953
+ return true;
21954
+ }
21955
+ #acceptNoticeFrame(key) {
21956
+ if (this.#seenNoticeFrames.has(key))
21957
+ return false;
21958
+ this.#seenNoticeFrames.add(key);
21959
+ if (this.#seenNoticeFrames.size > 512)
21960
+ this.#seenNoticeFrames.delete(this.#seenNoticeFrames.values().next().value);
21961
+ return true;
21962
+ }
21963
+ #publishProgress(progress, statusKey) {
21964
+ if (this.#activeTurn?.settlement === "pending") {
21965
+ this.#activeTurn.onEvent(progress);
21966
+ return;
21967
+ }
21968
+ if (statusKey !== void 0) {
21969
+ const previous = this.#pendingProgress.findIndex((pending) => pending.statusKey === statusKey);
21970
+ if (previous >= 0)
21971
+ this.#pendingProgress.splice(previous, 1);
21972
+ }
21973
+ if (this.#pendingProgress.length >= 128) {
21974
+ this.#pendingProgress.shift();
21975
+ this.#omittedProgress += 1;
21976
+ }
21977
+ this.#pendingProgress.push({
21978
+ event: progress,
21979
+ ...statusKey !== void 0 ? { statusKey } : {}
21980
+ });
21981
+ }
21982
+ #drainProgress(onEvent) {
21983
+ if (this.#omittedProgress > 0) {
21984
+ onEvent({
21985
+ type: "progress.message",
21986
+ itemId: hostItemIdSchema.parse(`pi-progress-${randomUUID6()}`),
21987
+ text: `Pi notifications: ${this.#omittedProgress} earlier updates were not retained while idle. Persisted notifications remain available in conversation history.`
21988
+ });
21989
+ this.#omittedProgress = 0;
21990
+ }
21991
+ for (const pending of this.#pendingProgress.splice(0))
21992
+ onEvent(pending.event);
21993
+ }
21041
21994
  #emitAutonomousTurn(active, result) {
21042
21995
  const handler = this.#autonomousTurnHandler;
21043
- if (active.origin !== "autonomous" || !active.autonomousEvents || !handler) {
21996
+ if (active.origin !== "autonomous" || !active.autonomousEvents || !active.autonomousRunId) {
21044
21997
  return;
21045
21998
  }
21046
21999
  try {
21047
- handler({
22000
+ const turn = {
21048
22001
  nativeTurnKey: active.nativeTurnKey,
21049
22002
  events: [...active.autonomousEvents],
21050
22003
  result
21051
- });
22004
+ };
22005
+ if (this.#autonomousLifecycleHandler)
22006
+ this.#autonomousLifecycleHandler({
22007
+ type: "completed",
22008
+ runId: active.autonomousRunId,
22009
+ turn
22010
+ });
22011
+ else
22012
+ handler?.(turn);
21052
22013
  } catch (error51) {
21053
22014
  this.#fail(new PiRpcFaultError("protocolError", `Pi autonomous Turn handler failed: ${message2(error51)}`));
21054
22015
  }
@@ -21195,31 +22156,73 @@ var PiRpcSession = class {
21195
22156
  isError: value.isError
21196
22157
  });
21197
22158
  }
21198
- async #confirmSettledTurn(active) {
22159
+ #isSettlementCurrent(active, generation) {
22160
+ return this.#activeTurn === active && active.runGeneration === generation && active.settlement === "confirming";
22161
+ }
22162
+ #waitForNextRun(generation) {
22163
+ if (this.#runGeneration > generation)
22164
+ return Promise.resolve();
22165
+ return new Promise((resolve, reject) => {
22166
+ const finish = (error51) => {
22167
+ clearTimeout(timer);
22168
+ this.#runWaiters.delete(waiter);
22169
+ if (error51)
22170
+ reject(error51);
22171
+ else
22172
+ resolve();
22173
+ };
22174
+ const waiter = {
22175
+ check: () => {
22176
+ if (this.#runGeneration > generation)
22177
+ finish();
22178
+ },
22179
+ reject: (error51) => finish(error51)
22180
+ };
22181
+ const timer = setTimeout(() => finish(new PiRpcFaultError("protocolError", "Pi RPC agent_settled state is still Streaming without a subsequent agent_start")), this.#options.commandTimeoutMs);
22182
+ this.#runWaiters.add(waiter);
22183
+ });
22184
+ }
22185
+ #drainDeferredRunFrames() {
22186
+ const frames = this.#deferredRunFrames;
22187
+ this.#deferredRunFrames = [];
22188
+ this.#deferredRunBytes = 0;
22189
+ for (const frame of frames) {
22190
+ if (this.#closed || this.#failed)
22191
+ break;
22192
+ this.#handle(frame.value, frame.generation);
22193
+ }
22194
+ }
22195
+ async #confirmSettledTurn(active, generation) {
21199
22196
  try {
21200
22197
  const response = await this.#send("get_state", {});
21201
22198
  const state2 = parseSessionState(response);
21202
- if (parseSessionStreaming(response)) {
21203
- throw new PiRpcFaultError("protocolError", "Pi RPC agent_settled state is still Streaming");
21204
- }
21205
- if (this.#activeTurn !== active)
22199
+ if (!this.#isSettlementCurrent(active, generation))
21206
22200
  return;
21207
- if (active.origin === "autonomous") {
22201
+ if (parseSessionStreaming(response))
22202
+ await this.#waitForNextRun(generation);
22203
+ if (!this.#isSettlementCurrent(active, generation))
22204
+ return;
22205
+ if (active.origin === "autonomous" && active.autonomousMessage) {
21208
22206
  const history = await this.getEntries();
21209
22207
  const snapshot = mapPiSnapshot(history, { sessionId: state2.sessionId, model: null });
21210
- const turn = snapshot.turns.at(-1);
22208
+ if (!this.#isSettlementCurrent(active, generation))
22209
+ return;
21211
22210
  const entries = activePiEntries(history);
21212
- const start = entries.findIndex((entry) => entry.id === turn?.nativeTurnRef.nativeTurnKey);
21213
- const firstAssistant = entries.slice(start + 1).find((entry) => isRecord8(entry.message) && entry.message.role === "assistant")?.message;
21214
22211
  const live = active.autonomousMessage;
21215
22212
  const responseId = assistantMessageId(live);
21216
- const matches = isRecord8(firstAssistant) && (responseId ? assistantMessageId(firstAssistant) === responseId : typeof live?.timestamp === "number" && firstAssistant.timestamp === live.timestamp);
21217
- if (!turn || turn.input.length !== 0 || !matches) {
22213
+ const matches = snapshot.turns.filter((turn2) => {
22214
+ if (turn2.input.length !== 0)
22215
+ return false;
22216
+ const start = entries.findIndex((entry) => entry.id === turn2.nativeTurnRef.nativeTurnKey);
22217
+ const firstAssistant = entries.slice(start + 1).find((entry) => isRecord9(entry.message) && entry.message.role === "assistant")?.message;
22218
+ return isRecord9(firstAssistant) && (responseId ? assistantMessageId(firstAssistant) === responseId : typeof live?.timestamp === "number" && firstAssistant.timestamp === live.timestamp);
22219
+ });
22220
+ const turn = matches.length === 1 ? matches[0] : void 0;
22221
+ if (!turn)
21218
22222
  throw new PiRpcFaultError("protocolError", "Pi autonomous Turn has no matching persisted custom Entry");
21219
- }
21220
22223
  active.nativeTurnKey = turn.nativeTurnRef.nativeTurnKey;
21221
22224
  }
21222
- if (this.#activeTurn !== active)
22225
+ if (!this.#isSettlementCurrent(active, generation))
21223
22226
  return;
21224
22227
  this.#state = state2;
21225
22228
  active.settlement = "confirmed";
@@ -21245,7 +22248,13 @@ var PiRpcSession = class {
21245
22248
  }
21246
22249
  this.#activeTurn = null;
21247
22250
  if (active.origin === "autonomous") {
21248
- if (active.failure) {
22251
+ if (active.cancellation === "accepted") {
22252
+ this.#emitAutonomousTurn(active, {
22253
+ status: "cancelled",
22254
+ text: active.text,
22255
+ reason: "Cancelled by user"
22256
+ });
22257
+ } else if (active.failure) {
21249
22258
  this.#emitAutonomousTurn(active, active.nativeCancellationObserved ? {
21250
22259
  status: "cancelled",
21251
22260
  text: active.text,
@@ -21260,6 +22269,7 @@ var PiRpcSession = class {
21260
22269
  } else {
21261
22270
  this.#emitAutonomousTurn(active, { status: "succeeded", text: active.text });
21262
22271
  }
22272
+ this.#drainDeferredRunFrames();
21263
22273
  return;
21264
22274
  }
21265
22275
  if (active.cancellation === "accepted") {
@@ -21271,20 +22281,56 @@ var PiRpcSession = class {
21271
22281
  } else {
21272
22282
  active.resolve({ text: active.text, cancelled: false });
21273
22283
  }
22284
+ this.#drainDeferredRunFrames();
22285
+ }
22286
+ #emitContent(active, reasoning, delta) {
22287
+ if (delta.length === 0)
22288
+ return;
22289
+ const messageId = active.assistantMessageId;
22290
+ if (messageId === null)
22291
+ throw new Error("Pi content arrived outside an Assistant message");
22292
+ if (reasoning) {
22293
+ active.reasoningMessageOpen = true;
22294
+ active.sawStreamedMessageReasoning = true;
22295
+ } else {
22296
+ active.text += delta;
22297
+ active.sawStreamedMessageText = true;
22298
+ }
22299
+ active.onEvent({
22300
+ type: reasoning ? "reasoning.delta" : "text.delta",
22301
+ messageId,
22302
+ ...nativeMessageIdentity(active),
22303
+ delta
22304
+ });
21274
22305
  }
21275
22306
  #startAssistantMessage(active, value) {
22307
+ if (active.origin === "autonomous" && !active.autonomousMessage && isRecord9(value))
22308
+ active.autonomousMessage = value;
21276
22309
  if (active.assistantMessageId !== null && active.reasoningMessageOpen) {
21277
22310
  active.onEvent({ type: "reasoning.completed", messageId: active.assistantMessageId });
21278
22311
  }
21279
- const messageId = assistantMessageId(value) ?? randomUUID5();
22312
+ const nativeResponseId = assistantMessageId(value);
22313
+ const messageId = nativeResponseId ?? randomUUID6();
21280
22314
  active.assistantMessageId = messageId;
22315
+ active.assistantNativeMessageIdentity = piMessageIdentity(this.state.sessionId, value, this.#messageTimestampCounts);
22316
+ active.textStream = new PiContentStream("text");
22317
+ active.reasoningStream = new PiContentStream("reasoning");
21281
22318
  active.sawStreamedMessageText = false;
21282
22319
  active.sawStreamedMessageReasoning = false;
21283
22320
  active.reasoningMessageOpen = false;
21284
22321
  return messageId;
21285
22322
  }
21286
22323
  #ensureAssistantMessage(active, value) {
21287
- return active.assistantMessageId ?? this.#startAssistantMessage(active, value);
22324
+ if (active.assistantMessageId === null)
22325
+ return this.#startAssistantMessage(active, value);
22326
+ if (!active.sawStreamedMessageText && !active.sawStreamedMessageReasoning) {
22327
+ const nativeResponseId = assistantMessageId(value);
22328
+ if (nativeResponseId) {
22329
+ active.assistantMessageId = nativeResponseId;
22330
+ active.assistantNativeMessageIdentity ??= { responseId: nativeResponseId };
22331
+ }
22332
+ }
22333
+ return active.assistantMessageId;
21288
22334
  }
21289
22335
  #finalizeAssistantMessage(active, value) {
21290
22336
  const finalText = assistantText(value);
@@ -21297,29 +22343,33 @@ var PiRpcSession = class {
21297
22343
  return;
21298
22344
  }
21299
22345
  active.failure = failure;
21300
- if (active.origin === "autonomous" && isRecord8(value) && value.stopReason === "aborted") {
22346
+ if (active.origin === "autonomous" && piAssistantWasAborted(value)) {
21301
22347
  active.nativeCancellationObserved = true;
21302
22348
  }
21303
22349
  this.#latestCacheHitRatePercent = cacheHitRatePercent;
21304
22350
  const messageId = this.#ensureAssistantMessage(active, value);
21305
- if (!active.sawStreamedMessageReasoning && finalReasoning.length > 0) {
21306
- active.reasoningMessageOpen = true;
21307
- active.onEvent({ type: "reasoning.delta", messageId, delta: finalReasoning });
22351
+ const content = value.content;
22352
+ if (failure === null || !active.sawStreamedMessageReasoning) {
22353
+ this.#emitContent(active, true, active.reasoningStream.finalize(content.flatMap((part, index) => {
22354
+ const text4 = extractReasoningText(part);
22355
+ return text4 === null ? [] : [{ index, text: text4 }];
22356
+ })));
21308
22357
  }
21309
22358
  if (active.reasoningMessageOpen && active.failure === null) {
21310
22359
  active.onEvent({ type: "reasoning.completed", messageId });
21311
22360
  }
21312
- if (!active.sawStreamedMessageText && finalText.length > 0) {
21313
- active.text += finalText;
21314
- active.onEvent({ type: "text.delta", messageId, delta: finalText });
22361
+ if (failure === null || !active.sawStreamedMessageText) {
22362
+ this.#emitContent(active, false, active.textStream.finalize(content.flatMap((part, index) => isRecord9(part) && part.type === "text" && typeof part.text === "string" ? [{ index, text: part.text }] : [])));
21315
22363
  }
21316
22364
  active.assistantMessageId = null;
22365
+ active.assistantNativeMessageIdentity = void 0;
21317
22366
  active.sawStreamedMessageText = false;
21318
22367
  active.sawStreamedMessageReasoning = false;
21319
22368
  active.reasoningMessageOpen = false;
21320
22369
  active.lastFinalizedMessageText = finalText;
21321
22370
  active.lastFinalizedMessageReasoning = finalReasoning;
21322
- active.onEvent({ type: "message.completed", messageId });
22371
+ const phase = piAssistantPhase(value);
22372
+ active.onEvent({ type: "message.completed", messageId, ...phase ? { phase } : {} });
21323
22373
  }
21324
22374
  #write(value) {
21325
22375
  const child = this.#child;
@@ -21337,7 +22387,7 @@ var PiRpcSession = class {
21337
22387
  if (!child?.stdin.writable || this.#closed || this.#failed) {
21338
22388
  return Promise.reject(new Error("Pi RPC stdin is unavailable"));
21339
22389
  }
21340
- const id = `codexhost-${randomUUID5()}`;
22390
+ const id = `codexhost-${randomUUID6()}`;
21341
22391
  return new Promise((resolve, reject) => {
21342
22392
  const pending = {
21343
22393
  command: type,
@@ -21427,9 +22477,16 @@ var PiRpcSession = class {
21427
22477
  } else {
21428
22478
  active.reject(error51);
21429
22479
  }
22480
+ this.#drainDeferredRunFrames();
21430
22481
  }
21431
22482
  #rejectAll(error51) {
22483
+ for (const waiter of this.#runWaiters)
22484
+ waiter.reject(error51);
22485
+ this.#deferredRunFrames = [];
22486
+ this.#deferredRunBytes = 0;
21432
22487
  this.#subagents.close(error51);
22488
+ this.#gotgenesHandler = void 0;
22489
+ this.#gotgenesLatest = void 0;
21433
22490
  for (const pending of this.#pending.values()) {
21434
22491
  if (pending.timeout)
21435
22492
  clearTimeout(pending.timeout);
@@ -21465,7 +22522,7 @@ var piCommandCatalog = harnessCommandCatalogSchema.parse({
21465
22522
  ]
21466
22523
  });
21467
22524
  var DEFAULT_TOOL_OUTPUT_LIMIT = 64e3;
21468
- function isRecord9(value) {
22525
+ function isRecord10(value) {
21469
22526
  return typeof value === "object" && value !== null && !Array.isArray(value);
21470
22527
  }
21471
22528
  function errorMessage(error51) {
@@ -21480,7 +22537,9 @@ var PiAdapterFaultError = class extends Error {
21480
22537
  }
21481
22538
  };
21482
22539
  function normalizedError(error51, fallbackCode) {
21483
- if (isRecord9(error51) && error51.code === "ENOENT") {
22540
+ if (error51 instanceof PiRpcBusyError)
22541
+ return { code: "sessionBusy", message: error51.message, retryable: true };
22542
+ if (isRecord10(error51) && error51.code === "ENOENT") {
21484
22543
  return { code: "notInstalled", message: errorMessage(error51), retryable: false };
21485
22544
  }
21486
22545
  if (error51 instanceof PiAdapterFaultError)
@@ -21543,7 +22602,7 @@ function nativeModelForHistory(state2) {
21543
22602
  return nativeModelFromState(state2);
21544
22603
  }
21545
22604
  function sessionFileFromRef(ref) {
21546
- if (ref.harnessId !== piHarnessId2 || !isRecord9(ref.locator) || typeof ref.locator.sessionFile !== "string" || ref.locator.sessionFile.length === 0) {
22605
+ if (ref.harnessId !== piHarnessId2 || !isRecord10(ref.locator) || typeof ref.locator.sessionFile !== "string" || ref.locator.sessionFile.length === 0) {
21547
22606
  throw new Error("Pi Native Session Ref has no resumable Session file");
21548
22607
  }
21549
22608
  return ref.locator.sessionFile;
@@ -21558,83 +22617,29 @@ function toolFailure(toolName) {
21558
22617
  function nativeText(value) {
21559
22618
  if (typeof value === "string")
21560
22619
  return value;
21561
- if (!isRecord9(value) || !Array.isArray(value.content))
22620
+ if (!isRecord10(value) || !Array.isArray(value.content))
21562
22621
  return "";
21563
- return value.content.filter((content) => isRecord9(content) && content.type === "text" && typeof content.text === "string").map(({ text: text2 }) => text2).join("");
22622
+ return value.content.filter((content) => isRecord10(content) && content.type === "text" && typeof content.text === "string").map(({ text: text4 }) => text4).join("");
21564
22623
  }
21565
22624
  function boundedOutput(value, limit) {
21566
- const text2 = nativeText(value);
21567
- if (text2.length === 0)
22625
+ const text4 = nativeText(value);
22626
+ if (text4.length === 0)
21568
22627
  return void 0;
21569
- const truncated = text2.length > limit;
22628
+ const truncated = text4.length > limit;
21570
22629
  return {
21571
- content: [{ type: "text", text: truncated ? text2.slice(0, limit) : text2 }],
22630
+ content: [{ type: "text", text: truncated ? text4.slice(0, limit) : text4 }],
21572
22631
  ...truncated ? { truncated: true } : {}
21573
22632
  };
21574
22633
  }
21575
22634
  function outputText(output) {
21576
- return output?.content.filter((content) => content.type === "text").map(({ text: text2 }) => text2).join("") ?? "";
21577
- }
21578
- function stringField(value, key) {
21579
- if (!isRecord9(value))
21580
- return void 0;
21581
- const field2 = value[key];
21582
- if (typeof field2 === "string" && field2.length > 0)
21583
- return field2;
21584
- if (isRecord9(value.input)) {
21585
- const nested = value.input[key];
21586
- if (typeof nested === "string" && nested.length > 0)
21587
- return nested;
21588
- }
21589
- if (isRecord9(value.arguments)) {
21590
- const nested = value.arguments[key];
21591
- if (typeof nested === "string" && nested.length > 0)
21592
- return nested;
21593
- }
21594
- return void 0;
22635
+ return output?.content.filter((content) => content.type === "text").map(({ text: text4 }) => text4).join("") ?? "";
21595
22636
  }
21596
22637
  function numberField(value, key) {
21597
- if (!isRecord9(value))
22638
+ if (!isRecord10(value))
21598
22639
  return void 0;
21599
22640
  const field2 = value[key];
21600
22641
  return typeof field2 === "number" || field2 === null ? field2 : void 0;
21601
22642
  }
21602
- function normalizeToolName(name) {
21603
- const lower = name.toLowerCase();
21604
- switch (lower) {
21605
- case "bash":
21606
- case "exec":
21607
- case "terminal":
21608
- case "run":
21609
- return "bash";
21610
- case "read":
21611
- case "read_file":
21612
- case "fileread":
21613
- return "Read";
21614
- case "edit":
21615
- case "edit_file":
21616
- case "fileedit":
21617
- return "Edit";
21618
- case "write":
21619
- case "write_file":
21620
- case "filewrite":
21621
- return "Write";
21622
- case "grep":
21623
- case "grep_search":
21624
- return "Grep";
21625
- case "find":
21626
- case "glob":
21627
- case "find_files":
21628
- return "Glob";
21629
- case "todo":
21630
- return "Todo";
21631
- case "web_search":
21632
- case "websearch":
21633
- return "WebSearch";
21634
- default:
21635
- return name.length > 0 ? `${name[0]?.toUpperCase() ?? ""}${name.slice(1)}` : name;
21636
- }
21637
- }
21638
22643
  function delay(milliseconds) {
21639
22644
  return new Promise((resolve) => setTimeout(resolve, milliseconds));
21640
22645
  }
@@ -21662,6 +22667,8 @@ var PiHarnessSession = class {
21662
22667
  #configuring = false;
21663
22668
  #phase = "open";
21664
22669
  #pendingAutonomousTurns = [];
22670
+ #pendingAutonomousLifecycle = [];
22671
+ #pendingAutonomousLifecycleBytes = 0;
21665
22672
  #starting = null;
21666
22673
  #state = {};
21667
22674
  #transport = null;
@@ -21710,13 +22717,20 @@ var PiHarnessSession = class {
21710
22717
  return this.#transport?.state.sessionId === id;
21711
22718
  }
21712
22719
  async readSubagentHistory(cwd) {
21713
- if (this.#phase !== "open" || path15.resolve(cwd) !== path15.resolve(this.#cwd)) {
22720
+ if (this.#phase !== "open" || path17.resolve(cwd) !== path17.resolve(this.#cwd)) {
21714
22721
  throw new Error("Pi Subagent parent workspace or Session is unavailable");
21715
22722
  }
21716
22723
  return (await this.#ensureTransport()).getEntries();
21717
22724
  }
22725
+ async readGotgenesChild(id, cwd) {
22726
+ const history = await this.readSubagentHistory(cwd);
22727
+ const transport = this.#transport;
22728
+ if (!transport)
22729
+ throw new Error("Pi parent Session is closed");
22730
+ return readGotgenesChild(history, transport.state.sessionId, id, this.#subagents.gotgenes.records.get(id));
22731
+ }
21718
22732
  async inspectSubagent(id, cwd) {
21719
- if (this.#phase !== "open" || path15.resolve(cwd) !== path15.resolve(this.#cwd)) {
22733
+ if (this.#phase !== "open" || path17.resolve(cwd) !== path17.resolve(this.#cwd)) {
21720
22734
  throw new Error("Pi Subagent parent workspace or Session is unavailable");
21721
22735
  }
21722
22736
  const transport = await this.#ensureTransport();
@@ -21784,7 +22798,7 @@ var PiHarnessSession = class {
21784
22798
  }
21785
22799
  };
21786
22800
  }
21787
- if (this.#acceptingTurn || this.#active || this.#configuring) {
22801
+ if (this.#acceptingTurn || this.#active || this.#configuring || this.#transport?.isBusy) {
21788
22802
  return {
21789
22803
  ok: false,
21790
22804
  error: {
@@ -21794,8 +22808,8 @@ var PiHarnessSession = class {
21794
22808
  }
21795
22809
  };
21796
22810
  }
21797
- const text2 = command.input.map((input) => input.text).join("\n");
21798
- if (text2.length === 0) {
22811
+ const text4 = command.input.map((input) => input.text).join("\n");
22812
+ if (text4.length === 0) {
21799
22813
  return {
21800
22814
  ok: false,
21801
22815
  error: {
@@ -21825,6 +22839,9 @@ var PiHarnessSession = class {
21825
22839
  } catch (error51) {
21826
22840
  return { ok: false, error: normalizedError(error51, "protocolError") };
21827
22841
  }
22842
+ if (this.#active || transport.isBusy || this.#pendingAutonomousLifecycle.length > 0 || this.#pendingAutonomousTurns.length > 0) {
22843
+ return { ok: false, error: normalizedError(new PiRpcBusyError(), "sessionBusy") };
22844
+ }
21828
22845
  let resolveCompletion = () => void 0;
21829
22846
  const completion = new Promise((resolve) => {
21830
22847
  resolveCompletion = resolve;
@@ -21845,21 +22862,27 @@ var PiHarnessSession = class {
21845
22862
  interactions: /* @__PURE__ */ new Map(),
21846
22863
  interactionByNativeId: /* @__PURE__ */ new Map(),
21847
22864
  cancellationRequested: false,
22865
+ settling: false,
21848
22866
  beforeNativeTurnKeys: new Set(beforeHistory.turns.map((turn) => turn.nativeTurnRef.nativeTurnKey)),
22867
+ progressItems: /* @__PURE__ */ new Set(),
21849
22868
  completion,
21850
22869
  resolveCompletion
21851
22870
  };
21852
22871
  this.#active = active;
21853
22872
  this.#event({ type: "turn.started", turnId: command.turnId });
21854
22873
  this.#event({ type: "item.started", turnId: command.turnId, item });
21855
- void transport.runTurn(text2, (event) => this.#handleTurnEvent(active, event)).then(async (result) => {
22874
+ void transport.runTurn(text4, (event) => this.#handleTurnEvent(active, event)).then(async (result) => {
22875
+ active.settling = true;
21856
22876
  try {
21857
22877
  const identity = await this.#completedTurnIdentity(active, transport);
21858
22878
  this.#completeTurn(active, result.cancelled ? {
21859
22879
  status: "cancelled",
21860
22880
  reason: "Cancelled by user",
21861
- checkpoint: identity.checkpoint
21862
- } : { status: "succeeded", checkpoint: identity.checkpoint }, result.text, identity.nativeTurnRef);
22881
+ ...identity.checkpoint ? { checkpoint: identity.checkpoint } : {}
22882
+ } : {
22883
+ status: "succeeded",
22884
+ ...identity.checkpoint ? { checkpoint: identity.checkpoint } : {}
22885
+ }, result.text, identity.nativeTurnRef);
21863
22886
  } catch (error51) {
21864
22887
  this.#completeTurn(active, {
21865
22888
  status: "failed",
@@ -21867,6 +22890,7 @@ var PiHarnessSession = class {
21867
22890
  });
21868
22891
  }
21869
22892
  }).catch(async (error51) => {
22893
+ active.settling = true;
21870
22894
  let identity;
21871
22895
  try {
21872
22896
  identity = await this.#completedTurnIdentity(active, transport);
@@ -21875,12 +22899,14 @@ var PiHarnessSession = class {
21875
22899
  this.#completeTurn(active, {
21876
22900
  status: "failed",
21877
22901
  error: normalizedError(error51, "nativeFailure"),
21878
- ...identity ? { checkpoint: identity.checkpoint } : {}
22902
+ ...identity?.checkpoint ? { checkpoint: identity.checkpoint } : {}
21879
22903
  }, void 0, identity?.nativeTurnRef);
21880
22904
  });
21881
22905
  return { ok: true, value: { turnId: command.turnId } };
21882
22906
  } finally {
21883
22907
  this.#acceptingTurn = false;
22908
+ if (this.#transport)
22909
+ this.#drainPendingAutonomousTurns(this.#transport);
21884
22910
  }
21885
22911
  }
21886
22912
  close() {
@@ -22008,6 +23034,8 @@ var PiHarnessSession = class {
22008
23034
  return { ok: true, value: { completed: true } };
22009
23035
  } finally {
22010
23036
  this.#configuring = false;
23037
+ if (this.#transport)
23038
+ this.#drainPendingAutonomousTurns(this.#transport);
22011
23039
  }
22012
23040
  }
22013
23041
  async #selectThinking(command) {
@@ -22082,6 +23110,8 @@ var PiHarnessSession = class {
22082
23110
  return { ok: true, value: { completed: true } };
22083
23111
  } finally {
22084
23112
  this.#configuring = false;
23113
+ if (this.#transport)
23114
+ this.#drainPendingAutonomousTurns(this.#transport);
22085
23115
  }
22086
23116
  }
22087
23117
  async #cancel(command) {
@@ -22092,6 +23122,12 @@ var PiHarnessSession = class {
22092
23122
  error: invalidState("Pi Turn Cancel must reference the active Turn")
22093
23123
  };
22094
23124
  }
23125
+ if (active.settling) {
23126
+ return {
23127
+ ok: false,
23128
+ error: invalidState("Pi Turn has finished native execution and is recording its completion")
23129
+ };
23130
+ }
22095
23131
  if (active.cancellationRequested) {
22096
23132
  return { ok: true, value: { cancellationRequested: true } };
22097
23133
  }
@@ -22206,7 +23242,9 @@ var PiHarnessSession = class {
22206
23242
  interactions: /* @__PURE__ */ new Map(),
22207
23243
  interactionByNativeId: /* @__PURE__ */ new Map(),
22208
23244
  cancellationRequested: false,
23245
+ settling: false,
22209
23246
  beforeNativeTurnKeys: /* @__PURE__ */ new Set(),
23247
+ progressItems: /* @__PURE__ */ new Set(),
22210
23248
  completion,
22211
23249
  resolveCompletion
22212
23250
  };
@@ -22239,6 +23277,8 @@ var PiHarnessSession = class {
22239
23277
  return { ok: true, value: { turnId: command.turnId } };
22240
23278
  } finally {
22241
23279
  this.#acceptingTurn = false;
23280
+ if (this.#transport)
23281
+ this.#drainPendingAutonomousTurns(this.#transport);
22242
23282
  }
22243
23283
  }
22244
23284
  async #ensureTransport() {
@@ -22289,6 +23329,8 @@ var PiHarnessSession = class {
22289
23329
  return transport;
22290
23330
  }).catch(async (error51) => {
22291
23331
  this.#pendingAutonomousTurns = this.#pendingAutonomousTurns.filter((pending) => pending.transport !== transport);
23332
+ this.#pendingAutonomousLifecycle = this.#pendingAutonomousLifecycle.filter((pending) => pending.transport !== transport);
23333
+ this.#pendingAutonomousLifecycleBytes = this.#pendingAutonomousLifecycle.reduce((total, pending) => total + pending.bytes, 0);
22292
23334
  await transport.close().catch(() => void 0);
22293
23335
  if (this.#phase === "open")
22294
23336
  this.#fault(error51);
@@ -22301,6 +23343,11 @@ var PiHarnessSession = class {
22301
23343
  return starting;
22302
23344
  }
22303
23345
  #bindAutonomousTurnHandler(transport) {
23346
+ transport.setGotgenesStatusHandler?.((records, owner) => {
23347
+ if (this.#phase !== "open")
23348
+ return;
23349
+ this.#subagents.observeGotgenes(records, owner === "requested" && this.#active && !this.#active.settling ? { turnId: this.#active.command.turnId, nextItemId: () => this.#newItemId() } : void 0);
23350
+ });
22304
23351
  transport.setSubagentStatusHandler?.((runs) => {
22305
23352
  if (this.#phase !== "open")
22306
23353
  return;
@@ -22312,12 +23359,16 @@ var PiHarnessSession = class {
22312
23359
  transport.setUsageHandler?.((observation) => {
22313
23360
  if (this.#phase !== "open")
22314
23361
  return;
22315
- const record7 = piUsageRecord(observation.message, observation);
22316
- if (record7?.kind === "request")
22317
- this.#event({ type: "usage.request", request: record7.request });
22318
- else if (record7?.kind === "missing")
23362
+ const record9 = piUsageRecord(observation.message, observation);
23363
+ if (record9?.kind === "request")
23364
+ this.#event({ type: "usage.request", request: record9.request });
23365
+ else if (record9?.kind === "missing")
22319
23366
  this.#event({ type: "usage.history", complete: false });
22320
23367
  });
23368
+ if (transport.setAutonomousTurnLifecycleHandler) {
23369
+ transport.setAutonomousTurnLifecycleHandler((update) => this.#handleAutonomousLifecycle(transport, update));
23370
+ return;
23371
+ }
22321
23372
  transport.setAutonomousTurnHandler((turn) => {
22322
23373
  if (this.#phase !== "open")
22323
23374
  return;
@@ -22329,6 +23380,20 @@ var PiHarnessSession = class {
22329
23380
  });
22330
23381
  }
22331
23382
  #drainPendingAutonomousTurns(transport) {
23383
+ if (this.#phase !== "open" || this.#acceptingTurn || this.#configuring)
23384
+ return;
23385
+ for (; ; ) {
23386
+ const pending2 = this.#pendingAutonomousLifecycle[0];
23387
+ if (!pending2 || pending2.transport !== transport || this.#active && this.#active.autonomousRunId !== pending2.update.runId)
23388
+ break;
23389
+ this.#pendingAutonomousLifecycle.shift();
23390
+ this.#pendingAutonomousLifecycleBytes -= pending2.bytes;
23391
+ this.#applyAutonomousLifecycle(transport, pending2.update);
23392
+ if (this.#phase !== "open")
23393
+ return;
23394
+ }
23395
+ if (this.#active)
23396
+ return;
22332
23397
  if (this.#pendingSubagentStatus) {
22333
23398
  this.#subagents.observe(this.#pendingSubagentStatus);
22334
23399
  this.#pendingSubagentStatus = null;
@@ -22341,6 +23406,52 @@ var PiHarnessSession = class {
22341
23406
  this.#handleAutonomousTurn(transport, candidate.turn);
22342
23407
  }
22343
23408
  }
23409
+ #handleAutonomousLifecycle(transport, update) {
23410
+ if (this.#phase === "closing" && this.#transport === transport && update.type !== "started" && this.#active?.autonomousRunId === update.runId) {
23411
+ this.#applyAutonomousLifecycle(transport, update);
23412
+ return;
23413
+ }
23414
+ if (this.#phase !== "open")
23415
+ return;
23416
+ if (this.#transport !== transport || this.#acceptingTurn || this.#configuring || this.#pendingAutonomousLifecycle.length > 0 || this.#active && this.#active.autonomousRunId !== update.runId) {
23417
+ const bytes = Buffer.byteLength(JSON.stringify(update));
23418
+ if (this.#pendingAutonomousLifecycleBytes + bytes > 8 * 1024 * 1024) {
23419
+ this.#fault(new PiAdapterFaultError({
23420
+ code: "protocolError",
23421
+ message: "Pi autonomous lifecycle exceeded its ordered event buffer bound",
23422
+ retryable: false
23423
+ }));
23424
+ return;
23425
+ }
23426
+ this.#pendingAutonomousLifecycle.push({ transport, update, bytes });
23427
+ this.#pendingAutonomousLifecycleBytes += bytes;
23428
+ if (this.#transport === transport)
23429
+ this.#drainPendingAutonomousTurns(transport);
23430
+ return;
23431
+ }
23432
+ this.#applyAutonomousLifecycle(transport, update);
23433
+ }
23434
+ #applyAutonomousLifecycle(transport, update) {
23435
+ if (update.type === "started" && !this.#active) {
23436
+ this.#startAutonomousHostTurn(update.runId);
23437
+ return;
23438
+ }
23439
+ const active = this.#active;
23440
+ if (!active || active.autonomousRunId !== update.runId || update.type === "started") {
23441
+ this.#fault(new PiAdapterFaultError({
23442
+ code: "protocolError",
23443
+ message: "Pi autonomous event has no matching active run",
23444
+ retryable: false
23445
+ }));
23446
+ return;
23447
+ }
23448
+ if (update.type === "event")
23449
+ this.#handleTurnEvent(active, update.event);
23450
+ else {
23451
+ active.settling = true;
23452
+ this.#finishAutonomousHostTurn(transport, active, update.turn);
23453
+ }
23454
+ }
22344
23455
  #handleAutonomousTurn(transport, turn) {
22345
23456
  if (this.#phase !== "open")
22346
23457
  return;
@@ -22352,7 +23463,7 @@ var PiHarnessSession = class {
22352
23463
  }));
22353
23464
  return;
22354
23465
  }
22355
- if (this.#active || this.#acceptingTurn || this.#configuring) {
23466
+ if (this.#active && !this.#active.settling) {
22356
23467
  this.#fault(new PiAdapterFaultError({
22357
23468
  code: "protocolError",
22358
23469
  message: "Pi autonomous Turn overlapped another Host operation",
@@ -22360,7 +23471,22 @@ var PiHarnessSession = class {
22360
23471
  }));
22361
23472
  return;
22362
23473
  }
22363
- const turnId = hostTurnIdSchema.parse(randomUUID6());
23474
+ if (this.#active || this.#acceptingTurn || this.#configuring) {
23475
+ if (this.#pendingAutonomousTurns.length >= 128) {
23476
+ this.#fault(new PiAdapterFaultError({
23477
+ code: "protocolError",
23478
+ message: "Pi autonomous completion queue exceeded its bound",
23479
+ retryable: false
23480
+ }));
23481
+ } else
23482
+ this.#pendingAutonomousTurns.push({ transport, turn });
23483
+ return;
23484
+ }
23485
+ const active = this.#startAutonomousHostTurn();
23486
+ this.#finishAutonomousHostTurn(transport, active, turn);
23487
+ }
23488
+ #startAutonomousHostTurn(runId) {
23489
+ const turnId = hostTurnIdSchema.parse(randomUUID7());
22364
23490
  let resolveCompletion = () => void 0;
22365
23491
  const completion = new Promise((resolve) => {
22366
23492
  resolveCompletion = resolve;
@@ -22372,6 +23498,7 @@ var PiHarnessSession = class {
22372
23498
  };
22373
23499
  const active = {
22374
23500
  command: { type: "turn.start", turnId, input: [] },
23501
+ ...runId ? { autonomousRunId: runId } : {},
22375
23502
  agentItem: item,
22376
23503
  agentMessageId: null,
22377
23504
  compactionItem: null,
@@ -22381,10 +23508,19 @@ var PiHarnessSession = class {
22381
23508
  interactions: /* @__PURE__ */ new Map(),
22382
23509
  interactionByNativeId: /* @__PURE__ */ new Map(),
22383
23510
  cancellationRequested: false,
23511
+ settling: false,
22384
23512
  beforeNativeTurnKeys: /* @__PURE__ */ new Set(),
23513
+ progressItems: /* @__PURE__ */ new Set(),
22385
23514
  completion,
22386
23515
  resolveCompletion
22387
23516
  };
23517
+ this.#active = active;
23518
+ this.#event({ type: "turn.autonomous.started", turnId, input: [] });
23519
+ this.#event({ type: "turn.started", turnId });
23520
+ this.#event({ type: "item.started", turnId, item });
23521
+ return active;
23522
+ }
23523
+ #finishAutonomousHostTurn(transport, active, turn) {
22388
23524
  const nativeTurnRef = turn.nativeTurnKey ? nativeTurnRefSchema.parse({
22389
23525
  harnessId: this.harnessId,
22390
23526
  nativeSessionId: transport.state.sessionId,
@@ -22397,10 +23533,6 @@ var PiHarnessSession = class {
22397
23533
  checkpointId: nativeTurnRef.nativeTurnKey,
22398
23534
  formatVersion: 1
22399
23535
  }) : void 0;
22400
- this.#active = active;
22401
- this.#event({ type: "turn.autonomous.started", turnId, input: [] });
22402
- this.#event({ type: "turn.started", turnId });
22403
- this.#event({ type: "item.started", turnId, item });
22404
23536
  try {
22405
23537
  for (const event of turn.events)
22406
23538
  this.#handleTurnEvent(active, event);
@@ -22470,17 +23602,35 @@ var PiHarnessSession = class {
22470
23602
  if (this.#active !== active || this.#phase === "closed" || this.#phase === "faulted")
22471
23603
  return;
22472
23604
  switch (event.type) {
23605
+ case "progress.message": {
23606
+ if (active.progressItems.has(event.itemId))
23607
+ return;
23608
+ active.progressItems.add(event.itemId);
23609
+ const item = {
23610
+ type: "agentMessage",
23611
+ itemId: event.itemId,
23612
+ text: event.text,
23613
+ phase: "commentary"
23614
+ };
23615
+ this.#event({ type: "item.started", turnId: active.command.turnId, item });
23616
+ this.#completeItem(active, item, { status: "succeeded" });
23617
+ return;
23618
+ }
22473
23619
  case "text.delta":
22474
- this.#activateAgentMessage(active, event.messageId);
23620
+ this.#activateAgentMessage(active, event.messageId, event.nativeMessageIdentity);
23621
+ active.sawAssistantMessage = true;
22475
23622
  this.#appendText(active, event.delta);
22476
23623
  return;
22477
23624
  case "reasoning.delta":
22478
- this.#appendReasoning(active, event.delta);
23625
+ this.#activateAgentMessage(active, event.messageId, event.nativeMessageIdentity);
23626
+ this.#appendReasoning(active, event.delta, event.nativeMessageIdentity);
22479
23627
  return;
22480
23628
  case "reasoning.completed":
22481
23629
  this.#completeReasoning(active, { status: "succeeded" });
22482
23630
  return;
22483
23631
  case "message.completed":
23632
+ if (event.phase && active.agentMessageId === event.messageId && active.agentItem)
23633
+ active.agentItem = { ...active.agentItem, phase: event.phase };
22484
23634
  void this.#refreshUsage(active.command.turnId);
22485
23635
  return;
22486
23636
  case "compaction.started":
@@ -22538,7 +23688,7 @@ var PiHarnessSession = class {
22538
23688
  if (active.interactionByNativeId.has(request.requestId)) {
22539
23689
  throw new Error("Pi Interaction started more than once");
22540
23690
  }
22541
- const interactionId = hostInteractionIdSchema.parse(randomUUID6());
23691
+ const interactionId = hostInteractionIdSchema.parse(randomUUID7());
22542
23692
  const question = request.method === "select" ? {
22543
23693
  id: "answer",
22544
23694
  type: "choice",
@@ -22595,17 +23745,21 @@ var PiHarnessSession = class {
22595
23745
  reason
22596
23746
  });
22597
23747
  }
22598
- #activateAgentMessage(active, messageId) {
23748
+ #activateAgentMessage(active, messageId, nativeMessageIdentity2) {
22599
23749
  if (active.agentMessageId === messageId)
22600
23750
  return;
23751
+ const nativeItemId = piMessageItemId(nativeMessageIdentity2, "assistant");
23752
+ if (nativeItemId && active.agentMessageId === null && active.agentItem?.text === "") {
23753
+ this.#completeAgentItem(active, { status: "succeeded" }, true);
23754
+ }
22601
23755
  if (active.agentMessageId !== null) {
22602
23756
  this.#completeReasoning(active, { status: "succeeded" });
22603
- this.#completeAgentItem(active, { status: "succeeded" }, false);
23757
+ this.#completeAgentItem(active, { status: "succeeded" }, true);
22604
23758
  }
22605
23759
  if (!active.agentItem) {
22606
23760
  active.agentItem = {
22607
23761
  type: "agentMessage",
22608
- itemId: this.#newItemId(),
23762
+ itemId: nativeItemId ?? this.#newItemId(),
22609
23763
  text: ""
22610
23764
  };
22611
23765
  this.#event({
@@ -22615,18 +23769,17 @@ var PiHarnessSession = class {
22615
23769
  });
22616
23770
  }
22617
23771
  active.agentMessageId = messageId;
22618
- active.sawAssistantMessage = true;
22619
23772
  }
22620
- #appendText(active, text2) {
23773
+ #appendText(active, text4) {
22621
23774
  if (active.agentMessageId === null || !active.agentItem) {
22622
23775
  throw new Error("Pi Assistant text arrived outside an active message");
22623
23776
  }
22624
- active.agentItem = { ...active.agentItem, text: active.agentItem.text + text2 };
23777
+ active.agentItem = { ...active.agentItem, text: active.agentItem.text + text4 };
22625
23778
  this.#event({
22626
23779
  type: "item.updated",
22627
23780
  turnId: active.command.turnId,
22628
23781
  itemId: active.agentItem.itemId,
22629
- update: { type: "text.append", text: text2 }
23782
+ update: { type: "text.append", text: text4 }
22630
23783
  });
22631
23784
  }
22632
23785
  #completeAgentItem(active, outcome, completeEmpty) {
@@ -22637,13 +23790,13 @@ var PiHarnessSession = class {
22637
23790
  active.agentItem = null;
22638
23791
  this.#completeItem(active, item, outcome);
22639
23792
  }
22640
- #appendReasoning(active, text2) {
22641
- if (text2.length === 0)
23793
+ #appendReasoning(active, text4, nativeMessageIdentity2) {
23794
+ if (text4.length === 0)
22642
23795
  return;
22643
23796
  if (!active.reasoningItem) {
22644
23797
  active.reasoningItem = {
22645
23798
  type: "reasoning",
22646
- itemId: this.#newItemId(),
23799
+ itemId: piMessageItemId(nativeMessageIdentity2, "reasoning") ?? this.#newItemId(),
22647
23800
  text: ""
22648
23801
  };
22649
23802
  this.#event({
@@ -22654,13 +23807,13 @@ var PiHarnessSession = class {
22654
23807
  }
22655
23808
  active.reasoningItem = {
22656
23809
  ...active.reasoningItem,
22657
- text: active.reasoningItem.text + text2
23810
+ text: active.reasoningItem.text + text4
22658
23811
  };
22659
23812
  this.#event({
22660
23813
  type: "item.updated",
22661
23814
  turnId: active.command.turnId,
22662
23815
  itemId: active.reasoningItem.itemId,
22663
- update: { type: "text.append", text: text2 }
23816
+ update: { type: "text.append", text: text4 }
22664
23817
  });
22665
23818
  }
22666
23819
  #completeReasoning(active, outcome) {
@@ -22673,13 +23826,12 @@ var PiHarnessSession = class {
22673
23826
  #startTool(active, event) {
22674
23827
  if (active.tools.has(event.callId))
22675
23828
  throw new Error("Pi Tool started more than once");
22676
- const normalizedName = normalizeToolName(event.toolName);
22677
- 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;
22678
- const item = command ? {
23829
+ const shell = piToolCommand(event.toolName, event.arguments);
23830
+ const item = shell ? {
22679
23831
  type: "commandExecution",
22680
23832
  itemId: this.#newItemId(),
22681
- command,
22682
- cwd: stringField(event.arguments, "cwd") ?? this.#cwd
23833
+ command: shell.command,
23834
+ cwd: shell.cwd ?? this.#cwd
22683
23835
  } : {
22684
23836
  type: "toolExecution",
22685
23837
  itemId: this.#newItemId(),
@@ -22797,14 +23949,17 @@ var PiHarnessSession = class {
22797
23949
  sessionId: transport.state.sessionId,
22798
23950
  model: nativeModelForHistory(transport.state)
22799
23951
  });
22800
- const created = snapshot.turns.filter((turn2) => !active.beforeNativeTurnKeys.has(turn2.nativeTurnRef.nativeTurnKey));
23952
+ const created = snapshot.turns.filter((turn2) => turn2.input.length > 0 && !active.beforeNativeTurnKeys.has(turn2.nativeTurnRef.nativeTurnKey));
22801
23953
  if (created.length !== 1) {
22802
23954
  throw new Error(`Pi Turn persisted ${created.length} new User Entries; exactly one is required`);
22803
23955
  }
22804
23956
  const turn = created[0];
22805
- if (!turn?.checkpoint)
22806
- throw new Error("Pi Turn has no terminal Checkpoint identity");
22807
- return { nativeTurnRef: turn.nativeTurnRef, checkpoint: turn.checkpoint };
23957
+ if (!turn)
23958
+ throw new Error("Pi Turn has no persisted User identity");
23959
+ return {
23960
+ nativeTurnRef: turn.nativeTurnRef,
23961
+ ...turn.checkpoint ? { checkpoint: turn.checkpoint } : {}
23962
+ };
22808
23963
  }
22809
23964
  #completeTurn(active, outcome, finalText, nativeTurnRef) {
22810
23965
  if (this.#active !== active)
@@ -22833,14 +23988,20 @@ var PiHarnessSession = class {
22833
23988
  });
22834
23989
  active.resolveCompletion();
22835
23990
  queueMicrotask(() => {
22836
- if (this.#phase === "open")
22837
- void this.#refreshUsage(active.command.turnId);
23991
+ if (this.#phase !== "open")
23992
+ return;
23993
+ if (this.#transport)
23994
+ this.#drainPendingAutonomousTurns(this.#transport);
23995
+ void this.#refreshUsage(active.command.turnId);
22838
23996
  });
22839
23997
  }
22840
23998
  #fault(error51) {
22841
23999
  if (this.#phase === "closed" || this.#phase === "faulted")
22842
24000
  return;
22843
24001
  const normalized = normalizedError(error51, "internalError");
24002
+ this.#pendingAutonomousTurns = [];
24003
+ this.#pendingAutonomousLifecycle = [];
24004
+ this.#pendingAutonomousLifecycleBytes = 0;
22844
24005
  if (this.#active) {
22845
24006
  this.#completeTurn(this.#active, { status: "failed", error: normalized });
22846
24007
  }
@@ -22849,6 +24010,9 @@ var PiHarnessSession = class {
22849
24010
  this.#channel.end();
22850
24011
  }
22851
24012
  async #close() {
24013
+ this.#pendingAutonomousTurns = [];
24014
+ this.#pendingAutonomousLifecycle = [];
24015
+ this.#pendingAutonomousLifecycleBytes = 0;
22852
24016
  if (this.#phase === "closed")
22853
24017
  return;
22854
24018
  const wasFaulted = this.#phase === "faulted";
@@ -22881,7 +24045,7 @@ var PiHarnessSession = class {
22881
24045
  this.#channel.emit({ kind: "event", event });
22882
24046
  }
22883
24047
  #newItemId() {
22884
- return hostItemIdSchema.parse(randomUUID6());
24048
+ return hostItemIdSchema.parse(randomUUID7());
22885
24049
  }
22886
24050
  };
22887
24051
  var PiAdapter = class {
@@ -22896,12 +24060,15 @@ var PiAdapter = class {
22896
24060
  if (this.#closePromise || parent.harnessId !== this.harnessId) {
22897
24061
  return { ok: false, error: invalidState("Pi Subagent parent is unavailable") };
22898
24062
  }
24063
+ const gotgenes = parseGotgenesId(nativeSubagentId);
22899
24064
  const workflow = parsePiWorkflowSubagentId(nativeSubagentId);
22900
- if (!workflow)
24065
+ if (!workflow && !gotgenes)
22901
24066
  parsePiSubagentId(nativeSubagentId);
22902
24067
  const live = [...this.#sessions].find((session) => session.ownsNativeSession(parent.nativeSessionId));
22903
24068
  let reply;
22904
24069
  if (live) {
24070
+ if (gotgenes)
24071
+ return await live.readGotgenesChild(gotgenes, cwd);
22905
24072
  if (workflow)
22906
24073
  return await readPiWorkflowChild(await live.readSubagentHistory(cwd), parent.nativeSessionId, workflow);
22907
24074
  reply = await live.inspectSubagent(nativeSubagentId, cwd);
@@ -22913,6 +24080,8 @@ var PiAdapter = class {
22913
24080
  if (transport.state.sessionId !== parent.nativeSessionId)
22914
24081
  throw new Error("Pi Subagent parent identity mismatch");
22915
24082
  await transport.verifySessionCwd(cwd);
24083
+ if (gotgenes)
24084
+ return await readGotgenesChild(await transport.getEntries(), parent.nativeSessionId, gotgenes);
22916
24085
  if (workflow)
22917
24086
  return await readPiWorkflowChild(await transport.getEntries(), parent.nativeSessionId, workflow);
22918
24087
  if (!transport.inspectSubagent)