@springbrand/agent-runtime 0.3.0-alpha.2 → 0.3.0-alpha.21
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 +11 -9
- package/src/adapter/cloudflare/agent.ts +233 -179
- package/src/adapter/cloudflare/define-agent.ts +252 -104
- package/src/adapter/cloudflare/index.ts +18 -0
- package/src/adapter/cloudflare/scheduling/schedule-rule.ts +322 -0
- package/src/adapter/cloudflare/scheduling/zoned-cron.ts +11 -6
- package/src/adapter/cloudflare/schema.ts +21 -2
- package/src/adapter/cloudflare/subagent/definition.ts +25 -13
- package/src/adapter/cloudflare/subagent/runner.ts +43 -50
- package/src/adapter/cloudflare/subagent/tools.ts +4 -4
- package/src/adapter/cloudflare/universal-agent/preparation.ts +3 -3
- package/src/adapter/cloudflare/universal-agent/tools.ts +4 -6
- package/src/adapter/cloudflare/workspace/version-control.ts +1 -1
- package/src/config/activation.ts +13 -15
- package/src/config/agent-context.ts +1 -1
- package/src/config/assembler.ts +48 -31
- package/src/config/assembly-snapshot.ts +1 -1
- package/src/config/definition.ts +1 -1
- package/src/config/harness-runtime.ts +77 -49
- package/src/config/index.ts +1 -1
- package/src/config/model-guidance.ts +20 -0
- package/src/config/ports.ts +57 -7
- package/src/config/{pinning.ts → prepared-runtime.ts} +59 -123
- package/src/config/public-contracts.ts +2 -2
- package/src/config/runtime-config.ts +2 -1
- package/src/context/assembly.ts +1 -1
- package/src/context/extension/assembly.ts +2 -2
- package/src/context/memory/budget/gate.ts +19 -3
- package/src/conversation/harness-resume.ts +89 -238
- package/src/conversation/harness-stream.ts +87 -71
- package/src/conversation/history.ts +154 -152
- package/src/conversation/message/contract.ts +28 -4
- package/src/conversation/message/conversion.ts +46 -5
- package/src/conversation/message/projection.ts +61 -21
- package/src/conversation/session-entry.ts +29 -0
- package/src/conversation/state.ts +23 -2
- package/src/harness/governance.ts +206 -0
- package/src/harness/index.ts +3 -0
- package/src/harness/session-harness.ts +269 -445
- package/src/harness/submission-operation.ts +15 -40
- package/src/index.ts +18 -8
- package/src/lib/artifacts.ts +18 -0
- package/src/lib/execution-level.ts +13 -0
- package/src/lib/prompt.ts +9 -10
- package/src/lib/token-estimate.ts +8 -0
- package/src/model-protocol/openrouter.ts +41 -0
- package/src/models/index.ts +200 -35
- package/src/models/openrouter/messages.ts +13 -8
- package/src/models/openrouter/openai.ts +200 -0
- package/src/models/openrouter/protocol-response.ts +85 -0
- package/src/models/provider-streams.ts +45 -0
- package/src/session/cloudflare/migration.ts +382 -864
- package/src/session/cloudflare/storage.ts +13 -536
- package/src/session/index.ts +22 -35
- package/src/skills/springbrand-worker-website/index.ts +1 -1
- package/src/submission/admission.ts +20 -30
- package/src/submission/contracts.ts +42 -2
- package/src/submission/delivery.ts +1 -1
- package/src/submission/finalization.ts +36 -15
- package/src/submission/lifecycle.ts +28 -15
- package/src/submission/repository.ts +97 -49
- package/src/submission/steer-delivery.ts +32 -76
- package/src/submission/unattended.ts +40 -0
- package/src/telemetry/contract.ts +0 -1
- package/src/telemetry/coordinator.ts +1 -1
- package/src/telemetry/runtime-telemetry.ts +0 -4
- package/src/telemetry/subagent-lifecycle.ts +1 -1
- package/src/telemetry/turn-events.ts +35 -25
- package/src/tools/README.md +44 -0
- package/src/tools/{ai-adapter.ts → adapters/ai-to-pi.ts} +6 -9
- package/src/tools/{declared.ts → adapters/declared.ts} +6 -2
- package/src/tools/{nested-tools.ts → adapters/pi-to-ai.ts} +4 -4
- package/src/tools/assistant/ask-user.ts +319 -0
- package/src/tools/assistant/candidate.ts +15 -0
- package/src/tools/assistant/followups.ts +34 -0
- package/src/tools/assistant/index.ts +19 -0
- package/src/tools/assistant/memory.ts +73 -0
- package/src/tools/assistant/plan.ts +98 -0
- package/src/tools/{time.ts → assistant/time.ts} +1 -1
- package/src/tools/{core-host.ts → codemode/adapter.ts} +50 -53
- package/src/tools/{core.ts → codemode/index.ts} +36 -92
- package/src/tools/codemode/workspace-connector.ts +198 -0
- package/src/tools/extension/index.ts +42 -0
- package/src/tools/index.ts +29 -26
- package/src/tools/{gateway.ts → mcp/gateway.ts} +19 -19
- package/src/tools/{mcp.ts → mcp/index.ts} +5 -5
- package/src/tools/runtime/activation.ts +40 -0
- package/src/tools/{approval → runtime/approval}/repository.ts +13 -12
- package/src/tools/runtime/compiler.ts +246 -0
- package/src/tools/runtime/contracts.ts +140 -0
- package/src/tools/{decision-gate.ts → runtime/decision-gate.ts} +149 -39
- package/src/tools/{human-decisions.ts → runtime/human-decisions.ts} +4 -4
- package/src/tools/{interaction → runtime/interaction}/repository.ts +1 -7
- package/src/tools/runtime/result.ts +22 -0
- package/src/tools/runtime/unattended-error.ts +4 -0
- package/src/tools/sandbox/index.ts +228 -0
- package/src/tools/schedule/index.ts +301 -0
- package/src/tools/skill/contracts.ts +20 -0
- package/src/tools/skill/index.ts +99 -0
- package/src/tools/skill/resources.ts +322 -0
- package/src/tools/skill/scripts.ts +168 -0
- package/src/tools/{subagent-authority.ts → subagent/authority.ts} +31 -31
- package/src/tools/{subagent.ts → subagent/index.ts} +34 -37
- package/src/tools/{subagent-run-repository.ts → subagent/repository.ts} +1 -1
- package/src/tools/{subagent-runtime.ts → subagent/runtime.ts} +1 -1
- package/src/tools/{temporary-agent → subagent/temporary}/approvals.ts +4 -7
- package/src/tools/{temporary-agent → subagent/temporary}/core.ts +2 -3
- package/src/tools/{temporary-agent → subagent/temporary}/runner.ts +1 -1
- package/src/tools/{temporary-agent → subagent/temporary}/workspace.ts +1 -4
- package/src/tools/{web-fetch.ts → web/fetch.ts} +4 -13
- package/src/tools/web/index.ts +2 -0
- package/src/tools/web/search/api.ts +1322 -0
- package/src/tools/web/search/index.ts +2 -0
- package/src/tools/{web-search/web-search.ts → web/search/search.ts} +5 -7
- package/src/tools/{workspace-sandbox.ts → workspace/index.ts} +12 -272
- package/src/tools/{workspace-revision.ts → workspace/revision.ts} +3 -3
- package/src/tools/base.ts +0 -534
- package/src/tools/compiler.ts +0 -327
- package/src/tools/schedule.ts +0 -261
- package/src/tools/skill.ts +0 -565
- package/src/tools/web-search/api.ts +0 -1318
- package/src/tools/web-search/index.ts +0 -2
- package/src/tools/workspace-state-connector.ts +0 -146
- package/src/tools/{approval → runtime/approval}/index.ts +0 -0
- package/src/tools/{interaction → runtime/interaction}/index.ts +0 -0
- package/src/tools/{temporary-agent → subagent/temporary}/coordinator.ts +0 -0
- package/src/tools/{subagent-types → subagent/types}/contract.ts +0 -0
- package/src/tools/{subagent-types → subagent/types}/extract/index.ts +0 -0
- package/src/tools/{subagent-types → subagent/types}/fanout/index.ts +0 -0
- package/src/tools/{subagent-types → subagent/types}/registry.ts +1 -1
- /package/src/tools/{workspace-versioning.ts → workspace/versioning.ts} +0 -0
package/src/config/ports.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
+
export type { RuntimeSchedulePreparation } from "../submission/contracts";
|
|
1
2
|
import type { RuntimeModelInputModality } from "./profile";
|
|
2
3
|
import type { SkillSource } from "agents/skills";
|
|
3
|
-
import type { ScheduleSpec } from "../submission/contracts";
|
|
4
|
+
import type { ScheduleSpec, RuntimeSchedulePreparation } from "../submission/contracts";
|
|
4
5
|
import type { RuntimeActivityProjection } from "../conversation/state";
|
|
5
6
|
import type { ExecutionLevel } from "../lib/execution-level";
|
|
6
7
|
import type { AgentToolResult } from "@earendil-works/pi-agent-core";
|
|
7
|
-
import type { PiToolCandidate } from "../tools/
|
|
8
|
+
import type { PiToolCandidate } from "../tools/runtime/contracts";
|
|
8
9
|
import type {
|
|
9
10
|
RuntimeEventConfirmation,
|
|
10
11
|
RuntimeLifecycleFact,
|
|
11
12
|
RuntimeSubagentUsageEvent,
|
|
12
13
|
RuntimeSubagentUsageMetrics,
|
|
13
|
-
} from "../tools/subagent
|
|
14
|
+
} from "../tools/subagent/authority";
|
|
14
15
|
export type { RuntimeModelInputModality } from "./profile";
|
|
15
16
|
export type {
|
|
16
17
|
RuntimeEventConfirmation,
|
|
@@ -21,7 +22,7 @@ export type {
|
|
|
21
22
|
RuntimeSubmissionAdmissionHook,
|
|
22
23
|
RuntimeSubmissionAdmissionInput,
|
|
23
24
|
RuntimeSubmissionAdmissionResult,
|
|
24
|
-
} from "../tools/subagent
|
|
25
|
+
} from "../tools/subagent/authority";
|
|
25
26
|
|
|
26
27
|
// #region Workspace 端口
|
|
27
28
|
|
|
@@ -669,16 +670,25 @@ export interface RuntimeScheduleAgentSummary {
|
|
|
669
670
|
* 让 Runtime 通过 Host 管理当前用户的定时任务。
|
|
670
671
|
*
|
|
671
672
|
* @remarks
|
|
672
|
-
*
|
|
673
|
+
* Host 提供准备与提交操作;Runtime 在现有持久化审批中固定候选并等待用户确认。
|
|
673
674
|
*
|
|
674
|
-
*
|
|
675
|
+
* 任务事实、候选版本、授权检查和保存幂等由 Host 持有,不存放凭据。
|
|
675
676
|
*/
|
|
677
|
+
export interface RuntimeScheduleConfirmationPort {
|
|
678
|
+
/** Read-only preparation; bind the full candidate and authorization to this stable intent. */
|
|
679
|
+
prepare(request: RuntimeScheduleUpdate & { intentId: string; id?: string }): Promise<RuntimeSchedulePreparation>;
|
|
680
|
+
/** Atomically check candidate/version, live authorization and quotas. Replay must return the same task. */
|
|
681
|
+
commit(prepared: RuntimeSchedulePreparation, context: { intentId: string; signal: AbortSignal }): Promise<{ id: string }>;
|
|
682
|
+
}
|
|
683
|
+
|
|
676
684
|
export interface RuntimeSchedulePort {
|
|
685
|
+
/** Required for chat creation/editing. Legacy management callers retain their CRUD contract. */
|
|
686
|
+
confirmation?: RuntimeScheduleConfirmationPort;
|
|
677
687
|
/**
|
|
678
688
|
* 创建一条定时任务并返回它的 ID。
|
|
679
689
|
*
|
|
680
690
|
* @remarks
|
|
681
|
-
* `schedule`
|
|
691
|
+
* 保留给既有宿主管理调用者;聊天 `schedule` 只经 confirmation.commit 保存。
|
|
682
692
|
*
|
|
683
693
|
* Host 在该边界内绑定用户与会话,Runtime 不携带业务归属 ID。
|
|
684
694
|
*/
|
|
@@ -940,6 +950,8 @@ export interface RuntimeBrowserPort {
|
|
|
940
950
|
export type RuntimeModelProtocol =
|
|
941
951
|
| "openai-chat"
|
|
942
952
|
| "openrouter-messages"
|
|
953
|
+
| "openrouter-chat"
|
|
954
|
+
| "openrouter-responses"
|
|
943
955
|
| "anthropic-messages"
|
|
944
956
|
| "google-generative-ai"
|
|
945
957
|
| "openai-codex-responses";
|
|
@@ -953,6 +965,31 @@ export type RuntimeModelProtocol =
|
|
|
953
965
|
*
|
|
954
966
|
* 凭据只留在 Port 对象,不进入 `RuntimeProfile` 或持久状态;术语见 `../index.ts`。
|
|
955
967
|
*/
|
|
968
|
+
export type RuntimeModelThinkingLevel =
|
|
969
|
+
| "off"
|
|
970
|
+
| "minimal"
|
|
971
|
+
| "low"
|
|
972
|
+
| "medium"
|
|
973
|
+
| "high"
|
|
974
|
+
| "xhigh"
|
|
975
|
+
| "max";
|
|
976
|
+
|
|
977
|
+
export interface RuntimeModelMetadata {
|
|
978
|
+
readonly name: string;
|
|
979
|
+
readonly reasoning: boolean;
|
|
980
|
+
readonly contextWindow: number;
|
|
981
|
+
readonly maxTokens: number;
|
|
982
|
+
readonly cost: Readonly<{
|
|
983
|
+
input: number;
|
|
984
|
+
output: number;
|
|
985
|
+
cacheRead: number;
|
|
986
|
+
cacheWrite: number;
|
|
987
|
+
}>;
|
|
988
|
+
readonly thinkingLevelMap?: Readonly<
|
|
989
|
+
Partial<Record<RuntimeModelThinkingLevel, string | null>>
|
|
990
|
+
>;
|
|
991
|
+
}
|
|
992
|
+
|
|
956
993
|
export interface RuntimeModelEndpoint {
|
|
957
994
|
protocol: RuntimeModelProtocol;
|
|
958
995
|
/** Resolved credential; never enters RuntimeProfile or persisted state. */
|
|
@@ -967,6 +1004,9 @@ export interface RuntimeModelEndpoint {
|
|
|
967
1004
|
>;
|
|
968
1005
|
/** OpenRouter upstream provider pins keyed by model ID; pinned requests never fall back. */
|
|
969
1006
|
openRouterProviderPins?: Readonly<Record<string, string>>;
|
|
1007
|
+
/** OpenRouter provider ordering; omitted keeps OpenRouter's default routing. */
|
|
1008
|
+
openRouterProviderSort?: "price" | "throughput" | "latency";
|
|
1009
|
+
modelMetadata?: Readonly<Record<string, RuntimeModelMetadata>>;
|
|
970
1010
|
}
|
|
971
1011
|
|
|
972
1012
|
/**
|
|
@@ -1020,6 +1060,16 @@ export interface RuntimePlatformPort {
|
|
|
1020
1060
|
requiredExecutionLevel: ExecutionLevel;
|
|
1021
1061
|
signal: AbortSignal;
|
|
1022
1062
|
}): Promise<void>;
|
|
1063
|
+
/**
|
|
1064
|
+
* Match a pinned scheduled-task grant against the concrete Tool operation
|
|
1065
|
+
* and recheck the Host-owned live account authorization.
|
|
1066
|
+
*
|
|
1067
|
+
* This callback must fail closed by throwing a user-safe, specific reason.
|
|
1068
|
+
* It is called before dispatch and again at the effect boundary so a grant
|
|
1069
|
+
* revocation cannot be hidden by an earlier decision.
|
|
1070
|
+
*/
|
|
1071
|
+
/** @deprecated Scheduled execution is authorized locally by execution level. */
|
|
1072
|
+
authorizeUnattendedExecution?(request: unknown): Promise<void>;
|
|
1023
1073
|
}
|
|
1024
1074
|
|
|
1025
1075
|
/**
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { sha256Hex } from "../lib/artifacts";
|
|
2
1
|
import type {
|
|
3
2
|
RuntimeBindings,
|
|
4
3
|
RuntimeGatewaySession,
|
|
@@ -9,7 +8,6 @@ import type {
|
|
|
9
8
|
RuntimeExtensionPermissions,
|
|
10
9
|
} from "../context/extension/contracts";
|
|
11
10
|
import type { RuntimeProfile } from "./profile";
|
|
12
|
-
import type { ExecutionLevel } from "../lib/execution-level";
|
|
13
11
|
import type { RuntimeSnapshot } from "./assembler";
|
|
14
12
|
import type { FinalizedPiToolSurface, PiRuntimeAssembly } from "../context";
|
|
15
13
|
import {
|
|
@@ -28,29 +26,8 @@ import {
|
|
|
28
26
|
type PiToolCandidate,
|
|
29
27
|
} from "../tools";
|
|
30
28
|
|
|
31
|
-
export interface RuntimeAssemblyPin {
|
|
32
|
-
readonly revision: string;
|
|
33
|
-
readonly descriptor: string;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** A saved pin is reusable only with its original Runtime key and intact descriptor. */
|
|
37
|
-
export async function validateRuntimeAssemblyPin(
|
|
38
|
-
runtimeKey: string,
|
|
39
|
-
pin: RuntimeAssemblyPin,
|
|
40
|
-
): Promise<boolean> {
|
|
41
|
-
if (!runtimeKey) {
|
|
42
|
-
throw new Error("Cannot safely recover a pinned Submission without its original Runtime key");
|
|
43
|
-
}
|
|
44
|
-
if (!pin.revision && !pin.descriptor) return false;
|
|
45
|
-
if (!pin.revision || !pin.descriptor) throw new Error("Submission assembly pin is incomplete");
|
|
46
|
-
if (pin.revision !== await sha256Hex(pin.descriptor)) {
|
|
47
|
-
throw new Error("Pinned Runtime assembly descriptor is invalid");
|
|
48
|
-
}
|
|
49
|
-
return true;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
29
|
/**
|
|
53
|
-
*
|
|
30
|
+
* 本文件负责准备当前 Pi 的扩展、工具与系统上下文。
|
|
54
31
|
*
|
|
55
32
|
* @remarks
|
|
56
33
|
* 核心术语见本目录入口 `./index.ts`,这里不重复定义。
|
|
@@ -93,8 +70,8 @@ interface PreparePiAssemblyOptions {
|
|
|
93
70
|
) => Fetcher;
|
|
94
71
|
}
|
|
95
72
|
|
|
96
|
-
//
|
|
97
|
-
// preparePiRuntime 读取工具与降级,
|
|
73
|
+
// 暴露后续准备和执行阶段会读取的扩展装配结果。
|
|
74
|
+
// preparePiRuntime 读取工具与降级,assembleCurrentPiContext 读取上下文贡献。
|
|
98
75
|
// 访问器直接代理扩展装配,避免维护会漂移的副本。
|
|
99
76
|
interface PreparedPiAssembly {
|
|
100
77
|
readonly loaded: readonly PiLoadedExtension[];
|
|
@@ -133,10 +110,10 @@ export interface PreparePiRuntimeOptions {
|
|
|
133
110
|
}
|
|
134
111
|
|
|
135
112
|
/**
|
|
136
|
-
*
|
|
113
|
+
* 表示已准备好供当前执行使用的 Pi 配置。
|
|
137
114
|
*
|
|
138
115
|
* @remarks
|
|
139
|
-
* Runtime
|
|
116
|
+
* Runtime 在配置完成后保存这个句柄,并在创建 Turn 时传回。
|
|
140
117
|
*
|
|
141
118
|
* 公开形状只给出版本描述和加载降级,调用方不会直接拿到可变的装配状态。
|
|
142
119
|
*/
|
|
@@ -147,21 +124,25 @@ export interface PreparedPiRuntime {
|
|
|
147
124
|
}
|
|
148
125
|
|
|
149
126
|
/**
|
|
150
|
-
*
|
|
127
|
+
* 当前执行切片读取系统上下文所需的值。
|
|
151
128
|
*
|
|
152
129
|
* @remarks
|
|
153
|
-
* Runtime
|
|
130
|
+
* Runtime 在打开或恢复 Harness 前把它交给 `HarnessRuntimeConfig.harnessInputs`。
|
|
154
131
|
*
|
|
155
132
|
* 扩展没有可读上下文时不需要读取函数,所以该端口保持可选。
|
|
156
133
|
*/
|
|
157
|
-
export interface
|
|
134
|
+
export interface CurrentPiContextOptions {
|
|
158
135
|
readonly prepared: PreparedPiRuntime;
|
|
159
|
-
readonly baseRevision: string;
|
|
160
136
|
/**
|
|
161
|
-
*
|
|
137
|
+
* Whether this Submission may inherit automatic hot and cold Memory context.
|
|
138
|
+
* Scheduled task input is intentionally isolated from those sources.
|
|
139
|
+
*/
|
|
140
|
+
readonly includeMemory?: boolean;
|
|
141
|
+
/**
|
|
142
|
+
* 读取一个扩展对当前系统提示词的上下文贡献。
|
|
162
143
|
*
|
|
163
144
|
* @remarks
|
|
164
|
-
*
|
|
145
|
+
* 每次装配 Harness 输入时为已加载扩展读取当前上下文。
|
|
165
146
|
*
|
|
166
147
|
* 本模块不持有扩展上下文存储,所以读取端口必须留在 Host。
|
|
167
148
|
*/
|
|
@@ -170,40 +151,6 @@ export interface PinPiRuntimeOptions {
|
|
|
170
151
|
) => Promise<string | null>;
|
|
171
152
|
}
|
|
172
153
|
|
|
173
|
-
/**
|
|
174
|
-
* 返回已经固定到一次提交的描述和上下文降级。
|
|
175
|
-
*
|
|
176
|
-
* @remarks
|
|
177
|
-
* Runtime 在准入时持久化描述,并在创建 Turn 时传回。
|
|
178
|
-
*
|
|
179
|
-
* 固定这些值可让恢复继续使用当时已经准入的配置。
|
|
180
|
-
*/
|
|
181
|
-
export interface PinnedPiRuntime {
|
|
182
|
-
readonly descriptor: string;
|
|
183
|
-
readonly degradations: readonly RuntimeDegradation[];
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* 描述一条已存提交可以恢复到哪份 Pi 配置。
|
|
188
|
-
*
|
|
189
|
-
* @remarks
|
|
190
|
-
* `HarnessRuntimeConfig.harnessInputs` 在打开或恢复 operation 前读取这个 JSON 结构。
|
|
191
|
-
*
|
|
192
|
-
* 基础版本作为准入时元数据保留,创建 Turn 时不与当前 Runtime 比较。
|
|
193
|
-
*/
|
|
194
|
-
export interface PinnedPiRuntimeDescriptor {
|
|
195
|
-
readonly version: 1;
|
|
196
|
-
readonly baseRevision: string;
|
|
197
|
-
readonly model: string;
|
|
198
|
-
readonly provider: string;
|
|
199
|
-
readonly thinking: RuntimeSnapshot["pi"]["thinkingLevel"];
|
|
200
|
-
readonly systemPrompt: string;
|
|
201
|
-
readonly executionLevel: ExecutionLevel;
|
|
202
|
-
readonly deny: readonly string[];
|
|
203
|
-
readonly tools: readonly ReturnType<typeof describeTools>[number][];
|
|
204
|
-
readonly [key: string]: unknown;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
154
|
/**
|
|
208
155
|
* 保存创建 Pi Turn 所需的内部准备结果。
|
|
209
156
|
*
|
|
@@ -249,9 +196,20 @@ function describeTools(candidates: readonly PiToolCandidate[]) {
|
|
|
249
196
|
description: candidate.tool.description ?? candidate.tool.label,
|
|
250
197
|
parameters: candidate.tool.parameters,
|
|
251
198
|
requiredExecutionLevel: candidate.requiredExecutionLevel,
|
|
199
|
+
...(candidate.confirmation ? { confirmation: true } : {}),
|
|
252
200
|
...(candidate.alwaysRequiresApproval
|
|
253
201
|
? { alwaysRequiresApproval: true }
|
|
254
202
|
: {}),
|
|
203
|
+
...(candidate.unattendedExecution
|
|
204
|
+
? {
|
|
205
|
+
unattendedExecution: {
|
|
206
|
+
capability: candidate.unattendedExecution.capability,
|
|
207
|
+
operation: candidate.unattendedExecution.operation,
|
|
208
|
+
objectConstrained:
|
|
209
|
+
candidate.unattendedExecution.objectForInput !== undefined,
|
|
210
|
+
},
|
|
211
|
+
}
|
|
212
|
+
: {}),
|
|
255
213
|
...(candidate.deferLoading ? { deferLoading: true } : {}),
|
|
256
214
|
...(candidate.source ? { source: candidate.source } : {}),
|
|
257
215
|
retry: piToolRetryPolicy(candidate),
|
|
@@ -267,10 +225,25 @@ function describeRuntime(
|
|
|
267
225
|
candidates: readonly PiToolCandidate[],
|
|
268
226
|
loadedExtensions: readonly PiLoadedExtension[],
|
|
269
227
|
): string {
|
|
228
|
+
const model = snapshot.pi.model;
|
|
229
|
+
const openRouterRouting = model.compat && "openRouterRouting" in model.compat
|
|
230
|
+
? model.compat.openRouterRouting
|
|
231
|
+
: undefined;
|
|
270
232
|
return JSON.stringify({
|
|
271
233
|
version: 1,
|
|
272
|
-
model:
|
|
273
|
-
provider:
|
|
234
|
+
model: model.id,
|
|
235
|
+
provider: model.provider,
|
|
236
|
+
modelConfig: {
|
|
237
|
+
api: model.api,
|
|
238
|
+
name: model.name,
|
|
239
|
+
reasoning: model.reasoning,
|
|
240
|
+
input: model.input,
|
|
241
|
+
contextWindow: model.contextWindow,
|
|
242
|
+
maxTokens: model.maxTokens,
|
|
243
|
+
cost: model.cost,
|
|
244
|
+
...(model.thinkingLevelMap ? { thinkingLevelMap: model.thinkingLevelMap } : {}),
|
|
245
|
+
...(openRouterRouting ? { openRouterRouting } : {}),
|
|
246
|
+
},
|
|
274
247
|
thinking: snapshot.pi.thinkingLevel,
|
|
275
248
|
systemPrompt: snapshot.pi.systemPrompt,
|
|
276
249
|
executionLevel: snapshot.profile.executionLevel,
|
|
@@ -314,7 +287,7 @@ class PreparedRuntime implements PreparedPiRuntime {
|
|
|
314
287
|
) {}
|
|
315
288
|
|
|
316
289
|
// 在调用方证明适配器身份后返回内部准备状态。
|
|
317
|
-
// readPreparedPiRuntime
|
|
290
|
+
// readPreparedPiRuntime 在创建 Turn 前调用它。
|
|
318
291
|
// 公开接口没有可信的来源字段,所以这里必须比较对象身份。
|
|
319
292
|
read(owner: object): PreparedPiRuntimeState {
|
|
320
293
|
if (owner !== this.owner) {
|
|
@@ -330,7 +303,7 @@ class PreparedRuntime implements PreparedPiRuntime {
|
|
|
330
303
|
* 为创建它的 HarnessRuntimeConfig 打开准备句柄。
|
|
331
304
|
*
|
|
332
305
|
* @remarks
|
|
333
|
-
*
|
|
306
|
+
* 创建 Turn 前调用它,读取快照、装配结果或工具候选。
|
|
334
307
|
*
|
|
335
308
|
* 具体类检查与 owner 检查一起拒绝伪造句柄和跨适配器复用。
|
|
336
309
|
*/
|
|
@@ -344,42 +317,6 @@ export function readPreparedPiRuntime(
|
|
|
344
317
|
return prepared.read(owner);
|
|
345
318
|
}
|
|
346
319
|
|
|
347
|
-
/**
|
|
348
|
-
* 读取已存的固定描述。
|
|
349
|
-
*
|
|
350
|
-
* @remarks
|
|
351
|
-
* `HarnessRuntimeConfig.harnessInputs` 在新建或恢复 Pi operation 前调用它。
|
|
352
|
-
*
|
|
353
|
-
* Prepared Runtime 提供当前执行能力,descriptor 仅保留 Submission 固定的 Turn 字段。
|
|
354
|
-
*/
|
|
355
|
-
export function readPinnedPiRuntime(
|
|
356
|
-
prepared: PreparedPiRuntime,
|
|
357
|
-
owner: object,
|
|
358
|
-
descriptorBody: string,
|
|
359
|
-
): {
|
|
360
|
-
readonly state: PreparedPiRuntimeState;
|
|
361
|
-
readonly descriptor: PinnedPiRuntimeDescriptor;
|
|
362
|
-
} {
|
|
363
|
-
const state = readPreparedPiRuntime(prepared, owner);
|
|
364
|
-
let value: unknown;
|
|
365
|
-
try {
|
|
366
|
-
value = JSON.parse(descriptorBody);
|
|
367
|
-
} catch {
|
|
368
|
-
throw new Error("Pinned Runtime assembly descriptor is invalid");
|
|
369
|
-
}
|
|
370
|
-
if (!value || typeof value !== "object") {
|
|
371
|
-
throw new Error("Pinned Runtime assembly descriptor is invalid");
|
|
372
|
-
}
|
|
373
|
-
const descriptor = value as PinnedPiRuntimeDescriptor;
|
|
374
|
-
if (
|
|
375
|
-
descriptor.version !== 1 ||
|
|
376
|
-
typeof descriptor.systemPrompt !== "string"
|
|
377
|
-
) {
|
|
378
|
-
throw new Error("Pinned Runtime assembly descriptor is invalid");
|
|
379
|
-
}
|
|
380
|
-
return { state, descriptor };
|
|
381
|
-
}
|
|
382
|
-
|
|
383
320
|
// #endregion
|
|
384
321
|
|
|
385
322
|
// #region 扩展与工具装配
|
|
@@ -431,7 +368,7 @@ async function preparePiAssembly(
|
|
|
431
368
|
|
|
432
369
|
// #endregion
|
|
433
370
|
|
|
434
|
-
// #region Runtime
|
|
371
|
+
// #region Runtime 准备与当前上下文
|
|
435
372
|
|
|
436
373
|
/**
|
|
437
374
|
* 为一份已校验的 Runtime 快照准备扩展和工具状态。
|
|
@@ -468,34 +405,33 @@ export async function preparePiRuntime(
|
|
|
468
405
|
}
|
|
469
406
|
|
|
470
407
|
/**
|
|
471
|
-
*
|
|
408
|
+
* 从当前 Runtime 装配模型要用的系统上下文。
|
|
472
409
|
*
|
|
473
410
|
* @remarks
|
|
474
|
-
* Runtime
|
|
411
|
+
* Runtime 每次打开或恢复 Harness 前调用它。
|
|
475
412
|
*
|
|
476
|
-
*
|
|
413
|
+
* 重新读取动态记忆和扩展上下文,不从旧 Submission 描述恢复配置。
|
|
477
414
|
*/
|
|
478
|
-
export async function
|
|
479
|
-
options:
|
|
415
|
+
export async function assembleCurrentPiContext(
|
|
416
|
+
options: CurrentPiContextOptions,
|
|
480
417
|
owner: object,
|
|
481
|
-
): Promise<
|
|
418
|
+
): Promise<{ systemPrompt: string; degradations: readonly RuntimeDegradation[] }> {
|
|
482
419
|
const state = readPreparedPiRuntime(options.prepared, owner);
|
|
483
420
|
const { snapshot, assembly } = state;
|
|
421
|
+
const includeMemory = options.includeMemory !== false;
|
|
484
422
|
const context = await assemblePiSystemContext({
|
|
485
423
|
baseSystemPrompt: snapshot.pi.systemPrompt,
|
|
486
|
-
memory:
|
|
487
|
-
|
|
488
|
-
|
|
424
|
+
memory: includeMemory
|
|
425
|
+
? snapshot.profile.memory
|
|
426
|
+
: { ...snapshot.profile.memory, enabled: false },
|
|
427
|
+
memoryPort: includeMemory ? snapshot.bindings.memory : undefined,
|
|
428
|
+
workspace: includeMemory ? snapshot.bindings.workspace : undefined,
|
|
489
429
|
skills: snapshot.bindings.skills.sources,
|
|
490
430
|
extensionContexts: assembly.context,
|
|
491
431
|
readExtensionContext: options.readExtensionContext,
|
|
492
432
|
});
|
|
493
433
|
return Object.freeze({
|
|
494
|
-
|
|
495
|
-
...JSON.parse(options.prepared.revisionDescriptor),
|
|
496
|
-
systemPrompt: context.systemPrompt,
|
|
497
|
-
baseRevision: options.baseRevision,
|
|
498
|
-
}),
|
|
434
|
+
systemPrompt: context.systemPrompt,
|
|
499
435
|
degradations: context.degradations,
|
|
500
436
|
});
|
|
501
437
|
}
|
|
@@ -17,7 +17,7 @@ export * from "../conversation/message";
|
|
|
17
17
|
export * from "../submission/contracts";
|
|
18
18
|
export * from "../conversation/state";
|
|
19
19
|
export * from "../lib/execution-level";
|
|
20
|
-
export type { WorkspaceRevision, WorkspaceRevisionManifest } from "../tools/workspace
|
|
20
|
+
export type { WorkspaceRevision, WorkspaceRevisionManifest } from "../tools/workspace/versioning";
|
|
21
21
|
export type {
|
|
22
22
|
RuntimeEventConfirmation,
|
|
23
23
|
RuntimeLifecycleFact,
|
|
@@ -27,4 +27,4 @@ export type {
|
|
|
27
27
|
RuntimeSubmissionAdmissionHook,
|
|
28
28
|
RuntimeSubmissionAdmissionInput,
|
|
29
29
|
RuntimeSubmissionAdmissionResult,
|
|
30
|
-
} from "../tools/subagent
|
|
30
|
+
} from "../tools/subagent/authority";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export interface RuntimeConfigUpdateResult<Change> {
|
|
2
2
|
readonly change: Change;
|
|
3
|
-
|
|
3
|
+
/** Deferred changes are persisted but activated at the next execution slice. */
|
|
4
|
+
readonly runtime: "unchanged" | "reloaded" | "deferred" | "reload-failed";
|
|
4
5
|
}
|
package/src/context/assembly.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { estimateStringTokens } from "
|
|
1
|
+
import { estimateStringTokens } from "../lib/token-estimate";
|
|
2
2
|
import type { RuntimeMemoryPort } from "../config/ports";
|
|
3
3
|
import type { RuntimeDegradation } from "../config/degradation";
|
|
4
4
|
import type { RuntimeMemoryProfile } from "../config/profile";
|
|
@@ -12,8 +12,8 @@ import type {
|
|
|
12
12
|
import type { RuntimeDegradation } from "../../config/degradation";
|
|
13
13
|
import { withRuntimeLoadTimeout } from "../../config/runtime-load";
|
|
14
14
|
import { sanitizeExtensionName } from "../../lib/extension-name";
|
|
15
|
-
import type { PiToolCandidate } from "../../tools/
|
|
16
|
-
import { createPiDeclaredToolCandidate } from "../../tools/declared";
|
|
15
|
+
import type { PiToolCandidate } from "../../tools/runtime/contracts";
|
|
16
|
+
import { createPiDeclaredToolCandidate } from "../../tools/adapters/declared";
|
|
17
17
|
|
|
18
18
|
export interface PiExtensionContextContribution {
|
|
19
19
|
readonly extensionName: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
artifactId,
|
|
2
3
|
type ArtifactRef,
|
|
3
4
|
serializeOutput,
|
|
4
5
|
sha256Hex,
|
|
@@ -29,7 +30,7 @@ import {
|
|
|
29
30
|
/**
|
|
30
31
|
* 持久化单个字符串叶子的上限。
|
|
31
32
|
*
|
|
32
|
-
* MUST ≥ 单页 read 的上限(见 `workspace
|
|
33
|
+
* MUST ≥ 单页 read 的上限(见 `tools/workspace/index.ts` 的 `READ_PAGE_MAX_CHARS`),
|
|
33
34
|
* 否则持久记录会比模型当轮看到的内容还少,会话恢复后出现凭空缺页。
|
|
34
35
|
*/
|
|
35
36
|
export const STORAGE_LEAF_MAX_CHARS = 64 * 1024;
|
|
@@ -161,11 +162,26 @@ export async function spillDurableToolOutput(
|
|
|
161
162
|
text,
|
|
162
163
|
ext === "json" ? "application/json" : "text/plain",
|
|
163
164
|
);
|
|
165
|
+
if (!options.workspace.stat || !options.workspace.readFileBytes) {
|
|
166
|
+
throw new Error("Workspace artifact verification is unavailable");
|
|
167
|
+
}
|
|
168
|
+
const stat = await options.workspace.stat(path);
|
|
169
|
+
const expectedBytes = new TextEncoder().encode(text).byteLength;
|
|
170
|
+
if (!stat || stat.type !== "file" || stat.size !== expectedBytes) {
|
|
171
|
+
throw new Error("Workspace artifact failed size verification");
|
|
172
|
+
}
|
|
173
|
+
const stored = await options.workspace.readFileBytes(path);
|
|
174
|
+
if (!stored || new TextDecoder().decode(stored) !== text) {
|
|
175
|
+
throw new Error("Workspace artifact failed content verification");
|
|
176
|
+
}
|
|
164
177
|
return {
|
|
165
178
|
kind: "artifact_ref",
|
|
179
|
+
artifactId: artifactId(hash),
|
|
166
180
|
path,
|
|
167
|
-
bytes:
|
|
168
|
-
hash
|
|
181
|
+
bytes: expectedBytes,
|
|
182
|
+
hash,
|
|
183
|
+
workspaceRevision: stat.contentVersion ?? `${stat.updatedAt}:${stat.size}`,
|
|
184
|
+
availability: "available",
|
|
169
185
|
preview: text.slice(0, PREVIEW_CHARS),
|
|
170
186
|
// 出口指令必须是可执行的:只说“去 read 这个路径”会诱导模型整读,而整读一个
|
|
171
187
|
// 刚刚因为过大被外置的文件毫无意义。这里明确要求分页,并告知 read 会返回
|