@springbrand/agent-runtime 0.1.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.
Files changed (75) hide show
  1. package/package.json +28 -0
  2. package/src/db/approval.repo.ts +291 -0
  3. package/src/db/ext-context.repo.ts +34 -0
  4. package/src/db/index.ts +83 -0
  5. package/src/db/message-ui.repo.ts +39 -0
  6. package/src/db/milestone.repo.ts +96 -0
  7. package/src/db/runtime-event-outbox.repo.ts +89 -0
  8. package/src/db/schema.ts +164 -0
  9. package/src/db/settlement.repo.ts +104 -0
  10. package/src/db/steer.repo.ts +73 -0
  11. package/src/db/submission.repo.ts +323 -0
  12. package/src/index.ts +133 -0
  13. package/src/kernel/approval-lifecycle.ts +552 -0
  14. package/src/kernel/bindings.ts +898 -0
  15. package/src/kernel/degradation.ts +15 -0
  16. package/src/kernel/extensions.ts +108 -0
  17. package/src/kernel/profile.ts +116 -0
  18. package/src/kernel/public-contracts.ts +17 -0
  19. package/src/kernel/receipts.ts +124 -0
  20. package/src/kernel/recoverable-chat-agent.ts +899 -0
  21. package/src/kernel/state.ts +76 -0
  22. package/src/kernel/submission-lifecycle.ts +600 -0
  23. package/src/layers/context/budget/gate.ts +88 -0
  24. package/src/layers/orchestration/subagents/agent-types/contract.ts +78 -0
  25. package/src/layers/orchestration/subagents/agent-types/extract/index.ts +47 -0
  26. package/src/layers/orchestration/subagents/agent-types/fanout/index.ts +53 -0
  27. package/src/layers/orchestration/subagents/agent-types/registry.ts +16 -0
  28. package/src/layers/orchestration/temporary-agent/core.ts +152 -0
  29. package/src/layers/orchestration/temporary-agent/runner.ts +133 -0
  30. package/src/layers/orchestration/temporary-agent/workspace.ts +154 -0
  31. package/src/lib/artifacts.ts +54 -0
  32. package/src/lib/egress.ts +44 -0
  33. package/src/lib/execution-level.ts +27 -0
  34. package/src/lib/extension-name.ts +18 -0
  35. package/src/lib/host-actions.ts +57 -0
  36. package/src/lib/mcp.ts +86 -0
  37. package/src/lib/model-catalog.ts +7 -0
  38. package/src/lib/prompt.ts +139 -0
  39. package/src/lib/telemetry-dev.ts +44 -0
  40. package/src/pi/assembly/context.ts +510 -0
  41. package/src/pi/assembly/extensions.ts +661 -0
  42. package/src/pi/assembly/index.ts +19 -0
  43. package/src/pi/assembly/snapshot.ts +200 -0
  44. package/src/pi/message/contract.ts +8 -0
  45. package/src/pi/message/conversion.ts +73 -0
  46. package/src/pi/message/index.ts +3 -0
  47. package/src/pi/message/projection.ts +604 -0
  48. package/src/pi/runtime-adapter/assembly.ts +552 -0
  49. package/src/pi/runtime-adapter/execution.ts +683 -0
  50. package/src/pi/runtime-adapter/index.ts +232 -0
  51. package/src/pi/runtime-adapter/models.ts +243 -0
  52. package/src/pi/runtime-adapter/recovery.ts +805 -0
  53. package/src/pi/runtime-adapter/transcript.ts +825 -0
  54. package/src/pi/session/index.ts +24 -0
  55. package/src/pi/session/storage.ts +353 -0
  56. package/src/pi/tool/ai-adapter.ts +100 -0
  57. package/src/pi/tool/base.ts +110 -0
  58. package/src/pi/tool/compiler.ts +444 -0
  59. package/src/pi/tool/core-host.ts +48 -0
  60. package/src/pi/tool/core.ts +251 -0
  61. package/src/pi/tool/index.ts +32 -0
  62. package/src/pi/tool/mcp.ts +319 -0
  63. package/src/pi/tool/schedule.ts +198 -0
  64. package/src/pi/tool/skill.ts +455 -0
  65. package/src/pi/tool/subagent.ts +148 -0
  66. package/src/pi/tool/web-search/api.ts +1292 -0
  67. package/src/pi/tool/web-search/index.ts +2 -0
  68. package/src/pi/tool/web-search/web-search.ts +127 -0
  69. package/src/pi/tool/workspace-sandbox.ts +664 -0
  70. package/src/pi/turn/approval.ts +181 -0
  71. package/src/pi/turn/index.ts +62 -0
  72. package/src/pi/turn/tool-recovery.ts +792 -0
  73. package/src/plugins.ts +1024 -0
  74. package/src/runtime-agent.ts +654 -0
  75. package/src/runtime.ts +2880 -0
