@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.
@@ -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-Q42DWR3T.js";
12
+ } from "./chunk-CUF7ELFO.js";
8
13
  import {
9
14
  createAgentRuntimeBridge
10
- } from "./chunk-LCEBDU6G.js";
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-P23XFC4W.js";
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-X4WT3TPU.js";
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-YVON2BHN.js";
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-XHMR3QN3.js")).createPiCodingAgentHarness;
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-pr1 DELIVERY v0: delegate_task returns final assistant text and artifact file references only; share-link delivery is gated on PR #424.";
8709
- var DEFAULT_MAX_BRIEF_CHARS = 12e3;
8710
- var DEFAULT_MAX_INLINE_ARTIFACT_CONTENT_CHARS = 8e3;
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.maxBriefChars = options.maxBriefChars ?? DEFAULT_MAX_BRIEF_CHARS;
8728
- this.maxInlineArtifactContentChars = options.maxInlineArtifactContentChars ?? DEFAULT_MAX_INLINE_ARTIFACT_CONTENT_CHARS;
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 receipt = await this.options.agent.start({
8759
- content: brief,
8760
- actor,
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
- abortStopPromise ??= this.stopDelegatedSession(receipt.sessionId, ctx);
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 this.options.agent.stream(receipt.sessionId, { startIndex: receipt.startIndex, ctx })) {
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: receipt.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
- artifacts,
8817
- deliveryRule: MANAGED_AGENT_MCP_DELIVERY_RULE
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 this.options.agent.stop(sessionId, ctx).catch(() => void 0);
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
- async collectArtifacts(input) {
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 artifacts = (supplied ?? extractArtifactRefs(input.events)).map(
8949
- (artifact) => normalizeArtifactRef(artifact, this.maxInlineArtifactContentChars)
8950
- );
8951
- this.assertPublicPayloadSafe(artifacts);
8952
- return artifacts;
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 normalizeArtifactRef(artifact, maxInlineArtifactContentChars) {
9056
- const path4 = normalizeArtifactPath(artifact.path);
9057
- const normalized = {
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: optionalNonEmptyString(artifact.mediaType),
9060
- title: optionalNonEmptyString(artifact.title)
9300
+ mediaType: MARKDOWN_MEDIA_TYPE
9061
9301
  };
9062
- if (artifact.content !== void 0) {
9063
- if (typeof artifact.content !== "string") {
9064
- throw new ManagedAgentMcpError(ErrorCode.enum.INTERNAL_ERROR, "artifact content must be text");
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.INTERNAL_ERROR, "artifact path must be a string");
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.INTERNAL_ERROR, "artifact path is required");
9079
- if (trimmed.includes("\0")) throw new ManagedAgentMcpError(ErrorCode.enum.INTERNAL_ERROR, "artifact path is invalid");
9080
- if (trimmed.startsWith("/") || /^[A-Za-z]:[\\/]/.test(trimmed)) {
9081
- throw new ManagedAgentMcpError(ErrorCode.enum.INTERNAL_ERROR, "artifact path must be workspace-relative");
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
- const parts = trimmed.split(/[\\/]+/);
9084
- if (parts.some((part) => part === "..")) {
9085
- throw new ManagedAgentMcpError(ErrorCode.enum.INTERNAL_ERROR, "artifact path must stay within the workspace");
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
- return parts.filter((part) => part && part !== ".").join("/");
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 DEFAULT_MAX_BRIEF_CHARS2 = 12e3;
9459
+ import { z as z2 } from "zod";
9460
+ var DEFAULT_MAX_BRIEF_SCHEMA_CHARS = 32 * 1024;
9104
9461
  var delegateTaskStatusInputSchema = {
9105
- delegationId: z.string().min(1)
9462
+ delegationId: z2.string().min(1)
9106
9463
  };
9107
- function createManagedAgentMcpServer(options, controller = createManagedAgentMcpDelegateController(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 ?? DEFAULT_MAX_BRIEF_CHARS2);
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 = createManagedAgentMcpServer(options, controller);
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: z.string().min(1).max(maxBriefChars)
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 z2 } from "zod";
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 = z2.object({
11430
- sessionId: z2.string().min(1).max(128)
11789
+ var SessionParamsSchema = z3.object({
11790
+ sessionId: z3.string().min(1).max(128)
11431
11791
  });
11432
- var CursorValueSchema = z2.preprocess((value) => {
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
- }, z2.number().int().nonnegative());
11437
- var EventsQuerySchema = z2.object({
11796
+ }, z3.number().int().nonnegative());
11797
+ var EventsQuerySchema = z3.object({
11438
11798
  cursor: CursorValueSchema
11439
11799
  });
11440
- var EmptyBodySchema = z2.preprocess((value) => value ?? {}, z2.object({}).strict());
11441
- var CreateSessionBodySchema = z2.preprocess((value) => value ?? {}, z2.object({
11442
- title: z2.string().min(1).max(200).optional()
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 isRuntimeReadinessRequirement(requirement) {
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 (!isRuntimeReadinessRequirement(requirement)) return true;
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 createLeasedWorkspaceAgentDispatcher(staticBinding, boundCtx, options?.request);
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 createLeasedWorkspaceAgentDispatcher(binding, boundCtx, options?.request);
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,