@hachej/boring-agent 0.1.79 → 0.1.80
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-LCEBDU6G.js → chunk-BNZIE26N.js} +13 -7
- package/dist/{chunk-YVON2BHN.js → chunk-CCNXYCD5.js} +3 -0
- package/dist/{chunk-Q42DWR3T.js → chunk-CUF7ELFO.js} +3 -1
- package/dist/{chunk-X4WT3TPU.js → chunk-N4ES6PVX.js} +1 -1
- package/dist/{chunk-P23XFC4W.js → chunk-UJQXCOHR.js} +1 -1
- package/dist/{chunk-RFHSFIHF.js → chunk-URRIDA6O.js} +553 -88
- package/dist/core/index.d.ts +5 -4
- package/dist/core/index.js +2 -2
- package/dist/{createHarness-XHMR3QN3.js → createHarness-EEA63XRC.js} +2 -2
- package/dist/front/index.d.ts +1 -1
- package/dist/front/index.js +2 -2
- package/dist/{harness-DD0zj704.d.ts → harness-BZW5Jiy3.d.ts} +8 -2
- package/dist/{piChatEvent-D0yuLiJh.d.ts → piChatEvent-CpoTZau1.d.ts} +13 -13
- package/dist/server/index.d.ts +95 -19
- package/dist/server/index.js +8 -6
- package/dist/server/worker/index.js +6 -6
- package/dist/shared/index.d.ts +24 -24
- package/dist/shared/index.js +7 -3
- package/dist/{workspaceAgentDispatcher-D3ZEBsH1.d.ts → workspaceAgentDispatcher-Wi6NIh2G.d.ts} +6 -3
- package/docs/ERROR_CODES.md +3 -0
- package/package.json +2 -2
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AgentDefinitionValidationError,
|
|
3
|
+
AgentDeploymentValidationError,
|
|
4
|
+
OpaqueRefSchema,
|
|
5
|
+
Sha256DigestSchema,
|
|
3
6
|
createAgentAssetDigest,
|
|
4
7
|
createAgentDefinitionDigest,
|
|
8
|
+
createAgentDeploymentDigest,
|
|
5
9
|
validateAgentDefinition,
|
|
10
|
+
validateAgentDeployment,
|
|
6
11
|
validateTool
|
|
7
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-CUF7ELFO.js";
|
|
8
13
|
import {
|
|
9
14
|
createAgentRuntimeBridge
|
|
10
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-BNZIE26N.js";
|
|
11
16
|
import {
|
|
12
17
|
sessionStreamPath
|
|
13
18
|
} from "./chunk-WSQ5QNIY.js";
|
|
@@ -22,7 +27,7 @@ import {
|
|
|
22
27
|
StopReceiptSchema,
|
|
23
28
|
extractToolUiMetadata,
|
|
24
29
|
sanitizeToolUiMetadata2 as sanitizeToolUiMetadata
|
|
25
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-UJQXCOHR.js";
|
|
26
31
|
import {
|
|
27
32
|
createLogger,
|
|
28
33
|
createPiCodingAgentHarness,
|
|
@@ -33,14 +38,15 @@ import {
|
|
|
33
38
|
registerConfiguredModelProviders,
|
|
34
39
|
setEnvDefault,
|
|
35
40
|
withPiHarnessDefaults
|
|
36
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-N4ES6PVX.js";
|
|
37
42
|
import {
|
|
38
43
|
safeCapture
|
|
39
44
|
} from "./chunk-AQBXNPMD.js";
|
|
40
45
|
import {
|
|
41
46
|
AgentDefinitionErrorCode,
|
|
47
|
+
AgentDeploymentErrorCode,
|
|
42
48
|
ErrorCode
|
|
43
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-CCNXYCD5.js";
|
|
44
50
|
|
|
45
51
|
// src/server/sandbox/direct/createDirectSandbox.ts
|
|
46
52
|
import { spawn } from "child_process";
|
|
@@ -8446,11 +8452,12 @@ function createAgentRuntimeBridge2(config, options = {}) {
|
|
|
8446
8452
|
}
|
|
8447
8453
|
return createAgentRuntimeBridge({
|
|
8448
8454
|
runtimeFactory: () => createRuntime(config, options),
|
|
8455
|
+
readiness: config.readiness,
|
|
8449
8456
|
readinessRequirements: config.readinessRequirements
|
|
8450
8457
|
});
|
|
8451
8458
|
}
|
|
8452
8459
|
async function createRuntime(config, options) {
|
|
8453
|
-
const harnessFactory = config.harnessFactory ?? (await import("./createHarness-
|
|
8460
|
+
const harnessFactory = config.harnessFactory ?? (await import("./createHarness-EEA63XRC.js")).createPiCodingAgentHarness;
|
|
8454
8461
|
const harnessInput = {
|
|
8455
8462
|
tools: config.tools ?? [],
|
|
8456
8463
|
cwd: config.workdir ?? DEFAULT_WORKDIR,
|
|
@@ -8702,15 +8709,140 @@ async function compileAgentDirectory(directory) {
|
|
|
8702
8709
|
return Object.freeze({ definition, definitionDigest, assets });
|
|
8703
8710
|
}
|
|
8704
8711
|
|
|
8712
|
+
// src/server/agentDefinition/resolveAgentDeployment.ts
|
|
8713
|
+
import { z } from "zod";
|
|
8714
|
+
var AuthorizedAgentDeploymentBindingSchema = z.object({
|
|
8715
|
+
workspaceId: OpaqueRefSchema,
|
|
8716
|
+
defaultDeploymentId: OpaqueRefSchema,
|
|
8717
|
+
workspaceCompositionDigest: Sha256DigestSchema
|
|
8718
|
+
});
|
|
8719
|
+
var RESOLVED_AGENT_DIGEST_DOMAIN = "boring-agent/resolved-agent:v1";
|
|
8720
|
+
function invalidDefinition(field, message) {
|
|
8721
|
+
return new AgentDefinitionValidationError({
|
|
8722
|
+
code: AgentDefinitionErrorCode.enum.AGENT_DEFINITION_INVALID,
|
|
8723
|
+
field,
|
|
8724
|
+
message
|
|
8725
|
+
});
|
|
8726
|
+
}
|
|
8727
|
+
function invalidDeployment(field, message) {
|
|
8728
|
+
return new AgentDeploymentValidationError({
|
|
8729
|
+
code: AgentDeploymentErrorCode.enum.AGENT_DEPLOYMENT_INVALID,
|
|
8730
|
+
field,
|
|
8731
|
+
message
|
|
8732
|
+
});
|
|
8733
|
+
}
|
|
8734
|
+
function parseBinding(raw) {
|
|
8735
|
+
const parsed = AuthorizedAgentDeploymentBindingSchema.safeParse(raw);
|
|
8736
|
+
if (parsed.success) return parsed.data;
|
|
8737
|
+
const issue = parsed.error.issues[0];
|
|
8738
|
+
const field = issue.path[0];
|
|
8739
|
+
const bindingField = typeof field === "string" ? field : "workspaceId";
|
|
8740
|
+
throw invalidDeployment(bindingField, `${bindingField} ${issue.message}`);
|
|
8741
|
+
}
|
|
8742
|
+
function assertEqual(actual, expected, field) {
|
|
8743
|
+
if (actual !== expected) {
|
|
8744
|
+
throw invalidDeployment(field, `${field} does not match the compiled agent bundle`);
|
|
8745
|
+
}
|
|
8746
|
+
}
|
|
8747
|
+
async function resolveAgentDeployment(bundle, deployment, authorizedBinding) {
|
|
8748
|
+
const binding = parseBinding(authorizedBinding);
|
|
8749
|
+
const definitionDigest = await createAgentDefinitionDigest({
|
|
8750
|
+
definition: bundle.definition,
|
|
8751
|
+
assets: bundle.assets
|
|
8752
|
+
});
|
|
8753
|
+
if (definitionDigest !== bundle.definitionDigest) {
|
|
8754
|
+
throw invalidDefinition(
|
|
8755
|
+
"definitionDigest",
|
|
8756
|
+
"definitionDigest does not match the compiled agent bundle"
|
|
8757
|
+
);
|
|
8758
|
+
}
|
|
8759
|
+
const validatedDeployment = validateAgentDeployment(deployment);
|
|
8760
|
+
if (!validatedDeployment.valid) {
|
|
8761
|
+
throw new AgentDeploymentValidationError(validatedDeployment.issues[0]);
|
|
8762
|
+
}
|
|
8763
|
+
const deploymentSnapshot = validatedDeployment.value;
|
|
8764
|
+
const deploymentDigest = await createAgentDeploymentDigest(deploymentSnapshot);
|
|
8765
|
+
assertEqual(
|
|
8766
|
+
deploymentSnapshot.definition.definitionId,
|
|
8767
|
+
bundle.definition.definitionId,
|
|
8768
|
+
"definition.definitionId"
|
|
8769
|
+
);
|
|
8770
|
+
assertEqual(
|
|
8771
|
+
deploymentSnapshot.definition.version,
|
|
8772
|
+
bundle.definition.version,
|
|
8773
|
+
"definition.version"
|
|
8774
|
+
);
|
|
8775
|
+
assertEqual(deploymentSnapshot.definition.digest, definitionDigest, "definition.digest");
|
|
8776
|
+
if (deploymentSnapshot.agentId !== "default") {
|
|
8777
|
+
throw invalidDeployment("agentId", "agentId must be default in schema version 1");
|
|
8778
|
+
}
|
|
8779
|
+
if (binding.defaultDeploymentId !== deploymentSnapshot.deploymentId) {
|
|
8780
|
+
throw invalidDeployment(
|
|
8781
|
+
"defaultDeploymentId",
|
|
8782
|
+
"defaultDeploymentId does not match the resolved deployment"
|
|
8783
|
+
);
|
|
8784
|
+
}
|
|
8785
|
+
const instructions = bundle.assets.find(
|
|
8786
|
+
(asset) => asset.path === bundle.definition.instructionsRef
|
|
8787
|
+
);
|
|
8788
|
+
if (instructions === void 0) {
|
|
8789
|
+
throw invalidDefinition(
|
|
8790
|
+
"instructionsRef",
|
|
8791
|
+
"instructionsRef must name an included verified asset"
|
|
8792
|
+
);
|
|
8793
|
+
}
|
|
8794
|
+
const resolvedDigest = await createAgentAssetDigest(JSON.stringify({
|
|
8795
|
+
domain: RESOLVED_AGENT_DIGEST_DOMAIN,
|
|
8796
|
+
workspaceId: binding.workspaceId,
|
|
8797
|
+
defaultDeploymentId: binding.defaultDeploymentId,
|
|
8798
|
+
workspaceCompositionDigest: binding.workspaceCompositionDigest,
|
|
8799
|
+
definitionDigest,
|
|
8800
|
+
deploymentDigest
|
|
8801
|
+
}));
|
|
8802
|
+
const workspace = Object.freeze({
|
|
8803
|
+
workspaceId: binding.workspaceId,
|
|
8804
|
+
defaultDeploymentId: binding.defaultDeploymentId,
|
|
8805
|
+
compositionDigest: binding.workspaceCompositionDigest
|
|
8806
|
+
});
|
|
8807
|
+
const resolvedDeployment = Object.freeze({
|
|
8808
|
+
deploymentId: deploymentSnapshot.deploymentId,
|
|
8809
|
+
version: deploymentSnapshot.version,
|
|
8810
|
+
agentId: deploymentSnapshot.agentId,
|
|
8811
|
+
digest: deploymentDigest
|
|
8812
|
+
});
|
|
8813
|
+
const definition = Object.freeze({
|
|
8814
|
+
definitionId: bundle.definition.definitionId,
|
|
8815
|
+
version: bundle.definition.version,
|
|
8816
|
+
digest: definitionDigest,
|
|
8817
|
+
instructionsRef: bundle.definition.instructionsRef
|
|
8818
|
+
});
|
|
8819
|
+
const resolvedInstructions = Object.freeze({
|
|
8820
|
+
ref: bundle.definition.instructionsRef,
|
|
8821
|
+
content: instructions.content
|
|
8822
|
+
});
|
|
8823
|
+
return Object.freeze({
|
|
8824
|
+
workspace,
|
|
8825
|
+
deployment: resolvedDeployment,
|
|
8826
|
+
definition,
|
|
8827
|
+
instructions: resolvedInstructions,
|
|
8828
|
+
resolvedDigest
|
|
8829
|
+
});
|
|
8830
|
+
}
|
|
8831
|
+
|
|
8705
8832
|
// src/server/mcp/managedAgentDelegate.ts
|
|
8706
|
-
import { randomUUID } from "crypto";
|
|
8833
|
+
import { createHash as createHash6, randomUUID } from "crypto";
|
|
8707
8834
|
var MANAGED_AGENT_MCP_ORIGIN_SURFACE = "mcp-managed-agent";
|
|
8708
|
-
var MANAGED_AGENT_MCP_DELIVERY_RULE = "M1
|
|
8709
|
-
var
|
|
8710
|
-
var
|
|
8835
|
+
var MANAGED_AGENT_MCP_DELIVERY_RULE = "M1 DELIVERY v0: delegate_task returns bounded final assistant text and at most one complete authorized inline Markdown artifact; no artifact paths, truncation, or share-link delivery.";
|
|
8836
|
+
var MAX_FINAL_ASSISTANT_TEXT_BYTES = 96 * 1024;
|
|
8837
|
+
var MAX_ARTIFACT_BYTES = 256 * 1024;
|
|
8838
|
+
var MAX_SERIALIZED_RESULT_BYTES = 384 * 1024;
|
|
8839
|
+
var MARKDOWN_MEDIA_TYPE = "text/markdown";
|
|
8840
|
+
var DEFAULT_MAX_BRIEF_BYTES = 32 * 1024;
|
|
8711
8841
|
var DEFAULT_TERMINAL_RETENTION_MS = 15 * 6e4;
|
|
8712
8842
|
var DEFAULT_MAX_DELEGATIONS = 100;
|
|
8713
8843
|
var MAX_RETAINED_PROGRESS = 100;
|
|
8844
|
+
var utf8Encoder = new TextEncoder();
|
|
8845
|
+
var strictUtf8Decoder = new TextDecoder("utf-8", { fatal: true });
|
|
8714
8846
|
var ManagedAgentMcpError = class extends Error {
|
|
8715
8847
|
code;
|
|
8716
8848
|
constructor(code, message) {
|
|
@@ -8724,8 +8856,8 @@ var ManagedAgentMcpDelegateController = class {
|
|
|
8724
8856
|
this.options = options;
|
|
8725
8857
|
this.createDelegationId = options.createDelegationId ?? randomUUID;
|
|
8726
8858
|
this.now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
8727
|
-
this.
|
|
8728
|
-
this.
|
|
8859
|
+
this.maxBriefBytes = options.maxBriefBytes ?? DEFAULT_MAX_BRIEF_BYTES;
|
|
8860
|
+
this.maxBriefChars = options.maxBriefChars;
|
|
8729
8861
|
this.terminalRetentionMs = Math.max(0, options.terminalRetentionMs ?? DEFAULT_TERMINAL_RETENTION_MS);
|
|
8730
8862
|
this.maxDelegations = Math.max(1, Math.floor(options.maxDelegations ?? DEFAULT_MAX_DELEGATIONS));
|
|
8731
8863
|
this.redactionCanaries = options.redactionCanaries ?? [];
|
|
@@ -8734,8 +8866,8 @@ var ManagedAgentMcpDelegateController = class {
|
|
|
8734
8866
|
delegations = /* @__PURE__ */ new Map();
|
|
8735
8867
|
createDelegationId;
|
|
8736
8868
|
now;
|
|
8869
|
+
maxBriefBytes;
|
|
8737
8870
|
maxBriefChars;
|
|
8738
|
-
maxInlineArtifactContentChars;
|
|
8739
8871
|
terminalRetentionMs;
|
|
8740
8872
|
maxDelegations;
|
|
8741
8873
|
redactionCanaries;
|
|
@@ -8755,19 +8887,13 @@ var ManagedAgentMcpDelegateController = class {
|
|
|
8755
8887
|
await input.onDelegationCreated?.(this.getStatus(delegationId, ctx));
|
|
8756
8888
|
this.assertNotAborted(input.signal);
|
|
8757
8889
|
const actor = await this.resolveActor(brief, ctx, request);
|
|
8758
|
-
const
|
|
8759
|
-
|
|
8760
|
-
|
|
8761
|
-
ctx,
|
|
8762
|
-
originSurface: MANAGED_AGENT_MCP_ORIGIN_SURFACE
|
|
8763
|
-
});
|
|
8764
|
-
if (input.signal?.aborted) {
|
|
8765
|
-
await this.stopDelegatedSession(receipt.sessionId, ctx);
|
|
8766
|
-
throw new ManagedAgentMcpError(ErrorCode.enum.ABORTED, "delegation was cancelled");
|
|
8767
|
-
}
|
|
8890
|
+
const bound = await this.resolveRunnerWorkspace(brief, ctx, request, actor);
|
|
8891
|
+
this.assertNotAborted(input.signal);
|
|
8892
|
+
let activeSessionId;
|
|
8768
8893
|
let abortStopPromise;
|
|
8769
8894
|
const abortListener = () => {
|
|
8770
|
-
|
|
8895
|
+
if (!activeSessionId) return;
|
|
8896
|
+
abortStopPromise ??= this.stopDelegatedSession(bound.runner, activeSessionId, ctx);
|
|
8771
8897
|
};
|
|
8772
8898
|
input.signal?.addEventListener("abort", abortListener, { once: true });
|
|
8773
8899
|
await this.pushProgress(record, "agent-started", "Agent session accepted for delegated task.", input.onProgress);
|
|
@@ -8775,11 +8901,21 @@ var ManagedAgentMcpDelegateController = class {
|
|
|
8775
8901
|
let terminal = false;
|
|
8776
8902
|
let terminalStatus;
|
|
8777
8903
|
try {
|
|
8778
|
-
for await (const event of
|
|
8904
|
+
for await (const event of bound.runner.run({
|
|
8905
|
+
brief,
|
|
8906
|
+
ctx,
|
|
8907
|
+
request,
|
|
8908
|
+
actor,
|
|
8909
|
+
signal: input.signal,
|
|
8910
|
+
onSessionStarted: (sessionId) => {
|
|
8911
|
+
activeSessionId = sessionId;
|
|
8912
|
+
}
|
|
8913
|
+
})) {
|
|
8779
8914
|
if (input.signal?.aborted) {
|
|
8780
8915
|
await abortStopPromise;
|
|
8781
8916
|
throw new ManagedAgentMcpError(ErrorCode.enum.ABORTED, "delegation was cancelled");
|
|
8782
8917
|
}
|
|
8918
|
+
activeSessionId = event.sessionId;
|
|
8783
8919
|
events.push(event);
|
|
8784
8920
|
await this.observeEvent(record, event, input.onProgress);
|
|
8785
8921
|
if (isTerminalAgentEvent(event)) {
|
|
@@ -8801,20 +8937,21 @@ var ManagedAgentMcpDelegateController = class {
|
|
|
8801
8937
|
if (terminalStatus !== "ok") {
|
|
8802
8938
|
throw terminalError(terminalStatus, events);
|
|
8803
8939
|
}
|
|
8804
|
-
const finalAssistantText = extractFinalAssistantText(events);
|
|
8940
|
+
const finalAssistantText = this.validateFinalAssistantText(extractFinalAssistantText(events));
|
|
8805
8941
|
const artifacts = await this.collectArtifacts({
|
|
8806
8942
|
delegationId,
|
|
8807
|
-
sessionId:
|
|
8943
|
+
sessionId: activeSessionId ?? "",
|
|
8808
8944
|
ctx,
|
|
8945
|
+
request,
|
|
8809
8946
|
finalAssistantText,
|
|
8810
8947
|
events
|
|
8811
|
-
});
|
|
8948
|
+
}, bound.workspace);
|
|
8812
8949
|
const result = {
|
|
8813
8950
|
delegationId,
|
|
8814
8951
|
status: "completed",
|
|
8815
8952
|
finalAssistantText,
|
|
8816
|
-
|
|
8817
|
-
|
|
8953
|
+
deliveryRule: MANAGED_AGENT_MCP_DELIVERY_RULE,
|
|
8954
|
+
...artifacts[0] ? { artifact: artifacts[0] } : {}
|
|
8818
8955
|
};
|
|
8819
8956
|
this.assertPublicPayloadSafe(result);
|
|
8820
8957
|
record.result = result;
|
|
@@ -8896,9 +9033,12 @@ var ManagedAgentMcpDelegateController = class {
|
|
|
8896
9033
|
if (typeof value !== "string") throw new ManagedAgentMcpError(ErrorCode.enum.TOOL_INVALID_INPUT, "brief must be a string");
|
|
8897
9034
|
const brief = value.trim();
|
|
8898
9035
|
if (!brief) throw new ManagedAgentMcpError(ErrorCode.enum.TOOL_INVALID_INPUT, "brief is required");
|
|
8899
|
-
if (brief.length > this.maxBriefChars) {
|
|
9036
|
+
if (this.maxBriefChars !== void 0 && brief.length > this.maxBriefChars) {
|
|
8900
9037
|
throw new ManagedAgentMcpError(ErrorCode.enum.TOOL_INVALID_INPUT, `brief must be ${this.maxBriefChars} characters or fewer`);
|
|
8901
9038
|
}
|
|
9039
|
+
if (utf8ByteLength(brief) > this.maxBriefBytes) {
|
|
9040
|
+
throw new ManagedAgentMcpError(ErrorCode.enum.TOOL_INVALID_INPUT, `brief must be ${this.maxBriefBytes} UTF-8 bytes or fewer`);
|
|
9041
|
+
}
|
|
8902
9042
|
return brief;
|
|
8903
9043
|
}
|
|
8904
9044
|
async resolveSessionCtx(brief, request) {
|
|
@@ -8911,11 +9051,56 @@ var ManagedAgentMcpDelegateController = class {
|
|
|
8911
9051
|
}
|
|
8912
9052
|
return { workspaceId: ctx.workspaceId, userId: ctx.userId };
|
|
8913
9053
|
}
|
|
9054
|
+
async resolveWorkspace(brief, ctx, request) {
|
|
9055
|
+
const resolveWorkspace = this.options.resolveWorkspace;
|
|
9056
|
+
if (!resolveWorkspace) {
|
|
9057
|
+
throw new ManagedAgentMcpError(ErrorCode.enum.CONFIG_INVALID, "MCP delegate requires a host-resolved Workspace");
|
|
9058
|
+
}
|
|
9059
|
+
const workspace = await resolveWorkspace({ brief, ctx, request });
|
|
9060
|
+
if (!workspace || typeof workspace.stat !== "function" || typeof workspace.readFile !== "function") {
|
|
9061
|
+
throw new ManagedAgentMcpError(ErrorCode.enum.CONFIG_INVALID, "MCP delegate requires a host-resolved Workspace");
|
|
9062
|
+
}
|
|
9063
|
+
return workspace;
|
|
9064
|
+
}
|
|
9065
|
+
async resolveRunnerWorkspace(brief, ctx, request, actor) {
|
|
9066
|
+
const resolved = this.options.resolveRunnerWorkspace ? await this.options.resolveRunnerWorkspace({ brief, ctx, request, actor }) : {
|
|
9067
|
+
runner: this.createAgentDelegateRunner(),
|
|
9068
|
+
workspace: await this.resolveWorkspace(brief, ctx, request)
|
|
9069
|
+
};
|
|
9070
|
+
if (!resolved || !resolved.runner || typeof resolved.runner.run !== "function") {
|
|
9071
|
+
throw new ManagedAgentMcpError(ErrorCode.enum.CONFIG_INVALID, "MCP delegate requires a host-resolved runner");
|
|
9072
|
+
}
|
|
9073
|
+
if (!resolved.workspace || typeof resolved.workspace.stat !== "function" || typeof resolved.workspace.readFile !== "function") {
|
|
9074
|
+
throw new ManagedAgentMcpError(ErrorCode.enum.CONFIG_INVALID, "MCP delegate requires a host-resolved Workspace");
|
|
9075
|
+
}
|
|
9076
|
+
return resolved;
|
|
9077
|
+
}
|
|
9078
|
+
createAgentDelegateRunner() {
|
|
9079
|
+
const agent = this.options.agent;
|
|
9080
|
+
if (!agent) {
|
|
9081
|
+
throw new ManagedAgentMcpError(ErrorCode.enum.CONFIG_INVALID, "MCP delegate requires a host-resolved runner");
|
|
9082
|
+
}
|
|
9083
|
+
return {
|
|
9084
|
+
async *run(input) {
|
|
9085
|
+
const receipt = await agent.start({
|
|
9086
|
+
content: input.brief,
|
|
9087
|
+
actor: input.actor,
|
|
9088
|
+
ctx: input.ctx,
|
|
9089
|
+
originSurface: MANAGED_AGENT_MCP_ORIGIN_SURFACE
|
|
9090
|
+
});
|
|
9091
|
+
input.onSessionStarted?.(receipt.sessionId);
|
|
9092
|
+
yield* agent.stream(receipt.sessionId, { startIndex: receipt.startIndex, ctx: input.ctx });
|
|
9093
|
+
},
|
|
9094
|
+
async stop(sessionId, ctx) {
|
|
9095
|
+
await agent.stop(sessionId, ctx);
|
|
9096
|
+
}
|
|
9097
|
+
};
|
|
9098
|
+
}
|
|
8914
9099
|
assertNotAborted(signal) {
|
|
8915
9100
|
if (signal?.aborted) throw new ManagedAgentMcpError(ErrorCode.enum.ABORTED, "delegation was cancelled");
|
|
8916
9101
|
}
|
|
8917
|
-
async stopDelegatedSession(sessionId, ctx) {
|
|
8918
|
-
await
|
|
9102
|
+
async stopDelegatedSession(runner, sessionId, ctx) {
|
|
9103
|
+
await Promise.resolve(runner.stop?.(sessionId, ctx)).catch(() => void 0);
|
|
8919
9104
|
}
|
|
8920
9105
|
async resolveActor(brief, ctx, request) {
|
|
8921
9106
|
const actor = await this.options.resolveActor?.({ brief, ctx, request });
|
|
@@ -8943,13 +9128,40 @@ var ManagedAgentMcpDelegateController = class {
|
|
|
8943
9128
|
} catch {
|
|
8944
9129
|
}
|
|
8945
9130
|
}
|
|
8946
|
-
|
|
9131
|
+
validateFinalAssistantText(value) {
|
|
9132
|
+
const byteSize = utf8ByteLength(value);
|
|
9133
|
+
if (byteSize > MAX_FINAL_ASSISTANT_TEXT_BYTES) {
|
|
9134
|
+
throw new ManagedAgentMcpError(
|
|
9135
|
+
ErrorCode.enum.MCP_AGENT_ARTIFACT_TOO_LARGE,
|
|
9136
|
+
`final assistant text must be ${MAX_FINAL_ASSISTANT_TEXT_BYTES} bytes or fewer`
|
|
9137
|
+
);
|
|
9138
|
+
}
|
|
9139
|
+
if (looksLikeSinglePath(value)) {
|
|
9140
|
+
throw new ManagedAgentMcpError(
|
|
9141
|
+
ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID,
|
|
9142
|
+
"final assistant text must not be only an artifact path"
|
|
9143
|
+
);
|
|
9144
|
+
}
|
|
9145
|
+
return value;
|
|
9146
|
+
}
|
|
9147
|
+
async collectArtifacts(input, workspace) {
|
|
8947
9148
|
const supplied = await this.options.collectArtifacts?.(input);
|
|
8948
|
-
const
|
|
8949
|
-
|
|
8950
|
-
|
|
8951
|
-
|
|
8952
|
-
|
|
9149
|
+
const rawCandidates = supplied ?? extractArtifactRefs(input.events);
|
|
9150
|
+
if (!Array.isArray(rawCandidates)) {
|
|
9151
|
+
throw new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID, "artifact references must be an array");
|
|
9152
|
+
}
|
|
9153
|
+
const candidates = rawCandidates.map((artifact2) => normalizeArtifactCandidate(artifact2));
|
|
9154
|
+
this.assertPublicPayloadSafe(candidates);
|
|
9155
|
+
if (candidates.length === 0) return [];
|
|
9156
|
+
if (candidates.length > 1) {
|
|
9157
|
+
throw new ManagedAgentMcpError(
|
|
9158
|
+
ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID,
|
|
9159
|
+
"MCP delegate delivery supports at most one artifact"
|
|
9160
|
+
);
|
|
9161
|
+
}
|
|
9162
|
+
const artifact = await resolveMarkdownArtifact(candidates[0], workspace);
|
|
9163
|
+
this.assertPublicPayloadSafe(artifact);
|
|
9164
|
+
return [artifact];
|
|
8953
9165
|
}
|
|
8954
9166
|
toSafeError(error) {
|
|
8955
9167
|
if (error instanceof ManagedAgentMcpError) {
|
|
@@ -8962,6 +9174,12 @@ var ManagedAgentMcpDelegateController = class {
|
|
|
8962
9174
|
}
|
|
8963
9175
|
assertPublicPayloadSafe(payload) {
|
|
8964
9176
|
const serialized = JSON.stringify(payload);
|
|
9177
|
+
if (utf8ByteLength(serialized) > MAX_SERIALIZED_RESULT_BYTES) {
|
|
9178
|
+
throw new ManagedAgentMcpError(
|
|
9179
|
+
ErrorCode.enum.MCP_AGENT_ARTIFACT_TOO_LARGE,
|
|
9180
|
+
`MCP delegate result must be ${MAX_SERIALIZED_RESULT_BYTES} bytes or fewer`
|
|
9181
|
+
);
|
|
9182
|
+
}
|
|
8965
9183
|
if (this.containsSecret(serialized)) {
|
|
8966
9184
|
throw new ManagedAgentMcpError(ErrorCode.enum.INTERNAL_ERROR, "MCP delegate payload failed secret redaction guard");
|
|
8967
9185
|
}
|
|
@@ -9052,39 +9270,178 @@ function extractArtifactRefs(events) {
|
|
|
9052
9270
|
}
|
|
9053
9271
|
return artifacts;
|
|
9054
9272
|
}
|
|
9055
|
-
function
|
|
9056
|
-
|
|
9057
|
-
|
|
9273
|
+
function normalizeArtifactCandidate(artifact) {
|
|
9274
|
+
if (!artifact || typeof artifact !== "object") {
|
|
9275
|
+
throw new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID, "artifact reference is invalid");
|
|
9276
|
+
}
|
|
9277
|
+
const record = artifact;
|
|
9278
|
+
if (record.content !== void 0) {
|
|
9279
|
+
throw new ManagedAgentMcpError(
|
|
9280
|
+
ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID,
|
|
9281
|
+
"artifact content must be resolved through the authorized workspace"
|
|
9282
|
+
);
|
|
9283
|
+
}
|
|
9284
|
+
if (record.truncated !== void 0) {
|
|
9285
|
+
throw new ManagedAgentMcpError(
|
|
9286
|
+
ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID,
|
|
9287
|
+
"artifact content must be complete and untruncated"
|
|
9288
|
+
);
|
|
9289
|
+
}
|
|
9290
|
+
const path4 = normalizeArtifactPath(record.path);
|
|
9291
|
+
const mediaType = optionalNonEmptyString(record.mediaType);
|
|
9292
|
+
if (mediaType !== void 0 && mediaType.toLowerCase().split(";", 1)[0]?.trim() !== MARKDOWN_MEDIA_TYPE) {
|
|
9293
|
+
throw new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID, "artifact must be Markdown");
|
|
9294
|
+
}
|
|
9295
|
+
if (mediaType === void 0 && !isMarkdownPath(path4)) {
|
|
9296
|
+
throw new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID, "artifact must be Markdown");
|
|
9297
|
+
}
|
|
9298
|
+
const candidate = {
|
|
9058
9299
|
path: path4,
|
|
9059
|
-
mediaType:
|
|
9060
|
-
title: optionalNonEmptyString(artifact.title)
|
|
9300
|
+
mediaType: MARKDOWN_MEDIA_TYPE
|
|
9061
9301
|
};
|
|
9062
|
-
|
|
9063
|
-
|
|
9064
|
-
|
|
9065
|
-
}
|
|
9066
|
-
if (artifact.content.length <= maxInlineArtifactContentChars) {
|
|
9067
|
-
normalized.content = artifact.content;
|
|
9068
|
-
} else {
|
|
9069
|
-
normalized.truncated = true;
|
|
9070
|
-
}
|
|
9071
|
-
}
|
|
9072
|
-
if (artifact.truncated === true) normalized.truncated = true;
|
|
9073
|
-
return normalized;
|
|
9302
|
+
const title = optionalNonEmptyString(record.title);
|
|
9303
|
+
if (title !== void 0) candidate.title = title;
|
|
9304
|
+
return candidate;
|
|
9074
9305
|
}
|
|
9075
9306
|
function normalizeArtifactPath(path4) {
|
|
9076
|
-
if (typeof path4 !== "string") throw new ManagedAgentMcpError(ErrorCode.enum.
|
|
9307
|
+
if (typeof path4 !== "string") throw new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID, "artifact path must be a string");
|
|
9077
9308
|
const trimmed = path4.trim();
|
|
9078
|
-
if (!trimmed) throw new ManagedAgentMcpError(ErrorCode.enum.
|
|
9079
|
-
if (trimmed.includes("\0")) throw new ManagedAgentMcpError(ErrorCode.enum.
|
|
9080
|
-
|
|
9081
|
-
|
|
9309
|
+
if (!trimmed) throw new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID, "artifact path is required");
|
|
9310
|
+
if (trimmed.includes("\0")) throw new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID, "artifact path is invalid");
|
|
9311
|
+
const decoded = safeDecodeArtifactPath(trimmed);
|
|
9312
|
+
const traversalCandidate = decoded.replace(/\\/g, "/");
|
|
9313
|
+
if (trimmed.startsWith("/") || traversalCandidate.startsWith("/") || /^[A-Za-z]:[\\/]/.test(trimmed) || /^[A-Za-z]:[\\/]/.test(traversalCandidate) || /^[A-Za-z][A-Za-z0-9+.-]*:/.test(trimmed)) {
|
|
9314
|
+
throw new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID, "artifact path must be workspace-relative");
|
|
9315
|
+
}
|
|
9316
|
+
const parts = traversalCandidate.split("/");
|
|
9317
|
+
if (traversalCandidate.startsWith("~") || traversalCandidate.startsWith("$") || /[\r\n]/.test(traversalCandidate) || parts.some((part) => part === ".." || part.startsWith(".."))) {
|
|
9318
|
+
throw new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID, "artifact path must stay within the workspace");
|
|
9319
|
+
}
|
|
9320
|
+
const normalized = parts.filter((part) => part && part !== ".").join("/");
|
|
9321
|
+
if (!normalized) throw new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID, "artifact path is required");
|
|
9322
|
+
return normalized;
|
|
9323
|
+
}
|
|
9324
|
+
async function resolveMarkdownArtifact(candidate, workspace) {
|
|
9325
|
+
const { content, bytes, byteSize } = await readStableArtifact(candidate.path, workspace);
|
|
9326
|
+
validateMarkdownContent(content);
|
|
9327
|
+
const artifact = {
|
|
9328
|
+
content,
|
|
9329
|
+
sha256: sha256(bytes),
|
|
9330
|
+
byteSize,
|
|
9331
|
+
mediaType: MARKDOWN_MEDIA_TYPE,
|
|
9332
|
+
...candidate.title ? { title: candidate.title } : {}
|
|
9333
|
+
};
|
|
9334
|
+
return artifact;
|
|
9335
|
+
}
|
|
9336
|
+
async function readStableArtifact(path4, workspace) {
|
|
9337
|
+
const before = await statArtifact(workspace, path4);
|
|
9338
|
+
assertArtifactStat(before);
|
|
9339
|
+
if (before.size > MAX_ARTIFACT_BYTES) {
|
|
9340
|
+
throw new ManagedAgentMcpError(
|
|
9341
|
+
ErrorCode.enum.MCP_AGENT_ARTIFACT_TOO_LARGE,
|
|
9342
|
+
`artifact must be ${MAX_ARTIFACT_BYTES} bytes or fewer`
|
|
9343
|
+
);
|
|
9344
|
+
}
|
|
9345
|
+
const read = await readArtifactContent(workspace, path4);
|
|
9346
|
+
const after = await statArtifact(workspace, path4);
|
|
9347
|
+
assertArtifactStat(after);
|
|
9348
|
+
if (!sameStat(before, after) || read.byteSize !== before.size) {
|
|
9349
|
+
throw new ManagedAgentMcpError(
|
|
9350
|
+
ErrorCode.enum.MCP_AGENT_ARTIFACT_UNAVAILABLE,
|
|
9351
|
+
"artifact changed while it was being read"
|
|
9352
|
+
);
|
|
9353
|
+
}
|
|
9354
|
+
if (read.byteSize > MAX_ARTIFACT_BYTES) {
|
|
9355
|
+
throw new ManagedAgentMcpError(
|
|
9356
|
+
ErrorCode.enum.MCP_AGENT_ARTIFACT_TOO_LARGE,
|
|
9357
|
+
`artifact must be ${MAX_ARTIFACT_BYTES} bytes or fewer`
|
|
9358
|
+
);
|
|
9359
|
+
}
|
|
9360
|
+
return read;
|
|
9361
|
+
}
|
|
9362
|
+
async function statArtifact(workspace, path4) {
|
|
9363
|
+
try {
|
|
9364
|
+
return await workspace.stat(path4);
|
|
9365
|
+
} catch (error) {
|
|
9366
|
+
throw artifactReadError(error);
|
|
9367
|
+
}
|
|
9368
|
+
}
|
|
9369
|
+
function assertArtifactStat(stat13) {
|
|
9370
|
+
if (stat13.kind !== "file") {
|
|
9371
|
+
throw new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID, "artifact must be a file");
|
|
9372
|
+
}
|
|
9373
|
+
if (!Number.isFinite(stat13.size) || stat13.size < 0) {
|
|
9374
|
+
throw new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID, "artifact size is invalid");
|
|
9375
|
+
}
|
|
9376
|
+
}
|
|
9377
|
+
async function readArtifactContent(workspace, path4) {
|
|
9378
|
+
try {
|
|
9379
|
+
if (!workspace.readBinaryFile) {
|
|
9380
|
+
throw new ManagedAgentMcpError(
|
|
9381
|
+
ErrorCode.enum.MCP_AGENT_ARTIFACT_UNAVAILABLE,
|
|
9382
|
+
"artifact bytes are unavailable through the authorized workspace"
|
|
9383
|
+
);
|
|
9384
|
+
}
|
|
9385
|
+
const bytes = await workspace.readBinaryFile(path4);
|
|
9386
|
+
const content = decodeUtf82(bytes);
|
|
9387
|
+
return { content, bytes, byteSize: bytes.byteLength };
|
|
9388
|
+
} catch (error) {
|
|
9389
|
+
if (error instanceof ManagedAgentMcpError) throw error;
|
|
9390
|
+
throw artifactReadError(error);
|
|
9082
9391
|
}
|
|
9083
|
-
|
|
9084
|
-
|
|
9085
|
-
|
|
9392
|
+
}
|
|
9393
|
+
function artifactReadError(error) {
|
|
9394
|
+
const code = error?.code;
|
|
9395
|
+
const reason = error?.reason;
|
|
9396
|
+
if (code === ErrorCode.enum.PATH_ESCAPE || code === ErrorCode.enum.PATH_ABSOLUTE || code === ErrorCode.enum.PATH_NULL_BYTE || code === ErrorCode.enum.PATH_SYMLINK_ESCAPE || reason === "path-escape" || reason === "absolute-path" || reason === "null-byte" || reason === "symlink-escape") {
|
|
9397
|
+
return new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID, "artifact path is invalid");
|
|
9398
|
+
}
|
|
9399
|
+
return new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_UNAVAILABLE, "artifact is unavailable");
|
|
9400
|
+
}
|
|
9401
|
+
function decodeUtf82(bytes) {
|
|
9402
|
+
try {
|
|
9403
|
+
return strictUtf8Decoder.decode(bytes);
|
|
9404
|
+
} catch {
|
|
9405
|
+
throw new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID, "artifact must be well-formed UTF-8");
|
|
9086
9406
|
}
|
|
9087
|
-
|
|
9407
|
+
}
|
|
9408
|
+
function validateMarkdownContent(content) {
|
|
9409
|
+
if (!content.trim()) {
|
|
9410
|
+
throw new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID, "artifact Markdown must not be empty");
|
|
9411
|
+
}
|
|
9412
|
+
for (let index = 0; index < content.length; index += 1) {
|
|
9413
|
+
const code = content.charCodeAt(index);
|
|
9414
|
+
if (code === 0 || code < 32 && code !== 9 && code !== 10 && code !== 13) {
|
|
9415
|
+
throw new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID, "artifact must be text Markdown");
|
|
9416
|
+
}
|
|
9417
|
+
}
|
|
9418
|
+
}
|
|
9419
|
+
function sameStat(left, right) {
|
|
9420
|
+
return left.kind === right.kind && left.size === right.size && left.mtimeMs === right.mtimeMs;
|
|
9421
|
+
}
|
|
9422
|
+
function sha256(bytes) {
|
|
9423
|
+
return `sha256:${createHash6("sha256").update(bytes).digest("hex")}`;
|
|
9424
|
+
}
|
|
9425
|
+
function safeDecodeArtifactPath(path4) {
|
|
9426
|
+
try {
|
|
9427
|
+
return decodeURIComponent(path4);
|
|
9428
|
+
} catch {
|
|
9429
|
+
return path4;
|
|
9430
|
+
}
|
|
9431
|
+
}
|
|
9432
|
+
function utf8ByteLength(value) {
|
|
9433
|
+
return utf8Encoder.encode(value).byteLength;
|
|
9434
|
+
}
|
|
9435
|
+
function isMarkdownPath(path4) {
|
|
9436
|
+
return /\.(md|markdown)$/i.test(path4);
|
|
9437
|
+
}
|
|
9438
|
+
function looksLikeSinglePath(value) {
|
|
9439
|
+
const trimmed = value.trim();
|
|
9440
|
+
if (!trimmed || /\s/.test(trimmed)) return false;
|
|
9441
|
+
if (!isMarkdownPath(trimmed)) return false;
|
|
9442
|
+
if (/^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(trimmed)) return true;
|
|
9443
|
+
if (trimmed.startsWith("/") || /^[A-Za-z]:[\\/]/.test(trimmed)) return true;
|
|
9444
|
+
return trimmed.includes("/") || trimmed.includes("\\");
|
|
9088
9445
|
}
|
|
9089
9446
|
function optionalNonEmptyString(value) {
|
|
9090
9447
|
if (value === void 0) return void 0;
|
|
@@ -9099,18 +9456,21 @@ function sameSessionCtx(a, b) {
|
|
|
9099
9456
|
// src/server/mcp/managedAgentMcpServer.ts
|
|
9100
9457
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
9101
9458
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
9102
|
-
import { z } from "zod";
|
|
9103
|
-
var
|
|
9459
|
+
import { z as z2 } from "zod";
|
|
9460
|
+
var DEFAULT_MAX_BRIEF_SCHEMA_CHARS = 32 * 1024;
|
|
9104
9461
|
var delegateTaskStatusInputSchema = {
|
|
9105
|
-
delegationId:
|
|
9462
|
+
delegationId: z2.string().min(1)
|
|
9106
9463
|
};
|
|
9107
|
-
function createManagedAgentMcpServer(options
|
|
9464
|
+
function createManagedAgentMcpServer(options) {
|
|
9465
|
+
return createManagedAgentMcpServerWithController(options, createManagedAgentMcpDelegateController(options));
|
|
9466
|
+
}
|
|
9467
|
+
function createManagedAgentMcpServerWithController(options, controller) {
|
|
9108
9468
|
const server = new McpServer({
|
|
9109
9469
|
name: options.name ?? "boring-managed-agent",
|
|
9110
9470
|
version: options.version ?? "0.0.0"
|
|
9111
9471
|
});
|
|
9112
9472
|
const registerTool = server.registerTool.bind(server);
|
|
9113
|
-
const delegateTaskInputSchema = createDelegateTaskInputSchema(options.maxBriefChars ??
|
|
9473
|
+
const delegateTaskInputSchema = createDelegateTaskInputSchema(options.maxBriefChars ?? DEFAULT_MAX_BRIEF_SCHEMA_CHARS);
|
|
9114
9474
|
registerTool(
|
|
9115
9475
|
"delegate_task",
|
|
9116
9476
|
{
|
|
@@ -9186,7 +9546,7 @@ function createManagedAgentMcpServer(options, controller = createManagedAgentMcp
|
|
|
9186
9546
|
function createManagedAgentMcpHttpHandler(options) {
|
|
9187
9547
|
const controller = options.controller ?? createManagedAgentMcpDelegateController(options);
|
|
9188
9548
|
return async (req, res, parsedBody) => {
|
|
9189
|
-
const server =
|
|
9549
|
+
const server = createManagedAgentMcpServerWithController(options, controller);
|
|
9190
9550
|
const transport = new StreamableHTTPServerTransport({
|
|
9191
9551
|
sessionIdGenerator: void 0,
|
|
9192
9552
|
enableJsonResponse: false
|
|
@@ -9207,7 +9567,7 @@ function requestContextFromExtra(extra) {
|
|
|
9207
9567
|
}
|
|
9208
9568
|
function createDelegateTaskInputSchema(maxBriefChars) {
|
|
9209
9569
|
return {
|
|
9210
|
-
brief:
|
|
9570
|
+
brief: z2.string().min(1).max(maxBriefChars)
|
|
9211
9571
|
};
|
|
9212
9572
|
}
|
|
9213
9573
|
async function sendMcpProgress(extra, progress, message) {
|
|
@@ -11420,26 +11780,26 @@ function skillsRoutes(app, opts, done) {
|
|
|
11420
11780
|
|
|
11421
11781
|
// src/server/http/routes/piChat.ts
|
|
11422
11782
|
import { PassThrough } from "stream";
|
|
11423
|
-
import { z as
|
|
11783
|
+
import { z as z3 } from "zod";
|
|
11424
11784
|
var DEFAULT_WORKSPACE_ID2 = "default";
|
|
11425
11785
|
var DEFAULT_HEARTBEAT_INTERVAL_MS = 25e3;
|
|
11426
11786
|
var DEFAULT_SESSION_LIST_LIMIT = 50;
|
|
11427
11787
|
var MAX_SESSION_LIST_LIMIT = 100;
|
|
11428
11788
|
var SAFE_SESSION_LIST_INCLUDE_ID = /^[a-zA-Z0-9_-]{1,128}$/;
|
|
11429
|
-
var SessionParamsSchema =
|
|
11430
|
-
sessionId:
|
|
11789
|
+
var SessionParamsSchema = z3.object({
|
|
11790
|
+
sessionId: z3.string().min(1).max(128)
|
|
11431
11791
|
});
|
|
11432
|
-
var CursorValueSchema =
|
|
11792
|
+
var CursorValueSchema = z3.preprocess((value) => {
|
|
11433
11793
|
if (value === void 0) return 0;
|
|
11434
11794
|
if (typeof value === "string" && value.length > 0) return Number(value);
|
|
11435
11795
|
return value;
|
|
11436
|
-
},
|
|
11437
|
-
var EventsQuerySchema =
|
|
11796
|
+
}, z3.number().int().nonnegative());
|
|
11797
|
+
var EventsQuerySchema = z3.object({
|
|
11438
11798
|
cursor: CursorValueSchema
|
|
11439
11799
|
});
|
|
11440
|
-
var EmptyBodySchema =
|
|
11441
|
-
var CreateSessionBodySchema =
|
|
11442
|
-
title:
|
|
11800
|
+
var EmptyBodySchema = z3.preprocess((value) => value ?? {}, z3.object({}).strict());
|
|
11801
|
+
var CreateSessionBodySchema = z3.preprocess((value) => value ?? {}, z3.object({
|
|
11802
|
+
title: z3.string().min(1).max(200).optional()
|
|
11443
11803
|
}).strict());
|
|
11444
11804
|
var PiChatRouteError = class extends Error {
|
|
11445
11805
|
statusCode;
|
|
@@ -12402,6 +12762,92 @@ function createWorkspaceAgentDispatcherError(code, message, statusCode) {
|
|
|
12402
12762
|
return error;
|
|
12403
12763
|
}
|
|
12404
12764
|
|
|
12765
|
+
// src/server/agentReadiness.ts
|
|
12766
|
+
var READINESS_PROBE_TOOL = {
|
|
12767
|
+
name: "agent_readiness_probe",
|
|
12768
|
+
description: "Internal readiness probe.",
|
|
12769
|
+
parameters: { type: "object", properties: {} },
|
|
12770
|
+
async execute() {
|
|
12771
|
+
return { content: [] };
|
|
12772
|
+
}
|
|
12773
|
+
};
|
|
12774
|
+
function collectToolReadinessRequirements(tools) {
|
|
12775
|
+
const requirements = /* @__PURE__ */ new Set();
|
|
12776
|
+
for (const tool of tools) {
|
|
12777
|
+
for (const requirement of tool.readinessRequirements ?? []) requirements.add(requirement);
|
|
12778
|
+
}
|
|
12779
|
+
return [...requirements];
|
|
12780
|
+
}
|
|
12781
|
+
function createAgentReadinessFromTracker(options) {
|
|
12782
|
+
const requirements = [...new Set(options.requirements)];
|
|
12783
|
+
return {
|
|
12784
|
+
requirements,
|
|
12785
|
+
async status() {
|
|
12786
|
+
return requirements.map((requirement) => readinessStatusForRequirement(requirement, options));
|
|
12787
|
+
}
|
|
12788
|
+
};
|
|
12789
|
+
}
|
|
12790
|
+
function readinessStatusForRequirement(requirement, options) {
|
|
12791
|
+
const snapshot = options.tracker.getReadiness();
|
|
12792
|
+
if (requirement === "workspace-fs") {
|
|
12793
|
+
return statusFromCapability(requirement, snapshot.capabilities.workspace, ErrorCode.enum.WORKSPACE_NOT_READY);
|
|
12794
|
+
}
|
|
12795
|
+
if (requirement === "sandbox-exec") {
|
|
12796
|
+
return snapshot.sandboxReady ? { key: requirement, ready: true, state: "ready" } : {
|
|
12797
|
+
key: requirement,
|
|
12798
|
+
ready: false,
|
|
12799
|
+
state: "preparing",
|
|
12800
|
+
errorCode: ErrorCode.enum.SANDBOX_NOT_READY,
|
|
12801
|
+
retryable: true
|
|
12802
|
+
};
|
|
12803
|
+
}
|
|
12804
|
+
if (isRuntimeReadinessRequirement(requirement)) {
|
|
12805
|
+
const status = statusFromCapability(
|
|
12806
|
+
requirement,
|
|
12807
|
+
snapshot.capabilities.runtimeDependencies,
|
|
12808
|
+
ErrorCode.enum.AGENT_RUNTIME_NOT_READY
|
|
12809
|
+
);
|
|
12810
|
+
if (status.ready || !options.checkReadiness) return status;
|
|
12811
|
+
return enrichRuntimeStatus(
|
|
12812
|
+
status,
|
|
12813
|
+
options.checkReadiness(requirement, READINESS_PROBE_TOOL)
|
|
12814
|
+
);
|
|
12815
|
+
}
|
|
12816
|
+
return { key: requirement, ready: false };
|
|
12817
|
+
}
|
|
12818
|
+
function enrichRuntimeStatus(status, readiness) {
|
|
12819
|
+
if (readiness === true || typeof readiness === "object" && readiness !== null && readiness.ready === true) {
|
|
12820
|
+
return status;
|
|
12821
|
+
}
|
|
12822
|
+
if (readiness === false) {
|
|
12823
|
+
return { ...status, retryable: status.retryable ?? true };
|
|
12824
|
+
}
|
|
12825
|
+
return {
|
|
12826
|
+
...status,
|
|
12827
|
+
...readiness.errorCode ? { errorCode: readiness.errorCode } : {},
|
|
12828
|
+
...readiness.causeCode ? { causeCode: readiness.causeCode } : {},
|
|
12829
|
+
...readiness.message ? { message: readiness.message } : {},
|
|
12830
|
+
...readiness.workspaceId ? { workspaceId: readiness.workspaceId } : {},
|
|
12831
|
+
retryable: readiness.retryable ?? status.retryable ?? true
|
|
12832
|
+
};
|
|
12833
|
+
}
|
|
12834
|
+
function statusFromCapability(key, detail, fallbackErrorCode) {
|
|
12835
|
+
const ready = detail.state === "ready";
|
|
12836
|
+
const errorCode = detail.errorCode ?? (detail.state === "failed" && isRuntimeReadinessRequirement(key) ? ErrorCode.enum.RUNTIME_PROVISIONING_FAILED : fallbackErrorCode);
|
|
12837
|
+
return {
|
|
12838
|
+
key,
|
|
12839
|
+
ready,
|
|
12840
|
+
state: detail.state,
|
|
12841
|
+
...!ready ? { errorCode } : {},
|
|
12842
|
+
...detail.causeCode ? { causeCode: detail.causeCode } : {},
|
|
12843
|
+
...detail.message ? { message: detail.message } : {},
|
|
12844
|
+
...detail.retryable !== void 0 ? { retryable: detail.retryable } : {}
|
|
12845
|
+
};
|
|
12846
|
+
}
|
|
12847
|
+
function isRuntimeReadinessRequirement(requirement) {
|
|
12848
|
+
return requirement === "runtime-dependencies" || requirement.startsWith("runtime:");
|
|
12849
|
+
}
|
|
12850
|
+
|
|
12405
12851
|
// src/server/createAgentApp.ts
|
|
12406
12852
|
var DEFAULT_VERSION = "0.1.0-dev";
|
|
12407
12853
|
var DEFAULT_SESSION_ID = "default";
|
|
@@ -12553,9 +12999,16 @@ async function createWorkspaceAgentAppProfile(opts, sessionId, resolvedMode, app
|
|
|
12553
12999
|
sessionRoot: opts.sessionRoot,
|
|
12554
13000
|
sessionDir: opts.sessionDir ?? input.sessionDir
|
|
12555
13001
|
}));
|
|
13002
|
+
const readyTracker = createRuntimeReadyStatusTracker(modeAdapter, {
|
|
13003
|
+
harnessReady: true
|
|
13004
|
+
});
|
|
12556
13005
|
const coreAgent = createAgentRuntimeBridge2({
|
|
12557
13006
|
runtime: modeAdapter,
|
|
12558
13007
|
tools,
|
|
13008
|
+
readiness: createAgentReadinessFromTracker({
|
|
13009
|
+
requirements: collectToolReadinessRequirements(tools),
|
|
13010
|
+
tracker: readyTracker
|
|
13011
|
+
}),
|
|
12559
13012
|
harnessFactory,
|
|
12560
13013
|
systemPromptAppend: opts.systemPromptAppend,
|
|
12561
13014
|
systemPromptDynamic: opts.systemPromptDynamic,
|
|
@@ -12573,9 +13026,6 @@ async function createWorkspaceAgentAppProfile(opts, sessionId, resolvedMode, app
|
|
|
12573
13026
|
opts.onWorkspaceAgentDispatcher?.(createStaticWorkspaceAgentDispatcherResolver(coreAgent.agent, sessionId));
|
|
12574
13027
|
const harness = agentRuntime.harness;
|
|
12575
13028
|
harnessRef = harness;
|
|
12576
|
-
const readyTracker = createRuntimeReadyStatusTracker(modeAdapter, {
|
|
12577
|
-
harnessReady: true
|
|
12578
|
-
});
|
|
12579
13029
|
const filesystemBindingsForRequest = opts.getFilesystemBindings ? (request) => {
|
|
12580
13030
|
const user = request.user;
|
|
12581
13031
|
return opts.getFilesystemBindings?.({
|
|
@@ -13194,7 +13644,7 @@ function createRuntimeProvisioningFailedError(workspaceId, cause) {
|
|
|
13194
13644
|
}
|
|
13195
13645
|
);
|
|
13196
13646
|
}
|
|
13197
|
-
function
|
|
13647
|
+
function isRuntimeReadinessRequirement2(requirement) {
|
|
13198
13648
|
return requirement === "runtime-dependencies" || requirement.startsWith("runtime:");
|
|
13199
13649
|
}
|
|
13200
13650
|
function causeCodeFrom(error) {
|
|
@@ -13203,7 +13653,7 @@ function causeCodeFrom(error) {
|
|
|
13203
13653
|
}
|
|
13204
13654
|
function createRuntimeReadinessCheck(workspaceId, getRuntimeDependencies) {
|
|
13205
13655
|
return (requirement) => {
|
|
13206
|
-
if (!
|
|
13656
|
+
if (!isRuntimeReadinessRequirement2(requirement)) return true;
|
|
13207
13657
|
const runtimeDependencies = getRuntimeDependencies();
|
|
13208
13658
|
if (runtimeDependencies.state === "ready" || runtimeDependencies.state === "not-started") return true;
|
|
13209
13659
|
return {
|
|
@@ -13532,6 +13982,11 @@ var registerAgentRoutes = async (app, opts) => {
|
|
|
13532
13982
|
const coreAgent = createAgentRuntimeBridge2({
|
|
13533
13983
|
runtime: modeAdapter,
|
|
13534
13984
|
tools,
|
|
13985
|
+
readiness: createAgentReadinessFromTracker({
|
|
13986
|
+
requirements: collectToolReadinessRequirements(tools),
|
|
13987
|
+
tracker: readyTracker,
|
|
13988
|
+
checkReadiness
|
|
13989
|
+
}),
|
|
13535
13990
|
harnessFactory,
|
|
13536
13991
|
systemPromptAppend: opts.systemPromptAppend,
|
|
13537
13992
|
systemPromptDynamic,
|
|
@@ -13752,6 +14207,9 @@ var registerAgentRoutes = async (app, opts) => {
|
|
|
13752
14207
|
}
|
|
13753
14208
|
opts.onWorkspaceAgentDispatcher?.({
|
|
13754
14209
|
async resolve(ctx, options) {
|
|
14210
|
+
return (await this.resolveWithWorkspace(ctx, options)).dispatcher;
|
|
14211
|
+
},
|
|
14212
|
+
async resolveWithWorkspace(ctx, options) {
|
|
13755
14213
|
const boundCtx = normalizeWorkspaceAgentDispatcherContext(ctx);
|
|
13756
14214
|
assertWorkspaceAgentDispatcherRequestContext(boundCtx, options?.request);
|
|
13757
14215
|
bindingLifecycle.assertAdmission(boundCtx.workspaceId, options?.request);
|
|
@@ -13763,11 +14221,17 @@ var registerAgentRoutes = async (app, opts) => {
|
|
|
13763
14221
|
401
|
|
13764
14222
|
);
|
|
13765
14223
|
}
|
|
13766
|
-
return
|
|
14224
|
+
return {
|
|
14225
|
+
dispatcher: createLeasedWorkspaceAgentDispatcher(staticBinding, boundCtx, options?.request),
|
|
14226
|
+
workspace: staticBinding.runtimeBundle.workspace
|
|
14227
|
+
};
|
|
13767
14228
|
}
|
|
13768
14229
|
const binding = await getOrCreateRuntimeBinding(boundCtx.workspaceId, options?.request, { trustedCtx: boundCtx });
|
|
13769
14230
|
bindingLifecycle.assertAdmission(boundCtx.workspaceId, options?.request);
|
|
13770
|
-
return
|
|
14231
|
+
return {
|
|
14232
|
+
dispatcher: createLeasedWorkspaceAgentDispatcher(binding, boundCtx, options?.request),
|
|
14233
|
+
workspace: binding.runtimeBundle.workspace
|
|
14234
|
+
};
|
|
13771
14235
|
}
|
|
13772
14236
|
});
|
|
13773
14237
|
function getSkillsScopeForRequest(request) {
|
|
@@ -14024,6 +14488,7 @@ export {
|
|
|
14024
14488
|
createAgent,
|
|
14025
14489
|
AgentDirectoryCompilerError,
|
|
14026
14490
|
compileAgentDirectory,
|
|
14491
|
+
resolveAgentDeployment,
|
|
14027
14492
|
MANAGED_AGENT_MCP_ORIGIN_SURFACE,
|
|
14028
14493
|
MANAGED_AGENT_MCP_DELIVERY_RULE,
|
|
14029
14494
|
ManagedAgentMcpError,
|