@springbrand/agent-runtime 0.2.0-alpha.72 → 0.3.0-alpha.1
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 +3 -3
- package/src/{agent-tool-runtime.ts → adapter/cloudflare/agent-tool.ts} +1 -1
- package/src/adapter/cloudflare/agent.ts +1539 -0
- package/src/{db/index.ts → adapter/cloudflare/database.ts} +18 -55
- package/src/{runtime-agent.ts → adapter/cloudflare/define-agent.ts} +25 -35
- package/src/adapter/cloudflare/dynamic-worker-observability.ts +1 -1
- package/src/adapter/cloudflare/resources/runtime-resources.ts +4 -4
- package/src/adapter/cloudflare/sandbox/adapter.ts +1 -1
- package/src/{db → adapter/cloudflare}/schema.ts +16 -83
- 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 -10
- 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} +20 -19
- 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 +182 -0
- package/src/config/index.ts +14 -0
- package/src/{pi/runtime-adapter/assembly.ts → config/pinning.ts} +38 -16
- package/src/{kernel/bindings.ts → config/ports.ts} +9 -13
- 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} +4 -206
- 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 +2 -2
- package/src/conversation/harness-resume.ts +288 -0
- package/src/conversation/harness-stream.ts +98 -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 +76 -10
- package/src/{db/message-ui.repo.ts → conversation/repository.ts} +4 -0
- package/src/conversation/state.ts +175 -0
- package/src/harness/index.ts +7 -0
- package/src/harness/session-harness.ts +481 -0
- package/src/harness/submission-operation.ts +49 -0
- package/src/index.ts +38 -43
- package/src/lib/mcp.ts +1 -1
- package/src/{pi/runtime-adapter/models.ts → models/index.ts} +64 -18
- package/src/{pi/turn/tool-recovery.ts → session/cloudflare/legacy-tool-recovery.ts} +33 -525
- package/src/{pi/session → session/cloudflare}/migration.ts +334 -8
- package/src/{pi/session → session/cloudflare}/storage.ts +8 -36
- package/src/session/index.ts +39 -0
- package/src/submission/admission.ts +275 -0
- package/src/{kernel/receipts.ts → submission/contracts.ts} +14 -0
- 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} +61 -118
- package/src/submission/steer-delivery.ts +167 -0
- package/src/{db/steer.repo.ts → submission/steer-repository.ts} +27 -5
- 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/{pi/tool → tools}/ai-adapter.ts +2 -2
- package/src/tools/approval/index.ts +1 -0
- package/src/{db/approval.repo.ts → tools/approval/repository.ts} +10 -30
- package/src/{pi/tool → tools}/base.ts +14 -30
- package/src/tools/compiler.ts +327 -0
- package/src/{pi/tool → tools}/core-host.ts +3 -3
- package/src/{pi/tool → tools}/core.ts +3 -3
- package/src/tools/decision-gate.ts +227 -0
- package/src/{pi/tool → tools}/gateway.ts +1 -1
- package/src/tools/human-decisions.ts +127 -0
- package/src/tools/index.ts +30 -0
- package/src/tools/interaction/index.ts +1 -0
- package/src/{pi/tool → tools}/mcp.ts +1 -1
- package/src/{pi/tool → tools}/schedule.ts +3 -3
- package/src/{pi/tool → tools}/skill.ts +4 -4
- package/src/{kernel → tools}/subagent-runtime.ts +1 -1
- package/src/{pi/tool → tools}/subagent.ts +4 -4
- package/src/tools/temporary-agent/approvals.ts +126 -0
- package/src/{layers/orchestration/temporary-agent/core.ts → tools/temporary-agent/coordinator.ts} +41 -49
- package/src/tools/temporary-agent/core.ts +53 -0
- package/src/{layers/orchestration → tools}/temporary-agent/runner.ts +1 -1
- package/src/{layers/orchestration → tools}/temporary-agent/workspace.ts +1 -1
- package/src/{pi/tool → tools}/web-search/api.ts +1 -1
- package/src/{pi/tool → tools}/workspace-revision.ts +2 -2
- package/src/{pi/tool → tools}/workspace-sandbox.ts +2 -2
- package/src/{pi/tool → tools}/workspace-state-connector.ts +1 -1
- 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/compiler.ts +0 -483
- package/src/pi/tool/index.ts +0 -38
- 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/{pi/tool → tools}/declared.ts +0 -0
- /package/src/{db/interaction.repo.ts → tools/interaction/repository.ts} +0 -0
- /package/src/{pi/tool → tools}/nested-tools.ts +0 -0
- /package/src/{kernel/submission-authority.ts → tools/subagent-authority.ts} +0 -0
- /package/src/{db/agent-tool.repo.ts → tools/subagent-run-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 +0 -0
- /package/src/{pi/tool → tools}/time.ts +0 -0
- /package/src/{pi/tool → tools}/web-fetch.ts +0 -0
- /package/src/{pi/tool → tools}/web-search/index.ts +0 -0
- /package/src/{pi/tool → tools}/web-search/web-search.ts +0 -0
- /package/src/{workspace-versioning.ts → tools/workspace-versioning.ts} +0 -0
package/src/lib/mcp.ts
CHANGED
|
@@ -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(
|
|
@@ -743,7 +790,6 @@ function configuredModel(
|
|
|
743
790
|
? {
|
|
744
791
|
compat: {
|
|
745
792
|
...anthropicMessagesCompat,
|
|
746
|
-
// OpenRouter rejects Anthropic's mid-conversation effort messages and block binding.
|
|
747
793
|
supportsMidConvoEffort: false,
|
|
748
794
|
supportsEagerToolInputStreaming: false,
|
|
749
795
|
supportsStrictTools:
|
|
@@ -789,7 +835,7 @@ export function resolvePiModel(
|
|
|
789
835
|
/**
|
|
790
836
|
* 用当前部署端点完整重建一个已有的 Pi 模型集合。
|
|
791
837
|
*
|
|
792
|
-
*
|
|
838
|
+
* HarnessRuntimeConfig 激活新运行快照时调用它;需要复用 MutableModels 的调用方也可以调用,并继续使用返回的同一实例。
|
|
793
839
|
* 该函数在全部新 provider 校验通过后才清空并替换集合,所以失败时旧集合保持可用。
|
|
794
840
|
*
|
|
795
841
|
* Pi 当前用 provider.id 在 Map 中注册和路由请求,因此每个部署端点都必须同时注册唯一 provider、对应模型、认证解析器和协议实现。
|