@springbrand/agent-runtime 0.2.0-alpha.72 → 0.3.0-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 +7 -7
- package/src/{agent-tool-runtime.ts → adapter/cloudflare/agent-tool.ts} +1 -1
- package/src/adapter/cloudflare/agent.ts +1682 -0
- package/src/{db/index.ts → adapter/cloudflare/database.ts} +18 -55
- package/src/{runtime-agent.ts → adapter/cloudflare/define-agent.ts} +37 -42
- package/src/adapter/cloudflare/dynamic-worker-observability.ts +1 -1
- package/src/adapter/cloudflare/index.ts +18 -0
- package/src/adapter/cloudflare/resources/runtime-resources.ts +4 -4
- package/src/adapter/cloudflare/sandbox/adapter.ts +1 -1
- package/src/adapter/cloudflare/scheduling/schedule-rule.ts +322 -0
- package/src/adapter/cloudflare/scheduling/zoned-cron.ts +11 -6
- package/src/{db → adapter/cloudflare}/schema.ts +28 -80
- package/src/adapter/cloudflare/subagent/definition.ts +63 -33
- package/src/adapter/cloudflare/subagent/runner.ts +174 -120
- package/src/adapter/cloudflare/subagent/tools.ts +13 -14
- package/src/adapter/cloudflare/universal-agent/preparation.ts +7 -7
- package/src/adapter/cloudflare/universal-agent/tools.ts +10 -12
- package/src/adapter/cloudflare/workspace/git-fs.ts +1 -1
- package/src/adapter/cloudflare/workspace/scoped-workspace.ts +1 -1
- package/src/adapter/cloudflare/workspace/version-control.ts +2 -2
- package/src/config/activation.ts +140 -0
- package/src/{runtime-agent-context.ts → config/agent-context.ts} +3 -3
- package/src/{runtime-assembler.ts → config/assembler.ts} +45 -46
- package/src/{kernel/runtime-assembly.ts → config/assembly-projection.ts} +4 -4
- package/src/{pi/assembly/snapshot.ts → config/assembly-snapshot.ts} +6 -6
- package/src/{runtime-definition.ts → config/definition.ts} +13 -13
- package/src/config/harness-runtime.ts +190 -0
- package/src/config/index.ts +14 -0
- package/src/config/model-guidance.ts +21 -0
- package/src/{pi/runtime-adapter/assembly.ts → config/pinning.ts} +60 -19
- package/src/{kernel/bindings.ts → config/ports.ts} +32 -16
- package/src/{kernel → config}/profile.ts +7 -0
- package/src/{kernel → config}/public-contracts.ts +6 -6
- package/src/{kernel → config}/runtime-load.ts +1 -1
- package/src/{pi/assembly/context.ts → context/assembly.ts} +5 -207
- package/src/{pi/assembly/extensions.ts → context/extension/assembly.ts} +5 -5
- package/src/context/extension/index.ts +3 -0
- package/src/context/index.ts +6 -0
- package/src/{layers/context → context/memory}/budget/gate.ts +21 -5
- package/src/conversation/harness-resume.ts +288 -0
- package/src/conversation/harness-stream.ts +99 -0
- package/src/{pi/runtime-adapter/transcript.ts → conversation/history.ts} +206 -233
- package/src/conversation/index.ts +6 -0
- package/src/{pi → conversation}/message/contract.ts +3 -0
- package/src/{pi → conversation}/message/conversion.ts +75 -0
- package/src/{pi → conversation}/message/index.ts +1 -0
- package/src/{pi → conversation}/message/model-input.ts +1 -1
- package/src/{pi → conversation}/message/projection.ts +113 -30
- package/src/{db/message-ui.repo.ts → conversation/repository.ts} +4 -0
- package/src/conversation/state.ts +196 -0
- package/src/harness/index.ts +7 -0
- package/src/harness/session-harness.ts +562 -0
- package/src/harness/submission-operation.ts +49 -0
- package/src/index.ts +38 -43
- package/src/lib/artifacts.ts +18 -0
- package/src/lib/execution-level.ts +13 -0
- package/src/lib/mcp.ts +1 -1
- package/src/lib/prompt.ts +7 -6
- package/src/lib/token-estimate.ts +8 -0
- package/src/{pi/runtime-adapter/models.ts → models/index.ts} +64 -17
- package/src/{pi/turn/tool-recovery.ts → session/cloudflare/legacy-tool-recovery.ts} +33 -525
- package/src/{pi/session → session/cloudflare}/migration.ts +404 -14
- package/src/{pi/session → session/cloudflare}/storage.ts +8 -36
- package/src/session/index.ts +39 -0
- package/src/skills/springbrand-worker-website/index.ts +1 -1
- package/src/submission/admission.ts +286 -0
- package/src/{kernel/receipts.ts → submission/contracts.ts} +56 -2
- package/src/submission/delivery.ts +212 -0
- package/src/submission/finalization.ts +111 -0
- package/src/submission/index.ts +9 -0
- package/src/{kernel/submission-lifecycle.ts → submission/lifecycle.ts} +41 -28
- package/src/{db/submission.repo.ts → submission/repository.ts} +117 -114
- package/src/submission/steer-delivery.ts +167 -0
- package/src/{db/steer.repo.ts → submission/steer-repository.ts} +27 -5
- package/src/submission/unattended.ts +40 -0
- package/src/telemetry/contract.ts +12 -0
- package/src/telemetry/coordinator.ts +65 -0
- package/src/telemetry/delivery.ts +2 -2
- package/src/telemetry/index.ts +5 -0
- package/src/{model-usage.ts → telemetry/model-usage.ts} +1 -1
- package/src/telemetry/recorder.ts +1 -1
- package/src/telemetry/runtime-telemetry.ts +12 -0
- package/src/{kernel/durable-lifecycle.ts → telemetry/subagent-lifecycle.ts} +1 -1
- package/src/telemetry/turn-events.ts +279 -0
- package/src/tools/README.md +44 -0
- package/src/{pi/tool/ai-adapter.ts → tools/adapters/ai-to-pi.ts} +6 -9
- package/src/{pi/tool → tools/adapters}/declared.ts +6 -2
- package/src/{pi/tool/nested-tools.ts → tools/adapters/pi-to-ai.ts} +2 -2
- package/src/tools/assistant/ask-user.ts +317 -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/{pi/tool → tools/assistant}/time.ts +1 -1
- package/src/{pi/tool/core-host.ts → tools/codemode/adapter.ts} +50 -49
- package/src/{pi/tool/core.ts → tools/codemode/index.ts} +35 -91
- package/src/tools/codemode/workspace-connector.ts +198 -0
- package/src/tools/extension/index.ts +42 -0
- package/src/tools/index.ts +32 -0
- package/src/{pi/tool → tools/mcp}/gateway.ts +19 -19
- package/src/{pi/tool/mcp.ts → tools/mcp/index.ts} +5 -5
- package/src/tools/runtime/approval/index.ts +1 -0
- package/src/{db/approval.repo.ts → tools/runtime/approval/repository.ts} +22 -41
- package/src/tools/runtime/compiler.ts +264 -0
- package/src/tools/runtime/contracts.ts +117 -0
- package/src/tools/runtime/decision-gate.ts +337 -0
- package/src/tools/runtime/human-decisions.ts +127 -0
- package/src/tools/runtime/interaction/index.ts +1 -0
- package/src/{db/interaction.repo.ts → tools/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/{kernel/submission-authority.ts → tools/subagent/authority.ts} +31 -31
- package/src/{pi/tool/subagent.ts → tools/subagent/index.ts} +33 -36
- package/src/{db/agent-tool.repo.ts → tools/subagent/repository.ts} +1 -1
- package/src/{kernel/subagent-runtime.ts → tools/subagent/runtime.ts} +1 -1
- package/src/tools/subagent/temporary/approvals.ts +123 -0
- package/src/{layers/orchestration/temporary-agent/core.ts → tools/subagent/temporary/coordinator.ts} +41 -49
- package/src/tools/subagent/temporary/core.ts +53 -0
- package/src/{layers/orchestration/temporary-agent → tools/subagent/temporary}/runner.ts +1 -1
- package/src/{layers/orchestration/temporary-agent → tools/subagent/temporary}/workspace.ts +1 -4
- package/src/{pi/tool/web-fetch.ts → tools/web/fetch.ts} +4 -13
- package/src/tools/web/index.ts +2 -0
- package/src/tools/web/search/api.ts +1320 -0
- package/src/tools/web/search/index.ts +2 -0
- package/src/{pi/tool/web-search/web-search.ts → tools/web/search/search.ts} +5 -7
- package/src/{pi/tool/workspace-sandbox.ts → tools/workspace/index.ts} +12 -272
- package/src/{pi/tool/workspace-revision.ts → tools/workspace/revision.ts} +2 -2
- package/src/db/milestone.repo.ts +0 -104
- package/src/db/settlement.repo.ts +0 -104
- package/src/kernel/approval-lifecycle.ts +0 -638
- package/src/kernel/interaction-lifecycle.ts +0 -433
- package/src/kernel/recoverable-chat-agent.ts +0 -1020
- package/src/kernel/state.ts +0 -91
- package/src/pi/assembly/index.ts +0 -19
- package/src/pi/runtime-adapter/execution.ts +0 -1163
- package/src/pi/runtime-adapter/index.ts +0 -293
- package/src/pi/runtime-adapter/recovery.ts +0 -982
- package/src/pi/session/index.ts +0 -24
- package/src/pi/tool/base.ts +0 -550
- package/src/pi/tool/compiler.ts +0 -483
- package/src/pi/tool/index.ts +0 -38
- package/src/pi/tool/schedule.ts +0 -261
- package/src/pi/tool/skill.ts +0 -565
- package/src/pi/tool/web-search/api.ts +0 -1318
- package/src/pi/tool/web-search/index.ts +0 -2
- package/src/pi/tool/workspace-state-connector.ts +0 -146
- package/src/pi/turn/approval.ts +0 -181
- package/src/pi/turn/index.ts +0 -82
- package/src/pi/turn/interaction.ts +0 -181
- package/src/runtime.ts +0 -4760
- package/src/{kernel/runtime-assembly-view.ts → config/assembly-view.ts} +0 -0
- package/src/{kernel → config}/degradation.ts +0 -0
- package/src/{kernel → config}/runtime-config.ts +0 -0
- package/src/{kernel/extensions.ts → context/extension/contracts.ts} +0 -0
- package/src/{db/ext-context.repo.ts → context/extension/repository.ts} +0 -0
- package/src/{pi/runtime-adapter/openrouter-messages.ts → models/openrouter/messages.ts} +0 -0
- package/src/{pi/runtime-adapter → models/openrouter}/test-fixtures/openrouter-tool-search.sse +0 -0
- package/src/{db/submission-admission.repo.ts → submission/admission-repository.ts} +0 -0
- package/src/{db/telemetry-outbox.repo.ts → telemetry/repository.ts} +0 -0
- package/src/{db/runtime-event-outbox.repo.ts → telemetry/runtime-event-repository.ts} +0 -0
- package/src/{layers/orchestration/subagents/agent-types → tools/subagent/types}/contract.ts +0 -0
- package/src/{layers/orchestration/subagents/agent-types → tools/subagent/types}/extract/index.ts +0 -0
- package/src/{layers/orchestration/subagents/agent-types → tools/subagent/types}/fanout/index.ts +0 -0
- package/src/{layers/orchestration/subagents/agent-types → tools/subagent/types}/registry.ts +1 -1
- /package/src/{workspace-versioning.ts → tools/workspace/versioning.ts} +0 -0
package/src/index.ts
CHANGED
|
@@ -9,14 +9,13 @@
|
|
|
9
9
|
* - `Session` 是本项目的聊天会话边界,由一个 `UniversalAgent` facet 承载。
|
|
10
10
|
* - `Turn` 是 Session 中从一次提示被接纳到输出终态的一次执行。
|
|
11
11
|
* - `Host` 是承载 Runtime 的 Cloudflare Agent,并负责提供生命周期、存储和网络边界。
|
|
12
|
-
* - `
|
|
13
|
-
* - `
|
|
12
|
+
* - `Harness` 是 Pi 提供的唯一模型、Tool 与 canonical transcript 执行引擎。
|
|
13
|
+
* - `Cloudflare adapter` 只连接 Durable Object 生命周期、RPC 和 Harness。
|
|
14
14
|
* - `Workspace` 是 Tool 可以读取或修改的受控文件系统视图。
|
|
15
15
|
* - `Memory` 是可跨 Turn 读取或写入的长期上下文能力。
|
|
16
16
|
* - `Tool` 是模型在 Turn 中可以调用的一项受控能力。
|
|
17
17
|
* - `Tool Candidate` 是尚未完成治理和编译的内部 Tool 定义。
|
|
18
|
-
* - `Tool
|
|
19
|
-
* - `Governance` 是对 Tool 可见性、审批和执行条件的集中约束。
|
|
18
|
+
* - `Tool decision` 是宿主持久化的审批或交互事实;Pi 仍保存执行位置与 Tool 结果。
|
|
20
19
|
* - `Artifact` 是 Runtime 保存并对外引用的结构化执行产物。
|
|
21
20
|
* - `Extension` 是 Pi 在装配期加载、并在 Turn 中参与执行的扩展模块。
|
|
22
21
|
* - `SubAgent` 是由父 Agent 发起、但拥有独立执行上下文的子任务执行者。
|
|
@@ -38,21 +37,21 @@
|
|
|
38
37
|
* Snapshot 不允许替换已选集合,但不承诺把每个 Port 的内部对象深冻结。
|
|
39
38
|
*
|
|
40
39
|
* 正常调用顺序是 `assemble → validate → freeze → guard → commit`。
|
|
41
|
-
*
|
|
40
|
+
* Config 装配独占跨能力校验,Harness 独占执行状态提交。
|
|
42
41
|
*
|
|
43
42
|
* @packageDocumentation
|
|
44
43
|
*/
|
|
45
|
-
export * from "./
|
|
46
|
-
export * from "./
|
|
47
|
-
export * from "./
|
|
48
|
-
export * from "./
|
|
49
|
-
export * from "./
|
|
44
|
+
export * from "./config/ports";
|
|
45
|
+
export * from "./context/extension/contracts";
|
|
46
|
+
export * from "./config/profile";
|
|
47
|
+
export * from "./submission/contracts";
|
|
48
|
+
export * from "./config/runtime-config";
|
|
50
49
|
export * from "./telemetry";
|
|
51
|
-
export type { RuntimeAssemblyView } from "./
|
|
52
|
-
export * from "./
|
|
53
|
-
export type { ToolInteractionResponsePreparation } from "./
|
|
54
|
-
export * from "./
|
|
55
|
-
export * from "./workspace
|
|
50
|
+
export type { RuntimeAssemblyView } from "./config/assembly-view";
|
|
51
|
+
export * from "./adapter/cloudflare/define-agent";
|
|
52
|
+
export type { ToolInteractionResponsePreparation } from "./adapter/cloudflare/agent";
|
|
53
|
+
export * from "./conversation/state";
|
|
54
|
+
export * from "./tools/workspace/versioning";
|
|
56
55
|
export * from "./lib/execution-level";
|
|
57
56
|
export type {
|
|
58
57
|
RuntimeAssemblyInput,
|
|
@@ -61,8 +60,8 @@ export type {
|
|
|
61
60
|
RuntimeProfileContribution,
|
|
62
61
|
RuntimeSkillContribution,
|
|
63
62
|
RuntimeToolSurfacePolicy,
|
|
64
|
-
} from "./
|
|
65
|
-
export { assembleRuntimeSnapshot } from "./
|
|
63
|
+
} from "./config/assembler";
|
|
64
|
+
export { assembleRuntimeSnapshot } from "./config/assembler";
|
|
66
65
|
export type {
|
|
67
66
|
ResolvedConnectors,
|
|
68
67
|
ResolvedResources,
|
|
@@ -71,7 +70,7 @@ export type {
|
|
|
71
70
|
RuntimeSkillBodyTransform,
|
|
72
71
|
RuntimeToolBindings,
|
|
73
72
|
ToolAssemblyResult,
|
|
74
|
-
} from "./
|
|
73
|
+
} from "./config/definition";
|
|
75
74
|
export type { ModelOption } from "./lib/model-catalog";
|
|
76
75
|
export {
|
|
77
76
|
assembleSubagentPrompt,
|
|
@@ -85,66 +84,62 @@ export type {
|
|
|
85
84
|
} from "./lib/host-actions";
|
|
86
85
|
export {
|
|
87
86
|
AGENT_TYPES,
|
|
88
|
-
} from "./
|
|
87
|
+
} from "./tools/subagent/types/registry";
|
|
89
88
|
export type {
|
|
90
89
|
AgentType,
|
|
91
|
-
} from "./
|
|
92
|
-
export { withProviderRetry } from "./pi/runtime-adapter";
|
|
93
|
-
export { compilePiTools } from "./pi/tool";
|
|
90
|
+
} from "./tools/subagent/types/contract";
|
|
94
91
|
export type {
|
|
95
|
-
CompilePiToolsOptions,
|
|
96
92
|
PiToolCandidate,
|
|
97
|
-
SettledPiToolCall,
|
|
98
93
|
ToolExposureMode,
|
|
99
|
-
} from "./
|
|
100
|
-
export { basePiToolCandidates } from "./
|
|
101
|
-
export { createPiDeclaredToolCandidate } from "./
|
|
94
|
+
} from "./tools";
|
|
95
|
+
export { basePiToolCandidates } from "./tools";
|
|
96
|
+
export { createPiDeclaredToolCandidate } from "./tools";
|
|
102
97
|
export type {
|
|
103
98
|
PiDeclaredTool,
|
|
104
99
|
PiDeclaredToolCallContext,
|
|
105
100
|
PiDeclaredToolPolicy,
|
|
106
|
-
} from "./
|
|
107
|
-
export { memoryPiToolCandidate } from "./
|
|
108
|
-
export { GET_TIME_TOOL_NAME, getTimePiToolCandidate } from "./
|
|
109
|
-
export { schedulePiToolCandidates } from "./
|
|
101
|
+
} from "./tools";
|
|
102
|
+
export { memoryPiToolCandidate } from "./tools";
|
|
103
|
+
export { GET_TIME_TOOL_NAME, getTimePiToolCandidate } from "./tools";
|
|
104
|
+
export { schedulePiToolCandidates } from "./tools";
|
|
110
105
|
export {
|
|
111
106
|
sandboxPiToolCandidates,
|
|
112
107
|
workspaceRevisionPiToolCandidate,
|
|
113
108
|
workspacePiToolCandidates,
|
|
114
|
-
} from "./
|
|
115
|
-
export { subagentPiToolCandidates } from "./
|
|
116
|
-
export { skillPiToolCandidates } from "./
|
|
117
|
-
export type { PiSkillBinding } from "./
|
|
109
|
+
} from "./tools";
|
|
110
|
+
export { subagentPiToolCandidates } from "./tools";
|
|
111
|
+
export { skillPiToolCandidates } from "./tools";
|
|
112
|
+
export type { PiSkillBinding } from "./tools";
|
|
118
113
|
export {
|
|
119
114
|
BROWSER_EXECUTE_TOOL_NAME,
|
|
120
115
|
browserExecutionPiToolCandidate,
|
|
121
116
|
codeExecutionPiToolCandidate,
|
|
122
|
-
} from "./
|
|
117
|
+
} from "./tools";
|
|
123
118
|
export {
|
|
124
119
|
createBrowserExecutionFactory,
|
|
125
120
|
createWorkspaceCodeExecutionFactory,
|
|
126
|
-
} from "./
|
|
121
|
+
} from "./tools";
|
|
127
122
|
export {
|
|
128
123
|
assemblePiExtensions,
|
|
129
124
|
loadPiExtension,
|
|
130
|
-
} from "./
|
|
125
|
+
} from "./context";
|
|
131
126
|
export type {
|
|
132
127
|
TemporaryAgentApprovalDecision,
|
|
133
128
|
TemporaryAgentApprovalRequest,
|
|
134
129
|
TemporaryAgentLaunch,
|
|
135
130
|
TemporaryAgentRequest,
|
|
136
131
|
TemporaryAgentRunContext,
|
|
137
|
-
} from "./
|
|
138
|
-
export { TEMPORARY_AGENT_LAUNCH_KEY } from "./
|
|
132
|
+
} from "./tools/subagent/temporary/core";
|
|
133
|
+
export { TEMPORARY_AGENT_LAUNCH_KEY } from "./tools/subagent/temporary/core";
|
|
139
134
|
export {
|
|
140
135
|
temporaryAgentExtensionIsSafe,
|
|
141
136
|
temporaryAgentToolAllowed,
|
|
142
|
-
} from "./
|
|
137
|
+
} from "./tools/subagent/temporary/runner";
|
|
143
138
|
export {
|
|
144
139
|
createTemporaryAgentWorkspace,
|
|
145
|
-
} from "./
|
|
140
|
+
} from "./tools/subagent/temporary/workspace";
|
|
146
141
|
export {
|
|
147
142
|
createPiModels,
|
|
148
143
|
modelRequestUrl,
|
|
149
144
|
resolvePiModel,
|
|
150
|
-
} from "./
|
|
145
|
+
} from "./models";
|
package/src/lib/artifacts.ts
CHANGED
|
@@ -4,9 +4,12 @@
|
|
|
4
4
|
/** Stable narrow reference shared by messages, RPC responses and the UI. */
|
|
5
5
|
export interface ArtifactRef {
|
|
6
6
|
kind: "artifact_ref";
|
|
7
|
+
artifactId: string;
|
|
7
8
|
path: string;
|
|
8
9
|
bytes: number;
|
|
9
10
|
hash: string;
|
|
11
|
+
workspaceRevision: string;
|
|
12
|
+
availability: "available" | "unavailable";
|
|
10
13
|
preview: string;
|
|
11
14
|
note: string;
|
|
12
15
|
}
|
|
@@ -14,6 +17,15 @@ export interface ArtifactRef {
|
|
|
14
17
|
export interface SpillWorkspace {
|
|
15
18
|
/** 把溢出的 Artifact 内容写入指定 Workspace 路径。 */
|
|
16
19
|
writeFile(path: string, content: string, mimeType?: string): Promise<void>;
|
|
20
|
+
/** 写入后验证物理文件,防止只持久化了一个不存在或被截断的引用。 */
|
|
21
|
+
stat?(path: string): Promise<{
|
|
22
|
+
type: "file" | "directory" | "symlink";
|
|
23
|
+
size: number;
|
|
24
|
+
updatedAt: number;
|
|
25
|
+
contentVersion?: string;
|
|
26
|
+
} | null>;
|
|
27
|
+
/** 写入后验证内容摘要;Artifact 全部是 UTF-8 文本。 */
|
|
28
|
+
readFileBytes?(path: string): Promise<Uint8Array | null>;
|
|
17
29
|
}
|
|
18
30
|
|
|
19
31
|
/**
|
|
@@ -33,6 +45,10 @@ export async function sha256Hex(text: string): Promise<string> {
|
|
|
33
45
|
return [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
34
46
|
}
|
|
35
47
|
|
|
48
|
+
function artifactId(hash: string): string {
|
|
49
|
+
return `artifact_${hash.slice(0, 24)}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
36
52
|
/**
|
|
37
53
|
* 把 Tool 结果转成可存储的文本,并选择 `.txt` 或 `.json` 扩展名。
|
|
38
54
|
*
|
|
@@ -52,3 +68,5 @@ export function serializeOutput(output: unknown): { text: string; ext: "txt" | "
|
|
|
52
68
|
return { text: String(output), ext: "txt" };
|
|
53
69
|
}
|
|
54
70
|
}
|
|
71
|
+
|
|
72
|
+
export { artifactId };
|
|
@@ -25,3 +25,16 @@ export function maxExecutionLevel(
|
|
|
25
25
|
)
|
|
26
26
|
]!;
|
|
27
27
|
}
|
|
28
|
+
|
|
29
|
+
/** The most permissive level shared by an Agent and a Scheduled Task ceiling. */
|
|
30
|
+
export function minExecutionLevel(
|
|
31
|
+
left: ExecutionLevel,
|
|
32
|
+
right: ExecutionLevel,
|
|
33
|
+
): ExecutionLevel {
|
|
34
|
+
return EXECUTION_LEVELS[
|
|
35
|
+
Math.min(
|
|
36
|
+
EXECUTION_LEVELS.indexOf(left),
|
|
37
|
+
EXECUTION_LEVELS.indexOf(right),
|
|
38
|
+
)
|
|
39
|
+
]!;
|
|
40
|
+
}
|
package/src/lib/mcp.ts
CHANGED
package/src/lib/prompt.ts
CHANGED
|
@@ -17,9 +17,8 @@ export const PERSONA =
|
|
|
17
17
|
// Names the stable runtime environment.
|
|
18
18
|
export const RUNTIME =
|
|
19
19
|
"Runtime: this agent runs on Cloudflare Workers. When execute is present, its Code Mode Dynamic Worker is your " +
|
|
20
|
-
"instrument — code there runs with
|
|
21
|
-
"
|
|
22
|
-
"requests, parsing a payload, hitting several known endpoints, or computing over a file. Write plain " +
|
|
20
|
+
"instrument — code there runs with your workspace filesystem (state.*) and the tools.* methods listed in its own description. " +
|
|
21
|
+
"Use it for tool composition, parsing a payload, or computing over a file. Write plain " +
|
|
23
22
|
"JavaScript — the sandbox evaluates " +
|
|
24
23
|
"it directly, so TypeScript type annotations (`: number`, `as Type`) are a syntax error, and there " +
|
|
25
24
|
"is no Python interpreter or package manager to invoke. Use the JS/Workers equivalent of what you " +
|
|
@@ -58,8 +57,7 @@ export const TOOLS =
|
|
|
58
57
|
"use state.* for workspace file operations, tools.* for other host capabilities, and sequential calls for repeated or durable operations. " +
|
|
59
58
|
"Top-level-only Tools remain Direct even when called repeatedly. " +
|
|
60
59
|
"For web tasks, use web_search for web discovery, current facts, cited research, " +
|
|
61
|
-
"and public URL analysis
|
|
62
|
-
"API calls, or when web_search cannot retrieve the required content; do not use execute for ordinary web " +
|
|
60
|
+
"and public URL analysis; do not use execute for ordinary web " +
|
|
63
61
|
"searches. When execute is absent, use the actually exposed Direct Tools. When sandbox_* tools are present, use that isolated Linux environment for Python/Node, " +
|
|
64
62
|
"package managers, system commands, builds, tests and background processes; its filesystem is temporary, " +
|
|
65
63
|
"persistent inputs are copied in automatically on first use, /userspace is read-only, and only explicitly " +
|
|
@@ -70,7 +68,10 @@ export const TOOLS =
|
|
|
70
68
|
"prioritize verification, saving durable results, and the final response. " +
|
|
71
69
|
"When related Tool calls can run independently, all are available inside execute, and execute is present, run them inside that execute rather than as parallel top-level calls; " +
|
|
72
70
|
"only independent top-level-only Direct Tools should be issued together in one turn. When you reference " +
|
|
73
|
-
"code, cite it as file_path:line_number."
|
|
71
|
+
"code, cite it as file_path:line_number. " +
|
|
72
|
+
"When schedule tools are available, prepare a standalone Requirement (at most 1000 Unicode characters), a name (at most 50), a time rule and an explicit timezone. Ask for missing information. " +
|
|
73
|
+
"Use local once/daily/weekly rules for new scheduled tasks. The Host prepares the authorization scope and the user must confirm before saving; never claim a task was created before the Tool succeeds. " +
|
|
74
|
+
"One source Chat may create multiple tasks. Before editing, list tasks and use the exact Task ID; ask when the target is ambiguous. Never attach source history or hidden context to the Requirement.";
|
|
74
75
|
|
|
75
76
|
// A real browser is the only way to observe what a page actually does, and the
|
|
76
77
|
// shared failure mode is a browser tool that returns nothing and looks clean.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Conservative token estimate for prompt budgeting, not provider billing. */
|
|
2
|
+
export function estimateStringTokens(text: string): number {
|
|
3
|
+
if (!text) return 0;
|
|
4
|
+
return Math.ceil(Math.max(
|
|
5
|
+
text.length / 4,
|
|
6
|
+
text.split(/\s+/u).filter(Boolean).length * 1.3,
|
|
7
|
+
));
|
|
8
|
+
}
|
|
@@ -48,9 +48,9 @@ import type {
|
|
|
48
48
|
RuntimeModelInputModality,
|
|
49
49
|
RuntimeModelProtocol,
|
|
50
50
|
RuntimeProviderPort,
|
|
51
|
-
} from "
|
|
52
|
-
import { modelInputMessages } from "../message/model-input";
|
|
53
|
-
import { openRouterMessagesApi } from "./openrouter
|
|
51
|
+
} from "../config/ports";
|
|
52
|
+
import { modelInputMessages } from "../conversation/message/model-input";
|
|
53
|
+
import { openRouterMessagesApi } from "./openrouter/messages";
|
|
54
54
|
|
|
55
55
|
const CATALOGS = {
|
|
56
56
|
"openai-chat": openaiProvider().getModels(),
|
|
@@ -60,8 +60,6 @@ const CATALOGS = {
|
|
|
60
60
|
"openai-codex-responses": openaiCodexProvider().getModels(),
|
|
61
61
|
} satisfies Record<RuntimeModelProtocol, readonly Model<Api>[]>;
|
|
62
62
|
|
|
63
|
-
const PROVIDER_MAX_RETRIES = 2;
|
|
64
|
-
|
|
65
63
|
const MESSAGES_HOSTED_INPUT_MODALITIES = ["image", "file"] as const;
|
|
66
64
|
const NO_HOSTED_INPUT_MODALITIES: readonly RuntimeModelInputModality[] = [];
|
|
67
65
|
|
|
@@ -83,7 +81,7 @@ function adapterHostedInputModalities(
|
|
|
83
81
|
// 结构上不可能收敛**,表现为前端 think 转到恢复预算耗尽为止。
|
|
84
82
|
//
|
|
85
83
|
// 调到 240s:比实测静默期留约 7 倍余量。代价是连接真死时单次要等更久,
|
|
86
|
-
//
|
|
84
|
+
// Harness owns bounded provider retries; this timeout only detects a stream that stopped making progress.
|
|
87
85
|
export const MODEL_STREAM_STALL_TIMEOUT_MS = 240_000;
|
|
88
86
|
export const MODEL_STREAM_STALL_MESSAGE =
|
|
89
87
|
`Chat stream stalled: no activity for ${MODEL_STREAM_STALL_TIMEOUT_MS}ms; the turn was aborted by the stall watchdog.`;
|
|
@@ -113,6 +111,12 @@ export type PiGenerationLifecycleEvent =
|
|
|
113
111
|
readonly generationId: string;
|
|
114
112
|
readonly timestamp: number;
|
|
115
113
|
readonly durationMs: number;
|
|
114
|
+
readonly responseHeadersMs?: number;
|
|
115
|
+
readonly firstRawEventMs?: number;
|
|
116
|
+
readonly firstMeaningfulEventMs?: number;
|
|
117
|
+
readonly firstTextEventMs?: number;
|
|
118
|
+
readonly sourceWaitMs?: number;
|
|
119
|
+
readonly forwardingOverheadMs?: number;
|
|
116
120
|
readonly outcome: "success" | "error" | "cancelled";
|
|
117
121
|
readonly stopReason?: string;
|
|
118
122
|
readonly errorName?: string;
|
|
@@ -302,8 +306,12 @@ async function* stopStalledModelStream(
|
|
|
302
306
|
let stalled = false;
|
|
303
307
|
let stallError: ChatStreamStalledError | undefined;
|
|
304
308
|
let idleWaitMs = 0;
|
|
309
|
+
let sourceWaitMs = 0;
|
|
310
|
+
let forwardingOverheadMs = 0;
|
|
311
|
+
let yieldedAt: number | undefined;
|
|
305
312
|
let rawEventCount = 0;
|
|
306
313
|
let meaningfulEventCount = 0;
|
|
314
|
+
let firstTextSeen = false;
|
|
307
315
|
let lastRawEventAt: number | undefined;
|
|
308
316
|
let lastRawEventType: AssistantMessageEvent["type"] | undefined;
|
|
309
317
|
const streamedContent = new Set<string>();
|
|
@@ -344,6 +352,10 @@ async function* stopStalledModelStream(
|
|
|
344
352
|
});
|
|
345
353
|
try {
|
|
346
354
|
while (true) {
|
|
355
|
+
if (yieldedAt !== undefined) {
|
|
356
|
+
forwardingOverheadMs += Math.max(0, Date.now() - yieldedAt);
|
|
357
|
+
yieldedAt = undefined;
|
|
358
|
+
}
|
|
347
359
|
const waitStartedAt = Date.now();
|
|
348
360
|
const nextPromise = iterator
|
|
349
361
|
? iterator.next()
|
|
@@ -375,6 +387,7 @@ async function* stopStalledModelStream(
|
|
|
375
387
|
timer = undefined;
|
|
376
388
|
}
|
|
377
389
|
if (stalled) throw stallError;
|
|
390
|
+
sourceWaitMs += Math.max(0, Date.now() - waitStartedAt);
|
|
378
391
|
if (next.done) break;
|
|
379
392
|
const event = next.value;
|
|
380
393
|
rawEventCount += 1;
|
|
@@ -395,6 +408,8 @@ async function* stopStalledModelStream(
|
|
|
395
408
|
output: event.type === "done" ? event.message : event.error,
|
|
396
409
|
rawEventCount,
|
|
397
410
|
meaningfulEventCount,
|
|
411
|
+
sourceWaitMs,
|
|
412
|
+
forwardingOverheadMs,
|
|
398
413
|
});
|
|
399
414
|
yield event;
|
|
400
415
|
return;
|
|
@@ -410,6 +425,15 @@ async function* stopStalledModelStream(
|
|
|
410
425
|
lastMeaningfulActivityType = progress;
|
|
411
426
|
idleWaitMs = 0;
|
|
412
427
|
}
|
|
428
|
+
if (
|
|
429
|
+
!firstTextSeen &&
|
|
430
|
+
(event.type === "text_delta" || event.type === "text_end") &&
|
|
431
|
+
(event.type === "text_delta" ? event.delta : event.content).trim()
|
|
432
|
+
) {
|
|
433
|
+
firstTextSeen = true;
|
|
434
|
+
probe("first_text_event", { eventType: event.type });
|
|
435
|
+
}
|
|
436
|
+
yieldedAt = Date.now();
|
|
413
437
|
yield event;
|
|
414
438
|
}
|
|
415
439
|
} finally {
|
|
@@ -431,7 +455,7 @@ function trimTrailingSlash(value: string): string {
|
|
|
431
455
|
/**
|
|
432
456
|
* 算出一个已解析模型真正会被请求的 URL。
|
|
433
457
|
*
|
|
434
|
-
* {@link
|
|
458
|
+
* {@link withProviderBoundary} 在每次派发模型请求前调用它写观测日志;诊断"这个 Agent 到底调了哪个 LLM"时也可以直接复用。
|
|
435
459
|
*
|
|
436
460
|
* 各协议的路径由底层 SDK 决定,这里必须与之逐条对齐:OpenAI 兼容 SDK 用 `baseURL + /chat/completions`,
|
|
437
461
|
* Anthropic SDK 用 `baseURL + /v1/messages`(纯字符串拼接,不会去重 `/v1`),Google 的 baseUrl 已含版本段,
|
|
@@ -458,18 +482,15 @@ export function modelRequestUrl(model: Model<Api>): string {
|
|
|
458
482
|
/**
|
|
459
483
|
* 给模型请求补上可中断的空闲终止边界。
|
|
460
484
|
*
|
|
461
|
-
* Runtime Turn 和 SubAgent 在把 `Models.streamSimple` 交给
|
|
462
|
-
*
|
|
463
|
-
* 调用方可以覆盖默认的 2 次 Provider 重试;主 Turn 传 0,由 Submission
|
|
464
|
-
* 统一持有恢复预算。连续 {@link MODEL_STREAM_STALL_TIMEOUT_MS} 毫秒没有可展示进展时中止 provider。
|
|
485
|
+
* Runtime Turn 和 SubAgent 在把 `Models.streamSimple` 交给 Harness 前调用。
|
|
486
|
+
* 本边界只负责载荷转换、观测和空闲超时;重试次数由 Harness 传入,这里不提供第二个默认值。
|
|
465
487
|
*
|
|
466
488
|
* 可选 observer 接收配对的 generation started/finished 事实及实际模型输入输出;响应头仅保留
|
|
467
489
|
* 白名单 request id,永不携带 key 或任意响应 header。正文由 telemetry 隐私模式统一脱敏。
|
|
468
490
|
* observer 的异常被隔离,不能改变模型执行结果。
|
|
469
491
|
*/
|
|
470
|
-
export function
|
|
492
|
+
export function withProviderBoundary(
|
|
471
493
|
streamFn: StreamFn,
|
|
472
|
-
defaultMaxRetries = PROVIDER_MAX_RETRIES,
|
|
473
494
|
defaultSessionId?: string,
|
|
474
495
|
onGeneration?: PiGenerationLifecycleObserver,
|
|
475
496
|
): StreamFn {
|
|
@@ -503,6 +524,12 @@ export function withProviderRetry(
|
|
|
503
524
|
let responseCount = 0;
|
|
504
525
|
let upstreamRequestId: string | undefined;
|
|
505
526
|
let responseStatus: number | undefined;
|
|
527
|
+
let responseHeadersMs: number | undefined;
|
|
528
|
+
let firstRawEventMs: number | undefined;
|
|
529
|
+
let firstMeaningfulEventMs: number | undefined;
|
|
530
|
+
let firstTextEventMs: number | undefined;
|
|
531
|
+
let sourceWaitMs: number | undefined;
|
|
532
|
+
let forwardingOverheadMs: number | undefined;
|
|
506
533
|
let finished = false;
|
|
507
534
|
const finish = (
|
|
508
535
|
outcome: "success" | "error" | "cancelled",
|
|
@@ -515,11 +542,18 @@ export function withProviderRetry(
|
|
|
515
542
|
) => {
|
|
516
543
|
if (finished) return;
|
|
517
544
|
finished = true;
|
|
545
|
+
const finishedAt = Date.now();
|
|
518
546
|
notify({
|
|
519
547
|
type: "finished",
|
|
520
548
|
generationId: requestId,
|
|
521
|
-
timestamp:
|
|
522
|
-
durationMs: Math.max(0,
|
|
549
|
+
timestamp: finishedAt,
|
|
550
|
+
durationMs: Math.max(0, finishedAt - startedAt),
|
|
551
|
+
responseHeadersMs,
|
|
552
|
+
firstRawEventMs,
|
|
553
|
+
firstMeaningfulEventMs,
|
|
554
|
+
firstTextEventMs,
|
|
555
|
+
sourceWaitMs,
|
|
556
|
+
forwardingOverheadMs,
|
|
523
557
|
outcome,
|
|
524
558
|
...details,
|
|
525
559
|
...(upstreamRequestId ? { upstreamRequestId } : {}),
|
|
@@ -527,7 +561,9 @@ export function withProviderRetry(
|
|
|
527
561
|
});
|
|
528
562
|
};
|
|
529
563
|
const probe = (phase: string, details: Record<string, unknown> = {}) => {
|
|
564
|
+
const elapsedMs = Math.max(0, Date.now() - startedAt);
|
|
530
565
|
if (phase === "response_headers") {
|
|
566
|
+
responseHeadersMs ??= elapsedMs;
|
|
531
567
|
if (typeof details.upstreamRequestId === "string") {
|
|
532
568
|
upstreamRequestId = details.upstreamRequestId;
|
|
533
569
|
}
|
|
@@ -536,6 +572,17 @@ export function withProviderRetry(
|
|
|
536
572
|
}
|
|
537
573
|
return;
|
|
538
574
|
}
|
|
575
|
+
if (phase === "first_raw_event") firstRawEventMs ??= elapsedMs;
|
|
576
|
+
if (phase === "first_meaningful_event") {
|
|
577
|
+
firstMeaningfulEventMs ??= elapsedMs;
|
|
578
|
+
}
|
|
579
|
+
if (phase === "first_text_event") firstTextEventMs ??= elapsedMs;
|
|
580
|
+
if (typeof details.sourceWaitMs === "number") {
|
|
581
|
+
sourceWaitMs = details.sourceWaitMs;
|
|
582
|
+
}
|
|
583
|
+
if (typeof details.forwardingOverheadMs === "number") {
|
|
584
|
+
forwardingOverheadMs = details.forwardingOverheadMs;
|
|
585
|
+
}
|
|
539
586
|
if (phase === "done") {
|
|
540
587
|
finish("success", {
|
|
541
588
|
...(typeof details.stopReason === "string"
|
|
@@ -579,7 +626,7 @@ export function withProviderRetry(
|
|
|
579
626
|
signal: options?.signal
|
|
580
627
|
? AbortSignal.any([options.signal, watchdog.signal])
|
|
581
628
|
: watchdog.signal,
|
|
582
|
-
maxRetries: options?.maxRetries
|
|
629
|
+
maxRetries: options?.maxRetries,
|
|
583
630
|
sessionId,
|
|
584
631
|
onPayload: async (payload, activeModel) =>
|
|
585
632
|
pdfPayload(
|
|
@@ -789,7 +836,7 @@ export function resolvePiModel(
|
|
|
789
836
|
/**
|
|
790
837
|
* 用当前部署端点完整重建一个已有的 Pi 模型集合。
|
|
791
838
|
*
|
|
792
|
-
*
|
|
839
|
+
* HarnessRuntimeConfig 激活新运行快照时调用它;需要复用 MutableModels 的调用方也可以调用,并继续使用返回的同一实例。
|
|
793
840
|
* 该函数在全部新 provider 校验通过后才清空并替换集合,所以失败时旧集合保持可用。
|
|
794
841
|
*
|
|
795
842
|
* Pi 当前用 provider.id 在 Map 中注册和路由请求,因此每个部署端点都必须同时注册唯一 provider、对应模型、认证解析器和协议实现。
|