pagegraph 0.14.1 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +169 -10
- package/dist/audit.d.ts +1 -1
- package/dist/audit.js +1 -1
- package/dist/{checks-BS-aDXB_.js → checks-BEhJPNzN.js} +12 -1
- package/dist/checks-BEhJPNzN.js.map +1 -0
- package/dist/{claims-Bch7Lxlo.d.ts → claims-CCf2_Jox.d.ts} +2 -2
- package/dist/{claims-Bv7voeEV.js → claims-CQlzze1K.js} +2 -2
- package/dist/{claims-Bv7voeEV.js.map → claims-CQlzze1K.js.map} +1 -1
- package/dist/claims.d.ts +2 -2
- package/dist/claims.js +1 -1
- package/dist/cli.js +1355 -616
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +7 -3
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/{content-CHd0X4s6.js → content-D5jZprMq.js} +2 -2
- package/dist/{content-CHd0X4s6.js.map → content-D5jZprMq.js.map} +1 -1
- package/dist/{content-DgNr7apS.d.ts → content-DerWgQy9.d.ts} +11 -3
- package/dist/{dist-cFoAzruL.js → dist-Br2oOB2Q.js} +2 -2
- package/dist/{dist-cFoAzruL.js.map → dist-Br2oOB2Q.js.map} +1 -1
- package/dist/{document-CztEu3Vd.d.ts → document-D9P8yY5g.d.ts} +4 -4
- package/dist/{graph-D1PIndsC.d.ts → graph-ChrvU-6X.d.ts} +27 -4
- package/dist/{graph-DMNOLXLu.js → graph-UONEaqIX.js} +43 -5
- package/dist/graph-UONEaqIX.js.map +1 -0
- package/dist/{index-C5w9ripz.d.ts → index-DzjUmbHY.d.ts} +5 -5
- package/dist/index.d.ts +6 -6
- package/dist/index.js +5 -6
- package/dist/index.js.map +1 -1
- package/dist/{page-heads-BfjWQvau.d.ts → page-heads-DDz_2_hq.d.ts} +3 -2
- package/dist/{page-heads-BgbaIjj9.js → page-heads-YL8nyYjF.js} +4 -3
- package/dist/page-heads-YL8nyYjF.js.map +1 -0
- package/dist/{pi-D3mMmYey.js → pi-Bz4BgZdC.js} +184 -154
- package/dist/pi-Bz4BgZdC.js.map +1 -0
- package/dist/{projections-Bk-qOOsR.d.ts → projections-Dqo_ih-J.d.ts} +2 -2
- package/dist/react.d.ts +5 -3
- package/dist/react.js +43 -19
- package/dist/react.js.map +1 -1
- package/dist/{state-BuJP_3Lr.js → state-2ikjo7uI.js} +638 -25
- package/dist/state-2ikjo7uI.js.map +1 -0
- package/dist/tanstack-start/index.d.ts +1 -1
- package/dist/tanstack-start/index.js +6 -4
- package/dist/tanstack-start/index.js.map +1 -1
- package/dist/tanstack-start/react.d.ts +1 -1
- package/dist/tanstack-start/server.d.ts +2 -2
- package/dist/tanstack-start/server.js +1 -1
- package/dist/tanstack-start/server.js.map +1 -1
- package/dist/{vite-graph-loader-DZCwejuJ.d.ts → vite-graph-loader-BtLgkN0V.d.ts} +7 -5
- package/package.json +1 -1
- package/dist/checks-BS-aDXB_.js.map +0 -1
- package/dist/declare-D5o7hwmv.js +0 -9
- package/dist/declare-D5o7hwmv.js.map +0 -1
- package/dist/graph-DMNOLXLu.js.map +0 -1
- package/dist/page-heads-BgbaIjj9.js.map +0 -1
- package/dist/pi-D3mMmYey.js.map +0 -1
- package/dist/state-BuJP_3Lr.js.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { n as __exportAll$1 } from "./rolldown-runtime-B-lAHAz2.js";
|
|
2
|
-
import {
|
|
2
|
+
import { An as fn, B as fromEnv, Bi as Service$1, E as resolveRepositoryReadPath, Ei as seconds, Er as withSpan, F as Redacted, Fn as gen, H as Boolean, I as String$2, It as make$1, K as Defect, L as all, Lt as value, Mn as forEach, On as fail, Or as effect, Qn as provide$1, R as option, S as normalizeEditPaths, Sn as catch_, Ti as minutes, Tt as optional, Un as map, V as ArraySchema, Wn as mapError, Xn as orElseSucceed, _ as prependUrl, _t as decodeUnknownEffect, a as layer$1, aa as none, ar as runPromise, at as NullOr, b as applyWorkflowEdits, br as tryPromise, c as mapRequest, dt as TaggedError, ei as findErrorOption, er as provideService, et as Literal, fr as succeed, g as post, gt as Unknown, h as get, ht as Union, i as salvageResearchState, ia as match, jr as provide, kn as flatMap, l as retryTransient, lt as String$1, m as bodyJsonUnsafe, n as dropNulls, na as isSome, ni as pretty, o as HttpClient, oa as some, or as runPromiseExit, ot as Number$1, qr as isSuccess, r as normalizeResearchState, sr as runSync, st as Record, t as decodeResearchState, tt as Literals, ut as Struct, v as setHeaders, x as decodeActionState, xi as format, y as actionStateJsonSchema, yr as timeoutOption, z as ConfigProvider } from "./state-2ikjo7uI.js";
|
|
3
3
|
import { a as ANTHROPIC_OAUTH_TOKEN_ENV, c as ANTHROPIC_WORKSPACE_ID_ENV, i as ANTHROPIC_IDENTITY_TOKEN_FILE_ENV, l as findEnvKeys, n as ANTHROPIC_AUTH_TOKEN_ENV, o as ANTHROPIC_ORGANIZATION_ID_ENV, r as ANTHROPIC_FEDERATION_RULE_ID_ENV, s as ANTHROPIC_SERVICE_ACCOUNT_ID_ENV, t as ANTHROPIC_API_KEY_ENV, u as getEnvApiKey } from "./env-api-keys-C-OA0yM-.js";
|
|
4
4
|
import { D as lazyApi, _ as normalizeContext, b as toToolDeclaration, d as getCurrentTools, i as createProvider, l as getCurrentSystemMessage, m as getToolStateChanges, r as createModels, s as createInitialSystemMessage, u as getCurrentSystemPrompt } from "./models-DcT5qOEL.js";
|
|
5
|
-
import { $ as Ref$1, A as Literal$1, At as IsNumber$1, B as Intersect, Bt as SomeAll$1, C as Number$2, Ct as IsInteger$1, D as IsLiteralBoolean, Dt as IsMinLength$2, E as IsLiteralBigInt, Et as IsMaxLength$2, F as IsBigInt$2, Ft as IsUndefined$1, G as IsCyclic, H as IsEnum$1, I as IsCodec, It as IsUnsafePropertyKey, J as _Object_, K as Unknown$1, L as Hash, Lt as IsValueLike, M as IsInteger$2, Mt as IsObjectNotArray$1, N as Boolean$1, Nt as IsString$1, O as IsLiteralNumber, Ot as IsMultipleOf$1, P as IsBoolean$2, Pt as IsSymbol$1, Q as IsRef$1, R as hash_exports, Rt as Keys$1, S as IsNumber$2, St as IsGreaterThan$1, T as IsLiteral, Tt as IsLessThan$1, U as Match$1, V as IsIntersect, Vt as guard_exports, W as Unsafe, X as Optional, Y as IsOptional, Z as IsNever, _ as IsUnion, _t as IsConstructor$1, a as With, at as IsSchema$1, b as String$3, bt as IsFunction$1, c as IsUndefined$2, ct as Counted$1, d as RecordKey, dt as Every$1, et as IsFunction$2, f as RecordPattern, ft as EveryAll, g as TemplateLiteralDecode, gt as IsBoolean$1, h as Tuple, ht as IsBigInt$1, i as Instantiate, it as _Array_, j as Integer, jt as IsObject$1, k as IsLiteralString, kt as IsNull$1, l as IsRecord, lt as Entries$2, m as IsTuple, mt as IsArray$1, n as Priority, nt as ArrayOptions, o as IsTemplateLiteral, ot as Clone$1, p as RecordValue, pt as HasPropertyKey$1, q as IsObject$2, r as Evaluate$1, rt as IsArray$2, s as IsVoid, st as Get$3, tt as IsConstructor$2, u as Record$1, ut as EntriesRegExp, v as Union$1, vt as IsDeepEqual$1, w as IsNull$2, wt as IsLessEqualThan$1, x as IsSymbol$2, xt as IsGreaterEqualThan$1, y as IsString$2, yt as IsEqual$1, z as Unreachable, zt as Some$1 } from "./dist-
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
5
|
+
import { $ as Ref$1, A as Literal$1, At as IsNumber$1, B as Intersect, Bt as SomeAll$1, C as Number$2, Ct as IsInteger$1, D as IsLiteralBoolean, Dt as IsMinLength$2, E as IsLiteralBigInt, Et as IsMaxLength$2, F as IsBigInt$2, Ft as IsUndefined$1, G as IsCyclic, H as IsEnum$1, I as IsCodec, It as IsUnsafePropertyKey, J as _Object_, K as Unknown$1, L as Hash, Lt as IsValueLike, M as IsInteger$2, Mt as IsObjectNotArray$1, N as Boolean$1, Nt as IsString$1, O as IsLiteralNumber, Ot as IsMultipleOf$1, P as IsBoolean$2, Pt as IsSymbol$1, Q as IsRef$1, R as hash_exports, Rt as Keys$1, S as IsNumber$2, St as IsGreaterThan$1, T as IsLiteral, Tt as IsLessThan$1, U as Match$1, V as IsIntersect, Vt as guard_exports, W as Unsafe, X as Optional, Y as IsOptional, Z as IsNever, _ as IsUnion, _t as IsConstructor$1, a as With, at as IsSchema$1, b as String$3, bt as IsFunction$1, c as IsUndefined$2, ct as Counted$1, d as RecordKey, dt as Every$1, et as IsFunction$2, f as RecordPattern, ft as EveryAll, g as TemplateLiteralDecode, gt as IsBoolean$1, h as Tuple, ht as IsBigInt$1, i as Instantiate, it as _Array_, j as Integer, jt as IsObject$1, k as IsLiteralString, kt as IsNull$1, l as IsRecord, lt as Entries$2, m as IsTuple, mt as IsArray$1, n as Priority, nt as ArrayOptions, o as IsTemplateLiteral, ot as Clone$1, p as RecordValue, pt as HasPropertyKey$1, q as IsObject$2, r as Evaluate$1, rt as IsArray$2, s as IsVoid, st as Get$3, tt as IsConstructor$2, u as Record$1, ut as EntriesRegExp, v as Union$1, vt as IsDeepEqual$1, w as IsNull$2, wt as IsLessEqualThan$1, x as IsSymbol$2, xt as IsGreaterEqualThan$1, y as IsString$2, yt as IsEqual$1, z as Unreachable, zt as Some$1 } from "./dist-Br2oOB2Q.js";
|
|
6
|
+
import { relative, resolve } from "node:path";
|
|
7
|
+
import { mkdir, open, readFile, readdir, realpath, writeFile } from "node:fs/promises";
|
|
8
8
|
//#region node_modules/typebox/build/guard/emit.mjs
|
|
9
9
|
const identifierRegExp = /^[\p{ID_Start}_$][\p{ID_Continue}_$\u200C\u200D]*$/u;
|
|
10
10
|
/** Returns true if this value is a valid JavaScript identifier */
|
|
@@ -56321,6 +56321,34 @@ const executorTools = (options) => [{
|
|
|
56321
56321
|
}];
|
|
56322
56322
|
//#endregion
|
|
56323
56323
|
//#region src/workflows/executor.ts
|
|
56324
|
+
/** Retains complete Executor outcomes even when the model-facing preview is truncated. */
|
|
56325
|
+
const persistExecutorToolResults = (toolset, runDirectory) => {
|
|
56326
|
+
const directory = resolve(runDirectory, "tool-results");
|
|
56327
|
+
let sequence;
|
|
56328
|
+
return {
|
|
56329
|
+
trace: toolset.trace,
|
|
56330
|
+
tools: toolset.tools.map((tool) => tool.name !== "executor_execute" ? tool : {
|
|
56331
|
+
...tool,
|
|
56332
|
+
execute: async (...args) => {
|
|
56333
|
+
const result = await tool.execute(...args);
|
|
56334
|
+
await mkdir(directory, { recursive: true });
|
|
56335
|
+
if (sequence === void 0) {
|
|
56336
|
+
const entries = await readdir(directory);
|
|
56337
|
+
sequence = Math.max(0, ...entries.flatMap((name) => /^\d+\.json$/.test(name) ? [Number(name.slice(0, -5))] : []));
|
|
56338
|
+
}
|
|
56339
|
+
const path = resolve(directory, `${++sequence}.json`);
|
|
56340
|
+
await writeFile(path, JSON.stringify(result.details ?? null, null, 2) + "\n", { flag: "wx" });
|
|
56341
|
+
return result.content.some((part) => part.type === "text" && /\[truncated \d+ chars\]/.test(part.text)) ? {
|
|
56342
|
+
...result,
|
|
56343
|
+
content: [...result.content, {
|
|
56344
|
+
type: "text",
|
|
56345
|
+
text: `Full Executor result: ${path}. Use read_file to read it; paginate with offset and maxBytes when needed.`
|
|
56346
|
+
}]
|
|
56347
|
+
} : result;
|
|
56348
|
+
}
|
|
56349
|
+
})
|
|
56350
|
+
};
|
|
56351
|
+
};
|
|
56324
56352
|
const executionEvidence = (record) => {
|
|
56325
56353
|
if (record.isError) return void 0;
|
|
56326
56354
|
const succeeded = (record.toolCalls ?? []).filter((call) => !call.isError).map((call) => call.path);
|
|
@@ -56368,74 +56396,15 @@ const repositoryToolNames = /* @__PURE__ */ new Set([
|
|
|
56368
56396
|
"list_files",
|
|
56369
56397
|
"search_text"
|
|
56370
56398
|
]);
|
|
56371
|
-
const writeToolNames = /* @__PURE__ */ new Set(["write_file", "edit_file"]);
|
|
56372
|
-
const missingPath = (cause) => cause instanceof Error && "code" in cause && cause.code === "ENOENT";
|
|
56373
|
-
const resolveWritablePath = async (path) => {
|
|
56374
|
-
let ancestor = path;
|
|
56375
|
-
const suffix = [];
|
|
56376
|
-
while (true) try {
|
|
56377
|
-
return resolve(await realpath(ancestor), ...suffix);
|
|
56378
|
-
} catch (cause) {
|
|
56379
|
-
if (!missingPath(cause)) throw cause;
|
|
56380
|
-
try {
|
|
56381
|
-
if ((await lstat(ancestor)).isSymbolicLink()) throw new Error(`Repository path has a dangling symlink: ${path}`);
|
|
56382
|
-
} catch (statCause) {
|
|
56383
|
-
if (!missingPath(statCause)) throw statCause;
|
|
56384
|
-
}
|
|
56385
|
-
const parent = dirname(ancestor);
|
|
56386
|
-
if (parent === ancestor) throw cause;
|
|
56387
|
-
suffix.unshift(relative(parent, ancestor));
|
|
56388
|
-
ancestor = parent;
|
|
56389
|
-
}
|
|
56390
|
-
};
|
|
56391
|
-
const writableRepositoryPath = async (root, path, options) => {
|
|
56392
|
-
const projectRoot = await realpath(root);
|
|
56393
|
-
const requested = resolve(projectRoot, path);
|
|
56394
|
-
if (!insideRoot(projectRoot, requested)) throw new Error(`Repository path escapes project root: ${path}`);
|
|
56395
|
-
const resolved = await resolveWritablePath(requested);
|
|
56396
|
-
if (!insideRoot(projectRoot, resolved)) throw new Error(`Repository path escapes project root through a symlink: ${path}`);
|
|
56397
|
-
if ([requested, resolved].some((target) => relative(projectRoot, target).split(sep).some((part) => part === ".git" || part === "node_modules"))) throw new Error(`Repository write targets a protected directory: ${path}`);
|
|
56398
|
-
const forbidden = [
|
|
56399
|
-
resolve(projectRoot, ".git"),
|
|
56400
|
-
resolve(projectRoot, "node_modules"),
|
|
56401
|
-
resolve(projectRoot, options.runsDirectory),
|
|
56402
|
-
resolve(projectRoot, options.presetDirectory)
|
|
56403
|
-
];
|
|
56404
|
-
for (const directory of forbidden) {
|
|
56405
|
-
const actual = await resolveWritablePath(directory);
|
|
56406
|
-
if (insideRoot(directory, requested) || insideRoot(actual, resolved)) throw new Error(`Repository write targets a protected directory: ${path}`);
|
|
56407
|
-
}
|
|
56408
|
-
const existing = await lstat(resolved).catch((error) => {
|
|
56409
|
-
if (error instanceof Error && "code" in error && error.code === "ENOENT") return void 0;
|
|
56410
|
-
throw error;
|
|
56411
|
-
});
|
|
56412
|
-
if (existing !== void 0 && existing.nlink > 1) throw new Error(`Repository write targets a hard-linked file: ${path}`);
|
|
56413
|
-
return resolved;
|
|
56414
|
-
};
|
|
56415
|
-
const insideRoot = (root, path) => {
|
|
56416
|
-
const pathFromRoot = relative(root, path);
|
|
56417
|
-
return pathFromRoot !== ".." && !pathFromRoot.startsWith(`..${sep}`) && !isAbsolute(pathFromRoot);
|
|
56418
|
-
};
|
|
56419
|
-
const repositoryPath = async (root, path) => {
|
|
56420
|
-
const projectRoot = await realpath(root);
|
|
56421
|
-
const requested = resolve(projectRoot, path);
|
|
56422
|
-
if (!insideRoot(projectRoot, requested) && !insideRoot(resolve(root), requested)) throw new Error(`Repository path escapes project root: ${path}`);
|
|
56423
|
-
const resolved = await realpath(requested);
|
|
56424
|
-
if (!insideRoot(projectRoot, resolved)) throw new Error(`Repository path escapes project root through a symlink: ${path}`);
|
|
56425
|
-
return resolved;
|
|
56426
|
-
};
|
|
56427
56399
|
const pathArgument = (args) => {
|
|
56428
56400
|
if (typeof args !== "object" || args === null || !("path" in args) || typeof args.path !== "string") throw new Error("Repository tools require a string path");
|
|
56429
56401
|
return args.path;
|
|
56430
56402
|
};
|
|
56431
|
-
const guardRepositoryToolCall = (root,
|
|
56432
|
-
if (!repositoryToolNames.has(toolCall.name)
|
|
56403
|
+
const guardRepositoryToolCall = (root, readOptions) => async ({ toolCall, args }, signal) => {
|
|
56404
|
+
if (!repositoryToolNames.has(toolCall.name)) return void 0;
|
|
56433
56405
|
try {
|
|
56434
56406
|
signal?.throwIfAborted();
|
|
56435
|
-
|
|
56436
|
-
if (!writeOptions) throw new Error("Repository writes are unavailable in this workflow phase");
|
|
56437
|
-
await writableRepositoryPath(root, pathArgument(args), writeOptions);
|
|
56438
|
-
} else await repositoryPath(root, pathArgument(args));
|
|
56407
|
+
await resolveRepositoryReadPath(readOptions?.repositoryRoot ?? root, pathArgument(args), readOptions);
|
|
56439
56408
|
return;
|
|
56440
56409
|
} catch (error) {
|
|
56441
56410
|
return {
|
|
@@ -56444,15 +56413,20 @@ const guardRepositoryToolCall = (root, writeOptions) => async ({ toolCall, args
|
|
|
56444
56413
|
};
|
|
56445
56414
|
}
|
|
56446
56415
|
};
|
|
56447
|
-
const readBoundedFile = async (path, signal) => {
|
|
56416
|
+
const readBoundedFile = async (path, signal, offset = 0, maxBytes = MAX_FILE_BYTES) => {
|
|
56448
56417
|
signal?.throwIfAborted();
|
|
56449
56418
|
const file = await open(path, "r");
|
|
56450
56419
|
try {
|
|
56451
56420
|
if (!(await file.stat()).isFile()) throw new Error(`Repository path is not a regular file: ${path}`);
|
|
56452
|
-
const buffer = Buffer.alloc(
|
|
56453
|
-
const { bytesRead } = await file.read(buffer, 0, buffer.length,
|
|
56421
|
+
const buffer = Buffer.alloc(maxBytes + 1);
|
|
56422
|
+
const { bytesRead } = await file.read(buffer, 0, buffer.length, offset);
|
|
56454
56423
|
signal?.throwIfAborted();
|
|
56455
|
-
|
|
56424
|
+
let consumed = Math.min(bytesRead, maxBytes);
|
|
56425
|
+
if (bytesRead > maxBytes) {
|
|
56426
|
+
while (consumed > 0 && (buffer[consumed] & 192) === 128) consumed--;
|
|
56427
|
+
if (consumed === 0) throw new Error("read_file maxBytes cannot fit the next UTF-8 character; increase maxBytes");
|
|
56428
|
+
}
|
|
56429
|
+
return buffer.subarray(0, consumed).toString("utf8") + (bytesRead > maxBytes ? `\n[File truncated; continue with read_file offset=${offset + consumed}]` : "");
|
|
56456
56430
|
} finally {
|
|
56457
56431
|
await file.close();
|
|
56458
56432
|
}
|
|
@@ -56464,14 +56438,14 @@ const result = (text) => ({
|
|
|
56464
56438
|
}],
|
|
56465
56439
|
details: void 0
|
|
56466
56440
|
});
|
|
56467
|
-
const discoverFiles = async (root, directory, recursive, signal) => {
|
|
56441
|
+
const discoverFiles = async (root, directory, recursive, signal, options) => {
|
|
56468
56442
|
const files = [];
|
|
56469
56443
|
const pending = [directory];
|
|
56470
56444
|
let inspected = 0;
|
|
56471
56445
|
while (pending.length > 0 && inspected < MAX_ENTRIES) {
|
|
56472
56446
|
signal?.throwIfAborted();
|
|
56473
56447
|
const next = pending.shift();
|
|
56474
|
-
const entries = (await readdir(await
|
|
56448
|
+
const entries = (await readdir(await resolveRepositoryReadPath(root, next, options), { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name));
|
|
56475
56449
|
for (const entry of entries) {
|
|
56476
56450
|
if (++inspected > MAX_ENTRIES) break;
|
|
56477
56451
|
const path = resolve(next, entry.name);
|
|
@@ -56481,13 +56455,26 @@ const discoverFiles = async (root, directory, recursive, signal) => {
|
|
|
56481
56455
|
}
|
|
56482
56456
|
return files;
|
|
56483
56457
|
};
|
|
56484
|
-
const
|
|
56458
|
+
const byteArgument = (args, key, fallback, minimum, maximum) => {
|
|
56459
|
+
const value = typeof args === "object" && args !== null ? Reflect.get(args, key) : void 0;
|
|
56460
|
+
if (value === void 0) return fallback;
|
|
56461
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < minimum || value > maximum) throw new Error(`read_file ${key} must be an integer between ${minimum} and ${maximum}`);
|
|
56462
|
+
return value;
|
|
56463
|
+
};
|
|
56464
|
+
const createRepositoryTools = (root, options = {}) => [
|
|
56485
56465
|
{
|
|
56486
56466
|
name: "read_file",
|
|
56487
56467
|
label: "Read repository file",
|
|
56488
|
-
description: "Read a UTF-8 file
|
|
56489
|
-
parameters: _Object_({
|
|
56490
|
-
|
|
56468
|
+
description: "Read a UTF-8 repository or run-artifact file. offset is a byte offset (default 0); maxBytes is at most 65536. A truncated page tells you the next offset.",
|
|
56469
|
+
parameters: _Object_({
|
|
56470
|
+
path: String$3(),
|
|
56471
|
+
offset: Optional(Integer({ minimum: 0 })),
|
|
56472
|
+
maxBytes: Optional(Integer({
|
|
56473
|
+
minimum: 1,
|
|
56474
|
+
maximum: MAX_FILE_BYTES
|
|
56475
|
+
}))
|
|
56476
|
+
}),
|
|
56477
|
+
execute: async (_id, args, signal) => result(await readBoundedFile(await resolveRepositoryReadPath(root, pathArgument(args), options), signal, byteArgument(args, "offset", 0, 0, Number.MAX_SAFE_INTEGER), byteArgument(args, "maxBytes", MAX_FILE_BYTES, 1, MAX_FILE_BYTES)))
|
|
56491
56478
|
},
|
|
56492
56479
|
{
|
|
56493
56480
|
name: "list_files",
|
|
@@ -56502,8 +56489,8 @@ const createRepositoryTools = (root) => [
|
|
|
56502
56489
|
const recursive = typeof args === "object" && args !== null && "recursive" in args ? args.recursive : false;
|
|
56503
56490
|
if (typeof recursive !== "boolean") throw new Error("list_files recursive must be a boolean");
|
|
56504
56491
|
const projectRoot = await realpath(root);
|
|
56505
|
-
const directory = await
|
|
56506
|
-
const files = await discoverFiles(root, directory, recursive, signal);
|
|
56492
|
+
const directory = await resolveRepositoryReadPath(root, path, options);
|
|
56493
|
+
const files = await discoverFiles(root, directory, recursive, signal, options);
|
|
56507
56494
|
return result(files.map((file) => relative(projectRoot, file)).join("\n").slice(0, MAX_OUTPUT_CHARACTERS));
|
|
56508
56495
|
}
|
|
56509
56496
|
},
|
|
@@ -56520,11 +56507,11 @@ const createRepositoryTools = (root) => [
|
|
|
56520
56507
|
const text = typeof args === "object" && args !== null && "text" in args ? args.text : void 0;
|
|
56521
56508
|
if (typeof text !== "string" || text.length === 0) throw new Error("search_text requires nonempty literal text");
|
|
56522
56509
|
const projectRoot = await realpath(root);
|
|
56523
|
-
const directory = await
|
|
56524
|
-
const files = await discoverFiles(root, directory, true, signal);
|
|
56510
|
+
const directory = await resolveRepositoryReadPath(root, path, options);
|
|
56511
|
+
const files = await discoverFiles(root, directory, true, signal, options);
|
|
56525
56512
|
const matches = [];
|
|
56526
56513
|
for (const file of files) {
|
|
56527
|
-
const content = await readBoundedFile(await
|
|
56514
|
+
const content = await readBoundedFile(await resolveRepositoryReadPath(root, file, options), signal);
|
|
56528
56515
|
if (content.includes("\0")) continue;
|
|
56529
56516
|
for (const [index, line] of content.split("\n").entries()) {
|
|
56530
56517
|
if (line.includes(text)) matches.push(`${relative(projectRoot, file)}:${index + 1}:${line}`);
|
|
@@ -56536,51 +56523,6 @@ const createRepositoryTools = (root) => [
|
|
|
56536
56523
|
}
|
|
56537
56524
|
}
|
|
56538
56525
|
];
|
|
56539
|
-
const stringArgument = (args, key) => {
|
|
56540
|
-
if (typeof args !== "object" || args === null || !(key in args) || typeof Reflect.get(args, key) !== "string") throw new Error(`Repository tools require a string ${key}`);
|
|
56541
|
-
return Reflect.get(args, key);
|
|
56542
|
-
};
|
|
56543
|
-
const createRepositoryWriteTools = (root, options) => [{
|
|
56544
|
-
name: "write_file",
|
|
56545
|
-
label: "Write repository file",
|
|
56546
|
-
description: "Create or overwrite a UTF-8 repository file. Protected directories and symlink escapes are blocked.",
|
|
56547
|
-
parameters: _Object_({
|
|
56548
|
-
path: String$3(),
|
|
56549
|
-
content: String$3()
|
|
56550
|
-
}),
|
|
56551
|
-
execute: async (_id, args, signal) => {
|
|
56552
|
-
signal?.throwIfAborted();
|
|
56553
|
-
const requested = pathArgument(args);
|
|
56554
|
-
const path = await writableRepositoryPath(root, requested, options);
|
|
56555
|
-
await mkdir(dirname(path), { recursive: true });
|
|
56556
|
-
signal?.throwIfAborted();
|
|
56557
|
-
await writeFile(await writableRepositoryPath(root, pathArgument(args), options), stringArgument(args, "content"), "utf8");
|
|
56558
|
-
return result(`Wrote ${pathArgument(args)}`);
|
|
56559
|
-
}
|
|
56560
|
-
}, {
|
|
56561
|
-
name: "edit_file",
|
|
56562
|
-
label: "Edit repository file",
|
|
56563
|
-
description: "Replace exact text in a UTF-8 repository file. oldText must match exactly one region; protected directories and symlink escapes are blocked.",
|
|
56564
|
-
parameters: _Object_({
|
|
56565
|
-
path: String$3(),
|
|
56566
|
-
oldText: String$3({ minLength: 1 }),
|
|
56567
|
-
newText: String$3()
|
|
56568
|
-
}),
|
|
56569
|
-
execute: async (_id, args, signal) => {
|
|
56570
|
-
signal?.throwIfAborted();
|
|
56571
|
-
const oldText = stringArgument(args, "oldText");
|
|
56572
|
-
const newText = stringArgument(args, "newText");
|
|
56573
|
-
if (oldText.length === 0) throw new Error("edit_file oldText must be nonempty");
|
|
56574
|
-
const requested = pathArgument(args);
|
|
56575
|
-
const path = await writableRepositoryPath(root, requested, options);
|
|
56576
|
-
const content = await readFile(path, "utf8");
|
|
56577
|
-
const index = content.indexOf(oldText);
|
|
56578
|
-
if (index < 0 || content.indexOf(oldText, index + 1) >= 0) throw new Error("edit_file oldText must match exactly once");
|
|
56579
|
-
signal?.throwIfAborted();
|
|
56580
|
-
await writeFile(await writableRepositoryPath(root, pathArgument(args), options), content.slice(0, index) + newText + content.slice(index + oldText.length), "utf8");
|
|
56581
|
-
return result(`Edited ${pathArgument(args)}`);
|
|
56582
|
-
}
|
|
56583
|
-
}];
|
|
56584
56526
|
//#endregion
|
|
56585
56527
|
//#region src/workflows/pi.ts
|
|
56586
56528
|
const MAX_REJECTED_SUBMISSIONS = 3;
|
|
@@ -56642,36 +56584,97 @@ var WorkflowRunnerError = class extends Error {
|
|
|
56642
56584
|
};
|
|
56643
56585
|
const createPiRunner = (options) => {
|
|
56644
56586
|
let agent;
|
|
56645
|
-
let researched =
|
|
56646
|
-
|
|
56587
|
+
let researched = options.resume?.phase === "action";
|
|
56588
|
+
let resume = options.resume;
|
|
56589
|
+
const priorEvidence = options.resume?.executor;
|
|
56590
|
+
const evidence = () => {
|
|
56591
|
+
const current = executorEvidence(options.executor.trace);
|
|
56592
|
+
return priorEvidence === void 0 ? current : {
|
|
56593
|
+
searches: [...priorEvidence.searches, ...current.searches],
|
|
56594
|
+
calls: [...priorEvidence.calls, ...current.calls]
|
|
56595
|
+
};
|
|
56596
|
+
};
|
|
56597
|
+
const replayTools = options.executor.tools.map((tool) => ({
|
|
56598
|
+
...tool,
|
|
56599
|
+
execute: async (id, params, signal, onUpdate) => {
|
|
56600
|
+
if (priorEvidence !== void 0 && typeof params === "object" && params !== null) {
|
|
56601
|
+
const recorded = tool.name === "executor_execute" && "code" in params ? priorEvidence.calls.findLast((call) => typeof call.input === "object" && call.input !== null && "code" in call.input && call.input.code === params.code) : tool.name === "executor_search" && "query" in params ? priorEvidence.searches.findLast((call) => typeof call.input === "object" && call.input !== null && "query" in call.input && call.input.query === params.query) : void 0;
|
|
56602
|
+
if (recorded !== void 0) {
|
|
56603
|
+
const text = JSON.stringify(recorded.output) ?? "null";
|
|
56604
|
+
return {
|
|
56605
|
+
content: [{
|
|
56606
|
+
type: "text",
|
|
56607
|
+
text: `Recorded completed Executor result (reused without a provider call):\n${text.length > 3e4 ? `${text.slice(0, 3e4)}... [truncated ${text.length - 3e4} chars]` : text}`
|
|
56608
|
+
}],
|
|
56609
|
+
details: recorded.output
|
|
56610
|
+
};
|
|
56611
|
+
}
|
|
56612
|
+
}
|
|
56613
|
+
return tool.execute(id, params, signal, onUpdate);
|
|
56614
|
+
}
|
|
56615
|
+
}));
|
|
56616
|
+
const executor = options.runDirectory === void 0 ? {
|
|
56617
|
+
...options.executor,
|
|
56618
|
+
tools: replayTools
|
|
56619
|
+
} : persistExecutorToolResults({
|
|
56620
|
+
...options.executor,
|
|
56621
|
+
tools: replayTools
|
|
56622
|
+
}, options.runDirectory);
|
|
56623
|
+
const writeOptions = {
|
|
56624
|
+
presetDirectory: options.presetDirectory,
|
|
56625
|
+
runsDirectory: options.runsDirectory ?? resolve(options.root, ".pagegraph/runs")
|
|
56626
|
+
};
|
|
56627
|
+
const readOptions = {
|
|
56628
|
+
repositoryRoot: options.repositoryRoot ?? options.root,
|
|
56629
|
+
runsDirectory: options.runsDirectory ?? resolve(options.root, ".pagegraph/runs")
|
|
56630
|
+
};
|
|
56631
|
+
const phase = async (spec, prompt, signal, action = false) => {
|
|
56647
56632
|
const assertDeadline = (messages = []) => {
|
|
56648
56633
|
if (signal.aborted) throw new WorkflowRunnerError(`Workflow deadline exceeded or run aborted: ${String(signal.reason)}`, {
|
|
56649
56634
|
messages,
|
|
56650
56635
|
usage: totalUsage(messages),
|
|
56651
|
-
executor:
|
|
56636
|
+
executor: evidence()
|
|
56652
56637
|
}, { cause: signal.reason });
|
|
56653
56638
|
};
|
|
56654
56639
|
assertDeadline(agent?.state.messages);
|
|
56655
|
-
if (
|
|
56656
|
-
const systemPrompt =
|
|
56640
|
+
if (action && !researched) throw new Error("Workflow action requires a completed research conversation");
|
|
56641
|
+
const systemPrompt = !action || agent === void 0 ? await composeSystemPrompt(options.presetDirectory, spec) : void 0;
|
|
56657
56642
|
assertDeadline();
|
|
56643
|
+
const validateAction = async (raw) => {
|
|
56644
|
+
const state = normalizeEditPaths(decodeActionState(dropNulls(raw)), readOptions.repositoryRoot, options.root);
|
|
56645
|
+
const refused = (await applyWorkflowEdits(options.root, state.edits.map((edit, index) => ({
|
|
56646
|
+
id: `edits[${index}]`,
|
|
56647
|
+
...edit
|
|
56648
|
+
})), {
|
|
56649
|
+
...writeOptions,
|
|
56650
|
+
check: true
|
|
56651
|
+
})).filter((outcome) => outcome.status !== "applicable");
|
|
56652
|
+
if (refused.length > 0) throw new Error(`Edits must apply to the current files:\n${refused.map((outcome) => `${outcome.id} (${outcome.path}): ${outcome.status}, ${outcome.reason}`).join("\n")}\nCopy oldText exactly from a fresh read_file result, with enough context to match once.`);
|
|
56653
|
+
return state;
|
|
56654
|
+
};
|
|
56658
56655
|
let state;
|
|
56659
56656
|
let submitted = false;
|
|
56660
56657
|
let rejected = 0;
|
|
56661
56658
|
let lastIssues = "No structured result was submitted.";
|
|
56659
|
+
let lastSubmission;
|
|
56660
|
+
let rejectedItems;
|
|
56662
56661
|
const rawSubmissions = /* @__PURE__ */ new Map();
|
|
56663
56662
|
const submit = {
|
|
56664
56663
|
name: "submit_result",
|
|
56665
56664
|
label: "Submit workflow result",
|
|
56666
56665
|
description: "Validate and submit the final workflow state after collecting Executor evidence.",
|
|
56667
|
-
parameters: Unsafe(
|
|
56668
|
-
prepareArguments: (args) =>
|
|
56666
|
+
parameters: Unsafe(action ? actionStateJsonSchema : spec.stateJsonSchema),
|
|
56667
|
+
prepareArguments: (args) => {
|
|
56668
|
+
lastSubmission = args;
|
|
56669
|
+
return action ? dropNulls(args) : normalizeResearchState(args, options.limit);
|
|
56670
|
+
},
|
|
56669
56671
|
execute: async (_id, params) => {
|
|
56670
56672
|
try {
|
|
56671
|
-
const
|
|
56672
|
-
const
|
|
56673
|
-
|
|
56674
|
-
|
|
56673
|
+
const raw = rawSubmissions.get(_id) ?? lastSubmission ?? params;
|
|
56674
|
+
const decoded = action ? await validateAction(raw) : decodeResearchState(spec, raw, options.limit);
|
|
56675
|
+
const collected = evidence();
|
|
56676
|
+
if (!action && (collected.searches.length === 0 || collected.calls.length === 0)) throw new Error([
|
|
56677
|
+
`Your research returned without completed Executor provider evidence (searches: ${collected.searches.length}, calls: ${collected.calls.length}).`,
|
|
56675
56678
|
"Catalog searches and schema discovery alone do not satisfy this workflow.",
|
|
56676
56679
|
"Use the catalog results already collected, inspect the exact discovered tool schema, and complete at least one relevant read-only provider call before submitting the original workflow state.",
|
|
56677
56680
|
"Preserve provider errors and empty datasets honestly; do not invent evidence or mutate provider state."
|
|
@@ -56700,29 +56703,26 @@ const createPiRunner = (options) => {
|
|
|
56700
56703
|
}
|
|
56701
56704
|
}
|
|
56702
56705
|
};
|
|
56703
|
-
const writeOptions = {
|
|
56704
|
-
presetDirectory: options.presetDirectory,
|
|
56705
|
-
runsDirectory: options.runsDirectory ?? resolve(options.root, ".pagegraph/runs")
|
|
56706
|
-
};
|
|
56707
56706
|
const tools = [
|
|
56708
|
-
...
|
|
56709
|
-
...createRepositoryTools(
|
|
56707
|
+
...executor.tools,
|
|
56708
|
+
...createRepositoryTools(readOptions.repositoryRoot, readOptions),
|
|
56710
56709
|
...options.additionalTools ?? [],
|
|
56711
|
-
...mode === "write" ? createRepositoryWriteTools(options.root, writeOptions) : [],
|
|
56712
56710
|
submit
|
|
56713
56711
|
];
|
|
56714
56712
|
if (systemPrompt !== void 0) {
|
|
56715
|
-
researched = false;
|
|
56713
|
+
if (!action) researched = false;
|
|
56716
56714
|
agent = new Agent({
|
|
56717
56715
|
initialState: {
|
|
56718
56716
|
systemPrompt,
|
|
56719
56717
|
model: options.model,
|
|
56720
|
-
tools
|
|
56718
|
+
tools,
|
|
56719
|
+
...resume === void 0 ? {} : { messages: [...resume.agent.messages] }
|
|
56721
56720
|
},
|
|
56722
56721
|
streamFn: options.streamFn ?? streamSimple,
|
|
56723
56722
|
getApiKey: getEnvApiKey,
|
|
56724
56723
|
toolExecution: "sequential"
|
|
56725
56724
|
});
|
|
56725
|
+
resume = void 0;
|
|
56726
56726
|
}
|
|
56727
56727
|
if (!agent) throw new Error("Workflow action requires a research conversation");
|
|
56728
56728
|
agent.state.tools = tools;
|
|
@@ -56733,7 +56733,7 @@ const createPiRunner = (options) => {
|
|
|
56733
56733
|
terminate: true
|
|
56734
56734
|
};
|
|
56735
56735
|
if (context.toolCall.name === "submit_result") rawSubmissions.set(context.toolCall.id, context.toolCall.arguments);
|
|
56736
|
-
return guardRepositoryToolCall(options.root,
|
|
56736
|
+
return guardRepositoryToolCall(options.root, readOptions)?.(context, signal);
|
|
56737
56737
|
};
|
|
56738
56738
|
agent.finishTurn = () => submitted || rejected >= MAX_REJECTED_SUBMISSIONS ? { action: "end" } : void 0;
|
|
56739
56739
|
const current = agent;
|
|
@@ -56751,15 +56751,30 @@ const createPiRunner = (options) => {
|
|
|
56751
56751
|
const result = {
|
|
56752
56752
|
messages: current.state.messages,
|
|
56753
56753
|
usage: totalUsage(current.state.messages),
|
|
56754
|
-
executor:
|
|
56754
|
+
executor: evidence()
|
|
56755
56755
|
};
|
|
56756
56756
|
if (signal.aborted) throw new WorkflowRunnerError(`Workflow deadline exceeded or run aborted: ${String(signal.reason)}`, result, { cause: signal.reason });
|
|
56757
|
+
if (!submitted && !action && rejected >= MAX_REJECTED_SUBMISSIONS && result.executor.searches.length > 0 && result.executor.calls.length > 0) try {
|
|
56758
|
+
const salvaged = salvageResearchState(spec, lastSubmission, options.limit);
|
|
56759
|
+
state = salvaged.state;
|
|
56760
|
+
rejectedItems = salvaged.rejectedItems;
|
|
56761
|
+
submitted = true;
|
|
56762
|
+
} catch {}
|
|
56757
56763
|
if (!submitted) throw new WorkflowRunnerError(`Workflow result rejected: ${lastIssues}${current.state.errorMessage ? `\n${current.state.errorMessage}` : ""}`, result);
|
|
56758
|
-
if (
|
|
56764
|
+
if (!action) researched = true;
|
|
56759
56765
|
return {
|
|
56760
56766
|
...result,
|
|
56761
|
-
state
|
|
56767
|
+
state,
|
|
56768
|
+
...rejectedItems === void 0 ? {} : { rejectedItems }
|
|
56762
56769
|
};
|
|
56770
|
+
} catch (cause) {
|
|
56771
|
+
if (cause instanceof WorkflowRunnerError) throw cause;
|
|
56772
|
+
const messages = current.state.messages;
|
|
56773
|
+
throw new WorkflowRunnerError(`Workflow agent turn failed: ${cause instanceof Error ? cause.message : String(cause)}`, {
|
|
56774
|
+
messages,
|
|
56775
|
+
usage: totalUsage(messages),
|
|
56776
|
+
executor: evidence()
|
|
56777
|
+
}, { cause });
|
|
56763
56778
|
} finally {
|
|
56764
56779
|
signal.removeEventListener("abort", abort);
|
|
56765
56780
|
unsubscribe();
|
|
@@ -56771,7 +56786,7 @@ const createPiRunner = (options) => {
|
|
|
56771
56786
|
id: options.model.id
|
|
56772
56787
|
},
|
|
56773
56788
|
research: (spec, prompt, { signal }) => phase(spec, prompt, signal),
|
|
56774
|
-
act: (spec, prompt, { signal
|
|
56789
|
+
act: (spec, prompt, { signal }) => phase(spec, prompt, signal, true),
|
|
56775
56790
|
async close() {
|
|
56776
56791
|
agent?.abort();
|
|
56777
56792
|
await agent?.waitForIdle();
|
|
@@ -56785,21 +56800,36 @@ const acquireWorkflowRunner = async (options) => {
|
|
|
56785
56800
|
const provider = id.slice(0, slash);
|
|
56786
56801
|
const model = builtinModels().getModel(provider, id.slice(slash + 1));
|
|
56787
56802
|
if (!model) throw new Error(`Unknown Pi model: ${id}`);
|
|
56788
|
-
if (!getEnvApiKey(provider)) {
|
|
56803
|
+
if (!getEnvApiKey(provider)?.trim()) {
|
|
56789
56804
|
const names = findEnvKeys(provider, new Proxy({}, { get: (_target, key) => typeof key === "string" ? "configured" : void 0 }));
|
|
56790
56805
|
throw new Error(`Missing Pi credentials for ${provider}; set ${names?.join(" or ") ?? `${provider} provider credentials`}.`);
|
|
56791
56806
|
}
|
|
56807
|
+
let executor = options.executor;
|
|
56808
|
+
if (executor === void 0) {
|
|
56809
|
+
const baseUrl = process.env["EXECUTOR_BASE_URL"]?.trim();
|
|
56810
|
+
if (!baseUrl) throw new Error("Missing Executor configuration; set EXECUTOR_BASE_URL before starting a workflow.");
|
|
56811
|
+
try {
|
|
56812
|
+
const url = new URL(baseUrl);
|
|
56813
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") throw new Error("expected http: or https:");
|
|
56814
|
+
executor = await createExecutorToolset({ policy: "decline" });
|
|
56815
|
+
} catch (cause) {
|
|
56816
|
+
throw new Error(`Invalid workflow Executor configuration: ${cause instanceof Error ? cause.message : String(cause)}`, { cause });
|
|
56817
|
+
}
|
|
56818
|
+
}
|
|
56792
56819
|
return createPiRunner({
|
|
56793
56820
|
root: options.root,
|
|
56794
56821
|
presetDirectory: resolve(options.root, options.config.presetDirectory),
|
|
56795
56822
|
model,
|
|
56796
56823
|
limit: options.limit,
|
|
56797
56824
|
...options.runsDirectory === void 0 ? {} : { runsDirectory: options.runsDirectory },
|
|
56825
|
+
...options.repositoryRoot === void 0 ? {} : { repositoryRoot: options.repositoryRoot },
|
|
56826
|
+
...options.runDirectory === void 0 ? {} : { runDirectory: options.runDirectory },
|
|
56827
|
+
...options.resume === void 0 ? {} : { resume: options.resume },
|
|
56798
56828
|
...options.additionalTools === void 0 ? {} : { additionalTools: options.additionalTools },
|
|
56799
|
-
executor
|
|
56829
|
+
executor
|
|
56800
56830
|
});
|
|
56801
56831
|
};
|
|
56802
56832
|
//#endregion
|
|
56803
56833
|
export { WorkflowRunnerError, acquireWorkflowRunner, composeSystemPrompt, createPiRunner, envApiKeyAuth as n, lazyOAuth as r, validateToolArguments as t, totalUsage };
|
|
56804
56834
|
|
|
56805
|
-
//# sourceMappingURL=pi-
|
|
56835
|
+
//# sourceMappingURL=pi-Bz4BgZdC.js.map
|