@springbrand/agent-runtime 0.1.3-alpha.1 → 0.1.3-alpha.10
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/package.json +12 -3
- package/src/adapter/cloudflare/index.ts +56 -0
- package/src/adapter/cloudflare/resources/runtime-resources.ts +89 -0
- package/src/adapter/cloudflare/sandbox/adapter.ts +1513 -0
- package/src/adapter/cloudflare/sandbox/id.ts +23 -0
- package/src/adapter/cloudflare/sandbox/policy.ts +15 -0
- package/src/adapter/cloudflare/subagent/definition.ts +574 -0
- package/src/adapter/cloudflare/subagent/runner.ts +175 -0
- package/src/adapter/cloudflare/subagent/tools.ts +254 -0
- package/src/adapter/cloudflare/universal-agent/hooks.ts +35 -0
- package/src/adapter/cloudflare/universal-agent/preparation.ts +277 -0
- package/src/adapter/cloudflare/universal-agent/tools.ts +80 -0
- package/src/adapter/cloudflare/workspace/git-fs.ts +178 -0
- package/src/adapter/cloudflare/workspace/publisher.ts +31 -0
- package/src/adapter/cloudflare/workspace/scoped-workspace.ts +376 -0
- package/src/adapter/cloudflare/workspace/version-control.ts +374 -0
- package/src/agent-tool-runtime.ts +152 -0
- package/src/db/agent-tool.repo.ts +27 -0
- package/src/db/index.ts +33 -0
- package/src/db/interaction.repo.ts +185 -0
- package/src/db/schema.ts +25 -1
- package/src/db/submission.repo.ts +63 -1
- package/src/index.ts +57 -21
- package/src/kernel/approval-lifecycle.ts +41 -6
- package/src/kernel/bindings.ts +73 -9
- package/src/kernel/interaction-lifecycle.ts +395 -0
- package/src/kernel/public-contracts.ts +2 -0
- package/src/kernel/recoverable-chat-agent.ts +104 -6
- package/src/kernel/runtime-assembly-view.ts +37 -0
- package/src/kernel/runtime-assembly.ts +41 -0
- package/src/kernel/runtime-config.ts +4 -0
- package/src/kernel/runtime-load.ts +191 -0
- package/src/kernel/state.ts +12 -1
- package/src/kernel/submission-lifecycle.ts +33 -2
- package/src/layers/orchestration/temporary-agent/core.ts +12 -1
- package/src/layers/orchestration/temporary-agent/runner.ts +1 -2
- package/src/lib/mcp.ts +7 -3
- package/src/lib/prompt.ts +1 -1
- package/src/lib/telemetry-dev.ts +7 -4
- package/src/pi/assembly/context.ts +3 -3
- package/src/pi/assembly/extensions.ts +11 -22
- package/src/pi/assembly/snapshot.ts +6 -3
- package/src/pi/message/contract.ts +7 -0
- package/src/pi/message/conversion.ts +9 -1
- package/src/pi/runtime-adapter/assembly.ts +26 -31
- package/src/pi/runtime-adapter/execution.ts +198 -15
- package/src/pi/runtime-adapter/index.ts +24 -8
- package/src/pi/runtime-adapter/models.ts +382 -35
- package/src/pi/runtime-adapter/recovery.ts +188 -1
- package/src/pi/runtime-adapter/transcript.ts +61 -3
- package/src/pi/tool/ai-adapter.ts +58 -1
- package/src/pi/tool/base.ts +190 -12
- package/src/pi/tool/compiler.ts +34 -1
- package/src/pi/tool/core-host.ts +19 -24
- package/src/pi/tool/core.ts +30 -120
- package/src/pi/tool/gateway.ts +54 -0
- package/src/pi/tool/index.ts +2 -0
- package/src/pi/tool/mcp.ts +96 -68
- package/src/pi/tool/schedule.ts +41 -19
- package/src/pi/tool/skill.ts +126 -420
- package/src/pi/tool/subagent.ts +14 -2
- package/src/pi/tool/web-fetch.ts +281 -0
- package/src/pi/tool/web-search/api.ts +34 -18
- package/src/pi/tool/web-search/web-search.ts +0 -1
- package/src/pi/tool/workspace-revision.ts +64 -0
- package/src/pi/tool/workspace-sandbox.ts +105 -263
- package/src/pi/turn/index.ts +20 -0
- package/src/pi/turn/interaction.ts +181 -0
- package/src/pi/turn/tool-recovery.ts +244 -1
- package/src/runtime-agent-context.ts +112 -0
- package/src/runtime-agent.ts +568 -321
- package/src/{plugins.ts → runtime-assembler.ts} +372 -398
- package/src/runtime-definition.ts +175 -0
- package/src/runtime.ts +835 -204
- package/src/tool-registry.ts +143 -0
- package/src/workspace-versioning.ts +46 -0
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
RuntimeExtensionPermissions,
|
|
12
12
|
} from "../../kernel/extensions";
|
|
13
13
|
import type { RuntimeDegradation } from "../../kernel/degradation";
|
|
14
|
+
import { withRuntimeLoadTimeout } from "../../kernel/runtime-load";
|
|
14
15
|
import { sanitizeExtensionName } from "../../lib/extension-name";
|
|
15
16
|
import type { PiToolCandidate } from "../tool/compiler";
|
|
16
17
|
|
|
@@ -42,9 +43,6 @@ export interface PiLoadedExtension {
|
|
|
42
43
|
|
|
43
44
|
export interface AssemblePiExtensionsOptions {
|
|
44
45
|
readonly extensions: readonly RuntimeExtensionConfig[];
|
|
45
|
-
readonly published: ReadonlySet<string>;
|
|
46
|
-
readonly enabled: ReadonlySet<string>;
|
|
47
|
-
readonly authorized: ReadonlySet<string>;
|
|
48
46
|
readonly load: (
|
|
49
47
|
extension: RuntimeExtensionConfig,
|
|
50
48
|
) => Promise<LoadedRuntimeExtension>;
|
|
@@ -237,7 +235,7 @@ const EXTENSION_HOOK_NAMES = [
|
|
|
237
235
|
* 通过 Cloudflare ExtensionManager 加载一个 Extension,并只暴露 Runtime 需要的描述和执行能力。
|
|
238
236
|
*
|
|
239
237
|
* @remarks
|
|
240
|
-
* Runtime
|
|
238
|
+
* Runtime 准备阶段会对已配置 Extension 调用,资源发布的 smoke test 也会用它校验候选源码;调用方必须提供 WorkerLoader,并在权限需要时提供 Host 绑定工厂。
|
|
241
239
|
*
|
|
242
240
|
* discovery 使用剔除权限的 manifest,有外部访问的执行 isolate 则延迟到首次 Tool 执行时创建。这是为了防止 `describe()` 在授权和审批前获得网络或 Host 能力,不能随意合并两条加载路径。
|
|
243
241
|
*
|
|
@@ -267,9 +265,12 @@ export async function loadPiExtension(
|
|
|
267
265
|
const { permissions: _ignored, ...manifestWithoutPermissions } =
|
|
268
266
|
extension.manifest;
|
|
269
267
|
try {
|
|
270
|
-
await
|
|
271
|
-
|
|
272
|
-
|
|
268
|
+
await withRuntimeLoadTimeout(
|
|
269
|
+
`extension:${name}:discover`,
|
|
270
|
+
() => discovery.load(
|
|
271
|
+
manifestWithoutPermissions as ExtensionManifest,
|
|
272
|
+
extension.source,
|
|
273
|
+
),
|
|
273
274
|
);
|
|
274
275
|
} catch (cause) {
|
|
275
276
|
// Upstream assumes describe() yields an array and throws an opaque TypeError
|
|
@@ -507,20 +508,17 @@ export function extensionToolRequiredExecutionLevel(
|
|
|
507
508
|
}
|
|
508
509
|
|
|
509
510
|
/**
|
|
510
|
-
*
|
|
511
|
+
* 把当前已配置的 Extension 装配成 Runtime 能力。
|
|
511
512
|
*
|
|
512
513
|
* @remarks
|
|
513
|
-
* Runtime 准备阶段和资源 smoke test
|
|
514
|
+
* Runtime 准备阶段和资源 smoke test 调用;调用方传入已选 Extension 及已确定加载策略的 `load`。
|
|
514
515
|
*
|
|
515
|
-
*
|
|
516
|
+
* 单个加载失败记为 degradation 而不影响其他项。
|
|
516
517
|
*
|
|
517
518
|
* 核心术语见包入口 `index.ts`。
|
|
518
519
|
*/
|
|
519
520
|
export async function assemblePiExtensions({
|
|
520
521
|
extensions,
|
|
521
|
-
published,
|
|
522
|
-
enabled,
|
|
523
|
-
authorized,
|
|
524
522
|
load,
|
|
525
523
|
}: AssemblePiExtensionsOptions): Promise<PiExtensionAssembly> {
|
|
526
524
|
const loadedExtensions: PiLoadedExtension[] = [];
|
|
@@ -530,14 +528,6 @@ export async function assemblePiExtensions({
|
|
|
530
528
|
|
|
531
529
|
for (const extension of extensions) {
|
|
532
530
|
const name = extension.manifest.name.trim();
|
|
533
|
-
if (
|
|
534
|
-
!published.has(name) ||
|
|
535
|
-
!enabled.has(name) ||
|
|
536
|
-
!authorized.has(name)
|
|
537
|
-
) {
|
|
538
|
-
continue;
|
|
539
|
-
}
|
|
540
|
-
|
|
541
531
|
let loaded: LoadedRuntimeExtension;
|
|
542
532
|
try {
|
|
543
533
|
loaded = await load(extension);
|
|
@@ -608,7 +598,6 @@ export async function assemblePiExtensions({
|
|
|
608
598
|
});
|
|
609
599
|
candidates.push(Object.freeze({
|
|
610
600
|
owner: `extension:${name}@${extension.manifest.version}`,
|
|
611
|
-
authorized: true,
|
|
612
601
|
requiredExecutionLevel,
|
|
613
602
|
summary: description,
|
|
614
603
|
tool,
|
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
ThinkingLevel,
|
|
4
4
|
} from "@earendil-works/pi-agent-core";
|
|
5
5
|
import type { Api, Model } from "@earendil-works/pi-ai";
|
|
6
|
+
import { clampReasoning } from "@earendil-works/pi-ai/api/simple-options";
|
|
6
7
|
import type {
|
|
7
8
|
RuntimeMcpServer,
|
|
8
9
|
RuntimeProfile,
|
|
@@ -21,7 +22,7 @@ import type { PiToolCandidate } from "../tool/compiler";
|
|
|
21
22
|
*/
|
|
22
23
|
export interface PiToolSurface {
|
|
23
24
|
finalize(
|
|
24
|
-
|
|
25
|
+
candidates: readonly PiToolCandidate[],
|
|
25
26
|
): readonly PiToolCandidate[];
|
|
26
27
|
}
|
|
27
28
|
|
|
@@ -79,11 +80,13 @@ function freezeModel(model: Model<Api>): Model<Api> {
|
|
|
79
80
|
|
|
80
81
|
// 作用:把 Runtime 的思考强度名称转成 Pi Agent Core 接受的名称。
|
|
81
82
|
// 调用:创建 Runtime 装配快照时对 profile 中的 `thinking` 调用。
|
|
82
|
-
//
|
|
83
|
+
// 原因:`none` 映射成 `off`;xhigh/max 用 clampReasoning 夹到 API 真正支持的最高档,
|
|
84
|
+
// 避免超出范围的等级在 provider 侧静默失败。
|
|
83
85
|
function toPiThinkingLevel(
|
|
84
86
|
thinking: ThinkingEffort,
|
|
85
87
|
): ThinkingLevel {
|
|
86
|
-
|
|
88
|
+
if (thinking === "none") return "off";
|
|
89
|
+
return clampReasoning(thinking) ?? "off";
|
|
87
90
|
}
|
|
88
91
|
|
|
89
92
|
// 作用:复制并冻结一个 Extension 配置的 manifest 和权限集合。
|
|
@@ -2,6 +2,13 @@ import type { UIMessage } from "ai";
|
|
|
2
2
|
|
|
3
3
|
export type UIChatTrigger = "submit-message" | "regenerate-message";
|
|
4
4
|
|
|
5
|
+
/** A user-selected Runtime capability persisted with the visible UIMessage. */
|
|
6
|
+
export interface RequestedCapability {
|
|
7
|
+
readonly kind: "skill" | "plan";
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly label: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
5
12
|
export interface UIChatRequestBody {
|
|
6
13
|
readonly messages: readonly UIMessage[];
|
|
7
14
|
readonly trigger: UIChatTrigger;
|
|
@@ -26,6 +26,7 @@ function attachmentText(
|
|
|
26
26
|
|
|
27
27
|
function userContent(
|
|
28
28
|
parts: ReadonlyArray<UIMessage["parts"][number]>,
|
|
29
|
+
privateContext?: string,
|
|
29
30
|
): UserMessage["content"] {
|
|
30
31
|
const content: Exclude<UserMessage["content"], string> = [];
|
|
31
32
|
for (const part of parts) {
|
|
@@ -46,16 +47,23 @@ function userContent(
|
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
49
|
if (content.length === 0) throw new Error("User message content is required");
|
|
50
|
+
if (privateContext) {
|
|
51
|
+
content.unshift({
|
|
52
|
+
type: "text",
|
|
53
|
+
text: `[Agent private context]\n${privateContext}\n[/Agent private context]`,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
49
56
|
return content;
|
|
50
57
|
}
|
|
51
58
|
|
|
52
59
|
/** Convert an official user UIMessage into canonical Pi model input. */
|
|
53
60
|
export function uiUserMessageToPi(
|
|
54
61
|
message: UIMessage & { readonly role: "user" },
|
|
62
|
+
privateContext?: string,
|
|
55
63
|
): UserMessage {
|
|
56
64
|
return {
|
|
57
65
|
role: "user",
|
|
58
|
-
content: userContent(message.parts),
|
|
66
|
+
content: userContent(message.parts, privateContext),
|
|
59
67
|
timestamp: timestampOf(message),
|
|
60
68
|
};
|
|
61
69
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
RuntimeBindings,
|
|
3
|
+
RuntimeGatewaySession,
|
|
3
4
|
RuntimePlatformPort,
|
|
4
5
|
} from "../../kernel/bindings";
|
|
5
6
|
import type { RuntimeDegradation } from "../../kernel/degradation";
|
|
@@ -8,7 +9,7 @@ import type {
|
|
|
8
9
|
} from "../../kernel/extensions";
|
|
9
10
|
import type { RuntimeProfile } from "../../kernel/profile";
|
|
10
11
|
import type { ExecutionLevel } from "../../lib/execution-level";
|
|
11
|
-
import type { RuntimeSnapshot } from "../../
|
|
12
|
+
import type { RuntimeSnapshot } from "../../runtime-assembler";
|
|
12
13
|
import type { PiRuntimeAssembly } from "../assembly";
|
|
13
14
|
import {
|
|
14
15
|
assemblePiSystemContext,
|
|
@@ -19,6 +20,7 @@ import {
|
|
|
19
20
|
type PiLoadedExtension,
|
|
20
21
|
} from "../assembly";
|
|
21
22
|
import {
|
|
23
|
+
createPiGatewayToolCandidates,
|
|
22
24
|
createPiMcpToolCandidates,
|
|
23
25
|
listExtensionsPiToolCandidate,
|
|
24
26
|
type PiMcpHost,
|
|
@@ -58,6 +60,7 @@ interface PiAssemblySnapshot {
|
|
|
58
60
|
interface PreparePiAssemblyOptions {
|
|
59
61
|
readonly snapshot: PiAssemblySnapshot;
|
|
60
62
|
readonly mcpHost: PiMcpHost;
|
|
63
|
+
readonly gatewaySession?: RuntimeGatewaySession;
|
|
61
64
|
// 为一个扩展生成带权限参数的 Host Fetcher。
|
|
62
65
|
// loadPiExtension 在扩展需要 Host 能力时调用它。
|
|
63
66
|
// Worker 掌握真实绑定,装配层只保存这个窄函数,不能自行扩大权限。
|
|
@@ -90,6 +93,8 @@ interface PreparedPiAssembly {
|
|
|
90
93
|
export interface PreparePiRuntimeOptions {
|
|
91
94
|
readonly snapshot: RuntimeSnapshot;
|
|
92
95
|
readonly mcpHost: PiMcpHost;
|
|
96
|
+
readonly gatewaySession?: RuntimeGatewaySession;
|
|
97
|
+
readonly additionalDegradations?: readonly RuntimeDegradation[];
|
|
93
98
|
/**
|
|
94
99
|
* 为一个扩展创建受限的 Host 绑定。
|
|
95
100
|
*
|
|
@@ -115,6 +120,7 @@ export interface PreparePiRuntimeOptions {
|
|
|
115
120
|
export interface PreparedPiRuntime {
|
|
116
121
|
readonly revisionDescriptor: string;
|
|
117
122
|
readonly degradations: readonly RuntimeDegradation[];
|
|
123
|
+
readonly extensions: readonly { readonly name: string; readonly version: string }[];
|
|
118
124
|
}
|
|
119
125
|
|
|
120
126
|
/**
|
|
@@ -160,7 +166,7 @@ export interface PinnedPiRuntime {
|
|
|
160
166
|
* @remarks
|
|
161
167
|
* `PreparedPiTurnAdapter` 在重建 Turn 前读取这个 JSON 结构。
|
|
162
168
|
*
|
|
163
|
-
*
|
|
169
|
+
* 基础版本作为准入时元数据保留,创建 Turn 时不与当前 Runtime 比较。
|
|
164
170
|
*/
|
|
165
171
|
export interface PinnedPiRuntimeDescriptor {
|
|
166
172
|
readonly version: 1;
|
|
@@ -200,6 +206,8 @@ const IDEMPOTENT_TOOL_NAMES = new Set([
|
|
|
200
206
|
"browser_markdown",
|
|
201
207
|
"browser_scrape",
|
|
202
208
|
"bind_resource",
|
|
209
|
+
"delete",
|
|
210
|
+
"edit",
|
|
203
211
|
"find",
|
|
204
212
|
"get_time",
|
|
205
213
|
"grep",
|
|
@@ -211,6 +219,7 @@ const IDEMPOTENT_TOOL_NAMES = new Set([
|
|
|
211
219
|
"read_skill_resource",
|
|
212
220
|
"sandbox_process_logs",
|
|
213
221
|
"web_search",
|
|
222
|
+
"write",
|
|
214
223
|
"unbind_resource",
|
|
215
224
|
]);
|
|
216
225
|
|
|
@@ -239,10 +248,12 @@ function describeTools(candidates: readonly PiToolCandidate[]) {
|
|
|
239
248
|
name: candidate.tool.name,
|
|
240
249
|
owner: candidate.owner,
|
|
241
250
|
label: candidate.tool.label,
|
|
242
|
-
description:
|
|
243
|
-
candidate.tool.description ?? candidate.tool.label,
|
|
251
|
+
description: candidate.tool.description ?? candidate.tool.label,
|
|
244
252
|
parameters: candidate.tool.parameters,
|
|
245
253
|
requiredExecutionLevel: candidate.requiredExecutionLevel,
|
|
254
|
+
...(candidate.alwaysRequiresApproval
|
|
255
|
+
? { alwaysRequiresApproval: true }
|
|
256
|
+
: {}),
|
|
246
257
|
...(candidate.source ? { source: candidate.source } : {}),
|
|
247
258
|
retry: piToolRetryPolicy(candidate),
|
|
248
259
|
}))
|
|
@@ -251,7 +262,7 @@ function describeTools(candidates: readonly PiToolCandidate[]) {
|
|
|
251
262
|
|
|
252
263
|
// 把本模块认定会影响版本的准备结果序列化出来。
|
|
253
264
|
// preparePiRuntime 创建一次,Runtime 接受快照前再对结果求哈希。
|
|
254
|
-
//
|
|
265
|
+
// 集合排序保证等价输入稳定;增删字段会改变版本哈希。
|
|
255
266
|
function describeRuntime(
|
|
256
267
|
snapshot: RuntimeSnapshot,
|
|
257
268
|
candidates: readonly PiToolCandidate[],
|
|
@@ -298,6 +309,7 @@ class PreparedRuntime implements PreparedPiRuntime {
|
|
|
298
309
|
constructor(
|
|
299
310
|
readonly revisionDescriptor: string,
|
|
300
311
|
readonly degradations: readonly RuntimeDegradation[],
|
|
312
|
+
readonly extensions: readonly { readonly name: string; readonly version: string }[],
|
|
301
313
|
private readonly owner: object,
|
|
302
314
|
private readonly state: PreparedPiRuntimeState,
|
|
303
315
|
) {}
|
|
@@ -334,18 +346,17 @@ export function readPreparedPiRuntime(
|
|
|
334
346
|
}
|
|
335
347
|
|
|
336
348
|
/**
|
|
337
|
-
*
|
|
349
|
+
* 读取已存的固定描述。
|
|
338
350
|
*
|
|
339
351
|
* @remarks
|
|
340
352
|
* `PreparedPiTurnAdapter` 在新建或恢复 Pi Turn 前调用它。
|
|
341
353
|
*
|
|
342
|
-
*
|
|
354
|
+
* Prepared Runtime 提供当前执行能力,descriptor 仅保留 Submission 固定的 Turn 字段。
|
|
343
355
|
*/
|
|
344
356
|
export function readPinnedPiRuntime(
|
|
345
357
|
prepared: PreparedPiRuntime,
|
|
346
358
|
owner: object,
|
|
347
359
|
descriptorBody: string,
|
|
348
|
-
baseRevision: string,
|
|
349
360
|
): {
|
|
350
361
|
readonly state: PreparedPiRuntimeState;
|
|
351
362
|
readonly descriptor: PinnedPiRuntimeDescriptor;
|
|
@@ -361,24 +372,11 @@ export function readPinnedPiRuntime(
|
|
|
361
372
|
throw new Error("Pinned Runtime assembly descriptor is invalid");
|
|
362
373
|
}
|
|
363
374
|
const descriptor = value as PinnedPiRuntimeDescriptor;
|
|
364
|
-
const expected = JSON.parse(prepared.revisionDescriptor) as Record<
|
|
365
|
-
string,
|
|
366
|
-
unknown
|
|
367
|
-
>;
|
|
368
|
-
const actual = descriptor as unknown as Record<string, unknown>;
|
|
369
|
-
const incompatible = Object.keys(expected).some((key) =>
|
|
370
|
-
key !== "systemPrompt" &&
|
|
371
|
-
JSON.stringify(actual[key]) !== JSON.stringify(expected[key])
|
|
372
|
-
);
|
|
373
375
|
if (
|
|
374
376
|
descriptor.version !== 1 ||
|
|
375
|
-
descriptor.
|
|
376
|
-
typeof descriptor.systemPrompt !== "string" ||
|
|
377
|
-
incompatible
|
|
377
|
+
typeof descriptor.systemPrompt !== "string"
|
|
378
378
|
) {
|
|
379
|
-
throw new Error(
|
|
380
|
-
"Pinned Runtime revision is unavailable for Pi recovery",
|
|
381
|
-
);
|
|
379
|
+
throw new Error("Pinned Runtime assembly descriptor is invalid");
|
|
382
380
|
}
|
|
383
381
|
return { state, descriptor };
|
|
384
382
|
}
|
|
@@ -394,16 +392,8 @@ async function preparePiAssembly(
|
|
|
394
392
|
options: PreparePiAssemblyOptions,
|
|
395
393
|
): Promise<PreparedPiAssembly> {
|
|
396
394
|
const { snapshot } = options;
|
|
397
|
-
const extensionNames = new Set(
|
|
398
|
-
snapshot.pi.extensions.map((extension) =>
|
|
399
|
-
extension.manifest.name.trim()
|
|
400
|
-
),
|
|
401
|
-
);
|
|
402
395
|
const extensions = await assemblePiExtensions({
|
|
403
396
|
extensions: snapshot.pi.extensions,
|
|
404
|
-
published: extensionNames,
|
|
405
|
-
enabled: extensionNames,
|
|
406
|
-
authorized: extensionNames,
|
|
407
397
|
load: async (extension) => {
|
|
408
398
|
const workspacePermission =
|
|
409
399
|
extension.manifest.permissions?.workspace ?? "none";
|
|
@@ -425,6 +415,9 @@ async function preparePiAssembly(
|
|
|
425
415
|
candidates: snapshot.pi.toolSurface.finalize([
|
|
426
416
|
...extensions.candidates,
|
|
427
417
|
listExtensionsPiToolCandidate(extensions.loaded),
|
|
418
|
+
...(options.gatewaySession
|
|
419
|
+
? createPiGatewayToolCandidates(options.gatewaySession)
|
|
420
|
+
: []),
|
|
428
421
|
...createPiMcpToolCandidates(
|
|
429
422
|
options.mcpHost,
|
|
430
423
|
snapshot.profile.mcpServers,
|
|
@@ -455,8 +448,10 @@ export async function preparePiRuntime(
|
|
|
455
448
|
describeRuntime(options.snapshot, candidates, assembly.loaded),
|
|
456
449
|
Object.freeze([
|
|
457
450
|
...options.snapshot.degradations,
|
|
451
|
+
...(options.additionalDegradations ?? []),
|
|
458
452
|
...assembly.degradations,
|
|
459
453
|
]),
|
|
454
|
+
Object.freeze(assembly.loaded.map(({ name, version }) => ({ name, version }))),
|
|
460
455
|
owner,
|
|
461
456
|
Object.freeze({
|
|
462
457
|
snapshot: options.snapshot,
|