aws-runtime-bridge 1.8.6 → 1.8.8

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 (42) hide show
  1. package/dist/adapter/AcodeSdkAdapter.d.ts.map +1 -1
  2. package/dist/adapter/AcodeSdkAdapter.js +98 -6
  3. package/dist/adapter/AcodeSdkAdapter.test.js +313 -2
  4. package/dist/adapter/OpencodeSdkAdapter.js +1 -1
  5. package/dist/adapter/types.d.ts.map +1 -1
  6. package/dist/adapter/types.js +7 -3
  7. package/dist/config.d.ts +2 -3
  8. package/dist/config.d.ts.map +1 -1
  9. package/dist/config.js +9 -10
  10. package/dist/config.test.js +1 -22
  11. package/dist/routes/ai-sources.js +5 -1
  12. package/dist/routes/ai-sources.test.js +21 -0
  13. package/dist/routes/instance.test.js +1 -70
  14. package/dist/routes/runtime-binding.d.ts.map +1 -1
  15. package/dist/routes/runtime-binding.js +36 -1
  16. package/dist/routes/terminal.d.ts +3 -0
  17. package/dist/routes/terminal.d.ts.map +1 -1
  18. package/dist/routes/terminal.js +141 -6
  19. package/dist/routes/terminal.test.js +118 -1
  20. package/dist/services/mcp-launch-binding-queue.d.ts +7 -0
  21. package/dist/services/mcp-launch-binding-queue.d.ts.map +1 -1
  22. package/dist/services/mcp-launch-binding-queue.js +25 -0
  23. package/dist/services/session-output.d.ts +8 -3
  24. package/dist/services/session-output.d.ts.map +1 -1
  25. package/dist/services/session-output.js +35 -14
  26. package/dist/services/session-output.test.js +41 -0
  27. package/package/acode/dist/runtime.d.ts +1 -0
  28. package/package/acode/dist/runtime.d.ts.map +1 -1
  29. package/package/acode/dist/runtime.js +265 -31
  30. package/package/acode/dist/types.d.ts +1 -1
  31. package/package/acode/dist/types.d.ts.map +1 -1
  32. package/package/aws-client-agent-mcp/dist/config.d.ts +4 -0
  33. package/package/aws-client-agent-mcp/dist/config.d.ts.map +1 -1
  34. package/package/aws-client-agent-mcp/dist/config.js +15 -0
  35. package/package/aws-client-agent-mcp/dist/config.js.map +1 -1
  36. package/package/aws-client-agent-mcp/dist/http-client.d.ts +10 -0
  37. package/package/aws-client-agent-mcp/dist/http-client.d.ts.map +1 -1
  38. package/package/aws-client-agent-mcp/dist/http-client.js +79 -1
  39. package/package/aws-client-agent-mcp/dist/http-client.js.map +1 -1
  40. package/package/aws-client-agent-mcp/dist/http-client.test.js +129 -265
  41. package/package/aws-client-agent-mcp/dist/http-client.test.js.map +1 -1
  42. package/package.json +1 -1
@@ -3,7 +3,7 @@ import os from "node:os";
3
3
  import path from "node:path";
4
4
  import { describe, expect, it } from "vitest";
5
5
  import { SDK_PROVIDER_DEFINITIONS } from "../adapter/SdkProviderSpi.js";
