@hachej/boring-agent 0.1.83 → 0.1.85

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,6 +1,6 @@
1
1
  import {
2
2
  ErrorCode
3
- } from "./chunk-PG2WOJ22.js";
3
+ } from "./chunk-HDIRWHJB.js";
4
4
 
5
5
  // src/shared/tool-ui.ts
6
6
  function isRecord(value) {
@@ -73,6 +73,9 @@ var ErrorCode = z.enum([
73
73
  "PROVISIONING_UV_BOOTSTRAP_FAILED",
74
74
  "PROVISIONING_UV_INSTALL_FAILED",
75
75
  "PROVISIONING_ARTIFACT_FAILED",
76
+ // Lane W same-workspace share deep-link (AR1-003)
77
+ "AR1_SHARE_NOT_FOUND",
78
+ "AR1_SHARE_TOMBSTONED",
76
79
  // Internal
77
80
  "ERR_NOT_IMPLEMENTED_UNTIL_T1",
78
81
  "INTERNAL_ERROR"
@@ -90,7 +93,8 @@ var AgentConsumptionErrorCode = z.enum([
90
93
  "AGENT_CONSUMPTION_INVALID_TRANSITION",
91
94
  "AGENT_CONSUMPTION_CYCLE_DETECTED",
92
95
  "AGENT_CONSUMPTION_DEPTH_EXCEEDED",
93
- "AGENT_CONSUMPTION_SCHEMA_MISMATCH"
96
+ "AGENT_CONSUMPTION_SCHEMA_MISMATCH",
97
+ "AGENT_CONSUMPTION_LEGACY_ARTIFACT_REJECTED"
94
98
  ]);
95
99
  var ApiErrorPayloadSchema = z.object({
96
100
  code: ErrorCode,
@@ -3,18 +3,21 @@ import {
3
3
  AgentDeploymentValidationError,
4
4
  OpaqueRefSchema,
5
5
  Sha256DigestSchema,
6
+ ShareEntryErrorCode,
6
7
  canonicalStringify,
7
8
  createAgentAssetDigest,
8
9
  createAgentDefinitionDigest,
9
10
  createAgentDeploymentDigest,
11
+ resolveShareEntry,
10
12
  sha256Bytes,
11
13
  validateAgentDefinition,
12
14
  validateAgentDeployment,
13
15
  validateTool
14
- } from "./chunk-WODTQBXR.js";
16
+ } from "./chunk-YONTHCD7.js";
15
17
  import {
18
+ AgentEffectAdmissionError,
16
19
  createAgentRuntimeBridge
17
- } from "./chunk-TNN3LPXE.js";
20
+ } from "./chunk-LYBTHR7J.js";
18
21
  import {
19
22
  sessionStreamPath
20
23
  } from "./chunk-WSQ5QNIY.js";
@@ -29,7 +32,7 @@ import {
29
32
  StopReceiptSchema,
30
33
  extractToolUiMetadata,
31
34
  sanitizeToolUiMetadata2 as sanitizeToolUiMetadata
32
- } from "./chunk-DC3S7SZG.js";
35
+ } from "./chunk-6O5ADR57.js";
33
36
  import {
34
37
  createLogger,
35
38
  createPiCodingAgentHarness,
@@ -40,7 +43,7 @@ import {
40
43
  registerConfiguredModelProviders,
41
44
  setEnvDefault,
42
45
  withPiHarnessDefaults
43
- } from "./chunk-5NAN3TAR.js";
46
+ } from "./chunk-ZUDWQAAB.js";
44
47
  import {
45
48
  safeCapture
46
49
  } from "./chunk-AQBXNPMD.js";
@@ -48,7 +51,7 @@ import {
48
51
  AgentDefinitionErrorCode,
49
52
  AgentDeploymentErrorCode,
50
53
  ErrorCode
51
- } from "./chunk-PG2WOJ22.js";
54
+ } from "./chunk-HDIRWHJB.js";
52
55
 
53
56
  // src/server/sandbox/direct/createDirectSandbox.ts
54
57
  import { spawn } from "child_process";
@@ -7309,6 +7312,19 @@ var PiChatMeteringCoordinator = class {
7309
7312
  if (run2) this.release(run2, "run-rejected");
7310
7313
  this.pruneSession(stateKey, state);
7311
7314
  }
7315
+ /**
7316
+ * Mark the currently-active run as voluntarily user-stopped (the /stop button),
7317
+ * so its terminal accounting RELEASES the hold instead of charging the fallback.
7318
+ * Must be called before the abort so the flag is set when the native aborted
7319
+ * agent-end is observed. Runs with real usage recorded before the stop still
7320
+ * settle that usage; only the unused remainder of the hold is released. No-op if
7321
+ * there is no active run (e.g. the stop landed before agent-start — releasePending
7322
+ * handles that case).
7323
+ */
7324
+ markActiveStopped(sessionId) {
7325
+ const active = this.sessions.get(sessionId)?.active;
7326
+ if (active && !active.terminal) active.userStopped = true;
7327
+ }
7312
7328
  /**
7313
7329
  * Release prompt runs reserved but not yet bound to an agent-start —
7314
7330
  * e.g. a stop/interrupt landing in the window between acceptance and the
@@ -7494,6 +7510,7 @@ var PiChatMeteringCoordinator = class {
7494
7510
  recordedMessageIds: /* @__PURE__ */ new Set(),
7495
7511
  lastIdlessUsageKey: void 0,
7496
7512
  usageWriteFailed: false,
7513
+ userStopped: false,
7497
7514
  reservation: Promise.resolve(),
7498
7515
  terminal: false,
7499
7516
  ops: Promise.resolve()
@@ -7535,7 +7552,7 @@ var PiChatMeteringCoordinator = class {
7535
7552
  if (run2.billableUsageCount > 0) {
7536
7553
  return this.sink.settleRun({ ...run2.scope, reservationId: run2.reservationId, status });
7537
7554
  }
7538
- const didPaidWork = status === "ok";
7555
+ const didPaidWork = status === "ok" && !run2.userStopped;
7539
7556
  if (didPaidWork) {
7540
7557
  return this.sink.releaseRun({ ...run2.scope, reservationId: run2.reservationId, reason: "fallback-hold-charge" });
7541
7558
  }
@@ -7987,6 +8004,7 @@ var HarnessPiChatService = class {
7987
8004
  const sessionKey = this.sessionKey(ctx, sessionId);
7988
8005
  const adapter = await this.getAdapter(ctx, sessionId, "");
7989
8006
  const clearedQueue = this.clearAllFollowUps(adapter, sessionId, sessionKey);
8007
+ this.metering?.markActiveStopped(sessionKey);
7990
8008
  this.metering?.releaseQueued(sessionKey);
7991
8009
  this.metering?.releasePending(sessionKey);
7992
8010
  await adapter.abort();
@@ -8479,12 +8497,13 @@ function createAgentRuntimeBridge2(config, options = {}) {
8479
8497
  }
8480
8498
  return createAgentRuntimeBridge({
8481
8499
  runtimeFactory: () => createRuntime(config, options),
8500
+ admitEffect: options.service?.admitEffect,
8482
8501
  readiness: config.readiness,
8483
8502
  readinessRequirements: config.readinessRequirements
8484
8503
  });
8485
8504
  }
8486
8505
  async function createRuntime(config, options) {
8487
- const harnessFactory = config.harnessFactory ?? (await import("./createHarness-TGBJZISM.js")).createPiCodingAgentHarness;
8506
+ const harnessFactory = config.harnessFactory ?? (await import("./createHarness-MJ5GEL6J.js")).createPiCodingAgentHarness;
8488
8507
  const harnessInput = {
8489
8508
  tools: config.tools ?? [],
8490
8509
  cwd: config.workdir ?? DEFAULT_WORKDIR,
@@ -9496,6 +9515,166 @@ function sameSessionCtx(a, b) {
9496
9515
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
9497
9516
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
9498
9517
  import { z as z2 } from "zod";
9518
+
9519
+ // src/server/mcp/shareEntryResources.ts
9520
+ import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
9521
+ var MAX_SHARE_READ_BYTES = 256 * 1024;
9522
+ var SHARE_RESOURCE_URI_TEMPLATE = "share:///{id}";
9523
+ var strictUtf8Decoder2 = new TextDecoder("utf-8", { fatal: true });
9524
+ function shareResourceUri(id) {
9525
+ return `share:///${encodeURIComponent(id)}`;
9526
+ }
9527
+ function registerShareEntryResources(server, options) {
9528
+ const template = new ResourceTemplate(SHARE_RESOURCE_URI_TEMPLATE, {
9529
+ list: async (extra) => listShareResources(options, requestContextFromResourceExtra(extra))
9530
+ });
9531
+ const readCallback = async (uri, variables, extra) => readShareResource(options, variables.id, requestContextFromResourceExtra(extra));
9532
+ server.registerResource(
9533
+ "share",
9534
+ template,
9535
+ {
9536
+ title: "Lane W share entry",
9537
+ description: "Same-workspace shareable file reference (AR1). Resolves live, never a blob snapshot."
9538
+ },
9539
+ readCallback
9540
+ );
9541
+ }
9542
+ function requestContextFromResourceExtra(extra) {
9543
+ return {
9544
+ sessionId: extra?.sessionId,
9545
+ authInfo: extra?.authInfo
9546
+ };
9547
+ }
9548
+ async function listShareResources(options, request) {
9549
+ const ctx = await options.resolveSessionCtx(request);
9550
+ if (!ctx.workspaceId) return { resources: [] };
9551
+ const entries = await options.store.list(ctx.workspaceId);
9552
+ return {
9553
+ resources: entries.map((entry) => ({
9554
+ uri: shareResourceUri(entry.id),
9555
+ name: entry.id
9556
+ }))
9557
+ };
9558
+ }
9559
+ async function readShareResource(options, rawId, request) {
9560
+ const id = typeof rawId === "string" ? rawId : Array.isArray(rawId) ? rawId[0] : void 0;
9561
+ if (!id) return notFoundResult(shareResourceUri(""));
9562
+ const uri = shareResourceUri(id);
9563
+ const ctx = await options.resolveSessionCtx(request);
9564
+ if (!ctx.workspaceId) return notFoundResult(uri);
9565
+ const entry = await options.store.get(id);
9566
+ if (!entry || entry.workspaceId !== ctx.workspaceId) {
9567
+ return notFoundResult(uri);
9568
+ }
9569
+ const workspace = await options.resolveWorkspace(ctx);
9570
+ const resolution = await resolveShareEntry(options.store, id, workspace);
9571
+ if (resolution.status === "not_found") return notFoundResult(uri);
9572
+ if (resolution.status === "tombstoned") {
9573
+ return tombstoneResult(uri, resolution.tombstone);
9574
+ }
9575
+ return readShareEntryContents(uri, resolution.entry, workspace);
9576
+ }
9577
+ function notFoundResult(uri) {
9578
+ return {
9579
+ contents: [
9580
+ {
9581
+ uri,
9582
+ mimeType: "application/json",
9583
+ text: JSON.stringify({
9584
+ status: "not_found",
9585
+ error: { code: ErrorCode.enum.AR1_SHARE_NOT_FOUND, message: "share not found" }
9586
+ })
9587
+ }
9588
+ ]
9589
+ };
9590
+ }
9591
+ function tombstoneResult(uri, tombstone) {
9592
+ return {
9593
+ contents: [
9594
+ {
9595
+ uri,
9596
+ mimeType: "application/json",
9597
+ text: JSON.stringify({
9598
+ status: "tombstoned",
9599
+ error: { code: ErrorCode.enum.AR1_SHARE_TOMBSTONED, message: "share target is gone" },
9600
+ id: tombstone.id,
9601
+ workspaceId: tombstone.workspaceId,
9602
+ provenance: tombstone.provenance
9603
+ })
9604
+ }
9605
+ ]
9606
+ };
9607
+ }
9608
+ async function readShareEntryContents(uri, entry, workspace) {
9609
+ const before = await statShareTarget(workspace, entry.path);
9610
+ assertShareTargetStat(before);
9611
+ assertWithinCap(before.size);
9612
+ if (!workspace.readBinaryFile) {
9613
+ throw new ManagedAgentMcpError(
9614
+ ErrorCode.enum.MCP_AGENT_ARTIFACT_UNAVAILABLE,
9615
+ "share target bytes are unavailable through the authorized workspace"
9616
+ );
9617
+ }
9618
+ const bytes = await workspace.readBinaryFile(entry.path);
9619
+ const after = await statShareTarget(workspace, entry.path);
9620
+ assertShareTargetStat(after);
9621
+ if (!sameStat2(before, after) || bytes.byteLength !== before.size) {
9622
+ throw new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_UNAVAILABLE, "share target changed while it was being read");
9623
+ }
9624
+ assertWithinCap(bytes.byteLength);
9625
+ const text = decodeUtf83(bytes);
9626
+ const digest = await sha256Bytes(bytes);
9627
+ return {
9628
+ contents: [
9629
+ {
9630
+ uri,
9631
+ mimeType: "text/plain",
9632
+ text,
9633
+ _meta: {
9634
+ status: "ok",
9635
+ digest,
9636
+ byteSize: bytes.byteLength,
9637
+ provenance: entry.provenance
9638
+ }
9639
+ }
9640
+ ]
9641
+ };
9642
+ }
9643
+ async function statShareTarget(workspace, path4) {
9644
+ try {
9645
+ return await workspace.stat(path4);
9646
+ } catch {
9647
+ throw new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_UNAVAILABLE, "share target is unavailable");
9648
+ }
9649
+ }
9650
+ function assertShareTargetStat(stat13) {
9651
+ if (stat13.kind !== "file") {
9652
+ throw new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID, "share target must be a file");
9653
+ }
9654
+ if (!Number.isFinite(stat13.size) || stat13.size < 0) {
9655
+ throw new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID, "share target size is invalid");
9656
+ }
9657
+ }
9658
+ function assertWithinCap(byteSize) {
9659
+ if (byteSize > MAX_SHARE_READ_BYTES) {
9660
+ throw new ManagedAgentMcpError(
9661
+ ErrorCode.enum.MCP_AGENT_ARTIFACT_TOO_LARGE,
9662
+ `share target must be ${MAX_SHARE_READ_BYTES} bytes or fewer`
9663
+ );
9664
+ }
9665
+ }
9666
+ function sameStat2(left, right) {
9667
+ return left.kind === right.kind && left.size === right.size && left.mtimeMs === right.mtimeMs;
9668
+ }
9669
+ function decodeUtf83(bytes) {
9670
+ try {
9671
+ return strictUtf8Decoder2.decode(bytes);
9672
+ } catch {
9673
+ throw new ManagedAgentMcpError(ErrorCode.enum.MCP_AGENT_ARTIFACT_INVALID, "share target must be well-formed UTF-8");
9674
+ }
9675
+ }
9676
+
9677
+ // src/server/mcp/managedAgentMcpServer.ts
9499
9678
  var DEFAULT_MAX_BRIEF_SCHEMA_CHARS = 32 * 1024;
9500
9679
  var delegateTaskStatusInputSchema = {
9501
9680
  delegationId: z2.string().min(1)
@@ -9508,6 +9687,13 @@ function createManagedAgentMcpServerWithController(options, controller) {
9508
9687
  name: options.name ?? "boring-managed-agent",
9509
9688
  version: options.version ?? "0.0.0"
9510
9689
  });
9690
+ if (options.shareEntryStore && options.resolveShareSessionCtx && options.resolveShareWorkspace) {
9691
+ registerShareEntryResources(server, {
9692
+ store: options.shareEntryStore,
9693
+ resolveSessionCtx: options.resolveShareSessionCtx,
9694
+ resolveWorkspace: options.resolveShareWorkspace
9695
+ });
9696
+ }
9511
9697
  const registerTool = server.registerTool.bind(server);
9512
9698
  const delegateTaskInputSchema = createDelegateTaskInputSchema(options.maxBriefChars ?? DEFAULT_MAX_BRIEF_SCHEMA_CHARS);
9513
9699
  registerTool(
@@ -11874,7 +12060,7 @@ function piChatRoutes(app, opts, done) {
11874
12060
  if (!service.createSession) throw unsupportedServiceMethod("create Pi chat session");
11875
12061
  return reply.code(201).send(await service.createSession(getRequestContext(request), body));
11876
12062
  } catch (err) {
11877
- return sendRouteError(reply, err, "create pi chat session failed");
12063
+ return sendRouteError(reply, err, "create pi chat session failed", true);
11878
12064
  }
11879
12065
  });
