aws-runtime-bridge 1.9.0 → 1.9.2

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 (117) hide show
  1. package/dist/adapter/AcodeSdkAdapter.d.ts +2 -0
  2. package/dist/adapter/AcodeSdkAdapter.d.ts.map +1 -1
  3. package/dist/adapter/AcodeSdkAdapter.js +84 -18
  4. package/dist/adapter/AcodeSdkAdapter.test.js +275 -13
  5. package/dist/adapter/acode-tool-names.d.ts +16 -0
  6. package/dist/adapter/acode-tool-names.d.ts.map +1 -0
  7. package/dist/adapter/acode-tool-names.js +37 -0
  8. package/dist/adapter/acode-tool-names.test.d.ts +2 -0
  9. package/dist/adapter/acode-tool-names.test.d.ts.map +1 -0
  10. package/dist/adapter/acode-tool-names.test.js +28 -0
  11. package/dist/adapter/types.d.ts +22 -3
  12. package/dist/adapter/types.d.ts.map +1 -1
  13. package/dist/adapter/types.js +2 -1
  14. package/dist/config.d.ts +0 -4
  15. package/dist/config.d.ts.map +1 -1
  16. package/dist/config.js +0 -4
  17. package/dist/index.js +1 -1
  18. package/dist/routes/ai-sources.js +18 -14
  19. package/dist/routes/git.d.ts +10 -0
  20. package/dist/routes/git.d.ts.map +1 -1
  21. package/dist/routes/git.js +37 -3
  22. package/dist/routes/git.test.js +47 -1
  23. package/dist/routes/sessions.d.ts +1 -1
  24. package/dist/routes/sessions.d.ts.map +1 -1
  25. package/dist/routes/sessions.js +11 -4
  26. package/dist/routes/sessions.test.js +3 -0
  27. package/dist/routes/terminal.d.ts +28 -8
  28. package/dist/routes/terminal.d.ts.map +1 -1
  29. package/dist/routes/terminal.js +266 -44
  30. package/dist/routes/terminal.stop-options.test.d.ts +2 -0
  31. package/dist/routes/terminal.stop-options.test.d.ts.map +1 -0
  32. package/dist/routes/terminal.stop-options.test.js +39 -0
  33. package/dist/routes/terminal.test.js +87 -4
  34. package/dist/services/auto-register.d.ts.map +1 -1
  35. package/dist/services/auto-register.js +4 -5
  36. package/dist/services/mcp-launch-binding-queue.d.ts +5 -0
  37. package/dist/services/mcp-launch-binding-queue.d.ts.map +1 -1
  38. package/dist/services/mcp-launch-binding-queue.js +17 -0
  39. package/dist/services/mcp-launch-binding-queue.test.js +16 -1
  40. package/dist/services/session-output.d.ts +5 -0
  41. package/dist/services/session-output.d.ts.map +1 -1
  42. package/package/acode/dist/built-in-file-tools.d.ts +5 -1
  43. package/package/acode/dist/built-in-file-tools.d.ts.map +1 -1
  44. package/package/acode/dist/built-in-file-tools.js +14 -203
  45. package/package/acode/dist/builtins/commandArtifacts.d.ts +25 -0
  46. package/package/acode/dist/builtins/commandArtifacts.d.ts.map +1 -0
  47. package/package/acode/dist/builtins/commandArtifacts.js +77 -0
  48. package/package/acode/dist/builtins/commandOutputEvents.d.ts +21 -0
  49. package/package/acode/dist/builtins/commandOutputEvents.d.ts.map +1 -0
  50. package/package/acode/dist/builtins/commandOutputEvents.js +56 -0
  51. package/package/acode/dist/builtins/shellCommandPreparation.d.ts +15 -0
  52. package/package/acode/dist/builtins/shellCommandPreparation.d.ts.map +1 -0
  53. package/package/acode/dist/builtins/shellCommandPreparation.js +44 -0
  54. package/package/acode/dist/builtins/shellCommandResult.d.ts +30 -0
  55. package/package/acode/dist/builtins/shellCommandResult.d.ts.map +1 -0
  56. package/package/acode/dist/builtins/shellCommandResult.js +71 -0
  57. package/package/acode/dist/builtins/shellCommandRunner.d.ts +14 -0
  58. package/package/acode/dist/builtins/shellCommandRunner.d.ts.map +1 -0
  59. package/package/acode/dist/builtins/shellCommandRunner.js +114 -0
  60. package/package/acode/dist/builtins/shellOutputDecoder.d.ts +5 -0
  61. package/package/acode/dist/builtins/shellOutputDecoder.d.ts.map +1 -0
  62. package/package/acode/dist/builtins/shellOutputDecoder.js +30 -0
  63. package/package/acode/dist/mcpToolNames.d.ts +11 -0
  64. package/package/acode/dist/mcpToolNames.d.ts.map +1 -0
  65. package/package/acode/dist/mcpToolNames.js +17 -0
  66. package/package/acode/dist/runtime.d.ts +19 -0
  67. package/package/acode/dist/runtime.d.ts.map +1 -1
  68. package/package/acode/dist/runtime.js +233 -35
  69. package/package/acode/dist/types.d.ts +1 -1
  70. package/package/acode/dist/types.d.ts.map +1 -1
  71. package/package/acode/package.json +1 -1
  72. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +20 -0
  73. package/package/aws-client-agent-mcp/dist/agent-client.d.ts.map +1 -1
  74. package/package/aws-client-agent-mcp/dist/agent-client.js +71 -2
  75. package/package/aws-client-agent-mcp/dist/agent-client.js.map +1 -1
  76. package/package/aws-client-agent-mcp/dist/constants.d.ts +4 -1
  77. package/package/aws-client-agent-mcp/dist/constants.d.ts.map +1 -1
  78. package/package/aws-client-agent-mcp/dist/constants.js +5 -1
  79. package/package/aws-client-agent-mcp/dist/constants.js.map +1 -1
  80. package/package/aws-client-agent-mcp/dist/http-client.d.ts +17 -1
  81. package/package/aws-client-agent-mcp/dist/http-client.d.ts.map +1 -1
  82. package/package/aws-client-agent-mcp/dist/http-client.js +124 -28
  83. package/package/aws-client-agent-mcp/dist/http-client.js.map +1 -1
  84. package/package/aws-client-agent-mcp/dist/http-client.test.js +108 -2
  85. package/package/aws-client-agent-mcp/dist/http-client.test.js.map +1 -1
  86. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +8 -3
  87. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts.map +1 -1
  88. package/package/aws-client-agent-mcp/dist/mcp-server.js +63 -10
  89. package/package/aws-client-agent-mcp/dist/mcp-server.js.map +1 -1
  90. package/package/aws-client-agent-mcp/dist/mcp-server.test.js +47 -0
  91. package/package/aws-client-agent-mcp/dist/mcp-server.test.js.map +1 -1
  92. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +1 -36
  93. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts.map +1 -1
  94. package/package/aws-client-agent-mcp/dist/mcp-tools.js +3 -169
  95. package/package/aws-client-agent-mcp/dist/mcp-tools.js.map +1 -1
  96. package/package/aws-client-agent-mcp/dist/mcp-tools.test.d.ts +2 -0
  97. package/package/aws-client-agent-mcp/dist/mcp-tools.test.d.ts.map +1 -0
  98. package/package/aws-client-agent-mcp/dist/mcp-tools.test.js +45 -0
  99. package/package/aws-client-agent-mcp/dist/mcp-tools.test.js.map +1 -0
  100. package/package/aws-client-agent-mcp/dist/memory-tools.d.ts +11 -0
  101. package/package/aws-client-agent-mcp/dist/memory-tools.d.ts.map +1 -0
  102. package/package/aws-client-agent-mcp/dist/memory-tools.js +144 -0
  103. package/package/aws-client-agent-mcp/dist/memory-tools.js.map +1 -0
  104. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.d.ts.map +1 -1
  105. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js +79 -28
  106. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js.map +1 -1
  107. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js +35 -0
  108. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js.map +1 -1
  109. package/package/aws-client-agent-mcp/dist/types.d.ts +9 -0
  110. package/package/aws-client-agent-mcp/dist/types.d.ts.map +1 -1
  111. package/package/aws-client-agent-mcp/dist/types.js.map +1 -1
  112. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts.map +1 -1
  113. package/package/aws-client-agent-mcp/dist/websocket-client.js +1 -0
  114. package/package/aws-client-agent-mcp/dist/websocket-client.js.map +1 -1
  115. package/package/aws-client-agent-mcp/dist/websocket-client.test.js +43 -3
  116. package/package/aws-client-agent-mcp/dist/websocket-client.test.js.map +1 -1
  117. 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, buildSdkOutputMetadata, 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, resolveStatusChangeRuntimeState, resolveStatusChangeUsage, shouldProbeSdkProcessPid, } from "./terminal.js";
