@hachej/boring-agent 0.1.103 → 0.1.105
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/dist/{chunk-7QM22DU7.js → chunk-6DRHERVK.js} +7 -5
- package/dist/{chunk-TW7G33QH.js → chunk-F2OJI2LX.js} +64 -15
- package/dist/{chunk-6WKQ4FC4.js → chunk-LFN45QDZ.js} +259 -140
- package/dist/core/index.d.ts +5 -5
- package/dist/{createHarness-4Q6DQBRT.js → createHarness-GMBZZPTN.js} +1 -1
- package/dist/{errors-szpcDUFQ.d.ts → errors-DH7C01Pm.d.ts} +1 -1
- package/dist/{file-search-BXdSm-Yq.d.ts → file-search-qcD5zItr.d.ts} +3 -3
- package/dist/front/index.d.ts +12 -2
- package/dist/front/index.js +200 -135
- package/dist/front/styles.css +56 -15
- package/dist/{harness-erpL2SER.d.ts → harness-Dcd08yKr.d.ts} +1 -1
- package/dist/{lease-K-EZhdL-.d.ts → lease-DffrPrQn.d.ts} +1 -1
- package/dist/{piChatEvent-g1nIBh44.d.ts → piChatEvent-iNSXiFQq.d.ts} +5 -0
- package/dist/{piChatSessionService-DugeRHzb.d.ts → piChatSessionService-DQSQ_kWZ.d.ts} +1 -1
- package/dist/server/agent-host/testing/gatewayConformance.d.ts +5 -5
- package/dist/server/agent-host/testing/gatewayConformance.js +1 -1
- package/dist/server/index.d.ts +53 -42
- package/dist/server/index.js +5 -3
- package/dist/server/worker/index.js +3 -3
- package/dist/shared/index.d.ts +93 -19
- package/dist/shared/index.js +1 -1
- package/dist/{types-BnjMLAd5.d.ts → types-BTsdaAQ2.d.ts} +33 -14
- package/docs/ERROR_CODES.md +1 -1
- package/package.json +6 -6
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
readConfiguredDefaultModel,
|
|
8
8
|
registerConfiguredModelProviders,
|
|
9
9
|
withPiHarnessDefaults
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-F2OJI2LX.js";
|
|
11
11
|
import {
|
|
12
12
|
AGENT_KNOWLEDGE_FILESYSTEM_ID,
|
|
13
13
|
AgentDefinitionValidationError,
|
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
AgentGatewayErrorCode,
|
|
42
42
|
extractToolUiMetadata,
|
|
43
43
|
sanitizeToolUiMetadata2 as sanitizeToolUiMetadata
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-6DRHERVK.js";
|
|
45
45
|
import {
|
|
46
46
|
AgentDefinitionErrorCode,
|
|
47
47
|
AgentDeploymentErrorCode,
|
|
@@ -2212,6 +2212,28 @@ var agentSandboxRuntimeHostOperations = {
|
|
|
2212
2212
|
withWorkspacePythonEnv
|
|
2213
2213
|
};
|
|
2214
2214
|
var sandboxRuntimeHostOperations = agentSandboxRuntimeHostOperations;
|
|
2215
|
+
function resolveBwrapPolicy(options) {
|
|
2216
|
+
const sandbox = options?.sandbox;
|
|
2217
|
+
const namespaceProfile = sandbox?.namespaceProfile ?? "full";
|
|
2218
|
+
return {
|
|
2219
|
+
namespaceProfile,
|
|
2220
|
+
network: sandbox?.network ?? "shared",
|
|
2221
|
+
// Docker mode runs outside a nested user namespace. Never allow the outer
|
|
2222
|
+
// container's SYS_ADMIN capability to reach any local execution path.
|
|
2223
|
+
dropAllCapabilities: namespaceProfile === "docker" || sandbox?.dropAllCapabilities === true
|
|
2224
|
+
};
|
|
2225
|
+
}
|
|
2226
|
+
function withBwrapPolicy(runtimeHost, policy) {
|
|
2227
|
+
return {
|
|
2228
|
+
...runtimeHost,
|
|
2229
|
+
buildBwrapArgs(workspaceRoot, executionOptions) {
|
|
2230
|
+
return runtimeHost.buildBwrapArgs(workspaceRoot, {
|
|
2231
|
+
...executionOptions,
|
|
2232
|
+
...policy
|
|
2233
|
+
});
|
|
2234
|
+
}
|
|
2235
|
+
};
|
|
2236
|
+
}
|
|
2215
2237
|
function resolveBuiltinRuntimeLayoutRoot(mode, workspaceRoot) {
|
|
2216
2238
|
return mode === "blaxel" ? BLAXEL_WORKSPACE_ROOT : mode === "vercel-sandbox" ? VERCEL_SANDBOX_WORKSPACE_ROOT : workspaceRoot;
|
|
2217
2239
|
}
|
|
@@ -2222,11 +2244,20 @@ function createSandboxRuntimeModeAdapter(mode, options = {}) {
|
|
|
2222
2244
|
provider: createDirectSandboxProvider(),
|
|
2223
2245
|
runtimeHost: agentSandboxRuntimeHostOperations
|
|
2224
2246
|
});
|
|
2225
|
-
case "local":
|
|
2247
|
+
case "local": {
|
|
2248
|
+
const policy = resolveBwrapPolicy(options.bwrap);
|
|
2249
|
+
const runtimeHost = withBwrapPolicy(agentSandboxRuntimeHostOperations, policy);
|
|
2226
2250
|
return createLocalModeAdapter({
|
|
2227
|
-
provider: createBwrapSandboxProvider(
|
|
2228
|
-
|
|
2251
|
+
provider: createBwrapSandboxProvider({
|
|
2252
|
+
...options.bwrap,
|
|
2253
|
+
sandbox: {
|
|
2254
|
+
...options.bwrap?.sandbox,
|
|
2255
|
+
...policy
|
|
2256
|
+
}
|
|
2257
|
+
}),
|
|
2258
|
+
runtimeHost
|
|
2229
2259
|
});
|
|
2260
|
+
}
|
|
2230
2261
|
case "vercel-sandbox":
|
|
2231
2262
|
return createVercelSandboxModeAdapter({
|
|
2232
2263
|
provider: createVercelSandboxProvider({
|
|
@@ -2793,7 +2824,7 @@ async function createConfiguredAgentHostAgentSpec(input) {
|
|
|
2793
2824
|
...plugin.config === void 0 ? {} : { config: frozenJson(plugin.config) }
|
|
2794
2825
|
}));
|
|
2795
2826
|
const preferredModel = nonEmpty(policy.preferredModel);
|
|
2796
|
-
const
|
|
2827
|
+
const instructionSources = policy.instructionSources?.length ? Object.freeze(policy.instructionSources.map((source) => Object.freeze({ ...source }))) : void 0;
|
|
2797
2828
|
return Object.freeze({
|
|
2798
2829
|
agentTypeId: input.source.agentTypeId,
|
|
2799
2830
|
definition: Object.freeze({
|
|
@@ -2803,24 +2834,75 @@ async function createConfiguredAgentHostAgentSpec(input) {
|
|
|
2803
2834
|
...input.source.definitionDigest === void 0 ? {} : { digest: input.source.definitionDigest }
|
|
2804
2835
|
}),
|
|
2805
2836
|
...input.source.knowledgeDir === void 0 ? {} : { knowledge: Object.freeze({ rootDir: input.source.knowledgeDir }) },
|
|
2806
|
-
...
|
|
2837
|
+
...instructionSources ? { instructionSources } : {},
|
|
2807
2838
|
...plugins?.length ? { plugins: Object.freeze(plugins) } : {},
|
|
2808
2839
|
...preferredModel ? { model: Object.freeze({ preferred: preferredModel }) } : {}
|
|
2809
2840
|
});
|
|
2810
2841
|
}
|
|
2811
2842
|
|
|
2812
2843
|
// src/server/agentDefinition/loadConfiguredAgentFleet.ts
|
|
2813
|
-
import { lstat as lstat3, readFile as readFile3, realpath as
|
|
2814
|
-
import { basename as basename2,
|
|
2844
|
+
import { lstat as lstat3, readFile as readFile3, realpath as realpath5 } from "node:fs/promises";
|
|
2845
|
+
import { basename as basename2, resolve as resolve5 } from "node:path";
|
|
2815
2846
|
import { parse as parseYaml } from "yaml";
|
|
2816
2847
|
|
|
2848
|
+
// src/server/agentDefinition/instructionFileRefs.ts
|
|
2849
|
+
import { realpath as realpath4 } from "node:fs/promises";
|
|
2850
|
+
import { isAbsolute as isAbsolute5, relative as relative6, resolve as resolve4, sep as sep5 } from "node:path";
|
|
2851
|
+
|
|
2817
2852
|
// src/server/agent-host/types.ts
|
|
2818
2853
|
var AGENT_USER_FILESYSTEM_ID = "user";
|
|
2819
2854
|
|
|
2820
|
-
// src/server/agentDefinition/
|
|
2855
|
+
// src/server/agentDefinition/instructionFileRefs.ts
|
|
2856
|
+
function isCanonicalPathInside(root, target) {
|
|
2857
|
+
const fromRoot = relative6(root, target);
|
|
2858
|
+
return fromRoot === "" || fromRoot !== ".." && !fromRoot.startsWith(`..${sep5}`) && !isAbsolute5(fromRoot);
|
|
2859
|
+
}
|
|
2821
2860
|
function isPublishableWorkspacePath(value) {
|
|
2822
2861
|
return value.length > 0 && !value.includes("\0") && !value.includes("\\") && !value.startsWith("/") && !/^[A-Za-z]:[\\/]/.test(value) && !/%(?:2e|2f|5c)/i.test(value) && !/^[A-Za-z][A-Za-z0-9+.-]*:/.test(value) && !value.split("/").some((segment) => segment === "" || segment === "." || segment === "..");
|
|
2823
2862
|
}
|
|
2863
|
+
async function resolveAgentInstructionFileRefs(input) {
|
|
2864
|
+
const sources = input.sources ?? [];
|
|
2865
|
+
if (sources.length === 0) return Object.freeze({ refs: Object.freeze([]), withheld: Object.freeze([]) });
|
|
2866
|
+
const canonicalWorkspaceRoot = typeof input.workspaceRoot === "string" && input.workspaceRoot.trim() ? await realpath4(resolve4(input.workspaceRoot)).catch(() => null) : null;
|
|
2867
|
+
const refs = [];
|
|
2868
|
+
const withheld = [];
|
|
2869
|
+
for (const source of sources) {
|
|
2870
|
+
if (canonicalWorkspaceRoot === null) {
|
|
2871
|
+
withheld.push({
|
|
2872
|
+
code: ErrorCode.enum.AGENT_FLEET_SEAT_INSTRUCTIONS_PATH_UNPUBLISHABLE,
|
|
2873
|
+
absolutePath: source.absolutePath,
|
|
2874
|
+
message: `this request resolves no readable workspace root, so persona instructions have no "${AGENT_USER_FILESYSTEM_ID}" path to be addressed against`
|
|
2875
|
+
});
|
|
2876
|
+
continue;
|
|
2877
|
+
}
|
|
2878
|
+
const canonicalSource = await realpath4(resolve4(source.absolutePath)).catch(() => null);
|
|
2879
|
+
if (canonicalSource === null || !isCanonicalPathInside(canonicalWorkspaceRoot, canonicalSource)) {
|
|
2880
|
+
withheld.push({
|
|
2881
|
+
code: ErrorCode.enum.AGENT_FLEET_SEAT_INSTRUCTIONS_PATH_UNPUBLISHABLE,
|
|
2882
|
+
absolutePath: source.absolutePath,
|
|
2883
|
+
message: `instruction source resolves outside the workspace root that the "${AGENT_USER_FILESYSTEM_ID}" filesystem serves for this request`
|
|
2884
|
+
});
|
|
2885
|
+
continue;
|
|
2886
|
+
}
|
|
2887
|
+
const path = relative6(canonicalWorkspaceRoot, canonicalSource).split(sep5).join("/");
|
|
2888
|
+
if (!isPublishableWorkspacePath(path)) {
|
|
2889
|
+
withheld.push({
|
|
2890
|
+
code: ErrorCode.enum.AGENT_FLEET_SEAT_INSTRUCTIONS_PATH_UNPUBLISHABLE,
|
|
2891
|
+
absolutePath: source.absolutePath,
|
|
2892
|
+
message: `instruction source composes an unsafe workspace-relative path (${JSON.stringify(path)})`
|
|
2893
|
+
});
|
|
2894
|
+
continue;
|
|
2895
|
+
}
|
|
2896
|
+
refs.push(Object.freeze({
|
|
2897
|
+
filesystem: AGENT_USER_FILESYSTEM_ID,
|
|
2898
|
+
path,
|
|
2899
|
+
role: source.role
|
|
2900
|
+
}));
|
|
2901
|
+
}
|
|
2902
|
+
return Object.freeze({ refs: Object.freeze(refs), withheld: Object.freeze(withheld) });
|
|
2903
|
+
}
|
|
2904
|
+
|
|
2905
|
+
// src/server/agentDefinition/loadConfiguredAgentFleet.ts
|
|
2824
2906
|
var FleetConfigError = class extends Error {
|
|
2825
2907
|
code;
|
|
2826
2908
|
field;
|
|
@@ -2831,10 +2913,6 @@ var FleetConfigError = class extends Error {
|
|
|
2831
2913
|
this.field = input.field;
|
|
2832
2914
|
}
|
|
2833
2915
|
};
|
|
2834
|
-
function isCanonicalPathInside(root, target) {
|
|
2835
|
-
const fromRoot = relative6(root, target);
|
|
2836
|
-
return fromRoot === "" || fromRoot !== ".." && !fromRoot.startsWith(`..${sep5}`) && !isAbsolute5(fromRoot);
|
|
2837
|
-
}
|
|
2838
2916
|
function isRecord(value) {
|
|
2839
2917
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2840
2918
|
}
|
|
@@ -2943,13 +3021,13 @@ function resolveSeatModel(tier, env, modelTierCandidates) {
|
|
|
2943
3021
|
return void 0;
|
|
2944
3022
|
}
|
|
2945
3023
|
async function readVerifiedSkillContent(root, reference, skill) {
|
|
2946
|
-
const rootTarget = await
|
|
2947
|
-
let candidate =
|
|
3024
|
+
const rootTarget = await realpath5(root);
|
|
3025
|
+
let candidate = resolve5(rootTarget, reference);
|
|
2948
3026
|
const candidateStat = await lstat3(candidate);
|
|
2949
|
-
if (candidateStat.isDirectory()) candidate =
|
|
3027
|
+
if (candidateStat.isDirectory()) candidate = resolve5(candidate, "SKILL.md");
|
|
2950
3028
|
const fileStat = await lstat3(candidate);
|
|
2951
3029
|
if (!fileStat.isFile() || fileStat.isSymbolicLink()) throw new Error("skill source is not a regular file");
|
|
2952
|
-
const target = await
|
|
3030
|
+
const target = await realpath5(candidate);
|
|
2953
3031
|
if (!isCanonicalPathInside(rootTarget, target)) throw new Error("skill source resolves outside its admitted root");
|
|
2954
3032
|
const content = await readFile3(target, "utf8");
|
|
2955
3033
|
if (await sha256(content) !== skill.digest) throw new Error("skill digest mismatch");
|
|
@@ -2981,7 +3059,6 @@ async function loadConfiguredAgentFleet(options) {
|
|
|
2981
3059
|
seatTiers = Object.freeze({});
|
|
2982
3060
|
}
|
|
2983
3061
|
validateSeatTierCandidates(seatTiers, modelTierCandidates, options.fleetConfigPath, options.policyPath);
|
|
2984
|
-
const canonicalWorkspaceRoot = options.workspaceRoot === null ? null : await realpath4(resolve4(options.workspaceRoot)).catch(() => null);
|
|
2985
3062
|
const agents = [];
|
|
2986
3063
|
const diagnostics = [];
|
|
2987
3064
|
const packagesByDefinitionId = /* @__PURE__ */ new Map();
|
|
@@ -3023,7 +3100,7 @@ async function loadConfiguredAgentFleet(options) {
|
|
|
3023
3100
|
if (conflictedDefinitionIds.has(binding.agentTypeId)) continue;
|
|
3024
3101
|
const descriptor = descriptors[0];
|
|
3025
3102
|
if (!descriptor || !descriptor.preflight.ok) throw new Error(`seat "${binding.seat}" has no valid discovered agent package`);
|
|
3026
|
-
const personaSource = await
|
|
3103
|
+
const personaSource = await realpath5(resolve5(descriptor.rootDir));
|
|
3027
3104
|
const source = await materializeAgentDirectory({
|
|
3028
3105
|
directory: personaSource,
|
|
3029
3106
|
expectedAgentTypeId: binding.agentTypeId,
|
|
@@ -3061,29 +3138,15 @@ async function loadConfiguredAgentFleet(options) {
|
|
|
3061
3138
|
instructionAppendices.push({ name: appendixName, digest: skill.digest, content });
|
|
3062
3139
|
}
|
|
3063
3140
|
const preferredModel = resolveSeatModel(seatTiers[binding.seat], env, modelTierCandidates);
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
if (unpublishableReason) {
|
|
3069
|
-
diagnostics.push({
|
|
3070
|
-
seat: binding.seat,
|
|
3071
|
-
agentTypeId: binding.agentTypeId,
|
|
3072
|
-
code: ErrorCode.enum.AGENT_FLEET_SEAT_INSTRUCTIONS_PATH_UNPUBLISHABLE,
|
|
3073
|
-
message: `${unpublishableReason}; its persona instructions will not be linkable`
|
|
3074
|
-
});
|
|
3075
|
-
} else {
|
|
3076
|
-
instructionFiles = [{
|
|
3077
|
-
filesystem: AGENT_USER_FILESYSTEM_ID,
|
|
3078
|
-
path: publishedInstructionPath,
|
|
3079
|
-
role: "persona"
|
|
3080
|
-
}];
|
|
3081
|
-
}
|
|
3141
|
+
const instructionSources = [{
|
|
3142
|
+
absolutePath: resolve5(personaSource, "instructions.md"),
|
|
3143
|
+
role: "persona"
|
|
3144
|
+
}];
|
|
3082
3145
|
const spec = await createConfiguredAgentHostAgentSpec({
|
|
3083
3146
|
source,
|
|
3084
3147
|
policy: {
|
|
3085
3148
|
instructionAppendices,
|
|
3086
|
-
|
|
3149
|
+
instructionSources,
|
|
3087
3150
|
...preferredModel ? { preferredModel } : {}
|
|
3088
3151
|
}
|
|
3089
3152
|
});
|
|
@@ -3103,7 +3166,7 @@ async function loadConfiguredAgentFleet(options) {
|
|
|
3103
3166
|
}
|
|
3104
3167
|
|
|
3105
3168
|
// src/server/agentDefinition/resolveDefaultAgentFleet.ts
|
|
3106
|
-
import { resolve as
|
|
3169
|
+
import { resolve as resolve6 } from "node:path";
|
|
3107
3170
|
import { createLogger } from "@hachej/boring-bash/server";
|
|
3108
3171
|
var logger = createLogger("agent-fleet-loader");
|
|
3109
3172
|
var LEGACY_DEFAULT_AGENT_FLEET = Object.freeze([
|
|
@@ -3117,15 +3180,13 @@ async function resolveDefaultAgentFleet(options) {
|
|
|
3117
3180
|
if (!options.discoveredPackages) throw new Error("agent package discovery descriptors were not injected by the boot layer");
|
|
3118
3181
|
const { agents: configuredAgents, diagnostics } = await loadConfiguredAgentFleet({
|
|
3119
3182
|
discoveredPackages: options.discoveredPackages,
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
skillsRoot: resolve5(root, ".agents", "skills"),
|
|
3183
|
+
fleetConfigPath: resolve6(root, ".agents", "factory", "fleet.yaml"),
|
|
3184
|
+
policyPath: resolve6(root, ".agents", "factory", "policy.yaml"),
|
|
3185
|
+
skillsRoot: resolve6(root, ".agents", "skills"),
|
|
3124
3186
|
env
|
|
3125
3187
|
});
|
|
3126
3188
|
for (const diagnostic of diagnostics) {
|
|
3127
|
-
|
|
3128
|
-
logger.warn(excluded ? "fleet package excluded or inert" : "fleet seat instructions not linkable", {
|
|
3189
|
+
logger.warn("fleet package excluded or inert", {
|
|
3129
3190
|
seat: diagnostic.seat,
|
|
3130
3191
|
agentTypeId: diagnostic.agentTypeId,
|
|
3131
3192
|
code: diagnostic.code,
|
|
@@ -4225,13 +4286,13 @@ function resultTool(result) {
|
|
|
4225
4286
|
};
|
|
4226
4287
|
}
|
|
4227
4288
|
function deferred() {
|
|
4228
|
-
let
|
|
4289
|
+
let resolve10;
|
|
4229
4290
|
let reject;
|
|
4230
4291
|
const promise = new Promise((res, rej) => {
|
|
4231
|
-
|
|
4292
|
+
resolve10 = res;
|
|
4232
4293
|
reject = rej;
|
|
4233
4294
|
});
|
|
4234
|
-
return { promise, resolve:
|
|
4295
|
+
return { promise, resolve: resolve10, reject };
|
|
4235
4296
|
}
|
|
4236
4297
|
function errorTool(error) {
|
|
4237
4298
|
const safe = safeError(error);
|
|
@@ -4645,7 +4706,7 @@ function isSqliteBusy(error) {
|
|
|
4645
4706
|
return (code === "SQLITE_BUSY" || code === "ERR_SQLITE_ERROR") && /busy|lock/i.test(error.message);
|
|
4646
4707
|
}
|
|
4647
4708
|
function delay(ms) {
|
|
4648
|
-
return new Promise((
|
|
4709
|
+
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
4649
4710
|
}
|
|
4650
4711
|
function clampLimit(value, defaultValue, maxValue) {
|
|
4651
4712
|
if (value === void 0) return defaultValue;
|
|
@@ -4889,6 +4950,7 @@ function buildPiChatSnapshot(adapter, options) {
|
|
|
4889
4950
|
seq: options.seq,
|
|
4890
4951
|
status,
|
|
4891
4952
|
activeTurnId: options.activeTurnId,
|
|
4953
|
+
currentModel: adapter.currentModel?.(),
|
|
4892
4954
|
messages: buildPiChatHistory(piSnapshot.messages, {
|
|
4893
4955
|
sessionId,
|
|
4894
4956
|
messageTurnIds: options.messageTurnIds,
|
|
@@ -5861,6 +5923,11 @@ function normalizeMeteringUsage(value) {
|
|
|
5861
5923
|
}
|
|
5862
5924
|
};
|
|
5863
5925
|
}
|
|
5926
|
+
function isExplicitCompleteZeroUsage(value) {
|
|
5927
|
+
if (!isRecord4(value) || !isRecord4(value.cost)) return false;
|
|
5928
|
+
const hasOwnZeroFields = (record, fields) => fields.every((field) => Object.prototype.hasOwnProperty.call(record, field) && record[field] === 0);
|
|
5929
|
+
return hasOwnZeroFields(value, ["input", "output", "cacheRead", "cacheWrite", "totalTokens"]) && hasOwnZeroFields(value.cost, ["input", "output", "cacheRead", "cacheWrite", "total"]);
|
|
5930
|
+
}
|
|
5864
5931
|
var PiChatMeteringCoordinator = class {
|
|
5865
5932
|
sessions = /* @__PURE__ */ new Map();
|
|
5866
5933
|
inflightOps = /* @__PURE__ */ new Set();
|
|
@@ -6128,13 +6195,18 @@ var PiChatMeteringCoordinator = class {
|
|
|
6128
6195
|
}
|
|
6129
6196
|
recordAssistantUsage(state, message, opts = {}) {
|
|
6130
6197
|
if (!isRecord4(message) || message.role !== "assistant") return;
|
|
6198
|
+
if (!Object.prototype.hasOwnProperty.call(message, "usage")) return;
|
|
6199
|
+
const explicitCompleteZero = isExplicitCompleteZeroUsage(message.usage);
|
|
6131
6200
|
const usage = normalizeMeteringUsage(message.usage);
|
|
6132
|
-
if (!usage) return;
|
|
6133
6201
|
const run2 = state.active ?? state.pendingPrompts[0];
|
|
6134
6202
|
if (!run2 || run2.terminal) {
|
|
6135
6203
|
this.logError("assistant usage arrived with no reserved run; usage not metered", { messageRole: "assistant" });
|
|
6136
6204
|
return;
|
|
6137
6205
|
}
|
|
6206
|
+
if (!usage) {
|
|
6207
|
+
run2.allUsageReportsExplicitZero = false;
|
|
6208
|
+
return;
|
|
6209
|
+
}
|
|
6138
6210
|
const messageId = typeof message.id === "string" && message.id.length > 0 ? message.id : void 0;
|
|
6139
6211
|
if (messageId) {
|
|
6140
6212
|
if (run2.recordedMessageIds.has(messageId)) return;
|
|
@@ -6146,6 +6218,7 @@ var PiChatMeteringCoordinator = class {
|
|
|
6146
6218
|
run2.lastIdlessUsageKey = signature;
|
|
6147
6219
|
}
|
|
6148
6220
|
run2.usageCount += 1;
|
|
6221
|
+
if (!explicitCompleteZero) run2.allUsageReportsExplicitZero = false;
|
|
6149
6222
|
const model = typeof message.model === "string" && message.model.length > 0 ? message.model : void 0;
|
|
6150
6223
|
const provider = typeof message.provider === "string" && message.provider.length > 0 ? message.provider : void 0;
|
|
6151
6224
|
const stopReason = typeof message.stopReason === "string" ? message.stopReason : void 0;
|
|
@@ -6164,9 +6237,9 @@ var PiChatMeteringCoordinator = class {
|
|
|
6164
6237
|
stopReason
|
|
6165
6238
|
});
|
|
6166
6239
|
if (result.billedMicros > 0) run2.billableUsageCount += 1;
|
|
6240
|
+
if (explicitCompleteZero) run2.persistedExplicitZeroUsageCount += 1;
|
|
6167
6241
|
} catch (error) {
|
|
6168
|
-
|
|
6169
|
-
if (couldBill) run2.usageWriteFailed = true;
|
|
6242
|
+
if (!explicitCompleteZero) run2.usageWriteFailed = true;
|
|
6170
6243
|
throw error;
|
|
6171
6244
|
}
|
|
6172
6245
|
},
|
|
@@ -6190,6 +6263,8 @@ var PiChatMeteringCoordinator = class {
|
|
|
6190
6263
|
reservationId: void 0,
|
|
6191
6264
|
instanceId: this.runInstances += 1,
|
|
6192
6265
|
usageCount: 0,
|
|
6266
|
+
allUsageReportsExplicitZero: true,
|
|
6267
|
+
persistedExplicitZeroUsageCount: 0,
|
|
6193
6268
|
billableUsageCount: 0,
|
|
6194
6269
|
recordedMessageIds: /* @__PURE__ */ new Set(),
|
|
6195
6270
|
lastIdlessUsageKey: void 0,
|
|
@@ -6236,8 +6311,10 @@ var PiChatMeteringCoordinator = class {
|
|
|
6236
6311
|
if (run2.billableUsageCount > 0) {
|
|
6237
6312
|
return this.sink.settleRun({ ...run2.scope, reservationId: run2.reservationId, status });
|
|
6238
6313
|
}
|
|
6239
|
-
|
|
6240
|
-
|
|
6314
|
+
if (status === "ok" && !run2.userStopped && run2.usageCount > 0 && run2.allUsageReportsExplicitZero && run2.persistedExplicitZeroUsageCount === run2.usageCount) {
|
|
6315
|
+
return this.sink.settleRun({ ...run2.scope, reservationId: run2.reservationId, status });
|
|
6316
|
+
}
|
|
6317
|
+
if (status === "ok" && !run2.userStopped) {
|
|
6241
6318
|
return this.sink.releaseRun({ ...run2.scope, reservationId: run2.reservationId, reason: "fallback-hold-charge" });
|
|
6242
6319
|
}
|
|
6243
6320
|
return this.sink.releaseRun({
|
|
@@ -6340,11 +6417,11 @@ function bindingDisposedError() {
|
|
|
6340
6417
|
});
|
|
6341
6418
|
}
|
|
6342
6419
|
function deferred2() {
|
|
6343
|
-
let
|
|
6420
|
+
let resolve10;
|
|
6344
6421
|
const promise = new Promise((nextResolve) => {
|
|
6345
|
-
|
|
6422
|
+
resolve10 = () => nextResolve();
|
|
6346
6423
|
});
|
|
6347
|
-
return { promise, resolve:
|
|
6424
|
+
return { promise, resolve: resolve10 };
|
|
6348
6425
|
}
|
|
6349
6426
|
|
|
6350
6427
|
// src/server/codedError.ts
|
|
@@ -6357,6 +6434,9 @@ function codedError(message, code, statusCode, extra) {
|
|
|
6357
6434
|
// src/server/pi-chat/harnessPiChatService.ts
|
|
6358
6435
|
var MAX_PROMPT_IMAGE_BYTES = 10 * 1024 * 1024;
|
|
6359
6436
|
var PROMPT_IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([".avif", ".gif", ".jpg", ".jpeg", ".png", ".webp"]);
|
|
6437
|
+
function sameModelSelection(left, right) {
|
|
6438
|
+
return left?.provider === right.provider && left.id === right.id;
|
|
6439
|
+
}
|
|
6360
6440
|
var HarnessPiChatService = class {
|
|
6361
6441
|
harness;
|
|
6362
6442
|
sessionStore;
|
|
@@ -6612,12 +6692,13 @@ var HarnessPiChatService = class {
|
|
|
6612
6692
|
async readPersistedState(ctx, sessionId) {
|
|
6613
6693
|
if (!this.sessionStore.loadEntries) return null;
|
|
6614
6694
|
try {
|
|
6615
|
-
const { id, messages } = await this.sessionStore.loadEntries(toSessionCtx(ctx), sessionId);
|
|
6695
|
+
const { id, messages, currentModel } = await this.sessionStore.loadEntries(toSessionCtx(ctx), sessionId);
|
|
6616
6696
|
return {
|
|
6617
6697
|
protocolVersion: 1,
|
|
6618
6698
|
sessionId: id,
|
|
6619
6699
|
seq: await this.readDurableLatestPiChatSeq(sessionStreamPath(this.sessionKey(ctx, id))),
|
|
6620
6700
|
status: "idle",
|
|
6701
|
+
currentModel,
|
|
6621
6702
|
messages: buildPiChatHistory(messages, {
|
|
6622
6703
|
sessionId: id,
|
|
6623
6704
|
attachmentUrl: this.attachmentUrlFor(id)
|
|
@@ -6666,6 +6747,13 @@ var HarnessPiChatService = class {
|
|
|
6666
6747
|
};
|
|
6667
6748
|
}
|
|
6668
6749
|
if (outcome === "cancelled") throw promptCancelledError();
|
|
6750
|
+
const currentModel = adapter.currentModel?.();
|
|
6751
|
+
if (currentModel && !sameModelSelection(channel.advertisedModel, currentModel)) {
|
|
6752
|
+
channel.advertisedModel = currentModel;
|
|
6753
|
+
this.publishChannelEvents(sessionId, channel, [
|
|
6754
|
+
channel.mapper.mapSynthetic({ type: "model-changed", currentModel })
|
|
6755
|
+
]);
|
|
6756
|
+
}
|
|
6669
6757
|
this.messageMetadata.recordPrompt(sessionKey, payload);
|
|
6670
6758
|
const receiptCursor = nextPromptReceiptCursor(channel);
|
|
6671
6759
|
try {
|
|
@@ -7112,7 +7200,8 @@ var HarnessPiChatService = class {
|
|
|
7112
7200
|
closed: closed.promise,
|
|
7113
7201
|
resolveClosed: () => closed.resolve(),
|
|
7114
7202
|
rejectClosed: closed.reject,
|
|
7115
|
-
messageTurnIds: /* @__PURE__ */ new Map()
|
|
7203
|
+
messageTurnIds: /* @__PURE__ */ new Map(),
|
|
7204
|
+
advertisedModel: adapter.currentModel?.()
|
|
7116
7205
|
};
|
|
7117
7206
|
const unsubscribe = adapter.subscribe((event) => {
|
|
7118
7207
|
const mappedEvents = mapper.map(event);
|
|
@@ -7210,13 +7299,13 @@ function promptCancelledError() {
|
|
|
7210
7299
|
});
|
|
7211
7300
|
}
|
|
7212
7301
|
function deferred3() {
|
|
7213
|
-
let
|
|
7302
|
+
let resolve10;
|
|
7214
7303
|
let reject;
|
|
7215
7304
|
const promise = new Promise((nextResolve, nextReject) => {
|
|
7216
|
-
|
|
7305
|
+
resolve10 = nextResolve;
|
|
7217
7306
|
reject = nextReject;
|
|
7218
7307
|
});
|
|
7219
|
-
return { promise, resolve:
|
|
7308
|
+
return { promise, resolve: resolve10, reject };
|
|
7220
7309
|
}
|
|
7221
7310
|
function rejectedReasons(results) {
|
|
7222
7311
|
return results.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
|
|
@@ -7745,10 +7834,17 @@ var AgentSessionInventory = class {
|
|
|
7745
7834
|
compiledById;
|
|
7746
7835
|
resolveAgentRuntimeScope;
|
|
7747
7836
|
stores = /* @__PURE__ */ new Map();
|
|
7748
|
-
|
|
7837
|
+
/**
|
|
7838
|
+
* Lists a seat's sessions. `options` is threaded straight into the store so a
|
|
7839
|
+
* bounded page reads a bounded number of transcripts: an unbounded call makes
|
|
7840
|
+
* the store stream and parse EVERY native transcript it holds (see
|
|
7841
|
+
* `summarizeNativeTranscript`, whose result is intentionally never cached),
|
|
7842
|
+
* which is what made a per-seat boot listing cost tens of seconds (#1338).
|
|
7843
|
+
*/
|
|
7844
|
+
async list(agentTypeId, scope, claim, options) {
|
|
7749
7845
|
const resolved = await this.resolveStore(agentTypeId, scope, claim);
|
|
7750
7846
|
if (!resolved) return [];
|
|
7751
|
-
return await resolved.store.list({ workspaceId: claim.workspaceScopeId });
|
|
7847
|
+
return await resolved.store.list({ workspaceId: claim.workspaceScopeId }, options);
|
|
7752
7848
|
}
|
|
7753
7849
|
async resolveSessionRuntime(agentTypeId, scope, claim, sessionId) {
|
|
7754
7850
|
const resolved = await this.resolveStore(agentTypeId, scope, claim);
|
|
@@ -7941,7 +8037,7 @@ async function buildAgentComposition(input) {
|
|
|
7941
8037
|
sessionNamespace: configuredNamespace,
|
|
7942
8038
|
sessionDir: runtimeScope.sessionDir ?? factoryInput.sessionDir
|
|
7943
8039
|
}) : async (factoryInput) => {
|
|
7944
|
-
const { createPiCodingAgentHarness } = await import("./createHarness-
|
|
8040
|
+
const { createPiCodingAgentHarness } = await import("./createHarness-GMBZZPTN.js");
|
|
7945
8041
|
return createPiCodingAgentHarness({
|
|
7946
8042
|
...factoryInput,
|
|
7947
8043
|
pi,
|
|
@@ -8015,7 +8111,7 @@ var AgentSessionEventQueue = class {
|
|
|
8015
8111
|
const event = this.pending.shift();
|
|
8016
8112
|
if (event) return { done: false, value: event };
|
|
8017
8113
|
if (this.ended) return { done: true, value: void 0 };
|
|
8018
|
-
return await new Promise((
|
|
8114
|
+
return await new Promise((resolve10) => this.waiters.push(resolve10));
|
|
8019
8115
|
},
|
|
8020
8116
|
return: async () => {
|
|
8021
8117
|
this.close();
|
|
@@ -8204,20 +8300,27 @@ var EmbeddedAgentGateway = class {
|
|
|
8204
8300
|
if (input.agentTypeId && !this.runtime.compiledById.has(input.agentTypeId)) {
|
|
8205
8301
|
throw new AgentGatewayError(AgentGatewayErrorCode.AGENT_TYPE_UNKNOWN, "agent type is not available");
|
|
8206
8302
|
}
|
|
8207
|
-
const cursor = input.cursor ? this.decodeCursor(input.cursor, claim.workspaceScopeId, input.agentTypeId, normalizedLimit) : void 0;
|
|
8303
|
+
const cursor = input.cursor ? this.decodeCursor(input.cursor, claim.workspaceScopeId, input.agentTypeId, normalizedLimit) : { depth: 0, after: void 0 };
|
|
8208
8304
|
const agents = input.agentTypeId ? [input.agentTypeId] : [...this.runtime.compiledById.keys()];
|
|
8305
|
+
const perAgentLimit = cursor.depth + normalizedLimit + 1;
|
|
8209
8306
|
const rows = [];
|
|
8210
8307
|
for (const agentTypeId of agents) {
|
|
8211
|
-
const listed = await this.runtime.listSessionSummaries(agentTypeId, input.scope, claim);
|
|
8308
|
+
const listed = await this.runtime.listSessionSummaries(agentTypeId, input.scope, claim, { limit: perAgentLimit });
|
|
8212
8309
|
for (const item of listed) {
|
|
8213
8310
|
const ref = { agentTypeId, sessionId: item.id };
|
|
8214
8311
|
rows.push(summaryFromLegacy(ref, item, this.runtime.activity.get(claim.workspaceScopeId, ref)));
|
|
8215
8312
|
}
|
|
8216
8313
|
}
|
|
8217
8314
|
rows.sort(compareSessions);
|
|
8218
|
-
const eligible = cursor ? rows.filter((row) => isAfterCursor(row, cursor)) : rows;
|
|
8315
|
+
const eligible = cursor.after ? rows.filter((row) => isAfterCursor(row, cursor.after)) : rows;
|
|
8219
8316
|
const sessions = eligible.slice(0, normalizedLimit);
|
|
8220
|
-
const nextCursor = eligible.length > sessions.length && sessions.length > 0 ? this.encodeCursor(
|
|
8317
|
+
const nextCursor = eligible.length > sessions.length && sessions.length > 0 ? this.encodeCursor(
|
|
8318
|
+
claim.workspaceScopeId,
|
|
8319
|
+
input.agentTypeId,
|
|
8320
|
+
normalizedLimit,
|
|
8321
|
+
cursor.depth + sessions.length,
|
|
8322
|
+
sessions.at(-1)
|
|
8323
|
+
) : void 0;
|
|
8221
8324
|
return { sessions, ...nextCursor ? { nextCursor } : {} };
|
|
8222
8325
|
}
|
|
8223
8326
|
async createSession(input) {
|
|
@@ -8760,8 +8863,8 @@ var EmbeddedAgentGateway = class {
|
|
|
8760
8863
|
const key = agentSessionKey(workspaceScopeId, ref);
|
|
8761
8864
|
const previous = this.writerTails.get(key) ?? Promise.resolve();
|
|
8762
8865
|
let release;
|
|
8763
|
-
const current = new Promise((
|
|
8764
|
-
release =
|
|
8866
|
+
const current = new Promise((resolve10) => {
|
|
8867
|
+
release = resolve10;
|
|
8765
8868
|
});
|
|
8766
8869
|
const tail = previous.then(() => current);
|
|
8767
8870
|
this.writerTails.set(key, tail);
|
|
@@ -8773,11 +8876,12 @@ var EmbeddedAgentGateway = class {
|
|
|
8773
8876
|
if (this.writerTails.get(key) === tail) this.writerTails.delete(key);
|
|
8774
8877
|
}
|
|
8775
8878
|
}
|
|
8776
|
-
encodeCursor(workspaceScopeId, agentTypeId, limit, last) {
|
|
8879
|
+
encodeCursor(workspaceScopeId, agentTypeId, limit, depth, last) {
|
|
8777
8880
|
const payload = JSON.stringify({
|
|
8778
8881
|
workspaceScopeId,
|
|
8779
8882
|
agentTypeId: agentTypeId ?? null,
|
|
8780
8883
|
limit,
|
|
8884
|
+
depth,
|
|
8781
8885
|
updatedAt: last.updatedAt,
|
|
8782
8886
|
lastAgentTypeId: last.ref.agentTypeId,
|
|
8783
8887
|
sessionId: last.ref.sessionId
|
|
@@ -8793,11 +8897,14 @@ var EmbeddedAgentGateway = class {
|
|
|
8793
8897
|
const expected = createHash6("sha256").update(`${this.cursorSecret}:${encoded}`).digest("base64url");
|
|
8794
8898
|
if (signature !== expected) throw new Error("signature");
|
|
8795
8899
|
const decoded = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8"));
|
|
8796
|
-
if (decoded.workspaceScopeId !== workspaceScopeId || decoded.agentTypeId !== (agentTypeId ?? null) || decoded.limit !== limit || typeof decoded.updatedAt !== "number" || typeof decoded.lastAgentTypeId !== "string" || typeof decoded.sessionId !== "string") throw new Error("binding");
|
|
8900
|
+
if (decoded.workspaceScopeId !== workspaceScopeId || decoded.agentTypeId !== (agentTypeId ?? null) || decoded.limit !== limit || typeof decoded.depth !== "number" || !Number.isInteger(decoded.depth) || decoded.depth < 0 || typeof decoded.updatedAt !== "number" || typeof decoded.lastAgentTypeId !== "string" || typeof decoded.sessionId !== "string") throw new Error("binding");
|
|
8797
8901
|
return {
|
|
8798
|
-
|
|
8799
|
-
|
|
8800
|
-
|
|
8902
|
+
depth: decoded.depth,
|
|
8903
|
+
after: {
|
|
8904
|
+
updatedAt: decoded.updatedAt,
|
|
8905
|
+
agentTypeId: decoded.lastAgentTypeId,
|
|
8906
|
+
sessionId: decoded.sessionId
|
|
8907
|
+
}
|
|
8801
8908
|
};
|
|
8802
8909
|
} catch {
|
|
8803
8910
|
throw new AgentGatewayError(AgentGatewayErrorCode.AGENT_SESSION_CURSOR_INVALID, "session cursor is invalid");
|
|
@@ -8819,7 +8926,7 @@ function closedError() {
|
|
|
8819
8926
|
return new AgentGatewayError(AgentGatewayErrorCode.AGENT_GATEWAY_CLOSED, "agent host is closing");
|
|
8820
8927
|
}
|
|
8821
8928
|
function delay2(ms) {
|
|
8822
|
-
return new Promise((
|
|
8929
|
+
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
8823
8930
|
}
|
|
8824
8931
|
var EnvironmentLeaseManager = class {
|
|
8825
8932
|
constructor(adapter) {
|
|
@@ -9251,7 +9358,7 @@ function sessionChangesRoutes(app, opts, done) {
|
|
|
9251
9358
|
}
|
|
9252
9359
|
|
|
9253
9360
|
// src/server/http/routes/skills.ts
|
|
9254
|
-
import { dirname as dirname6, isAbsolute as isAbsolute6, relative as relative7, resolve as
|
|
9361
|
+
import { dirname as dirname6, isAbsolute as isAbsolute6, relative as relative7, resolve as resolve7, sep as sep6 } from "node:path";
|
|
9255
9362
|
import {
|
|
9256
9363
|
DefaultPackageManager,
|
|
9257
9364
|
getAgentDir,
|
|
@@ -9260,12 +9367,12 @@ import {
|
|
|
9260
9367
|
var CACHE_TTL_MS = 3e4;
|
|
9261
9368
|
function provisionedWorkspaceRoots(additionalSkillPaths) {
|
|
9262
9369
|
const userSkillsSuffix = `${sep6}.agents${sep6}skills`;
|
|
9263
|
-
return additionalSkillPaths.map((skillPath) =>
|
|
9370
|
+
return additionalSkillPaths.map((skillPath) => resolve7(skillPath)).filter((skillPath) => skillPath.endsWith(userSkillsSuffix)).map((skillPath) => dirname6(dirname6(skillPath)));
|
|
9264
9371
|
}
|
|
9265
9372
|
function pathForWorkspaceEditor(workspace, filePath, additionalSkillPaths = []) {
|
|
9266
9373
|
const roots = [workspace.root, ...provisionedWorkspaceRoots(additionalSkillPaths)];
|
|
9267
9374
|
for (const root of roots) {
|
|
9268
|
-
const pathWithinWorkspace = relative7(
|
|
9375
|
+
const pathWithinWorkspace = relative7(resolve7(root), resolve7(filePath));
|
|
9269
9376
|
if (pathWithinWorkspace === "" || pathWithinWorkspace === ".." || pathWithinWorkspace.startsWith(`..${sep6}`) || isAbsolute6(pathWithinWorkspace)) {
|
|
9270
9377
|
continue;
|
|
9271
9378
|
}
|
|
@@ -9491,7 +9598,7 @@ function createAgentHostRuntimeCapabilityProjection(input) {
|
|
|
9491
9598
|
);
|
|
9492
9599
|
return { scope, claim, resolved };
|
|
9493
9600
|
};
|
|
9494
|
-
const
|
|
9601
|
+
const resolve10 = async (request, agentTypeId, sessionId) => {
|
|
9495
9602
|
if (sessionId) {
|
|
9496
9603
|
const { scope: scope2 } = await authorize(request);
|
|
9497
9604
|
const pinned = await gateway.resolveHostSessionBinding(scope2, { agentTypeId, sessionId });
|
|
@@ -9513,7 +9620,7 @@ function createAgentHostRuntimeCapabilityProjection(input) {
|
|
|
9513
9620
|
}
|
|
9514
9621
|
},
|
|
9515
9622
|
async resolveBinding({ request, agentTypeId, sessionId }) {
|
|
9516
|
-
const { claim, binding } = await
|
|
9623
|
+
const { claim, binding } = await resolve10(request, agentTypeId, sessionId);
|
|
9517
9624
|
const skillResourceSnapshotPromise = binding.scope.getSkillResourceSnapshot?.({
|
|
9518
9625
|
scope: claim,
|
|
9519
9626
|
sessionId,
|
|
@@ -9577,7 +9684,7 @@ function createAgentHostRuntimeCapabilityProjection(input) {
|
|
|
9577
9684
|
};
|
|
9578
9685
|
},
|
|
9579
9686
|
async describeAgent({ request, agentTypeId }) {
|
|
9580
|
-
const { claim } = await authorizeAgentAccess(request, agentTypeId);
|
|
9687
|
+
const { claim, resolved } = await authorizeAgentAccess(request, agentTypeId);
|
|
9581
9688
|
const spec = runtime.compiledById.get(agentTypeId);
|
|
9582
9689
|
if (!spec) {
|
|
9583
9690
|
throw new AgentGatewayError(AgentGatewayErrorCode.AGENT_TYPE_UNKNOWN, "agent type is not available");
|
|
@@ -9588,28 +9695,39 @@ function createAgentHostRuntimeCapabilityProjection(input) {
|
|
|
9588
9695
|
const refs = mcpGrants.getMcpServerRefs(agentTypeId) ?? [];
|
|
9589
9696
|
if (refs.length > 0) {
|
|
9590
9697
|
const listed = await mcpGrants.store.listGrants(claim.workspaceScopeId);
|
|
9591
|
-
const
|
|
9698
|
+
const resolved2 = resolveAgentMcpGrants({
|
|
9592
9699
|
workspaceId: claim.workspaceScopeId,
|
|
9593
9700
|
agentTypeId,
|
|
9594
9701
|
mcpServerRefs: refs,
|
|
9595
9702
|
grants: listed.grants,
|
|
9596
9703
|
catalog: mcpGrants.catalog
|
|
9597
9704
|
});
|
|
9598
|
-
mcpServers =
|
|
9705
|
+
mcpServers = resolved2.connectors.map((connector) => ({
|
|
9599
9706
|
id: connector.connectorId,
|
|
9600
9707
|
tools: connector.allowedTools
|
|
9601
9708
|
}));
|
|
9602
9709
|
}
|
|
9603
9710
|
}
|
|
9711
|
+
const { refs: instructionFiles, withheld } = legacy ? { refs: [], withheld: [] } : await resolveAgentInstructionFileRefs({
|
|
9712
|
+
sources: spec.instructionSources,
|
|
9713
|
+
workspaceRoot: resolved.environment.workspaceRoot
|
|
9714
|
+
});
|
|
9715
|
+
for (const entry of withheld) {
|
|
9716
|
+
request.log?.warn?.({
|
|
9717
|
+
agentTypeId,
|
|
9718
|
+
code: entry.code,
|
|
9719
|
+
workspaceScopeId: claim.workspaceScopeId
|
|
9720
|
+
}, `${entry.message}; its persona instructions are not linkable here`);
|
|
9721
|
+
}
|
|
9604
9722
|
return {
|
|
9605
9723
|
agentTypeId,
|
|
9606
9724
|
model: legacy ? null : spec.model?.preferred ?? null,
|
|
9607
|
-
instructionFiles
|
|
9725
|
+
instructionFiles,
|
|
9608
9726
|
mcpServers
|
|
9609
9727
|
};
|
|
9610
9728
|
},
|
|
9611
9729
|
async executeCommand({ request, agentTypeId, requestId, sessionId, name, args }) {
|
|
9612
|
-
const { scope, binding } = await
|
|
9730
|
+
const { scope, binding } = await resolve10(request, agentTypeId, sessionId);
|
|
9613
9731
|
if (!binding.composition.harness.executeSlashCommand) {
|
|
9614
9732
|
throw new AgentGatewayError(
|
|
9615
9733
|
AgentGatewayErrorCode.AGENT_COMMAND_INVALID_STATE,
|
|
@@ -9810,7 +9928,7 @@ function createAgentHostRuntimeCapabilityRoutes(projection) {
|
|
|
9810
9928
|
return async (app) => {
|
|
9811
9929
|
app.setErrorHandler((error, _request, reply) => sendError(reply, error));
|
|
9812
9930
|
const cache = /* @__PURE__ */ new WeakMap();
|
|
9813
|
-
const
|
|
9931
|
+
const resolve10 = (request, agentTypeId, sessionId) => {
|
|
9814
9932
|
let entries = cache.get(request);
|
|
9815
9933
|
if (!entries) {
|
|
9816
9934
|
entries = /* @__PURE__ */ new Map();
|
|
@@ -9829,40 +9947,40 @@ function createAgentHostRuntimeCapabilityRoutes(projection) {
|
|
|
9829
9947
|
path: "/api/v1/agents/:agentTypeId/models",
|
|
9830
9948
|
filterModels: projection.filterModels,
|
|
9831
9949
|
authorizeRequest: async (request) => {
|
|
9832
|
-
await
|
|
9950
|
+
await resolve10(request, agentId(request));
|
|
9833
9951
|
}
|
|
9834
9952
|
});
|
|
9835
9953
|
await app.register(skillsRoutes, {
|
|
9836
9954
|
path: "/api/v1/agents/:agentTypeId/skills",
|
|
9837
9955
|
authorizeRequest: async (request) => {
|
|
9838
|
-
await
|
|
9956
|
+
await resolve10(request, agentId(request));
|
|
9839
9957
|
},
|
|
9840
|
-
getWorkspace: async (request) => (await
|
|
9958
|
+
getWorkspace: async (request) => (await resolve10(request, agentId(request))).workspace,
|
|
9841
9959
|
getAdditionalSkillPaths: async (request) => [
|
|
9842
|
-
...(await
|
|
9843
|
-
...(await
|
|
9960
|
+
...(await resolve10(request, agentId(request))).additionalSkillPaths ?? [],
|
|
9961
|
+
...(await resolve10(request, agentId(request))).pi?.additionalSkillPaths ?? []
|
|
9844
9962
|
],
|
|
9845
|
-
getPiPackages: async (request) => (await
|
|
9846
|
-
getNoSkills: async (request) => (await
|
|
9847
|
-
getSkillResourceSnapshot: async (request) => (await
|
|
9963
|
+
getPiPackages: async (request) => (await resolve10(request, agentId(request))).pi?.packages,
|
|
9964
|
+
getNoSkills: async (request) => (await resolve10(request, agentId(request))).pi?.noSkills,
|
|
9965
|
+
getSkillResourceSnapshot: async (request) => (await resolve10(request, agentId(request))).skillResourceSnapshot
|
|
9848
9966
|
});
|
|
9849
9967
|
await app.register(catalogRoutes, {
|
|
9850
9968
|
path: "/api/v1/agents/:agentTypeId/tools",
|
|
9851
9969
|
authorizeRequest: async (request) => {
|
|
9852
|
-
await
|
|
9970
|
+
await resolve10(request, agentId(request));
|
|
9853
9971
|
},
|
|
9854
|
-
getTools: async (request) => [...(await
|
|
9972
|
+
getTools: async (request) => [...(await resolve10(request, agentId(request))).tools]
|
|
9855
9973
|
});
|
|
9856
9974
|
await app.register(systemPromptRoutes, {
|
|
9857
9975
|
path: "/api/v1/agents/:agentTypeId/sessions/:sessionId/system-prompt",
|
|
9858
9976
|
sessionIdParam: "sessionId",
|
|
9859
9977
|
authorizeRequest: async (request) => {
|
|
9860
9978
|
const value = request.params;
|
|
9861
|
-
await
|
|
9979
|
+
await resolve10(request, value.agentTypeId, value.sessionId);
|
|
9862
9980
|
},
|
|
9863
9981
|
getHarness: async (request) => {
|
|
9864
9982
|
const value = request.params;
|
|
9865
|
-
return (await
|
|
9983
|
+
return (await resolve10(request, value.agentTypeId, value.sessionId)).harness;
|
|
9866
9984
|
}
|
|
9867
9985
|
});
|
|
9868
9986
|
await app.register(sessionChangesRoutes, {
|
|
@@ -9871,11 +9989,11 @@ function createAgentHostRuntimeCapabilityRoutes(projection) {
|
|
|
9871
9989
|
tracker: projection.sessionChangesTracker,
|
|
9872
9990
|
authorizeRequest: async (request) => {
|
|
9873
9991
|
const value = request.params;
|
|
9874
|
-
await
|
|
9992
|
+
await resolve10(request, value.agentTypeId, value.sessionId);
|
|
9875
9993
|
},
|
|
9876
9994
|
resolveScope: async (request, sessionId) => {
|
|
9877
9995
|
const value = request.params;
|
|
9878
|
-
const binding = await
|
|
9996
|
+
const binding = await resolve10(request, value.agentTypeId, sessionId);
|
|
9879
9997
|
return {
|
|
9880
9998
|
workspaceScopeId: binding.runContext.workspaceId,
|
|
9881
9999
|
agentTypeId: value.agentTypeId,
|
|
@@ -9886,9 +10004,9 @@ function createAgentHostRuntimeCapabilityRoutes(projection) {
|
|
|
9886
10004
|
await app.register(readyStatusRoutes, {
|
|
9887
10005
|
path: "/api/v1/agents/:agentTypeId/ready-status",
|
|
9888
10006
|
authorizeRequest: async (request) => {
|
|
9889
|
-
await
|
|
10007
|
+
await resolve10(request, agentId(request));
|
|
9890
10008
|
},
|
|
9891
|
-
getTracker: async (request) => (await
|
|
10009
|
+
getTracker: async (request) => (await resolve10(request, agentId(request))).readyTracker,
|
|
9892
10010
|
registerStreamClose: projection.registerSubscription
|
|
9893
10011
|
});
|
|
9894
10012
|
app.get("/api/v1/agents/:agentTypeId/describe", async (request, reply) => {
|
|
@@ -9909,7 +10027,7 @@ function createAgentHostRuntimeCapabilityRoutes(projection) {
|
|
|
9909
10027
|
try {
|
|
9910
10028
|
const query = request.query;
|
|
9911
10029
|
const sessionId = typeof query.sessionId === "string" && query.sessionId.trim() ? query.sessionId.trim() : "default";
|
|
9912
|
-
const binding = await
|
|
10030
|
+
const binding = await resolve10(
|
|
9913
10031
|
request,
|
|
9914
10032
|
value.agentTypeId,
|
|
9915
10033
|
typeof query.sessionId === "string" && query.sessionId.trim() ? sessionId : void 0
|
|
@@ -10983,12 +11101,12 @@ async function runWithWorkspaceAgentLease(input) {
|
|
|
10983
11101
|
const operations = /* @__PURE__ */ new Set();
|
|
10984
11102
|
const cleanups = /* @__PURE__ */ new Set();
|
|
10985
11103
|
let signalDrain;
|
|
10986
|
-
const drainRequested = new Promise((
|
|
10987
|
-
signalDrain =
|
|
11104
|
+
const drainRequested = new Promise((resolve10) => {
|
|
11105
|
+
signalDrain = resolve10;
|
|
10988
11106
|
});
|
|
10989
11107
|
let signalRevocation;
|
|
10990
|
-
const revocation = new Promise((
|
|
10991
|
-
signalRevocation =
|
|
11108
|
+
const revocation = new Promise((resolve10) => {
|
|
11109
|
+
signalRevocation = resolve10;
|
|
10992
11110
|
});
|
|
10993
11111
|
let drainDeadline;
|
|
10994
11112
|
const registerCleanup = (cleanup) => {
|
|
@@ -11043,8 +11161,8 @@ async function runWithWorkspaceAgentLease(input) {
|
|
|
11043
11161
|
const remainingMs = Math.max(0, drainDeadline - Date.now());
|
|
11044
11162
|
const outcome = await Promise.race([
|
|
11045
11163
|
Promise.allSettled(pending).then((results) => ({ kind: "settled", results })),
|
|
11046
|
-
new Promise((
|
|
11047
|
-
setTimeout(() =>
|
|
11164
|
+
new Promise((resolve10) => {
|
|
11165
|
+
setTimeout(() => resolve10({ kind: "expired" }), remainingMs);
|
|
11048
11166
|
})
|
|
11049
11167
|
]);
|
|
11050
11168
|
if (outcome.kind === "expired") break;
|
|
@@ -11326,9 +11444,9 @@ function createRuntime(options, compiledAgents) {
|
|
|
11326
11444
|
},
|
|
11327
11445
|
activity,
|
|
11328
11446
|
shutdownGraceMs: graceMs,
|
|
11329
|
-
listSessionSummaries(agentTypeId, scope, claim) {
|
|
11447
|
+
listSessionSummaries(agentTypeId, scope, claim, options2) {
|
|
11330
11448
|
runtime.assertOpen();
|
|
11331
|
-
return inventory.list(agentTypeId, scope, claim);
|
|
11449
|
+
return inventory.list(agentTypeId, scope, claim, options2);
|
|
11332
11450
|
},
|
|
11333
11451
|
isDraining: () => draining,
|
|
11334
11452
|
assertOpen() {
|
|
@@ -11506,8 +11624,8 @@ function createRuntime(options, compiledAgents) {
|
|
|
11506
11624
|
if (work.length === 0) return;
|
|
11507
11625
|
const completed = await Promise.race([
|
|
11508
11626
|
Promise.allSettled(work).then((results) => ({ completed: true, results })),
|
|
11509
|
-
new Promise((
|
|
11510
|
-
setTimeout(() =>
|
|
11627
|
+
new Promise((resolve10) => {
|
|
11628
|
+
setTimeout(() => resolve10({ completed: false }), graceMs);
|
|
11511
11629
|
})
|
|
11512
11630
|
]);
|
|
11513
11631
|
if (completed.completed) {
|
|
@@ -11550,8 +11668,8 @@ function createRuntime(options, compiledAgents) {
|
|
|
11550
11668
|
runtime.assertOpen();
|
|
11551
11669
|
let resolveEffect;
|
|
11552
11670
|
let rejectEffect;
|
|
11553
|
-
const effect = new Promise((
|
|
11554
|
-
resolveEffect =
|
|
11671
|
+
const effect = new Promise((resolve10, reject) => {
|
|
11672
|
+
resolveEffect = resolve10;
|
|
11555
11673
|
rejectEffect = reject;
|
|
11556
11674
|
});
|
|
11557
11675
|
finiteEffects.set(effect, key);
|
|
@@ -11567,8 +11685,8 @@ function createRuntime(options, compiledAgents) {
|
|
|
11567
11685
|
async runBindingOperation(bindingKey, operation) {
|
|
11568
11686
|
const previous = bindingOperationTails.get(bindingKey) ?? Promise.resolve();
|
|
11569
11687
|
let release;
|
|
11570
|
-
const current = new Promise((
|
|
11571
|
-
release =
|
|
11688
|
+
const current = new Promise((resolve10) => {
|
|
11689
|
+
release = resolve10;
|
|
11572
11690
|
});
|
|
11573
11691
|
const tail = previous.then(() => current);
|
|
11574
11692
|
bindingOperationTails.set(bindingKey, tail);
|
|
@@ -11599,7 +11717,7 @@ function createRuntime(options, compiledAgents) {
|
|
|
11599
11717
|
));
|
|
11600
11718
|
const bindingCleanupResult = await Promise.race([
|
|
11601
11719
|
bindingCleanup.then((results) => ({ completed: true, results })),
|
|
11602
|
-
new Promise((
|
|
11720
|
+
new Promise((resolve10) => setTimeout(() => resolve10({ completed: false }), graceMs))
|
|
11603
11721
|
]);
|
|
11604
11722
|
if (bindingCleanupResult.completed) {
|
|
11605
11723
|
const failed = bindingCleanupResult.results.find(
|
|
@@ -11615,7 +11733,7 @@ function createRuntime(options, compiledAgents) {
|
|
|
11615
11733
|
try {
|
|
11616
11734
|
await Promise.race([
|
|
11617
11735
|
options.runtimeModeAdapter.dispose?.() ?? Promise.resolve(),
|
|
11618
|
-
new Promise((
|
|
11736
|
+
new Promise((resolve10) => setTimeout(resolve10, graceMs))
|
|
11619
11737
|
]);
|
|
11620
11738
|
} catch (error) {
|
|
11621
11739
|
firstError ??= error;
|
|
@@ -11880,7 +11998,7 @@ async function registerAgentHostEnvironmentRoutes(app, options) {
|
|
|
11880
11998
|
|
|
11881
11999
|
// src/server/harness/pi-coding-agent/pluginLoader.ts
|
|
11882
12000
|
import { readdir as readdir4, stat as stat6, readFile as readFile5 } from "node:fs/promises";
|
|
11883
|
-
import { join as join8, extname, resolve as
|
|
12001
|
+
import { join as join8, extname, resolve as resolve8, sep as sep7, relative as relative8 } from "node:path";
|
|
11884
12002
|
import { homedir } from "node:os";
|
|
11885
12003
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
11886
12004
|
var VALID_EXTENSIONS = /* @__PURE__ */ new Set([".js", ".mjs"]);
|
|
@@ -11950,8 +12068,8 @@ async function loadNpmPlugin(pkgDir, importFn) {
|
|
|
11950
12068
|
if (!await fileExists(pkgJsonPath)) return [];
|
|
11951
12069
|
const pkgJson = JSON.parse(await readFile5(pkgJsonPath, "utf-8"));
|
|
11952
12070
|
const main = pkgJson.main ?? "index.js";
|
|
11953
|
-
const resolvedMain =
|
|
11954
|
-
const resolvedPkgDir =
|
|
12071
|
+
const resolvedMain = resolve8(pkgDir, main);
|
|
12072
|
+
const resolvedPkgDir = resolve8(pkgDir);
|
|
11955
12073
|
if (resolvedMain !== resolvedPkgDir && !resolvedMain.startsWith(resolvedPkgDir + sep7)) {
|
|
11956
12074
|
return [];
|
|
11957
12075
|
}
|
|
@@ -12090,9 +12208,9 @@ function withRuntimeEnvContributions(runtimeBundle, baseContext, contributions,
|
|
|
12090
12208
|
// src/server/piResourceDigest.ts
|
|
12091
12209
|
import { createHash as createHash7 } from "node:crypto";
|
|
12092
12210
|
import { constants as constants3 } from "node:fs";
|
|
12093
|
-
import { lstat as lstat4, open as open2, opendir, realpath as
|
|
12211
|
+
import { lstat as lstat4, open as open2, opendir, realpath as realpath6, stat as statPath } from "node:fs/promises";
|
|
12094
12212
|
import { homedir as homedir2 } from "node:os";
|
|
12095
|
-
import { dirname as dirname8, isAbsolute as isAbsolute7, join as join9, parse, relative as relative9, resolve as
|
|
12213
|
+
import { dirname as dirname8, isAbsolute as isAbsolute7, join as join9, parse, relative as relative9, resolve as resolve9, sep as sep8 } from "node:path";
|
|
12096
12214
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
12097
12215
|
import { DefaultPackageManager as DefaultPackageManager2, getAgentDir as getAgentDir2, loadProjectContextFiles } from "@mariozechner/pi-coding-agent";
|
|
12098
12216
|
var DEFAULT_PI_RESOURCE_DIGEST_LIMITS = Object.freeze({
|
|
@@ -12290,11 +12408,11 @@ function resolvePiPath(input, baseDir) {
|
|
|
12290
12408
|
let normalized = input.trim();
|
|
12291
12409
|
if (normalized === "~") normalized = homedir2();
|
|
12292
12410
|
else if (normalized.startsWith("~/") || process.platform === "win32" && normalized.startsWith("~\\")) {
|
|
12293
|
-
normalized =
|
|
12411
|
+
normalized = resolve9(homedir2(), normalized.slice(2));
|
|
12294
12412
|
} else if (/^file:\/\//.test(normalized)) {
|
|
12295
12413
|
normalized = fileURLToPath7(normalized);
|
|
12296
12414
|
}
|
|
12297
|
-
return isAbsolute7(normalized) ?
|
|
12415
|
+
return isAbsolute7(normalized) ? resolve9(normalized) : resolve9(baseDir, normalized);
|
|
12298
12416
|
}
|
|
12299
12417
|
async function findContainingArtifactRoot(path, authorizedRoots) {
|
|
12300
12418
|
let current = dirname8(path);
|
|
@@ -12302,7 +12420,7 @@ async function findContainingArtifactRoot(path, authorizedRoots) {
|
|
|
12302
12420
|
if (!boundary) throw stableError(ErrorCode.enum.PATH_ESCAPE, 403, `Pi resource path is outside authorized roots: ${path}`);
|
|
12303
12421
|
while (isContained(current, boundary)) {
|
|
12304
12422
|
try {
|
|
12305
|
-
const packageStat = await lstat4(
|
|
12423
|
+
const packageStat = await lstat4(resolve9(current, "package.json"));
|
|
12306
12424
|
if (packageStat.isSymbolicLink()) {
|
|
12307
12425
|
throw stableError(ErrorCode.enum.PATH_SYMLINK_ESCAPE, 403, `Pi resource package manifest cannot be a symlink: ${current}`);
|
|
12308
12426
|
}
|
|
@@ -12316,7 +12434,7 @@ async function findContainingArtifactRoot(path, authorizedRoots) {
|
|
|
12316
12434
|
return dirname8(path);
|
|
12317
12435
|
}
|
|
12318
12436
|
async function hashLocalResource(state, path, logicalPath, depth) {
|
|
12319
|
-
const absolutePath =
|
|
12437
|
+
const absolutePath = resolve9(path);
|
|
12320
12438
|
await assertContainedWithoutSymlinks(absolutePath, state.authorizedRoots);
|
|
12321
12439
|
if (depth > state.limits.maxDepth) {
|
|
12322
12440
|
throw limitError(`Pi resource tree exceeds maximum depth ${state.limits.maxDepth}`);
|
|
@@ -12340,7 +12458,7 @@ async function hashLocalResource(state, path, logicalPath, depth) {
|
|
|
12340
12458
|
}
|
|
12341
12459
|
if (stat7.isDirectory()) {
|
|
12342
12460
|
frameString(state.hash, "directory", logicalPath);
|
|
12343
|
-
const openedTarget = await
|
|
12461
|
+
const openedTarget = await realpath6(absolutePath);
|
|
12344
12462
|
if (!mostSpecificContainingRoot(openedTarget, state.authorizedRoots)) {
|
|
12345
12463
|
throw stableError(ErrorCode.enum.PATH_SYMLINK_ESCAPE, 403, `Pi resource resolves outside authorized roots: ${absolutePath}`);
|
|
12346
12464
|
}
|
|
@@ -12359,12 +12477,12 @@ async function hashLocalResource(state, path, logicalPath, depth) {
|
|
|
12359
12477
|
frameString(state.hash, "entry-name", entry.name);
|
|
12360
12478
|
await hashLocalResource(
|
|
12361
12479
|
state,
|
|
12362
|
-
|
|
12480
|
+
resolve9(openedTarget, entry.name),
|
|
12363
12481
|
logicalPath === "." ? entry.name : `${logicalPath}/${entry.name}`,
|
|
12364
12482
|
depth + 1
|
|
12365
12483
|
);
|
|
12366
12484
|
}
|
|
12367
|
-
const afterTarget = await
|
|
12485
|
+
const afterTarget = await realpath6(absolutePath);
|
|
12368
12486
|
if (afterTarget !== openedTarget) throw changedError(absolutePath);
|
|
12369
12487
|
assertSameFile(stat7, await statPath(afterTarget), absolutePath);
|
|
12370
12488
|
return;
|
|
@@ -12384,7 +12502,7 @@ async function hashLocalResource(state, path, logicalPath, depth) {
|
|
|
12384
12502
|
try {
|
|
12385
12503
|
const opened = await handle.stat();
|
|
12386
12504
|
assertSameFile(stat7, opened, absolutePath);
|
|
12387
|
-
const openedTarget = await
|
|
12505
|
+
const openedTarget = await realpath6(absolutePath);
|
|
12388
12506
|
if (!mostSpecificContainingRoot(openedTarget, state.authorizedRoots)) {
|
|
12389
12507
|
throw stableError(ErrorCode.enum.PATH_SYMLINK_ESCAPE, 403, `Pi resource resolves outside authorized roots: ${absolutePath}`);
|
|
12390
12508
|
}
|
|
@@ -12399,7 +12517,7 @@ async function hashLocalResource(state, path, logicalPath, depth) {
|
|
|
12399
12517
|
}
|
|
12400
12518
|
const after = await handle.stat();
|
|
12401
12519
|
assertSameFile(opened, after, absolutePath);
|
|
12402
|
-
const afterTarget = await
|
|
12520
|
+
const afterTarget = await realpath6(absolutePath);
|
|
12403
12521
|
if (afterTarget !== openedTarget) throw changedError(absolutePath);
|
|
12404
12522
|
assertSameFile(after, await statPath(afterTarget), absolutePath);
|
|
12405
12523
|
state.bytes += offset;
|
|
@@ -12415,12 +12533,12 @@ async function assertContainedWithoutSymlinks(path, roots) {
|
|
|
12415
12533
|
if (!root) {
|
|
12416
12534
|
throw stableError(ErrorCode.enum.PATH_ESCAPE, 403, `Pi resource path is outside authorized roots: ${path}`);
|
|
12417
12535
|
}
|
|
12418
|
-
const absolutePath =
|
|
12536
|
+
const absolutePath = resolve9(path);
|
|
12419
12537
|
const pathRoot = parse(absolutePath).root;
|
|
12420
12538
|
const segments = relative9(pathRoot, absolutePath).split(sep8).filter(Boolean);
|
|
12421
12539
|
let current = pathRoot;
|
|
12422
12540
|
for (const segment of segments) {
|
|
12423
|
-
current =
|
|
12541
|
+
current = resolve9(current, segment);
|
|
12424
12542
|
try {
|
|
12425
12543
|
if ((await lstat4(current)).isSymbolicLink()) {
|
|
12426
12544
|
throw stableError(ErrorCode.enum.PATH_SYMLINK_ESCAPE, 403, `Pi resource symlinks are not allowed: ${current}`);
|
|
@@ -12435,7 +12553,7 @@ function mostSpecificContainingRoot(path, roots) {
|
|
|
12435
12553
|
return roots.filter((root) => isContained(path, root)).sort((left, right) => right.length - left.length)[0];
|
|
12436
12554
|
}
|
|
12437
12555
|
function isContained(path, root) {
|
|
12438
|
-
const value = relative9(
|
|
12556
|
+
const value = relative9(resolve9(root), resolve9(path));
|
|
12439
12557
|
return value === "" || value !== ".." && !value.startsWith(`..${sep8}`) && !isAbsolute7(value);
|
|
12440
12558
|
}
|
|
12441
12559
|
function frameString(hash, tag, value) {
|
|
@@ -13528,6 +13646,7 @@ export {
|
|
|
13528
13646
|
materializeAgentDirectory,
|
|
13529
13647
|
TrustedAgentCompositionError,
|
|
13530
13648
|
createConfiguredAgentHostAgentSpec,
|
|
13649
|
+
resolveAgentInstructionFileRefs,
|
|
13531
13650
|
FleetConfigError,
|
|
13532
13651
|
loadConfiguredAgentFleet,
|
|
13533
13652
|
LEGACY_DEFAULT_AGENT_FLEET,
|