11880
12066
  app.delete("/api/v1/agent/pi-chat/sessions/:sessionId", async (request, reply) => {
@@ -11886,7 +12072,7 @@ function piChatRoutes(app, opts, done) {
11886
12072
  await service.deleteSession(getRequestContext(request), params.sessionId);
11887
12073
  return reply.code(204).send();
11888
12074
  } catch (err) {
11889
- return sendRouteError(reply, err, "delete pi chat session failed");
12075
+ return sendRouteError(reply, err, "delete pi chat session failed", true);
11890
12076
  }
11891
12077
  });
11892
12078
  app.get("/api/v1/agent/pi-chat/:sessionId/state", async (request, reply) => {
@@ -11977,7 +12163,7 @@ function piChatRoutes(app, opts, done) {
11977
12163
  const receipt = await service.prompt(getRequestContext(request), params.sessionId, body);
11978
12164
  return reply.code(202).send(receipt);
11979
12165
  } catch (err) {
11980
- return sendRouteError(reply, err, "prompt rejected");
12166
+ return sendRouteError(reply, err, "prompt rejected", true);
11981
12167
  }
11982
12168
  });
11983
12169
  app.post("/api/v1/agent/pi-chat/:sessionId/followup", async (request, reply) => {
@@ -11990,7 +12176,7 @@ function piChatRoutes(app, opts, done) {
11990
12176
  const receipt = await service.followUp(getRequestContext(request), params.sessionId, body);
11991
12177
  return reply.code(202).send(receipt);
11992
12178
  } catch (err) {
11993
- return sendRouteError(reply, err, "follow-up rejected");
12179
+ return sendRouteError(reply, err, "follow-up rejected", true);
11994
12180
  }
11995
12181
  });