7
7
  describe("terminal route validation", () => {
8
8
  it("requires agentId and workspacePath for start", () => {
9
9
  const validateStartRequest = (body) => {
@@ -90,6 +90,10 @@ describe("terminal route validation", () => {
90
90
  });
91
91
  });
92
92
  describe("SDK startup idle command ordering", () => {
93
+ it("skips PID probing for in-process ACode sessions", () => {
94
+ expect(shouldProbeSdkProcessPid("acode")).toBe(false);
95
+ expect(shouldProbeSdkProcessPid("claude-code")).toBe(true);
96
+ });
93
97
  it("sets idle commands immediately after adapter startup and before PID probing or persistence", async () => {
94
98
  const calls = [];
95
99
  const adapter = {
@@ -217,10 +221,19 @@ describe("SDK provider event runtime status mapping", () => {
217
221
  expect(resolveRuntimeStatusFromProviderEvent(event("thinking"))?.status).toBe("thinking");
218
222
  expect(resolveRuntimeStatusFromProviderEvent(event("text_delta"))?.status).toBe("thinking");
219
223
  });
224
+ it("keeps command output chunks from changing the runtime status", () => {
225
+ expect(resolveRuntimeStatusFromProviderEvent(event("command_output", { text: "stdout chunk", stream: "stdout" }))).toBeUndefined();
226
+ });
220
227
  it("maps AI request events to thinking status with request details", () => {
221
228
  const state = resolveRuntimeStatusFromProviderEvent(event("ai_request", {
222
229
  model: "test-model",
223
230
  endpoint: "https://example.invalid/v1/chat/completions",
231
+ requestMethod: "POST",
232
+ requestUrl: "https://example.invalid/v1/chat/completions",
233
+ requestHeaders: {
234
+ "Content-Type": "application/json",
235
+ Authorization: "Bearer ***",
236
+ },
224
237
  stream: true,
225
238
  messageCount: 3,
226
239
  toolCount: 2,
@@ -234,9 +247,25 @@ describe("SDK provider event runtime status mapping", () => {
234
247
  });
235
248
  expect(state?.actionInfo?.actionDetail).toContain("模型: test-model");
236
249
  expect(state?.actionInfo?.actionDetail).toContain("接口: https://example.invalid/v1/chat/completions");
250
+ expect(state?.actionInfo?.actionDetail).toContain("方法: POST");
251
+ expect(state?.actionInfo?.actionDetail).toContain("请求头:\nContent-Type: application/json\nAuthorization: Bearer ***");
237
252
  expect(state?.actionInfo?.actionDetail).toContain("最后请求: inspect status");
238
253
  expect(state?.actionInfo?.actionDetail).toContain('请求体:\n{"model":"test-model"}');
239
254
  });
255
+ it("does not let idle polling text chunks override waiting_input", () => {
256
+ expect(resolveRuntimeStatusFromProviderEvent(event("thinking"), "waiting_input")).toBeUndefined();
257
+ expect(resolveRuntimeStatusFromProviderEvent(event("text_delta"), "waiting_input")).toBeUndefined();
258
+ });
259
+ it("still reports AI request details when a request starts from waiting_input", () => {
260
+ expect(resolveRuntimeStatusFromProviderEvent(event("ai_request", {
261
+ model: "test-model",
262
+ requestBody: '{"model":"test-model"}',
263
+ }), "waiting_input")?.actionInfo).toMatchObject({
264
+ actionType: "ai_request",
265
+ actionLabel: "AI请求",
266
+ actionDetail: expect.stringContaining('请求体:\n{"model":"test-model"}'),
267
+ });
268
+ });
240
269
  it("maps tool start events to tool_using with action info", () => {
241
270
  const state = resolveRuntimeStatusFromProviderEvent(event("tool_use_start", {
242
271
  toolName: "mcp__aws__my_task",
@@ -315,8 +344,8 @@ describe("terminal command helpers", () => {
315
344
  expect(outputPath).toBe(path.join("D:", "code", "repo", ".agentswork", "acode", "cmd-dist", "2026-02-03", "04", "05", "20260203-040506-007-cmd.out"));
316
345
  });
317
346
  it("formats ACode long-output and inactivity notices for terminal users", () => {
318
- expect(formatCommandOutputSpilloverNotice("/repo/out.txt", 100)).toContain("命令输出超过 100 行");
319
- expect(formatCommandOutputSpilloverNotice("/repo/out.txt", 100)).toContain("/repo/out.txt");
347
+ expect(formatCommandOutputSpilloverNotice("/repo/out.txt", 300)).toContain("命令输出超过 300 行");
348
+ expect(formatCommandOutputSpilloverNotice("/repo/out.txt", 300)).toContain("/repo/out.txt");
320
349
  expect(formatCommandInactivityTimeoutNotice(60_000)).toContain("超过 60 秒没有新的输出");
321
350
  });
322
351
  });
@@ -343,6 +372,20 @@ describe("resolveSdkProviderId", () => {
343
372
  });
344
373
  });
345
374
  describe("SDK status usage forwarding", () => {
375
+ it("normalizes idle tool status changes to waiting_input", () => {
376
+ expect(resolveStatusChangeRuntimeState("tool_using", {
377
+ actionType: "idle",
378
+ actionLabel: "监听消息",
379
+ actionDetail: "aws-mcp/poll_message",
380
+ })).toEqual({
381
+ status: "waiting_input",
382
+ actionInfo: {
383
+ actionType: "idle",
384
+ actionLabel: "监听消息",
385
+ actionDetail: "aws-mcp/poll_message",
386
+ },
387
+ });
388
+ });
346
389
  it("keeps accumulated usage from status-change action info", () => {
347
390
  expect(resolveStatusChangeUsage({
348
391
  usage: { inputTokens: 12000, outputTokens: 345 },
@@ -435,6 +478,20 @@ describe("SDK output forwarding", () => {
435
478
  };
436
479
  expect(formatSdkOutputEvent(thinkingEvent)).toBe("internal prompt or reasoning");
437
480
  });
481
+ it("formats command output provider events as realtime output chunks", () => {
482
+ const commandOutputEvent = {
483
+ type: "command_output",
484
+ sessionId: "session-1",
485
+ timestamp: new Date(0).toISOString(),
486
+ data: {
487
+ text: "stdout chunk",
488
+ stream: "stdout",
489
+ sequence: 7,
490
+ cwd: "/repo",
491
+ },
492
+ };
493
+ expect(formatSdkOutputEvent(commandOutputEvent)).toBe("stdout chunk");
494
+ });
438
495
  it("formats SDK errors as terminal output and ignores non-output events", () => {
439
496
  const errorEvent = {
440
497
  type: "error",
@@ -468,7 +525,11 @@ describe("SDK output forwarding", () => {
468
525
  type: "ai_request",
469
526
  sessionId: "session-1",
470
527
  timestamp: new Date(0).toISOString(),
471
- data: { model: "test-model", endpoint: "openai-compatible", toolCount: 2 },
528
+ data: {
529
+ model: "test-model",
530
+ endpoint: "openai-compatible",
531
+ toolCount: 2,
532
+ },
472
533
  };
473
534
  const errorEvent = {
474
535
  type: "error",
@@ -489,6 +550,28 @@ describe("SDK output forwarding", () => {
489
550
  logMessage: "provider failed",
490
551
  });
491
552
  });
553
+ it("builds ordered ACode log metadata for command output callbacks", () => {
554
+ const commandOutputEvent = {
555
+ type: "command_output",
556
+ sessionId: "session-1",
557
+ timestamp: new Date(0).toISOString(),
558
+ data: {
559
+ text: "stdout chunk",
560
+ stream: "stdout",
561
+ sequence: 7,
562
+ cwd: "/repo",
563
+ },
564
+ };
565
+ expect(buildSdkOutputMetadata(commandOutputEvent)).toEqual({
566
+ sourceEventType: "command_output",
567
+ logCategory: "acode",
568
+ logLevel: "info",
569
+ logMessage: "命令输出(stdout #7): stdout chunk",
570
+ stream: "stdout",
571
+ sequence: 7,
572
+ cwd: "/repo",
573
+ });
574
+ });
492
575
  it("does not mark streaming text chunks as standalone ACode log rows", () => {
493
576
  const metadata = buildSdkOutputMetadata({
494
577
  type: "text_delta",
@@ -1 +1 @@
1
- {"version":3,"file":"auto-register.d.ts","sourceRoot":"","sources":["../../src/services/auto-register.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAmDH;;GAEG;AACH,UAAU,kBAAkB;IAC1B,eAAe;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,oBAAoB;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yCAAyC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAwBD,wBAAgB,2BAA2B,IAAI,MAAM,EAAE,CAEtD;AAiED;;GAEG;AACH,wBAAgB,6BAA6B,IAAI,MAAM,CAGtD;AAyJD;;;;;;GAMG;AACH,wBAAgB,UAAU,IAAI,kBAAkB,CA2C/C;AAED,wBAAgB,WAAW,IAAI,kBAAkB,EAAE,CA0ClD;AA2PD;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAChC,YAAY,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GACzC,OAAO,CAAC,OAAO,CAAC,CAalB;AAyHD;;GAEG;AACH,wBAAsB,gCAAgC,IAAI,OAAO,CAAC;IAChE,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CAoED;AAED,wBAAsB,yCAAyC,CAC7D,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC;IACT,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CA0ED;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAgCnD;AAED;;GAEG;AACH,wBAAgB,oBAAoB;gBAh6BtB,OAAO;iBACN,MAAM;mBACJ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;kBACvB,IAAI;YACV,MAAM;EA85Bf;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,GAAG,SAAS,CAElD;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC;IACpD,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CA0ED"}
1
+ {"version":3,"file":"auto-register.d.ts","sourceRoot":"","sources":["../../src/services/auto-register.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAmDH;;GAEG;AACH,UAAU,kBAAkB;IAC1B,eAAe;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,oBAAoB;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yCAAyC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAuBD,wBAAgB,2BAA2B,IAAI,MAAM,EAAE,CAEtD;AAiED;;GAEG;AACH,wBAAgB,6BAA6B,IAAI,MAAM,CAGtD;AAyJD;;;;;;GAMG;AACH,wBAAgB,UAAU,IAAI,kBAAkB,CA2C/C;AAED,wBAAgB,WAAW,IAAI,kBAAkB,EAAE,CA0ClD;AA2PD;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAChC,YAAY,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GACzC,OAAO,CAAC,OAAO,CAAC,CAalB;AAyHD;;GAEG;AACH,wBAAsB,gCAAgC,IAAI,OAAO,CAAC;IAChE,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CAoED;AAED,wBAAsB,yCAAyC,CAC7D,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC;IACT,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CA0ED;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAgCnD;AAED;;GAEG;AACH,wBAAgB,oBAAoB;gBAh6BtB,OAAO;iBACN,MAAM;mBACJ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;kBACvB,IAAI;YACV,MAAM;EA85Bf;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,GAAG,SAAS,CAElD;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC;IACpD,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CA0ED"}
@@ -14,13 +14,12 @@ import fs from "node:fs";
14
14
  import { logger } from "../utils/logger.js";
15
15
  import { schedulerBaseUrl } from "../config.js";
16
16
  import { clearRuntimeBinding, clearScopedRuntimeAccessToken, getRuntimeAccessToken, getRuntimeBindingPublicState, loadRuntimeBinding, normalizeSchedulerBaseUrl, saveRuntimeBinding, saveScopedRuntimeAccessToken, } from "./runtime-binding.js";
17
- // 默认配置
18
17
  const DEFAULT_CONFIG = {
19
18
  enabled: false,
20
19
  serverUrl: schedulerBaseUrl,
21
20
  preferSameLanIp: true,
22
- maxRetries: 5,
23
- retryInterval: 5000,
21
+ maxRetries: 3,
22
+ retryInterval: 2000,
24
23
  };
25
24
  let registrationState = {
26
25
  registered: false,
@@ -533,8 +532,8 @@ async function autoRegisterSingle(config) {
533
532
  return false;
534
533
  }
535
534
  // tenantId 现在是可选的,如果没有提供,后端会根据 userKey 自动推导
536
- const maxRetries = config.maxRetries || 5;
537
- const retryInterval = config.retryInterval || 5000;
535
+ const maxRetries = config.maxRetries ?? 3;
536
+ const retryInterval = config.retryInterval ?? 2000;
538
537
  // 重试循环
539
538
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
540
539
  try {
@@ -31,6 +31,11 @@ export interface McpLaunchBindingClaimRequest {
31
31
  export declare function enqueueMcpLaunchBinding(input: McpLaunchBindingInput): McpLaunchBinding | null;
32
32
  export declare function claimMcpLaunchBinding(request: McpLaunchBindingClaimRequest): ClaimedMcpLaunchBinding | null;
33
33
  export declare function getMcpLaunchQueueSize(workspacePath: unknown): number;
34
+ /**
35
+ * 主流程:按启动绑定 ID 移除尚未被 MCP node 认领的绑定。
36
+ * 具体逻辑:启动流程失败时调用;若绑定已被认领或 ID 不存在则返回 false,保持幂等。
37
+ */
38
+ export declare function removeMcpLaunchBinding(bindingId: string): boolean;
34
39
  export declare function clearMcpLaunchBindingQueues(): void;
35
40
  /**
36
41
  * 获取指定 agent 的最新 MCP session token。
@@ -1 +1 @@
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"}
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;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAcjE;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"}
@@ -142,6 +142,23 @@ export function getMcpLaunchQueueSize(workspacePath) {
142
142
  }
143
143
  return launchBindings.filter((binding) => normalizeWorkspacePath(binding.workspacePath) === workspaceKey).length;
144
144
  }
145
+ /**
146
+ * 主流程:按启动绑定 ID 移除尚未被 MCP node 认领的绑定。
147
+ * 具体逻辑:启动流程失败时调用;若绑定已被认领或 ID 不存在则返回 false,保持幂等。
148
+ */
149
+ export function removeMcpLaunchBinding(bindingId) {
150
+ pruneExpiredBindings();
151
+ const normalizedId = String(bindingId || "").trim();
152
+ if (!normalizedId) {
153
+ return false;
154
+ }
155
+ const index = launchBindings.findIndex((binding) => binding.id === normalizedId);
156
+ if (index < 0) {
157
+ return false;
158
+ }
159
+ launchBindings.splice(index, 1);
160
+ return true;
161
+ }
145
162
  export function clearMcpLaunchBindingQueues() {
146
163
  launchBindings.splice(0, launchBindings.length);
147
164
  }
@@ -1,5 +1,5 @@
1
1
  import { afterEach, describe, expect, it } from 'vitest';
2
- import { claimMcpLaunchBinding, clearMcpLaunchBindingQueues, enqueueMcpLaunchBinding, getMcpLaunchQueueSize, } from './mcp-launch-binding-queue.js';
2
+ import { claimMcpLaunchBinding, clearMcpLaunchBindingQueues, enqueueMcpLaunchBinding, getMcpLaunchQueueSize, removeMcpLaunchBinding, } from './mcp-launch-binding-queue.js';
3
3
  describe('mcp launch binding queue', () => {
4
4
  afterEach(() => {
5
5
  clearMcpLaunchBindingQueues();
@@ -157,6 +157,21 @@ describe('mcp launch binding queue', () => {
157
157
  expect(claimMcpLaunchBinding({ workspacePath: 'C:/repo/b', serverUrl: 'ws://server:7380/ws/agent' })?.agentId).toBe('agent-b');
158
158
  expect(claimMcpLaunchBinding({ workspacePath: 'C:/repo/a', serverUrl: 'ws://server:7380/ws/agent' })?.agentId).toBe('agent-a');
159
159
  });
160
+ it('removes a stale launch binding by id after a failed start', () => {
161
+ const binding = enqueueMcpLaunchBinding({
162
+ agentId: 'agent-a',
163
+ workspacePath: 'C:/repo/demo',
164
+ serverUrl: 'ws://server:7380/ws/agent',
165
+ });
166
+ expect(binding).not.toBeNull();
167
+ expect(removeMcpLaunchBinding(binding?.id || '')).toBe(true);
168
+ expect(claimMcpLaunchBinding({
169
+ agentId: 'agent-a',
170
+ workspacePath: 'C:/repo/demo',
171
+ serverUrl: 'ws://server:7380/ws/agent',
172
+ })).toBeNull();
173
+ expect(getMcpLaunchQueueSize('C:/repo/demo')).toBe(0);
174
+ });
160
175
  it('returns null for missing or invalid workspaces', () => {
161
176
  expect(enqueueMcpLaunchBinding({ agentId: '', workspacePath: 'C:/repo/demo' })).toBeNull();
162
177
  expect(enqueueMcpLaunchBinding({ agentId: 'agent-a', workspacePath: '' })).toBeNull();
@@ -21,6 +21,11 @@ export interface RuntimeOutputMetadata {
21
21
  logLevel?: "info" | "warn" | "error";
22
22
  logMessage?: string;
23
23
  logCategory?: string;
24
+ stream?: string;
25
+ sequence?: number;
26
+ cwd?: string;
27
+ commandFilePath?: string;
28
+ commandLineCount?: number;
24
29
  }
25
30
  /** 活跃会话存储 */
26
31
  export declare const sessions: Map<string, Session>;
@@ -1 +1 @@
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"}
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;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;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"}
@@ -1,3 +1,4 @@
1
+ import { type CommandOutputSink } from "./builtins/shellCommandRunner.js";
1
2
  export type JsonValue = string | number | boolean | null | JsonValue[] | {
2
3
  [key: string]: JsonValue;
3
4
  };
@@ -10,7 +11,10 @@ export interface ACodeBuiltInTool {
10
11
  exposedName: string;
11
12
  description: string;
12
13
  inputSchema: JsonObject;
13
- execute(args: JsonObject): Promise<unknown>;
14
+ execute(args: JsonObject, context?: ACodeBuiltInToolExecutionContext): Promise<unknown>;
15
+ }
16
+ export interface ACodeBuiltInToolExecutionContext {
17
+ readonly onOutput?: CommandOutputSink;
14
18
  }
15
19
  export declare function createBuiltInFileTools(workingDirectory: string): ACodeBuiltInTool[];
16
20
  //# sourceMappingURL=built-in-file-tools.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"built-in-file-tools.d.ts","sourceRoot":"","sources":["../src/built-in-file-tools.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,EAAE,GACX;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AACjC,MAAM,MAAM,UAAU,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEtD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,UAAU,CAAC;IACxB,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7C;AAyvBD,wBAAgB,sBAAsB,CACpC,gBAAgB,EAAE,MAAM,GACvB,gBAAgB,EAAE,CAOpB"}
1
+ {"version":3,"file":"built-in-file-tools.d.ts","sourceRoot":"","sources":["../src/built-in-file-tools.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,kCAAkC,CAAC;AAE1C,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,EAAE,GACX;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AACjC,MAAM,MAAM,UAAU,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEtD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,UAAU,CAAC;IACxB,OAAO,CACL,IAAI,EAAE,UAAU,EAChB,OAAO,CAAC,EAAE,gCAAgC,GACzC,OAAO,CAAC,OAAO,CAAC,CAAC;CACrB;AAED,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CACvC;AAsfD,wBAAgB,sBAAsB,CACpC,gBAAgB,EAAE,MAAM,GACvB,gBAAgB,EAAE,CAOpB"}
@@ -1,7 +1,7 @@
1
- import { spawn } from "node:child_process";
2
1
  import { randomUUID } from "node:crypto";
3
2
  import { promises as fs } from "node:fs";
4
3
  import path from "node:path";
4
+ import { runShellCommand, } from "./builtins/shellCommandRunner.js";
5
5
  function toDisplayPath(targetPath) {
6
6
  return targetPath.replace(/\\/g, "/");
7
7
  }
@@ -178,208 +178,10 @@ async function readFileInsideWorkspace(workingDirectory, filePath) {
178
178
  content: await fs.readFile(realTargetPath, "utf-8"),
179
179
  };
180
180
  }
181
- const DEFAULT_COMMAND_TIMEOUT_MS = 30_000;
182
181
  const MAX_COMMAND_TIMEOUT_MS = 10 * 60_000;
182
+ const DEFAULT_COMMAND_TIMEOUT_MS = MAX_COMMAND_TIMEOUT_MS;
183
183
  const DEFAULT_COMMAND_INACTIVITY_TIMEOUT_MS = 60_000;
184
184
  const MAX_COMMAND_INACTIVITY_TIMEOUT_MS = 10 * 60_000;
185
- const MAX_COMMAND_OUTPUT_BYTES = 128 * 1024;
186
- const COMMAND_OUTPUT_SPILLOVER_LINE_LIMIT = 100;
187
- function padDatePart(value) {
188
- return String(value).padStart(2, "0");
189
- }
190
- function countOutputLines(output) {
191
- if (!output) {
192
- return 0;
193
- }
194
- const normalized = output.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
195
- const withoutTrailingLineBreak = normalized.endsWith("\n")
196
- ? normalized.slice(0, -1)
197
- : normalized;
198
- return withoutTrailingLineBreak
199
- ? withoutTrailingLineBreak.split("\n").length
200
- : 1;
201
- }
202
- function buildCommandOutputSpilloverPath(workspaceRoot, now = new Date()) {
203
- const year = now.getFullYear();
204
- const month = padDatePart(now.getMonth() + 1);
205
- const day = padDatePart(now.getDate());
206
- const hour = padDatePart(now.getHours());
207
- const minute = padDatePart(now.getMinutes());
208
- const timestamp = `${year}${month}${day}-${hour}${minute}${padDatePart(now.getSeconds())}-${String(now.getMilliseconds()).padStart(3, "0")}-${process.pid}-${randomUUID().slice(0, 8)}`;
209
- return path.join(workspaceRoot, ".agentswork", "acode", "cmd-dist", `${year}-${month}-${day}`, hour, minute, `${timestamp}-cmd.out`);
210
- }
211
- async function writeCommandOutputSpilloverFile(workspaceRoot, content) {
212
- const targetPath = buildCommandOutputSpilloverPath(workspaceRoot);
213
- await fs.mkdir(path.dirname(targetPath), { recursive: true });
214
- await fs.writeFile(targetPath, content, "utf-8");
215
- return targetPath;
216
- }
217
- function buildCommandOutputSpilloverContent(input) {
218
- return [
219
- `Command: ${input.commandText}`,
220
- `CWD: ${input.cwd}`,
221
- `Started: ${input.startedAt.toISOString()}`,
222
- `Ended: ${input.endedAt.toISOString()}`,
223
- `Exit code: ${input.exitCode ?? "null"}`,
224
- `Signal: ${input.signal ?? "null"}`,
225
- `Timed out: ${input.timedOut}`,
226
- `Timed out by inactivity: ${input.inactivityTimedOut}`,
227
- "",
228
- "--- stdout ---",
229
- input.stdout,
230
- "",
231
- "--- stderr ---",
232
- input.stderr,
233
- ].join("\n");
234
- }
235
- function formatCommandOutputSpilloverStdout(outputFilePath, outputLineCount) {
236
- return [
237
- `[ACode] 命令输出超过 ${COMMAND_OUTPUT_SPILLOVER_LINE_LIMIT} 行(共 ${outputLineCount} 行),完整输出已写入: ${toDisplayPath(outputFilePath)}`,
238
- "[ACode] Agent 可自行读取该文件,或在该文件中搜索需要的内容。",
239
- "",
240
- ].join("\n");
241
- }
242
- function truncateOutput(value) {
243
- const bytes = Buffer.byteLength(value, "utf-8");
244
- if (bytes <= MAX_COMMAND_OUTPUT_BYTES) {
245
- return { text: value, truncated: false };
246
- }
247
- const buffer = Buffer.from(value, "utf-8");
248
- return {
249
- text: buffer.subarray(0, MAX_COMMAND_OUTPUT_BYTES).toString("utf-8") +
250
- `\n...[truncated after ${MAX_COMMAND_OUTPUT_BYTES} bytes]`,
251
- truncated: true,
252
- };
253
- }
254
- function shellExecutable() {
255
- if (process.platform === "win32") {
256
- return {
257
- command: process.env.ComSpec || "cmd.exe",
258
- argsPrefix: ["/d", "/s", "/c"],
259
- };
260
- }
261
- return { command: process.env.SHELL || "/bin/sh", argsPrefix: ["-lc"] };
262
- }
263
- function runShellCommand(commandText, workspaceRoot, cwd, timeoutMs, inactivityTimeoutMs) {
264
- return new Promise((resolve, reject) => {
265
- const shell = shellExecutable();
266
- const startedAt = new Date();
267
- const child = spawn(shell.command, [...shell.argsPrefix, commandText], {
268
- cwd,
269
- env: process.env,
270
- windowsHide: true,
271
- });
272
- let stdout = "";
273
- let stderr = "";
274
- let timedOut = false;
275
- let inactivityTimedOut = false;
276
- let killEscalationTimer;
277
- let inactivityTimer;
278
- const escalateKill = () => {
279
- killEscalationTimer = setTimeout(() => {
280
- if (!child.killed) {
281
- child.kill("SIGKILL");
282
- }
283
- }, 1000);
284
- killEscalationTimer.unref?.();
285
- };
286
- const timer = setTimeout(() => {
287
- timedOut = true;
288
- child.kill("SIGTERM");
289
- escalateKill();
290
- }, timeoutMs);
291
- timer.unref?.();
292
- const resetInactivityTimer = () => {
293
- if (inactivityTimer) {
294
- clearTimeout(inactivityTimer);
295
- }
296
- inactivityTimer = setTimeout(() => {
297
- inactivityTimedOut = true;
298
- timedOut = true;
299
- child.kill("SIGTERM");
300
- escalateKill();
301
- }, inactivityTimeoutMs);
302
- inactivityTimer.unref?.();
303
- };
304
- resetInactivityTimer();
305
- child.stdout?.setEncoding("utf-8");
306
- child.stderr?.setEncoding("utf-8");
307
- child.stdout?.on("data", (chunk) => {
308
- stdout += chunk;
309
- resetInactivityTimer();
310
- });
311
- child.stderr?.on("data", (chunk) => {
312
- stderr += chunk;
313
- resetInactivityTimer();
314
- });
315
- child.on("error", (error) => {
316
- clearTimeout(timer);
317
- if (inactivityTimer) {
318
- clearTimeout(inactivityTimer);
319
- }
320
- if (killEscalationTimer) {
321
- clearTimeout(killEscalationTimer);
322
- }
323
- reject(error);
324
- });
325
- child.on("close", async (exitCode, signal) => {
326
- clearTimeout(timer);
327
- if (inactivityTimer) {
328
- clearTimeout(inactivityTimer);
329
- }
330
- if (killEscalationTimer) {
331
- clearTimeout(killEscalationTimer);
332
- }
333
- const endedAt = new Date();
334
- const outputLineCount = countOutputLines(`${stdout}${stderr}`);
335
- try {
336
- if (outputLineCount > COMMAND_OUTPUT_SPILLOVER_LINE_LIMIT) {
337
- const outputFilePath = await writeCommandOutputSpilloverFile(workspaceRoot, buildCommandOutputSpilloverContent({
338
- commandText,
339
- cwd,
340
- startedAt,
341
- endedAt,
342
- exitCode,
343
- signal,
344
- timedOut,
345
- inactivityTimedOut,
346
- stdout,
347
- stderr,
348
- }));
349
- resolve({
350
- exitCode,
351
- signal,
352
- stdout: formatCommandOutputSpilloverStdout(outputFilePath, outputLineCount),
353
- stderr: "",
354
- durationMs: endedAt.getTime() - startedAt.getTime(),
355
- timedOut,
356
- inactivityTimedOut,
357
- outputSpilled: true,
358
- outputFilePath: toDisplayPath(outputFilePath),
359
- outputLineCount,
360
- });
361
- return;
362
- }
363
- const truncatedStdout = truncateOutput(stdout);
364
- const truncatedStderr = truncateOutput(stderr);
365
- resolve({
366
- exitCode,
367
- signal,
368
- stdout: truncatedStdout.text,
369
- stderr: truncatedStderr.text,
370
- durationMs: endedAt.getTime() - startedAt.getTime(),
371
- timedOut,
372
- inactivityTimedOut,
373
- outputSpilled: false,
374
- outputLineCount,
375
- });
376
- }
377
- catch (error) {
378
- reject(error);
379
- }
380
- });
381
- });
382
- }
383
185
  function writeFileTool(workingDirectory) {
384
186
  return {
385
187
  kind: "builtin",
@@ -512,7 +314,7 @@ function bashTool(workingDirectory) {
512
314
  },
513
315
  timeout_ms: {
514
316
  type: "number",
515
- description: "Optional timeout in milliseconds. Defaults to 30000 and is capped at 600000.",
317
+ description: "Optional timeout in milliseconds. Defaults to 600000 and is capped at 600000.",
516
318
  },
517
319
  inactivity_timeout_ms: {
518
320
  type: "number",
@@ -526,7 +328,7 @@ function bashTool(workingDirectory) {
526
328
  required: ["command"],
527
329
  additionalProperties: false,
528
330
  },
529
- async execute(args) {
331
+ async execute(args, context) {
530
332
  const command = readStringArg(args, ["command"], "command").trim();
531
333
  if (!command) {
532
334
  throw new Error("command must not be empty");
@@ -537,7 +339,14 @@ function bashTool(workingDirectory) {
537
339
  const inactivityTimeoutMs = Math.min(requestedInactivityTimeoutMs, MAX_COMMAND_INACTIVITY_TIMEOUT_MS);
538
340
  const cwdArg = readOptionalStringArg(args, ["cwd"]);
539
341
  const resolved = await resolveWorkspaceDirectory(workingDirectory, cwdArg);
540
- const result = await runShellCommand(command, resolved.workspaceRoot, resolved.cwd, timeoutMs, inactivityTimeoutMs);
342
+ const result = await runShellCommand({
343
+ commandText: command,
344
+ workspaceRoot: resolved.workspaceRoot,
345
+ cwd: resolved.cwd,
346
+ timeoutMs,
347
+ inactivityTimeoutMs,
348
+ onOutput: context?.onOutput,
349
+ });
541
350
  return {
542
351
  ok: result.exitCode === 0 && !result.timedOut,
543
352
  tool: "Bash",
@@ -553,6 +362,8 @@ function bashTool(workingDirectory) {
553
362
  outputSpilled: result.outputSpilled,
554
363
  outputFilePath: result.outputFilePath,
555
364
  outputLineCount: result.outputLineCount,
365
+ commandFilePath: result.commandFilePath,
366
+ commandLineCount: result.commandLineCount,
556
367
  stdout: result.stdout,
557
368
  stderr: result.stderr,
558
369
  };
@@ -0,0 +1,25 @@
1
+ export declare const COMMAND_OUTPUT_SPILLOVER_LINE_LIMIT = 300;
2
+ export declare const LONG_COMMAND_LINE_LIMIT = 300;
3
+ export declare const MAX_COMMAND_OUTPUT_BYTES: number;
4
+ export declare function toDisplayPath(targetPath: string): string;
5
+ export declare function countOutputLines(output: string): number;
6
+ export declare function writeCommandArtifactFile(workspaceRoot: string, suffix: string, extension: string, content: string, now?: Date): Promise<string>;
7
+ export declare function buildCommandOutputSpilloverContent(input: {
8
+ readonly commandText: string;
9
+ readonly commandFilePath?: string;
10
+ readonly commandLineCount: number;
11
+ readonly cwd: string;
12
+ readonly startedAt: Date;
13
+ readonly endedAt: Date;
14
+ readonly exitCode: number | null;
15
+ readonly signal: NodeJS.Signals | null;
16
+ readonly timedOut: boolean;
17
+ readonly inactivityTimedOut: boolean;
18
+ readonly stdout: string;
19
+ readonly stderr: string;
20
+ }): string;
21
+ export declare function formatCommandOutputSpilloverStdout(outputFilePath: string, outputLineCount: number): string;
22
+ export declare function truncateOutput(value: string): {
23
+ readonly text: string;
24
+ };
25
+ //# sourceMappingURL=commandArtifacts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandArtifacts.d.ts","sourceRoot":"","sources":["../../src/builtins/commandArtifacts.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,mCAAmC,MAAM,CAAC;AACvD,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,eAAO,MAAM,wBAAwB,QAAa,CAAC;AAEnD,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAExD;AAMD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAWvD;AA4BD,wBAAsB,wBAAwB,CAC5C,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,GAAG,OAAa,GACf,OAAO,CAAC,MAAM,CAAC,CAUjB;AAED,wBAAgB,kCAAkC,CAAC,KAAK,EAAE;IACxD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,GAAG,MAAM,CAmBT;AAED,wBAAgB,kCAAkC,CAChD,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,MAAM,GACtB,MAAM,CAMR;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAWvE"}