@liberseek/boft-cli-win32-arm64 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/THIRD_PARTY_NOTICES.txt +0 -4
- package/app/codexhost-distribution.json +1 -1
- package/app/desktop-controller.mjs +256 -179
- package/app/host-runtime.mjs +646 -323
- package/app/plugins/antigravity/plugin.mjs +123 -1
- package/app/plugins/claude-code/plugin.mjs +252 -46
- package/app/plugins/codebuddy/plugin.mjs +2287 -879
- package/app/plugins/cursor-cli/plugin.mjs +35756 -10755
- package/app/plugins/deepseek-harness/plugin.mjs +70 -0
- package/app/plugins/enabled.json +1 -0
- package/app/plugins/grok/plugin.mjs +193 -82
- package/app/plugins/hermes/plugin.mjs +2444 -94
- package/app/plugins/kiro-cli/plugin.mjs +70 -0
- package/app/plugins/muse/plugin.mjs +70 -0
- package/app/plugins/omp/plugin.mjs +92 -4
- package/app/plugins/opencode/plugin.mjs +70 -0
- package/app/plugins/pi/plugin.mjs +2139 -973
- package/app/plugins/qoder/plugin.mjs +71 -9
- package/app/plugins/qoder-cn/plugin.mjs +71 -9
- package/app/plugins/workbuddy/assets/icon.svg +29 -0
- package/app/plugins/workbuddy/manifest.json +14 -0
- package/app/plugins/workbuddy/plugin.mjs +25007 -0
- package/app/renderer-extension.js +2874 -1408
- package/bin/boft.exe +0 -0
- package/libexec/boft-node-repl.exe +0 -0
- package/libexec/boft-shim.exe +0 -0
- package/libexec/boft-updater.exe +0 -0
- package/package.json +1 -1
- package/licenses/opencodex-LICENSE.txt +0 -21
|
@@ -5,9 +5,15 @@ var __export = (target, all) => {
|
|
|
5
5
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
-
// dist/pi-
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
8
|
+
// dist/pi-credential-imports.js
|
|
9
|
+
import { randomUUID } from "node:crypto";
|
|
10
|
+
import { execFile } from "node:child_process";
|
|
11
|
+
import { promisify } from "node:util";
|
|
12
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync, readdirSync, lstatSync, renameSync, rmdirSync } from "node:fs";
|
|
13
|
+
import { realpath } from "node:fs/promises";
|
|
14
|
+
import os2 from "node:os";
|
|
15
|
+
import path3 from "node:path";
|
|
16
|
+
import { pathToFileURL } from "node:url";
|
|
11
17
|
|
|
12
18
|
// ../../../node_modules/zod/v4/classic/external.js
|
|
13
19
|
var external_exports = {};
|
|
@@ -731,9 +737,9 @@ function floatSafeRemainder(val, step) {
|
|
|
731
737
|
return ratio - roundedRatio;
|
|
732
738
|
}
|
|
733
739
|
var EVALUATING = /* @__PURE__ */ Symbol("evaluating");
|
|
734
|
-
function defineLazy(
|
|
740
|
+
function defineLazy(object3, key, getter) {
|
|
735
741
|
let value = void 0;
|
|
736
|
-
Object.defineProperty(
|
|
742
|
+
Object.defineProperty(object3, key, {
|
|
737
743
|
get() {
|
|
738
744
|
if (value === EVALUATING) {
|
|
739
745
|
return void 0;
|
|
@@ -745,7 +751,7 @@ function defineLazy(object2, key, getter) {
|
|
|
745
751
|
return value;
|
|
746
752
|
},
|
|
747
753
|
set(v) {
|
|
748
|
-
Object.defineProperty(
|
|
754
|
+
Object.defineProperty(object3, key, {
|
|
749
755
|
value: v
|
|
750
756
|
// configurable: true,
|
|
751
757
|
});
|
|
@@ -775,10 +781,10 @@ function mergeDefs(...defs) {
|
|
|
775
781
|
function cloneDef(schema) {
|
|
776
782
|
return mergeDefs(schema._zod.def);
|
|
777
783
|
}
|
|
778
|
-
function getElementAtPath(obj,
|
|
779
|
-
if (!
|
|
784
|
+
function getElementAtPath(obj, path10) {
|
|
785
|
+
if (!path10)
|
|
780
786
|
return obj;
|
|
781
|
-
return
|
|
787
|
+
return path10.reduce((acc, key) => acc?.[key], obj);
|
|
782
788
|
}
|
|
783
789
|
function promiseAllObject(promisesObj) {
|
|
784
790
|
const keys = Object.keys(promisesObj);
|
|
@@ -1187,11 +1193,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
1187
1193
|
}
|
|
1188
1194
|
return false;
|
|
1189
1195
|
}
|
|
1190
|
-
function prefixIssues(
|
|
1196
|
+
function prefixIssues(path10, issues) {
|
|
1191
1197
|
return issues.map((iss) => {
|
|
1192
1198
|
var _a3;
|
|
1193
1199
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
1194
|
-
iss.path.unshift(
|
|
1200
|
+
iss.path.unshift(path10);
|
|
1195
1201
|
return iss;
|
|
1196
1202
|
});
|
|
1197
1203
|
}
|
|
@@ -1338,16 +1344,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
1338
1344
|
}
|
|
1339
1345
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
1340
1346
|
const fieldErrors = { _errors: [] };
|
|
1341
|
-
const processError = (error52,
|
|
1347
|
+
const processError = (error52, path10 = []) => {
|
|
1342
1348
|
for (const issue2 of error52.issues) {
|
|
1343
1349
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
1344
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
1350
|
+
issue2.errors.map((issues) => processError({ issues }, [...path10, ...issue2.path]));
|
|
1345
1351
|
} else if (issue2.code === "invalid_key") {
|
|
1346
|
-
processError({ issues: issue2.issues }, [...
|
|
1352
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
1347
1353
|
} else if (issue2.code === "invalid_element") {
|
|
1348
|
-
processError({ issues: issue2.issues }, [...
|
|
1354
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
1349
1355
|
} else {
|
|
1350
|
-
const fullpath = [...
|
|
1356
|
+
const fullpath = [...path10, ...issue2.path];
|
|
1351
1357
|
if (fullpath.length === 0) {
|
|
1352
1358
|
fieldErrors._errors.push(mapper(issue2));
|
|
1353
1359
|
} else {
|
|
@@ -1374,17 +1380,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
1374
1380
|
}
|
|
1375
1381
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
1376
1382
|
const result = { errors: [] };
|
|
1377
|
-
const processError = (error52,
|
|
1383
|
+
const processError = (error52, path10 = []) => {
|
|
1378
1384
|
var _a3, _b;
|
|
1379
1385
|
for (const issue2 of error52.issues) {
|
|
1380
1386
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
1381
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
1387
|
+
issue2.errors.map((issues) => processError({ issues }, [...path10, ...issue2.path]));
|
|
1382
1388
|
} else if (issue2.code === "invalid_key") {
|
|
1383
|
-
processError({ issues: issue2.issues }, [...
|
|
1389
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
1384
1390
|
} else if (issue2.code === "invalid_element") {
|
|
1385
|
-
processError({ issues: issue2.issues }, [...
|
|
1391
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
1386
1392
|
} else {
|
|
1387
|
-
const fullpath = [...
|
|
1393
|
+
const fullpath = [...path10, ...issue2.path];
|
|
1388
1394
|
if (fullpath.length === 0) {
|
|
1389
1395
|
result.errors.push(mapper(issue2));
|
|
1390
1396
|
continue;
|
|
@@ -1416,8 +1422,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
1416
1422
|
}
|
|
1417
1423
|
function toDotPath(_path) {
|
|
1418
1424
|
const segs = [];
|
|
1419
|
-
const
|
|
1420
|
-
for (const seg of
|
|
1425
|
+
const path10 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
1426
|
+
for (const seg of path10) {
|
|
1421
1427
|
if (typeof seg === "number")
|
|
1422
1428
|
segs.push(`[${seg}]`);
|
|
1423
1429
|
else if (typeof seg === "symbol")
|
|
@@ -2670,9 +2676,9 @@ var $ZodE164 = /* @__PURE__ */ $constructor("$ZodE164", (inst, def) => {
|
|
|
2670
2676
|
def.pattern ?? (def.pattern = e164);
|
|
2671
2677
|
$ZodStringFormat.init(inst, def);
|
|
2672
2678
|
});
|
|
2673
|
-
function isValidJWT(
|
|
2679
|
+
function isValidJWT(token2, algorithm = null) {
|
|
2674
2680
|
try {
|
|
2675
|
-
const tokensParts =
|
|
2681
|
+
const tokensParts = token2.split(".");
|
|
2676
2682
|
if (tokensParts.length !== 3)
|
|
2677
2683
|
return false;
|
|
2678
2684
|
const [header] = tokensParts;
|
|
@@ -7647,8 +7653,8 @@ function ko_default() {
|
|
|
7647
7653
|
}
|
|
7648
7654
|
|
|
7649
7655
|
// ../../../node_modules/zod/v4/locales/lt.js
|
|
7650
|
-
var capitalizeFirstCharacter = (
|
|
7651
|
-
return
|
|
7656
|
+
var capitalizeFirstCharacter = (text2) => {
|
|
7657
|
+
return text2.charAt(0).toUpperCase() + text2.slice(1);
|
|
7652
7658
|
};
|
|
7653
7659
|
function getUnitTypeFromNumber(number4) {
|
|
7654
7660
|
const abs = Math.abs(number4);
|
|
@@ -14109,13 +14115,13 @@ function resolveRef(ref, ctx) {
|
|
|
14109
14115
|
if (!ref.startsWith("#")) {
|
|
14110
14116
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
14111
14117
|
}
|
|
14112
|
-
const
|
|
14113
|
-
if (
|
|
14118
|
+
const path10 = ref.slice(1).split("/").filter(Boolean);
|
|
14119
|
+
if (path10.length === 0) {
|
|
14114
14120
|
return ctx.rootSchema;
|
|
14115
14121
|
}
|
|
14116
14122
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
14117
|
-
if (
|
|
14118
|
-
const key =
|
|
14123
|
+
if (path10[0] === defsKey) {
|
|
14124
|
+
const key = path10[1];
|
|
14119
14125
|
if (!key || !ctx.defs[key]) {
|
|
14120
14126
|
throw new Error(`Reference not found: ${ref}`);
|
|
14121
14127
|
}
|
|
@@ -14523,6 +14529,61 @@ function date4(params) {
|
|
|
14523
14529
|
// ../../../node_modules/zod/v4/classic/external.js
|
|
14524
14530
|
config(en_default());
|
|
14525
14531
|
|
|
14532
|
+
// ../../shared-contracts/dist/credential-imports.js
|
|
14533
|
+
var credentialSourceSchema = external_exports.object({
|
|
14534
|
+
id: external_exports.string().min(1).max(256),
|
|
14535
|
+
harnessId: external_exports.string().min(1),
|
|
14536
|
+
label: external_exports.string().min(1).max(512),
|
|
14537
|
+
provider: external_exports.enum(["openai-codex", "xai"])
|
|
14538
|
+
}).strict();
|
|
14539
|
+
var credentialImportNameSchema = external_exports.string().regex(/^[a-z][a-z0-9-]{0,47}$/);
|
|
14540
|
+
var credentialImportRecordSchema = external_exports.object({
|
|
14541
|
+
name: credentialImportNameSchema,
|
|
14542
|
+
source: credentialSourceSchema,
|
|
14543
|
+
importedAt: external_exports.string()
|
|
14544
|
+
}).strict();
|
|
14545
|
+
var credentialImportsRequestSchema = external_exports.discriminatedUnion("action", [
|
|
14546
|
+
external_exports.object({ action: external_exports.literal("list") }).strict(),
|
|
14547
|
+
external_exports.object({
|
|
14548
|
+
action: external_exports.literal("import"),
|
|
14549
|
+
sourceId: external_exports.string().min(1).max(256),
|
|
14550
|
+
name: credentialImportNameSchema,
|
|
14551
|
+
confirmed: external_exports.literal(true)
|
|
14552
|
+
}).strict(),
|
|
14553
|
+
external_exports.object({
|
|
14554
|
+
action: external_exports.literal("reimport"),
|
|
14555
|
+
sourceId: external_exports.string().min(1).max(256),
|
|
14556
|
+
name: credentialImportNameSchema,
|
|
14557
|
+
confirmed: external_exports.literal(true)
|
|
14558
|
+
}).strict(),
|
|
14559
|
+
external_exports.object({
|
|
14560
|
+
action: external_exports.literal("remove"),
|
|
14561
|
+
name: credentialImportNameSchema,
|
|
14562
|
+
confirmed: external_exports.literal(true)
|
|
14563
|
+
}).strict()
|
|
14564
|
+
]);
|
|
14565
|
+
var credentialOtherLoginSchema = external_exports.object({
|
|
14566
|
+
provider: external_exports.string().min(1).max(128),
|
|
14567
|
+
type: external_exports.enum(["oauth", "api_key", "unknown"]),
|
|
14568
|
+
/** Best-effort account label (e.g. the email in a Codex token), derived locally when present. */
|
|
14569
|
+
label: external_exports.string().min(1).max(512).optional(),
|
|
14570
|
+
/** Recognized credential vendor, derived from the OAuth token issuer. Absent when unknown. */
|
|
14571
|
+
vendor: external_exports.enum(["openai-codex", "xai"]).optional()
|
|
14572
|
+
}).strict();
|
|
14573
|
+
var credentialImportsResultSchema = external_exports.object({
|
|
14574
|
+
sources: external_exports.array(credentialSourceSchema),
|
|
14575
|
+
targets: external_exports.array(external_exports.object({
|
|
14576
|
+
harnessId: external_exports.string(),
|
|
14577
|
+
providers: external_exports.array(external_exports.enum(["openai-codex", "xai"])),
|
|
14578
|
+
imports: external_exports.array(credentialImportRecordSchema),
|
|
14579
|
+
others: external_exports.array(credentialOtherLoginSchema).default([])
|
|
14580
|
+
}).strict())
|
|
14581
|
+
}).strict();
|
|
14582
|
+
var credentialImportsParamsSchema = external_exports.object({
|
|
14583
|
+
targetHarnessId: external_exports.string().min(1).max(128).optional(),
|
|
14584
|
+
request: credentialImportsRequestSchema
|
|
14585
|
+
}).strict();
|
|
14586
|
+
|
|
14526
14587
|
// ../../shared-contracts/dist/version.js
|
|
14527
14588
|
var WORKSPACE_CONTRACT_VERSION = 1;
|
|
14528
14589
|
|
|
@@ -14938,8 +14999,8 @@ var harnessConfigurationStateSchema = external_exports.object({
|
|
|
14938
14999
|
effectiveThinkingOptionId: harnessThinkingOptionIdSchema.optional(),
|
|
14939
15000
|
availableThinkingOptions: harnessThinkingOptionsSchema.optional(),
|
|
14940
15001
|
effectivePermissionModeId: harnessPermissionModeIdSchema.optional()
|
|
14941
|
-
}).strict().superRefine((
|
|
14942
|
-
if (
|
|
15002
|
+
}).strict().superRefine((state2, context) => {
|
|
15003
|
+
if (state2.effectiveThinkingOptionId && state2.availableThinkingOptions && !state2.availableThinkingOptions.some(({ id }) => id === state2.effectiveThinkingOptionId)) {
|
|
14943
15004
|
context.addIssue({
|
|
14944
15005
|
code: "custom",
|
|
14945
15006
|
message: "Effective Thinking option must be currently available",
|
|
@@ -15072,6 +15133,8 @@ var pluginPresentationShape = {
|
|
|
15072
15133
|
id: harnessPluginIdSchema,
|
|
15073
15134
|
name: external_exports.string().trim().min(1).max(128),
|
|
15074
15135
|
version: external_exports.string().min(1).max(128),
|
|
15136
|
+
/** The factory accepts a persisted local entrypoint through its construction context. */
|
|
15137
|
+
launchCommand: external_exports.literal(true).optional(),
|
|
15075
15138
|
links: external_exports.object({
|
|
15076
15139
|
documentation: documentationUrlSchema.optional(),
|
|
15077
15140
|
installation: documentationUrlSchema.optional()
|
|
@@ -15109,6 +15172,19 @@ var harnessPluginRouteSchema = external_exports.object({
|
|
|
15109
15172
|
permissionModeId: harnessPermissionModeIdSchema.optional()
|
|
15110
15173
|
}).strict();
|
|
15111
15174
|
|
|
15175
|
+
// ../../shared-contracts/dist/harness-launch-settings.js
|
|
15176
|
+
var harnessLaunchPathSchema = external_exports.string().trim().min(1).max(4096).refine((value) => !/[\u0000\r\n]/u.test(value), "Invalid entrypoint path");
|
|
15177
|
+
var harnessLaunchSettingsGetSchema = external_exports.object({
|
|
15178
|
+
harnessId: harnessPluginIdSchema
|
|
15179
|
+
}).strict();
|
|
15180
|
+
var harnessLaunchSettingsSetSchema = harnessLaunchSettingsGetSchema.extend({
|
|
15181
|
+
path: harnessLaunchPathSchema.nullable()
|
|
15182
|
+
});
|
|
15183
|
+
var harnessLaunchSettingsSchema = external_exports.object({
|
|
15184
|
+
path: harnessLaunchPathSchema.nullable(),
|
|
15185
|
+
restartRequired: external_exports.boolean()
|
|
15186
|
+
}).strict();
|
|
15187
|
+
|
|
15112
15188
|
// ../../shared-contracts/dist/codex-accounts.js
|
|
15113
15189
|
var accountIdSchema = external_exports.string().min(1).max(256).regex(/^[A-Za-z0-9._~-]+$/u);
|
|
15114
15190
|
var nonBlankTextSchema3 = external_exports.string().trim().min(1);
|
|
@@ -15399,149 +15475,1103 @@ var updateStatusResultSchema = external_exports.strictObject({
|
|
|
15399
15475
|
// ../../shared-contracts/dist/index.js
|
|
15400
15476
|
var workspaceContractVersionSchema = external_exports.literal(WORKSPACE_CONTRACT_VERSION);
|
|
15401
15477
|
|
|
15402
|
-
// dist/
|
|
15403
|
-
import
|
|
15404
|
-
import { link, open as open2, rm } from "node:fs/promises";
|
|
15478
|
+
// ../../harness-discovery/dist/environment.js
|
|
15479
|
+
import fs from "node:fs";
|
|
15405
15480
|
import path from "node:path";
|
|
15406
|
-
|
|
15407
|
-
|
|
15408
|
-
var PI_MODEL_REF_PREFIX = "pi-model-v1.";
|
|
15409
|
-
var PI_DRAFT_THINKING_OPTION_IDS = [
|
|
15410
|
-
"off",
|
|
15411
|
-
"minimal",
|
|
15412
|
-
"low",
|
|
15413
|
-
"medium",
|
|
15414
|
-
"high",
|
|
15415
|
-
"xhigh",
|
|
15416
|
-
"max"
|
|
15417
|
-
].map((id) => harnessThinkingOptionIdSchema.parse(id));
|
|
15418
|
-
var PI_THINKING_LABELS = {
|
|
15419
|
-
off: "Off",
|
|
15420
|
-
minimal: "Minimal",
|
|
15421
|
-
low: "Low",
|
|
15422
|
-
medium: "Medium",
|
|
15423
|
-
high: "High",
|
|
15424
|
-
xhigh: "Extra High",
|
|
15425
|
-
max: "Max"
|
|
15426
|
-
};
|
|
15427
|
-
function compareText(left, right) {
|
|
15428
|
-
return left < right ? -1 : left > right ? 1 : 0;
|
|
15481
|
+
function targetPath(platform) {
|
|
15482
|
+
return platform === "win32" ? path.win32 : path.posix;
|
|
15429
15483
|
}
|
|
15430
|
-
function
|
|
15431
|
-
|
|
15432
|
-
|
|
15484
|
+
function environmentValue(environment, name) {
|
|
15485
|
+
const lowered = name.toLowerCase();
|
|
15486
|
+
for (const [key, value] of Object.entries(environment)) {
|
|
15487
|
+
if (key.toLowerCase() === lowered)
|
|
15488
|
+
return value;
|
|
15489
|
+
}
|
|
15490
|
+
return void 0;
|
|
15433
15491
|
}
|
|
15434
|
-
function
|
|
15435
|
-
|
|
15436
|
-
assertNativePart(model.id, "Model id");
|
|
15437
|
-
const encoded = Buffer.from(JSON.stringify([model.provider, model.id]), "utf8").toString("base64url");
|
|
15438
|
-
return harnessModelRefSchema.parse({ id: `${PI_MODEL_REF_PREFIX}${encoded}` });
|
|
15492
|
+
function pathDelimiter(platform) {
|
|
15493
|
+
return platform === "win32" ? ";" : ":";
|
|
15439
15494
|
}
|
|
15440
|
-
function
|
|
15441
|
-
|
|
15442
|
-
|
|
15443
|
-
|
|
15444
|
-
|
|
15445
|
-
|
|
15446
|
-
|
|
15495
|
+
function pathDirectories(environment, platform) {
|
|
15496
|
+
return (environmentValue(environment, "PATH") ?? "").split(pathDelimiter(platform)).map((directory) => directory.trim().replace(/^"|"$/gu, "")).filter(Boolean);
|
|
15497
|
+
}
|
|
15498
|
+
function executableExtensions(command, platform, environment) {
|
|
15499
|
+
if (platform !== "win32")
|
|
15500
|
+
return [""];
|
|
15501
|
+
if (targetPath(platform).extname(command) !== "")
|
|
15502
|
+
return [""];
|
|
15503
|
+
return (environmentValue(environment, "PATHEXT") ?? ".COM;.EXE;.BAT;.CMD").split(";").map((extension) => extension.trim()).filter(Boolean);
|
|
15504
|
+
}
|
|
15505
|
+
function isExecutableFile(filePath, platform) {
|
|
15447
15506
|
try {
|
|
15448
|
-
|
|
15507
|
+
fs.accessSync(filePath, platform === "win32" ? fs.constants.F_OK : fs.constants.X_OK);
|
|
15508
|
+
return fs.statSync(filePath).isFile();
|
|
15449
15509
|
} catch {
|
|
15450
|
-
|
|
15451
|
-
}
|
|
15452
|
-
if (!Array.isArray(decoded) || decoded.length !== 2 || typeof decoded[0] !== "string" || typeof decoded[1] !== "string") {
|
|
15453
|
-
throw new Error("Pi Model Ref has an invalid native identity");
|
|
15454
|
-
}
|
|
15455
|
-
const native = { provider: decoded[0], id: decoded[1] };
|
|
15456
|
-
assertNativePart(native.provider, "Model provider");
|
|
15457
|
-
assertNativePart(native.id, "Model id");
|
|
15458
|
-
if (encodePiModelRef(native).id !== parsedRef.id) {
|
|
15459
|
-
throw new Error("Pi Model Ref is not canonical");
|
|
15510
|
+
return false;
|
|
15460
15511
|
}
|
|
15461
|
-
return native;
|
|
15462
15512
|
}
|
|
15463
|
-
function
|
|
15464
|
-
|
|
15513
|
+
function subdirectoryNames(directory) {
|
|
15514
|
+
try {
|
|
15515
|
+
return fs.readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
15516
|
+
} catch {
|
|
15517
|
+
return [];
|
|
15518
|
+
}
|
|
15465
15519
|
}
|
|
15466
|
-
function
|
|
15467
|
-
|
|
15468
|
-
return label || id;
|
|
15520
|
+
function newestFirst(names) {
|
|
15521
|
+
return [...names].sort((left, right) => right.localeCompare(left, void 0, { numeric: true }));
|
|
15469
15522
|
}
|
|
15470
|
-
|
|
15471
|
-
|
|
15472
|
-
|
|
15473
|
-
|
|
15474
|
-
|
|
15523
|
+
|
|
15524
|
+
// ../../harness-discovery/dist/node-runtime.js
|
|
15525
|
+
import path2 from "node:path";
|
|
15526
|
+
function withNodeRuntimeOnPath(environment, runtimeExecutable = process.execPath, platform = process.platform) {
|
|
15527
|
+
const pathKey = Object.keys(environment).find((name) => name.toLowerCase() === "path") ?? "PATH";
|
|
15528
|
+
const delimiter = platform === "win32" ? ";" : ":";
|
|
15529
|
+
const runtimeDirectory = path2.dirname(runtimeExecutable);
|
|
15530
|
+
const directories = (environment[pathKey] ?? "").split(delimiter).filter(Boolean);
|
|
15531
|
+
const equal = platform === "win32" ? (value) => value.toLowerCase() : (value) => value;
|
|
15532
|
+
if (!directories.some((directory) => equal(directory) === equal(runtimeDirectory))) {
|
|
15533
|
+
directories.push(runtimeDirectory);
|
|
15534
|
+
}
|
|
15535
|
+
return { ...environment, [pathKey]: directories.join(delimiter) };
|
|
15475
15536
|
}
|
|
15476
|
-
|
|
15477
|
-
|
|
15478
|
-
|
|
15479
|
-
|
|
15480
|
-
|
|
15481
|
-
|
|
15482
|
-
|
|
15483
|
-
|
|
15484
|
-
|
|
15485
|
-
|
|
15537
|
+
|
|
15538
|
+
// ../../harness-discovery/dist/resolve.js
|
|
15539
|
+
import os from "node:os";
|
|
15540
|
+
|
|
15541
|
+
// ../../harness-discovery/dist/version-managers.js
|
|
15542
|
+
function versionManagerBinaryDirectories(context) {
|
|
15543
|
+
const { platform, environment, home } = context;
|
|
15544
|
+
const list = context.subdirectories ?? subdirectoryNames;
|
|
15545
|
+
const pathFlavor = targetPath(platform);
|
|
15546
|
+
const value = (name) => environmentValue(environment, name);
|
|
15547
|
+
const directories = [];
|
|
15548
|
+
const versioned = (root, ...tail) => {
|
|
15549
|
+
for (const version2 of newestFirst(list(root))) {
|
|
15550
|
+
directories.push(pathFlavor.join(root, version2, ...tail));
|
|
15486
15551
|
}
|
|
15487
|
-
|
|
15488
|
-
|
|
15489
|
-
|
|
15490
|
-
|
|
15491
|
-
|
|
15492
|
-
|
|
15493
|
-
|
|
15494
|
-
|
|
15495
|
-
|
|
15496
|
-
|
|
15497
|
-
|
|
15552
|
+
};
|
|
15553
|
+
if (platform === "win32") {
|
|
15554
|
+
const appData = value("APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming");
|
|
15555
|
+
const localAppData = value("LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local");
|
|
15556
|
+
versioned(pathFlavor.join(appData, "nvm"));
|
|
15557
|
+
versioned(value("FNM_DIR") ?? pathFlavor.join(appData, "fnm", "node-versions"), "installation");
|
|
15558
|
+
directories.push(pathFlavor.join(localAppData, "Volta", "bin"));
|
|
15559
|
+
directories.push(pathFlavor.join(home, ".bun", "bin"));
|
|
15560
|
+
const pnpmHome2 = value("PNPM_HOME");
|
|
15561
|
+
if (pnpmHome2)
|
|
15562
|
+
directories.push(pnpmHome2);
|
|
15563
|
+
directories.push(pathFlavor.join(localAppData, "pnpm"));
|
|
15564
|
+
return directories;
|
|
15498
15565
|
}
|
|
15499
|
-
|
|
15500
|
-
|
|
15566
|
+
versioned(pathFlavor.join(value("NVM_DIR") ?? pathFlavor.join(home, ".nvm"), "versions", "node"), "bin");
|
|
15567
|
+
const fnmRoots = [
|
|
15568
|
+
value("FNM_DIR"),
|
|
15569
|
+
pathFlavor.join(home, ".local", "share", "fnm"),
|
|
15570
|
+
pathFlavor.join(home, "Library", "Application Support", "fnm")
|
|
15571
|
+
].filter((root) => root !== void 0);
|
|
15572
|
+
for (const root of fnmRoots) {
|
|
15573
|
+
versioned(pathFlavor.join(root, "node-versions"), "installation", "bin");
|
|
15501
15574
|
}
|
|
15502
|
-
|
|
15503
|
-
|
|
15575
|
+
const voltaHome = value("VOLTA_HOME") ?? pathFlavor.join(home, ".volta");
|
|
15576
|
+
versioned(pathFlavor.join(voltaHome, "tools", "image", "node"), "bin");
|
|
15577
|
+
directories.push(pathFlavor.join(voltaHome, "bin"));
|
|
15578
|
+
const asdfHome = value("ASDF_DATA_DIR") ?? pathFlavor.join(home, ".asdf");
|
|
15579
|
+
versioned(pathFlavor.join(asdfHome, "installs", "nodejs"), "bin");
|
|
15580
|
+
directories.push(pathFlavor.join(asdfHome, "shims"));
|
|
15581
|
+
const nodenvHome = value("NODENV_ROOT") ?? pathFlavor.join(home, ".nodenv");
|
|
15582
|
+
versioned(pathFlavor.join(nodenvHome, "versions"), "bin");
|
|
15583
|
+
directories.push(pathFlavor.join(nodenvHome, "shims"));
|
|
15584
|
+
versioned(pathFlavor.join(value("N_PREFIX") ?? "/usr/local", "n", "versions", "node"), "bin");
|
|
15585
|
+
directories.push(pathFlavor.join(home, ".bun", "bin"));
|
|
15586
|
+
const pnpmHome = value("PNPM_HOME");
|
|
15587
|
+
if (pnpmHome)
|
|
15588
|
+
directories.push(pnpmHome);
|
|
15589
|
+
directories.push(pathFlavor.join(home, "Library", "pnpm"));
|
|
15590
|
+
directories.push(pathFlavor.join(home, ".local", "share", "pnpm"));
|
|
15591
|
+
for (const prefix of ["/opt/homebrew/opt", "/usr/local/opt"]) {
|
|
15592
|
+
for (const formula of newestFirst(list(prefix).filter((name) => name.startsWith("node@")))) {
|
|
15593
|
+
directories.push(pathFlavor.join(prefix, formula, "bin"));
|
|
15594
|
+
}
|
|
15504
15595
|
}
|
|
15505
|
-
|
|
15506
|
-
const allThinkingOptionIds = thinkingOptions.map(({ id }) => id);
|
|
15507
|
-
const offThinkingOptionId = thinkingOptions.find(({ id }) => id === "off")?.id;
|
|
15508
|
-
const models = [...byRef.values()].map(({ model, reasoning }) => ({
|
|
15509
|
-
...model,
|
|
15510
|
-
supportedThinkingOptionIds: reasoning ? allThinkingOptionIds : offThinkingOptionId ? [offThinkingOptionId] : []
|
|
15511
|
-
})).sort((left, right) => compareText(left.label, right.label) || compareText(left.ref.id, right.ref.id));
|
|
15512
|
-
const defaultThinkingOptionId = thinkingOptions.find(({ id }) => id === effectiveThinkingOptionId)?.id;
|
|
15513
|
-
return harnessModelCatalogSchema.parse({
|
|
15514
|
-
models,
|
|
15515
|
-
...defaultModel ? { defaultModel } : {},
|
|
15516
|
-
thinkingOptions,
|
|
15517
|
-
...defaultThinkingOptionId ? { defaultThinkingOptionId } : {}
|
|
15518
|
-
});
|
|
15596
|
+
return directories;
|
|
15519
15597
|
}
|
|
15520
15598
|
|
|
15521
|
-
// dist/
|
|
15522
|
-
var
|
|
15523
|
-
function
|
|
15524
|
-
return
|
|
15525
|
-
}
|
|
15526
|
-
function textContent(value) {
|
|
15527
|
-
if (typeof value === "string")
|
|
15528
|
-
return value;
|
|
15529
|
-
if (!Array.isArray(value))
|
|
15530
|
-
return "";
|
|
15531
|
-
return value.filter((part) => isRecord(part) && part.type === "text" && typeof part.text === "string").map((part) => part.text).join("");
|
|
15599
|
+
// ../../harness-discovery/dist/resolve.js
|
|
15600
|
+
var VERSION_MANAGER_ROOTS = "<version-managers>";
|
|
15601
|
+
function installRootExtensions(platform) {
|
|
15602
|
+
return platform === "win32" ? [".exe", ".cmd"] : [""];
|
|
15532
15603
|
}
|
|
15533
|
-
function
|
|
15534
|
-
|
|
15535
|
-
return "";
|
|
15536
|
-
return value.filter((part) => isRecord(part) && part.type === "thinking" && typeof part.thinking === "string").map((part) => part.thinking).join("");
|
|
15604
|
+
function resolveHomeDirectory(input) {
|
|
15605
|
+
return input.homeDirectory ?? environmentValue(input.environment, "HOME") ?? environmentValue(input.environment, "USERPROFILE") ?? os.homedir();
|
|
15537
15606
|
}
|
|
15538
|
-
function
|
|
15539
|
-
|
|
15540
|
-
|
|
15541
|
-
|
|
15542
|
-
|
|
15607
|
+
function templateVariables(environment, platform, home) {
|
|
15608
|
+
const pathFlavor = targetPath(platform);
|
|
15609
|
+
return {
|
|
15610
|
+
HOME: home,
|
|
15611
|
+
USERPROFILE: home,
|
|
15612
|
+
APPDATA: environmentValue(environment, "APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming"),
|
|
15613
|
+
LOCALAPPDATA: environmentValue(environment, "LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local")
|
|
15614
|
+
};
|
|
15543
15615
|
}
|
|
15544
|
-
function
|
|
15616
|
+
function joinTemplate(platform, value) {
|
|
15617
|
+
const pathFlavor = targetPath(platform);
|
|
15618
|
+
const segments = value.split("/");
|
|
15619
|
+
const head = segments[0] ?? "";
|
|
15620
|
+
const tail = segments.slice(1);
|
|
15621
|
+
if (head === "")
|
|
15622
|
+
return pathFlavor.join(pathFlavor.sep, ...tail);
|
|
15623
|
+
return tail.length === 0 ? head : pathFlavor.join(head, ...tail);
|
|
15624
|
+
}
|
|
15625
|
+
function expandInstallRoot(template, environment, platform, home) {
|
|
15626
|
+
const variables = templateVariables(environment, platform, home);
|
|
15627
|
+
let unresolved = false;
|
|
15628
|
+
const substituted = template.replace(/^~(?=\/|$)/u, home).replace(/\$\{(\w+)\}/gu, (_match, name) => {
|
|
15629
|
+
const value = variables[name] ?? environmentValue(environment, name);
|
|
15630
|
+
if (value === void 0 || value === "") {
|
|
15631
|
+
unresolved = true;
|
|
15632
|
+
return "";
|
|
15633
|
+
}
|
|
15634
|
+
return value;
|
|
15635
|
+
});
|
|
15636
|
+
return unresolved ? void 0 : joinTemplate(platform, substituted);
|
|
15637
|
+
}
|
|
15638
|
+
function installRootDirectories(spec, input, dependencies, platform, home) {
|
|
15639
|
+
const templates = (platform === "win32" ? spec.installRoots?.windows : spec.installRoots?.posix) ?? [];
|
|
15640
|
+
const directories = [];
|
|
15641
|
+
for (const template of templates) {
|
|
15642
|
+
if (template === VERSION_MANAGER_ROOTS) {
|
|
15643
|
+
directories.push(...versionManagerBinaryDirectories({
|
|
15644
|
+
platform,
|
|
15645
|
+
environment: input.environment,
|
|
15646
|
+
home,
|
|
15647
|
+
...dependencies.subdirectories ? { subdirectories: dependencies.subdirectories } : {}
|
|
15648
|
+
}));
|
|
15649
|
+
continue;
|
|
15650
|
+
}
|
|
15651
|
+
const directory = expandInstallRoot(template, input.environment, platform, home);
|
|
15652
|
+
if (directory !== void 0)
|
|
15653
|
+
directories.push(directory);
|
|
15654
|
+
}
|
|
15655
|
+
return directories;
|
|
15656
|
+
}
|
|
15657
|
+
function harnessCandidates(spec, input, dependencies = {}) {
|
|
15658
|
+
const platform = input.platform ?? process.platform;
|
|
15659
|
+
const pathFlavor = targetPath(platform);
|
|
15660
|
+
const configured = input.command ?? (spec.commandEnvironmentVariable ? environmentValue(input.environment, spec.commandEnvironmentVariable) : void 0);
|
|
15661
|
+
const command = configured ?? spec.command;
|
|
15662
|
+
if (pathFlavor.isAbsolute(command) || command.includes("/") || command.includes("\\")) {
|
|
15663
|
+
return [{ candidate: command, source: "configured" }];
|
|
15664
|
+
}
|
|
15665
|
+
const candidates = [];
|
|
15666
|
+
const extensions = executableExtensions(command, platform, input.environment);
|
|
15667
|
+
for (const directory of pathDirectories(input.environment, platform)) {
|
|
15668
|
+
for (const extension of extensions) {
|
|
15669
|
+
candidates.push({
|
|
15670
|
+
candidate: pathFlavor.join(directory, command + extension),
|
|
15671
|
+
source: "path"
|
|
15672
|
+
});
|
|
15673
|
+
}
|
|
15674
|
+
}
|
|
15675
|
+
if (configured !== void 0)
|
|
15676
|
+
return candidates;
|
|
15677
|
+
const home = resolveHomeDirectory(input);
|
|
15678
|
+
for (const directory of installRootDirectories(spec, input, dependencies, platform, home)) {
|
|
15679
|
+
for (const extension of installRootExtensions(platform)) {
|
|
15680
|
+
candidates.push({
|
|
15681
|
+
candidate: pathFlavor.join(directory, spec.command + extension),
|
|
15682
|
+
source: "install-root"
|
|
15683
|
+
});
|
|
15684
|
+
}
|
|
15685
|
+
}
|
|
15686
|
+
return candidates;
|
|
15687
|
+
}
|
|
15688
|
+
function resolveHarnessExecutable(spec, input, dependencies = {}) {
|
|
15689
|
+
const platform = input.platform ?? process.platform;
|
|
15690
|
+
const isExecutable = dependencies.isExecutable ?? ((candidate) => isExecutableFile(candidate, platform));
|
|
15691
|
+
const runnable = spec.runnableCandidate ?? ((candidate) => candidate);
|
|
15692
|
+
const context = { platform, isExecutable };
|
|
15693
|
+
for (const { candidate, source } of harnessCandidates(spec, input, dependencies)) {
|
|
15694
|
+
const executable = runnable(candidate, context);
|
|
15695
|
+
if (executable !== void 0 && isExecutable(executable))
|
|
15696
|
+
return { executable, source };
|
|
15697
|
+
}
|
|
15698
|
+
return void 0;
|
|
15699
|
+
}
|
|
15700
|
+
|
|
15701
|
+
// dist/command.js
|
|
15702
|
+
var piDiscoverySpec = {
|
|
15703
|
+
id: "pi",
|
|
15704
|
+
command: "pi",
|
|
15705
|
+
commandEnvironmentVariable: "PI_COMMAND",
|
|
15706
|
+
installRoots: {
|
|
15707
|
+
posix: [
|
|
15708
|
+
"~/.npm-global/bin",
|
|
15709
|
+
"~/.local/bin",
|
|
15710
|
+
VERSION_MANAGER_ROOTS,
|
|
15711
|
+
"/opt/homebrew/bin",
|
|
15712
|
+
"/usr/local/bin"
|
|
15713
|
+
],
|
|
15714
|
+
windows: ["${APPDATA}/npm", "~/.local/bin", VERSION_MANAGER_ROOTS]
|
|
15715
|
+
}
|
|
15716
|
+
};
|
|
15717
|
+
function resolvePiExecutable(input, dependencies = {}) {
|
|
15718
|
+
const resolution = resolveHarnessExecutable(piDiscoverySpec, {
|
|
15719
|
+
...input.command ? { command: input.command } : {},
|
|
15720
|
+
environment: input.environment,
|
|
15721
|
+
...dependencies.platform ? { platform: dependencies.platform } : {},
|
|
15722
|
+
...dependencies.homeDirectory ? { homeDirectory: dependencies.homeDirectory } : {}
|
|
15723
|
+
}, { ...dependencies.isExecutable ? { isExecutable: dependencies.isExecutable } : {} });
|
|
15724
|
+
return resolution?.executable ?? input.command ?? input.environment.PI_COMMAND ?? "pi";
|
|
15725
|
+
}
|
|
15726
|
+
|
|
15727
|
+
// dist/pi-credential-imports.js
|
|
15728
|
+
var PREFIX = "codexhost-account-";
|
|
15729
|
+
function object2(value) {
|
|
15730
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15731
|
+
}
|
|
15732
|
+
function parseAuth(raw) {
|
|
15733
|
+
const value = JSON.parse(raw ?? "{}");
|
|
15734
|
+
if (!object2(value))
|
|
15735
|
+
throw new Error("Invalid Pi auth store");
|
|
15736
|
+
return value;
|
|
15737
|
+
}
|
|
15738
|
+
var OAUTH_VENDORS = [
|
|
15739
|
+
{
|
|
15740
|
+
issuer: "https://auth.openai.com",
|
|
15741
|
+
client: "app_EMoamEEZ73f0CkXaXp7hrann",
|
|
15742
|
+
vendor: "openai-codex"
|
|
15743
|
+
},
|
|
15744
|
+
{ issuer: "https://auth.x.ai", client: "b1a00492-073a-47ea-816f-4c329264a828", vendor: "xai" }
|
|
15745
|
+
];
|
|
15746
|
+
function describeOauth(credential) {
|
|
15747
|
+
if (!object2(credential) || credential.type !== "oauth")
|
|
15748
|
+
return {};
|
|
15749
|
+
const token2 = credential.access;
|
|
15750
|
+
if (typeof token2 !== "string")
|
|
15751
|
+
return {};
|
|
15752
|
+
let claims;
|
|
15753
|
+
try {
|
|
15754
|
+
claims = JSON.parse(Buffer.from(token2.split(".")[1] ?? "", "base64url").toString("utf8"));
|
|
15755
|
+
} catch {
|
|
15756
|
+
return {};
|
|
15757
|
+
}
|
|
15758
|
+
if (!object2(claims))
|
|
15759
|
+
return {};
|
|
15760
|
+
const match = OAUTH_VENDORS.find((candidate) => claims.iss === candidate.issuer && claims.client_id === candidate.client);
|
|
15761
|
+
const profile = claims["https://api.openai.com/profile"];
|
|
15762
|
+
const email3 = object2(profile) ? profile.email : claims.email;
|
|
15763
|
+
return {
|
|
15764
|
+
...typeof email3 === "string" && email3.length > 0 && email3.length <= 512 ? { label: email3 } : {},
|
|
15765
|
+
...match ? { vendor: match.vendor } : {}
|
|
15766
|
+
};
|
|
15767
|
+
}
|
|
15768
|
+
function writeAuth(filename, content) {
|
|
15769
|
+
const temporary = `${filename}.${randomUUID()}.tmp`;
|
|
15770
|
+
try {
|
|
15771
|
+
writeFileSync(temporary, content, { flag: "wx", mode: 384 });
|
|
15772
|
+
renameSync(temporary, filename);
|
|
15773
|
+
} finally {
|
|
15774
|
+
rmSync(temporary, { force: true });
|
|
15775
|
+
}
|
|
15776
|
+
}
|
|
15777
|
+
function removeOwnedFiles(dir) {
|
|
15778
|
+
rmSync(path3.join(dir, "index.ts"), { force: true });
|
|
15779
|
+
rmSync(path3.join(dir, "import.json"), { force: true });
|
|
15780
|
+
try {
|
|
15781
|
+
rmdirSync(dir);
|
|
15782
|
+
} catch {
|
|
15783
|
+
}
|
|
15784
|
+
}
|
|
15785
|
+
async function installation(command, environment, authPath) {
|
|
15786
|
+
const executable = await realpath(resolvePiExecutable({ ...command ? { command } : {}, environment }));
|
|
15787
|
+
let directory = path3.dirname(executable);
|
|
15788
|
+
while (true) {
|
|
15789
|
+
const manifest = path3.join(directory, "package.json");
|
|
15790
|
+
if (existsSync(manifest)) {
|
|
15791
|
+
const pkg = JSON.parse(readFileSync(manifest, "utf8"));
|
|
15792
|
+
if (pkg.name === "@earendil-works/pi-coding-agent")
|
|
15793
|
+
break;
|
|
15794
|
+
}
|
|
15795
|
+
const parent = path3.dirname(directory);
|
|
15796
|
+
if (parent === directory)
|
|
15797
|
+
throw new Error("Pi credential import requires a supported npm Pi installation");
|
|
15798
|
+
directory = parent;
|
|
15799
|
+
}
|
|
15800
|
+
const storage = await import(pathToFileURL(path3.join(directory, "dist/core/auth-storage.js")).href);
|
|
15801
|
+
const ai = path3.join(directory, "node_modules/@earendil-works/pi-ai/dist");
|
|
15802
|
+
const all = await import(pathToFileURL(path3.join(ai, "providers/all.js")).href);
|
|
15803
|
+
const providers = all.getBuiltinProviders();
|
|
15804
|
+
const providerModules = {
|
|
15805
|
+
"openai-codex": pathToFileURL(path3.join(ai, "providers/openai-codex.js")).href,
|
|
15806
|
+
xai: pathToFileURL(path3.join(ai, "providers/xai.js")).href
|
|
15807
|
+
};
|
|
15808
|
+
for (const [id, url2] of Object.entries(providerModules)) {
|
|
15809
|
+
const module = await import(url2);
|
|
15810
|
+
const provider = id === "xai" ? module.xaiProvider() : module.openaiCodexProvider();
|
|
15811
|
+
if (!provider.auth?.oauth || !provider.getModels().length)
|
|
15812
|
+
throw new Error("Pi version does not support subscription imports");
|
|
15813
|
+
}
|
|
15814
|
+
return {
|
|
15815
|
+
backend: new storage.FileAuthStorageBackend(authPath),
|
|
15816
|
+
providerModules,
|
|
15817
|
+
reservedNames: providers.map((p) => typeof p === "string" ? p : p.id),
|
|
15818
|
+
async configuredProviderNames() {
|
|
15819
|
+
const { stdout } = await promisify(execFile)(process.execPath, [executable, "--offline", "--no-approve", "--list-models"], {
|
|
15820
|
+
cwd: existsSync(path3.dirname(authPath)) ? path3.dirname(authPath) : os2.homedir(),
|
|
15821
|
+
env: { ...environment, PI_CODING_AGENT_DIR: path3.dirname(authPath), PI_OFFLINE: "1" },
|
|
15822
|
+
timeout: 15e3,
|
|
15823
|
+
maxBuffer: 4 * 1024 * 1024
|
|
15824
|
+
});
|
|
15825
|
+
return stdout.split(/\r?\n/).map((line) => line.trim().split(/\s+/)[0] ?? "").filter(Boolean);
|
|
15826
|
+
}
|
|
15827
|
+
};
|
|
15828
|
+
}
|
|
15829
|
+
function extensionSource(moduleUrl, provider, name, owner) {
|
|
15830
|
+
return `// Managed by codexhost. Removing this file disables the imported Provider.
|
|
15831
|
+
export default async function (pi) {
|
|
15832
|
+
const moduleUrl = ${JSON.stringify(moduleUrl)};
|
|
15833
|
+
const nativeModule = await import(moduleUrl);
|
|
15834
|
+
const native = nativeModule.${provider === "xai" ? "xaiProvider" : "openaiCodexProvider"}();
|
|
15835
|
+
const oauth = native.auth.oauth;
|
|
15836
|
+
const models = native.getModels().map(model => ({ ...model, provider: ${JSON.stringify(name)} }));
|
|
15837
|
+
pi.registerProvider({
|
|
15838
|
+
...native, id: ${JSON.stringify(name)}, name: ${JSON.stringify(name)},
|
|
15839
|
+
auth: { oauth: { ...oauth,
|
|
15840
|
+
async refresh(credential, signal) {
|
|
15841
|
+
return { ...await oauth.refresh(credential, signal), codexhostImportId: ${JSON.stringify(owner)} };
|
|
15842
|
+
}
|
|
15843
|
+
} },
|
|
15844
|
+
getModels: () => models
|
|
15845
|
+
});
|
|
15846
|
+
}
|
|
15847
|
+
`;
|
|
15848
|
+
}
|
|
15849
|
+
function createPiCredentialImports(options = {}) {
|
|
15850
|
+
const env = { ...process.env, ...options.environment };
|
|
15851
|
+
const agentDir = env.PI_CODING_AGENT_DIR ?? path3.join(env.HOME ?? os2.homedir(), ".pi/agent");
|
|
15852
|
+
const authPath = path3.join(agentDir, "auth.json");
|
|
15853
|
+
const extensionsDir = path3.join(agentDir, "extensions");
|
|
15854
|
+
const saveAuth = (auth) => (options.writeAuth ?? writeAuth)(authPath, JSON.stringify(auth, null, 2) + "\n");
|
|
15855
|
+
const resolve = () => options.resolveInstallation?.(authPath) ?? installation(options.command, env, authPath);
|
|
15856
|
+
const location = (name) => path3.join(extensionsDir, `${PREFIX}${credentialImportNameSchema.parse(name)}`);
|
|
15857
|
+
const readRecord = (name) => {
|
|
15858
|
+
const dir = location(name);
|
|
15859
|
+
if (lstatSync(dir).isSymbolicLink())
|
|
15860
|
+
throw new Error("Imported configuration was changed; manage it in Pi");
|
|
15861
|
+
const value = JSON.parse(readFileSync(path3.join(dir, "import.json"), "utf8"));
|
|
15862
|
+
if (value.version !== 1 || typeof value.owner !== "string" || typeof value.extension !== "string")
|
|
15863
|
+
throw new Error("Invalid import metadata");
|
|
15864
|
+
const record6 = value.record;
|
|
15865
|
+
if (!object2(record6))
|
|
15866
|
+
throw new Error("Invalid import metadata");
|
|
15867
|
+
value.record = credentialImportRecordSchema.parse({
|
|
15868
|
+
name: record6.name,
|
|
15869
|
+
source: record6.source,
|
|
15870
|
+
importedAt: record6.importedAt
|
|
15871
|
+
});
|
|
15872
|
+
if (value.record.name !== name)
|
|
15873
|
+
throw new Error("Import identity mismatch");
|
|
15874
|
+
return value;
|
|
15875
|
+
};
|
|
15876
|
+
const owned = (meta3, auth) => {
|
|
15877
|
+
const credential = auth[meta3.record.name];
|
|
15878
|
+
const file2 = path3.join(location(meta3.record.name), "index.ts");
|
|
15879
|
+
return existsSync(file2) && !lstatSync(file2).isSymbolicLink() && readFileSync(file2, "utf8") === meta3.extension && object2(credential) && credential.type === "oauth" && credential.codexhostImportId === meta3.owner;
|
|
15880
|
+
};
|
|
15881
|
+
const readAuth = () => existsSync(authPath) ? parseAuth(readFileSync(authPath, "utf8")) : {};
|
|
15882
|
+
const ownedRecords = (auth) => {
|
|
15883
|
+
if (!existsSync(extensionsDir))
|
|
15884
|
+
return [];
|
|
15885
|
+
const result = [];
|
|
15886
|
+
for (const entry of readdirSync(extensionsDir)) {
|
|
15887
|
+
if (!entry.startsWith(PREFIX))
|
|
15888
|
+
continue;
|
|
15889
|
+
const name = entry.slice(PREFIX.length);
|
|
15890
|
+
if (!credentialImportNameSchema.safeParse(name).success)
|
|
15891
|
+
continue;
|
|
15892
|
+
if (!existsSync(path3.join(location(name), "import.json")))
|
|
15893
|
+
continue;
|
|
15894
|
+
try {
|
|
15895
|
+
const meta3 = readRecord(name);
|
|
15896
|
+
if (owned(meta3, auth))
|
|
15897
|
+
result.push(meta3.record);
|
|
15898
|
+
} catch {
|
|
15899
|
+
}
|
|
15900
|
+
}
|
|
15901
|
+
return result;
|
|
15902
|
+
};
|
|
15903
|
+
return {
|
|
15904
|
+
providers: ["openai-codex", "xai"],
|
|
15905
|
+
async list() {
|
|
15906
|
+
if (!existsSync(agentDir))
|
|
15907
|
+
throw new Error("Pi has no configuration directory");
|
|
15908
|
+
await resolve();
|
|
15909
|
+
return ownedRecords(readAuth());
|
|
15910
|
+
},
|
|
15911
|
+
async listOthers() {
|
|
15912
|
+
const auth = readAuth();
|
|
15913
|
+
const ours = new Set(ownedRecords(auth).map((record6) => record6.name));
|
|
15914
|
+
const result = /* @__PURE__ */ new Map();
|
|
15915
|
+
const usable = (provider) => Boolean(provider) && provider.length <= 128 && !ours.has(provider) && !result.has(provider);
|
|
15916
|
+
for (const [provider, credential] of Object.entries(auth)) {
|
|
15917
|
+
if (!usable(provider))
|
|
15918
|
+
continue;
|
|
15919
|
+
const type = object2(credential) ? credential.type : void 0;
|
|
15920
|
+
result.set(provider, {
|
|
15921
|
+
provider,
|
|
15922
|
+
type: type === "oauth" || type === "api_key" ? type : "unknown",
|
|
15923
|
+
...describeOauth(credential)
|
|
15924
|
+
});
|
|
15925
|
+
}
|
|
15926
|
+
const modelsPath = path3.join(agentDir, "models.json");
|
|
15927
|
+
if (existsSync(modelsPath)) {
|
|
15928
|
+
const models = JSON.parse(readFileSync(modelsPath, "utf8"));
|
|
15929
|
+
const providers = object2(models) && object2(models.providers) ? models.providers : {};
|
|
15930
|
+
for (const [provider, definition] of Object.entries(providers)) {
|
|
15931
|
+
if (!usable(provider) || !object2(definition) || !definition.apiKey)
|
|
15932
|
+
continue;
|
|
15933
|
+
const name = definition.name;
|
|
15934
|
+
const label = typeof name === "string" && name && name !== provider ? name : void 0;
|
|
15935
|
+
result.set(provider, { provider, type: "api_key", ...label ? { label } : {} });
|
|
15936
|
+
}
|
|
15937
|
+
}
|
|
15938
|
+
return [...result.values()].sort((a, b) => a.provider.localeCompare(b.provider));
|
|
15939
|
+
},
|
|
15940
|
+
async add(name, transfer) {
|
|
15941
|
+
credentialImportNameSchema.parse(name);
|
|
15942
|
+
const sdk = await resolve();
|
|
15943
|
+
if (!this.providers.includes(transfer.source.provider))
|
|
15944
|
+
throw new Error("Unsupported credential source");
|
|
15945
|
+
if (sdk.reservedNames.includes(name) || (await sdk.configuredProviderNames?.())?.includes(name))
|
|
15946
|
+
throw new Error("Provider name already exists; choose another name");
|
|
15947
|
+
const owner = randomUUID();
|
|
15948
|
+
const record6 = credentialImportRecordSchema.parse({
|
|
15949
|
+
name,
|
|
15950
|
+
source: transfer.source,
|
|
15951
|
+
importedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
15952
|
+
});
|
|
15953
|
+
const extension = extensionSource(sdk.providerModules[transfer.source.provider], transfer.source.provider, name, owner);
|
|
15954
|
+
const dir = location(name);
|
|
15955
|
+
let created = false;
|
|
15956
|
+
let committed = false;
|
|
15957
|
+
try {
|
|
15958
|
+
sdk.backend.withLock((current) => {
|
|
15959
|
+
const auth = parseAuth(current);
|
|
15960
|
+
const modelsPath = path3.join(agentDir, "models.json");
|
|
15961
|
+
const models = existsSync(modelsPath) ? JSON.parse(readFileSync(modelsPath, "utf8")) : {};
|
|
15962
|
+
if (Object.hasOwn(auth, name) || Object.hasOwn(models.providers ?? {}, name) || existsSync(dir) || existsSync(path3.join(extensionsDir, `${name}-provider.ts`)))
|
|
15963
|
+
throw new Error("Provider name already exists; choose another name");
|
|
15964
|
+
mkdirSync(extensionsDir, { recursive: true, mode: 448 });
|
|
15965
|
+
mkdirSync(dir, { mode: 448 });
|
|
15966
|
+
created = true;
|
|
15967
|
+
writeFileSync(path3.join(dir, "import.json"), JSON.stringify({ version: 1, owner, record: record6, extension }), { flag: "wx", mode: 384 });
|
|
15968
|
+
writeFileSync(path3.join(dir, "index.ts"), extension, { flag: "wx", mode: 384 });
|
|
15969
|
+
auth[name] = { type: "oauth", ...transfer.oauth, codexhostImportId: owner };
|
|
15970
|
+
saveAuth(auth);
|
|
15971
|
+
committed = true;
|
|
15972
|
+
return { result: void 0 };
|
|
15973
|
+
});
|
|
15974
|
+
} catch (error51) {
|
|
15975
|
+
if (created && !committed)
|
|
15976
|
+
removeOwnedFiles(dir);
|
|
15977
|
+
throw error51;
|
|
15978
|
+
}
|
|
15979
|
+
},
|
|
15980
|
+
async reimport(name, transfer) {
|
|
15981
|
+
const sdk = await resolve();
|
|
15982
|
+
sdk.backend.withLock((current) => {
|
|
15983
|
+
const meta3 = readRecord(name);
|
|
15984
|
+
const auth = parseAuth(current);
|
|
15985
|
+
if (!owned(meta3, auth) || meta3.record.source.id !== transfer.source.id || meta3.record.source.provider !== transfer.source.provider)
|
|
15986
|
+
throw new Error("Import ownership or source account changed; refusing replacement");
|
|
15987
|
+
const metadataPath = path3.join(location(name), "import.json");
|
|
15988
|
+
const previous = readFileSync(metadataPath, "utf8");
|
|
15989
|
+
const updated = {
|
|
15990
|
+
...meta3,
|
|
15991
|
+
record: { ...meta3.record, importedAt: (/* @__PURE__ */ new Date()).toISOString() }
|
|
15992
|
+
};
|
|
15993
|
+
writeAuth(metadataPath, JSON.stringify(updated));
|
|
15994
|
+
try {
|
|
15995
|
+
saveAuth({
|
|
15996
|
+
...auth,
|
|
15997
|
+
[name]: { type: "oauth", ...transfer.oauth, codexhostImportId: meta3.owner }
|
|
15998
|
+
});
|
|
15999
|
+
} catch (error51) {
|
|
16000
|
+
writeAuth(metadataPath, previous);
|
|
16001
|
+
throw error51;
|
|
16002
|
+
}
|
|
16003
|
+
return { result: void 0 };
|
|
16004
|
+
});
|
|
16005
|
+
},
|
|
16006
|
+
async remove(name) {
|
|
16007
|
+
const sdk = await resolve();
|
|
16008
|
+
const meta3 = readRecord(name);
|
|
16009
|
+
sdk.backend.withLock((current) => {
|
|
16010
|
+
const auth = parseAuth(current);
|
|
16011
|
+
if (!owned(meta3, auth))
|
|
16012
|
+
throw new Error("Imported configuration was changed; manage it in Pi");
|
|
16013
|
+
saveAuth(Object.fromEntries(Object.entries(auth).filter(([key]) => key !== name)));
|
|
16014
|
+
removeOwnedFiles(location(name));
|
|
16015
|
+
return { result: void 0 };
|
|
16016
|
+
});
|
|
16017
|
+
}
|
|
16018
|
+
};
|
|
16019
|
+
}
|
|
16020
|
+
|
|
16021
|
+
// dist/pi-empty-session.js
|
|
16022
|
+
import { createReadStream } from "node:fs";
|
|
16023
|
+
import { createInterface } from "node:readline";
|
|
16024
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
16025
|
+
import { link, open as open2, rm } from "node:fs/promises";
|
|
16026
|
+
import path4 from "node:path";
|
|
16027
|
+
|
|
16028
|
+
// dist/pi-subagents.js
|
|
16029
|
+
import { createHash } from "node:crypto";
|
|
16030
|
+
|
|
16031
|
+
// dist/pi-subagent-workflow.js
|
|
16032
|
+
var PREFIX2 = "pi-subagents-workflow-v1:";
|
|
16033
|
+
var STATES = {
|
|
16034
|
+
pending: "pending",
|
|
16035
|
+
running: "running",
|
|
16036
|
+
completed: "completed",
|
|
16037
|
+
failed: "failed",
|
|
16038
|
+
paused: "interrupted",
|
|
16039
|
+
stopped: "interrupted",
|
|
16040
|
+
rejected: "failed",
|
|
16041
|
+
detached: "running"
|
|
16042
|
+
};
|
|
16043
|
+
function record2(value) {
|
|
16044
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16045
|
+
}
|
|
16046
|
+
function text(value, limit = 256) {
|
|
16047
|
+
return typeof value === "string" && value.length > 0 && value.length <= limit;
|
|
16048
|
+
}
|
|
16049
|
+
function piWorkflowSummary(result) {
|
|
16050
|
+
if (!record2(result) || !record2(result.details) || result.details.mode !== "workflow" || result.details.asyncId !== void 0)
|
|
16051
|
+
return null;
|
|
16052
|
+
const details = result.details;
|
|
16053
|
+
const summary = details.workflowChildren;
|
|
16054
|
+
if (!record2(summary) || summary.version !== 1 || !text(summary.workflowRunId) || summary.workflowRunId !== details.runId || !text(summary.parentToolCallId) || typeof summary.inventoryComplete !== "boolean" || !Array.isArray(summary.children) || summary.children.length > 256)
|
|
16055
|
+
return null;
|
|
16056
|
+
const children = [];
|
|
16057
|
+
const seen = /* @__PURE__ */ new Set();
|
|
16058
|
+
for (const child of summary.children) {
|
|
16059
|
+
if (!record2(child) || !text(child.childId) || seen.has(child.childId) || typeof child.state !== "string" || !Object.hasOwn(STATES, child.state))
|
|
16060
|
+
return null;
|
|
16061
|
+
for (const key of ["agent", "sessionName", "model", "thinking"]) {
|
|
16062
|
+
if (child[key] !== void 0 && !text(child[key], 2048))
|
|
16063
|
+
return null;
|
|
16064
|
+
}
|
|
16065
|
+
const mappedState = STATES[child.state];
|
|
16066
|
+
if (!mappedState)
|
|
16067
|
+
return null;
|
|
16068
|
+
seen.add(child.childId);
|
|
16069
|
+
children.push({
|
|
16070
|
+
childId: child.childId,
|
|
16071
|
+
state: mappedState,
|
|
16072
|
+
background: child.state === "detached",
|
|
16073
|
+
...typeof child.agent === "string" ? { agent: child.agent } : {},
|
|
16074
|
+
...typeof child.sessionName === "string" ? { sessionName: child.sessionName } : {},
|
|
16075
|
+
...typeof child.model === "string" ? { model: child.model } : {},
|
|
16076
|
+
...typeof child.thinking === "string" ? { thinking: child.thinking } : {}
|
|
16077
|
+
});
|
|
16078
|
+
}
|
|
16079
|
+
return {
|
|
16080
|
+
workflowRunId: summary.workflowRunId,
|
|
16081
|
+
parentToolCallId: summary.parentToolCallId,
|
|
16082
|
+
children
|
|
16083
|
+
};
|
|
16084
|
+
}
|
|
16085
|
+
function piWorkflowSubagentId(address) {
|
|
16086
|
+
return PREFIX2 + Buffer.from(JSON.stringify([address.workflowRunId, address.childId])).toString("base64url");
|
|
16087
|
+
}
|
|
16088
|
+
function parsePiWorkflowSubagentId(id) {
|
|
16089
|
+
if (!id.startsWith(PREFIX2))
|
|
16090
|
+
return null;
|
|
16091
|
+
if (id.length > 3e3)
|
|
16092
|
+
throw new Error("Invalid Pi workflow child identity");
|
|
16093
|
+
const value = JSON.parse(Buffer.from(id.slice(PREFIX2.length), "base64url").toString("utf8"));
|
|
16094
|
+
if (!Array.isArray(value) || value.length !== 2 || !text(value[0]) || !text(value[1]))
|
|
16095
|
+
throw new Error("Invalid Pi workflow child identity");
|
|
16096
|
+
const address = { workflowRunId: value[0], childId: value[1] };
|
|
16097
|
+
if (piWorkflowSubagentId(address) !== id)
|
|
16098
|
+
throw new Error("Non-canonical Pi workflow child identity");
|
|
16099
|
+
return address;
|
|
16100
|
+
}
|
|
16101
|
+
function projectPiWorkflow(summary, itemId2) {
|
|
16102
|
+
if (!summary.children.length)
|
|
16103
|
+
return null;
|
|
16104
|
+
return {
|
|
16105
|
+
type: "subagentDelegation",
|
|
16106
|
+
itemId: itemId2,
|
|
16107
|
+
operation: "spawn",
|
|
16108
|
+
subagents: summary.children.map((child) => {
|
|
16109
|
+
const id = piWorkflowSubagentId({
|
|
16110
|
+
workflowRunId: summary.workflowRunId,
|
|
16111
|
+
childId: child.childId
|
|
16112
|
+
});
|
|
16113
|
+
return {
|
|
16114
|
+
subagentId: id,
|
|
16115
|
+
nativeSubagentId: id,
|
|
16116
|
+
description: child.sessionName ?? child.agent ?? child.childId,
|
|
16117
|
+
status: child.state,
|
|
16118
|
+
background: child.background,
|
|
16119
|
+
...child.agent ? { role: child.agent } : {},
|
|
16120
|
+
...child.model ? { model: child.model } : {},
|
|
16121
|
+
...child.thinking ? { reasoningEffort: child.thinking } : {}
|
|
16122
|
+
};
|
|
16123
|
+
})
|
|
16124
|
+
};
|
|
16125
|
+
}
|
|
16126
|
+
|
|
16127
|
+
// dist/pi-subagents.js
|
|
16128
|
+
var STATUS_PREFIX = "PI_SUBAGENT_ASYNC_JSON:";
|
|
16129
|
+
var INSPECT_PREFIX = "PI_SUBAGENT_INSPECT_JSON:";
|
|
16130
|
+
var ID_PREFIX = "pi-subagents-v1:";
|
|
16131
|
+
var MAX_BYTES = 64 * 1024;
|
|
16132
|
+
function record3(value) {
|
|
16133
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16134
|
+
}
|
|
16135
|
+
function token(value) {
|
|
16136
|
+
return typeof value === "string" && value.length > 0 && value.length <= 256 && !value.startsWith("--") && !/\s/u.test(value) && [...value].every((character) => character.charCodeAt(0) > 32 && character.charCodeAt(0) !== 127);
|
|
16137
|
+
}
|
|
16138
|
+
var statuses = {
|
|
16139
|
+
queued: "pending",
|
|
16140
|
+
running: "running",
|
|
16141
|
+
complete: "completed",
|
|
16142
|
+
failed: "failed",
|
|
16143
|
+
partial: "failed",
|
|
16144
|
+
paused: "interrupted",
|
|
16145
|
+
stopped: "interrupted",
|
|
16146
|
+
rejected: "failed"
|
|
16147
|
+
};
|
|
16148
|
+
function node(value, depth, budget) {
|
|
16149
|
+
if (!record3(value) || depth > 8 || ++budget.count > 256 || !token(value.id) || !["subagent", "workflow", "step", "host-step"].includes(String(value.kind)) || typeof value.label !== "string" || value.label.length > 2048 || typeof value.state !== "string" || !Object.hasOwn(statuses, value.state))
|
|
16150
|
+
return null;
|
|
16151
|
+
const children = [];
|
|
16152
|
+
if (value.children !== void 0) {
|
|
16153
|
+
if (!Array.isArray(value.children))
|
|
16154
|
+
return null;
|
|
16155
|
+
for (const child of value.children) {
|
|
16156
|
+
const parsed = node(child, depth + 1, budget);
|
|
16157
|
+
if (!parsed)
|
|
16158
|
+
return null;
|
|
16159
|
+
children.push(parsed);
|
|
16160
|
+
}
|
|
16161
|
+
}
|
|
16162
|
+
return {
|
|
16163
|
+
id: value.id,
|
|
16164
|
+
kind: value.kind,
|
|
16165
|
+
label: value.label,
|
|
16166
|
+
state: value.state,
|
|
16167
|
+
...children.length ? { children } : {}
|
|
16168
|
+
};
|
|
16169
|
+
}
|
|
16170
|
+
function widget(value, key, prefix) {
|
|
16171
|
+
if (!record3(value) || value.type !== "extension_ui_request" || value.method !== "setWidget" || value.widgetKey !== key || !Array.isArray(value.widgetLines))
|
|
16172
|
+
return null;
|
|
16173
|
+
const line = value.widgetLines.find((part) => typeof part === "string" && part.startsWith(prefix));
|
|
16174
|
+
if (!line || Buffer.byteLength(line) > MAX_BYTES + prefix.length)
|
|
16175
|
+
return null;
|
|
16176
|
+
try {
|
|
16177
|
+
const parsed = JSON.parse(line.slice(prefix.length));
|
|
16178
|
+
return record3(parsed) && parsed.version === 1 ? parsed : null;
|
|
16179
|
+
} catch {
|
|
16180
|
+
return null;
|
|
16181
|
+
}
|
|
16182
|
+
}
|
|
16183
|
+
function parsePiSubagentStatus(value) {
|
|
16184
|
+
const parsed = widget(value, "subagent-async", STATUS_PREFIX);
|
|
16185
|
+
if (!parsed || parsed.kind !== "pi-subagents.async-status-snapshot" || !Array.isArray(parsed.runs))
|
|
16186
|
+
return null;
|
|
16187
|
+
const runs = [];
|
|
16188
|
+
const budget = { count: 0 };
|
|
16189
|
+
for (const run of parsed.runs) {
|
|
16190
|
+
const parsedNode = node(run, 0, budget);
|
|
16191
|
+
if (!parsedNode)
|
|
16192
|
+
return null;
|
|
16193
|
+
runs.push(parsedNode);
|
|
16194
|
+
}
|
|
16195
|
+
return runs;
|
|
16196
|
+
}
|
|
16197
|
+
function piSubagentId(address) {
|
|
16198
|
+
return ID_PREFIX + Buffer.from(JSON.stringify([address.runId, address.childId ?? null])).toString("base64url");
|
|
16199
|
+
}
|
|
16200
|
+
function parsePiSubagentId(id) {
|
|
16201
|
+
if (!id.startsWith(ID_PREFIX) || id.length > 1500)
|
|
16202
|
+
throw new Error("Invalid Pi Subagent identity");
|
|
16203
|
+
const value = JSON.parse(Buffer.from(id.slice(ID_PREFIX.length), "base64url").toString("utf8"));
|
|
16204
|
+
if (!Array.isArray(value) || value.length !== 2 || !token(value[0]) || value[1] !== null && !token(value[1]))
|
|
16205
|
+
throw new Error("Invalid Pi Subagent identity");
|
|
16206
|
+
const address = { runId: value[0], ...value[1] === null ? {} : { childId: value[1] } };
|
|
16207
|
+
if (piSubagentId(address) !== id)
|
|
16208
|
+
throw new Error("Non-canonical Pi Subagent identity");
|
|
16209
|
+
return address;
|
|
16210
|
+
}
|
|
16211
|
+
function states(run) {
|
|
16212
|
+
const result = [];
|
|
16213
|
+
const seen = /* @__PURE__ */ new Set();
|
|
16214
|
+
const visit = (entry, root) => {
|
|
16215
|
+
if (entry.kind === "host-step" || !root && entry.kind === "workflow")
|
|
16216
|
+
return;
|
|
16217
|
+
if (entry.kind !== "workflow") {
|
|
16218
|
+
const id = piSubagentId({ runId: run.id, ...!root ? { childId: entry.id } : {} });
|
|
16219
|
+
if (!seen.has(id)) {
|
|
16220
|
+
seen.add(id);
|
|
16221
|
+
result.push({
|
|
16222
|
+
subagentId: id,
|
|
16223
|
+
nativeSubagentId: id,
|
|
16224
|
+
description: entry.label,
|
|
16225
|
+
background: true,
|
|
16226
|
+
status: statuses[entry.state] ?? "running"
|
|
16227
|
+
});
|
|
16228
|
+
}
|
|
16229
|
+
}
|
|
16230
|
+
for (const child of entry.children ?? []) {
|
|
16231
|
+
if (entry.kind === "subagent" && child.kind === "step") {
|
|
16232
|
+
for (const nested of child.children ?? [])
|
|
16233
|
+
visit(nested, false);
|
|
16234
|
+
} else
|
|
16235
|
+
visit(child, false);
|
|
16236
|
+
}
|
|
16237
|
+
};
|
|
16238
|
+
visit(run, true);
|
|
16239
|
+
return result;
|
|
16240
|
+
}
|
|
16241
|
+
function asyncRunId(toolName, result) {
|
|
16242
|
+
if (toolName !== "subagent" || !record3(result) || !record3(result.details))
|
|
16243
|
+
return null;
|
|
16244
|
+
const details = result.details;
|
|
16245
|
+
return ["single", "parallel", "chain", "workflow"].includes(String(details.mode)) && token(details.asyncId) && typeof details.asyncDir === "string" ? details.asyncId : null;
|
|
16246
|
+
}
|
|
16247
|
+
var PiSubagents = class {
|
|
16248
|
+
emit;
|
|
16249
|
+
#children = /* @__PURE__ */ new Map();
|
|
16250
|
+
#active = /* @__PURE__ */ new Map();
|
|
16251
|
+
#waiting = /* @__PURE__ */ new Map();
|
|
16252
|
+
constructor(emit) {
|
|
16253
|
+
this.emit = emit;
|
|
16254
|
+
}
|
|
16255
|
+
observe(runs) {
|
|
16256
|
+
this.#apply(runs, true);
|
|
16257
|
+
}
|
|
16258
|
+
restore(runs) {
|
|
16259
|
+
this.#apply(runs, false);
|
|
16260
|
+
}
|
|
16261
|
+
#apply(runs, publish) {
|
|
16262
|
+
for (const run of runs) {
|
|
16263
|
+
const observed = states(run);
|
|
16264
|
+
const retained = this.#children.get(run.id) ?? /* @__PURE__ */ new Map();
|
|
16265
|
+
for (const child of observed)
|
|
16266
|
+
retained.set(child.subagentId, child);
|
|
16267
|
+
this.#children.set(run.id, retained);
|
|
16268
|
+
const children = [...retained.values()];
|
|
16269
|
+
if (!publish)
|
|
16270
|
+
continue;
|
|
16271
|
+
const waiting = this.#waiting.get(run.id);
|
|
16272
|
+
if (waiting && children.length) {
|
|
16273
|
+
const item = {
|
|
16274
|
+
type: "subagentDelegation",
|
|
16275
|
+
itemId: waiting.itemId,
|
|
16276
|
+
operation: "spawn",
|
|
16277
|
+
subagents: children
|
|
16278
|
+
};
|
|
16279
|
+
this.#waiting.delete(run.id);
|
|
16280
|
+
this.#active.set(run.id, { turnId: waiting.turnId, item });
|
|
16281
|
+
this.emit({ type: "item.started", turnId: waiting.turnId, item });
|
|
16282
|
+
}
|
|
16283
|
+
const active = this.#active.get(run.id);
|
|
16284
|
+
if (active && children.length) {
|
|
16285
|
+
const merged = new Map(active.item.subagents.map((child) => [child.nativeSubagentId, child]));
|
|
16286
|
+
for (const child of children)
|
|
16287
|
+
merged.set(child.nativeSubagentId, child);
|
|
16288
|
+
active.item = { ...active.item, subagents: [...merged.values()] };
|
|
16289
|
+
this.emit({
|
|
16290
|
+
type: "item.updated",
|
|
16291
|
+
turnId: active.turnId,
|
|
16292
|
+
itemId: active.item.itemId,
|
|
16293
|
+
update: { type: "subagents.replace", subagents: active.item.subagents }
|
|
16294
|
+
});
|
|
16295
|
+
}
|
|
16296
|
+
for (const child of observed) {
|
|
16297
|
+
this.emit({
|
|
16298
|
+
type: "subagent.state.changed",
|
|
16299
|
+
nativeSubagentId: child.subagentId,
|
|
16300
|
+
status: child.status
|
|
16301
|
+
});
|
|
16302
|
+
this.emit({ type: "subagent.transcript.changed", nativeSubagentId: child.subagentId });
|
|
16303
|
+
}
|
|
16304
|
+
}
|
|
16305
|
+
}
|
|
16306
|
+
project(toolName, result, itemId2, callId) {
|
|
16307
|
+
const workflow = toolName === "subagent" ? piWorkflowSummary(result) : null;
|
|
16308
|
+
if (workflow && (!callId || workflow.parentToolCallId === callId))
|
|
16309
|
+
return projectPiWorkflow(workflow, itemId2);
|
|
16310
|
+
const runId = asyncRunId(toolName, result);
|
|
16311
|
+
if (!runId || !this.#children.has(runId))
|
|
16312
|
+
return null;
|
|
16313
|
+
const children = [...this.#children.get(runId)?.values() ?? []];
|
|
16314
|
+
return children.length ? { type: "subagentDelegation", itemId: itemId2, operation: "spawn", subagents: children } : null;
|
|
16315
|
+
}
|
|
16316
|
+
start(turnId, toolName, result, itemId2, callId) {
|
|
16317
|
+
const workflow = toolName === "subagent" ? piWorkflowSummary(result) : null;
|
|
16318
|
+
if (workflow && (!callId || workflow.parentToolCallId === callId)) {
|
|
16319
|
+
const key = `workflow:${workflow.workflowRunId}`;
|
|
16320
|
+
const previous = this.#active.get(key);
|
|
16321
|
+
const item2 = projectPiWorkflow(workflow, previous?.item.itemId ?? itemId2);
|
|
16322
|
+
if (!item2)
|
|
16323
|
+
return;
|
|
16324
|
+
if (previous) {
|
|
16325
|
+
const children = new Map(previous.item.subagents.map((child) => [child.nativeSubagentId, child]));
|
|
16326
|
+
for (const child of item2.subagents)
|
|
16327
|
+
children.set(child.nativeSubagentId, child);
|
|
16328
|
+
item2.subagents = [...children.values()];
|
|
16329
|
+
previous.item = item2;
|
|
16330
|
+
this.emit({
|
|
16331
|
+
type: "item.updated",
|
|
16332
|
+
turnId: previous.turnId,
|
|
16333
|
+
itemId: item2.itemId,
|
|
16334
|
+
update: { type: "subagents.replace", subagents: item2.subagents }
|
|
16335
|
+
});
|
|
16336
|
+
} else {
|
|
16337
|
+
this.#active.set(key, { turnId, item: item2 });
|
|
16338
|
+
this.emit({ type: "item.started", turnId, item: item2 });
|
|
16339
|
+
}
|
|
16340
|
+
for (const child of item2.subagents) {
|
|
16341
|
+
this.emit({
|
|
16342
|
+
type: "subagent.state.changed",
|
|
16343
|
+
nativeSubagentId: child.subagentId,
|
|
16344
|
+
status: child.status
|
|
16345
|
+
});
|
|
16346
|
+
this.emit({ type: "subagent.transcript.changed", nativeSubagentId: child.subagentId });
|
|
16347
|
+
}
|
|
16348
|
+
return;
|
|
16349
|
+
}
|
|
16350
|
+
const runId = asyncRunId(toolName, result);
|
|
16351
|
+
const item = this.project(toolName, result, itemId2);
|
|
16352
|
+
if (!runId || this.#active.has(runId))
|
|
16353
|
+
return;
|
|
16354
|
+
if (!item) {
|
|
16355
|
+
this.#waiting.set(runId, { turnId, itemId: itemId2 });
|
|
16356
|
+
return;
|
|
16357
|
+
}
|
|
16358
|
+
this.#active.set(runId, { turnId, item });
|
|
16359
|
+
this.emit({ type: "item.started", turnId, item });
|
|
16360
|
+
}
|
|
16361
|
+
finish(turnId) {
|
|
16362
|
+
for (const [runId, waiting] of this.#waiting) {
|
|
16363
|
+
if (waiting.turnId === turnId)
|
|
16364
|
+
this.#waiting.delete(runId);
|
|
16365
|
+
}
|
|
16366
|
+
for (const [runId, active] of this.#active) {
|
|
16367
|
+
if (active.turnId !== turnId)
|
|
16368
|
+
continue;
|
|
16369
|
+
this.#active.delete(runId);
|
|
16370
|
+
this.emit({
|
|
16371
|
+
type: "item.completed",
|
|
16372
|
+
turnId,
|
|
16373
|
+
snapshot: { item: active.item, outcome: { status: "succeeded" } }
|
|
16374
|
+
});
|
|
16375
|
+
}
|
|
16376
|
+
}
|
|
16377
|
+
};
|
|
16378
|
+
function parsePiSubagentInspection(value) {
|
|
16379
|
+
const parsed = widget(value, "subagent-inspect", INSPECT_PREFIX);
|
|
16380
|
+
if (!parsed || parsed.kind !== "pi-subagents.inspect-reply" || !token(parsed.requestId))
|
|
16381
|
+
return null;
|
|
16382
|
+
if (parsed.error !== void 0 && (!record3(parsed.error) || typeof parsed.error.code !== "string" || typeof parsed.error.message !== "string"))
|
|
16383
|
+
return null;
|
|
16384
|
+
for (const field of ["asyncId", "childId", "status", "task", "finalOutput"]) {
|
|
16385
|
+
if (parsed[field] !== void 0 && typeof parsed[field] !== "string")
|
|
16386
|
+
return null;
|
|
16387
|
+
}
|
|
16388
|
+
if (parsed.messages !== void 0 && (!Array.isArray(parsed.messages) || parsed.messages.length > 200 || parsed.messages.some((entry) => !record3(entry) || typeof entry.role !== "string" || typeof entry.text !== "string" || !["text", "toolCall", "toolResult"].includes(String(entry.kind)) || entry.name !== void 0 && typeof entry.name !== "string")))
|
|
16389
|
+
return null;
|
|
16390
|
+
if (parsed.truncated !== void 0 && (!record3(parsed.truncated) || typeof parsed.truncated.task !== "boolean" || typeof parsed.truncated.finalOutput !== "boolean" || !Number.isSafeInteger(parsed.truncated.messages) || Number(parsed.truncated.messages) < 0))
|
|
16391
|
+
return null;
|
|
16392
|
+
return parsed;
|
|
16393
|
+
}
|
|
16394
|
+
function piSubagentSnapshot(parentSessionId, id, reply) {
|
|
16395
|
+
const messages = reply.messages ?? [];
|
|
16396
|
+
const texts = messages.map((entry) => entry.kind === "text" && entry.role === "assistant" ? entry.text : `[${entry.role}${entry.name ? `: ${entry.name}` : ""} / ${entry.kind}]
|
|
16397
|
+
${entry.text}`);
|
|
16398
|
+
if (!texts.length && reply.finalOutput)
|
|
16399
|
+
texts.push(reply.finalOutput);
|
|
16400
|
+
if (reply.truncated && (reply.truncated.task || reply.truncated.messages || reply.truncated.finalOutput)) {
|
|
16401
|
+
texts.push("[Pi subagent: native inspection returned a truncated transcript window.]");
|
|
16402
|
+
}
|
|
16403
|
+
return {
|
|
16404
|
+
turns: [
|
|
16405
|
+
{
|
|
16406
|
+
nativeTurnRef: nativeTurnRefSchema.parse({
|
|
16407
|
+
harnessId: "pi",
|
|
16408
|
+
nativeSessionId: parentSessionId,
|
|
16409
|
+
nativeTurnKey: `pi-subagent-${createHash("sha256").update(id).digest("hex")}`,
|
|
16410
|
+
formatVersion: 1
|
|
16411
|
+
}),
|
|
16412
|
+
input: reply.task ? [{ type: "text", text: reply.task }] : [],
|
|
16413
|
+
items: texts.map((text2, index) => ({
|
|
16414
|
+
item: {
|
|
16415
|
+
type: "agentMessage",
|
|
16416
|
+
text: text2,
|
|
16417
|
+
itemId: hostItemIdSchema.parse(`pi-subagent-${createHash("sha256").update(`${id}:${index}:${text2}`).digest("hex")}`)
|
|
16418
|
+
},
|
|
16419
|
+
outcome: { status: "succeeded" }
|
|
16420
|
+
})),
|
|
16421
|
+
outcome: reply.status === "complete" ? { status: "succeeded" } : reply.status === "stopped" ? { status: "cancelled", reason: "Pi subagent stopped" } : ["failed", "partial", "rejected"].includes(reply.status ?? "") ? {
|
|
16422
|
+
status: "failed",
|
|
16423
|
+
error: {
|
|
16424
|
+
code: "nativeFailure",
|
|
16425
|
+
message: `Pi subagent ${reply.status}`,
|
|
16426
|
+
retryable: false
|
|
16427
|
+
}
|
|
16428
|
+
} : {
|
|
16429
|
+
status: "unknown",
|
|
16430
|
+
reason: `Pi subagent ${reply.status ?? "status unavailable"}`
|
|
16431
|
+
}
|
|
16432
|
+
}
|
|
16433
|
+
]
|
|
16434
|
+
};
|
|
16435
|
+
}
|
|
16436
|
+
|
|
16437
|
+
// dist/pi-model-catalog.js
|
|
16438
|
+
var PI_MODEL_REF_PREFIX = "pi-model-v1.";
|
|
16439
|
+
var PI_DRAFT_THINKING_OPTION_IDS = [
|
|
16440
|
+
"off",
|
|
16441
|
+
"minimal",
|
|
16442
|
+
"low",
|
|
16443
|
+
"medium",
|
|
16444
|
+
"high",
|
|
16445
|
+
"xhigh",
|
|
16446
|
+
"max"
|
|
16447
|
+
].map((id) => harnessThinkingOptionIdSchema.parse(id));
|
|
16448
|
+
var PI_THINKING_LABELS = {
|
|
16449
|
+
off: "Off",
|
|
16450
|
+
minimal: "Minimal",
|
|
16451
|
+
low: "Low",
|
|
16452
|
+
medium: "Medium",
|
|
16453
|
+
high: "High",
|
|
16454
|
+
xhigh: "Extra High",
|
|
16455
|
+
max: "Max"
|
|
16456
|
+
};
|
|
16457
|
+
function compareText(left, right) {
|
|
16458
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
16459
|
+
}
|
|
16460
|
+
function assertNativePart(value, name) {
|
|
16461
|
+
if (value.trim().length === 0)
|
|
16462
|
+
throw new Error(`Pi ${name} must not be empty`);
|
|
16463
|
+
}
|
|
16464
|
+
function encodePiModelRef(model) {
|
|
16465
|
+
assertNativePart(model.provider, "Model provider");
|
|
16466
|
+
assertNativePart(model.id, "Model id");
|
|
16467
|
+
const encoded = Buffer.from(JSON.stringify([model.provider, model.id]), "utf8").toString("base64url");
|
|
16468
|
+
return harnessModelRefSchema.parse({ id: `${PI_MODEL_REF_PREFIX}${encoded}` });
|
|
16469
|
+
}
|
|
16470
|
+
function decodePiModelRef(ref) {
|
|
16471
|
+
const parsedRef = harnessModelRefSchema.parse(ref);
|
|
16472
|
+
if (!parsedRef.id.startsWith(PI_MODEL_REF_PREFIX)) {
|
|
16473
|
+
throw new Error("Model Ref does not belong to PiAdapter");
|
|
16474
|
+
}
|
|
16475
|
+
const encoded = parsedRef.id.slice(PI_MODEL_REF_PREFIX.length);
|
|
16476
|
+
let decoded;
|
|
16477
|
+
try {
|
|
16478
|
+
decoded = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8"));
|
|
16479
|
+
} catch {
|
|
16480
|
+
throw new Error("Pi Model Ref is malformed");
|
|
16481
|
+
}
|
|
16482
|
+
if (!Array.isArray(decoded) || decoded.length !== 2 || typeof decoded[0] !== "string" || typeof decoded[1] !== "string") {
|
|
16483
|
+
throw new Error("Pi Model Ref has an invalid native identity");
|
|
16484
|
+
}
|
|
16485
|
+
const native = { provider: decoded[0], id: decoded[1] };
|
|
16486
|
+
assertNativePart(native.provider, "Model provider");
|
|
16487
|
+
assertNativePart(native.id, "Model id");
|
|
16488
|
+
if (encodePiModelRef(native).id !== parsedRef.id) {
|
|
16489
|
+
throw new Error("Pi Model Ref is not canonical");
|
|
16490
|
+
}
|
|
16491
|
+
return native;
|
|
16492
|
+
}
|
|
16493
|
+
function samePiModel(left, right) {
|
|
16494
|
+
return left === null ? right === null : right !== null && left.provider === right.provider && left.id === right.id;
|
|
16495
|
+
}
|
|
16496
|
+
function fallbackThinkingLabel(id) {
|
|
16497
|
+
const label = id.split(/[._~-]+/u).filter((part) => part.length > 0).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
16498
|
+
return label || id;
|
|
16499
|
+
}
|
|
16500
|
+
function normalizePiThinkingOptions(levels) {
|
|
16501
|
+
return levels.map((id) => harnessThinkingOptionSchema.parse({
|
|
16502
|
+
id,
|
|
16503
|
+
label: PI_THINKING_LABELS[id] ?? fallbackThinkingLabel(id)
|
|
16504
|
+
}));
|
|
16505
|
+
}
|
|
16506
|
+
function normalizePiModelCatalog(nativeModels, effectiveModel, thinkingLevels, effectiveThinkingOptionId) {
|
|
16507
|
+
const byRef = /* @__PURE__ */ new Map();
|
|
16508
|
+
for (const native of nativeModels) {
|
|
16509
|
+
const ref = encodePiModelRef(native);
|
|
16510
|
+
const existing = byRef.get(ref.id);
|
|
16511
|
+
if (existing) {
|
|
16512
|
+
if (existing.reasoning !== native.reasoning) {
|
|
16513
|
+
throw new Error("Pi duplicate Model entries disagree on reasoning capability");
|
|
16514
|
+
}
|
|
16515
|
+
continue;
|
|
16516
|
+
}
|
|
16517
|
+
byRef.set(ref.id, {
|
|
16518
|
+
model: {
|
|
16519
|
+
ref,
|
|
16520
|
+
label: `${native.provider} / ${native.id}`
|
|
16521
|
+
},
|
|
16522
|
+
reasoning: native.reasoning
|
|
16523
|
+
});
|
|
16524
|
+
}
|
|
16525
|
+
const defaultModel = effectiveModel ? encodePiModelRef(effectiveModel) : void 0;
|
|
16526
|
+
if (defaultModel && !byRef.has(defaultModel.id)) {
|
|
16527
|
+
throw new Error("Pi effective Model is absent from the available Model catalog");
|
|
16528
|
+
}
|
|
16529
|
+
if (thinkingLevels && effectiveThinkingOptionId && !thinkingLevels.includes(effectiveThinkingOptionId)) {
|
|
16530
|
+
throw new Error("Pi effective Thinking option is absent from the available option catalog");
|
|
16531
|
+
}
|
|
16532
|
+
if (thinkingLevels && !effectiveThinkingOptionId) {
|
|
16533
|
+
throw new Error("Pi did not report an effective Thinking option");
|
|
16534
|
+
}
|
|
16535
|
+
const thinkingOptions = thinkingLevels ? normalizePiThinkingOptions(PI_DRAFT_THINKING_OPTION_IDS) : [];
|
|
16536
|
+
const allThinkingOptionIds = thinkingOptions.map(({ id }) => id);
|
|
16537
|
+
const offThinkingOptionId = thinkingOptions.find(({ id }) => id === "off")?.id;
|
|
16538
|
+
const models = [...byRef.values()].map(({ model, reasoning }) => ({
|
|
16539
|
+
...model,
|
|
16540
|
+
supportedThinkingOptionIds: reasoning ? allThinkingOptionIds : offThinkingOptionId ? [offThinkingOptionId] : []
|
|
16541
|
+
})).sort((left, right) => compareText(left.label, right.label) || compareText(left.ref.id, right.ref.id));
|
|
16542
|
+
const defaultThinkingOptionId = thinkingOptions.find(({ id }) => id === effectiveThinkingOptionId)?.id;
|
|
16543
|
+
return harnessModelCatalogSchema.parse({
|
|
16544
|
+
models,
|
|
16545
|
+
...defaultModel ? { defaultModel } : {},
|
|
16546
|
+
thinkingOptions,
|
|
16547
|
+
...defaultThinkingOptionId ? { defaultThinkingOptionId } : {}
|
|
16548
|
+
});
|
|
16549
|
+
}
|
|
16550
|
+
|
|
16551
|
+
// dist/pi-history.js
|
|
16552
|
+
var piHarnessId = harnessIdSchema.parse("pi");
|
|
16553
|
+
function isRecord(value) {
|
|
16554
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16555
|
+
}
|
|
16556
|
+
function textContent(value) {
|
|
16557
|
+
if (typeof value === "string")
|
|
16558
|
+
return value;
|
|
16559
|
+
if (!Array.isArray(value))
|
|
16560
|
+
return "";
|
|
16561
|
+
return value.filter((part) => isRecord(part) && part.type === "text" && typeof part.text === "string").map((part) => part.text).join("");
|
|
16562
|
+
}
|
|
16563
|
+
function thinkingContent(value) {
|
|
16564
|
+
if (!Array.isArray(value))
|
|
16565
|
+
return "";
|
|
16566
|
+
return value.filter((part) => isRecord(part) && part.type === "thinking" && typeof part.thinking === "string").map((part) => part.thinking).join("");
|
|
16567
|
+
}
|
|
16568
|
+
function validatedEntry(value) {
|
|
16569
|
+
if (typeof value.id !== "string" || value.id.length === 0 || value.parentId !== null && typeof value.parentId !== "string" || typeof value.type !== "string") {
|
|
16570
|
+
throw new Error("Pi history contains an invalid Entry identity");
|
|
16571
|
+
}
|
|
16572
|
+
return value;
|
|
16573
|
+
}
|
|
16574
|
+
function activePiEntries(history) {
|
|
15545
16575
|
if (history.leafId === null)
|
|
15546
16576
|
return [];
|
|
15547
16577
|
const byId = new Map(history.entries.map((value) => {
|
|
@@ -15609,10 +16639,10 @@ function itemOutcome(outcome) {
|
|
|
15609
16639
|
return { status: "succeeded" };
|
|
15610
16640
|
}
|
|
15611
16641
|
function toolOutput(value) {
|
|
15612
|
-
const
|
|
15613
|
-
return
|
|
16642
|
+
const text2 = textContent(value);
|
|
16643
|
+
return text2.length > 0 ? { content: [{ type: "text", text: text2 }] } : void 0;
|
|
15614
16644
|
}
|
|
15615
|
-
function snapshotItems(entries, outcome) {
|
|
16645
|
+
function snapshotItems(entries, outcome, subagents) {
|
|
15616
16646
|
const snapshots = [];
|
|
15617
16647
|
const toolCalls = /* @__PURE__ */ new Map();
|
|
15618
16648
|
for (const entry of entries) {
|
|
@@ -15621,7 +16651,7 @@ function snapshotItems(entries, outcome) {
|
|
|
15621
16651
|
continue;
|
|
15622
16652
|
const content = Array.isArray(nativeMessage.content) ? nativeMessage.content : [];
|
|
15623
16653
|
if (nativeMessage.role === "assistant") {
|
|
15624
|
-
const
|
|
16654
|
+
const text2 = textContent(content);
|
|
15625
16655
|
const reasoning = thinkingContent(content);
|
|
15626
16656
|
let projectedText = false;
|
|
15627
16657
|
let projectedReasoning = false;
|
|
@@ -15638,11 +16668,11 @@ function snapshotItems(entries, outcome) {
|
|
|
15638
16668
|
projectedReasoning = true;
|
|
15639
16669
|
continue;
|
|
15640
16670
|
}
|
|
15641
|
-
if (part.type === "text" && !projectedText &&
|
|
16671
|
+
if (part.type === "text" && !projectedText && text2.length > 0) {
|
|
15642
16672
|
const item2 = {
|
|
15643
16673
|
type: "agentMessage",
|
|
15644
16674
|
itemId: itemId(entry.id, "assistant", 0),
|
|
15645
|
-
text
|
|
16675
|
+
text: text2
|
|
15646
16676
|
};
|
|
15647
16677
|
snapshots.push({ item: item2, outcome: itemOutcome(outcome) });
|
|
15648
16678
|
projectedText = true;
|
|
@@ -15678,6 +16708,7 @@ function snapshotItems(entries, outcome) {
|
|
|
15678
16708
|
...output ? { output } : {}
|
|
15679
16709
|
};
|
|
15680
16710
|
const toolFailed = nativeMessage.isError === true;
|
|
16711
|
+
const delegation = subagents?.project(call.name, nativeMessage, itemId(call.entryId, "subagent", call.ordinal), nativeMessage.toolCallId);
|
|
15681
16712
|
snapshots.push({
|
|
15682
16713
|
item,
|
|
15683
16714
|
outcome: toolFailed ? {
|
|
@@ -15689,16 +16720,18 @@ function snapshotItems(entries, outcome) {
|
|
|
15689
16720
|
}
|
|
15690
16721
|
} : { status: "succeeded" }
|
|
15691
16722
|
});
|
|
16723
|
+
if (delegation)
|
|
16724
|
+
snapshots.push({ item: delegation, outcome: { status: "succeeded" } });
|
|
15692
16725
|
}
|
|
15693
16726
|
return snapshots;
|
|
15694
16727
|
}
|
|
15695
16728
|
function modelChange(entry) {
|
|
15696
16729
|
return entry.type === "model_change" && typeof entry.provider === "string" && typeof entry.modelId === "string" ? { provider: entry.provider, id: entry.modelId } : null;
|
|
15697
16730
|
}
|
|
15698
|
-
function mapPiSnapshot(history,
|
|
16731
|
+
function mapPiSnapshot(history, state2, subagents = new PiSubagents(() => void 0)) {
|
|
15699
16732
|
const active = activePiEntries(history);
|
|
15700
16733
|
const turns = [];
|
|
15701
|
-
let effectiveModel =
|
|
16734
|
+
let effectiveModel = state2.model;
|
|
15702
16735
|
for (let index = 0; index < active.length; ) {
|
|
15703
16736
|
const model = modelChange(active[index]);
|
|
15704
16737
|
if (model) {
|
|
@@ -15719,13 +16752,13 @@ function mapPiSnapshot(history, state) {
|
|
|
15719
16752
|
const userText = textContent(message(user)?.content);
|
|
15720
16753
|
const nativeTurnRef = nativeTurnRefSchema.parse({
|
|
15721
16754
|
harnessId: piHarnessId,
|
|
15722
|
-
nativeSessionId:
|
|
16755
|
+
nativeSessionId: state2.sessionId,
|
|
15723
16756
|
nativeTurnKey: user.id,
|
|
15724
16757
|
formatVersion: 1
|
|
15725
16758
|
});
|
|
15726
16759
|
const checkpoint = nativeCheckpointRefSchema.parse({
|
|
15727
16760
|
harnessId: piHarnessId,
|
|
15728
|
-
nativeSessionId:
|
|
16761
|
+
nativeSessionId: state2.sessionId,
|
|
15729
16762
|
checkpointId: user.id,
|
|
15730
16763
|
formatVersion: 1
|
|
15731
16764
|
});
|
|
@@ -15733,7 +16766,7 @@ function mapPiSnapshot(history, state) {
|
|
|
15733
16766
|
nativeTurnRef,
|
|
15734
16767
|
checkpoint,
|
|
15735
16768
|
input: [{ type: "text", text: userText }],
|
|
15736
|
-
items: snapshotItems(entries, outcome),
|
|
16769
|
+
items: snapshotItems(entries, outcome, subagents),
|
|
15737
16770
|
outcome,
|
|
15738
16771
|
...effectiveModel ? { model: encodePiModelRef(effectiveModel) } : {}
|
|
15739
16772
|
});
|
|
@@ -15764,7 +16797,7 @@ function resolvePiForkBoundary(history, checkpointId) {
|
|
|
15764
16797
|
}
|
|
15765
16798
|
|
|
15766
16799
|
// dist/pi-session-file.js
|
|
15767
|
-
import { open, realpath } from "node:fs/promises";
|
|
16800
|
+
import { open, realpath as realpath2 } from "node:fs/promises";
|
|
15768
16801
|
var MAX_SESSION_HEADER_BYTES = 64 * 1024;
|
|
15769
16802
|
var utf8Decoder = new TextDecoder("utf-8", { fatal: true });
|
|
15770
16803
|
function isRecord2(value) {
|
|
@@ -15808,8 +16841,8 @@ async function verifyPiSessionCwd(input) {
|
|
|
15808
16841
|
throw new Error("Pi Fork Session header identity does not match RPC state");
|
|
15809
16842
|
}
|
|
15810
16843
|
const [actualCwd, expectedCwd] = await Promise.all([
|
|
15811
|
-
|
|
15812
|
-
|
|
16844
|
+
realpath2(header.cwd),
|
|
16845
|
+
realpath2(input.expectedCwd)
|
|
15813
16846
|
]);
|
|
15814
16847
|
if (actualCwd !== expectedCwd) {
|
|
15815
16848
|
throw new Error("Pi Fork Session did not bind the requested cwd");
|
|
@@ -15818,9 +16851,9 @@ async function verifyPiSessionCwd(input) {
|
|
|
15818
16851
|
|
|
15819
16852
|
// dist/pi-empty-session.js
|
|
15820
16853
|
async function persistEmptyPiSession(input) {
|
|
15821
|
-
const { state, history, sourceSessionFile, sourceSessionId, cwd } = input;
|
|
15822
|
-
const destination =
|
|
15823
|
-
if (!destination || !
|
|
16854
|
+
const { state: state2, history, sourceSessionFile, sourceSessionId, cwd } = input;
|
|
16855
|
+
const destination = state2.sessionFile;
|
|
16856
|
+
if (!destination || !path4.isAbsolute(destination) || path4.resolve(destination) === path4.resolve(sourceSessionFile) || state2.sessionId === sourceSessionId || mapPiSnapshot(history, { sessionId: state2.sessionId, model: null }).turns.length !== 0)
|
|
15824
16857
|
throw new Error("Pi empty Session is not an independent empty native fork");
|
|
15825
16858
|
await verifyPiSessionCwd({
|
|
15826
16859
|
sessionFile: sourceSessionFile,
|
|
@@ -15839,12 +16872,12 @@ async function persistEmptyPiSession(input) {
|
|
|
15839
16872
|
const header = {
|
|
15840
16873
|
type: "session",
|
|
15841
16874
|
version: 3,
|
|
15842
|
-
id:
|
|
16875
|
+
id: state2.sessionId,
|
|
15843
16876
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15844
16877
|
cwd,
|
|
15845
16878
|
parentSession: sourceSessionFile
|
|
15846
16879
|
};
|
|
15847
|
-
const temporary =
|
|
16880
|
+
const temporary = path4.join(path4.dirname(destination), `.codexhost-${randomUUID2()}.tmp`);
|
|
15848
16881
|
try {
|
|
15849
16882
|
const file2 = await open2(temporary, "wx", 384);
|
|
15850
16883
|
try {
|
|
@@ -15855,7 +16888,7 @@ async function persistEmptyPiSession(input) {
|
|
|
15855
16888
|
}
|
|
15856
16889
|
await link(temporary, destination);
|
|
15857
16890
|
if (process.platform !== "win32") {
|
|
15858
|
-
const directory = await open2(
|
|
16891
|
+
const directory = await open2(path4.dirname(destination), "r");
|
|
15859
16892
|
try {
|
|
15860
16893
|
await directory.sync();
|
|
15861
16894
|
} finally {
|
|
@@ -16018,16 +17051,16 @@ var Diff = class {
|
|
|
16018
17051
|
}
|
|
16019
17052
|
}
|
|
16020
17053
|
}
|
|
16021
|
-
addToPath(
|
|
16022
|
-
const last =
|
|
17054
|
+
addToPath(path10, added, removed, oldPosInc, options) {
|
|
17055
|
+
const last = path10.lastComponent;
|
|
16023
17056
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
16024
17057
|
return {
|
|
16025
|
-
oldPos:
|
|
17058
|
+
oldPos: path10.oldPos + oldPosInc,
|
|
16026
17059
|
lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
|
|
16027
17060
|
};
|
|
16028
17061
|
} else {
|
|
16029
17062
|
return {
|
|
16030
|
-
oldPos:
|
|
17063
|
+
oldPos: path10.oldPos + oldPosInc,
|
|
16031
17064
|
lastComponent: { count: 1, added, removed, previousComponent: last }
|
|
16032
17065
|
};
|
|
16033
17066
|
}
|
|
@@ -16393,788 +17426,729 @@ function formatPatch(patch) {
|
|
|
16393
17426
|
ret.push("+++ " + patch.newFileName + (typeof patch.newHeader === "undefined" ? "" : " " + patch.newHeader));
|
|
16394
17427
|
for (let i = 0; i < patch.hunks.length; i++) {
|
|
16395
17428
|
const hunk = patch.hunks[i];
|
|
16396
|
-
if (hunk.oldLines === 0) {
|
|
16397
|
-
hunk.oldStart -= 1;
|
|
16398
|
-
}
|
|
16399
|
-
if (hunk.newLines === 0) {
|
|
16400
|
-
hunk.newStart -= 1;
|
|
16401
|
-
}
|
|
16402
|
-
ret.push("@@ -" + hunk.oldStart + "," + hunk.oldLines + " +" + hunk.newStart + "," + hunk.newLines + " @@");
|
|
16403
|
-
for (const line of hunk.lines) {
|
|
16404
|
-
ret.push(line);
|
|
16405
|
-
}
|
|
16406
|
-
}
|
|
16407
|
-
return ret.join("\n") + "\n";
|
|
16408
|
-
}
|
|
16409
|
-
function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
|
|
16410
|
-
if (typeof options === "function") {
|
|
16411
|
-
options = { callback: options };
|
|
16412
|
-
}
|
|
16413
|
-
if (!(options === null || options === void 0 ? void 0 : options.callback)) {
|
|
16414
|
-
const patchObj = structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options);
|
|
16415
|
-
if (!patchObj) {
|
|
16416
|
-
return;
|
|
16417
|
-
}
|
|
16418
|
-
return formatPatch(patchObj);
|
|
16419
|
-
} else {
|
|
16420
|
-
const { callback } = options;
|
|
16421
|
-
structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, Object.assign(Object.assign({}, options), { callback: (patchObj) => {
|
|
16422
|
-
if (!patchObj) {
|
|
16423
|
-
callback(void 0);
|
|
16424
|
-
} else {
|
|
16425
|
-
callback(formatPatch(patchObj));
|
|
16426
|
-
}
|
|
16427
|
-
} }));
|
|
16428
|
-
}
|
|
16429
|
-
}
|
|
16430
|
-
function splitLines(text) {
|
|
16431
|
-
const hasTrailingNl = text.endsWith("\n");
|
|
16432
|
-
const result = text.split("\n").map((line) => line + "\n");
|
|
16433
|
-
if (hasTrailingNl) {
|
|
16434
|
-
result.pop();
|
|
16435
|
-
} else {
|
|
16436
|
-
result.push(result.pop().slice(0, -1));
|
|
16437
|
-
}
|
|
16438
|
-
return result;
|
|
16439
|
-
}
|
|
16440
|
-
|
|
16441
|
-
// dist/pi-adapter.js
|
|
16442
|
-
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
16443
|
-
import path6 from "node:path";
|
|
16444
|
-
|
|
16445
|
-
// ../../harness-adapter/dist/question.js
|
|
16446
|
-
function invalidRequest(message3) {
|
|
16447
|
-
return { code: "invalidRequest", message: message3, retryable: false };
|
|
16448
|
-
}
|
|
16449
|
-
function validateHostQuestionResponse(interaction, response) {
|
|
16450
|
-
const questionIds = new Set(interaction.questions.map(({ id }) => id));
|
|
16451
|
-
if (response.cancelled) {
|
|
16452
|
-
return Object.keys(response.answers).length === 0 ? null : invalidRequest("Cancelled Question Response must not contain answers");
|
|
16453
|
-
}
|
|
16454
|
-
for (const answerId of Object.keys(response.answers)) {
|
|
16455
|
-
if (!questionIds.has(answerId)) {
|
|
16456
|
-
return invalidRequest("Question Response contains an unknown Question ID");
|
|
16457
|
-
}
|
|
16458
|
-
}
|
|
16459
|
-
for (const question of interaction.questions) {
|
|
16460
|
-
const answers = response.answers[question.id] ?? [];
|
|
16461
|
-
if (!question.optional && answers.length === 0) {
|
|
16462
|
-
return invalidRequest("Question Response omits a required answer");
|
|
16463
|
-
}
|
|
16464
|
-
if (question.type === "text") {
|
|
16465
|
-
if (answers.length > 1) {
|
|
16466
|
-
return invalidRequest("Text Question accepts at most one answer");
|
|
16467
|
-
}
|
|
16468
|
-
continue;
|
|
16469
|
-
}
|
|
16470
|
-
if (!question.multiple && answers.length > 1) {
|
|
16471
|
-
return invalidRequest("Single-choice Question accepts at most one answer");
|
|
16472
|
-
}
|
|
16473
|
-
const declared = new Set(question.options.map(({ value }) => value));
|
|
16474
|
-
if (!question.allowOther && answers.some((answer) => !declared.has(answer))) {
|
|
16475
|
-
return invalidRequest("Question Response contains an undeclared choice");
|
|
16476
|
-
}
|
|
16477
|
-
}
|
|
16478
|
-
return null;
|
|
16479
|
-
}
|
|
16480
|
-
|
|
16481
|
-
// ../../harness-adapter/dist/output-channel.js
|
|
16482
|
-
var HarnessOutputChannel = class {
|
|
16483
|
-
outputs;
|
|
16484
|
-
#consumerCreated = false;
|
|
16485
|
-
#ended = false;
|
|
16486
|
-
#pending = [];
|
|
16487
|
-
#values = [];
|
|
16488
|
-
constructor() {
|
|
16489
|
-
this.outputs = {
|
|
16490
|
-
[Symbol.asyncIterator]: () => {
|
|
16491
|
-
if (this.#consumerCreated) {
|
|
16492
|
-
throw new Error("Harness outputs allow only one consumer");
|
|
16493
|
-
}
|
|
16494
|
-
this.#consumerCreated = true;
|
|
16495
|
-
return {
|
|
16496
|
-
next: () => this.#next()
|
|
16497
|
-
};
|
|
16498
|
-
}
|
|
16499
|
-
};
|
|
16500
|
-
}
|
|
16501
|
-
emit(value) {
|
|
16502
|
-
if (this.#ended)
|
|
16503
|
-
return false;
|
|
16504
|
-
const resolve = this.#pending.shift();
|
|
16505
|
-
if (resolve)
|
|
16506
|
-
resolve({ done: false, value });
|
|
16507
|
-
else
|
|
16508
|
-
this.#values.push(value);
|
|
16509
|
-
return true;
|
|
16510
|
-
}
|
|
16511
|
-
end() {
|
|
16512
|
-
if (this.#ended)
|
|
16513
|
-
return;
|
|
16514
|
-
this.#ended = true;
|
|
16515
|
-
if (this.#values.length !== 0)
|
|
16516
|
-
return;
|
|
16517
|
-
for (const resolve of this.#pending.splice(0))
|
|
16518
|
-
resolve({ done: true, value: void 0 });
|
|
16519
|
-
}
|
|
16520
|
-
#next() {
|
|
16521
|
-
const value = this.#values.shift();
|
|
16522
|
-
if (value !== void 0)
|
|
16523
|
-
return Promise.resolve({ done: false, value });
|
|
16524
|
-
if (this.#ended)
|
|
16525
|
-
return Promise.resolve({ done: true, value: void 0 });
|
|
16526
|
-
return new Promise((resolve) => this.#pending.push(resolve));
|
|
16527
|
-
}
|
|
16528
|
-
};
|
|
16529
|
-
|
|
16530
|
-
// ../../harness-adapter/dist/diagnostics.js
|
|
16531
|
-
var DIAGNOSTIC_TAIL_MAX_LENGTH = 8e3;
|
|
16532
|
-
var SENSITIVE_VALUE_PATTERN = /(api[_-]?key|access[_-]?token|auth(?:orization)?|password|secret)(\s*[:=]\s*)([^\s,;]+)/giu;
|
|
16533
|
-
var BEARER_PATTERN = /\bBearer\s+[A-Za-z0-9._~+/=-]+/giu;
|
|
16534
|
-
function sanitizeDiagnosticTail(value) {
|
|
16535
|
-
const redacted = value.replace(BEARER_PATTERN, "Bearer [redacted]").replace(SENSITIVE_VALUE_PATTERN, "$1$2[redacted]");
|
|
16536
|
-
return redacted.length <= DIAGNOSTIC_TAIL_MAX_LENGTH ? redacted : redacted.slice(-DIAGNOSTIC_TAIL_MAX_LENGTH);
|
|
16537
|
-
}
|
|
16538
|
-
|
|
16539
|
-
// ../../harness-adapter/dist/usage.js
|
|
16540
|
-
var tokenFields = [
|
|
16541
|
-
"inputTokens",
|
|
16542
|
-
"cachedInputTokens",
|
|
16543
|
-
"cacheWriteInputTokens",
|
|
16544
|
-
"outputTokens",
|
|
16545
|
-
"outputTokensPerSecond",
|
|
16546
|
-
"reasoningOutputTokens",
|
|
16547
|
-
"totalTokens",
|
|
16548
|
-
"contextWindowTokens",
|
|
16549
|
-
"contextUsedTokens"
|
|
16550
|
-
];
|
|
16551
|
-
var safeIntegerFields = [
|
|
16552
|
-
"planFiveHourResetsAtUnix",
|
|
16553
|
-
"planSevenDayResetsAtUnix"
|
|
16554
|
-
];
|
|
16555
|
-
var percentFields = [
|
|
16556
|
-
"cacheHitRatePercent",
|
|
16557
|
-
"planFiveHourUsedPercent",
|
|
16558
|
-
"planSevenDayUsedPercent"
|
|
16559
|
-
];
|
|
16560
|
-
var usageFields = /* @__PURE__ */ new Set([
|
|
16561
|
-
...tokenFields,
|
|
16562
|
-
...safeIntegerFields,
|
|
16563
|
-
...percentFields,
|
|
16564
|
-
"totalCostUsd",
|
|
16565
|
-
"totalCredits",
|
|
16566
|
-
"contextUsagePercent"
|
|
16567
|
-
]);
|
|
16568
|
-
function isRecord3(value) {
|
|
16569
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16570
|
-
}
|
|
16571
|
-
function parseHostUsage(value) {
|
|
16572
|
-
if (!isRecord3(value))
|
|
16573
|
-
throw new Error("Harness Usage must be an object");
|
|
16574
|
-
const keys = Object.keys(value);
|
|
16575
|
-
if (keys.length === 0)
|
|
16576
|
-
throw new Error("Harness Usage must contain a reliable field");
|
|
16577
|
-
for (const key of keys) {
|
|
16578
|
-
if (!usageFields.has(key)) {
|
|
16579
|
-
throw new Error(`Harness Usage contains unknown field '${key}'`);
|
|
16580
|
-
}
|
|
16581
|
-
}
|
|
16582
|
-
for (const field of ["totalCredits", "contextUsagePercent"]) {
|
|
16583
|
-
const candidate = value[field];
|
|
16584
|
-
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0)) {
|
|
16585
|
-
throw new Error(`Harness Usage '${field}' must be a finite non-negative number`);
|
|
16586
|
-
}
|
|
16587
|
-
}
|
|
16588
|
-
for (const field of tokenFields) {
|
|
16589
|
-
const candidate = value[field];
|
|
16590
|
-
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0)) {
|
|
16591
|
-
throw new Error(`Harness Usage '${field}' must be a non-negative safe integer`);
|
|
16592
|
-
}
|
|
16593
|
-
}
|
|
16594
|
-
for (const field of safeIntegerFields) {
|
|
16595
|
-
const candidate = value[field];
|
|
16596
|
-
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0)) {
|
|
16597
|
-
throw new Error(`Harness Usage '${field}' must be a non-negative safe integer`);
|
|
16598
|
-
}
|
|
16599
|
-
}
|
|
16600
|
-
if (value.outputTokensPerSecond !== void 0 && (typeof value.outputTokensPerSecond !== "number" || !Number.isFinite(value.outputTokensPerSecond) || value.outputTokensPerSecond < 0)) {
|
|
16601
|
-
throw new Error("Harness Usage 'outputTokensPerSecond' must be a finite non-negative number");
|
|
16602
|
-
}
|
|
16603
|
-
if (value.totalCostUsd !== void 0 && (typeof value.totalCostUsd !== "number" || !Number.isFinite(value.totalCostUsd) || value.totalCostUsd < 0)) {
|
|
16604
|
-
throw new Error("Harness Usage 'totalCostUsd' must be a finite non-negative number");
|
|
16605
|
-
}
|
|
16606
|
-
for (const field of ["totalCredits", "contextUsagePercent"]) {
|
|
16607
|
-
const candidate = value[field];
|
|
16608
|
-
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0)) {
|
|
16609
|
-
throw new Error(`Harness Usage '${field}' must be a finite non-negative number`);
|
|
17429
|
+
if (hunk.oldLines === 0) {
|
|
17430
|
+
hunk.oldStart -= 1;
|
|
16610
17431
|
}
|
|
16611
|
-
|
|
16612
|
-
|
|
16613
|
-
|
|
16614
|
-
|
|
16615
|
-
|
|
17432
|
+
if (hunk.newLines === 0) {
|
|
17433
|
+
hunk.newStart -= 1;
|
|
17434
|
+
}
|
|
17435
|
+
ret.push("@@ -" + hunk.oldStart + "," + hunk.oldLines + " +" + hunk.newStart + "," + hunk.newLines + " @@");
|
|
17436
|
+
for (const line of hunk.lines) {
|
|
17437
|
+
ret.push(line);
|
|
16616
17438
|
}
|
|
16617
17439
|
}
|
|
16618
|
-
|
|
16619
|
-
|
|
16620
|
-
|
|
16621
|
-
|
|
16622
|
-
|
|
16623
|
-
if (hasContextWindow && value.contextWindowTokens === 0) {
|
|
16624
|
-
throw new Error("Harness Usage 'contextWindowTokens' must be greater than zero");
|
|
17440
|
+
return ret.join("\n") + "\n";
|
|
17441
|
+
}
|
|
17442
|
+
function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
|
|
17443
|
+
if (typeof options === "function") {
|
|
17444
|
+
options = { callback: options };
|
|
16625
17445
|
}
|
|
16626
|
-
if (
|
|
16627
|
-
|
|
17446
|
+
if (!(options === null || options === void 0 ? void 0 : options.callback)) {
|
|
17447
|
+
const patchObj = structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options);
|
|
17448
|
+
if (!patchObj) {
|
|
17449
|
+
return;
|
|
17450
|
+
}
|
|
17451
|
+
return formatPatch(patchObj);
|
|
17452
|
+
} else {
|
|
17453
|
+
const { callback } = options;
|
|
17454
|
+
structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, Object.assign(Object.assign({}, options), { callback: (patchObj) => {
|
|
17455
|
+
if (!patchObj) {
|
|
17456
|
+
callback(void 0);
|
|
17457
|
+
} else {
|
|
17458
|
+
callback(formatPatch(patchObj));
|
|
17459
|
+
}
|
|
17460
|
+
} }));
|
|
16628
17461
|
}
|
|
16629
|
-
|
|
16630
|
-
|
|
17462
|
+
}
|
|
17463
|
+
function splitLines(text2) {
|
|
17464
|
+
const hasTrailingNl = text2.endsWith("\n");
|
|
17465
|
+
const result = text2.split("\n").map((line) => line + "\n");
|
|
17466
|
+
if (hasTrailingNl) {
|
|
17467
|
+
result.pop();
|
|
17468
|
+
} else {
|
|
17469
|
+
result.push(result.pop().slice(0, -1));
|
|
16631
17470
|
}
|
|
16632
|
-
return
|
|
17471
|
+
return result;
|
|
16633
17472
|
}
|
|
16634
17473
|
|
|
16635
|
-
// dist/pi-
|
|
16636
|
-
|
|
16637
|
-
|
|
16638
|
-
|
|
16639
|
-
|
|
16640
|
-
|
|
16641
|
-
}
|
|
16642
|
-
return { provider: state.provider, id: state.modelId };
|
|
17474
|
+
// dist/pi-adapter.js
|
|
17475
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
17476
|
+
import path9 from "node:path";
|
|
17477
|
+
|
|
17478
|
+
// ../../harness-adapter/dist/question.js
|
|
17479
|
+
function invalidRequest(message3) {
|
|
17480
|
+
return { code: "invalidRequest", message: message3, retryable: false };
|
|
16643
17481
|
}
|
|
16644
|
-
|
|
16645
|
-
const
|
|
16646
|
-
|
|
16647
|
-
|
|
16648
|
-
const currentThinking = startupState.thinkingLevel;
|
|
16649
|
-
const copiedHistory = await transport.getEntries();
|
|
16650
|
-
const boundary = resolvePiLastTurnBoundary(copiedHistory);
|
|
16651
|
-
if (!boundary)
|
|
16652
|
-
return { ok: false, reason: "empty" };
|
|
16653
|
-
const sourceSnapshot = mapPiSnapshot(copiedHistory, {
|
|
16654
|
-
sessionId: startupSessionId,
|
|
16655
|
-
model: currentModel
|
|
16656
|
-
});
|
|
16657
|
-
let state = await transport.fork(boundary.lastUserEntryId);
|
|
16658
|
-
if (state.sessionId === sourceSessionId || state.sessionId === startupSessionId) {
|
|
16659
|
-
throw new Error("Pi last-Turn rollback did not create a distinct Native Session");
|
|
16660
|
-
}
|
|
16661
|
-
if (!samePiModel(modelFromState(state), currentModel)) {
|
|
16662
|
-
if (!currentModel)
|
|
16663
|
-
throw new Error("Pi last-Turn rollback changed the current Model");
|
|
16664
|
-
state = await transport.selectModel(currentModel);
|
|
16665
|
-
}
|
|
16666
|
-
if (state.thinkingLevel !== currentThinking) {
|
|
16667
|
-
if (!currentThinking)
|
|
16668
|
-
throw new Error("Pi last-Turn rollback changed current Thinking");
|
|
16669
|
-
state = await transport.selectThinkingOption(currentThinking);
|
|
16670
|
-
}
|
|
16671
|
-
if (!samePiModel(modelFromState(state), currentModel) || state.thinkingLevel !== currentThinking) {
|
|
16672
|
-
throw new Error("Pi last-Turn rollback could not restore current Model and Thinking");
|
|
17482
|
+
function validateHostQuestionResponse(interaction, response) {
|
|
17483
|
+
const questionIds = new Set(interaction.questions.map(({ id }) => id));
|
|
17484
|
+
if (response.cancelled) {
|
|
17485
|
+
return Object.keys(response.answers).length === 0 ? null : invalidRequest("Cancelled Question Response must not contain answers");
|
|
16673
17486
|
}
|
|
16674
|
-
const
|
|
16675
|
-
|
|
16676
|
-
|
|
16677
|
-
|
|
16678
|
-
const expectedTurnKeys = sourceSnapshot.turns.slice(0, -1).map((turn) => turn.nativeTurnRef.nativeTurnKey);
|
|
16679
|
-
const actualTurnKeys = snapshot.turns.map((turn) => turn.nativeTurnRef.nativeTurnKey);
|
|
16680
|
-
if (snapshot.turns.length !== boundary.sourceTurnCount - 1 || actualTurnKeys.some((key, index) => key !== expectedTurnKeys[index])) {
|
|
16681
|
-
throw new Error("Pi last-Turn rollback did not produce the exact retained history prefix");
|
|
17487
|
+
for (const answerId of Object.keys(response.answers)) {
|
|
17488
|
+
if (!questionIds.has(answerId)) {
|
|
17489
|
+
return invalidRequest("Question Response contains an unknown Question ID");
|
|
17490
|
+
}
|
|
16682
17491
|
}
|
|
16683
|
-
|
|
16684
|
-
|
|
16685
|
-
|
|
16686
|
-
|
|
16687
|
-
|
|
16688
|
-
|
|
17492
|
+
for (const question of interaction.questions) {
|
|
17493
|
+
const answers = response.answers[question.id] ?? [];
|
|
17494
|
+
if (!question.optional && answers.length === 0) {
|
|
17495
|
+
return invalidRequest("Question Response omits a required answer");
|
|
17496
|
+
}
|
|
17497
|
+
if (question.type === "text") {
|
|
17498
|
+
if (answers.length > 1) {
|
|
17499
|
+
return invalidRequest("Text Question accepts at most one answer");
|
|
17500
|
+
}
|
|
17501
|
+
continue;
|
|
17502
|
+
}
|
|
17503
|
+
if (!question.multiple && answers.length > 1) {
|
|
17504
|
+
return invalidRequest("Single-choice Question accepts at most one answer");
|
|
17505
|
+
}
|
|
17506
|
+
const declared = new Set(question.options.map(({ value }) => value));
|
|
17507
|
+
if (!question.allowOther && answers.some((answer) => !declared.has(answer))) {
|
|
17508
|
+
return invalidRequest("Question Response contains an undeclared choice");
|
|
16689
17509
|
}
|
|
16690
|
-
throw error51;
|
|
16691
17510
|
}
|
|
17511
|
+
return null;
|
|
16692
17512
|
}
|
|
16693
17513
|
|
|
16694
|
-
// dist/
|
|
16695
|
-
|
|
16696
|
-
|
|
16697
|
-
|
|
16698
|
-
|
|
16699
|
-
|
|
16700
|
-
|
|
17514
|
+
// ../../harness-adapter/dist/output-channel.js
|
|
17515
|
+
var HarnessOutputChannel = class {
|
|
17516
|
+
outputs;
|
|
17517
|
+
#consumerCreated = false;
|
|
17518
|
+
#ended = false;
|
|
17519
|
+
#pending = [];
|
|
17520
|
+
#values = [];
|
|
16701
17521
|
constructor() {
|
|
16702
|
-
|
|
17522
|
+
this.outputs = {
|
|
17523
|
+
[Symbol.asyncIterator]: () => {
|
|
17524
|
+
if (this.#consumerCreated) {
|
|
17525
|
+
throw new Error("Harness outputs allow only one consumer");
|
|
17526
|
+
}
|
|
17527
|
+
this.#consumerCreated = true;
|
|
17528
|
+
return {
|
|
17529
|
+
next: () => this.#next()
|
|
17530
|
+
};
|
|
17531
|
+
}
|
|
17532
|
+
};
|
|
16703
17533
|
}
|
|
16704
|
-
|
|
16705
|
-
|
|
16706
|
-
|
|
16707
|
-
|
|
16708
|
-
|
|
16709
|
-
|
|
16710
|
-
|
|
16711
|
-
|
|
16712
|
-
|
|
16713
|
-
}
|
|
16714
|
-
|
|
16715
|
-
|
|
16716
|
-
}
|
|
16717
|
-
function piSessionImportDirectory(environment) {
|
|
16718
|
-
const home = (process.platform === "win32" ? environment.USERPROFILE : environment.HOME) || os.homedir();
|
|
16719
|
-
const custom2 = environment.PI_CODING_AGENT_SESSION_DIR;
|
|
16720
|
-
if (custom2)
|
|
16721
|
-
return { directory: expandDirectory(custom2, home), flat: true };
|
|
16722
|
-
const agent = environment.PI_CODING_AGENT_DIR;
|
|
16723
|
-
return {
|
|
16724
|
-
directory: path2.join(agent ? expandDirectory(agent, home) : path2.join(home, ".pi", "agent"), "sessions"),
|
|
16725
|
-
flat: false
|
|
16726
|
-
};
|
|
16727
|
-
}
|
|
16728
|
-
async function sessionFiles(directory, flat, signal) {
|
|
16729
|
-
const files = [];
|
|
16730
|
-
const visit = async (dir, projectLevel) => {
|
|
16731
|
-
signal.throwIfAborted();
|
|
16732
|
-
const entries = await opendir(dir).catch((error51) => {
|
|
16733
|
-
if (missing(error51))
|
|
16734
|
-
return null;
|
|
16735
|
-
throw error51;
|
|
16736
|
-
});
|
|
16737
|
-
if (!entries)
|
|
17534
|
+
emit(value) {
|
|
17535
|
+
if (this.#ended)
|
|
17536
|
+
return false;
|
|
17537
|
+
const resolve = this.#pending.shift();
|
|
17538
|
+
if (resolve)
|
|
17539
|
+
resolve({ done: false, value });
|
|
17540
|
+
else
|
|
17541
|
+
this.#values.push(value);
|
|
17542
|
+
return true;
|
|
17543
|
+
}
|
|
17544
|
+
end() {
|
|
17545
|
+
if (this.#ended)
|
|
16738
17546
|
return;
|
|
16739
|
-
|
|
16740
|
-
|
|
16741
|
-
|
|
16742
|
-
|
|
16743
|
-
|
|
16744
|
-
|
|
16745
|
-
|
|
16746
|
-
|
|
16747
|
-
|
|
16748
|
-
|
|
16749
|
-
|
|
16750
|
-
}
|
|
16751
|
-
|
|
16752
|
-
const before = await stat(file2);
|
|
16753
|
-
if (!before.isFile() || before.size === 0)
|
|
16754
|
-
return null;
|
|
16755
|
-
const stream = createReadStream2(file2, { encoding: "utf8", signal, end: before.size - 1 });
|
|
16756
|
-
const lines = createInterface2({ input: stream, crlfDelay: Infinity });
|
|
16757
|
-
let header;
|
|
16758
|
-
let name = null;
|
|
16759
|
-
let firstMessage = null;
|
|
16760
|
-
let hasUser = false;
|
|
16761
|
-
let updatedAt = before.mtimeMs;
|
|
16762
|
-
const entries = /* @__PURE__ */ new Map();
|
|
16763
|
-
try {
|
|
16764
|
-
for await (const line of lines) {
|
|
16765
|
-
signal.throwIfAborted();
|
|
16766
|
-
if (!line.trim())
|
|
16767
|
-
continue;
|
|
16768
|
-
let entry;
|
|
16769
|
-
try {
|
|
16770
|
-
entry = JSON.parse(line);
|
|
16771
|
-
} catch {
|
|
16772
|
-
return null;
|
|
16773
|
-
}
|
|
16774
|
-
if (!isRecord4(entry))
|
|
16775
|
-
return null;
|
|
16776
|
-
if (!header) {
|
|
16777
|
-
if (entry.type !== "session" || entry.version !== 3 || typeof entry.id !== "string" || typeof entry.cwd !== "string" || !path2.isAbsolute(entry.cwd))
|
|
16778
|
-
return null;
|
|
16779
|
-
header = entry;
|
|
16780
|
-
continue;
|
|
16781
|
-
}
|
|
16782
|
-
if (typeof entry.id !== "string" || entry.id.length === 0 || entries.has(entry.id) || entry.parentId !== null && (typeof entry.parentId !== "string" || !entries.has(entry.parentId)))
|
|
16783
|
-
return null;
|
|
16784
|
-
const message3 = isRecord4(entry.message) ? entry.message : null;
|
|
16785
|
-
if (!firstMessage && entry.type === "message" && message3?.role === "user") {
|
|
16786
|
-
const content = message3.content;
|
|
16787
|
-
const text = typeof content === "string" ? content : Array.isArray(content) ? content.filter((block) => isRecord4(block) && block.type === "text" && typeof block.text === "string").map((block) => block.text).join(" ") : "";
|
|
16788
|
-
firstMessage = text.replaceAll("\0", "").trim().slice(0, HARNESS_SESSION_IMPORT_TITLE_MAX_LENGTH) || null;
|
|
16789
|
-
}
|
|
16790
|
-
hasUser = entry.type === "message" && message3?.role === "user" || typeof entry.parentId === "string" && entries.get(entry.parentId) === true;
|
|
16791
|
-
entries.set(entry.id, hasUser);
|
|
16792
|
-
if (entry.type === "session_info")
|
|
16793
|
-
name = typeof entry.name === "string" ? entry.name.trim() || null : null;
|
|
16794
|
-
if (entry.type === "message" && (message3?.role === "user" || message3?.role === "assistant")) {
|
|
16795
|
-
const time3 = typeof message3.timestamp === "number" ? message3.timestamp : typeof entry.timestamp === "string" ? Date.parse(entry.timestamp) : NaN;
|
|
16796
|
-
if (Number.isFinite(time3))
|
|
16797
|
-
updatedAt = time3;
|
|
16798
|
-
}
|
|
16799
|
-
}
|
|
16800
|
-
} finally {
|
|
16801
|
-
lines.close();
|
|
16802
|
-
stream.destroy();
|
|
17547
|
+
this.#ended = true;
|
|
17548
|
+
if (this.#values.length !== 0)
|
|
17549
|
+
return;
|
|
17550
|
+
for (const resolve of this.#pending.splice(0))
|
|
17551
|
+
resolve({ done: true, value: void 0 });
|
|
17552
|
+
}
|
|
17553
|
+
#next() {
|
|
17554
|
+
const value = this.#values.shift();
|
|
17555
|
+
if (value !== void 0)
|
|
17556
|
+
return Promise.resolve({ done: false, value });
|
|
17557
|
+
if (this.#ended)
|
|
17558
|
+
return Promise.resolve({ done: true, value: void 0 });
|
|
17559
|
+
return new Promise((resolve) => this.#pending.push(resolve));
|
|
16803
17560
|
}
|
|
16804
|
-
|
|
16805
|
-
|
|
16806
|
-
|
|
16807
|
-
|
|
16808
|
-
|
|
16809
|
-
|
|
16810
|
-
|
|
16811
|
-
const
|
|
16812
|
-
|
|
16813
|
-
return null;
|
|
16814
|
-
const nativeRef = nativeSessionRefSchema.safeParse({
|
|
16815
|
-
harnessId: "pi",
|
|
16816
|
-
nativeSessionId: header.id,
|
|
16817
|
-
locator: { sessionFile: await realpath2(file2) },
|
|
16818
|
-
formatVersion: 1
|
|
16819
|
-
});
|
|
16820
|
-
const candidate = harnessSessionImportCandidateSchema.safeParse({
|
|
16821
|
-
nativeSessionId: header.id,
|
|
16822
|
-
cwd,
|
|
16823
|
-
title: name ?? firstMessage,
|
|
16824
|
-
updatedAt: Math.floor(updatedAt),
|
|
16825
|
-
running: null
|
|
16826
|
-
});
|
|
16827
|
-
return candidate.success && nativeRef.success ? { candidate: candidate.data, nativeRef: nativeRef.data } : null;
|
|
17561
|
+
};
|
|
17562
|
+
|
|
17563
|
+
// ../../harness-adapter/dist/diagnostics.js
|
|
17564
|
+
var DIAGNOSTIC_TAIL_MAX_LENGTH = 8e3;
|
|
17565
|
+
var SENSITIVE_VALUE_PATTERN = /(api[_-]?key|access[_-]?token|auth(?:orization)?|password|secret)(\s*[:=]\s*)([^\s,;]+)/giu;
|
|
17566
|
+
var BEARER_PATTERN = /\bBearer\s+[A-Za-z0-9._~+/=-]+/giu;
|
|
17567
|
+
function sanitizeDiagnosticTail(value) {
|
|
17568
|
+
const redacted = value.replace(BEARER_PATTERN, "Bearer [redacted]").replace(SENSITIVE_VALUE_PATTERN, "$1$2[redacted]");
|
|
17569
|
+
return redacted.length <= DIAGNOSTIC_TAIL_MAX_LENGTH ? redacted : redacted.slice(-DIAGNOSTIC_TAIL_MAX_LENGTH);
|
|
16828
17570
|
}
|
|
16829
|
-
|
|
16830
|
-
|
|
16831
|
-
|
|
16832
|
-
|
|
16833
|
-
|
|
16834
|
-
|
|
16835
|
-
|
|
16836
|
-
|
|
16837
|
-
|
|
16838
|
-
|
|
16839
|
-
|
|
16840
|
-
|
|
16841
|
-
|
|
16842
|
-
|
|
16843
|
-
|
|
17571
|
+
|
|
17572
|
+
// ../../harness-adapter/dist/usage.js
|
|
17573
|
+
var tokenFields = [
|
|
17574
|
+
"inputTokens",
|
|
17575
|
+
"cachedInputTokens",
|
|
17576
|
+
"cacheWriteInputTokens",
|
|
17577
|
+
"outputTokens",
|
|
17578
|
+
"outputTokensPerSecond",
|
|
17579
|
+
"reasoningOutputTokens",
|
|
17580
|
+
"totalTokens",
|
|
17581
|
+
"contextWindowTokens",
|
|
17582
|
+
"contextUsedTokens"
|
|
17583
|
+
];
|
|
17584
|
+
var safeIntegerFields = [
|
|
17585
|
+
"planFiveHourResetsAtUnix",
|
|
17586
|
+
"planSevenDayResetsAtUnix"
|
|
17587
|
+
];
|
|
17588
|
+
var percentFields = [
|
|
17589
|
+
"cacheHitRatePercent",
|
|
17590
|
+
"planFiveHourUsedPercent",
|
|
17591
|
+
"planSevenDayUsedPercent"
|
|
17592
|
+
];
|
|
17593
|
+
var usageFields = /* @__PURE__ */ new Set([
|
|
17594
|
+
...tokenFields,
|
|
17595
|
+
...safeIntegerFields,
|
|
17596
|
+
...percentFields,
|
|
17597
|
+
"totalCostUsd",
|
|
17598
|
+
"totalCredits",
|
|
17599
|
+
"contextUsagePercent"
|
|
17600
|
+
]);
|
|
17601
|
+
function isRecord3(value) {
|
|
17602
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17603
|
+
}
|
|
17604
|
+
function parseHostUsage(value) {
|
|
17605
|
+
if (!isRecord3(value))
|
|
17606
|
+
throw new Error("Harness Usage must be an object");
|
|
17607
|
+
const keys = Object.keys(value);
|
|
17608
|
+
if (keys.length === 0)
|
|
17609
|
+
throw new Error("Harness Usage must contain a reliable field");
|
|
17610
|
+
for (const key of keys) {
|
|
17611
|
+
if (!usageFields.has(key)) {
|
|
17612
|
+
throw new Error(`Harness Usage contains unknown field '${key}'`);
|
|
16844
17613
|
}
|
|
16845
|
-
return null;
|
|
16846
|
-
} finally {
|
|
16847
|
-
lines.close();
|
|
16848
|
-
stream.destroy();
|
|
16849
17614
|
}
|
|
16850
|
-
|
|
16851
|
-
|
|
16852
|
-
|
|
16853
|
-
|
|
16854
|
-
|
|
16855
|
-
constructor(environment) {
|
|
16856
|
-
this.#location = piSessionImportDirectory(environment);
|
|
17615
|
+
for (const field of ["totalCredits", "contextUsagePercent"]) {
|
|
17616
|
+
const candidate = value[field];
|
|
17617
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0)) {
|
|
17618
|
+
throw new Error(`Harness Usage '${field}' must be a finite non-negative number`);
|
|
17619
|
+
}
|
|
16857
17620
|
}
|
|
16858
|
-
|
|
16859
|
-
|
|
16860
|
-
|
|
16861
|
-
|
|
16862
|
-
|
|
17621
|
+
for (const field of tokenFields) {
|
|
17622
|
+
const candidate = value[field];
|
|
17623
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0)) {
|
|
17624
|
+
throw new Error(`Harness Usage '${field}' must be a non-negative safe integer`);
|
|
17625
|
+
}
|
|
16863
17626
|
}
|
|
16864
|
-
|
|
16865
|
-
const
|
|
16866
|
-
|
|
16867
|
-
|
|
16868
|
-
const identities = /* @__PURE__ */ new Set();
|
|
16869
|
-
const sources = [];
|
|
16870
|
-
for (const file2 of files) {
|
|
16871
|
-
signal.throwIfAborted();
|
|
16872
|
-
try {
|
|
16873
|
-
const fingerprint = await stat(file2);
|
|
16874
|
-
const cached2 = this.#cache.get(file2);
|
|
16875
|
-
const source = cached2 && sameFile(cached2.fingerprint, fingerprint) ? cached2.source : await readCandidate(file2, signal);
|
|
16876
|
-
if (!source)
|
|
16877
|
-
continue;
|
|
16878
|
-
if (!(await stat(source.candidate.cwd)).isDirectory())
|
|
16879
|
-
continue;
|
|
16880
|
-
if (identities.has(source.nativeRef.nativeSessionId))
|
|
16881
|
-
throw new Error("Pi Session identity is ambiguous across files");
|
|
16882
|
-
identities.add(source.nativeRef.nativeSessionId);
|
|
16883
|
-
next.set(file2, { fingerprint, source });
|
|
16884
|
-
sources.push(source);
|
|
16885
|
-
} catch (error51) {
|
|
16886
|
-
if (!missing(error51) && !(error51 instanceof PiSessionChangedError))
|
|
16887
|
-
throw error51;
|
|
16888
|
-
}
|
|
17627
|
+
for (const field of safeIntegerFields) {
|
|
17628
|
+
const candidate = value[field];
|
|
17629
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0)) {
|
|
17630
|
+
throw new Error(`Harness Usage '${field}' must be a non-negative safe integer`);
|
|
16889
17631
|
}
|
|
16890
|
-
this.#cache = next;
|
|
16891
|
-
return structuredClone(sources.sort((left, right) => right.candidate.updatedAt - left.candidate.updatedAt));
|
|
16892
17632
|
}
|
|
16893
|
-
|
|
16894
|
-
|
|
16895
|
-
|
|
16896
|
-
|
|
16897
|
-
|
|
16898
|
-
|
|
16899
|
-
|
|
16900
|
-
|
|
16901
|
-
|
|
16902
|
-
|
|
16903
|
-
continue;
|
|
16904
|
-
if (selected)
|
|
16905
|
-
throw new Error("Pi Session identity is ambiguous across files");
|
|
16906
|
-
selected = file2;
|
|
16907
|
-
} catch (error51) {
|
|
16908
|
-
if (!missing(error51))
|
|
16909
|
-
throw error51;
|
|
16910
|
-
}
|
|
17633
|
+
if (value.outputTokensPerSecond !== void 0 && (typeof value.outputTokensPerSecond !== "number" || !Number.isFinite(value.outputTokensPerSecond) || value.outputTokensPerSecond < 0)) {
|
|
17634
|
+
throw new Error("Harness Usage 'outputTokensPerSecond' must be a finite non-negative number");
|
|
17635
|
+
}
|
|
17636
|
+
if (value.totalCostUsd !== void 0 && (typeof value.totalCostUsd !== "number" || !Number.isFinite(value.totalCostUsd) || value.totalCostUsd < 0)) {
|
|
17637
|
+
throw new Error("Harness Usage 'totalCostUsd' must be a finite non-negative number");
|
|
17638
|
+
}
|
|
17639
|
+
for (const field of ["totalCredits", "contextUsagePercent"]) {
|
|
17640
|
+
const candidate = value[field];
|
|
17641
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0)) {
|
|
17642
|
+
throw new Error(`Harness Usage '${field}' must be a finite non-negative number`);
|
|
16911
17643
|
}
|
|
16912
|
-
|
|
16913
|
-
|
|
16914
|
-
|
|
16915
|
-
|
|
16916
|
-
|
|
16917
|
-
} catch (error51) {
|
|
16918
|
-
if (missing(error51))
|
|
16919
|
-
return null;
|
|
16920
|
-
throw error51;
|
|
17644
|
+
}
|
|
17645
|
+
for (const field of percentFields) {
|
|
17646
|
+
const candidate = value[field];
|
|
17647
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0 || candidate > 100)) {
|
|
17648
|
+
throw new Error(`Harness Usage '${field}' must be between 0 and 100`);
|
|
16921
17649
|
}
|
|
16922
17650
|
}
|
|
16923
|
-
|
|
17651
|
+
const hasContextUsed = value.contextUsedTokens !== void 0;
|
|
17652
|
+
const hasContextWindow = value.contextWindowTokens !== void 0;
|
|
17653
|
+
if (hasContextUsed !== hasContextWindow) {
|
|
17654
|
+
throw new Error("Harness Usage context fields must be provided together");
|
|
17655
|
+
}
|
|
17656
|
+
if (hasContextWindow && value.contextWindowTokens === 0) {
|
|
17657
|
+
throw new Error("Harness Usage 'contextWindowTokens' must be greater than zero");
|
|
17658
|
+
}
|
|
17659
|
+
if (value.planFiveHourResetsAtUnix !== void 0 && value.planFiveHourUsedPercent === void 0) {
|
|
17660
|
+
throw new Error("Harness Usage 'planFiveHourResetsAtUnix' must be provided with 'planFiveHourUsedPercent'");
|
|
17661
|
+
}
|
|
17662
|
+
if (value.planSevenDayResetsAtUnix !== void 0 && value.planSevenDayUsedPercent === void 0) {
|
|
17663
|
+
throw new Error("Harness Usage 'planSevenDayResetsAtUnix' must be provided with 'planSevenDayUsedPercent'");
|
|
17664
|
+
}
|
|
17665
|
+
return { ...value };
|
|
17666
|
+
}
|
|
16924
17667
|
|
|
16925
|
-
// dist/pi-
|
|
16926
|
-
import {
|
|
16927
|
-
import {
|
|
17668
|
+
// dist/pi-workflow-child-history.js
|
|
17669
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
17670
|
+
import { constants } from "node:fs";
|
|
17671
|
+
import { open as open3 } from "node:fs/promises";
|
|
16928
17672
|
import path5 from "node:path";
|
|
16929
|
-
|
|
16930
|
-
|
|
16931
|
-
import fs from "node:fs";
|
|
16932
|
-
import path3 from "node:path";
|
|
16933
|
-
function targetPath(platform) {
|
|
16934
|
-
return platform === "win32" ? path3.win32 : path3.posix;
|
|
17673
|
+
function record4(value) {
|
|
17674
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16935
17675
|
}
|
|
16936
|
-
|
|
16937
|
-
|
|
16938
|
-
|
|
16939
|
-
|
|
16940
|
-
|
|
17676
|
+
var MAX_SESSION_BYTES = 8 * 1024 * 1024;
|
|
17677
|
+
async function childHistory(file2, parentSessionId, identity) {
|
|
17678
|
+
if (!path5.isAbsolute(file2))
|
|
17679
|
+
throw new Error("Pi child Session path is not absolute");
|
|
17680
|
+
const handle = await open3(file2, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0));
|
|
17681
|
+
try {
|
|
17682
|
+
const stat2 = await handle.stat();
|
|
17683
|
+
if (!stat2.isFile() || stat2.size > MAX_SESSION_BYTES)
|
|
17684
|
+
throw new Error("Pi child Session exceeds read bounds");
|
|
17685
|
+
const buffer = Buffer.alloc(MAX_SESSION_BYTES + 1);
|
|
17686
|
+
const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);
|
|
17687
|
+
if (bytesRead > MAX_SESSION_BYTES)
|
|
17688
|
+
throw new Error("Pi child Session exceeds read bounds");
|
|
17689
|
+
const values = buffer.subarray(0, bytesRead).toString("utf8").split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
|
|
17690
|
+
const header = values[0];
|
|
17691
|
+
if (!record4(header) || header.type !== "session" || typeof header.id !== "string" || header.version !== 3)
|
|
17692
|
+
throw new Error("Unsupported Pi child Session header");
|
|
17693
|
+
const entries = [];
|
|
17694
|
+
for (const entry of values.slice(1)) {
|
|
17695
|
+
const parsed = jsonValueSchema.safeParse(entry);
|
|
17696
|
+
if (!parsed.success || !record4(parsed.data) || typeof parsed.data.id !== "string")
|
|
17697
|
+
throw new Error("Malformed Pi child Session entry");
|
|
17698
|
+
entries.push(parsed.data);
|
|
17699
|
+
}
|
|
17700
|
+
const history = { entries, leafId: String(entries.at(-1)?.id ?? "") || null };
|
|
17701
|
+
const snapshot = mapPiSnapshot(history, { sessionId: parentSessionId, model: null });
|
|
17702
|
+
const prefix = createHash2("sha256").update(identity).digest("hex");
|
|
17703
|
+
return {
|
|
17704
|
+
turns: snapshot.turns.map((turn) => {
|
|
17705
|
+
const readonlyTurn = {
|
|
17706
|
+
...turn,
|
|
17707
|
+
nativeTurnRef: {
|
|
17708
|
+
...turn.nativeTurnRef,
|
|
17709
|
+
nativeTurnKey: `${prefix}:${turn.nativeTurnRef.nativeTurnKey}`
|
|
17710
|
+
}
|
|
17711
|
+
};
|
|
17712
|
+
delete readonlyTurn.checkpoint;
|
|
17713
|
+
return readonlyTurn;
|
|
17714
|
+
})
|
|
17715
|
+
};
|
|
17716
|
+
} finally {
|
|
17717
|
+
await handle.close();
|
|
16941
17718
|
}
|
|
16942
|
-
return void 0;
|
|
16943
17719
|
}
|
|
16944
|
-
function
|
|
16945
|
-
|
|
17720
|
+
async function readPiWorkflowChild(history, parentSessionId, address) {
|
|
17721
|
+
for (const entry of activePiEntries(history).reverse()) {
|
|
17722
|
+
const message3 = entry.message;
|
|
17723
|
+
if (!record4(message3) || message3.role !== "toolResult" || message3.toolName !== "subagent")
|
|
17724
|
+
continue;
|
|
17725
|
+
const summary = piWorkflowSummary(message3);
|
|
17726
|
+
if (!summary || summary.workflowRunId !== address.workflowRunId || summary.parentToolCallId !== message3.toolCallId)
|
|
17727
|
+
continue;
|
|
17728
|
+
const child = summary.children.find((candidate) => candidate.childId === address.childId);
|
|
17729
|
+
if (!child)
|
|
17730
|
+
break;
|
|
17731
|
+
const details = message3.details;
|
|
17732
|
+
if (!record4(details) || !Array.isArray(details.results))
|
|
17733
|
+
break;
|
|
17734
|
+
const result = details.results.findLast((candidate) => record4(candidate) && candidate.workflowKey === address.childId);
|
|
17735
|
+
if (!record4(result))
|
|
17736
|
+
break;
|
|
17737
|
+
const id = piWorkflowSubagentId(address);
|
|
17738
|
+
if (typeof result.sessionFile === "string") {
|
|
17739
|
+
try {
|
|
17740
|
+
const snapshot = await childHistory(result.sessionFile, parentSessionId, id);
|
|
17741
|
+
if (snapshot.turns.length)
|
|
17742
|
+
return { ok: true, value: snapshot };
|
|
17743
|
+
} catch {
|
|
17744
|
+
}
|
|
17745
|
+
}
|
|
17746
|
+
if (typeof result.finalOutput === "string" && result.finalOutput.length > 0) {
|
|
17747
|
+
const output = result.finalOutput.slice(0, 64 * 1024);
|
|
17748
|
+
return {
|
|
17749
|
+
ok: true,
|
|
17750
|
+
value: piSubagentSnapshot(parentSessionId, id, {
|
|
17751
|
+
kind: "pi-subagents.inspect-reply",
|
|
17752
|
+
version: 1,
|
|
17753
|
+
requestId: "native-workflow-result",
|
|
17754
|
+
status: child.state === "completed" ? "complete" : child.state === "failed" ? "failed" : child.state === "interrupted" ? "paused" : "running",
|
|
17755
|
+
...typeof result.task === "string" ? { task: result.task.slice(0, 4096) } : {},
|
|
17756
|
+
finalOutput: `[Pi subagent: saved native result; Session transcript unavailable.]
|
|
17757
|
+
${output}`,
|
|
17758
|
+
truncated: {
|
|
17759
|
+
task: typeof result.task === "string" && result.task.length > 4096,
|
|
17760
|
+
messages: 0,
|
|
17761
|
+
finalOutput: output.length < result.finalOutput.length
|
|
17762
|
+
}
|
|
17763
|
+
})
|
|
17764
|
+
};
|
|
17765
|
+
}
|
|
17766
|
+
break;
|
|
17767
|
+
}
|
|
17768
|
+
return {
|
|
17769
|
+
ok: false,
|
|
17770
|
+
error: {
|
|
17771
|
+
code: "sessionNotFound",
|
|
17772
|
+
message: "Pi workflow child has no published transcript/result in this parent's active history",
|
|
17773
|
+
retryable: true
|
|
17774
|
+
}
|
|
17775
|
+
};
|
|
16946
17776
|
}
|
|
16947
|
-
|
|
16948
|
-
|
|
17777
|
+
|
|
17778
|
+
// dist/pi-subagent-history.js
|
|
17779
|
+
import { constants as constants2 } from "node:fs";
|
|
17780
|
+
import { open as open4 } from "node:fs/promises";
|
|
17781
|
+
import path6 from "node:path";
|
|
17782
|
+
function record5(value) {
|
|
17783
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16949
17784
|
}
|
|
16950
|
-
function
|
|
16951
|
-
|
|
16952
|
-
return [""];
|
|
16953
|
-
if (targetPath(platform).extname(command) !== "")
|
|
16954
|
-
return [""];
|
|
16955
|
-
return (environmentValue(environment, "PATHEXT") ?? ".COM;.EXE;.BAT;.CMD").split(";").map((extension) => extension.trim()).filter(Boolean);
|
|
17785
|
+
function state(value) {
|
|
17786
|
+
return value === "pending" ? "queued" : value === "completed" ? "complete" : value;
|
|
16956
17787
|
}
|
|
16957
|
-
function
|
|
16958
|
-
|
|
16959
|
-
|
|
16960
|
-
|
|
16961
|
-
|
|
16962
|
-
|
|
17788
|
+
function piSubagentArtifact(value, runId, parentSessionId) {
|
|
17789
|
+
if (!record5(value) || value.lifecycleArtifactVersion !== 3 || value.runId !== runId || value.sessionId !== parentSessionId || !["single", "parallel", "chain", "workflow"].includes(String(value.mode)))
|
|
17790
|
+
return null;
|
|
17791
|
+
if (value.steps !== void 0 && (!Array.isArray(value.steps) || value.steps.length > 128))
|
|
17792
|
+
return null;
|
|
17793
|
+
const steps = Array.isArray(value.steps) ? value.steps : [];
|
|
17794
|
+
const children = [];
|
|
17795
|
+
for (const [index, step] of steps.entries()) {
|
|
17796
|
+
if (!record5(step) || typeof step.agent !== "string")
|
|
17797
|
+
return null;
|
|
17798
|
+
children.push({
|
|
17799
|
+
id: step.workflowKey ?? step.runId ?? `step:${index}`,
|
|
17800
|
+
kind: "step",
|
|
17801
|
+
label: step.label ?? step.agent,
|
|
17802
|
+
state: state(step.status)
|
|
17803
|
+
});
|
|
16963
17804
|
}
|
|
17805
|
+
return parsePiSubagentStatus({
|
|
17806
|
+
type: "extension_ui_request",
|
|
17807
|
+
method: "setWidget",
|
|
17808
|
+
widgetKey: "subagent-async",
|
|
17809
|
+
widgetLines: [
|
|
17810
|
+
"PI_SUBAGENT_ASYNC_JSON:" + JSON.stringify({
|
|
17811
|
+
kind: "pi-subagents.async-status-snapshot",
|
|
17812
|
+
version: 1,
|
|
17813
|
+
runs: [
|
|
17814
|
+
{
|
|
17815
|
+
id: runId,
|
|
17816
|
+
kind: value.mode === "single" ? "subagent" : "workflow",
|
|
17817
|
+
label: "Pi subagent",
|
|
17818
|
+
state: value.state,
|
|
17819
|
+
children
|
|
17820
|
+
}
|
|
17821
|
+
]
|
|
17822
|
+
})
|
|
17823
|
+
]
|
|
17824
|
+
});
|
|
16964
17825
|
}
|
|
16965
|
-
function
|
|
16966
|
-
|
|
16967
|
-
|
|
16968
|
-
|
|
16969
|
-
|
|
17826
|
+
async function restorePiSubagents(history, parentSessionId, observer) {
|
|
17827
|
+
const receipts = /* @__PURE__ */ new Map();
|
|
17828
|
+
for (const entry of activePiEntries(history)) {
|
|
17829
|
+
if (!record5(entry.message) || entry.message.role !== "toolResult" || entry.message.toolName !== "subagent" || entry.message.isError !== false || !record5(entry.message.details))
|
|
17830
|
+
continue;
|
|
17831
|
+
const details = entry.message.details;
|
|
17832
|
+
if (!["single", "parallel", "chain", "workflow"].includes(String(details.mode)) || typeof details.asyncId !== "string" || typeof details.asyncDir !== "string" || !path6.isAbsolute(details.asyncDir) || path6.basename(details.asyncDir) !== details.asyncId)
|
|
17833
|
+
continue;
|
|
17834
|
+
receipts.set(details.asyncId, details.asyncDir);
|
|
17835
|
+
}
|
|
17836
|
+
for (const [id, directory] of [...receipts].slice(-128)) {
|
|
17837
|
+
let file2;
|
|
17838
|
+
try {
|
|
17839
|
+
file2 = await open4(path6.join(directory, "status.json"), constants2.O_RDONLY | (constants2.O_NOFOLLOW ?? 0));
|
|
17840
|
+
const stat2 = await file2.stat();
|
|
17841
|
+
if (!stat2.isFile() || stat2.size > 1024 * 1024)
|
|
17842
|
+
continue;
|
|
17843
|
+
const buffer = Buffer.alloc(1024 * 1024 + 1);
|
|
17844
|
+
const { bytesRead } = await file2.read(buffer, 0, buffer.length, 0);
|
|
17845
|
+
if (bytesRead > 1024 * 1024)
|
|
17846
|
+
continue;
|
|
17847
|
+
const value = JSON.parse(buffer.subarray(0, bytesRead).toString("utf8"));
|
|
17848
|
+
const runs = piSubagentArtifact(value, id, parentSessionId);
|
|
17849
|
+
if (runs)
|
|
17850
|
+
observer.restore(runs);
|
|
17851
|
+
} catch {
|
|
17852
|
+
} finally {
|
|
17853
|
+
await file2?.close();
|
|
17854
|
+
}
|
|
16970
17855
|
}
|
|
16971
|
-
}
|
|
16972
|
-
function newestFirst(names) {
|
|
16973
|
-
return [...names].sort((left, right) => right.localeCompare(left, void 0, { numeric: true }));
|
|
16974
17856
|
}
|
|
16975
17857
|
|
|
16976
|
-
//
|
|
16977
|
-
|
|
16978
|
-
|
|
16979
|
-
|
|
16980
|
-
|
|
16981
|
-
|
|
16982
|
-
const directories = (environment[pathKey] ?? "").split(delimiter).filter(Boolean);
|
|
16983
|
-
const equal = platform === "win32" ? (value) => value.toLowerCase() : (value) => value;
|
|
16984
|
-
if (!directories.some((directory) => equal(directory) === equal(runtimeDirectory))) {
|
|
16985
|
-
directories.unshift(runtimeDirectory);
|
|
17858
|
+
// dist/pi-last-turn-rollback.js
|
|
17859
|
+
function modelFromState(state2) {
|
|
17860
|
+
if (state2.provider === null && state2.modelId === null)
|
|
17861
|
+
return null;
|
|
17862
|
+
if (state2.provider === null || state2.modelId === null) {
|
|
17863
|
+
throw new Error("Pi state contains a partial Model identity");
|
|
16986
17864
|
}
|
|
16987
|
-
return {
|
|
17865
|
+
return { provider: state2.provider, id: state2.modelId };
|
|
16988
17866
|
}
|
|
16989
|
-
|
|
16990
|
-
|
|
16991
|
-
|
|
16992
|
-
|
|
16993
|
-
|
|
16994
|
-
|
|
16995
|
-
const
|
|
16996
|
-
|
|
16997
|
-
|
|
16998
|
-
const
|
|
16999
|
-
|
|
17000
|
-
|
|
17001
|
-
|
|
17002
|
-
|
|
17003
|
-
|
|
17004
|
-
|
|
17005
|
-
if (platform === "win32") {
|
|
17006
|
-
const appData = value("APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming");
|
|
17007
|
-
const localAppData = value("LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local");
|
|
17008
|
-
versioned(pathFlavor.join(appData, "nvm"));
|
|
17009
|
-
versioned(value("FNM_DIR") ?? pathFlavor.join(appData, "fnm", "node-versions"), "installation");
|
|
17010
|
-
directories.push(pathFlavor.join(localAppData, "Volta", "bin"));
|
|
17011
|
-
directories.push(pathFlavor.join(home, ".bun", "bin"));
|
|
17012
|
-
const pnpmHome2 = value("PNPM_HOME");
|
|
17013
|
-
if (pnpmHome2)
|
|
17014
|
-
directories.push(pnpmHome2);
|
|
17015
|
-
directories.push(pathFlavor.join(localAppData, "pnpm"));
|
|
17016
|
-
return directories;
|
|
17867
|
+
async function rollbackPiLastTurn(transport, sourceSessionId, cwd) {
|
|
17868
|
+
const startupState = transport.state;
|
|
17869
|
+
const startupSessionId = startupState.sessionId;
|
|
17870
|
+
const currentModel = modelFromState(startupState);
|
|
17871
|
+
const currentThinking = startupState.thinkingLevel;
|
|
17872
|
+
const copiedHistory = await transport.getEntries();
|
|
17873
|
+
const boundary = resolvePiLastTurnBoundary(copiedHistory);
|
|
17874
|
+
if (!boundary)
|
|
17875
|
+
return { ok: false, reason: "empty" };
|
|
17876
|
+
const sourceSnapshot = mapPiSnapshot(copiedHistory, {
|
|
17877
|
+
sessionId: startupSessionId,
|
|
17878
|
+
model: currentModel
|
|
17879
|
+
});
|
|
17880
|
+
let state2 = await transport.fork(boundary.lastUserEntryId);
|
|
17881
|
+
if (state2.sessionId === sourceSessionId || state2.sessionId === startupSessionId) {
|
|
17882
|
+
throw new Error("Pi last-Turn rollback did not create a distinct Native Session");
|
|
17017
17883
|
}
|
|
17018
|
-
|
|
17019
|
-
|
|
17020
|
-
|
|
17021
|
-
|
|
17022
|
-
pathFlavor.join(home, "Library", "Application Support", "fnm")
|
|
17023
|
-
].filter((root) => root !== void 0);
|
|
17024
|
-
for (const root of fnmRoots) {
|
|
17025
|
-
versioned(pathFlavor.join(root, "node-versions"), "installation", "bin");
|
|
17884
|
+
if (!samePiModel(modelFromState(state2), currentModel)) {
|
|
17885
|
+
if (!currentModel)
|
|
17886
|
+
throw new Error("Pi last-Turn rollback changed the current Model");
|
|
17887
|
+
state2 = await transport.selectModel(currentModel);
|
|
17026
17888
|
}
|
|
17027
|
-
|
|
17028
|
-
|
|
17029
|
-
|
|
17030
|
-
|
|
17031
|
-
|
|
17032
|
-
|
|
17033
|
-
|
|
17034
|
-
|
|
17035
|
-
|
|
17036
|
-
|
|
17037
|
-
|
|
17038
|
-
|
|
17039
|
-
|
|
17040
|
-
|
|
17041
|
-
|
|
17042
|
-
|
|
17043
|
-
|
|
17044
|
-
|
|
17045
|
-
|
|
17889
|
+
if (state2.thinkingLevel !== currentThinking) {
|
|
17890
|
+
if (!currentThinking)
|
|
17891
|
+
throw new Error("Pi last-Turn rollback changed current Thinking");
|
|
17892
|
+
state2 = await transport.selectThinkingOption(currentThinking);
|
|
17893
|
+
}
|
|
17894
|
+
if (!samePiModel(modelFromState(state2), currentModel) || state2.thinkingLevel !== currentThinking) {
|
|
17895
|
+
throw new Error("Pi last-Turn rollback could not restore current Model and Thinking");
|
|
17896
|
+
}
|
|
17897
|
+
const snapshot = mapPiSnapshot(await transport.getEntries(), {
|
|
17898
|
+
sessionId: state2.sessionId,
|
|
17899
|
+
model: modelFromState(state2)
|
|
17900
|
+
});
|
|
17901
|
+
const expectedTurnKeys = sourceSnapshot.turns.slice(0, -1).map((turn) => turn.nativeTurnRef.nativeTurnKey);
|
|
17902
|
+
const actualTurnKeys = snapshot.turns.map((turn) => turn.nativeTurnRef.nativeTurnKey);
|
|
17903
|
+
if (snapshot.turns.length !== boundary.sourceTurnCount - 1 || actualTurnKeys.some((key, index) => key !== expectedTurnKeys[index])) {
|
|
17904
|
+
throw new Error("Pi last-Turn rollback did not produce the exact retained history prefix");
|
|
17905
|
+
}
|
|
17906
|
+
try {
|
|
17907
|
+
await transport.verifySessionCwd(cwd);
|
|
17908
|
+
return { ok: true, unpersisted: false };
|
|
17909
|
+
} catch (error51) {
|
|
17910
|
+
if (snapshot.turns.length === 0 && error51?.code === "ENOENT") {
|
|
17911
|
+
return { ok: true, unpersisted: true };
|
|
17046
17912
|
}
|
|
17913
|
+
throw error51;
|
|
17047
17914
|
}
|
|
17048
|
-
return directories;
|
|
17049
17915
|
}
|
|
17050
17916
|
|
|
17051
|
-
//
|
|
17052
|
-
|
|
17053
|
-
|
|
17054
|
-
|
|
17917
|
+
// dist/pi-session-import.js
|
|
17918
|
+
import { createReadStream as createReadStream2 } from "node:fs";
|
|
17919
|
+
import { opendir, realpath as realpath3, stat } from "node:fs/promises";
|
|
17920
|
+
import os3 from "node:os";
|
|
17921
|
+
import path7 from "node:path";
|
|
17922
|
+
import { createInterface as createInterface2 } from "node:readline";
|
|
17923
|
+
var PiSessionChangedError = class extends Error {
|
|
17924
|
+
constructor() {
|
|
17925
|
+
super("Pi Session changed during discovery; refresh and retry");
|
|
17926
|
+
}
|
|
17927
|
+
};
|
|
17928
|
+
function sameFile(left, right) {
|
|
17929
|
+
return left.size === right.size && left.mtimeMs === right.mtimeMs && left.ctimeMs === right.ctimeMs && left.ino === right.ino && left.dev === right.dev;
|
|
17055
17930
|
}
|
|
17056
|
-
function
|
|
17057
|
-
return
|
|
17931
|
+
function isRecord4(value) {
|
|
17932
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17058
17933
|
}
|
|
17059
|
-
function
|
|
17060
|
-
|
|
17934
|
+
function missing(error51) {
|
|
17935
|
+
return isRecord4(error51) && error51.code === "ENOENT";
|
|
17936
|
+
}
|
|
17937
|
+
function expandDirectory(value, home) {
|
|
17938
|
+
return path7.resolve(value === "~" ? home : value.startsWith(`~${path7.sep}`) || value.startsWith("~/") ? path7.join(home, value.slice(2)) : value);
|
|
17939
|
+
}
|
|
17940
|
+
function piSessionImportDirectory(environment) {
|
|
17941
|
+
const home = (process.platform === "win32" ? environment.USERPROFILE : environment.HOME) || os3.homedir();
|
|
17942
|
+
const custom2 = environment.PI_CODING_AGENT_SESSION_DIR;
|
|
17943
|
+
if (custom2)
|
|
17944
|
+
return { directory: expandDirectory(custom2, home), flat: true };
|
|
17945
|
+
const agent = environment.PI_CODING_AGENT_DIR;
|
|
17061
17946
|
return {
|
|
17062
|
-
|
|
17063
|
-
|
|
17064
|
-
APPDATA: environmentValue(environment, "APPDATA") ?? pathFlavor.join(home, "AppData", "Roaming"),
|
|
17065
|
-
LOCALAPPDATA: environmentValue(environment, "LOCALAPPDATA") ?? pathFlavor.join(home, "AppData", "Local")
|
|
17947
|
+
directory: path7.join(agent ? expandDirectory(agent, home) : path7.join(home, ".pi", "agent"), "sessions"),
|
|
17948
|
+
flat: false
|
|
17066
17949
|
};
|
|
17067
17950
|
}
|
|
17068
|
-
function
|
|
17069
|
-
const
|
|
17070
|
-
const
|
|
17071
|
-
|
|
17072
|
-
|
|
17073
|
-
|
|
17074
|
-
|
|
17075
|
-
|
|
17951
|
+
async function sessionFiles(directory, flat, signal) {
|
|
17952
|
+
const files = [];
|
|
17953
|
+
const visit = async (dir, projectLevel) => {
|
|
17954
|
+
signal.throwIfAborted();
|
|
17955
|
+
const entries = await opendir(dir).catch((error51) => {
|
|
17956
|
+
if (missing(error51))
|
|
17957
|
+
return null;
|
|
17958
|
+
throw error51;
|
|
17959
|
+
});
|
|
17960
|
+
if (!entries)
|
|
17961
|
+
return;
|
|
17962
|
+
for await (const entry of entries) {
|
|
17963
|
+
signal.throwIfAborted();
|
|
17964
|
+
if (projectLevel && entry.isDirectory())
|
|
17965
|
+
await visit(path7.join(dir, entry.name), false);
|
|
17966
|
+
else if (!projectLevel && entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
17967
|
+
files.push(path7.join(dir, entry.name));
|
|
17968
|
+
}
|
|
17969
|
+
}
|
|
17970
|
+
};
|
|
17971
|
+
await visit(directory, !flat);
|
|
17972
|
+
return files;
|
|
17076
17973
|
}
|
|
17077
|
-
function
|
|
17078
|
-
const
|
|
17079
|
-
|
|
17080
|
-
|
|
17081
|
-
|
|
17082
|
-
|
|
17083
|
-
|
|
17084
|
-
|
|
17974
|
+
async function readCandidate(file2, signal) {
|
|
17975
|
+
const before = await stat(file2);
|
|
17976
|
+
if (!before.isFile() || before.size === 0)
|
|
17977
|
+
return null;
|
|
17978
|
+
const stream = createReadStream2(file2, { encoding: "utf8", signal, end: before.size - 1 });
|
|
17979
|
+
const lines = createInterface2({ input: stream, crlfDelay: Infinity });
|
|
17980
|
+
let header;
|
|
17981
|
+
let name = null;
|
|
17982
|
+
let firstMessage = null;
|
|
17983
|
+
let hasUser = false;
|
|
17984
|
+
let updatedAt = before.mtimeMs;
|
|
17985
|
+
const entries = /* @__PURE__ */ new Map();
|
|
17986
|
+
try {
|
|
17987
|
+
for await (const line of lines) {
|
|
17988
|
+
signal.throwIfAborted();
|
|
17989
|
+
if (!line.trim())
|
|
17990
|
+
continue;
|
|
17991
|
+
let entry;
|
|
17992
|
+
try {
|
|
17993
|
+
entry = JSON.parse(line);
|
|
17994
|
+
} catch {
|
|
17995
|
+
return null;
|
|
17996
|
+
}
|
|
17997
|
+
if (!isRecord4(entry))
|
|
17998
|
+
return null;
|
|
17999
|
+
if (!header) {
|
|
18000
|
+
if (entry.type !== "session" || entry.version !== 3 || typeof entry.id !== "string" || typeof entry.cwd !== "string" || !path7.isAbsolute(entry.cwd))
|
|
18001
|
+
return null;
|
|
18002
|
+
header = entry;
|
|
18003
|
+
continue;
|
|
18004
|
+
}
|
|
18005
|
+
if (typeof entry.id !== "string" || entry.id.length === 0 || entries.has(entry.id) || entry.parentId !== null && (typeof entry.parentId !== "string" || !entries.has(entry.parentId)))
|
|
18006
|
+
return null;
|
|
18007
|
+
const message3 = isRecord4(entry.message) ? entry.message : null;
|
|
18008
|
+
if (!firstMessage && entry.type === "message" && message3?.role === "user") {
|
|
18009
|
+
const content = message3.content;
|
|
18010
|
+
const text2 = typeof content === "string" ? content : Array.isArray(content) ? content.filter((block) => isRecord4(block) && block.type === "text" && typeof block.text === "string").map((block) => block.text).join(" ") : "";
|
|
18011
|
+
firstMessage = text2.replaceAll("\0", "").trim().slice(0, HARNESS_SESSION_IMPORT_TITLE_MAX_LENGTH) || null;
|
|
18012
|
+
}
|
|
18013
|
+
hasUser = entry.type === "message" && message3?.role === "user" || typeof entry.parentId === "string" && entries.get(entry.parentId) === true;
|
|
18014
|
+
entries.set(entry.id, hasUser);
|
|
18015
|
+
if (entry.type === "session_info")
|
|
18016
|
+
name = typeof entry.name === "string" ? entry.name.trim() || null : null;
|
|
18017
|
+
if (entry.type === "message" && (message3?.role === "user" || message3?.role === "assistant")) {
|
|
18018
|
+
const time3 = typeof message3.timestamp === "number" ? message3.timestamp : typeof entry.timestamp === "string" ? Date.parse(entry.timestamp) : NaN;
|
|
18019
|
+
if (Number.isFinite(time3))
|
|
18020
|
+
updatedAt = time3;
|
|
18021
|
+
}
|
|
17085
18022
|
}
|
|
17086
|
-
|
|
18023
|
+
} finally {
|
|
18024
|
+
lines.close();
|
|
18025
|
+
stream.destroy();
|
|
18026
|
+
}
|
|
18027
|
+
if (!header)
|
|
18028
|
+
return null;
|
|
18029
|
+
if (!hasUser)
|
|
18030
|
+
return null;
|
|
18031
|
+
const after = await stat(file2);
|
|
18032
|
+
if (!sameFile(before, after))
|
|
18033
|
+
throw new PiSessionChangedError();
|
|
18034
|
+
const cwd = await realpath3(String(header.cwd));
|
|
18035
|
+
if (!(await stat(cwd)).isDirectory())
|
|
18036
|
+
return null;
|
|
18037
|
+
const nativeRef = nativeSessionRefSchema.safeParse({
|
|
18038
|
+
harnessId: "pi",
|
|
18039
|
+
nativeSessionId: header.id,
|
|
18040
|
+
locator: { sessionFile: await realpath3(file2) },
|
|
18041
|
+
formatVersion: 1
|
|
17087
18042
|
});
|
|
17088
|
-
|
|
18043
|
+
const candidate = harnessSessionImportCandidateSchema.safeParse({
|
|
18044
|
+
nativeSessionId: header.id,
|
|
18045
|
+
cwd,
|
|
18046
|
+
title: name ?? firstMessage,
|
|
18047
|
+
updatedAt: Math.floor(updatedAt),
|
|
18048
|
+
running: null
|
|
18049
|
+
});
|
|
18050
|
+
return candidate.success && nativeRef.success ? { candidate: candidate.data, nativeRef: nativeRef.data } : null;
|
|
17089
18051
|
}
|
|
17090
|
-
function
|
|
17091
|
-
const
|
|
17092
|
-
const
|
|
17093
|
-
|
|
17094
|
-
|
|
17095
|
-
|
|
17096
|
-
|
|
17097
|
-
|
|
17098
|
-
|
|
17099
|
-
|
|
17100
|
-
|
|
17101
|
-
|
|
18052
|
+
async function readIdentity(file2, signal) {
|
|
18053
|
+
const stream = createReadStream2(file2, { encoding: "utf8", signal });
|
|
18054
|
+
const lines = createInterface2({ input: stream, crlfDelay: Infinity });
|
|
18055
|
+
try {
|
|
18056
|
+
for await (const line of lines) {
|
|
18057
|
+
signal.throwIfAborted();
|
|
18058
|
+
if (!line.trim())
|
|
18059
|
+
continue;
|
|
18060
|
+
let header;
|
|
18061
|
+
try {
|
|
18062
|
+
header = JSON.parse(line);
|
|
18063
|
+
} catch {
|
|
18064
|
+
return null;
|
|
18065
|
+
}
|
|
18066
|
+
return isRecord4(header) && header.type === "session" && header.version === 3 && typeof header.id === "string" ? header.id : null;
|
|
17102
18067
|
}
|
|
17103
|
-
|
|
17104
|
-
|
|
17105
|
-
|
|
18068
|
+
return null;
|
|
18069
|
+
} finally {
|
|
18070
|
+
lines.close();
|
|
18071
|
+
stream.destroy();
|
|
17106
18072
|
}
|
|
17107
|
-
return directories;
|
|
17108
18073
|
}
|
|
17109
|
-
|
|
17110
|
-
|
|
17111
|
-
|
|
17112
|
-
|
|
17113
|
-
|
|
17114
|
-
|
|
17115
|
-
return [{ candidate: command, source: "configured" }];
|
|
18074
|
+
var PiSessionImportIndex = class {
|
|
18075
|
+
#location;
|
|
18076
|
+
#cache = /* @__PURE__ */ new Map();
|
|
18077
|
+
#listing;
|
|
18078
|
+
constructor(environment) {
|
|
18079
|
+
this.#location = piSessionImportDirectory(environment);
|
|
17116
18080
|
}
|
|
17117
|
-
|
|
17118
|
-
|
|
17119
|
-
|
|
17120
|
-
|
|
17121
|
-
|
|
17122
|
-
candidate: pathFlavor.join(directory, command + extension),
|
|
17123
|
-
source: "path"
|
|
17124
|
-
});
|
|
17125
|
-
}
|
|
18081
|
+
list(signal) {
|
|
18082
|
+
this.#listing ??= this.#scan(signal).finally(() => {
|
|
18083
|
+
this.#listing = void 0;
|
|
18084
|
+
});
|
|
18085
|
+
return this.#listing;
|
|
17126
18086
|
}
|
|
17127
|
-
|
|
17128
|
-
|
|
17129
|
-
|
|
17130
|
-
|
|
17131
|
-
|
|
17132
|
-
|
|
17133
|
-
|
|
17134
|
-
|
|
17135
|
-
|
|
18087
|
+
async #scan(signal) {
|
|
18088
|
+
const { directory, flat } = this.#location;
|
|
18089
|
+
const files = await sessionFiles(directory, flat, signal);
|
|
18090
|
+
const next = /* @__PURE__ */ new Map();
|
|
18091
|
+
const identities = /* @__PURE__ */ new Set();
|
|
18092
|
+
const sources = [];
|
|
18093
|
+
for (const file2 of files) {
|
|
18094
|
+
signal.throwIfAborted();
|
|
18095
|
+
try {
|
|
18096
|
+
const fingerprint = await stat(file2);
|
|
18097
|
+
const cached2 = this.#cache.get(file2);
|
|
18098
|
+
const source = cached2 && sameFile(cached2.fingerprint, fingerprint) ? cached2.source : await readCandidate(file2, signal);
|
|
18099
|
+
if (!source)
|
|
18100
|
+
continue;
|
|
18101
|
+
if (!(await stat(source.candidate.cwd)).isDirectory())
|
|
18102
|
+
continue;
|
|
18103
|
+
if (identities.has(source.nativeRef.nativeSessionId))
|
|
18104
|
+
throw new Error("Pi Session identity is ambiguous across files");
|
|
18105
|
+
identities.add(source.nativeRef.nativeSessionId);
|
|
18106
|
+
next.set(file2, { fingerprint, source });
|
|
18107
|
+
sources.push(source);
|
|
18108
|
+
} catch (error51) {
|
|
18109
|
+
if (!missing(error51) && !(error51 instanceof PiSessionChangedError))
|
|
18110
|
+
throw error51;
|
|
18111
|
+
}
|
|
17136
18112
|
}
|
|
18113
|
+
this.#cache = next;
|
|
18114
|
+
return structuredClone(sources.sort((left, right) => right.candidate.updatedAt - left.candidate.updatedAt));
|
|
17137
18115
|
}
|
|
17138
|
-
|
|
17139
|
-
}
|
|
17140
|
-
|
|
17141
|
-
|
|
17142
|
-
|
|
17143
|
-
|
|
17144
|
-
|
|
17145
|
-
|
|
17146
|
-
|
|
17147
|
-
|
|
17148
|
-
|
|
17149
|
-
|
|
17150
|
-
|
|
17151
|
-
|
|
17152
|
-
|
|
17153
|
-
|
|
17154
|
-
|
|
17155
|
-
|
|
17156
|
-
|
|
17157
|
-
|
|
17158
|
-
|
|
17159
|
-
|
|
17160
|
-
|
|
17161
|
-
|
|
17162
|
-
|
|
17163
|
-
|
|
17164
|
-
|
|
17165
|
-
|
|
17166
|
-
|
|
18116
|
+
async resolve(nativeSessionId, signal) {
|
|
18117
|
+
const { directory, flat } = this.#location;
|
|
18118
|
+
let selected;
|
|
18119
|
+
for (const file2 of await sessionFiles(directory, flat, signal)) {
|
|
18120
|
+
signal.throwIfAborted();
|
|
18121
|
+
try {
|
|
18122
|
+
const fingerprint = await stat(file2);
|
|
18123
|
+
const cached2 = this.#cache.get(file2);
|
|
18124
|
+
const id = cached2 && sameFile(cached2.fingerprint, fingerprint) ? cached2.source.nativeRef.nativeSessionId : await readIdentity(file2, signal);
|
|
18125
|
+
if (id !== nativeSessionId)
|
|
18126
|
+
continue;
|
|
18127
|
+
if (selected)
|
|
18128
|
+
throw new Error("Pi Session identity is ambiguous across files");
|
|
18129
|
+
selected = file2;
|
|
18130
|
+
} catch (error51) {
|
|
18131
|
+
if (!missing(error51))
|
|
18132
|
+
throw error51;
|
|
18133
|
+
}
|
|
18134
|
+
}
|
|
18135
|
+
if (!selected)
|
|
18136
|
+
return null;
|
|
18137
|
+
try {
|
|
18138
|
+
const source = await readCandidate(selected, signal);
|
|
18139
|
+
return source?.nativeRef.nativeSessionId === nativeSessionId ? source : null;
|
|
18140
|
+
} catch (error51) {
|
|
18141
|
+
if (missing(error51))
|
|
18142
|
+
return null;
|
|
18143
|
+
throw error51;
|
|
18144
|
+
}
|
|
17167
18145
|
}
|
|
17168
18146
|
};
|
|
17169
|
-
|
|
17170
|
-
|
|
17171
|
-
|
|
17172
|
-
|
|
17173
|
-
|
|
17174
|
-
...dependencies.homeDirectory ? { homeDirectory: dependencies.homeDirectory } : {}
|
|
17175
|
-
}, { ...dependencies.isExecutable ? { isExecutable: dependencies.isExecutable } : {} });
|
|
17176
|
-
return resolution?.executable ?? input.command ?? input.environment.PI_COMMAND ?? "pi";
|
|
17177
|
-
}
|
|
18147
|
+
|
|
18148
|
+
// dist/pi-rpc-session.js
|
|
18149
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
18150
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
18151
|
+
import path8 from "node:path";
|
|
17178
18152
|
|
|
17179
18153
|
// dist/pi-usage.js
|
|
17180
18154
|
function isRecord5(value) {
|
|
@@ -17247,6 +18221,82 @@ function optionalPiStateContextUsage(value) {
|
|
|
17247
18221
|
}
|
|
17248
18222
|
}
|
|
17249
18223
|
|
|
18224
|
+
// dist/pi-subagent-rpc.js
|
|
18225
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
18226
|
+
var PiSubagentRpc = class {
|
|
18227
|
+
send;
|
|
18228
|
+
timeoutMs;
|
|
18229
|
+
#handler;
|
|
18230
|
+
#latest;
|
|
18231
|
+
#pending = /* @__PURE__ */ new Map();
|
|
18232
|
+
constructor(send, timeoutMs) {
|
|
18233
|
+
this.send = send;
|
|
18234
|
+
this.timeoutMs = timeoutMs;
|
|
18235
|
+
}
|
|
18236
|
+
setHandler(handler) {
|
|
18237
|
+
this.#handler = handler;
|
|
18238
|
+
if (this.#latest)
|
|
18239
|
+
handler(this.#latest);
|
|
18240
|
+
}
|
|
18241
|
+
handle(value) {
|
|
18242
|
+
if (value.type !== "extension_ui_request" || value.method !== "setWidget" || value.widgetKey !== "subagent-async" && value.widgetKey !== "subagent-inspect")
|
|
18243
|
+
return false;
|
|
18244
|
+
const status = parsePiSubagentStatus(value);
|
|
18245
|
+
if (status) {
|
|
18246
|
+
this.#latest = status;
|
|
18247
|
+
this.#handler?.(status);
|
|
18248
|
+
}
|
|
18249
|
+
const reply = parsePiSubagentInspection(value);
|
|
18250
|
+
if (reply) {
|
|
18251
|
+
const pending = this.#pending.get(reply.requestId);
|
|
18252
|
+
if (pending) {
|
|
18253
|
+
this.#pending.delete(reply.requestId);
|
|
18254
|
+
clearTimeout(pending.timer);
|
|
18255
|
+
pending.resolve(reply);
|
|
18256
|
+
}
|
|
18257
|
+
}
|
|
18258
|
+
return true;
|
|
18259
|
+
}
|
|
18260
|
+
async inspect(nativeSubagentId) {
|
|
18261
|
+
const address = parsePiSubagentId(nativeSubagentId);
|
|
18262
|
+
const commands = await this.send("get_commands", {});
|
|
18263
|
+
const data = commands.data;
|
|
18264
|
+
if (!Array.isArray(data?.commands) || !data.commands.some((command) => command?.name === "subagents-inspect-rpc" && command.source === "extension")) {
|
|
18265
|
+
throw new Error("Installed Pi has no pi-subagents Host inspection command");
|
|
18266
|
+
}
|
|
18267
|
+
const requestId = randomUUID3();
|
|
18268
|
+
const reply = new Promise((resolve, reject) => {
|
|
18269
|
+
const timer = setTimeout(() => {
|
|
18270
|
+
this.#pending.delete(requestId);
|
|
18271
|
+
reject(new Error("Pi subagent inspection timed out"));
|
|
18272
|
+
}, this.timeoutMs);
|
|
18273
|
+
this.#pending.set(requestId, { resolve, reject, timer });
|
|
18274
|
+
});
|
|
18275
|
+
try {
|
|
18276
|
+
const message3 = `/subagents-inspect-rpc ${requestId} ${address.runId}${address.childId ? ` ${address.childId}` : ""} --lines 200`;
|
|
18277
|
+
const [, result] = await Promise.all([this.send("prompt", { message: message3 }), reply]);
|
|
18278
|
+
if (!result.error && (result.asyncId !== address.runId && result.asyncId !== address.childId || result.childId !== address.childId)) {
|
|
18279
|
+
throw new Error("Pi subagent inspection identity does not match the request");
|
|
18280
|
+
}
|
|
18281
|
+
return result;
|
|
18282
|
+
} finally {
|
|
18283
|
+
const pending = this.#pending.get(requestId);
|
|
18284
|
+
if (pending) {
|
|
18285
|
+
clearTimeout(pending.timer);
|
|
18286
|
+
this.#pending.delete(requestId);
|
|
18287
|
+
}
|
|
18288
|
+
}
|
|
18289
|
+
}
|
|
18290
|
+
close(error51 = new Error("Pi subagent inspection transport closed")) {
|
|
18291
|
+
for (const pending of this.#pending.values()) {
|
|
18292
|
+
clearTimeout(pending.timer);
|
|
18293
|
+
pending.reject(error51);
|
|
18294
|
+
}
|
|
18295
|
+
this.#pending.clear();
|
|
18296
|
+
this.#handler = void 0;
|
|
18297
|
+
}
|
|
18298
|
+
};
|
|
18299
|
+
|
|
17250
18300
|
// dist/pi-rpc-session.js
|
|
17251
18301
|
var PiRpcFaultError = class extends Error {
|
|
17252
18302
|
kind;
|
|
@@ -17378,15 +18428,15 @@ function extractReasoningText(content) {
|
|
|
17378
18428
|
return null;
|
|
17379
18429
|
const type = String(content.type ?? "");
|
|
17380
18430
|
if (type === "thinking" || type === "reasoning" || type === "thought") {
|
|
17381
|
-
const
|
|
17382
|
-
return typeof
|
|
18431
|
+
const text2 = content.thinking ?? content.reasoning ?? content.text ?? content.delta;
|
|
18432
|
+
return typeof text2 === "string" ? text2 : null;
|
|
17383
18433
|
}
|
|
17384
18434
|
return null;
|
|
17385
18435
|
}
|
|
17386
18436
|
function assistantReasoning(value) {
|
|
17387
18437
|
if (!isRecord6(value) || value.role !== "assistant" || !Array.isArray(value.content))
|
|
17388
18438
|
return null;
|
|
17389
|
-
return value.content.map(extractReasoningText).filter((
|
|
18439
|
+
return value.content.map(extractReasoningText).filter((text2) => typeof text2 === "string").join("");
|
|
17390
18440
|
}
|
|
17391
18441
|
function assistantFailure(value) {
|
|
17392
18442
|
if (!isRecord6(value) || value.role !== "assistant")
|
|
@@ -17451,7 +18501,7 @@ function piRpcProcessCommand(options, dependencies = {}) {
|
|
|
17451
18501
|
...thinkingArguments,
|
|
17452
18502
|
...sessionArguments
|
|
17453
18503
|
];
|
|
17454
|
-
const extension =
|
|
18504
|
+
const extension = path8.win32.extname(command).toLowerCase();
|
|
17455
18505
|
if (platform !== "win32" || ![".cmd", ".bat"].includes(extension)) {
|
|
17456
18506
|
return { command, arguments: arguments_, windowsVerbatimArguments: false };
|
|
17457
18507
|
}
|
|
@@ -17493,6 +18543,7 @@ var PiRpcSession = class {
|
|
|
17493
18543
|
#latestCacheHitRatePercent;
|
|
17494
18544
|
#manualCompaction = null;
|
|
17495
18545
|
#stderrTail = "";
|
|
18546
|
+
#subagents;
|
|
17496
18547
|
constructor(options, processAdapter = nodeProcessAdapter) {
|
|
17497
18548
|
if (options.sessionFile && options.forkSessionFile) {
|
|
17498
18549
|
throw new Error("Pi RPC cannot combine Session resume and Fork startup");
|
|
@@ -17507,6 +18558,7 @@ var PiRpcSession = class {
|
|
|
17507
18558
|
...options
|
|
17508
18559
|
};
|
|
17509
18560
|
this.#processAdapter = processAdapter;
|
|
18561
|
+
this.#subagents = new PiSubagentRpc((type, payload) => this.#send(type, payload), this.#options.commandTimeoutMs);
|
|
17510
18562
|
}
|
|
17511
18563
|
get state() {
|
|
17512
18564
|
if (!this.#state)
|
|
@@ -17516,6 +18568,12 @@ var PiRpcSession = class {
|
|
|
17516
18568
|
get stderrTail() {
|
|
17517
18569
|
return this.#stderrTail;
|
|
17518
18570
|
}
|
|
18571
|
+
setSubagentStatusHandler(handler) {
|
|
18572
|
+
this.#subagents.setHandler(handler);
|
|
18573
|
+
}
|
|
18574
|
+
inspectSubagent(id) {
|
|
18575
|
+
return this.#subagents.inspect(id);
|
|
18576
|
+
}
|
|
17519
18577
|
setAutonomousTurnHandler(handler) {
|
|
17520
18578
|
this.#autonomousTurnHandler = handler;
|
|
17521
18579
|
}
|
|
@@ -17685,13 +18743,13 @@ var PiRpcSession = class {
|
|
|
17685
18743
|
throw fault;
|
|
17686
18744
|
}
|
|
17687
18745
|
}
|
|
17688
|
-
async runTurn(
|
|
18746
|
+
async runTurn(text2, onEvent) {
|
|
17689
18747
|
if (!this.#child || !this.#state || this.#closed || this.#failed) {
|
|
17690
18748
|
throw new Error("Pi RPC Session is unavailable");
|
|
17691
18749
|
}
|
|
17692
18750
|
if (this.#activeTurn)
|
|
17693
18751
|
throw new Error("Pi RPC Session already has an active Turn");
|
|
17694
|
-
if (
|
|
18752
|
+
if (text2.length === 0)
|
|
17695
18753
|
throw new Error("Pi text Turn must not be empty");
|
|
17696
18754
|
const settled = new Promise((resolve, reject) => {
|
|
17697
18755
|
this.#activeTurn = {
|
|
@@ -17720,7 +18778,7 @@ var PiRpcSession = class {
|
|
|
17720
18778
|
};
|
|
17721
18779
|
});
|
|
17722
18780
|
try {
|
|
17723
|
-
await this.#send("prompt", { message:
|
|
18781
|
+
await this.#send("prompt", { message: text2 });
|
|
17724
18782
|
} catch (error51) {
|
|
17725
18783
|
this.#rejectActiveTurn(error51 instanceof Error ? error51 : new Error(message2(error51)));
|
|
17726
18784
|
}
|
|
@@ -17840,6 +18898,8 @@ var PiRpcSession = class {
|
|
|
17840
18898
|
this.#handleResponse(value);
|
|
17841
18899
|
return;
|
|
17842
18900
|
}
|
|
18901
|
+
if (this.#subagents.handle(value))
|
|
18902
|
+
return;
|
|
17843
18903
|
if (value.type === "compaction_start") {
|
|
17844
18904
|
this.#compactionActive = true;
|
|
17845
18905
|
this.#compactionTurn = this.#activeTurn;
|
|
@@ -17954,7 +19014,7 @@ var PiRpcSession = class {
|
|
|
17954
19014
|
const active = {
|
|
17955
19015
|
origin: "autonomous",
|
|
17956
19016
|
autonomousEvents: events,
|
|
17957
|
-
nativeTurnKey: assistantMessageId(value) ??
|
|
19017
|
+
nativeTurnKey: assistantMessageId(value) ?? randomUUID4(),
|
|
17958
19018
|
nativeCancellationObserved: false,
|
|
17959
19019
|
text: "",
|
|
17960
19020
|
assistantMessageId: null,
|
|
@@ -18156,13 +19216,13 @@ var PiRpcSession = class {
|
|
|
18156
19216
|
async #confirmSettledTurn(active) {
|
|
18157
19217
|
try {
|
|
18158
19218
|
const response = await this.#send("get_state", {});
|
|
18159
|
-
const
|
|
19219
|
+
const state2 = parseSessionState(response);
|
|
18160
19220
|
if (parseSessionStreaming(response)) {
|
|
18161
19221
|
throw new PiRpcFaultError("protocolError", "Pi RPC agent_settled state is still Streaming");
|
|
18162
19222
|
}
|
|
18163
19223
|
if (this.#activeTurn !== active)
|
|
18164
19224
|
return;
|
|
18165
|
-
this.#state =
|
|
19225
|
+
this.#state = state2;
|
|
18166
19226
|
active.settlement = "confirmed";
|
|
18167
19227
|
this.#finishSettledTurn(active);
|
|
18168
19228
|
} catch (error51) {
|
|
@@ -18217,7 +19277,7 @@ var PiRpcSession = class {
|
|
|
18217
19277
|
if (active.assistantMessageId !== null && active.reasoningMessageOpen) {
|
|
18218
19278
|
active.onEvent({ type: "reasoning.completed", messageId: active.assistantMessageId });
|
|
18219
19279
|
}
|
|
18220
|
-
const messageId = assistantMessageId(value) ??
|
|
19280
|
+
const messageId = assistantMessageId(value) ?? randomUUID4();
|
|
18221
19281
|
active.assistantMessageId = messageId;
|
|
18222
19282
|
active.sawStreamedMessageText = false;
|
|
18223
19283
|
active.sawStreamedMessageReasoning = false;
|
|
@@ -18278,7 +19338,7 @@ var PiRpcSession = class {
|
|
|
18278
19338
|
if (!child?.stdin.writable || this.#closed || this.#failed) {
|
|
18279
19339
|
return Promise.reject(new Error("Pi RPC stdin is unavailable"));
|
|
18280
19340
|
}
|
|
18281
|
-
const id = `codexhost-${
|
|
19341
|
+
const id = `codexhost-${randomUUID4()}`;
|
|
18282
19342
|
return new Promise((resolve, reject) => {
|
|
18283
19343
|
const pending = {
|
|
18284
19344
|
command: type,
|
|
@@ -18364,6 +19424,7 @@ var PiRpcSession = class {
|
|
|
18364
19424
|
}
|
|
18365
19425
|
}
|
|
18366
19426
|
#rejectAll(error51) {
|
|
19427
|
+
this.#subagents.close(error51);
|
|
18367
19428
|
for (const pending of this.#pending.values()) {
|
|
18368
19429
|
if (pending.timeout)
|
|
18369
19430
|
clearTimeout(pending.timeout);
|
|
@@ -18442,38 +19503,38 @@ function normalizedError(error51, fallbackCode) {
|
|
|
18442
19503
|
function invalidState(message3) {
|
|
18443
19504
|
return { code: "invalidState", message: message3, retryable: false };
|
|
18444
19505
|
}
|
|
18445
|
-
function nativeModelFromState(
|
|
18446
|
-
if (
|
|
19506
|
+
function nativeModelFromState(state2) {
|
|
19507
|
+
if (state2.provider === null && state2.modelId === null)
|
|
18447
19508
|
return null;
|
|
18448
|
-
if (
|
|
19509
|
+
if (state2.provider === null || state2.modelId === null) {
|
|
18449
19510
|
throw new PiRpcFaultError("protocolError", "Pi state contains a partial Model identity");
|
|
18450
19511
|
}
|
|
18451
|
-
return { provider:
|
|
19512
|
+
return { provider: state2.provider, id: state2.modelId };
|
|
18452
19513
|
}
|
|
18453
|
-
function effectiveModelFromState(
|
|
18454
|
-
const model = nativeModelFromState(
|
|
19514
|
+
function effectiveModelFromState(state2) {
|
|
19515
|
+
const model = nativeModelFromState(state2);
|
|
18455
19516
|
return model ? encodePiModelRef(model) : void 0;
|
|
18456
19517
|
}
|
|
18457
|
-
function harnessStateFromPi(
|
|
18458
|
-
const effectiveModel = effectiveModelFromState(
|
|
19518
|
+
function harnessStateFromPi(state2, thinkingLevels) {
|
|
19519
|
+
const effectiveModel = effectiveModelFromState(state2);
|
|
18459
19520
|
const availableThinkingOptions = thinkingLevels ? normalizePiThinkingOptions(thinkingLevels) : void 0;
|
|
18460
|
-
if (availableThinkingOptions && (!
|
|
19521
|
+
if (availableThinkingOptions && (!state2.thinkingLevel || !thinkingLevels?.includes(state2.thinkingLevel))) {
|
|
18461
19522
|
throw new PiRpcFaultError("protocolError", "Pi effective Thinking level is absent from its available levels");
|
|
18462
19523
|
}
|
|
18463
19524
|
return {
|
|
18464
19525
|
nativeRef: nativeSessionRefSchema.parse({
|
|
18465
19526
|
harnessId: piHarnessId2,
|
|
18466
|
-
nativeSessionId:
|
|
18467
|
-
...
|
|
19527
|
+
nativeSessionId: state2.sessionId,
|
|
19528
|
+
...state2.sessionFile ? { locator: { sessionFile: state2.sessionFile } } : {},
|
|
18468
19529
|
formatVersion: 1
|
|
18469
19530
|
}),
|
|
18470
19531
|
...effectiveModel ? { effectiveModel } : {},
|
|
18471
|
-
...
|
|
19532
|
+
...state2.thinkingLevel ? { effectiveThinkingOptionId: state2.thinkingLevel } : {},
|
|
18472
19533
|
...availableThinkingOptions ? { availableThinkingOptions } : {}
|
|
18473
19534
|
};
|
|
18474
19535
|
}
|
|
18475
|
-
function nativeModelForHistory(
|
|
18476
|
-
return nativeModelFromState(
|
|
19536
|
+
function nativeModelForHistory(state2) {
|
|
19537
|
+
return nativeModelFromState(state2);
|
|
18477
19538
|
}
|
|
18478
19539
|
function sessionFileFromRef(ref) {
|
|
18479
19540
|
if (ref.harnessId !== piHarnessId2 || !isRecord7(ref.locator) || typeof ref.locator.sessionFile !== "string" || ref.locator.sessionFile.length === 0) {
|
|
@@ -18493,20 +19554,20 @@ function nativeText(value) {
|
|
|
18493
19554
|
return value;
|
|
18494
19555
|
if (!isRecord7(value) || !Array.isArray(value.content))
|
|
18495
19556
|
return "";
|
|
18496
|
-
return value.content.filter((content) => isRecord7(content) && content.type === "text" && typeof content.text === "string").map(({ text }) =>
|
|
19557
|
+
return value.content.filter((content) => isRecord7(content) && content.type === "text" && typeof content.text === "string").map(({ text: text2 }) => text2).join("");
|
|
18497
19558
|
}
|
|
18498
19559
|
function boundedOutput(value, limit) {
|
|
18499
|
-
const
|
|
18500
|
-
if (
|
|
19560
|
+
const text2 = nativeText(value);
|
|
19561
|
+
if (text2.length === 0)
|
|
18501
19562
|
return void 0;
|
|
18502
|
-
const truncated =
|
|
19563
|
+
const truncated = text2.length > limit;
|
|
18503
19564
|
return {
|
|
18504
|
-
content: [{ type: "text", text: truncated ?
|
|
19565
|
+
content: [{ type: "text", text: truncated ? text2.slice(0, limit) : text2 }],
|
|
18505
19566
|
...truncated ? { truncated: true } : {}
|
|
18506
19567
|
};
|
|
18507
19568
|
}
|
|
18508
19569
|
function outputText(output) {
|
|
18509
|
-
return output?.content.filter((content) => content.type === "text").map(({ text }) =>
|
|
19570
|
+
return output?.content.filter((content) => content.type === "text").map(({ text: text2 }) => text2).join("") ?? "";
|
|
18510
19571
|
}
|
|
18511
19572
|
function stringField(value, key) {
|
|
18512
19573
|
if (!isRecord7(value))
|
|
@@ -18538,10 +19599,10 @@ function stripDiffPrefix(pathString) {
|
|
|
18538
19599
|
return pathString.startsWith("a/") || pathString.startsWith("b/") ? pathString.slice(2) : pathString;
|
|
18539
19600
|
}
|
|
18540
19601
|
function displayPath(nativePath, cwd) {
|
|
18541
|
-
const resolvedCwd =
|
|
18542
|
-
const resolvedPath =
|
|
18543
|
-
const relative =
|
|
18544
|
-
const inside = relative.length > 0 && relative !== ".." && !relative.startsWith(`..${
|
|
19602
|
+
const resolvedCwd = path9.resolve(cwd);
|
|
19603
|
+
const resolvedPath = path9.isAbsolute(nativePath) ? path9.resolve(nativePath) : path9.resolve(cwd, nativePath);
|
|
19604
|
+
const relative = path9.relative(resolvedCwd, resolvedPath);
|
|
19605
|
+
const inside = relative.length > 0 && relative !== ".." && !relative.startsWith(`..${path9.sep}`);
|
|
18545
19606
|
const selected = inside ? relative : resolvedPath;
|
|
18546
19607
|
const normalized = selected.replaceAll("\\", "/");
|
|
18547
19608
|
if (normalized.length === 0 || normalized === ".")
|
|
@@ -18731,6 +19792,8 @@ var PiHarnessSession = class {
|
|
|
18731
19792
|
initialUsage;
|
|
18732
19793
|
outputs;
|
|
18733
19794
|
#channel = new HarnessOutputChannel();
|
|
19795
|
+
#subagents = new PiSubagents((event) => this.#event(event));
|
|
19796
|
+
#pendingSubagentStatus = null;
|
|
18734
19797
|
#closeTimeoutMs;
|
|
18735
19798
|
#createTransport;
|
|
18736
19799
|
#cwd;
|
|
@@ -18766,7 +19829,8 @@ var PiHarnessSession = class {
|
|
|
18766
19829
|
permissionModeScope: "live"
|
|
18767
19830
|
},
|
|
18768
19831
|
history: { fork: true, forkAcrossCwd: true, rollbackLastTurn: true },
|
|
18769
|
-
autonomousTurns: { observe: true }
|
|
19832
|
+
autonomousTurns: { observe: true },
|
|
19833
|
+
subagents: { observe: true, readTranscript: true }
|
|
18770
19834
|
};
|
|
18771
19835
|
this.commands = {
|
|
18772
19836
|
list: async () => ({ ok: true, value: piCommandCatalog }),
|
|
@@ -18781,6 +19845,24 @@ var PiHarnessSession = class {
|
|
|
18781
19845
|
if (this.#transport)
|
|
18782
19846
|
this.#bindAutonomousTurnHandler(this.#transport);
|
|
18783
19847
|
}
|
|
19848
|
+
ownsNativeSession(id) {
|
|
19849
|
+
return this.#transport?.state.sessionId === id;
|
|
19850
|
+
}
|
|
19851
|
+
async readSubagentHistory(cwd) {
|
|
19852
|
+
if (this.#phase !== "open" || path9.resolve(cwd) !== path9.resolve(this.#cwd)) {
|
|
19853
|
+
throw new Error("Pi Subagent parent workspace or Session is unavailable");
|
|
19854
|
+
}
|
|
19855
|
+
return (await this.#ensureTransport()).getEntries();
|
|
19856
|
+
}
|
|
19857
|
+
async inspectSubagent(id, cwd) {
|
|
19858
|
+
if (this.#phase !== "open" || path9.resolve(cwd) !== path9.resolve(this.#cwd)) {
|
|
19859
|
+
throw new Error("Pi Subagent parent workspace or Session is unavailable");
|
|
19860
|
+
}
|
|
19861
|
+
const transport = await this.#ensureTransport();
|
|
19862
|
+
if (!transport.inspectSubagent)
|
|
19863
|
+
throw new Error("Pi transport does not support Subagent inspection");
|
|
19864
|
+
return transport.inspectSubagent(id);
|
|
19865
|
+
}
|
|
18784
19866
|
handleTransportFault(error51) {
|
|
18785
19867
|
queueMicrotask(() => this.#fault(error51));
|
|
18786
19868
|
}
|
|
@@ -18801,13 +19883,14 @@ var PiHarnessSession = class {
|
|
|
18801
19883
|
try {
|
|
18802
19884
|
const transport = await this.#ensureTransport();
|
|
18803
19885
|
const history = await transport.getEntries();
|
|
19886
|
+
await restorePiSubagents(history, transport.state.sessionId, this.#subagents);
|
|
18804
19887
|
return {
|
|
18805
19888
|
ok: true,
|
|
18806
19889
|
value: {
|
|
18807
19890
|
...mapPiSnapshot(history, {
|
|
18808
19891
|
sessionId: transport.state.sessionId,
|
|
18809
19892
|
model: nativeModelForHistory(transport.state)
|
|
18810
|
-
}),
|
|
19893
|
+
}, this.#subagents),
|
|
18811
19894
|
state: this.#state
|
|
18812
19895
|
}
|
|
18813
19896
|
};
|
|
@@ -18850,8 +19933,8 @@ var PiHarnessSession = class {
|
|
|
18850
19933
|
}
|
|
18851
19934
|
};
|
|
18852
19935
|
}
|
|
18853
|
-
const
|
|
18854
|
-
if (
|
|
19936
|
+
const text2 = command.input.filter((input) => input.type === "text").map((input) => input.text).join("\n");
|
|
19937
|
+
if (text2.length === 0) {
|
|
18855
19938
|
return {
|
|
18856
19939
|
ok: false,
|
|
18857
19940
|
error: {
|
|
@@ -18908,7 +19991,7 @@ var PiHarnessSession = class {
|
|
|
18908
19991
|
this.#active = active;
|
|
18909
19992
|
this.#event({ type: "turn.started", turnId: command.turnId });
|
|
18910
19993
|
this.#event({ type: "item.started", turnId: command.turnId, item });
|
|
18911
|
-
void transport.runTurn(
|
|
19994
|
+
void transport.runTurn(text2, (event) => this.#handleTurnEvent(active, event)).then(async (result) => {
|
|
18912
19995
|
try {
|
|
18913
19996
|
const identity = await this.#completedTurnIdentity(active, transport);
|
|
18914
19997
|
this.#completeTurn(active, result.cancelled ? {
|
|
@@ -19027,19 +20110,19 @@ var PiHarnessSession = class {
|
|
|
19027
20110
|
const previousModel = this.#state.effectiveModel;
|
|
19028
20111
|
this.#configuring = true;
|
|
19029
20112
|
try {
|
|
19030
|
-
let
|
|
20113
|
+
let state2;
|
|
19031
20114
|
let thinkingLevels;
|
|
19032
20115
|
try {
|
|
19033
|
-
|
|
20116
|
+
state2 = await transport.selectModel(requested);
|
|
19034
20117
|
thinkingLevels = await transport.getAvailableThinkingLevels();
|
|
19035
|
-
this.#publishTransportState(
|
|
20118
|
+
this.#publishTransportState(state2, thinkingLevels);
|
|
19036
20119
|
} catch (error51) {
|
|
19037
20120
|
if (error51 instanceof PiRpcFaultError)
|
|
19038
20121
|
this.#fault(error51);
|
|
19039
20122
|
return { ok: false, error: normalizedError(error51, "nativeFailure") };
|
|
19040
20123
|
}
|
|
19041
|
-
const actual = nativeModelFromState(
|
|
19042
|
-
const nextModel = effectiveModelFromState(
|
|
20124
|
+
const actual = nativeModelFromState(state2);
|
|
20125
|
+
const nextModel = effectiveModelFromState(state2);
|
|
19043
20126
|
if (previousModel?.id !== nextModel?.id) {
|
|
19044
20127
|
this.#invalidateUsage();
|
|
19045
20128
|
void this.#refreshUsage();
|
|
@@ -19101,10 +20184,10 @@ var PiHarnessSession = class {
|
|
|
19101
20184
|
const thinkingOptionId = parsedThinkingOptionId.data;
|
|
19102
20185
|
this.#configuring = true;
|
|
19103
20186
|
try {
|
|
19104
|
-
let
|
|
20187
|
+
let state2;
|
|
19105
20188
|
let thinkingLevels;
|
|
19106
20189
|
try {
|
|
19107
|
-
|
|
20190
|
+
state2 = await transport.selectThinkingOption(thinkingOptionId);
|
|
19108
20191
|
thinkingLevels = await transport.getAvailableThinkingLevels();
|
|
19109
20192
|
} catch (error51) {
|
|
19110
20193
|
if (error51 instanceof PiRpcFaultError)
|
|
@@ -19122,7 +20205,7 @@ var PiHarnessSession = class {
|
|
|
19122
20205
|
};
|
|
19123
20206
|
}
|
|
19124
20207
|
try {
|
|
19125
|
-
this.#publishTransportState(
|
|
20208
|
+
this.#publishTransportState(state2, thinkingLevels);
|
|
19126
20209
|
} catch (error51) {
|
|
19127
20210
|
if (error51 instanceof PiRpcFaultError)
|
|
19128
20211
|
this.#fault(error51);
|
|
@@ -19279,16 +20362,16 @@ var PiHarnessSession = class {
|
|
|
19279
20362
|
const starting = transport.start().then(async () => {
|
|
19280
20363
|
if (this.#phase !== "open")
|
|
19281
20364
|
throw new Error("Pi Session closed during startup");
|
|
19282
|
-
let
|
|
20365
|
+
let state2 = transport.state;
|
|
19283
20366
|
let thinkingLevels = await transport.getAvailableThinkingLevels();
|
|
19284
20367
|
if (this.#requestedModel) {
|
|
19285
20368
|
const requested = decodePiModelRef(this.#requestedModel);
|
|
19286
|
-
const current = nativeModelFromState(
|
|
20369
|
+
const current = nativeModelFromState(state2);
|
|
19287
20370
|
if (!samePiModel(current, requested))
|
|
19288
|
-
|
|
20371
|
+
state2 = await transport.selectModel(requested);
|
|
19289
20372
|
thinkingLevels = await transport.getAvailableThinkingLevels();
|
|
19290
|
-
if (!samePiModel(nativeModelFromState(
|
|
19291
|
-
this.#publishTransportState(
|
|
20373
|
+
if (!samePiModel(nativeModelFromState(state2), requested)) {
|
|
20374
|
+
this.#publishTransportState(state2, thinkingLevels);
|
|
19292
20375
|
throw new Error("Pi did not activate the requested create Model");
|
|
19293
20376
|
}
|
|
19294
20377
|
}
|
|
@@ -19300,11 +20383,11 @@ var PiHarnessSession = class {
|
|
|
19300
20383
|
retryable: false
|
|
19301
20384
|
});
|
|
19302
20385
|
}
|
|
19303
|
-
|
|
20386
|
+
state2 = await transport.selectThinkingOption(this.#requestedThinkingOptionId);
|
|
19304
20387
|
thinkingLevels = await transport.getAvailableThinkingLevels();
|
|
19305
20388
|
}
|
|
19306
20389
|
this.#transport = transport;
|
|
19307
|
-
this.#publishTransportState(
|
|
20390
|
+
this.#publishTransportState(state2, thinkingLevels);
|
|
19308
20391
|
this.#drainPendingAutonomousTurns(transport);
|
|
19309
20392
|
return transport;
|
|
19310
20393
|
}).catch(async (error51) => {
|
|
@@ -19321,6 +20404,14 @@ var PiHarnessSession = class {
|
|
|
19321
20404
|
return starting;
|
|
19322
20405
|
}
|
|
19323
20406
|
#bindAutonomousTurnHandler(transport) {
|
|
20407
|
+
transport.setSubagentStatusHandler?.((runs) => {
|
|
20408
|
+
if (this.#phase !== "open")
|
|
20409
|
+
return;
|
|
20410
|
+
if (this.#transport !== transport)
|
|
20411
|
+
this.#pendingSubagentStatus = runs;
|
|
20412
|
+
else
|
|
20413
|
+
this.#subagents.observe(runs);
|
|
20414
|
+
});
|
|
19324
20415
|
transport.setAutonomousTurnHandler((turn) => {
|
|
19325
20416
|
if (this.#phase !== "open")
|
|
19326
20417
|
return;
|
|
@@ -19332,6 +20423,10 @@ var PiHarnessSession = class {
|
|
|
19332
20423
|
});
|
|
19333
20424
|
}
|
|
19334
20425
|
#drainPendingAutonomousTurns(transport) {
|
|
20426
|
+
if (this.#pendingSubagentStatus) {
|
|
20427
|
+
this.#subagents.observe(this.#pendingSubagentStatus);
|
|
20428
|
+
this.#pendingSubagentStatus = null;
|
|
20429
|
+
}
|
|
19335
20430
|
const pending = this.#pendingAutonomousTurns.filter((candidate) => candidate.transport === transport);
|
|
19336
20431
|
this.#pendingAutonomousTurns = this.#pendingAutonomousTurns.filter((candidate) => candidate.transport !== transport);
|
|
19337
20432
|
for (const candidate of pending) {
|
|
@@ -19359,7 +20454,7 @@ var PiHarnessSession = class {
|
|
|
19359
20454
|
}));
|
|
19360
20455
|
return;
|
|
19361
20456
|
}
|
|
19362
|
-
const turnId = hostTurnIdSchema.parse(
|
|
20457
|
+
const turnId = hostTurnIdSchema.parse(randomUUID5());
|
|
19363
20458
|
let resolveCompletion = () => void 0;
|
|
19364
20459
|
const completion = new Promise((resolve) => {
|
|
19365
20460
|
resolveCompletion = resolve;
|
|
@@ -19412,8 +20507,8 @@ var PiHarnessSession = class {
|
|
|
19412
20507
|
this.#fault(new PiAdapterFaultError(normalized));
|
|
19413
20508
|
}
|
|
19414
20509
|
}
|
|
19415
|
-
#publishTransportState(
|
|
19416
|
-
this.#state = harnessStateFromPi(
|
|
20510
|
+
#publishTransportState(state2, thinkingLevels) {
|
|
20511
|
+
this.#state = harnessStateFromPi(state2, thinkingLevels);
|
|
19417
20512
|
this.#event({ type: "session.state.changed", state: this.#state });
|
|
19418
20513
|
}
|
|
19419
20514
|
#invalidateUsage() {
|
|
@@ -19521,7 +20616,7 @@ var PiHarnessSession = class {
|
|
|
19521
20616
|
if (active.interactionByNativeId.has(request.requestId)) {
|
|
19522
20617
|
throw new Error("Pi Interaction started more than once");
|
|
19523
20618
|
}
|
|
19524
|
-
const interactionId = hostInteractionIdSchema.parse(
|
|
20619
|
+
const interactionId = hostInteractionIdSchema.parse(randomUUID5());
|
|
19525
20620
|
const question = request.method === "select" ? {
|
|
19526
20621
|
id: "answer",
|
|
19527
20622
|
type: "choice",
|
|
@@ -19600,16 +20695,16 @@ var PiHarnessSession = class {
|
|
|
19600
20695
|
active.agentMessageId = messageId;
|
|
19601
20696
|
active.sawAssistantMessage = true;
|
|
19602
20697
|
}
|
|
19603
|
-
#appendText(active,
|
|
20698
|
+
#appendText(active, text2) {
|
|
19604
20699
|
if (active.agentMessageId === null || !active.agentItem) {
|
|
19605
20700
|
throw new Error("Pi Assistant text arrived outside an active message");
|
|
19606
20701
|
}
|
|
19607
|
-
active.agentItem = { ...active.agentItem, text: active.agentItem.text +
|
|
20702
|
+
active.agentItem = { ...active.agentItem, text: active.agentItem.text + text2 };
|
|
19608
20703
|
this.#event({
|
|
19609
20704
|
type: "item.updated",
|
|
19610
20705
|
turnId: active.command.turnId,
|
|
19611
20706
|
itemId: active.agentItem.itemId,
|
|
19612
|
-
update: { type: "text.append", text }
|
|
20707
|
+
update: { type: "text.append", text: text2 }
|
|
19613
20708
|
});
|
|
19614
20709
|
}
|
|
19615
20710
|
#completeAgentItem(active, outcome, completeEmpty) {
|
|
@@ -19620,8 +20715,8 @@ var PiHarnessSession = class {
|
|
|
19620
20715
|
active.agentItem = null;
|
|
19621
20716
|
this.#completeItem(active, item, outcome);
|
|
19622
20717
|
}
|
|
19623
|
-
#appendReasoning(active,
|
|
19624
|
-
if (
|
|
20718
|
+
#appendReasoning(active, text2) {
|
|
20719
|
+
if (text2.length === 0)
|
|
19625
20720
|
return;
|
|
19626
20721
|
if (!active.reasoningItem) {
|
|
19627
20722
|
active.reasoningItem = {
|
|
@@ -19637,13 +20732,13 @@ var PiHarnessSession = class {
|
|
|
19637
20732
|
}
|
|
19638
20733
|
active.reasoningItem = {
|
|
19639
20734
|
...active.reasoningItem,
|
|
19640
|
-
text: active.reasoningItem.text +
|
|
20735
|
+
text: active.reasoningItem.text + text2
|
|
19641
20736
|
};
|
|
19642
20737
|
this.#event({
|
|
19643
20738
|
type: "item.updated",
|
|
19644
20739
|
turnId: active.command.turnId,
|
|
19645
20740
|
itemId: active.reasoningItem.itemId,
|
|
19646
|
-
update: { type: "text.append", text }
|
|
20741
|
+
update: { type: "text.append", text: text2 }
|
|
19647
20742
|
});
|
|
19648
20743
|
}
|
|
19649
20744
|
#completeReasoning(active, outcome) {
|
|
@@ -19680,6 +20775,7 @@ var PiHarnessSession = class {
|
|
|
19680
20775
|
const tool = active.tools.get(event.callId);
|
|
19681
20776
|
if (!tool)
|
|
19682
20777
|
throw new Error("Pi Tool update references an unknown Tool Call");
|
|
20778
|
+
this.#subagents.start(active.command.turnId, tool.nativeName, event.output, this.#newItemId(), event.callId);
|
|
19683
20779
|
const output = boundedOutput(event.output, this.#toolOutputLimit);
|
|
19684
20780
|
if (!output)
|
|
19685
20781
|
return;
|
|
@@ -19736,6 +20832,7 @@ var PiHarnessSession = class {
|
|
|
19736
20832
|
}
|
|
19737
20833
|
const outcome = active.cancellationRequested ? { status: "cancelled", reason: "Cancelled by user" } : event.isError ? { status: "failed", error: toolFailure(event.toolName) } : { status: "succeeded" };
|
|
19738
20834
|
this.#completeItem(active, tool.item, outcome);
|
|
20835
|
+
this.#subagents.start(active.command.turnId, event.toolName, event.result, this.#newItemId(), event.callId);
|
|
19739
20836
|
if (!event.isError) {
|
|
19740
20837
|
try {
|
|
19741
20838
|
const kind = fileMutatingKind(event.toolName);
|
|
@@ -19805,6 +20902,7 @@ var PiHarnessSession = class {
|
|
|
19805
20902
|
for (const tool of active.tools.values())
|
|
19806
20903
|
this.#completeItem(active, tool.item, itemOutcome2);
|
|
19807
20904
|
active.tools.clear();
|
|
20905
|
+
this.#subagents.finish(active.command.turnId);
|
|
19808
20906
|
if (!active.sawAssistantMessage && finalText !== void 0 && active.agentItem) {
|
|
19809
20907
|
active.agentItem = { ...active.agentItem, text: finalText };
|
|
19810
20908
|
}
|
|
@@ -19865,12 +20963,66 @@ var PiHarnessSession = class {
|
|
|
19865
20963
|
this.#channel.emit({ kind: "event", event });
|
|
19866
20964
|
}
|
|
19867
20965
|
#newItemId() {
|
|
19868
|
-
return hostItemIdSchema.parse(
|
|
20966
|
+
return hostItemIdSchema.parse(randomUUID5());
|
|
19869
20967
|
}
|
|
19870
20968
|
};
|
|
19871
20969
|
var PiAdapter = class {
|
|
20970
|
+
credentialImports;
|
|
19872
20971
|
commandCatalog = piCommandCatalog;
|
|
19873
20972
|
harnessId = piHarnessId2;
|
|
20973
|
+
subagents = {
|
|
20974
|
+
readSnapshot: async ({ parent, nativeSubagentId, cwd }) => {
|
|
20975
|
+
let transport;
|
|
20976
|
+
try {
|
|
20977
|
+
if (this.#closePromise || parent.harnessId !== this.harnessId) {
|
|
20978
|
+
return { ok: false, error: invalidState("Pi Subagent parent is unavailable") };
|
|
20979
|
+
}
|
|
20980
|
+
const workflow = parsePiWorkflowSubagentId(nativeSubagentId);
|
|
20981
|
+
if (!workflow)
|
|
20982
|
+
parsePiSubagentId(nativeSubagentId);
|
|
20983
|
+
const live = [...this.#sessions].find((session) => session.ownsNativeSession(parent.nativeSessionId));
|
|
20984
|
+
let reply;
|
|
20985
|
+
if (live) {
|
|
20986
|
+
if (workflow)
|
|
20987
|
+
return await readPiWorkflowChild(await live.readSubagentHistory(cwd), parent.nativeSessionId, workflow);
|
|
20988
|
+
reply = await live.inspectSubagent(nativeSubagentId, cwd);
|
|
20989
|
+
} else {
|
|
20990
|
+
const sessionFile = sessionFileFromRef(parent);
|
|
20991
|
+
transport = this.#createTransport({ cwd, sessionFile });
|
|
20992
|
+
this.#inspections.add(transport);
|
|
20993
|
+
await transport.start();
|
|
20994
|
+
if (transport.state.sessionId !== parent.nativeSessionId)
|
|
20995
|
+
throw new Error("Pi Subagent parent identity mismatch");
|
|
20996
|
+
await transport.verifySessionCwd(cwd);
|
|
20997
|
+
if (workflow)
|
|
20998
|
+
return await readPiWorkflowChild(await transport.getEntries(), parent.nativeSessionId, workflow);
|
|
20999
|
+
if (!transport.inspectSubagent)
|
|
21000
|
+
throw new Error("Pi transport does not support Subagent inspection");
|
|
21001
|
+
reply = await transport.inspectSubagent(nativeSubagentId);
|
|
21002
|
+
}
|
|
21003
|
+
if (reply.error)
|
|
21004
|
+
return {
|
|
21005
|
+
ok: false,
|
|
21006
|
+
error: {
|
|
21007
|
+
code: reply.error.code === "foreign_session" ? "invalidRequest" : ["not_found", "stale"].includes(reply.error.code) ? "sessionNotFound" : "unavailable",
|
|
21008
|
+
message: reply.error.message,
|
|
21009
|
+
retryable: false
|
|
21010
|
+
}
|
|
21011
|
+
};
|
|
21012
|
+
return {
|
|
21013
|
+
ok: true,
|
|
21014
|
+
value: piSubagentSnapshot(parent.nativeSessionId, nativeSubagentId, reply)
|
|
21015
|
+
};
|
|
21016
|
+
} catch (error51) {
|
|
21017
|
+
return { ok: false, error: normalizedError(error51, "unavailable") };
|
|
21018
|
+
} finally {
|
|
21019
|
+
if (transport) {
|
|
21020
|
+
this.#inspections.delete(transport);
|
|
21021
|
+
await transport.close();
|
|
21022
|
+
}
|
|
21023
|
+
}
|
|
21024
|
+
}
|
|
21025
|
+
};
|
|
19874
21026
|
sessionImport = Object.freeze({
|
|
19875
21027
|
listCandidates: async () => {
|
|
19876
21028
|
const result = await this.#readImport((signal) => this.#importIndex.list(signal));
|
|
@@ -19906,6 +21058,19 @@ var PiAdapter = class {
|
|
|
19906
21058
|
constructor(options = {}, dependencies = {
|
|
19907
21059
|
createTransport: (sessionOptions) => new PiRpcSession({ ...options, ...sessionOptions })
|
|
19908
21060
|
}) {
|
|
21061
|
+
const imports = createPiCredentialImports(options);
|
|
21062
|
+
const updateCatalog = async (operation) => {
|
|
21063
|
+
await operation;
|
|
21064
|
+
this.#inspectionCache.clear();
|
|
21065
|
+
};
|
|
21066
|
+
this.credentialImports = {
|
|
21067
|
+
providers: imports.providers,
|
|
21068
|
+
list: () => imports.list(),
|
|
21069
|
+
listOthers: () => imports.listOthers?.() ?? Promise.resolve([]),
|
|
21070
|
+
add: (name, credential) => updateCatalog(imports.add(name, credential)),
|
|
21071
|
+
reimport: (name, credential) => updateCatalog(imports.reimport(name, credential)),
|
|
21072
|
+
remove: (name) => updateCatalog(imports.remove(name))
|
|
21073
|
+
};
|
|
19909
21074
|
this.#createTransport = dependencies.createTransport;
|
|
19910
21075
|
this.#importIndex = new PiSessionImportIndex({ ...process.env, ...options.environment });
|
|
19911
21076
|
this.#closeTimeoutMs = options.closeTimeoutMs ?? 2e3;
|
|
@@ -19983,7 +21148,8 @@ var PiAdapter = class {
|
|
|
19983
21148
|
permissionModeScope: "live"
|
|
19984
21149
|
},
|
|
19985
21150
|
history: { fork: true, forkAcrossCwd: true, rollbackLastTurn: true },
|
|
19986
|
-
autonomousTurns: { observe: true }
|
|
21151
|
+
autonomousTurns: { observe: true },
|
|
21152
|
+
subagents: { observe: true, readTranscript: true }
|
|
19987
21153
|
}
|
|
19988
21154
|
};
|
|
19989
21155
|
} catch (error51) {
|
|
@@ -20137,40 +21303,40 @@ var PiAdapter = class {
|
|
|
20137
21303
|
});
|
|
20138
21304
|
}
|
|
20139
21305
|
if (rolledBack.unpersisted) {
|
|
20140
|
-
const
|
|
21306
|
+
const state2 = transport.state;
|
|
20141
21307
|
const history = await transport.getEntries();
|
|
20142
21308
|
await transport.close();
|
|
20143
21309
|
await persistEmptyPiSession({
|
|
20144
|
-
state,
|
|
21310
|
+
state: state2,
|
|
20145
21311
|
history,
|
|
20146
21312
|
sourceSessionFile,
|
|
20147
21313
|
sourceSessionId: sourceRef.nativeSessionId,
|
|
20148
21314
|
cwd: input.cwd
|
|
20149
21315
|
});
|
|
20150
|
-
if (!
|
|
21316
|
+
if (!state2.sessionFile)
|
|
20151
21317
|
throw new Error("Pi empty fork has no Session file");
|
|
20152
|
-
const configuration = await readPiEmptySessionConfiguration(
|
|
21318
|
+
const configuration = await readPiEmptySessionConfiguration(state2.sessionFile);
|
|
20153
21319
|
if (!configuration)
|
|
20154
21320
|
throw new Error("Pi empty fork has no restorable configuration");
|
|
20155
21321
|
transport = this.#createTransport({
|
|
20156
21322
|
cwd: input.cwd,
|
|
20157
21323
|
...input.environment ? { environment: input.environment } : {},
|
|
20158
|
-
sessionFile:
|
|
21324
|
+
sessionFile: state2.sessionFile,
|
|
20159
21325
|
emptySessionConfiguration: configuration,
|
|
20160
21326
|
onFault: (error51) => session?.handleTransportFault(error51)
|
|
20161
21327
|
});
|
|
20162
21328
|
await transport.start();
|
|
20163
|
-
if (transport.state.sessionId !==
|
|
21329
|
+
if (transport.state.sessionId !== state2.sessionId) {
|
|
20164
21330
|
throw new Error("Pi empty fork resumed with a different identity");
|
|
20165
21331
|
}
|
|
20166
|
-
const model = nativeModelFromState(
|
|
21332
|
+
const model = nativeModelFromState(state2);
|
|
20167
21333
|
if (model && !samePiModel(nativeModelFromState(transport.state), model)) {
|
|
20168
21334
|
await transport.selectModel(model);
|
|
20169
21335
|
}
|
|
20170
|
-
if (
|
|
20171
|
-
await transport.selectThinkingOption(
|
|
21336
|
+
if (state2.thinkingLevel && transport.state.thinkingLevel !== state2.thinkingLevel) {
|
|
21337
|
+
await transport.selectThinkingOption(state2.thinkingLevel);
|
|
20172
21338
|
}
|
|
20173
|
-
if (!samePiModel(nativeModelFromState(transport.state), model) || transport.state.thinkingLevel !==
|
|
21339
|
+
if (!samePiModel(nativeModelFromState(transport.state), model) || transport.state.thinkingLevel !== state2.thinkingLevel) {
|
|
20174
21340
|
throw new Error("Pi empty fork could not restore its configuration");
|
|
20175
21341
|
}
|
|
20176
21342
|
await transport.verifySessionCwd(input.cwd);
|