@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.
- package/dist/{chunk-DC3S7SZG.js → chunk-6O5ADR57.js} +1 -1
- package/dist/{chunk-PG2WOJ22.js → chunk-HDIRWHJB.js} +5 -1
- package/dist/{chunk-7V3E6KHX.js → chunk-HY7EERLW.js} +279 -30
- package/dist/{chunk-TNN3LPXE.js → chunk-LYBTHR7J.js} +68 -3
- package/dist/{chunk-WODTQBXR.js → chunk-YONTHCD7.js} +108 -2
- package/dist/{chunk-5NAN3TAR.js → chunk-ZUDWQAAB.js} +1 -1
- package/dist/core/index.d.ts +7 -51
- package/dist/core/index.js +10 -4
- package/dist/{createHarness-TGBJZISM.js → createHarness-MJ5GEL6J.js} +2 -2
- package/dist/front/index.d.ts +1 -1
- package/dist/front/index.js +2 -2
- package/dist/{harness-C53mjCcq.d.ts → harness-RhGbdGWY.d.ts} +1 -1
- package/dist/{piChatEvent-3pFPXYPx.d.ts → piChatEvent-CUTKRaZD.d.ts} +15 -15
- package/dist/piChatSessionService-iBtx32ya.d.ts +67 -0
- package/dist/server/index.d.ts +47 -5
- package/dist/server/index.js +12 -8
- package/dist/server/worker/index.js +6 -6
- package/dist/shared/index.d.ts +86 -38
- package/dist/shared/index.js +96 -5
- package/dist/workspaceAgentDispatcher-Dv0DocrE.d.ts +314 -0
- package/docs/ERROR_CODES.md +2 -0
- package/package.json +2 -2
- package/dist/workspaceAgentDispatcher-p4tlVvbM.d.ts +0 -151
|
@@ -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-
|
|
16
|
+
} from "./chunk-YONTHCD7.js";
|
|
15
17
|
import {
|
|
18
|
+
AgentEffectAdmissionError,
|
|
16
19
|
createAgentRuntimeBridge
|
|
17
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
12122
|
-
const
|
|
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
|
|
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
|
|
13621
|
-
return request.workspaceContext?.workspaceId ??
|
|
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 ??
|
|
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(
|
|
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(
|
|
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:
|
|
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 =
|
|
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 =
|
|
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,
|