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