@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.
- package/README.md +2 -2
- package/THIRD_PARTY_NOTICES.txt +6 -2
- package/app/codexhost-distribution.json +1 -1
- package/app/console-server.mjs +55 -20
- package/app/console-web.js +46 -18
- package/app/desktop-controller.mjs +982 -59
- package/app/host-runtime.mjs +3578 -1900
- package/app/plugins/antigravity/plugin.mjs +62 -9
- package/app/plugins/claude-code/plugin.mjs +12 -6
- package/app/plugins/codebuddy/plugin.mjs +10 -0
- package/app/plugins/cursor-cli/plugin.mjs +28 -8
- package/app/plugins/deepseek-harness/plugin.mjs +459 -46
- package/app/plugins/devin/assets/icon.svg +1 -0
- package/app/plugins/devin/manifest.json +30 -0
- package/app/plugins/devin/plugin.mjs +23363 -0
- package/app/plugins/enabled.json +2 -0
- package/app/plugins/grok/plugin.mjs +472 -391
- package/app/plugins/hermes/plugin.mjs +453 -196
- package/app/plugins/kimi-code/plugin.mjs +50 -3
- package/app/plugins/pi/plugin.mjs +1580 -411
- package/app/plugins/qoder/plugin.mjs +9524 -8654
- package/app/plugins/qoder-cn/plugin.mjs +9524 -8654
- package/app/plugins/qwen-code/assets/icon.svg +1 -0
- package/app/plugins/qwen-code/manifest.json +29 -0
- package/app/plugins/qwen-code/plugin.mjs +29298 -0
- package/app/plugins/workbuddy/plugin.mjs +10 -0
- package/app/plugins/zcode/plugin.mjs +142 -9
- package/app/renderer-extension.js +163 -55
- package/bin/codexhost +0 -0
- package/libexec/codexhost-shim +0 -0
- package/libexec/codexhost-updater +0 -0
- package/licenses/Qwen-Code-SDK-LICENSE.txt +203 -0
- package/package.json +2 -2
|
@@ -528,9 +528,9 @@ async function jsonlHeader(file2, match, signal, maxLines = 4) {
|
|
|
528
528
|
continue;
|
|
529
529
|
}
|
|
530
530
|
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
531
|
-
const
|
|
532
|
-
if (match(
|
|
533
|
-
return
|
|
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,
|
|
1321
|
-
if (!
|
|
1320
|
+
function getElementAtPath(obj, path18) {
|
|
1321
|
+
if (!path18)
|
|
1322
1322
|
return obj;
|
|
1323
|
-
return
|
|
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(
|
|
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(
|
|
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,
|
|
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 }, [...
|
|
1886
|
+
issue2.errors.map((issues) => processError({ issues }, [...path18, ...issue2.path]));
|
|
1887
1887
|
} else if (issue2.code === "invalid_key") {
|
|
1888
|
-
processError({ issues: issue2.issues }, [...
|
|
1888
|
+
processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
|
|
1889
1889
|
} else if (issue2.code === "invalid_element") {
|
|
1890
|
-
processError({ issues: issue2.issues }, [...
|
|
1890
|
+
processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
|
|
1891
1891
|
} else {
|
|
1892
|
-
const fullpath = [...
|
|
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,
|
|
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 }, [...
|
|
1923
|
+
issue2.errors.map((issues) => processError({ issues }, [...path18, ...issue2.path]));
|
|
1924
1924
|
} else if (issue2.code === "invalid_key") {
|
|
1925
|
-
processError({ issues: issue2.issues }, [...
|
|
1925
|
+
processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
|
|
1926
1926
|
} else if (issue2.code === "invalid_element") {
|
|
1927
|
-
processError({ issues: issue2.issues }, [...
|
|
1927
|
+
processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
|
|
1928
1928
|
} else {
|
|
1929
|
-
const fullpath = [...
|
|
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
|
|
1962
|
-
for (const seg of
|
|
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 = (
|
|
8193
|
-
return
|
|
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
|
|
14655
|
-
if (
|
|
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 (
|
|
14660
|
-
const key =
|
|
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((
|
|
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((
|
|
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
|
|
16723
|
-
firstMessage = sessionImportTitle(
|
|
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
|
|
17237
|
-
return
|
|
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(
|
|
17374
|
-
const last =
|
|
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:
|
|
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:
|
|
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(
|
|
17783
|
-
const hasTrailingNl =
|
|
17784
|
-
const result =
|
|
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-
|
|
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
|
|
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
|
|
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 || !
|
|
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) || !
|
|
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 && !
|
|
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
|
|
18409
|
+
return PREFIX2 + Buffer.from(JSON.stringify([address.workflowRunId, address.childId])).toString("base64url");
|
|
18077
18410
|
}
|
|
18078
18411
|
function parsePiWorkflowSubagentId(id) {
|
|
18079
|
-
if (!id.startsWith(
|
|
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(
|
|
18084
|
-
if (!Array.isArray(value) || value.length !== 2 || !
|
|
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-${
|
|
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((
|
|
18747
|
+
items: texts.map((text4, index) => ({
|
|
18404
18748
|
item: {
|
|
18405
18749
|
type: "agentMessage",
|
|
18406
|
-
text:
|
|
18407
|
-
itemId: hostItemIdSchema.parse(`pi-subagent-${
|
|
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("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
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
|
|
19028
|
+
function isRecord5(value) {
|
|
18558
19029
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18559
19030
|
}
|
|
18560
|
-
function
|
|
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) =>
|
|
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) =>
|
|
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" &&
|
|
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 (
|
|
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" ||
|
|
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
|
|
18647
|
-
return
|
|
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
|
|
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 (!
|
|
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 &&
|
|
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:
|
|
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
|
|
18729
|
-
|
|
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 =
|
|
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
|
|
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 (!
|
|
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" &&
|
|
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 (!
|
|
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 (!
|
|
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 && !
|
|
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
|
-
...
|
|
18905
|
-
...
|
|
18906
|
-
...
|
|
18907
|
-
...
|
|
18908
|
-
...
|
|
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 (!
|
|
19436
|
+
if (!isRecord6(message3) || message3.role !== "assistant")
|
|
18928
19437
|
return null;
|
|
18929
|
-
const usage =
|
|
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
|
|
18967
|
-
if (
|
|
18968
|
-
requests.push(
|
|
18969
|
-
else if (
|
|
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
|
|
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) =>
|
|
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, (
|
|
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
|
|
19006
|
-
if (
|
|
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(
|
|
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
|
|
19032
|
-
import
|
|
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
|
|
19550
|
+
return path8.join(environment.HOME ?? environment.USERPROFILE ?? homedir3(), ".pi", "agent");
|
|
19042
19551
|
}
|
|
19043
|
-
var
|
|
19552
|
+
var record6 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
19044
19553
|
async function deepSeekApiKey(environment) {
|
|
19045
|
-
const auth =
|
|
19046
|
-
const 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 =
|
|
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(
|
|
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 =
|
|
19591
|
+
const data = record6(payload);
|
|
19083
19592
|
if (!Array.isArray(data.balance_infos))
|
|
19084
19593
|
return null;
|
|
19085
|
-
const first =
|
|
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 =
|
|
19115
|
-
const 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 =
|
|
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
|
|
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
|
|
19188
|
-
import
|
|
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 =
|
|
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 =
|
|
19725
|
+
let directory = path9.dirname(executable);
|
|
19217
19726
|
while (true) {
|
|
19218
|
-
for (const candidate of [directory,
|
|
19727
|
+
for (const candidate of [directory, path9.join(directory, PI_PACKAGE_PATH)]) {
|
|
19219
19728
|
try {
|
|
19220
|
-
const manifest = JSON.parse(fs2.readFileSync(
|
|
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 =
|
|
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(
|
|
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 =
|
|
19243
|
-
const relative =
|
|
19244
|
-
if (relative === ".." || relative.startsWith(`..${
|
|
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 =
|
|
19254
|
-
return resolved ===
|
|
19762
|
+
const resolved = path9.resolve(cwd);
|
|
19763
|
+
return resolved === path9.parse(resolved).root;
|
|
19255
19764
|
}
|
|
19256
19765
|
function writableDirectory(candidate) {
|
|
19257
|
-
if (!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
|
|
19779
|
+
return path9.resolve(inputCwd);
|
|
19271
19780
|
}
|
|
19272
|
-
const candidates = [environment.USERPROFILE, environment.HOME,
|
|
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 ?
|
|
19787
|
+
return inputCwd && inputCwd.length > 0 ? path9.resolve(inputCwd) : process.cwd();
|
|
19279
19788
|
}
|
|
19280
19789
|
|
|
19281
19790
|
// dist/pi-credential-imports.js
|
|
19282
|
-
var
|
|
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}.${
|
|
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(
|
|
19333
|
-
rmSync(
|
|
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(
|
|
19346
|
-
const ai =
|
|
19347
|
-
const all = await import(pathToFileURL(
|
|
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(
|
|
19351
|
-
xai: pathToFileURL(
|
|
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(
|
|
19366
|
-
env: { ...environment, PI_CODING_AGENT_DIR:
|
|
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 ??
|
|
19397
|
-
const authPath =
|
|
19398
|
-
const extensionsDir =
|
|
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) =>
|
|
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(
|
|
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
|
|
19410
|
-
if (!object2(
|
|
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:
|
|
19414
|
-
source:
|
|
19415
|
-
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 =
|
|
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(
|
|
19941
|
+
if (!entry.startsWith(PREFIX3))
|
|
19433
19942
|
continue;
|
|
19434
|
-
const name = entry.slice(
|
|
19943
|
+
const name = entry.slice(PREFIX3.length);
|
|
19435
19944
|
if (!credentialImportNameSchema.safeParse(name).success)
|
|
19436
19945
|
continue;
|
|
19437
|
-
if (!existsSync(
|
|
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((
|
|
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 =
|
|
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 =
|
|
19493
|
-
const
|
|
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 =
|
|
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(
|
|
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(
|
|
19513
|
-
writeFileSync(
|
|
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 =
|
|
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
|
|
19568
|
-
import { mkdir, readFile as
|
|
19569
|
-
import { homedir as
|
|
19570
|
-
import
|
|
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 =
|
|
19621
|
-
const dataDirectory = environment.CODEXHOST_DATA_DIR ??
|
|
19622
|
-
const directory =
|
|
19623
|
-
const file2 =
|
|
19624
|
-
if (await
|
|
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
|
|
19627
|
-
const temporary = `${file2}.${
|
|
20135
|
+
await mkdir2(directory, { recursive: true });
|
|
20136
|
+
const temporary = `${file2}.${randomUUID3()}.tmp`;
|
|
19628
20137
|
try {
|
|
19629
|
-
await
|
|
20138
|
+
await writeFile3(temporary, PI_FAST_EXTENSION, { mode: 384 });
|
|
19630
20139
|
try {
|
|
19631
|
-
await
|
|
20140
|
+
await rename2(temporary, file2);
|
|
19632
20141
|
} catch (error51) {
|
|
19633
|
-
if (await
|
|
20142
|
+
if (await readFile3(file2, "utf8").catch(() => "") !== PI_FAST_EXTENSION)
|
|
19634
20143
|
throw error51;
|
|
19635
20144
|
}
|
|
19636
20145
|
} finally {
|
|
19637
|
-
await
|
|
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
|
|
19655
|
-
import { link, open as open2, rm as
|
|
19656
|
-
import
|
|
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
|
|
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 (!
|
|
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 || !
|
|
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 =
|
|
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(
|
|
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
|
|
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
|
|
19815
|
-
import
|
|
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
|
|
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
|
|
19822
|
-
function
|
|
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 (!
|
|
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 (!
|
|
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 || !
|
|
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 =
|
|
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 (!
|
|
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 (!
|
|
20396
|
+
if (!record7(details) || !Array.isArray(details.results))
|
|
19886
20397
|
break;
|
|
19887
|
-
const result = details.results.findLast((candidate) =>
|
|
19888
|
-
if (!
|
|
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
|
|
19935
|
-
function
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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" || !
|
|
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(
|
|
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
|
|
20075
|
-
import
|
|
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
|
|
20098
|
-
const name = typeof
|
|
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
|
|
20105
|
-
...typeof
|
|
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
|
|
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 =
|
|
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
|
|
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 (!
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 || !
|
|
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 =
|
|
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 =
|
|
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 || !
|
|
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 (!
|
|
21095
|
+
if (!isRecord9(value) || value.role !== "assistant" || !Array.isArray(value.content))
|
|
20330
21096
|
return null;
|
|
20331
|
-
return value.content.filter((content) =>
|
|
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 (!
|
|
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 (!
|
|
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
|
|
20344
|
-
return typeof
|
|
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 (!
|
|
21115
|
+
if (!isRecord9(value) || value.role !== "assistant" || !Array.isArray(value.content))
|
|
20350
21116
|
return null;
|
|
20351
|
-
return value.content.map(extractReasoningText).filter((
|
|
21117
|
+
return value.content.map(extractReasoningText).filter((text4) => typeof text4 === "string").join("");
|
|
20352
21118
|
}
|
|
20353
21119
|
function assistantFailure(value) {
|
|
20354
|
-
if (!
|
|
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 (!
|
|
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 =
|
|
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
|
-
|
|
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 &&
|
|
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" &&
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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(
|
|
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
|
|
20740
|
-
throw new
|
|
20741
|
-
if (
|
|
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
|
-
|
|
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 (!
|
|
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" :
|
|
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" &&
|
|
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 :
|
|
20968
|
-
|
|
20969
|
-
|
|
20970
|
-
|
|
20971
|
-
active.
|
|
20972
|
-
active.
|
|
20973
|
-
|
|
20974
|
-
|
|
20975
|
-
active.
|
|
20976
|
-
|
|
20977
|
-
|
|
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
|
-
...
|
|
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) =>
|
|
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 || !
|
|
21996
|
+
if (active.origin !== "autonomous" || !active.autonomousEvents || !active.autonomousRunId) {
|
|
21044
21997
|
return;
|
|
21045
21998
|
}
|
|
21046
21999
|
try {
|
|
21047
|
-
|
|
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
|
-
|
|
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 (
|
|
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 (
|
|
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
|
-
|
|
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 =
|
|
21217
|
-
|
|
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.#
|
|
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.
|
|
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
|
|
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
|
-
|
|
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" &&
|
|
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
|
-
|
|
21306
|
-
|
|
21307
|
-
active
|
|
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
|
|
21313
|
-
active.text
|
|
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
|
-
|
|
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-${
|
|
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
|
|
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 (
|
|
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 || !
|
|
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 (!
|
|
22620
|
+
if (!isRecord10(value) || !Array.isArray(value.content))
|
|
21562
22621
|
return "";
|
|
21563
|
-
return value.content.filter((content) =>
|
|
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
|
|
21567
|
-
if (
|
|
22625
|
+
const text4 = nativeText(value);
|
|
22626
|
+
if (text4.length === 0)
|
|
21568
22627
|
return void 0;
|
|
21569
|
-
const truncated =
|
|
22628
|
+
const truncated = text4.length > limit;
|
|
21570
22629
|
return {
|
|
21571
|
-
content: [{ type: "text", text: truncated ?
|
|
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:
|
|
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 (!
|
|
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" ||
|
|
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" ||
|
|
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
|
|
21798
|
-
if (
|
|
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(
|
|
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
|
-
} : {
|
|
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
|
|
22316
|
-
if (
|
|
22317
|
-
this.#event({ type: "usage.request", request:
|
|
22318
|
-
else if (
|
|
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
|
|
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
|
-
|
|
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.#
|
|
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(
|
|
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" },
|
|
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,
|
|
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 +
|
|
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:
|
|
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,
|
|
22641
|
-
if (
|
|
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 +
|
|
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:
|
|
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
|
|
22677
|
-
const
|
|
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:
|
|
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
|
|
22806
|
-
throw new Error("Pi Turn has no
|
|
22807
|
-
return {
|
|
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
|
|
22837
|
-
|
|
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(
|
|
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)
|