6
- import { buildAcodeCommandOutputPath, buildClaudeCodeLaunchConfig, buildRuntimeEnv, buildToolResultTimelineActionInfo, countTerminalOutputLines, createTerminalOutputDecoder, decodeTerminalOutputChunk, evaluatePersistedSessionReuse, formatCommandInactivityTimeoutNotice, formatCommandOutputSpilloverNotice, formatTerminalPrompt, formatSdkOutputEvent, normalizeTerminalCommandInput, parseTerminalDirectoryChangeTarget, resolveSdkInputMessage, resolveTerminalOutputEncoding, resolveSdkProviderId, resolveSdkSessionDisplayStatus, resolveRuntimeStatusFromProviderEvent, resolveStatusChangeUsage, } from "./terminal.js";
6
+ import { buildAcodeCommandOutputPath, buildClaudeCodeLaunchConfig, buildRuntimeEnv, buildSdkOutputMetadata, buildToolResultTimelineActionInfo, countTerminalOutputLines, createTerminalOutputDecoder, decodeTerminalOutputChunk, evaluatePersistedSessionReuse, formatCommandInactivityTimeoutNotice, formatCommandOutputSpilloverNotice, formatTerminalPrompt, formatSdkOutputEvent, normalizeTerminalCommandInput, parseTerminalDirectoryChangeTarget, resolveSdkInputMessage, resolveTerminalOutputEncoding, resolveSdkProviderId, resolveSdkSessionDisplayStatus, resolveRuntimeStatusFromProviderEvent, resolveStatusChangeUsage, } from "./terminal.js";
7
7
  describe("terminal route validation", () => {
8
8
  it("requires agentId and workspacePath for start", () => {
9
9
  const validateStartRequest = (body) => {
@@ -377,6 +377,44 @@ describe("SDK status usage forwarding", () => {
377
377
  },
378
378
  });
379
379
  });
380
+ it("includes file paths and commands in tool status action details", () => {
381
+ expect(resolveRuntimeStatusFromProviderEvent({
382
+ type: "tool_use_start",
383
+ sessionId: "session-1",
384
+ timestamp: new Date(0).toISOString(),
385
+ data: {
386
+ toolName: "builtin/read_file",
387
+ toolInput: { path: "src/views/App.vue" },
388
+ toolUseId: "tool-read",
389
+ },
390
+ })).toEqual({
391
+ status: "tool_using",
392
+ actionInfo: {
393
+ actionType: "read_file",
394
+ actionLabel: "读取文件",
395
+ actionDetail: "src/views/App.vue",
396
+ actionId: "tool-read",
397
+ },
398
+ });
399
+ expect(resolveRuntimeStatusFromProviderEvent({
400
+ type: "tool_use_start",
401
+ sessionId: "session-1",
402
+ timestamp: new Date(0).toISOString(),
403
+ data: {
404
+ toolName: "bash",
405
+ toolInput: { command: "npm run test:agent-timeline-panel" },
406
+ toolUseId: "tool-bash",
407
+ },
408
+ })).toEqual({
409
+ status: "tool_using",
410
+ actionInfo: {
411
+ actionType: "bash",
412
+ actionLabel: "执行命令",
413
+ actionDetail: "npm run test:agent-timeline-panel",
414
+ actionId: "tool-bash",
415
+ },
416
+ });
417
+ });
380
418
  });