@@ -0,0 +1,148 @@
1
+ import type { AgentTool, AgentToolResult } from "@earendil-works/pi-agent-core";
2
+ import { z } from "zod";
3
+ import type { RuntimeSubagentPort } from "../../kernel/bindings";
4
+ import { AGENT_TYPES } from "../../layers/orchestration/subagents/agent-types/registry";
5
+ import { serializeOutput } from "../../lib/artifacts";
6
+ import type { PiToolCandidate } from "./compiler";
7
+
8
+ const BACKGROUND_MAX_BUDGET_MS = 10 * 60 * 1_000;
9
+
10
+ // 作用:把 SubAgent 的结构化值包装成 Pi 可读的工具结果。
11
+ // 调用:前台执行、前台失败和后台派发成功后调用。
12
+ // 原因:模型读取序列化文本,Runtime 事件继续保留原始 details,
13
+ // 避免两套结果格式漂移。
14
+ function result(details: unknown, modelValue = details): AgentToolResult<unknown> {
15
+ return {
16
+ content: [{ type: "text", text: serializeOutput(modelValue).text }],
17
+ details,
18
+ };
19
+ }
20
+
21
+ // 作用:为没有正常完成的前台 SubAgent 生成稳定失败值。
22
+ // 调用:AgentType 工具发现 run 状态不是 completed 或没有 output 时调用。
23
+ // 原因:子任务失败是一次已完成的工具结果而不是适配器异常,
24
+ // 保留状态能让主 Agent 决定后续动作。
25
+ function failure(agentType: string, status: string, error?: string) {
26
+ // TODO(待确认):Host 当前没有把 Agents SDK 的 retryable、reason 和
27
+ // childStillRunning 投影进 RuntimeSubagentPort,
28
+ // 主 Agent 无法据此区分可重试中断。
29
+ return {
30
+ ok: false as const,
31
+ agentType,
32
+ status,
33
+ error: error ?? "sub-agent did not complete",
34
+ };
35
+ }
36
+
37
+ /**
38
+ * 把已启用的 SubAgent 类型转换成 Pi 候选工具。
39
+ *
40
+ * Worker 的 SubAgent Plugin 在绑定执行端口后调用它。调用方应传入该 Runtime
41
+ * 快照启用的类型名称;未注册名称会被忽略,没有端口或没有有效类型时不公开工具。
42
+ *
43
+ * 这里的 “AgentType” 是注册表中的输入 Schema、说明和显示名称,“前台执行”
44
+ * 会等待子任务结果,“后台派发”只返回 runId,并由 Host 通过通知把最终结果送回
45
+ * 当前会话。注册表同时生成工具 Schema 和再次校验后台 input,不能改成两份定义。
46
+ *
47
+ * `Host`、`Pi`、`Port`、`Runtime Snapshot` 与“候选工具”见 `../../index.ts`。
48
+ */
49
+ export function subagentPiToolCandidates(
50
+ subagents: RuntimeSubagentPort | undefined,
51
+ enabledSubagents: readonly string[],
52
+ ): PiToolCandidate[] {
53
+ if (!subagents) return [];
54
+ const types = [...new Set(enabledSubagents)].flatMap((name) => {
55
+ const type = AGENT_TYPES.byName[name];
56
+ return type ? [type] : [];
57
+ });
58
+ if (types.length === 0) return [];
59
+
60
+ // TODO(待确认):RuntimeSubagentPort.run 目前不接收 AbortSignal;两个 execute
61
+ // 只能在启动前拒绝已取消调用,
62
+ // 开始后的子任务可能无法跟随父工具取消。
63
+ const candidates = types.map((type): PiToolCandidate => {
64
+ const tool: AgentTool<any, unknown> = {
65
+ name: type.name,
66
+ label: type.displayName,
67
+ description: type.description,
68
+ parameters: z.toJSONSchema(
69
+ type.inputSchema,
70
+ ) as AgentTool["parameters"],
71
+ // 作用:运行一种已启用的前台 SubAgent,
72
+ // 并把完成或失败状态返回主 Agent。
73
+ // 调用:Pi 选择对应 AgentType 工具并通过其 Schema 校验后调用。
74
+ // 原因:执行细节留给 RuntimeSubagentPort;
75
+ // 适配层只固定类型名并统一结果语义。
76
+ async execute(_toolCallId, input, signal) {
77
+ signal?.throwIfAborted();
78
+ const run = await subagents.run(
79
+ type.name,
80
+ input as Record<string, unknown>,
81
+ );
82
+ if (run.status !== "completed" || run.output === undefined) {
83
+ return result(failure(type.name, run.status, run.error));
84
+ }
85
+ return result(run.output);
86
+ },
87
+ };
88
+ return {
89
+ owner: `subagent:${type.name}`,
90
+ authorized: true,
91
+ requiredExecutionLevel: "safe",
92
+ tool,
93
+ };
94
+ });
95
+
96
+ const typeNames = types.map(({ name }) => name) as [string, ...string[]];
97
+ const parameters = z.object({
98
+ agentType: z.enum(typeNames),
99
+ input: z.record(z.string(), z.unknown()),
100
+ });
101
+ const background: AgentTool<any, unknown> = {
102
+ name: "dispatch_background",
103
+ label: "Dispatch background SubAgent",
104
+ description:
105
+ "Dispatch a bounded sub-agent job in the background. Returns a runId; " +
106
+ "the structured result is injected into this chat when complete.",
107
+ parameters: z.toJSONSchema(parameters) as AgentTool["parameters"],
108
+ // 作用:派发一个有时间预算的后台 SubAgent,并立即返回运行标识。
109
+ // 调用:Pi 需要子任务异步进行、不应阻塞当前 Turn 时调用。
110
+ // 原因:先用具体 AgentType Schema 复核嵌套 input,
111
+ // 再把 detached 和通知语义交给 Host,避免后台入口绕过类型约束。
112
+ async execute(_toolCallId, value, signal) {
113
+ signal?.throwIfAborted();
114
+ const input = value as z.infer<typeof parameters>;
115
+ const parsed = AGENT_TYPES.byName[input.agentType]!.inputSchema.safeParse(
116
+ input.input,
117
+ );
118
+ if (!parsed.success) {
119
+ throw new Error(
120
+ `SubAgent input failed schema validation: ${parsed.error.message}`,
121
+ );
122
+ }
123
+ const run = await subagents.run(
124
+ input.agentType,
125
+ parsed.data as Record<string, unknown>,
126
+ {
127
+ detached: true,
128
+ maxBudgetMs: BACKGROUND_MAX_BUDGET_MS,
129
+ notifySource: "dispatch-background",
130
+ },
131
+ );
132
+ return result({
133
+ runId: run.runId,
134
+ status: run.status,
135
+ agentType: input.agentType,
136
+ });
137
+ },
138
+ };
139
+ candidates.push({
140
+ owner: "subagent:background",
141
+ authorized: true,
142
+ requiredExecutionLevel: "low",
143
+ summary: "Dispatch a background sub-agent",
144
+ source: "action",
145
+ tool: background,
146
+ });
147
+ return candidates;
148
+ }