@hachej/boring-agent 0.1.111 → 0.2.0
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/LICENSE +1 -1
- package/README.md +262 -51
- package/dist/agents.d.ts +75 -0
- package/dist/agents.js +91 -0
- package/dist/approval.d.ts +71 -0
- package/dist/approval.js +126 -0
- package/dist/artifacts.d.ts +53 -0
- package/dist/artifacts.js +129 -0
- package/dist/ask-user.d.ts +40 -0
- package/dist/ask-user.js +134 -0
- package/dist/attachment.d.ts +5 -0
- package/dist/attachment.js +4 -0
- package/dist/browser-task.d.ts +32 -0
- package/dist/browser-task.js +119 -0
- package/dist/chat-transport.d.ts +80 -0
- package/dist/chat-transport.js +306 -0
- package/dist/contracts.d.ts +40 -0
- package/dist/contracts.js +1 -0
- package/dist/conversations.d.ts +136 -0
- package/dist/conversations.js +366 -0
- package/dist/definitions.d.ts +37 -0
- package/dist/definitions.js +99 -0
- package/dist/delivery-input.d.ts +35 -0
- package/dist/delivery-input.js +56 -0
- package/dist/delivery.d.ts +33 -0
- package/dist/delivery.js +154 -0
- package/dist/durable-wait.d.ts +23 -0
- package/dist/durable-wait.js +79 -0
- package/dist/file-convert.d.ts +46 -0
- package/dist/file-convert.js +159 -0
- package/dist/file-guard.d.ts +50 -0
- package/dist/file-guard.js +171 -0
- package/dist/file-types.d.ts +17 -0
- package/dist/file-types.js +95 -0
- package/dist/gateway-provider.d.ts +24 -0
- package/dist/gateway-provider.js +42 -0
- package/dist/git.d.ts +34 -0
- package/dist/git.js +79 -0
- package/dist/harness-pool.d.ts +38 -0
- package/dist/harness-pool.js +134 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +1 -0
- package/dist/json-schema-tool.d.ts +25 -0
- package/dist/json-schema-tool.js +19 -0
- package/dist/memory/optchat-core.d.ts +118 -0
- package/dist/memory/optchat-core.js +317 -0
- package/dist/memory/optchat.d.ts +156 -0
- package/dist/memory/optchat.js +432 -0
- package/dist/mentions.d.ts +56 -0
- package/dist/mentions.js +140 -0
- package/dist/metering.d.ts +183 -0
- package/dist/metering.js +443 -0
- package/dist/model-gateway.d.ts +86 -0
- package/dist/model-gateway.js +241 -0
- package/dist/native-version.d.ts +9 -0
- package/dist/native-version.js +7 -0
- package/dist/native.d.ts +4 -0
- package/dist/native.js +1 -0
- package/dist/presentation.d.ts +17 -0
- package/dist/presentation.js +39 -0
- package/dist/projection-format.d.ts +68 -0
- package/dist/projection-format.js +118 -0
- package/dist/projection-window.d.ts +9 -0
- package/dist/projection-window.js +93 -0
- package/dist/projection.d.ts +22 -0
- package/dist/projection.js +153 -0
- package/dist/question-response.d.ts +20 -0
- package/dist/question-response.js +75 -0
- package/dist/questions.d.ts +74 -0
- package/dist/questions.js +199 -0
- package/dist/self-evolving.d.ts +55 -0
- package/dist/self-evolving.js +239 -0
- package/dist/skills.d.ts +15 -0
- package/dist/skills.js +51 -0
- package/dist/tool-evidence.d.ts +14 -0
- package/dist/tool-evidence.js +54 -0
- package/dist/validation.d.ts +38 -0
- package/dist/validation.js +68 -0
- package/dist/workspaces.d.ts +107 -0
- package/dist/workspaces.js +212 -0
- package/package.json +145 -150
- package/dist/DebugDrawer-JNA43SVR.js +0 -8
- package/dist/admin-DORVQfLn.d.ts +0 -340
- package/dist/chunk-2BGLZZ7T.js +0 -10
- package/dist/chunk-42D6KAQV.js +0 -2882
- package/dist/chunk-4XOW57KJ.js +0 -343
- package/dist/chunk-72KT6VWV.js +0 -1338
- package/dist/chunk-7XAOVFSN.js +0 -28
- package/dist/chunk-KJIEMSQP.js +0 -198
- package/dist/chunk-KN72XWP7.js +0 -394
- package/dist/chunk-N6THTH7P.js +0 -110
- package/dist/chunk-V3H5A3BR.js +0 -22501
- package/dist/chunk-YGRQ4Q5P.js +0 -20
- package/dist/chunk-YTUZFKB3.js +0 -78
- package/dist/core/index.d.ts +0 -28
- package/dist/core/index.js +0 -617
- package/dist/createHarness-DOLOHA62.js +0 -18
- package/dist/eval/index.d.ts +0 -247
- package/dist/eval/index.js +0 -541
- package/dist/file-search-BUgMSKZE.d.ts +0 -289
- package/dist/front/artifacts.d.ts +0 -34
- package/dist/front/artifacts.js +0 -21
- package/dist/front/index.d.ts +0 -1082
- package/dist/front/index.js +0 -12912
- package/dist/front/styles.css +0 -5380
- package/dist/harness-qHlMJhZo.d.ts +0 -276
- package/dist/middleware-CaAEXpi5.d.ts +0 -115
- package/dist/piChatEvent-DpE0lIb9.d.ts +0 -450
- package/dist/piChatSessionService-CBct-hmz.d.ts +0 -86
- package/dist/sandbox-BMhut3kh.d.ts +0 -317
- package/dist/server/agent-host/testing/compositionRouteProof.d.ts +0 -8
- package/dist/server/agent-host/testing/compositionRouteProof.js +0 -78
- package/dist/server/agent-host/testing/gatewayConformance.d.ts +0 -43
- package/dist/server/agent-host/testing/gatewayConformance.js +0 -605
- package/dist/server/index.d.ts +0 -2278
- package/dist/server/index.js +0 -274
- package/dist/server/pi-session-readability.d.ts +0 -12
- package/dist/server/pi-session-readability.js +0 -23
- package/dist/server/worker/index.d.ts +0 -68
- package/dist/server/worker/index.js +0 -377
- package/dist/share-entry-CxS6UJ_L.d.ts +0 -330
- package/dist/shared/index.d.ts +0 -2111
- package/dist/shared/index.js +0 -262
- package/dist/types-DcWoQMn8.d.ts +0 -1377
- package/docs/ACCESSIBILITY.md +0 -52
- package/docs/AGENT_GATEWAY_V0.md +0 -212
- package/docs/AGENT_PACKAGES.md +0 -90
- package/docs/API.md +0 -123
- package/docs/AUTHORING.md +0 -68
- package/docs/CSP.md +0 -41
- package/docs/ERROR_CODES.md +0 -229
- package/docs/KNOWN_LIMITATIONS.md +0 -100
- package/docs/MIGRATION.md +0 -50
- package/docs/PERFORMANCE.md +0 -68
- package/docs/PLUGINS.md +0 -138
- package/docs/README.md +0 -98
- package/docs/RISKS-MULTI-TAB.md +0 -46
- package/docs/SESSION_IDENTITY.md +0 -91
- package/docs/STYLING.md +0 -73
- package/docs/UI-SHADCN.md +0 -56
- package/docs/VERCEL_COSTS.md +0 -103
- package/docs/plans/archive/AGENT_EVAL_FRAMEWORK.md +0 -466
- package/docs/plans/archive/agent-package-spec.md +0 -1777
- package/docs/plans/archive/harness-followup-capabilities.md +0 -440
- package/docs/plans/archive/harness-tool-ui-capabilities.md +0 -144
- package/docs/plans/archive/pi-followup-history-projection.md +0 -229
- package/docs/plans/archive/pi-tools-migration.md +0 -1061
- package/docs/plans/archive/reviews/pi-followup-history-codex-review.md +0 -11
- package/docs/plans/archive/reviews/pi-followup-history-gpt-review.md +0 -64
- package/docs/plans/archive/reviews/pi-followup-history-opus-review.md +0 -43
- package/docs/plans/archive/reviews/pi-followup-history-xai-review.md +0 -43
- package/docs/plans/archive/vercel-base-snapshot-template-plan.md +0 -527
- package/docs/plans/archive/vercel-persistent-sandbox-adapter.md +0 -553
- package/docs/runtime-provisioning.md +0 -157
- package/docs/runtime.md +0 -296
- package/docs/tools.md +0 -102
package/dist/chunk-72KT6VWV.js
DELETED
|
@@ -1,1338 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
safeRandomUUID
|
|
3
|
-
} from "./chunk-YGRQ4Q5P.js";
|
|
4
|
-
import {
|
|
5
|
-
AgentConsumptionErrorCode,
|
|
6
|
-
AgentDefinitionErrorCode,
|
|
7
|
-
AgentDeploymentErrorCode,
|
|
8
|
-
ErrorCode
|
|
9
|
-
} from "./chunk-KJIEMSQP.js";
|
|
10
|
-
|
|
11
|
-
// src/shared/skill-resource.ts
|
|
12
|
-
var AGENT_RESOURCES_FILESYSTEM_ID = "agent_resources";
|
|
13
|
-
var AGENT_KNOWLEDGE_FILESYSTEM_ID = "agent_knowledge";
|
|
14
|
-
|
|
15
|
-
// src/shared/workspace.ts
|
|
16
|
-
var READONLY_FILESYSTEM_MUTATION_CODE = "readonly";
|
|
17
|
-
var RUNTIME_FILESYSTEM_CAPABILITIES = Object.freeze([
|
|
18
|
-
"read",
|
|
19
|
-
"write",
|
|
20
|
-
"create-child",
|
|
21
|
-
"delete",
|
|
22
|
-
"move-from"
|
|
23
|
-
]);
|
|
24
|
-
var ReadonlyFilesystemMutationError = class extends Error {
|
|
25
|
-
code = READONLY_FILESYSTEM_MUTATION_CODE;
|
|
26
|
-
statusCode = 403;
|
|
27
|
-
filesystem;
|
|
28
|
-
operation;
|
|
29
|
-
constructor(filesystem, operation) {
|
|
30
|
-
super(`${filesystem} binding is readonly`);
|
|
31
|
-
this.name = "ReadonlyFilesystemMutationError";
|
|
32
|
-
this.filesystem = filesystem;
|
|
33
|
-
this.operation = operation;
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
function isReadonlyFilesystemMutationError(value) {
|
|
37
|
-
if (!value || typeof value !== "object") return false;
|
|
38
|
-
const candidate = value;
|
|
39
|
-
return candidate.code === READONLY_FILESYSTEM_MUTATION_CODE && candidate.statusCode === 403 && typeof candidate.filesystem === "string" && RUNTIME_FILESYSTEM_CAPABILITIES.includes(candidate.operation);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// src/shared/channel.ts
|
|
43
|
-
var descriptors = [
|
|
44
|
-
{
|
|
45
|
-
id: "web",
|
|
46
|
-
label: "Web",
|
|
47
|
-
icon: "globe",
|
|
48
|
-
sessionsReadOnlyInWorkspace: false,
|
|
49
|
-
dialect: "passthrough",
|
|
50
|
-
canOriginateIdentity: true
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
id: "whatsapp",
|
|
54
|
-
label: "WhatsApp",
|
|
55
|
-
icon: "message-circle",
|
|
56
|
-
sessionsReadOnlyInWorkspace: true,
|
|
57
|
-
dialect: "whatsapp/markdown",
|
|
58
|
-
canOriginateIdentity: true
|
|
59
|
-
}
|
|
60
|
-
];
|
|
61
|
-
var CHANNEL_DESCRIPTORS = new Map(
|
|
62
|
-
descriptors.map((descriptor) => [descriptor.id, Object.freeze(descriptor)])
|
|
63
|
-
);
|
|
64
|
-
function channelDescriptor(originChannel = "web") {
|
|
65
|
-
return CHANNEL_DESCRIPTORS.get(originChannel);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// src/shared/config-schema.ts
|
|
69
|
-
import { z } from "zod";
|
|
70
|
-
var RuntimeModeSchema = z.enum(["direct", "local", "blaxel", "vercel-sandbox"]);
|
|
71
|
-
var ConfigSchema = z.object({
|
|
72
|
-
workspaceRoot: z.string(),
|
|
73
|
-
workspaceId: z.string(),
|
|
74
|
-
port: z.number().int().positive(),
|
|
75
|
-
mode: RuntimeModeSchema,
|
|
76
|
-
model: z.string().optional(),
|
|
77
|
-
noOpen: z.boolean(),
|
|
78
|
-
noGitignore: z.boolean(),
|
|
79
|
-
dev: z.boolean(),
|
|
80
|
-
verbose: z.boolean()
|
|
81
|
-
});
|
|
82
|
-
var EnvSchema = z.object({
|
|
83
|
-
BORING_AGENT_MODE: RuntimeModeSchema.optional(),
|
|
84
|
-
BORING_AGENT_WORKSPACE_ROOT: z.string().optional(),
|
|
85
|
-
BORING_AGENT_PORT: z.coerce.number().int().positive().optional(),
|
|
86
|
-
BORING_AGENT_TEMPLATE_PATH: z.string().optional(),
|
|
87
|
-
BORING_AGENT_VERBOSE: z.enum(["0", "1"]).optional(),
|
|
88
|
-
BORING_AGENT_MODEL: z.string().optional(),
|
|
89
|
-
BORING_AGENT_DEFAULT_MODEL: z.string().optional(),
|
|
90
|
-
BORING_AGENT_DEFAULT_MODEL_PROVIDER: z.string().optional(),
|
|
91
|
-
BORING_AGENT_DEFAULT_MODEL_ID: z.string().optional(),
|
|
92
|
-
BORING_AGENT_INFOMANIAK_PROVIDER: z.string().optional(),
|
|
93
|
-
BORING_AGENT_INFOMANIAK_PRODUCT_ID: z.string().optional(),
|
|
94
|
-
BORING_AGENT_INFOMANIAK_BASE_URL: z.string().url().optional(),
|
|
95
|
-
BORING_AGENT_INFOMANIAK_MODEL: z.string().optional(),
|
|
96
|
-
BORING_AGENT_INFOMANIAK_MODEL_NAME: z.string().optional(),
|
|
97
|
-
BORING_AGENT_INFOMANIAK_API_KEY_ENV: z.string().optional(),
|
|
98
|
-
BORING_AGENT_INFOMANIAK_API_KEY: z.string().optional(),
|
|
99
|
-
BORING_AGENT_CUSTOM_MODEL_PROVIDER: z.string().optional(),
|
|
100
|
-
BORING_AGENT_CUSTOM_MODEL_ID: z.string().optional(),
|
|
101
|
-
BORING_AGENT_CUSTOM_MODEL_NAME: z.string().optional(),
|
|
102
|
-
BORING_AGENT_CUSTOM_MODEL_BASE_URL: z.string().url().optional(),
|
|
103
|
-
BORING_AGENT_CUSTOM_MODEL_API_KEY_ENV: z.string().optional(),
|
|
104
|
-
BORING_AGENT_CUSTOM_MODEL_API_KEY: z.string().optional(),
|
|
105
|
-
BORING_AGENT_CONFIG: z.string().optional(),
|
|
106
|
-
BORING_AGENT_DEV: z.enum(["0", "1"]).optional(),
|
|
107
|
-
BORING_AGENT_NO_OPEN: z.enum(["0", "1"]).optional(),
|
|
108
|
-
BORING_AGENT_NO_GITIGNORE: z.enum(["0", "1"]).optional(),
|
|
109
|
-
BORING_AGENT_SNAPSHOT_KEEP: z.coerce.number().int().nonnegative().optional(),
|
|
110
|
-
BORING_AGENT_PYTHON_PACKAGES: z.string().optional(),
|
|
111
|
-
VERCEL_OIDC_TOKEN: z.string().optional(),
|
|
112
|
-
VERCEL_ACCESS_TOKEN: z.string().optional(),
|
|
113
|
-
VERCEL_TOKEN: z.string().optional(),
|
|
114
|
-
VERCEL_TEAM_ID: z.string().optional(),
|
|
115
|
-
VERCEL_PROJECT_ID: z.string().optional(),
|
|
116
|
-
BORING_AGENT_VERCEL_SANDBOX_TIMEOUT_MS: z.coerce.number().int().positive().optional(),
|
|
117
|
-
BL_WORKSPACE: z.string().optional(),
|
|
118
|
-
BL_API_KEY: z.string().optional(),
|
|
119
|
-
BORING_BLAXEL_IMAGE: z.string().optional(),
|
|
120
|
-
BORING_BLAXEL_MEMORY_MB: z.coerce.number().int().positive().optional(),
|
|
121
|
-
BORING_BLAXEL_REGION: z.string().optional(),
|
|
122
|
-
BORING_BLAXEL_VOLUME_SIZE_MB: z.coerce.number().int().positive().optional(),
|
|
123
|
-
BORING_BLAXEL_TTL: z.string().optional(),
|
|
124
|
-
BORING_BLAXEL_IDLE_TTL: z.string().optional(),
|
|
125
|
-
BORING_BLAXEL_TERMINATED_RETENTION: z.string().optional()
|
|
126
|
-
});
|
|
127
|
-
function validateConfig(config) {
|
|
128
|
-
return ConfigSchema.parse(config);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// src/shared/capabilities.ts
|
|
132
|
-
var DEFAULT_AGENT_RUNTIME_CAPABILITIES = {
|
|
133
|
-
nativeFollowUp: false,
|
|
134
|
-
aiSdkOwnsHistory: true
|
|
135
|
-
};
|
|
136
|
-
var PI_AGENT_RUNTIME_CAPABILITIES = {
|
|
137
|
-
nativeFollowUp: true,
|
|
138
|
-
aiSdkOwnsHistory: false
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
// src/shared/agent-definition.ts
|
|
142
|
-
import { z as z3 } from "zod";
|
|
143
|
-
|
|
144
|
-
// src/shared/digest.ts
|
|
145
|
-
function toHex(bytes) {
|
|
146
|
-
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
147
|
-
}
|
|
148
|
-
async function digestBytes(bytes) {
|
|
149
|
-
const hash = await globalThis.crypto.subtle.digest("SHA-256", new Uint8Array(bytes));
|
|
150
|
-
return `sha256:${toHex(new Uint8Array(hash))}`;
|
|
151
|
-
}
|
|
152
|
-
async function sha256(value) {
|
|
153
|
-
return digestBytes(new TextEncoder().encode(value));
|
|
154
|
-
}
|
|
155
|
-
async function sha256Bytes(bytes) {
|
|
156
|
-
return digestBytes(bytes);
|
|
157
|
-
}
|
|
158
|
-
function canonicalStringify(value) {
|
|
159
|
-
if (value === null || typeof value !== "object") {
|
|
160
|
-
const encoded = JSON.stringify(value);
|
|
161
|
-
if (encoded === void 0) throw new TypeError("Cannot canonicalize undefined");
|
|
162
|
-
return encoded;
|
|
163
|
-
}
|
|
164
|
-
if (Array.isArray(value)) return `[${value.map(canonicalStringify).join(",")}]`;
|
|
165
|
-
const record = value;
|
|
166
|
-
return `{${Object.keys(record).filter((key) => record[key] !== void 0).sort().map((key) => `${JSON.stringify(key)}:${canonicalStringify(record[key])}`).join(",")}}`;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// src/shared/schema-issue.ts
|
|
170
|
-
import { z as z2 } from "zod";
|
|
171
|
-
function formatPath(path) {
|
|
172
|
-
if (path.length === 0) return "<root>";
|
|
173
|
-
return path.reduce(
|
|
174
|
-
(result, part) => typeof part === "number" ? `${result}[${part}]` : result.length === 0 ? String(part) : `${result}.${String(part)}`,
|
|
175
|
-
""
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
function mapZodIssues(issues, invalidCode, unsupportedCode) {
|
|
179
|
-
return issues.flatMap((issue) => {
|
|
180
|
-
if (issue.code === z2.ZodIssueCode.unrecognized_keys) {
|
|
181
|
-
const parent = formatPath(issue.path);
|
|
182
|
-
return [...issue.keys].sort().map((key) => ({
|
|
183
|
-
code: unsupportedCode,
|
|
184
|
-
field: parent === "<root>" ? key : `${parent}.${key}`,
|
|
185
|
-
message: `${key} is not supported by schema version 1`
|
|
186
|
-
}));
|
|
187
|
-
}
|
|
188
|
-
const field = formatPath(issue.path);
|
|
189
|
-
return [{
|
|
190
|
-
code: invalidCode,
|
|
191
|
-
field,
|
|
192
|
-
message: field === "<root>" ? issue.message : `${field} ${issue.message}`
|
|
193
|
-
}];
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
var SchemaValidationError = class extends Error {
|
|
197
|
-
code = ErrorCode.enum.CONFIG_INVALID;
|
|
198
|
-
field;
|
|
199
|
-
validationCode;
|
|
200
|
-
constructor(issue) {
|
|
201
|
-
super(issue.message);
|
|
202
|
-
this.field = issue.field;
|
|
203
|
-
this.validationCode = issue.code;
|
|
204
|
-
}
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
// src/shared/agent-definition.ts
|
|
208
|
-
var SHA256_DIGEST_RE = /^sha256:[a-f0-9]{64}$/;
|
|
209
|
-
function hasWellFormedUnicode(value) {
|
|
210
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
211
|
-
const code = value.charCodeAt(index);
|
|
212
|
-
if (code >= 55296 && code <= 56319) {
|
|
213
|
-
if (index + 1 >= value.length) return false;
|
|
214
|
-
const next = value.charCodeAt(index + 1);
|
|
215
|
-
if (next < 56320 || next > 57343) return false;
|
|
216
|
-
index += 1;
|
|
217
|
-
} else if (code >= 56320 && code <= 57343) {
|
|
218
|
-
return false;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
return true;
|
|
222
|
-
}
|
|
223
|
-
function isOpaqueRef(value) {
|
|
224
|
-
return hasWellFormedUnicode(value) && value.trim() === value && !/[\0-\x1f\x7f]/.test(value);
|
|
225
|
-
}
|
|
226
|
-
function isSafeAssetPath(value) {
|
|
227
|
-
const segments = value.split("/");
|
|
228
|
-
return hasWellFormedUnicode(value) && value.normalize("NFC") === value && !/[\0-\x1f\x7f]/.test(value) && !value.includes("\\") && !value.startsWith("/") && !/^[A-Za-z]:[\\/]/.test(value) && !value.startsWith("./") && segments.every((segment) => segment !== "" && segment !== "." && segment !== "..");
|
|
229
|
-
}
|
|
230
|
-
var OpaqueRefSchema = z3.string().min(1, "must be a non-empty reference").max(256, "must be at most 256 characters").refine(isOpaqueRef, "must be a non-empty reference");
|
|
231
|
-
var ReferenceArraySchema = z3.array(OpaqueRefSchema).superRefine((refs, ctx) => {
|
|
232
|
-
const seen = /* @__PURE__ */ new Set();
|
|
233
|
-
refs.forEach((ref, index) => {
|
|
234
|
-
if (seen.has(ref)) {
|
|
235
|
-
ctx.addIssue({
|
|
236
|
-
code: z3.ZodIssueCode.custom,
|
|
237
|
-
path: [index],
|
|
238
|
-
message: "must not contain duplicate references"
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
seen.add(ref);
|
|
242
|
-
});
|
|
243
|
-
});
|
|
244
|
-
var LABEL_MAX_LENGTH = 128;
|
|
245
|
-
var DESCRIPTION_MAX_LENGTH = 1024;
|
|
246
|
-
function isSafeDisplayText(value) {
|
|
247
|
-
return hasWellFormedUnicode(value) && value.trim() === value && !/[\0-\x1f\x7f-\x9f\u061c\u200e\u200f\u2028\u2029\u202a-\u202e\u2066-\u2069]/.test(value);
|
|
248
|
-
}
|
|
249
|
-
var LabelSchema = z3.string().min(1, "must not be empty").max(LABEL_MAX_LENGTH, `must be at most ${LABEL_MAX_LENGTH} characters`).refine(isSafeDisplayText, "must be trimmed and contain no control characters");
|
|
250
|
-
var DescriptionSchema = z3.string().min(1, "must not be empty").max(DESCRIPTION_MAX_LENGTH, `must be at most ${DESCRIPTION_MAX_LENGTH} characters`).refine(isSafeDisplayText, "must be trimmed and contain no control characters");
|
|
251
|
-
var SafeAssetPathSchema = z3.string().min(1).refine(isSafeAssetPath, "must be a safe relative asset path");
|
|
252
|
-
var Sha256DigestSchema = z3.string().regex(SHA256_DIGEST_RE, "must be a lowercase sha256 digest").transform((value) => value);
|
|
253
|
-
var AgentDefinitionInputSchema = z3.object({
|
|
254
|
-
schemaVersion: z3.literal(1),
|
|
255
|
-
definitionId: OpaqueRefSchema,
|
|
256
|
-
version: OpaqueRefSchema,
|
|
257
|
-
label: LabelSchema.optional(),
|
|
258
|
-
description: DescriptionSchema.optional(),
|
|
259
|
-
instructionsRef: SafeAssetPathSchema,
|
|
260
|
-
// Empty legacy arrays remain parseable only so old declarative directories
|
|
261
|
-
// fail with a targeted migration error when they still select behavior.
|
|
262
|
-
capabilityRequirements: ReferenceArraySchema.optional(),
|
|
263
|
-
toolRefs: ReferenceArraySchema.optional(),
|
|
264
|
-
skillRefs: ReferenceArraySchema.optional(),
|
|
265
|
-
mcpServerRefs: ReferenceArraySchema.optional()
|
|
266
|
-
}).strict();
|
|
267
|
-
var LEGACY_REFERENCE_FIELDS = [
|
|
268
|
-
"capabilityRequirements",
|
|
269
|
-
"toolRefs",
|
|
270
|
-
"skillRefs",
|
|
271
|
-
"mcpServerRefs"
|
|
272
|
-
];
|
|
273
|
-
var AgentDefinitionReferenceSchema = z3.object({
|
|
274
|
-
definitionId: OpaqueRefSchema,
|
|
275
|
-
version: OpaqueRefSchema,
|
|
276
|
-
digest: Sha256DigestSchema
|
|
277
|
-
}).strict();
|
|
278
|
-
var AgentDeploymentSchema = z3.object({
|
|
279
|
-
deploymentId: OpaqueRefSchema,
|
|
280
|
-
version: OpaqueRefSchema,
|
|
281
|
-
agentId: OpaqueRefSchema,
|
|
282
|
-
definition: AgentDefinitionReferenceSchema
|
|
283
|
-
}).strict();
|
|
284
|
-
var AgentDefinitionDigestAssetSchema = z3.object({
|
|
285
|
-
path: SafeAssetPathSchema,
|
|
286
|
-
digest: Sha256DigestSchema,
|
|
287
|
-
content: z3.string().refine(hasWellFormedUnicode, "must contain well-formed Unicode")
|
|
288
|
-
}).strict();
|
|
289
|
-
function validateAgentDefinition(raw) {
|
|
290
|
-
const result = AgentDefinitionInputSchema.safeParse(raw);
|
|
291
|
-
if (!result.success) {
|
|
292
|
-
return {
|
|
293
|
-
valid: false,
|
|
294
|
-
issues: mapZodIssues(
|
|
295
|
-
result.error.issues,
|
|
296
|
-
AgentDefinitionErrorCode.enum.AGENT_DEFINITION_INVALID,
|
|
297
|
-
AgentDefinitionErrorCode.enum.AGENT_DEFINITION_UNSUPPORTED_FIELD
|
|
298
|
-
)
|
|
299
|
-
};
|
|
300
|
-
}
|
|
301
|
-
for (const field of LEGACY_REFERENCE_FIELDS) {
|
|
302
|
-
if ((result.data[field]?.length ?? 0) > 0) {
|
|
303
|
-
return {
|
|
304
|
-
valid: false,
|
|
305
|
-
issues: [{
|
|
306
|
-
code: AgentDefinitionErrorCode.enum.AUTHORED_AGENT_REFERENCE_UNSUPPORTED,
|
|
307
|
-
field,
|
|
308
|
-
message: `${field} cannot select behavior; configure trusted host plugins instead`
|
|
309
|
-
}]
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
return {
|
|
314
|
-
valid: true,
|
|
315
|
-
value: {
|
|
316
|
-
schemaVersion: result.data.schemaVersion,
|
|
317
|
-
definitionId: result.data.definitionId,
|
|
318
|
-
version: result.data.version,
|
|
319
|
-
...result.data.label === void 0 ? {} : { label: result.data.label },
|
|
320
|
-
...result.data.description === void 0 ? {} : { description: result.data.description },
|
|
321
|
-
instructionsRef: result.data.instructionsRef
|
|
322
|
-
}
|
|
323
|
-
};
|
|
324
|
-
}
|
|
325
|
-
function validateAgentDeployment(raw) {
|
|
326
|
-
const result = AgentDeploymentSchema.safeParse(raw);
|
|
327
|
-
if (!result.success) {
|
|
328
|
-
return {
|
|
329
|
-
valid: false,
|
|
330
|
-
issues: mapZodIssues(
|
|
331
|
-
result.error.issues,
|
|
332
|
-
AgentDeploymentErrorCode.enum.AGENT_DEPLOYMENT_INVALID,
|
|
333
|
-
AgentDeploymentErrorCode.enum.AGENT_DEPLOYMENT_UNSUPPORTED_FIELD
|
|
334
|
-
)
|
|
335
|
-
};
|
|
336
|
-
}
|
|
337
|
-
return { valid: true, value: result.data };
|
|
338
|
-
}
|
|
339
|
-
async function createAgentAssetDigest(content) {
|
|
340
|
-
if (!hasWellFormedUnicode(content)) {
|
|
341
|
-
throw new AgentDefinitionValidationError({
|
|
342
|
-
code: AgentDefinitionErrorCode.enum.AGENT_DEFINITION_INVALID,
|
|
343
|
-
field: "content",
|
|
344
|
-
message: "content must contain well-formed Unicode"
|
|
345
|
-
});
|
|
346
|
-
}
|
|
347
|
-
return sha256(content);
|
|
348
|
-
}
|
|
349
|
-
var AgentDefinitionValidationError = class extends SchemaValidationError {
|
|
350
|
-
constructor(issue) {
|
|
351
|
-
super(issue);
|
|
352
|
-
this.name = "AgentDefinitionValidationError";
|
|
353
|
-
}
|
|
354
|
-
};
|
|
355
|
-
var AgentDeploymentValidationError = class extends SchemaValidationError {
|
|
356
|
-
constructor(issue) {
|
|
357
|
-
super(issue);
|
|
358
|
-
this.name = "AgentDeploymentValidationError";
|
|
359
|
-
}
|
|
360
|
-
};
|
|
361
|
-
async function validatedDefinitionAssets(definition, assets) {
|
|
362
|
-
if (!Array.isArray(assets)) {
|
|
363
|
-
throw new AgentDefinitionValidationError({
|
|
364
|
-
code: AgentDefinitionErrorCode.enum.AGENT_DEFINITION_INVALID,
|
|
365
|
-
field: "assets",
|
|
366
|
-
message: "assets must be an array"
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
const canonicalAssets = [];
|
|
370
|
-
for (const [index, input] of assets.entries()) {
|
|
371
|
-
const result = AgentDefinitionDigestAssetSchema.safeParse(input);
|
|
372
|
-
if (!result.success) {
|
|
373
|
-
const issue = mapZodIssues(
|
|
374
|
-
result.error.issues,
|
|
375
|
-
AgentDefinitionErrorCode.enum.AGENT_DEFINITION_INVALID,
|
|
376
|
-
AgentDefinitionErrorCode.enum.AGENT_DEFINITION_UNSUPPORTED_FIELD
|
|
377
|
-
)[0];
|
|
378
|
-
throw new AgentDefinitionValidationError({
|
|
379
|
-
...issue,
|
|
380
|
-
field: `assets[${index}].${issue.field}`
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
if (await createAgentAssetDigest(result.data.content) !== result.data.digest) {
|
|
384
|
-
throw new AgentDefinitionValidationError({
|
|
385
|
-
code: AgentDefinitionErrorCode.enum.AGENT_DEFINITION_INVALID,
|
|
386
|
-
field: "assets.digest",
|
|
387
|
-
message: `asset digest does not match UTF-8 content: ${result.data.path}`
|
|
388
|
-
});
|
|
389
|
-
}
|
|
390
|
-
canonicalAssets.push(result.data);
|
|
391
|
-
}
|
|
392
|
-
canonicalAssets.sort(
|
|
393
|
-
(left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0
|
|
394
|
-
);
|
|
395
|
-
for (let index = 1; index < canonicalAssets.length; index += 1) {
|
|
396
|
-
if (canonicalAssets[index - 1].path === canonicalAssets[index].path) {
|
|
397
|
-
throw new AgentDefinitionValidationError({
|
|
398
|
-
code: AgentDefinitionErrorCode.enum.AGENT_DEFINITION_INVALID,
|
|
399
|
-
field: "assets.path",
|
|
400
|
-
message: `duplicate asset path: ${canonicalAssets[index].path}`
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
if (!canonicalAssets.some((asset) => asset.path === definition.instructionsRef)) {
|
|
405
|
-
throw new AgentDefinitionValidationError({
|
|
406
|
-
code: AgentDefinitionErrorCode.enum.AGENT_DEFINITION_INVALID,
|
|
407
|
-
field: "instructionsRef",
|
|
408
|
-
message: "instructionsRef must name an included verified asset"
|
|
409
|
-
});
|
|
410
|
-
}
|
|
411
|
-
return canonicalAssets;
|
|
412
|
-
}
|
|
413
|
-
async function createAgentDefinitionDigest(input) {
|
|
414
|
-
const validated = validateAgentDefinition(input.definition);
|
|
415
|
-
if (!validated.valid) throw new AgentDefinitionValidationError(validated.issues[0]);
|
|
416
|
-
const assets = await validatedDefinitionAssets(validated.value, input.assets);
|
|
417
|
-
return sha256(canonicalStringify({ definition: validated.value, assets }));
|
|
418
|
-
}
|
|
419
|
-
async function createAgentDeploymentDigest(deployment) {
|
|
420
|
-
const validated = validateAgentDeployment(deployment);
|
|
421
|
-
if (!validated.valid) throw new AgentDeploymentValidationError(validated.issues[0]);
|
|
422
|
-
return sha256(canonicalStringify(validated.value));
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
// src/shared/validateTool.ts
|
|
426
|
-
function validateTool(tool) {
|
|
427
|
-
if (typeof tool !== "object" || tool === null) return null;
|
|
428
|
-
const t = tool;
|
|
429
|
-
if (typeof t.name !== "string" || t.name.length === 0) return null;
|
|
430
|
-
if (typeof t.description !== "string") return null;
|
|
431
|
-
if (typeof t.parameters !== "object" || t.parameters === null) return null;
|
|
432
|
-
if (typeof t.execute !== "function") return null;
|
|
433
|
-
return t;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
// src/shared/agent-consumption.ts
|
|
437
|
-
import { z as z4 } from "zod";
|
|
438
|
-
var nonEmptyString = z4.string().min(1);
|
|
439
|
-
function isOpaqueLocatorId(value) {
|
|
440
|
-
return value.trim() === value && !/[\0-\x1f\x7f]/.test(value) && !value.includes("/") && !value.includes("\\") && !value.includes(":") && value !== "." && value !== "..";
|
|
441
|
-
}
|
|
442
|
-
var OpaqueLocatorIdSchema = z4.string().min(1, "must be a non-empty opaque id").max(256, "must be at most 256 characters").refine(isOpaqueLocatorId, 'must be an opaque platform-owned id (no path separators, scheme, or "..")');
|
|
443
|
-
var TASK_STATES = [
|
|
444
|
-
"submitted",
|
|
445
|
-
"working",
|
|
446
|
-
"input-required",
|
|
447
|
-
"completed",
|
|
448
|
-
"failed",
|
|
449
|
-
"canceled",
|
|
450
|
-
"rejected"
|
|
451
|
-
];
|
|
452
|
-
var TaskStateSchema = z4.enum(TASK_STATES);
|
|
453
|
-
var TASK_TRANSITIONS = {
|
|
454
|
-
submitted: ["working", "rejected", "canceled"],
|
|
455
|
-
working: ["input-required", "completed", "failed", "canceled", "rejected"],
|
|
456
|
-
"input-required": ["working", "canceled"],
|
|
457
|
-
completed: [],
|
|
458
|
-
failed: [],
|
|
459
|
-
canceled: [],
|
|
460
|
-
rejected: []
|
|
461
|
-
};
|
|
462
|
-
function isValidTaskTransition(from, to) {
|
|
463
|
-
return TASK_TRANSITIONS[from].includes(to);
|
|
464
|
-
}
|
|
465
|
-
function assertValidTransition(from, to) {
|
|
466
|
-
if (!isValidTaskTransition(from, to)) {
|
|
467
|
-
throw new AgentConsumptionValidationError({
|
|
468
|
-
code: AgentConsumptionErrorCode.enum.AGENT_CONSUMPTION_INVALID_TRANSITION,
|
|
469
|
-
field: "state",
|
|
470
|
-
message: `invalid task state transition: '${from}' -> '${to}'`
|
|
471
|
-
});
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
var PrincipalRefSchema = z4.object({
|
|
475
|
-
userId: nonEmptyString,
|
|
476
|
-
workspaceId: nonEmptyString
|
|
477
|
-
}).strict();
|
|
478
|
-
var AgentRefSchema = z4.object({
|
|
479
|
-
agentId: nonEmptyString,
|
|
480
|
-
deploymentId: nonEmptyString.optional()
|
|
481
|
-
}).strict();
|
|
482
|
-
function agentRefEquals(a, b) {
|
|
483
|
-
return a.agentId === b.agentId && (a.deploymentId ?? null) === (b.deploymentId ?? null);
|
|
484
|
-
}
|
|
485
|
-
var ARTIFACT_LOCATOR_KINDS = ["workspace-file"];
|
|
486
|
-
var WorkspaceFileLocatorSchema = z4.object({
|
|
487
|
-
kind: z4.literal("workspace-file"),
|
|
488
|
-
workspaceId: OpaqueLocatorIdSchema,
|
|
489
|
-
fileId: OpaqueLocatorIdSchema,
|
|
490
|
-
digest: Sha256DigestSchema
|
|
491
|
-
}).strict();
|
|
492
|
-
var ArtifactLocatorSchema = z4.discriminatedUnion("kind", [WorkspaceFileLocatorSchema]);
|
|
493
|
-
var ArtifactRefSchema = z4.object({
|
|
494
|
-
artifactId: nonEmptyString,
|
|
495
|
-
name: z4.string().optional(),
|
|
496
|
-
mimeType: nonEmptyString,
|
|
497
|
-
locator: ArtifactLocatorSchema
|
|
498
|
-
}).strict();
|
|
499
|
-
var PartSchema = z4.discriminatedUnion("type", [
|
|
500
|
-
z4.object({ type: z4.literal("text"), text: z4.string() }).strict(),
|
|
501
|
-
z4.object({ type: z4.literal("file"), file: ArtifactRefSchema }).strict(),
|
|
502
|
-
z4.object({ type: z4.literal("data"), mimeType: nonEmptyString, data: z4.unknown() }).strict()
|
|
503
|
-
]);
|
|
504
|
-
var AgentMessageSchema = z4.object({
|
|
505
|
-
role: z4.enum(["consumer", "agent"]),
|
|
506
|
-
parts: z4.array(PartSchema),
|
|
507
|
-
ts: nonEmptyString
|
|
508
|
-
}).strict();
|
|
509
|
-
var AGENT_TASK_SCHEMA_VERSION = "2";
|
|
510
|
-
var AgentTaskSchema = z4.object({
|
|
511
|
-
id: nonEmptyString,
|
|
512
|
-
contextId: nonEmptyString,
|
|
513
|
-
state: TaskStateSchema,
|
|
514
|
-
messages: z4.array(AgentMessageSchema),
|
|
515
|
-
artifacts: z4.array(ArtifactRefSchema),
|
|
516
|
-
principal: PrincipalRefSchema,
|
|
517
|
-
actor: AgentRefSchema.optional(),
|
|
518
|
-
schemaVersion: z4.literal(AGENT_TASK_SCHEMA_VERSION),
|
|
519
|
-
createdAt: nonEmptyString,
|
|
520
|
-
updatedAt: nonEmptyString
|
|
521
|
-
}).strict();
|
|
522
|
-
function schemaMismatchIssues(issues) {
|
|
523
|
-
return issues.map((issue) => {
|
|
524
|
-
const field = formatPath(issue.path);
|
|
525
|
-
return {
|
|
526
|
-
code: AgentConsumptionErrorCode.enum.AGENT_CONSUMPTION_SCHEMA_MISMATCH,
|
|
527
|
-
field,
|
|
528
|
-
message: field === "<root>" ? issue.message : `${field} ${issue.message}`
|
|
529
|
-
};
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
|
-
function validateAgentTask(raw) {
|
|
533
|
-
const result = AgentTaskSchema.safeParse(raw);
|
|
534
|
-
if (!result.success) {
|
|
535
|
-
return { valid: false, issues: schemaMismatchIssues(result.error.issues) };
|
|
536
|
-
}
|
|
537
|
-
return { valid: true, value: result.data };
|
|
538
|
-
}
|
|
539
|
-
var AgentConsumptionValidationError = class extends SchemaValidationError {
|
|
540
|
-
constructor(issue) {
|
|
541
|
-
super(issue);
|
|
542
|
-
this.name = "AgentConsumptionValidationError";
|
|
543
|
-
}
|
|
544
|
-
};
|
|
545
|
-
var LegacyArtifactRefSchema = z4.object({
|
|
546
|
-
artifactId: nonEmptyString,
|
|
547
|
-
name: z4.string().optional(),
|
|
548
|
-
mimeType: nonEmptyString,
|
|
549
|
-
uri: nonEmptyString
|
|
550
|
-
}).strict();
|
|
551
|
-
var LegacyPartSchema = z4.discriminatedUnion("type", [
|
|
552
|
-
z4.object({ type: z4.literal("text"), text: z4.string() }).strict(),
|
|
553
|
-
z4.object({ type: z4.literal("file"), file: LegacyArtifactRefSchema }).strict(),
|
|
554
|
-
z4.object({ type: z4.literal("data"), mimeType: nonEmptyString, data: z4.unknown() }).strict()
|
|
555
|
-
]);
|
|
556
|
-
var LegacyAgentMessageSchema = z4.object({
|
|
557
|
-
role: z4.enum(["consumer", "agent"]),
|
|
558
|
-
parts: z4.array(LegacyPartSchema),
|
|
559
|
-
ts: nonEmptyString
|
|
560
|
-
}).strict();
|
|
561
|
-
var LegacyAgentTaskSchema = z4.object({
|
|
562
|
-
id: nonEmptyString,
|
|
563
|
-
contextId: nonEmptyString,
|
|
564
|
-
state: TaskStateSchema,
|
|
565
|
-
messages: z4.array(LegacyAgentMessageSchema),
|
|
566
|
-
artifacts: z4.array(LegacyArtifactRefSchema),
|
|
567
|
-
principal: PrincipalRefSchema,
|
|
568
|
-
actor: AgentRefSchema.optional(),
|
|
569
|
-
schemaVersion: z4.literal("1"),
|
|
570
|
-
createdAt: nonEmptyString,
|
|
571
|
-
updatedAt: nonEmptyString
|
|
572
|
-
}).strict();
|
|
573
|
-
function collectLegacyArtifactUris(raw) {
|
|
574
|
-
const uris = [];
|
|
575
|
-
for (const artifact of raw.artifacts) uris.push(artifact.uri);
|
|
576
|
-
for (const message of raw.messages) {
|
|
577
|
-
for (const part of message.parts) {
|
|
578
|
-
if (part.type === "file") uris.push(part.file.uri);
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
return uris;
|
|
582
|
-
}
|
|
583
|
-
function parseAgentTaskEdgeCompat(raw) {
|
|
584
|
-
const v2 = AgentTaskSchema.safeParse(raw);
|
|
585
|
-
if (v2.success) return { valid: true, value: v2.data };
|
|
586
|
-
const legacy = LegacyAgentTaskSchema.safeParse(raw);
|
|
587
|
-
if (legacy.success) {
|
|
588
|
-
const uris = collectLegacyArtifactUris(legacy.data);
|
|
589
|
-
const issues = uris.length > 0 ? uris.map((uri, index) => ({
|
|
590
|
-
code: AgentConsumptionErrorCode.enum.AGENT_CONSUMPTION_LEGACY_ARTIFACT_REJECTED,
|
|
591
|
-
field: `artifacts[${index}].uri`,
|
|
592
|
-
message: `schemaVersion '1' artifact uri '${uri}' has no typed ArtifactLocator translation and is refused before any storage/network effect`
|
|
593
|
-
})) : [
|
|
594
|
-
{
|
|
595
|
-
code: AgentConsumptionErrorCode.enum.AGENT_CONSUMPTION_LEGACY_ARTIFACT_REJECTED,
|
|
596
|
-
field: "schemaVersion",
|
|
597
|
-
message: "schemaVersion '1' is no longer accepted; publish schemaVersion '2' with a typed ArtifactLocator"
|
|
598
|
-
}
|
|
599
|
-
];
|
|
600
|
-
return { valid: false, issues };
|
|
601
|
-
}
|
|
602
|
-
return { valid: false, issues: schemaMismatchIssues(v2.error.issues) };
|
|
603
|
-
}
|
|
604
|
-
var ConsumptionGuardsSchema = z4.object({
|
|
605
|
-
maxDepth: z4.number().int().positive(),
|
|
606
|
-
inputRequiredTimeoutMs: z4.number().int().positive()
|
|
607
|
-
}).strict();
|
|
608
|
-
function validateConsumptionGuards(raw) {
|
|
609
|
-
const result = ConsumptionGuardsSchema.safeParse(raw);
|
|
610
|
-
if (!result.success) {
|
|
611
|
-
return { valid: false, issues: schemaMismatchIssues(result.error.issues) };
|
|
612
|
-
}
|
|
613
|
-
return { valid: true, value: result.data };
|
|
614
|
-
}
|
|
615
|
-
function detectConsumptionCycle(chain, next) {
|
|
616
|
-
return chain.some((ref) => agentRefEquals(ref, next));
|
|
617
|
-
}
|
|
618
|
-
function assertNoConsumptionCycle(chain, next) {
|
|
619
|
-
if (detectConsumptionCycle(chain, next)) {
|
|
620
|
-
const label = next.deploymentId ? `${next.agentId}@${next.deploymentId}` : next.agentId;
|
|
621
|
-
throw new AgentConsumptionValidationError({
|
|
622
|
-
code: AgentConsumptionErrorCode.enum.AGENT_CONSUMPTION_CYCLE_DETECTED,
|
|
623
|
-
field: "actor",
|
|
624
|
-
message: `consumption cycle detected: agent '${label}' already present in the delegation chain`
|
|
625
|
-
});
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
function isWithinConsumptionDepth(chain, guards) {
|
|
629
|
-
return chain.length < guards.maxDepth;
|
|
630
|
-
}
|
|
631
|
-
function assertWithinConsumptionDepth(chain, guards) {
|
|
632
|
-
if (!isWithinConsumptionDepth(chain, guards)) {
|
|
633
|
-
throw new AgentConsumptionValidationError({
|
|
634
|
-
code: AgentConsumptionErrorCode.enum.AGENT_CONSUMPTION_DEPTH_EXCEEDED,
|
|
635
|
-
field: "depth",
|
|
636
|
-
message: `consumption depth exceeded: chain length ${chain.length} >= max depth ${guards.maxDepth}`
|
|
637
|
-
});
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
// src/shared/share-entry.ts
|
|
642
|
-
import { z as z5 } from "zod";
|
|
643
|
-
var nonEmptyString2 = z5.string().min(1);
|
|
644
|
-
function isOpaqueLocatorId2(value) {
|
|
645
|
-
return value.trim() === value && !/[\0-\x1f\x7f]/.test(value) && !value.includes("/") && !value.includes("\\") && !value.includes(":") && value !== "." && value !== "..";
|
|
646
|
-
}
|
|
647
|
-
var OpaqueShareLocatorIdSchema = z5.string().min(1, "must be a non-empty opaque id").max(256, "must be at most 256 characters").refine(isOpaqueLocatorId2, "must be an opaque platform-owned id (no path separators, no scheme, no traversal)");
|
|
648
|
-
function mintShareEntryId() {
|
|
649
|
-
return safeRandomUUID();
|
|
650
|
-
}
|
|
651
|
-
var ShareEntryProvenanceSchema = z5.object({
|
|
652
|
-
producerPrincipalRef: nonEmptyString2,
|
|
653
|
-
createdAt: nonEmptyString2
|
|
654
|
-
}).strict();
|
|
655
|
-
var ShareEntryV1Schema = z5.object({
|
|
656
|
-
schemaVersion: z5.literal(1),
|
|
657
|
-
id: OpaqueShareLocatorIdSchema,
|
|
658
|
-
workspaceId: OpaqueShareLocatorIdSchema,
|
|
659
|
-
path: nonEmptyString2,
|
|
660
|
-
provenance: ShareEntryProvenanceSchema
|
|
661
|
-
}).strict();
|
|
662
|
-
var ShareEntryErrorCode = z5.enum(["AR1_SHARE_NOT_FOUND", "AR1_SHARE_TOMBSTONED"]);
|
|
663
|
-
var ShareEntryValidationCode = z5.enum(["SHARE_ENTRY_INPUT_INVALID"]);
|
|
664
|
-
var ShareEntryValidationError = class extends Error {
|
|
665
|
-
code = ErrorCode.enum.CONFIG_INVALID;
|
|
666
|
-
field;
|
|
667
|
-
constructor(issue) {
|
|
668
|
-
super(issue.message);
|
|
669
|
-
this.name = "ShareEntryValidationError";
|
|
670
|
-
this.field = issue.field;
|
|
671
|
-
}
|
|
672
|
-
};
|
|
673
|
-
function assertValidCreateInput(raw) {
|
|
674
|
-
const result = CreateShareEntryInputSchema.safeParse(raw);
|
|
675
|
-
if (result.success) return;
|
|
676
|
-
const issue = result.error.issues[0];
|
|
677
|
-
const field = formatPath(issue.path);
|
|
678
|
-
throw new ShareEntryValidationError({
|
|
679
|
-
code: ShareEntryValidationCode.enum.SHARE_ENTRY_INPUT_INVALID,
|
|
680
|
-
field,
|
|
681
|
-
message: field === "<root>" ? issue.message : `${field} ${issue.message}`
|
|
682
|
-
});
|
|
683
|
-
}
|
|
684
|
-
var CreateShareEntryInputSchema = z5.object({
|
|
685
|
-
workspaceId: OpaqueShareLocatorIdSchema,
|
|
686
|
-
path: nonEmptyString2,
|
|
687
|
-
provenance: z5.object({
|
|
688
|
-
producerPrincipalRef: nonEmptyString2,
|
|
689
|
-
createdAt: nonEmptyString2.optional()
|
|
690
|
-
}).strict()
|
|
691
|
-
}).strict();
|
|
692
|
-
var InMemoryShareEntryStore = class {
|
|
693
|
-
entries = /* @__PURE__ */ new Map();
|
|
694
|
-
async create(input) {
|
|
695
|
-
assertValidCreateInput(input);
|
|
696
|
-
const entry = {
|
|
697
|
-
schemaVersion: 1,
|
|
698
|
-
id: mintShareEntryId(),
|
|
699
|
-
workspaceId: input.workspaceId,
|
|
700
|
-
path: input.path,
|
|
701
|
-
provenance: {
|
|
702
|
-
producerPrincipalRef: input.provenance.producerPrincipalRef,
|
|
703
|
-
createdAt: input.provenance.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
704
|
-
}
|
|
705
|
-
};
|
|
706
|
-
this.entries.set(entry.id, entry);
|
|
707
|
-
return entry;
|
|
708
|
-
}
|
|
709
|
-
async get(id) {
|
|
710
|
-
return this.entries.get(id) ?? null;
|
|
711
|
-
}
|
|
712
|
-
async delete(id) {
|
|
713
|
-
this.entries.delete(id);
|
|
714
|
-
}
|
|
715
|
-
async list(workspaceId) {
|
|
716
|
-
return Array.from(this.entries.values()).filter((entry) => entry.workspaceId === workspaceId);
|
|
717
|
-
}
|
|
718
|
-
};
|
|
719
|
-
async function resolveShareEntry(store, id, workspace) {
|
|
720
|
-
const entry = await store.get(id);
|
|
721
|
-
if (!entry) {
|
|
722
|
-
return { status: "not_found", code: ShareEntryErrorCode.enum.AR1_SHARE_NOT_FOUND };
|
|
723
|
-
}
|
|
724
|
-
try {
|
|
725
|
-
await workspace.stat(entry.path);
|
|
726
|
-
} catch {
|
|
727
|
-
return {
|
|
728
|
-
status: "tombstoned",
|
|
729
|
-
code: ShareEntryErrorCode.enum.AR1_SHARE_TOMBSTONED,
|
|
730
|
-
tombstone: {
|
|
731
|
-
id: entry.id,
|
|
732
|
-
workspaceId: entry.workspaceId,
|
|
733
|
-
provenance: entry.provenance
|
|
734
|
-
}
|
|
735
|
-
};
|
|
736
|
-
}
|
|
737
|
-
return { status: "ok", entry };
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
// src/shared/credentials/errors.ts
|
|
741
|
-
var CREDENTIAL_ERROR_CODES = {
|
|
742
|
-
PROVIDER_UNKNOWN: "CREDENTIAL_PROVIDER_UNKNOWN",
|
|
743
|
-
NOT_CONFIGURED: "CREDENTIAL_NOT_CONFIGURED",
|
|
744
|
-
DISABLED: "CREDENTIAL_DISABLED",
|
|
745
|
-
REVOKED: "CREDENTIAL_REVOKED",
|
|
746
|
-
FORBIDDEN: "CREDENTIAL_FORBIDDEN",
|
|
747
|
-
WORKSPACE_MISMATCH: "CREDENTIAL_WORKSPACE_MISMATCH",
|
|
748
|
-
CONSUMER_MISMATCH: "CREDENTIAL_CONSUMER_MISMATCH",
|
|
749
|
-
DELIVERY_FORBIDDEN: "CREDENTIAL_DELIVERY_FORBIDDEN",
|
|
750
|
-
AUTHORITY_INVALID: "CREDENTIAL_AUTHORITY_INVALID",
|
|
751
|
-
SCHEMA_MISMATCH: "CREDENTIAL_SCHEMA_MISMATCH",
|
|
752
|
-
UNREADABLE: "CREDENTIAL_UNREADABLE",
|
|
753
|
-
BACKEND_UNAVAILABLE: "CREDENTIAL_BACKEND_UNAVAILABLE",
|
|
754
|
-
KEK_UNAVAILABLE: "CREDENTIAL_KEK_UNAVAILABLE",
|
|
755
|
-
LEASE_EXPIRED: "CREDENTIAL_LEASE_EXPIRED",
|
|
756
|
-
OAUTH_STATE_INVALID: "CREDENTIAL_OAUTH_STATE_INVALID",
|
|
757
|
-
OAUTH_REFRESH_FAILED: "CREDENTIAL_OAUTH_REFRESH_FAILED",
|
|
758
|
-
VALIDATION_UNAUTHORIZED: "CREDENTIAL_VALIDATION_UNAUTHORIZED",
|
|
759
|
-
VALIDATION_RATE_LIMITED: "CREDENTIAL_VALIDATION_RATE_LIMITED",
|
|
760
|
-
VALIDATION_UNAVAILABLE: "CREDENTIAL_VALIDATION_UNAVAILABLE",
|
|
761
|
-
VALIDATION_TIMEOUT: "CREDENTIAL_VALIDATION_TIMEOUT",
|
|
762
|
-
VALIDATION_UNSUPPORTED: "CREDENTIAL_VALIDATION_UNSUPPORTED"
|
|
763
|
-
};
|
|
764
|
-
var CredentialResolutionError = class extends Error {
|
|
765
|
-
code;
|
|
766
|
-
retryable;
|
|
767
|
-
constructor(code, message, options = {}) {
|
|
768
|
-
super(message);
|
|
769
|
-
this.name = "CredentialResolutionError";
|
|
770
|
-
this.code = code;
|
|
771
|
-
this.retryable = options.retryable ?? false;
|
|
772
|
-
}
|
|
773
|
-
};
|
|
774
|
-
|
|
775
|
-
// src/shared/credentials/custody.ts
|
|
776
|
-
function workspaceCredentialCustodyScopeV1(workspaceId) {
|
|
777
|
-
return assertCredentialCustodyScopeV1({ workspaceId, subject: { kind: "workspace" } });
|
|
778
|
-
}
|
|
779
|
-
function userCredentialCustodyScopeV1(workspaceId, userId) {
|
|
780
|
-
return assertCredentialCustodyScopeV1({ workspaceId, subject: { kind: "user", userId } });
|
|
781
|
-
}
|
|
782
|
-
function assertCredentialCustodyScopeV1(scope) {
|
|
783
|
-
if (!scope || typeof scope.workspaceId !== "string" || scope.workspaceId.length === 0 || !scope.subject || scope.subject.kind !== "workspace" && scope.subject.kind !== "user" || scope.subject.kind === "user" && (typeof scope.subject.userId !== "string" || scope.subject.userId.length === 0)) {
|
|
784
|
-
throw new CredentialResolutionError(CREDENTIAL_ERROR_CODES.SCHEMA_MISMATCH, "Invalid credential custody scope");
|
|
785
|
-
}
|
|
786
|
-
return Object.freeze({
|
|
787
|
-
workspaceId: scope.workspaceId,
|
|
788
|
-
subject: scope.subject.kind === "workspace" ? Object.freeze({ kind: "workspace" }) : Object.freeze({ kind: "user", userId: scope.subject.userId })
|
|
789
|
-
});
|
|
790
|
-
}
|
|
791
|
-
function credentialCustodySubjectKeyV1(subject) {
|
|
792
|
-
return subject.kind === "workspace" ? "workspace" : encodeURIComponent(subject.userId);
|
|
793
|
-
}
|
|
794
|
-
|
|
795
|
-
// src/shared/credentials/bindings.ts
|
|
796
|
-
var CREDENTIAL_ID_PATTERN = /^[a-z0-9][a-z0-9._-]{0,63}$/;
|
|
797
|
-
var MAX_BINDING_TEXT_LENGTH_V1 = 256;
|
|
798
|
-
function deepFreeze(value) {
|
|
799
|
-
if (value !== null && typeof value === "object" && !Object.isFrozen(value)) {
|
|
800
|
-
for (const child of Object.values(value)) {
|
|
801
|
-
deepFreeze(child);
|
|
802
|
-
}
|
|
803
|
-
Object.freeze(value);
|
|
804
|
-
}
|
|
805
|
-
return value;
|
|
806
|
-
}
|
|
807
|
-
function schemaMismatch(message) {
|
|
808
|
-
throw new CredentialResolutionError(
|
|
809
|
-
CREDENTIAL_ERROR_CODES.SCHEMA_MISMATCH,
|
|
810
|
-
message
|
|
811
|
-
);
|
|
812
|
-
}
|
|
813
|
-
function validateCredentialId(value, kind) {
|
|
814
|
-
if (typeof value !== "string" || !CREDENTIAL_ID_PATTERN.test(value)) {
|
|
815
|
-
schemaMismatch(`Invalid ${kind}`);
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
function validateBindingText(value, kind) {
|
|
819
|
-
if (typeof value !== "string" || value.length === 0 || value.length > MAX_BINDING_TEXT_LENGTH_V1 || /[\u0000-\u001f\u007f]/.test(value)) {
|
|
820
|
-
schemaMismatch(`Invalid ${kind}`);
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
function validateHttpsOrigin(value) {
|
|
824
|
-
if (typeof value !== "string") schemaMismatch("Invalid sandbox egress origin");
|
|
825
|
-
try {
|
|
826
|
-
const parsed = new URL(value);
|
|
827
|
-
if (parsed.protocol !== "https:" || parsed.username !== "" || parsed.password !== "" || parsed.origin !== value) {
|
|
828
|
-
schemaMismatch("Invalid sandbox egress origin");
|
|
829
|
-
}
|
|
830
|
-
} catch (error) {
|
|
831
|
-
if (error instanceof CredentialResolutionError) throw error;
|
|
832
|
-
schemaMismatch("Invalid sandbox egress origin");
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
function providerCredentialFieldsV1(provider) {
|
|
836
|
-
if (provider.credential.type === "api-key") return provider.credential.fields;
|
|
837
|
-
if (provider.credential.type === "oauth2-authorization-code" && provider.credential.tokenCustody === "local-vault") {
|
|
838
|
-
return [
|
|
839
|
-
provider.credential.refreshTokenField,
|
|
840
|
-
provider.credential.resolvedAccessTokenField
|
|
841
|
-
];
|
|
842
|
-
}
|
|
843
|
-
return [];
|
|
844
|
-
}
|
|
845
|
-
function validateBinding(binding, providerRegistry) {
|
|
846
|
-
if (!binding || typeof binding !== "object") {
|
|
847
|
-
schemaMismatch("Invalid consumer binding");
|
|
848
|
-
}
|
|
849
|
-
if (binding.contractVersion !== "boring.credential-consumer-binding.v1") {
|
|
850
|
-
schemaMismatch("Invalid consumer binding contract version");
|
|
851
|
-
}
|
|
852
|
-
validateCredentialId(binding.id, "consumer binding id");
|
|
853
|
-
validateCredentialId(binding.providerId, "provider id");
|
|
854
|
-
if (!binding.consumer || typeof binding.consumer !== "object") {
|
|
855
|
-
schemaMismatch("Missing consumer binding identity");
|
|
856
|
-
}
|
|
857
|
-
validateBindingText(binding.consumer.id, "consumer id");
|
|
858
|
-
if (!["model-provider", "first-party-tool", "plugin-server", "mcp-server", "tenant-custom-tool"].includes(binding.consumer.kind)) {
|
|
859
|
-
schemaMismatch("Invalid consumer kind");
|
|
860
|
-
}
|
|
861
|
-
if (binding.consumer.trust !== "trusted" && binding.consumer.trust !== "untrusted") {
|
|
862
|
-
schemaMismatch("Invalid consumer trust");
|
|
863
|
-
}
|
|
864
|
-
validateBindingText(binding.purpose, "consumer purpose");
|
|
865
|
-
if (!Array.isArray(binding.allowedFieldIds)) schemaMismatch("Invalid allowed field ids");
|
|
866
|
-
if (!["host-only", "sandbox-pipe", "sandbox-tmpfs"].includes(binding.delivery)) {
|
|
867
|
-
schemaMismatch("Invalid credential delivery mode");
|
|
868
|
-
}
|
|
869
|
-
const provider = providerRegistry.list().find(
|
|
870
|
-
(candidate) => candidate.id === binding.providerId
|
|
871
|
-
);
|
|
872
|
-
if (!provider) schemaMismatch("Consumer binding references an unknown provider");
|
|
873
|
-
if (!provider.consumerBindingIds.includes(binding.id)) {
|
|
874
|
-
schemaMismatch("Provider does not declare consumer binding");
|
|
875
|
-
}
|
|
876
|
-
const availableFieldIds = new Set(
|
|
877
|
-
providerCredentialFieldsV1(provider).map((field) => field.id)
|
|
878
|
-
);
|
|
879
|
-
const allowedFieldIds = /* @__PURE__ */ new Set();
|
|
880
|
-
for (const fieldId of binding.allowedFieldIds) {
|
|
881
|
-
validateCredentialId(fieldId, "allowed credential field id");
|
|
882
|
-
if (allowedFieldIds.has(fieldId)) schemaMismatch("Duplicate allowed credential field id");
|
|
883
|
-
if (!availableFieldIds.has(fieldId)) schemaMismatch("Consumer binding requests an unknown field");
|
|
884
|
-
allowedFieldIds.add(fieldId);
|
|
885
|
-
}
|
|
886
|
-
if (provider.credential.type === "oauth2-authorization-code" && provider.credential.tokenCustody === "local-vault" && allowedFieldIds.has(provider.credential.refreshTokenField.id)) {
|
|
887
|
-
schemaMismatch("Consumer binding cannot request an OAuth refresh field");
|
|
888
|
-
}
|
|
889
|
-
if (binding.consumer.trust === "trusted") {
|
|
890
|
-
if (binding.delivery !== "host-only" || binding.sandbox !== void 0) {
|
|
891
|
-
schemaMismatch("Trusted consumers require host-only delivery");
|
|
892
|
-
}
|
|
893
|
-
} else {
|
|
894
|
-
if (binding.delivery === "host-only" || !binding.sandbox) {
|
|
895
|
-
schemaMismatch("Untrusted consumers require sandbox delivery");
|
|
896
|
-
}
|
|
897
|
-
if (binding.delivery === "sandbox-pipe" && binding.sandbox.credentialChannel !== "fd-3" || binding.delivery === "sandbox-tmpfs" && binding.sandbox.credentialChannel !== "tmpfs-v1") {
|
|
898
|
-
schemaMismatch("Sandbox delivery channel does not match delivery mode");
|
|
899
|
-
}
|
|
900
|
-
if (!Array.isArray(binding.sandbox.egressOrigins)) {
|
|
901
|
-
schemaMismatch("Missing sandbox egress origins");
|
|
902
|
-
}
|
|
903
|
-
const providerOrigins = new Set(provider.sandboxEgressOrigins);
|
|
904
|
-
const seenOrigins = /* @__PURE__ */ new Set();
|
|
905
|
-
for (const origin of binding.sandbox.egressOrigins) {
|
|
906
|
-
validateHttpsOrigin(origin);
|
|
907
|
-
if (seenOrigins.has(origin)) schemaMismatch("Duplicate sandbox egress origin");
|
|
908
|
-
if (!providerOrigins.has(origin)) schemaMismatch("Sandbox egress origin is not provider-approved");
|
|
909
|
-
seenOrigins.add(origin);
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
if (provider.credential.type === "oauth2-authorization-code" && provider.credential.tokenCustody === "external-managed" && (binding.allowedFieldIds.length !== 0 || binding.consumer.trust !== "trusted" || binding.delivery !== "host-only" || binding.sandbox !== void 0)) {
|
|
913
|
-
schemaMismatch("External-managed credentials require an empty host-only binding");
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
function createCredentialConsumerBindingRegistryV1(bindings, providerRegistry) {
|
|
917
|
-
const byId = /* @__PURE__ */ new Map();
|
|
918
|
-
for (const binding of bindings) {
|
|
919
|
-
validateBinding(binding, providerRegistry);
|
|
920
|
-
if (byId.has(binding.id)) schemaMismatch("Duplicate consumer binding id");
|
|
921
|
-
const immutableBinding = deepFreeze(binding);
|
|
922
|
-
byId.set(immutableBinding.id, immutableBinding);
|
|
923
|
-
}
|
|
924
|
-
return Object.freeze({
|
|
925
|
-
contractVersion: "boring.credential-consumer-bindings.v1",
|
|
926
|
-
require(bindingId) {
|
|
927
|
-
validateCredentialId(bindingId, "consumer binding id");
|
|
928
|
-
const binding = byId.get(bindingId);
|
|
929
|
-
if (!binding) {
|
|
930
|
-
throw new CredentialResolutionError(
|
|
931
|
-
CREDENTIAL_ERROR_CODES.CONSUMER_MISMATCH,
|
|
932
|
-
"Credential consumer binding is not registered"
|
|
933
|
-
);
|
|
934
|
-
}
|
|
935
|
-
return binding;
|
|
936
|
-
}
|
|
937
|
-
});
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
// src/shared/credentials/kmsBackend.ts
|
|
941
|
-
var WORKSPACE_KEK_PROVIDER_VERSION = "boring.workspace-kek-provider.v1";
|
|
942
|
-
var CREDENTIAL_ENVELOPE_VERSION = "boring.credential-envelope.v1";
|
|
943
|
-
var CREDENTIAL_AAD_ENCODING_VERSION = "boring.credential-aad.v1";
|
|
944
|
-
var CREDENTIAL_DEK_BYTE_LENGTH_V1 = 32;
|
|
945
|
-
var CREDENTIAL_KEK_BYTE_LENGTH_V1 = 32;
|
|
946
|
-
var CREDENTIAL_NONCE_BYTE_LENGTH_V1 = 12;
|
|
947
|
-
var CREDENTIAL_AUTH_TAG_BYTE_LENGTH_V1 = 16;
|
|
948
|
-
|
|
949
|
-
// src/shared/credentials/ref.ts
|
|
950
|
-
var PROVIDER_CREDENTIAL_REF_VERSION = "boring.provider-credential-ref.v1";
|
|
951
|
-
var MAX_EXECUTION_ID_LENGTH_V1 = 256;
|
|
952
|
-
function createProviderCredentialRefFactoryV1(bindingRegistry) {
|
|
953
|
-
return Object.freeze({
|
|
954
|
-
contractVersion: "boring.provider-credential-ref-factory.v1",
|
|
955
|
-
create(input) {
|
|
956
|
-
const binding = bindingRegistry.require(input.bindingId);
|
|
957
|
-
if (binding.providerId !== input.providerId) {
|
|
958
|
-
throw new CredentialResolutionError(
|
|
959
|
-
CREDENTIAL_ERROR_CODES.CONSUMER_MISMATCH,
|
|
960
|
-
"Credential reference does not match its registered consumer binding"
|
|
961
|
-
);
|
|
962
|
-
}
|
|
963
|
-
if (typeof input.executionId !== "string" || input.executionId.trim().length === 0 || input.executionId.length > MAX_EXECUTION_ID_LENGTH_V1) {
|
|
964
|
-
throw new CredentialResolutionError(
|
|
965
|
-
CREDENTIAL_ERROR_CODES.SCHEMA_MISMATCH,
|
|
966
|
-
"Invalid credential execution id"
|
|
967
|
-
);
|
|
968
|
-
}
|
|
969
|
-
return Object.freeze({
|
|
970
|
-
contractVersion: PROVIDER_CREDENTIAL_REF_VERSION,
|
|
971
|
-
providerId: binding.providerId,
|
|
972
|
-
executionId: input.executionId,
|
|
973
|
-
bindingId: binding.id
|
|
974
|
-
});
|
|
975
|
-
}
|
|
976
|
-
});
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
// src/shared/credentials/registry.ts
|
|
980
|
-
var CREDENTIAL_ID_PATTERN2 = /^[a-z0-9][a-z0-9._-]{0,63}$/;
|
|
981
|
-
var MAX_CREDENTIAL_FIELD_BYTES_V1 = 65536;
|
|
982
|
-
var MAX_ACCOUNT_REFERENCE_BYTES_V1 = 16384;
|
|
983
|
-
var MAX_LABEL_LENGTH_V1 = 256;
|
|
984
|
-
var MAX_SCOPE_LENGTH_V1 = 256;
|
|
985
|
-
function deepFreeze2(value) {
|
|
986
|
-
if (value !== null && typeof value === "object" && !Object.isFrozen(value)) {
|
|
987
|
-
for (const child of Object.values(value)) {
|
|
988
|
-
deepFreeze2(child);
|
|
989
|
-
}
|
|
990
|
-
Object.freeze(value);
|
|
991
|
-
}
|
|
992
|
-
return value;
|
|
993
|
-
}
|
|
994
|
-
function schemaMismatch2(message) {
|
|
995
|
-
throw new CredentialResolutionError(
|
|
996
|
-
CREDENTIAL_ERROR_CODES.SCHEMA_MISMATCH,
|
|
997
|
-
message
|
|
998
|
-
);
|
|
999
|
-
}
|
|
1000
|
-
function isCredentialId(value) {
|
|
1001
|
-
return typeof value === "string" && CREDENTIAL_ID_PATTERN2.test(value);
|
|
1002
|
-
}
|
|
1003
|
-
function validateCredentialId2(value, kind) {
|
|
1004
|
-
if (!isCredentialId(value)) schemaMismatch2(`Invalid ${kind}`);
|
|
1005
|
-
}
|
|
1006
|
-
function validateBoundedText(value, kind) {
|
|
1007
|
-
if (typeof value !== "string" || value.length === 0 || value.length > MAX_LABEL_LENGTH_V1 || /[\u0000-\u001f\u007f]/.test(value)) {
|
|
1008
|
-
schemaMismatch2(`Invalid ${kind}`);
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
function validateBoundedBytes(value, maximum, kind) {
|
|
1012
|
-
if (!Number.isSafeInteger(value) || value <= 0 || value > maximum) {
|
|
1013
|
-
schemaMismatch2(`Invalid ${kind}`);
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
function validateHttpsEndpoint(value, kind) {
|
|
1017
|
-
if (typeof value !== "string") schemaMismatch2(`Invalid ${kind}`);
|
|
1018
|
-
try {
|
|
1019
|
-
const parsed = new URL(value);
|
|
1020
|
-
if (parsed.protocol !== "https:" || parsed.username !== "" || parsed.password !== "" || parsed.hash !== "") {
|
|
1021
|
-
schemaMismatch2(`Invalid ${kind}`);
|
|
1022
|
-
}
|
|
1023
|
-
} catch (error) {
|
|
1024
|
-
if (error instanceof CredentialResolutionError) throw error;
|
|
1025
|
-
schemaMismatch2(`Invalid ${kind}`);
|
|
1026
|
-
}
|
|
1027
|
-
}
|
|
1028
|
-
function validateHttpsOrigin2(value, kind) {
|
|
1029
|
-
validateHttpsEndpoint(value, kind);
|
|
1030
|
-
const parsed = new URL(value);
|
|
1031
|
-
if (parsed.origin !== value) schemaMismatch2(`Invalid ${kind}`);
|
|
1032
|
-
}
|
|
1033
|
-
function validateUniqueStrings(values, validate, kind) {
|
|
1034
|
-
if (!Array.isArray(values)) schemaMismatch2(`Invalid ${kind}`);
|
|
1035
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1036
|
-
for (const value of values) {
|
|
1037
|
-
validate(value);
|
|
1038
|
-
if (seen.has(value)) schemaMismatch2(`Duplicate ${kind}`);
|
|
1039
|
-
seen.add(value);
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
function validateScopes(scopes) {
|
|
1043
|
-
validateUniqueStrings(
|
|
1044
|
-
scopes,
|
|
1045
|
-
(scope) => {
|
|
1046
|
-
if (typeof scope !== "string" || scope.length === 0 || scope.length > MAX_SCOPE_LENGTH_V1 || !/^[\x21-\x7e]+$/.test(scope)) {
|
|
1047
|
-
schemaMismatch2("Invalid OAuth scope");
|
|
1048
|
-
}
|
|
1049
|
-
},
|
|
1050
|
-
"OAuth scope"
|
|
1051
|
-
);
|
|
1052
|
-
}
|
|
1053
|
-
function validateCredentialField(field) {
|
|
1054
|
-
if (!field || typeof field !== "object") schemaMismatch2("Missing credential field");
|
|
1055
|
-
validateCredentialId2(field.id, "credential field id");
|
|
1056
|
-
validateBoundedText(field.label, "credential field label");
|
|
1057
|
-
if (typeof field.required !== "boolean") schemaMismatch2("Invalid credential field required flag");
|
|
1058
|
-
if (field.sensitivity !== "secret" && field.sensitivity !== "public") {
|
|
1059
|
-
schemaMismatch2("Invalid credential field sensitivity");
|
|
1060
|
-
}
|
|
1061
|
-
validateBoundedBytes(field.maxBytes, MAX_CREDENTIAL_FIELD_BYTES_V1, "credential field maxBytes");
|
|
1062
|
-
if (field.minBytes !== void 0 && (!Number.isSafeInteger(field.minBytes) || field.minBytes < 0 || field.minBytes > field.maxBytes)) {
|
|
1063
|
-
schemaMismatch2("Invalid credential field minBytes");
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
function validateDistinctCredentialFields(fields) {
|
|
1067
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1068
|
-
for (const field of fields) {
|
|
1069
|
-
validateCredentialField(field);
|
|
1070
|
-
if (seen.has(field.id)) schemaMismatch2("Duplicate credential field id");
|
|
1071
|
-
seen.add(field.id);
|
|
1072
|
-
}
|
|
1073
|
-
}
|
|
1074
|
-
function validateLocalVaultOAuth(credential) {
|
|
1075
|
-
validateBoundedText(credential.clientRegistrationRef, "OAuth client registration reference");
|
|
1076
|
-
validateHttpsEndpoint(credential.authorizationEndpoint, "OAuth authorization endpoint");
|
|
1077
|
-
validateHttpsEndpoint(credential.tokenEndpoint, "OAuth token endpoint");
|
|
1078
|
-
if (credential.revocationEndpoint !== void 0) {
|
|
1079
|
-
validateHttpsEndpoint(credential.revocationEndpoint, "OAuth revocation endpoint");
|
|
1080
|
-
}
|
|
1081
|
-
validateScopes(credential.scopes);
|
|
1082
|
-
if (credential.usePkce !== true || credential.accessTokenPersistence !== "memory-only") {
|
|
1083
|
-
schemaMismatch2("Invalid local-vault OAuth policy");
|
|
1084
|
-
}
|
|
1085
|
-
validateCredentialField(credential.refreshTokenField);
|
|
1086
|
-
validateCredentialField(credential.resolvedAccessTokenField);
|
|
1087
|
-
if (credential.refreshTokenField.id === credential.resolvedAccessTokenField.id || credential.refreshTokenField.required !== true || credential.resolvedAccessTokenField.required !== true || credential.refreshTokenField.sensitivity !== "secret" || credential.resolvedAccessTokenField.sensitivity !== "secret") {
|
|
1088
|
-
schemaMismatch2("Invalid local-vault OAuth token fields");
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
function validateExternalManagedOAuth(credential) {
|
|
1092
|
-
const allowedProperties = /* @__PURE__ */ new Set([
|
|
1093
|
-
"type",
|
|
1094
|
-
"tokenCustody",
|
|
1095
|
-
"custodianAdapterId",
|
|
1096
|
-
"connectUrlOrigins",
|
|
1097
|
-
"scopes",
|
|
1098
|
-
"accountReference",
|
|
1099
|
-
"delivery"
|
|
1100
|
-
]);
|
|
1101
|
-
if (Object.keys(credential).some((key) => !allowedProperties.has(key))) {
|
|
1102
|
-
schemaMismatch2("External-managed OAuth cannot declare token or secret fields");
|
|
1103
|
-
}
|
|
1104
|
-
validateBoundedText(credential.custodianAdapterId, "custodian adapter id");
|
|
1105
|
-
validateUniqueStrings(
|
|
1106
|
-
credential.connectUrlOrigins,
|
|
1107
|
-
(origin) => validateHttpsOrigin2(origin, "connect URL origin"),
|
|
1108
|
-
"connect URL origin"
|
|
1109
|
-
);
|
|
1110
|
-
validateScopes(credential.scopes);
|
|
1111
|
-
if (!credential.accountReference || typeof credential.accountReference !== "object") {
|
|
1112
|
-
schemaMismatch2("Missing external-managed account reference");
|
|
1113
|
-
}
|
|
1114
|
-
const allowedAccountReferenceProperties = /* @__PURE__ */ new Set([
|
|
1115
|
-
"label",
|
|
1116
|
-
"maxBytes",
|
|
1117
|
-
"persistence"
|
|
1118
|
-
]);
|
|
1119
|
-
if (Object.keys(credential.accountReference).some(
|
|
1120
|
-
(key) => !allowedAccountReferenceProperties.has(key)
|
|
1121
|
-
)) {
|
|
1122
|
-
schemaMismatch2("External-managed account reference contains unsupported fields");
|
|
1123
|
-
}
|
|
1124
|
-
validateBoundedText(credential.accountReference.label, "account reference label");
|
|
1125
|
-
validateBoundedBytes(
|
|
1126
|
-
credential.accountReference.maxBytes,
|
|
1127
|
-
MAX_ACCOUNT_REFERENCE_BYTES_V1,
|
|
1128
|
-
"account reference maxBytes"
|
|
1129
|
-
);
|
|
1130
|
-
if (credential.accountReference.persistence !== "server-only-metadata" || credential.delivery !== "host-session-adapter-only") {
|
|
1131
|
-
schemaMismatch2("Invalid external-managed OAuth custody policy");
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
function validateProviderDefinition(definition) {
|
|
1135
|
-
if (!definition || typeof definition !== "object") {
|
|
1136
|
-
schemaMismatch2("Invalid provider definition");
|
|
1137
|
-
}
|
|
1138
|
-
if (definition.contractVersion !== "boring.provider.v1") {
|
|
1139
|
-
schemaMismatch2("Invalid provider contract version");
|
|
1140
|
-
}
|
|
1141
|
-
validateCredentialId2(definition.id, "provider id");
|
|
1142
|
-
validateBoundedText(definition.displayName, "provider display name");
|
|
1143
|
-
if (!["llm", "search", "transcription", "mcp", "other"].includes(definition.category)) {
|
|
1144
|
-
schemaMismatch2("Invalid provider category");
|
|
1145
|
-
}
|
|
1146
|
-
validateUniqueStrings(
|
|
1147
|
-
definition.consumerBindingIds,
|
|
1148
|
-
(id) => validateCredentialId2(id, "consumer binding id"),
|
|
1149
|
-
"consumer binding id"
|
|
1150
|
-
);
|
|
1151
|
-
validateUniqueStrings(
|
|
1152
|
-
definition.sandboxEgressOrigins,
|
|
1153
|
-
(origin) => validateHttpsOrigin2(origin, "sandbox egress origin"),
|
|
1154
|
-
"sandbox egress origin"
|
|
1155
|
-
);
|
|
1156
|
-
if (!definition.credential || typeof definition.credential !== "object") {
|
|
1157
|
-
schemaMismatch2("Missing provider credential definition");
|
|
1158
|
-
}
|
|
1159
|
-
const credential = definition.credential;
|
|
1160
|
-
if (credential.type === "api-key") {
|
|
1161
|
-
if (!Array.isArray(credential.fields) || credential.fields.length === 0) {
|
|
1162
|
-
schemaMismatch2("API-key provider requires credential fields");
|
|
1163
|
-
}
|
|
1164
|
-
validateDistinctCredentialFields(credential.fields);
|
|
1165
|
-
} else if (credential.type === "oauth2-authorization-code") {
|
|
1166
|
-
if (credential.tokenCustody === "local-vault") {
|
|
1167
|
-
validateLocalVaultOAuth(credential);
|
|
1168
|
-
} else if (credential.tokenCustody === "external-managed") {
|
|
1169
|
-
validateExternalManagedOAuth(credential);
|
|
1170
|
-
} else {
|
|
1171
|
-
schemaMismatch2("Invalid OAuth token custody");
|
|
1172
|
-
}
|
|
1173
|
-
} else if (credential.type !== "none") {
|
|
1174
|
-
schemaMismatch2("Invalid provider credential type");
|
|
1175
|
-
}
|
|
1176
|
-
if (definition.mcp !== void 0) {
|
|
1177
|
-
if (definition.mcp.transport !== "streamable-http") schemaMismatch2("Invalid MCP transport");
|
|
1178
|
-
if (definition.mcp.endpoint !== void 0) {
|
|
1179
|
-
validateHttpsEndpoint(definition.mcp.endpoint, "MCP endpoint");
|
|
1180
|
-
}
|
|
1181
|
-
if (definition.mcp.toolkitId !== void 0) {
|
|
1182
|
-
validateBoundedText(definition.mcp.toolkitId, "MCP toolkit id");
|
|
1183
|
-
}
|
|
1184
|
-
validateUniqueStrings(
|
|
1185
|
-
definition.mcp.allowedTools,
|
|
1186
|
-
(tool) => validateBoundedText(tool, "MCP allowed tool"),
|
|
1187
|
-
"MCP allowed tool"
|
|
1188
|
-
);
|
|
1189
|
-
validateUniqueStrings(
|
|
1190
|
-
definition.mcp.deniedTools,
|
|
1191
|
-
(tool) => validateBoundedText(tool, "MCP denied tool"),
|
|
1192
|
-
"MCP denied tool"
|
|
1193
|
-
);
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
function createProviderRegistryV1(defs) {
|
|
1197
|
-
const providers = [];
|
|
1198
|
-
const byId = /* @__PURE__ */ new Map();
|
|
1199
|
-
for (const definition of defs) {
|
|
1200
|
-
validateProviderDefinition(definition);
|
|
1201
|
-
if (byId.has(definition.id)) schemaMismatch2("Duplicate provider id");
|
|
1202
|
-
const immutableDefinition = deepFreeze2(definition);
|
|
1203
|
-
providers.push(immutableDefinition);
|
|
1204
|
-
byId.set(immutableDefinition.id, immutableDefinition);
|
|
1205
|
-
}
|
|
1206
|
-
const immutableProviders = Object.freeze(providers);
|
|
1207
|
-
return Object.freeze({
|
|
1208
|
-
contractVersion: "boring.provider-registry.v1",
|
|
1209
|
-
list: () => immutableProviders,
|
|
1210
|
-
require(providerId) {
|
|
1211
|
-
validateCredentialId2(providerId, "provider id");
|
|
1212
|
-
const provider = byId.get(providerId);
|
|
1213
|
-
if (!provider) {
|
|
1214
|
-
throw new CredentialResolutionError(
|
|
1215
|
-
CREDENTIAL_ERROR_CODES.PROVIDER_UNKNOWN,
|
|
1216
|
-
"Credential provider is not registered"
|
|
1217
|
-
);
|
|
1218
|
-
}
|
|
1219
|
-
return provider;
|
|
1220
|
-
}
|
|
1221
|
-
});
|
|
1222
|
-
}
|
|
1223
|
-
|
|
1224
|
-
// src/shared/credentials/sandboxDelivery.ts
|
|
1225
|
-
var SANDBOX_CREDENTIAL_MAX_FIELDS_V1 = 16;
|
|
1226
|
-
var SANDBOX_CREDENTIAL_MAX_METADATA_BYTES_V1 = 16384;
|
|
1227
|
-
var SANDBOX_CREDENTIAL_MAX_TOTAL_BYTES_V1 = 65536;
|
|
1228
|
-
function sandboxCredentialPayloadMetadataBytesV1(payload) {
|
|
1229
|
-
return new TextEncoder().encode(JSON.stringify({
|
|
1230
|
-
contractVersion: payload.contractVersion,
|
|
1231
|
-
workspaceId: payload.workspaceId,
|
|
1232
|
-
sandboxId: payload.sandboxId,
|
|
1233
|
-
executionId: payload.executionId,
|
|
1234
|
-
deliveryAttemptId: payload.deliveryAttemptId,
|
|
1235
|
-
bindingId: payload.bindingId,
|
|
1236
|
-
credentialVersion: payload.credentialVersion,
|
|
1237
|
-
expiresAt: payload.expiresAt,
|
|
1238
|
-
fields: payload.fields.map((field) => ({
|
|
1239
|
-
fieldId: field.fieldId,
|
|
1240
|
-
byteLength: field.value.byteLength
|
|
1241
|
-
}))
|
|
1242
|
-
})).byteLength;
|
|
1243
|
-
}
|
|
1244
|
-
function createNotImplementedSandboxCredentialPayloadResolverV1() {
|
|
1245
|
-
return Object.freeze({
|
|
1246
|
-
contractVersion: "boring.sandbox-credential-payload-resolver.v1",
|
|
1247
|
-
async resolveForDelivery() {
|
|
1248
|
-
throw new CredentialResolutionError(
|
|
1249
|
-
CREDENTIAL_ERROR_CODES.DELIVERY_FORBIDDEN,
|
|
1250
|
-
"Tier-2 in-sandbox injection not implemented in v1 (deferred to 16f.6)"
|
|
1251
|
-
);
|
|
1252
|
-
}
|
|
1253
|
-
});
|
|
1254
|
-
}
|
|
1255
|
-
|
|
1256
|
-
export {
|
|
1257
|
-
AGENT_RESOURCES_FILESYSTEM_ID,
|
|
1258
|
-
AGENT_KNOWLEDGE_FILESYSTEM_ID,
|
|
1259
|
-
READONLY_FILESYSTEM_MUTATION_CODE,
|
|
1260
|
-
RUNTIME_FILESYSTEM_CAPABILITIES,
|
|
1261
|
-
ReadonlyFilesystemMutationError,
|
|
1262
|
-
isReadonlyFilesystemMutationError,
|
|
1263
|
-
CHANNEL_DESCRIPTORS,
|
|
1264
|
-
channelDescriptor,
|
|
1265
|
-
RuntimeModeSchema,
|
|
1266
|
-
ConfigSchema,
|
|
1267
|
-
EnvSchema,
|
|
1268
|
-
validateConfig,
|
|
1269
|
-
DEFAULT_AGENT_RUNTIME_CAPABILITIES,
|
|
1270
|
-
PI_AGENT_RUNTIME_CAPABILITIES,
|
|
1271
|
-
sha256,
|
|
1272
|
-
sha256Bytes,
|
|
1273
|
-
canonicalStringify,
|
|
1274
|
-
OpaqueRefSchema,
|
|
1275
|
-
Sha256DigestSchema,
|
|
1276
|
-
validateAgentDefinition,
|
|
1277
|
-
validateAgentDeployment,
|
|
1278
|
-
createAgentAssetDigest,
|
|
1279
|
-
AgentDefinitionValidationError,
|
|
1280
|
-
AgentDeploymentValidationError,
|
|
1281
|
-
createAgentDefinitionDigest,
|
|
1282
|
-
createAgentDeploymentDigest,
|
|
1283
|
-
validateTool,
|
|
1284
|
-
TASK_STATES,
|
|
1285
|
-
TaskStateSchema,
|
|
1286
|
-
isValidTaskTransition,
|
|
1287
|
-
assertValidTransition,
|
|
1288
|
-
PrincipalRefSchema,
|
|
1289
|
-
AgentRefSchema,
|
|
1290
|
-
agentRefEquals,
|
|
1291
|
-
ARTIFACT_LOCATOR_KINDS,
|
|
1292
|
-
WorkspaceFileLocatorSchema,
|
|
1293
|
-
ArtifactLocatorSchema,
|
|
1294
|
-
ArtifactRefSchema,
|
|
1295
|
-
PartSchema,
|
|
1296
|
-
AgentMessageSchema,
|
|
1297
|
-
AGENT_TASK_SCHEMA_VERSION,
|
|
1298
|
-
AgentTaskSchema,
|
|
1299
|
-
validateAgentTask,
|
|
1300
|
-
AgentConsumptionValidationError,
|
|
1301
|
-
parseAgentTaskEdgeCompat,
|
|
1302
|
-
ConsumptionGuardsSchema,
|
|
1303
|
-
validateConsumptionGuards,
|
|
1304
|
-
detectConsumptionCycle,
|
|
1305
|
-
assertNoConsumptionCycle,
|
|
1306
|
-
isWithinConsumptionDepth,
|
|
1307
|
-
assertWithinConsumptionDepth,
|
|
1308
|
-
OpaqueShareLocatorIdSchema,
|
|
1309
|
-
ShareEntryProvenanceSchema,
|
|
1310
|
-
ShareEntryV1Schema,
|
|
1311
|
-
ShareEntryErrorCode,
|
|
1312
|
-
ShareEntryValidationError,
|
|
1313
|
-
InMemoryShareEntryStore,
|
|
1314
|
-
resolveShareEntry,
|
|
1315
|
-
CREDENTIAL_ERROR_CODES,
|
|
1316
|
-
CredentialResolutionError,
|
|
1317
|
-
workspaceCredentialCustodyScopeV1,
|
|
1318
|
-
userCredentialCustodyScopeV1,
|
|
1319
|
-
assertCredentialCustodyScopeV1,
|
|
1320
|
-
credentialCustodySubjectKeyV1,
|
|
1321
|
-
providerCredentialFieldsV1,
|
|
1322
|
-
createCredentialConsumerBindingRegistryV1,
|
|
1323
|
-
WORKSPACE_KEK_PROVIDER_VERSION,
|
|
1324
|
-
CREDENTIAL_ENVELOPE_VERSION,
|
|
1325
|
-
CREDENTIAL_AAD_ENCODING_VERSION,
|
|
1326
|
-
CREDENTIAL_DEK_BYTE_LENGTH_V1,
|
|
1327
|
-
CREDENTIAL_KEK_BYTE_LENGTH_V1,
|
|
1328
|
-
CREDENTIAL_NONCE_BYTE_LENGTH_V1,
|
|
1329
|
-
CREDENTIAL_AUTH_TAG_BYTE_LENGTH_V1,
|
|
1330
|
-
PROVIDER_CREDENTIAL_REF_VERSION,
|
|
1331
|
-
createProviderCredentialRefFactoryV1,
|
|
1332
|
-
createProviderRegistryV1,
|
|
1333
|
-
SANDBOX_CREDENTIAL_MAX_FIELDS_V1,
|
|
1334
|
-
SANDBOX_CREDENTIAL_MAX_METADATA_BYTES_V1,
|
|
1335
|
-
SANDBOX_CREDENTIAL_MAX_TOTAL_BYTES_V1,
|
|
1336
|
-
sandboxCredentialPayloadMetadataBytesV1,
|
|
1337
|
-
createNotImplementedSandboxCredentialPayloadResolverV1
|
|
1338
|
-
};
|