381
419
  describe("SDK output forwarding", () => {
382
420
  it("formats assistant text provider events for the terminal output callback path", () => {
@@ -425,6 +463,85 @@ describe("SDK output forwarding", () => {
425
463
  };
426
464
  expect(formatSdkOutputEvent(requestEvent)).toBe("\r\n[ACode] 正在请求模型 test-model:inspect status\r\n");
427
465
  });
466
+ it("builds ACode log metadata for output callbacks", () => {
467
+ const requestEvent = {
468
+ type: "ai_request",
469
+ sessionId: "session-1",
470
+ timestamp: new Date(0).toISOString(),
471
+ data: { model: "test-model", endpoint: "openai-compatible", toolCount: 2 },
472
+ };
473
+ const errorEvent = {
474
+ type: "error",
475
+ sessionId: "session-1",
476
+ timestamp: new Date(0).toISOString(),
477
+ data: { text: "provider failed" },
478
+ };
479
+ expect(buildSdkOutputMetadata(requestEvent)).toEqual({
480
+ sourceEventType: "ai_request",
481
+ logCategory: "acode",
482
+ logLevel: "info",
483
+ logMessage: "AI request started: test-model @ openai-compatible, tools=2",
484
+ });
485
+ expect(buildSdkOutputMetadata(errorEvent)).toEqual({
486
+ sourceEventType: "error",
487
+ logCategory: "acode",
488
+ logLevel: "error",
489
+ logMessage: "provider failed",
490
+ });
491
+ });
492
+ it("does not mark streaming text chunks as standalone ACode log rows", () => {
493
+ const metadata = buildSdkOutputMetadata({
494
+ type: "text_delta",
495
+ sessionId: "session-1",
496
+ data: { text: "word" },
497
+ });
498
+ expect(metadata).toEqual({
499
+ sourceEventType: "text_delta",
500
+ logCategory: "acode",
501
+ });
502
+ });
503
+ it("includes file paths and commands in ACode tool log metadata", () => {
504
+ const readEvent = {
505
+ type: "tool_use_start",
506
+ sessionId: "session-1",
507
+ timestamp: new Date(0).toISOString(),
508
+ data: {
509
+ toolName: "read_file",
510
+ toolInput: { path: "src/index.ts" },
511
+ },
512
+ };
513
+ const editEvent = {
514
+ type: "tool_use_start",
515
+ sessionId: "session-1",
516
+ timestamp: new Date(0).toISOString(),
517
+ data: {
518
+ toolName: "edit",
519
+ toolInput: { file_path: "src/app.ts" },
520
+ },
521
+ };
522
+ const writeEvent = {
523
+ type: "tool_use_end",
524
+ sessionId: "session-1",
525
+ timestamp: new Date(0).toISOString(),
526
+ data: {
527
+ toolName: "write_file",
528
+ toolInput: { path: "src/new-file.ts" },
529
+ },
530
+ };
531
+ const bashEvent = {
532
+ type: "tool_use_start",
533
+ sessionId: "session-1",
534
+ timestamp: new Date(0).toISOString(),
535
+ data: {
536
+ toolName: "bash",
537
+ toolInput: { command: "npm run build -- --mode production" },
538
+ },
539
+ };
540
+ expect(buildSdkOutputMetadata(readEvent).logMessage).toBe("开始读取文件: src/index.ts");
541
+ expect(buildSdkOutputMetadata(editEvent).logMessage).toBe("开始编辑文件: src/app.ts");
542
+ expect(buildSdkOutputMetadata(writeEvent).logMessage).toBe("完成写入文件: src/new-file.ts");
543
+ expect(buildSdkOutputMetadata(bashEvent).logMessage).toBe("开始执行命令: npm run build -- --mode production");
544
+ });
428
545
  });
429
546
  describe("SDK tool result timeline action info", () => {
430
547
  it("keeps MCP tool results on MCP timeline events", () => {
@@ -32,4 +32,11 @@ export declare function enqueueMcpLaunchBinding(input: McpLaunchBindingInput): M
32
32
  export declare function claimMcpLaunchBinding(request: McpLaunchBindingClaimRequest): ClaimedMcpLaunchBinding | null;
33
33
  export declare function getMcpLaunchQueueSize(workspacePath: unknown): number;
34
34
  export declare function clearMcpLaunchBindingQueues(): void;
35
+ /**
36
+ * 获取指定 agent 的最新 MCP session token。
37
+ * 供 MCP node 在 401 后向 bridge 查询最新 token 使用。
38
+ */
39
+ export declare function getLatestAgentToken(agentId: string): {
40
+ runtimeAccessToken: string;
41
+ } | null;
35
42
  //# sourceMappingURL=mcp-launch-binding-queue.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-launch-binding-queue.d.ts","sourceRoot":"","sources":["../../src/services/mcp-launch-binding-queue.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAwB,SAAQ,gBAAgB;IAC/D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,4BAA4B;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AA2DD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,qBAAqB,GAAG,gBAAgB,GAAG,IAAI,CA+B7F;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,GAAG,uBAAuB,GAAG,IAAI,CAkD3G;AAED,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,OAAO,GAAG,MAAM,CAOpE;AAED,wBAAgB,2BAA2B,IAAI,IAAI,CAElD"}
1
+ {"version":3,"file":"mcp-launch-binding-queue.d.ts","sourceRoot":"","sources":["../../src/services/mcp-launch-binding-queue.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAwB,SAAQ,gBAAgB;IAC/D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,4BAA4B;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AA2DD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,qBAAqB,GAAG,gBAAgB,GAAG,IAAI,CAyC7F;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,GAAG,uBAAuB,GAAG,IAAI,CAkD3G;AAED,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,OAAO,GAAG,MAAM,CAOpE;AAED,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,kBAAkB,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAM1F"}
@@ -2,6 +2,12 @@ import path from "node:path";
2
2
  import { schedulerBaseUrl as defaultSchedulerBaseUrl } from "../config.js";
3
3
  import { getRuntimeAccessToken, loadRuntimeBinding, normalizeSchedulerBaseUrl } from "./runtime-binding.js";
4
4
  const LAUNCH_BINDING_TTL_MS = 5 * 60 * 1000;
5
+ /**
6
+ * 每个 agent 最新的 MCP session token 缓存。
7
+ * key = agentId,value = { runtimeAccessToken, updatedAt }
8
+ * 当 /runtime/start 入队新 binding 时更新,供 MCP node 401 后刷新使用。
9
+ */
10
+ const latestAgentTokens = new Map();
5
11
  const launchBindings = [];
6
12
  function normalizeWorkspacePath(workspacePath) {
7
13
  const raw = String(workspacePath || "").trim();
@@ -76,6 +82,14 @@ export function enqueueMcpLaunchBinding(input) {
76
82
  enqueuedAt: new Date().toISOString(),
77
83
  };
78
84
  launchBindings.push(binding);
85
+ // 缓存最新 token,供 MCP node 401 后刷新
86
+ const tokenValue = binding.runtimeAccessToken;
87
+ if (tokenValue) {
88
+ latestAgentTokens.set(agentId, {
89
+ runtimeAccessToken: tokenValue,
90
+ updatedAt: Date.now(),
91
+ });
92
+ }
79
93
  return binding;
80
94
  }
81
95
  export function claimMcpLaunchBinding(request) {
@@ -131,3 +145,14 @@ export function getMcpLaunchQueueSize(workspacePath) {
131
145
  export function clearMcpLaunchBindingQueues() {
132
146
  launchBindings.splice(0, launchBindings.length);
133
147
  }
148
+ /**
149
+ * 获取指定 agent 的最新 MCP session token。
150
+ * 供 MCP node 在 401 后向 bridge 查询最新 token 使用。
151
+ */
152
+ export function getLatestAgentToken(agentId) {
153
+ const cached = latestAgentTokens.get(agentId);
154
+ if (!cached || !cached.runtimeAccessToken) {
155
+ return null;
156
+ }
157
+ return { runtimeAccessToken: cached.runtimeAccessToken };
158
+ }
@@ -14,6 +14,13 @@ interface RuntimeStatusActionInfo {
14
14
  }
15
15
  export interface RuntimeCallbackAuthOptions {
16
16
  runtimeAccessToken?: string;
17
+ schedulerBaseUrl?: string;
18
+ }
19
+ export interface RuntimeOutputMetadata {
20
+ sourceEventType?: string;
21
+ logLevel?: "info" | "warn" | "error";
22
+ logMessage?: string;
23
+ logCategory?: string;
17
24
  }
18
25
  /** 活跃会话存储 */
19
26
  export declare const sessions: Map<string, Session>;
@@ -37,9 +44,7 @@ export declare function sendStatus(agentId: string, sessionId: string | null, st
37
44
  * @param sessionId - 会话 ID
38
45
  * @param seq - 序列号
39
46
  */
40
- export declare function sendOutput(agentId: string, output: string, sessionId: string, seq: number, metadata?: {
41
- sourceEventType?: string;
42
- }, authOptions?: RuntimeCallbackAuthOptions): Promise<void>;
47
+ export declare function sendOutput(agentId: string, output: string, sessionId: string, seq: number, metadata?: RuntimeOutputMetadata, authOptions?: RuntimeCallbackAuthOptions): Promise<void>;
43
48
  /**
44
49
  * 发送 AskUserQuestion 事件到调度器。
45
50
  *
@@ -1 +1 @@
1
- {"version":3,"file":"session-output.d.ts","sourceRoot":"","sources":["../../src/services/session-output.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAI3C,UAAU,uBAAuB;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,0BAA0B;IACzC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAmBD,aAAa;AACb,eAAO,MAAM,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAa,CAAC;AAExD;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,uBAAuB,EACpC,KAAK,CAAC,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,EACrD,WAAW,CAAC,EAAE,0BAA0B,GACvC,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC,CA0C7C;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE;IAAE,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,EACvC,WAAW,CAAC,EAAE,0BAA0B,GACvC,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,OAAO,EAAE,EACpB,WAAW,CAAC,EAAE,0BAA0B,GACvC,OAAO,CAAC,IAAI,CAAC,CAcf;AAED,MAAM,WAAW,yBAAyB;IACxC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAgBzE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAa3D;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCzE"}
1
+ {"version":3,"file":"session-output.d.ts","sourceRoot":"","sources":["../../src/services/session-output.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAG3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAI3C,UAAU,uBAAuB;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,0BAA0B;IACzC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,qBAAqB;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA8BD,aAAa;AACb,eAAO,MAAM,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAa,CAAC;AAExD;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,uBAAuB,EACpC,KAAK,CAAC,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,EACrD,WAAW,CAAC,EAAE,0BAA0B,GACvC,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC,CA4C7C;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,qBAAqB,EAChC,WAAW,CAAC,EAAE,0BAA0B,GACvC,OAAO,CAAC,IAAI,CAAC,CA2Bf;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,OAAO,EAAE,EACpB,WAAW,CAAC,EAAE,0BAA0B,GACvC,OAAO,CAAC,IAAI,CAAC,CAef;AAED,MAAM,WAAW,yBAAyB;IACxC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAgBzE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAa3D;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCzE"}
@@ -4,15 +4,22 @@
4
4
  * 管理终端会话的输出缓冲和刷新机制
5
5
  */
6
6
  import axios from "axios";
7
- import { schedulerBaseUrl } from "../config.js";
7
+ import { resolveSchedulerBaseUrlFrom } from "../config.js";
8
8
  import { logger } from "../utils/logger.js";
9
9
  import { getRuntimeAccessToken } from "./runtime-binding.js";
10
- function runtimeAuthHeaders(options) {
10
+ function runtimeAuthHeaders(options, callbackBaseUrl = resolveRuntimeCallbackBaseUrl(options)) {
11
11
  const token = options?.runtimeAccessToken ||
12
- getRuntimeAccessToken(undefined, schedulerBaseUrl) ||
12
+ getRuntimeAccessToken(undefined, callbackBaseUrl) ||
13
13
  getRuntimeAccessToken();
14
14
  return token ? { "X-Runtime-Token": token } : undefined;
15
15
  }
16
+ /**
17
+ * 解析 Runtime 回调的调度中心地址。
18
+ * 主流程:优先使用启动请求携带的 scheduler 地址;否则按环境变量、单自动注册目标、默认值依次回退。
19
+ */
20
+ function resolveRuntimeCallbackBaseUrl(options) {
21
+ return resolveSchedulerBaseUrlFrom(options?.schedulerBaseUrl).url;
22
+ }
16
23
  /** 输出刷新防抖时间:合并启动期高频小块输出,降低 HTTP/WebSocket 压力。 */
17
24
  const OUTPUT_FLUSH_DEBOUNCE_MS = 100;
18
25
  /** 单个会话待发送输出上限,避免调度器不可达时内存无限增长。 */
@@ -49,19 +56,21 @@ export async function sendStatus(agentId, sessionId, status, actionInfo, usage,
49
56
  payload.inputTokens = usage.inputTokens;
50
57
  payload.outputTokens = usage.outputTokens;
51
58
  }
52
- const headers = runtimeAuthHeaders(authOptions);
59
+ const callbackBaseUrl = resolveRuntimeCallbackBaseUrl(authOptions);
60
+ const headers = runtimeAuthHeaders(authOptions, callbackBaseUrl);
53
61
  if (!headers) {
54
- logger.warn("Skip runtime status callback because runtime token is missing", { agentId, sessionId, status });
62
+ logger.warn("Skip runtime status callback because runtime token is missing", { agentId, sessionId, status, schedulerBaseUrl: callbackBaseUrl });
55
63
  return undefined;
56
64
  }
57
65
  try {
58
- return await axios.post(`${schedulerBaseUrl}/api/runtime/callback/status`, payload, { headers });
66
+ return await axios.post(`${callbackBaseUrl}/api/runtime/callback/status`, payload, { headers });
59
67
  }
60
68
  catch (error) {
61
69
  logger.warn("Runtime status callback failed", {
62
70
  agentId,
63
71
  sessionId,
64
72
  status,
73
+ schedulerBaseUrl: callbackBaseUrl,
65
74
  error,
66
75
  });
67
76
  return undefined;
@@ -77,14 +86,24 @@ export async function sendStatus(agentId, sessionId, status, actionInfo, usage,
77
86
  */
78
87
  export async function sendOutput(agentId, output, sessionId, seq, metadata, authOptions) {
79
88
  try {
80
- const headers = runtimeAuthHeaders(authOptions);
89
+ const callbackBaseUrl = resolveRuntimeCallbackBaseUrl(authOptions);
90
+ const headers = runtimeAuthHeaders(authOptions, callbackBaseUrl);
81
91
  if (!headers) {
92
+ logger.warn("Skip runtime output callback because runtime token is missing", {
93
+ agentId,
94
+ sessionId,
95
+ schedulerBaseUrl: callbackBaseUrl,
96
+ });
82
97
  return;
83
98
  }
84
- await axios.post(`${schedulerBaseUrl}/api/runtime/callback/output`, { agentId, output, sessionId, seq, ...metadata }, { headers });
99
+ await axios.post(`${callbackBaseUrl}/api/runtime/callback/output`, { agentId, output, sessionId, seq, ...metadata }, { headers });
85
100
  }
86
- catch {
87
- // ignore transient callback failures
101
+ catch (error) {
102
+ logger.warn("Runtime output callback failed", {
103
+ agentId,
104
+ sessionId,
105
+ error,
106
+ });
88
107
  }
89
108
  }
90
109
  /**
@@ -96,11 +115,12 @@ export async function sendOutput(agentId, output, sessionId, seq, metadata, auth
96
115
  */
97
116
  export async function sendQuestionRequest(agentId, sessionId, questions, authOptions) {
98
117
  try {
99
- const headers = runtimeAuthHeaders(authOptions);
118
+ const callbackBaseUrl = resolveRuntimeCallbackBaseUrl(authOptions);
119
+ const headers = runtimeAuthHeaders(authOptions, callbackBaseUrl);
100
120
  if (!headers) {
101
121
  return;
102
122
  }
103
- await axios.post(`${schedulerBaseUrl}/api/runtime/callback/question`, { agentId, sessionId, questions }, { headers });
123
+ await axios.post(`${callbackBaseUrl}/api/runtime/callback/question`, { agentId, sessionId, questions }, { headers });
104
124
  }
105
125
  catch {
106
126
  // ignore transient callback failures
@@ -111,11 +131,12 @@ export async function sendQuestionRequest(agentId, sessionId, questions, authOpt
111
131
  */
112
132
  export async function sendFileChanged(payload) {
113
133
  try {
114
- const headers = runtimeAuthHeaders();
134
+ const callbackBaseUrl = resolveRuntimeCallbackBaseUrl();
135
+ const headers = runtimeAuthHeaders(undefined, callbackBaseUrl);
115
136
  if (!headers) {
116
137
  return;
117
138
  }
118
- await axios.post(`${schedulerBaseUrl}/api/runtime/callback/file-changed`, payload, { headers });
139
+ await axios.post(`${callbackBaseUrl}/api/runtime/callback/file-changed`, payload, { headers });
119
140
  }
120
141
  catch {
121
142
  // ignore transient callback failures
@@ -5,6 +5,7 @@ import axios from "axios";
5
5
  import { afterEach, describe, expect, it, vi } from "vitest";
6
6
  import { logger } from "../utils/logger.js";
7
7
  import { appendSessionOutput, sendOutput, sendStatus, sessions, } from "./session-output.js";
8
+ import { getRuntimeAccessToken } from "./runtime-binding.js";
8
9
  vi.mock("axios", () => ({
9
10
  default: {
10
11
  post: vi.fn(),
@@ -20,6 +21,7 @@ vi.mock("../utils/logger.js", () => ({
20
21
  }));
21
22
  const mockedAxiosPost = axios.post;
22
23
  const mockedLogger = vi.mocked(logger);
24
+ const mockedGetRuntimeAccessToken = vi.mocked(getRuntimeAccessToken);
23
25
  const createSession = (overrides = {}) => ({
24
26
  agentId: "agent-1",
25
27
  workspacePath: "D:/workspace",
@@ -133,4 +135,43 @@ describe("session-output service", () => {
133
135
  sourceEventType: "text_delta",
134
136
  }, { headers: { "X-Runtime-Token": "session-runtime-token" } });
135
137
  });
138
+ it("uses launch scheduler URL for Docker-deployed scheduler callbacks", async () => {
139
+ mockedAxiosPost.mockResolvedValue({ data: { ok: true } });
140
+ await sendStatus("agent-1", "session-1", "thinking", undefined, undefined, {
141
+ runtimeAccessToken: "session-runtime-token",
142
+ schedulerBaseUrl: "http://127.0.0.1:7380",
143
+ });
144
+ await sendOutput("agent-1", "[ACode] 正在请求模型 gpt-test:hello", "session-1", 8, { sourceEventType: "ai_request", logCategory: "acode" }, {
145
+ runtimeAccessToken: "session-runtime-token",
146
+ schedulerBaseUrl: "http://127.0.0.1:7380",
147
+ });
148
+ expect(mockedAxiosPost).toHaveBeenNthCalledWith(1, "http://127.0.0.1:7380/api/runtime/callback/status", {
149
+ agentId: "agent-1",
150
+ sessionId: "session-1",
151
+ status: "thinking",
152
+ }, { headers: { "X-Runtime-Token": "session-runtime-token" } });
153
+ expect(mockedAxiosPost).toHaveBeenNthCalledWith(2, "http://127.0.0.1:7380/api/runtime/callback/output", {
154
+ agentId: "agent-1",
155
+ output: "[ACode] 正在请求模型 gpt-test:hello",
156
+ sessionId: "session-1",
157
+ seq: 8,
158
+ sourceEventType: "ai_request",
159
+ logCategory: "acode",
160
+ }, { headers: { "X-Runtime-Token": "session-runtime-token" } });
161
+ });
162
+ it("looks up persisted runtime token by launch scheduler URL when explicit token is missing", async () => {
163
+ mockedAxiosPost.mockResolvedValueOnce({ data: { ok: true } });
164
+ mockedGetRuntimeAccessToken.mockImplementationOnce((_, serverBaseUrl) => serverBaseUrl === "http://127.0.0.1:7380"
165
+ ? "scoped-7380-token"
166
+ : undefined);
167
+ await sendStatus("agent-1", "session-1", "thinking", undefined, undefined, {
168
+ schedulerBaseUrl: "http://127.0.0.1:7380",
169
+ });
170
+ expect(mockedGetRuntimeAccessToken).toHaveBeenNthCalledWith(1, undefined, "http://127.0.0.1:7380");
171
+ expect(mockedAxiosPost).toHaveBeenCalledWith("http://127.0.0.1:7380/api/runtime/callback/status", {
172
+ agentId: "agent-1",
173
+ sessionId: "session-1",
174
+ status: "thinking",
175
+ }, { headers: { "X-Runtime-Token": "scoped-7380-token" } });
176
+ });
136
177
  });
@@ -33,6 +33,7 @@ export declare class ACodeRuntime extends EventEmitter {
33
33
  private requestChatCompletion;
34
34
  private readChatCompletionStream;
35
35
  private handleToolCalls;
36
+ private callMcpToolWithTimeout;
36
37
  private appendSyntheticMultimodalUserMessage;
37
38
  private appendToolFailureResult;
38
39
  private connectMcpServers;
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAiB3C,OAAO,KAAK,EAOV,kBAAkB,EAEnB,MAAM,YAAY,CAAC;AA44BpB,qBAAa,YAAa,SAAQ,YAAY;IAmChC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAlCnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IAEvC,OAAO,CAAC,KAAK,CAoBX;IAEF,OAAO,CAAC,eAAe,CAAgC;IAEvD,OAAO,CAAC,WAAW,CAAoC;IAEvD,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO,CAAC,cAAc,CAAS;IAE/B,OAAO,CAAC,sBAAsB,CAAS;gBAEV,MAAM,EAAE,kBAAkB;IAevD,OAAO,CAAC,cAAc;IAatB;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAwF5B;;;;OAIG;IACG,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAM9B,aAAa;IA2E3B,oDAAoD;IAC9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B,uCAAuC;IACjC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA8B3B,OAAO,CAAC,kBAAkB;YAaZ,YAAY;YA6DZ,qBAAqB;YAiHrB,wBAAwB;YA6ExB,eAAe;YAwJf,oCAAoC;IAkBlD,OAAO,CAAC,uBAAuB;YAuBjB,iBAAiB;IA2C/B,OAAO,CAAC,kBAAkB;YA2BZ,oBAAoB;CAiBnC"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAiB3C,OAAO,KAAK,EAOV,kBAAkB,EAEnB,MAAM,YAAY,CAAC;AAuoCpB,qBAAa,YAAa,SAAQ,YAAY;IAmChC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAlCnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IAEvC,OAAO,CAAC,KAAK,CAoBX;IAEF,OAAO,CAAC,eAAe,CAAgC;IAEvD,OAAO,CAAC,WAAW,CAAoC;IAEvD,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO,CAAC,cAAc,CAAS;IAE/B,OAAO,CAAC,sBAAsB,CAAS;gBAEV,MAAM,EAAE,kBAAkB;IAevD,OAAO,CAAC,cAAc;IAatB;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAyF5B;;;;OAIG;IACG,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAM9B,aAAa;IA2E3B,oDAAoD;IAC9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B,uCAAuC;IACjC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA8B3B,OAAO,CAAC,kBAAkB;YAaZ,YAAY;YAoEZ,qBAAqB;YA4JrB,wBAAwB;YA6ExB,eAAe;YAoJf,sBAAsB;YAqCtB,oCAAoC;IAkBlD,OAAO,CAAC,uBAAuB;YAuBjB,iBAAiB;IA2C/B,OAAO,CAAC,kBAAkB;YA2BZ,oBAAoB;CAiBnC"}