11996
12182
  app.post("/api/v1/agent/pi-chat/:sessionId/queue/clear", async (request, reply) => {
@@ -12003,7 +12189,7 @@ function piChatRoutes(app, opts, done) {
12003
12189
  const receipt = await service.clearQueue(getRequestContext(request), params.sessionId, body);
12004
12190
  return reply.code(202).send(receipt);
12005
12191
  } catch (err) {
12006
- return sendRouteError(reply, err, "queue clear rejected");
12192
+ return sendRouteError(reply, err, "queue clear rejected", true);
12007
12193
  }
12008
12194
  });
12009
12195
  app.post("/api/v1/agent/pi-chat/:sessionId/interrupt", async (request, reply) => {
@@ -12016,7 +12202,7 @@ function piChatRoutes(app, opts, done) {
12016
12202
  const receipt = await service.interrupt(getRequestContext(request), params.sessionId, body);
12017
12203
  return reply.code(202).send(receipt);
12018
12204
  } catch (err) {
12019
- return sendRouteError(reply, err, "interrupt rejected");
12205
+ return sendRouteError(reply, err, "interrupt rejected", true);
12020
12206
  }
12021
12207
  });
12022
12208
  app.post("/api/v1/agent/pi-chat/:sessionId/stop", async (request, reply) => {
@@ -12029,7 +12215,7 @@ function piChatRoutes(app, opts, done) {
12029
12215
  const receipt = await service.stop(getRequestContext(request), params.sessionId, body);
12030
12216
  return reply.code(202).send(receipt);
12031
12217
  } catch (err) {
12032
- return sendRouteError(reply, err, "stop rejected");
12218
+ return sendRouteError(reply, err, "stop rejected", true);
12033
12219
  }
12034
12220
  });
12035
12221
  done();
@@ -12115,17 +12301,19 @@ function sendReplayRangeError(reply, error) {
12115
12301
  }
12116
12302
  });
12117
12303
  }
12118
- function sendRouteError(reply, err, fallbackMessage) {
12304
+ function sendRouteError(reply, err, fallbackMessage, preserveAdmissionError = false) {
12119
12305
  const statusCode = statusCodeFromError(err);
12120
12306
  const parsedCode = ErrorCode.safeParse(err?.code);
12121
- const code = parsedCode.success ? parsedCode.data : ErrorCode.enum.INTERNAL_ERROR;
12122
- const message = err instanceof Error ? err.message : fallbackMessage;
12307
+ const admissionError = preserveAdmissionError && err instanceof AgentEffectAdmissionError;
12308
+ const rejectedAdmissionError = !preserveAdmissionError && err instanceof AgentEffectAdmissionError;
12309
+ const code = admissionError ? err.code : parsedCode.success ? parsedCode.data : ErrorCode.enum.INTERNAL_ERROR;
12310
+ const message = !rejectedAdmissionError && err instanceof Error ? err.message : fallbackMessage;
12123
12311
  return reply.code(statusCode).send({
12124
12312
  error: {
12125
12313
  code,
12126
12314
  message,
12127
12315
  retryable: err?.retryable === true ? true : void 0,
12128
- details: err?.details
12316
+ details: rejectedAdmissionError ? void 0 : err?.details
12129
12317
  }
12130
12318
  });
12131
12319
  }
@@ -12364,7 +12552,7 @@ function meteredCommandBlocked(command) {
12364
12552
  }
12365
12553
  function stableErrorPayload(error, message) {
12366
12554
  const code = error?.code;
12367
- if (!isErrorCode(code)) return void 0;
12555
+ if (!isErrorCode(code) && !(error instanceof AgentEffectAdmissionError)) return void 0;
12368
12556
  const details = error?.details;
12369
12557
  return {
12370
12558
  error: {
@@ -12412,6 +12600,7 @@ function commandsRoutes(app, opts, done) {
12412
12600
  if (meteringActive) {
12413
12601
  return reply.code(409).send(meteredCommandBlocked(name));
12414
12602
  }
12603
+ await opts.admitEffect?.({ workspaceId: getRequestWorkspaceId(request), requestId: request.id });
12415
12604
  await harness.executeSlashCommand(sessionId, name, args, runContext);
12416
12605
  return reply.code(200).send({ ok: true });
12417
12606
  } catch (error) {
@@ -13310,6 +13499,51 @@ function buildUploadAgentTools(bundle) {
13310
13499
  ];
13311
13500
  }
13312
13501
 
13502
+ // src/server/http/routes/deepLink.ts
13503
+ var DEFAULT_WORKSPACE_ID4 = "default";
13504
+ function getRequestWorkspaceId2(request) {
13505
+ return request.workspaceContext?.workspaceId ?? DEFAULT_WORKSPACE_ID4;
13506
+ }
13507
+ function sendShareNotFound(reply) {
13508
+ return reply.code(404).send({
13509
+ error: { code: ShareEntryErrorCode.enum.AR1_SHARE_NOT_FOUND, message: "share not found" }
13510
+ });
13511
+ }
13512
+ var deepLinkRoutes = (app, opts, done) => {
13513
+ async function resolveWorkspace(request) {
13514
+ if (opts.getWorkspace) return await opts.getWorkspace(request);
13515
+ if (opts.workspace) return opts.workspace;
13516
+ throw new Error("deep-link route requires workspace or getWorkspace");
13517
+ }
13518
+ app.get("/a/:id", async (request, reply) => {
13519
+ const { id } = request.params;
13520
+ const requestWorkspaceId = getRequestWorkspaceId2(request);
13521
+ const entry = await opts.store.get(id);
13522
+ if (!entry || entry.workspaceId !== requestWorkspaceId) {
13523
+ return sendShareNotFound(reply);
13524
+ }
13525
+ const workspace = await resolveWorkspace(request);
13526
+ const resolution = await resolveShareEntry(opts.store, id, workspace);
13527
+ switch (resolution.status) {
13528
+ case "not_found":
13529
+ return sendShareNotFound(reply);
13530
+ case "tombstoned":
13531
+ return reply.code(200).send({
13532
+ status: "tombstoned",
13533
+ code: resolution.code,
13534
+ tombstone: resolution.tombstone
13535
+ });
13536
+ case "ok":
13537
+ return reply.code(200).send({
13538
+ status: "ok",
13539
+ workspaceId: resolution.entry.workspaceId,
13540
+ id: resolution.entry.id
13541
+ });
13542
+ }
13543
+ });
13544
+ done();
13545
+ };
13546
+
13313
13547
  // src/server/runtime/runtimeBindingLifecycle.ts
13314
13548
  function createRuntimeBindingLifecycle(options) {
13315
13549
  const { app } = options;
@@ -13597,7 +13831,7 @@ function createRuntimeBindingLifecycle(options) {
13597
13831
 
13598
13832
  // src/server/registerAgentRoutes.ts
13599
13833
  var DEFAULT_VERSION2 = "0.1.0-dev";
13600
- var DEFAULT_WORKSPACE_ID4 = "default";
13834
+ var DEFAULT_WORKSPACE_ID5 = "default";
13601
13835
  var STANDARD_AGENT_TOOL_NAMES = ["bash", "read", "write", "edit", "find", "grep", "ls"];
13602
13836
  function pluginNameFromPath(path4) {
13603
13837
  const fileName = basename2(path4);
@@ -13617,8 +13851,8 @@ function getAvailableModelProviders() {
13617
13851
  new Set(availableModels.map((model) => model.provider))
13618
13852
  ).sort((a, b) => a.localeCompare(b));
13619
13853
  }
13620
- function getRequestWorkspaceId2(request) {
13621
- return request.workspaceContext?.workspaceId ?? DEFAULT_WORKSPACE_ID4;
13854
+ function getRequestWorkspaceId3(request) {
13855
+ return request.workspaceContext?.workspaceId ?? DEFAULT_WORKSPACE_ID5;
13622
13856
  }
13623
13857
  function promoteRawFileWorkspaceQueryToHeader(request) {
13624
13858
  const pathname = request.url.split("?")[0] ?? request.url;
@@ -13711,7 +13945,7 @@ function createRuntimeReadinessCheck(workspaceId, getRuntimeDependencies) {
13711
13945
  };
13712
13946
  }
13713
13947
  var registerAgentRoutes = async (app, opts) => {
13714
- const sessionId = opts.sessionId ?? DEFAULT_WORKSPACE_ID4;
13948
+ const sessionId = opts.sessionId ?? DEFAULT_WORKSPACE_ID5;
13715
13949
  const resolvedMode = opts.runtimeModeAdapter?.id ?? opts.mode ?? autoDetectMode();
13716
13950
  const workspaceRoot = opts.workspaceRoot ?? process.cwd();
13717
13951
  const templatePath = opts.templatePath ?? getEnv("BORING_AGENT_TEMPLATE_PATH");
@@ -14039,6 +14273,7 @@ var registerAgentRoutes = async (app, opts) => {
14039
14273
  workdir: root
14040
14274
  }, {
14041
14275
  service: {
14276
+ admitEffect: opts.admitEffect,
14042
14277
  workdir: runtimeBundle.workspace.root,
14043
14278
  workspace: runtimeBundle.workspace
14044
14279
  }
@@ -14280,14 +14515,14 @@ var registerAgentRoutes = async (app, opts) => {
14280
14515
  function getSkillsScopeForRequest(request) {
14281
14516
  let promise = skillsScopeByRequest.get(request);
14282
14517
  if (!promise) {
14283
- promise = resolveSkillScope(getRequestWorkspaceId2(request), request);
14518
+ promise = resolveSkillScope(getRequestWorkspaceId3(request), request);
14284
14519
  skillsScopeByRequest.set(request, promise);
14285
14520
  }
14286
14521
  return promise;
14287
14522
  }
14288
14523
  async function getBindingForRequest(request, options = {}) {
14289
14524
  if (staticBinding) return staticBinding;
14290
- return await getOrCreateRuntimeBinding(getRequestWorkspaceId2(request), request, options);
14525
+ return await getOrCreateRuntimeBinding(getRequestWorkspaceId3(request), request, options);
14291
14526
  }
14292
14527
  async function getFilesystemBindingsForRequest(request) {
14293
14528
  const binding = await getBindingForRequest(request);
@@ -14295,7 +14530,7 @@ var registerAgentRoutes = async (app, opts) => {
14295
14530
  const user = request.user;
14296
14531
  return await opts.getFilesystemBindings({
14297
14532
  request,
14298
- workspaceId: getRequestWorkspaceId2(request),
14533
+ workspaceId: getRequestWorkspaceId3(request),
14299
14534
  workspaceRoot: binding.workspaceRoot,
14300
14535
  userId: user?.id,
14301
14536
  userEmail: user?.email,
@@ -14322,7 +14557,7 @@ var registerAgentRoutes = async (app, opts) => {
14322
14557
  }
14323
14558
  app.addHook("onRequest", async (request, reply) => {
14324
14559
  const user = request.user;
14325
- let workspaceId = DEFAULT_WORKSPACE_ID4;
14560
+ let workspaceId = DEFAULT_WORKSPACE_ID5;
14326
14561
  promoteRawFileWorkspaceQueryToHeader(request);
14327
14562
  if (opts.getWorkspaceId && !isWorkspaceAgnosticAgentRequest(request, { readyStatusWorkspaceScoped: requestScopedRuntime, modelsWorkspaceScoped })) {
14328
14563
  try {
@@ -14376,6 +14611,12 @@ var registerAgentRoutes = async (app, opts) => {
14376
14611
  await app.register(searchRoutes, {
14377
14612
  getFileSearch: async (request) => (await getBindingForRequest(request)).runtimeBundle.fileSearch
14378
14613
  });
14614
+ if (opts.shareEntryStore) {
14615
+ await app.register(deepLinkRoutes, {
14616
+ store: opts.shareEntryStore,
14617
+ getWorkspace: async (request) => (await getBindingForRequest(request)).runtimeBundle.workspace
14618
+ });
14619
+ }
14379
14620
  await app.register(gitRoutes, {
14380
14621
  getWorkspace: async (request) => {
14381
14622
  const runtimeBundle = (await getBindingForRequest(request)).runtimeBundle;
@@ -14421,12 +14662,13 @@ var registerAgentRoutes = async (app, opts) => {
14421
14662
  });
14422
14663
  await app.register(sessionChangesRoutes, { tracker: sessionChangesTracker });
14423
14664
  app.post("/api/v1/agent/reload", async (request, reply) => {
14424
- const workspaceId = getRequestWorkspaceId2(request);
14665
+ const workspaceId = getRequestWorkspaceId3(request);
14425
14666
  const binding = await getBindingForRequest(request);
14426
14667
  if (!binding.harness.reloadSession) {
14427
14668
  return reply.status(501).send({ ok: false, error: "Agent harness does not support reload" });
14428
14669
  }
14429
14670
  try {
14671
+ await opts.admitEffect?.({ workspaceId, requestId: request.id });
14430
14672
  await binding.reprovision(request);
14431
14673
  binding.assertActive();
14432
14674
  const hookResult = await opts.beforeReload?.({
@@ -14464,6 +14706,9 @@ var registerAgentRoutes = async (app, opts) => {
14464
14706
  };
14465
14707
  } catch (error) {
14466
14708
  const message = error instanceof Error ? error.message : String(error);
14709
+ if (error instanceof AgentEffectAdmissionError) {
14710
+ return reply.status(error.statusCode).send({ ok: false, error: { code: error.code, message } });
14711
+ }
14467
14712
  return reply.status(422).send({ ok: false, error: message });
14468
14713
  }
14469
14714
  });
@@ -14477,12 +14722,14 @@ var registerAgentRoutes = async (app, opts) => {
14477
14722
  harness: staticBinding.harness,
14478
14723
  defaultSessionId: sessionId,
14479
14724
  workdir: staticBinding.runtimeBundle.workspace.root,
14480
- metering: opts.metering
14725
+ metering: opts.metering,
14726
+ admitEffect: opts.admitEffect
14481
14727
  } : {
14482
14728
  defaultSessionId: sessionId,
14483
14729
  getHarness: async (request) => (await getBindingForRequest(request)).harness,
14484
14730
  getWorkdir: async (request) => (await getBindingForRequest(request)).runtimeBundle.workspace.root,
14485
- metering: opts.metering
14731
+ metering: opts.metering,
14732
+ admitEffect: opts.admitEffect
14486
14733
  }
14487
14734
  );
14488
14735
  await app.register(
@@ -14545,6 +14792,8 @@ export {
14545
14792
  ManagedAgentMcpError,
14546
14793
  ManagedAgentMcpDelegateController,
14547
14794
  createManagedAgentMcpDelegateController,
14795
+ shareResourceUri,
14796
+ registerShareEntryResources,
14548
14797
  createManagedAgentMcpServer,
14549
14798
  createManagedAgentMcpHttpHandler,
14550
14799
  createAgentApp,