aws-runtime-bridge 1.8.8 → 1.9.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.
Files changed (84) 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/routes/git.d.ts +10 -0
  15. package/dist/routes/git.d.ts.map +1 -1
  16. package/dist/routes/git.js +37 -3
  17. package/dist/routes/git.test.js +47 -1
  18. package/dist/routes/sessions.d.ts +1 -1
  19. package/dist/routes/sessions.d.ts.map +1 -1
  20. package/dist/routes/sessions.js +11 -4
  21. package/dist/routes/sessions.test.js +3 -0
  22. package/dist/routes/terminal.d.ts +28 -8
  23. package/dist/routes/terminal.d.ts.map +1 -1
  24. package/dist/routes/terminal.js +260 -44
  25. package/dist/routes/terminal.stop-options.test.d.ts +2 -0
  26. package/dist/routes/terminal.stop-options.test.d.ts.map +1 -0
  27. package/dist/routes/terminal.stop-options.test.js +39 -0
  28. package/dist/routes/terminal.test.js +87 -4
  29. package/dist/services/session-output.d.ts +5 -0
  30. package/dist/services/session-output.d.ts.map +1 -1
  31. package/package/acode/dist/built-in-file-tools.d.ts +5 -1
  32. package/package/acode/dist/built-in-file-tools.d.ts.map +1 -1
  33. package/package/acode/dist/built-in-file-tools.js +14 -203
  34. package/package/acode/dist/builtins/commandArtifacts.d.ts +25 -0
  35. package/package/acode/dist/builtins/commandArtifacts.d.ts.map +1 -0
  36. package/package/acode/dist/builtins/commandArtifacts.js +77 -0
  37. package/package/acode/dist/builtins/commandOutputEvents.d.ts +21 -0
  38. package/package/acode/dist/builtins/commandOutputEvents.d.ts.map +1 -0
  39. package/package/acode/dist/builtins/commandOutputEvents.js +56 -0
  40. package/package/acode/dist/builtins/shellCommandPreparation.d.ts +15 -0
  41. package/package/acode/dist/builtins/shellCommandPreparation.d.ts.map +1 -0
  42. package/package/acode/dist/builtins/shellCommandPreparation.js +44 -0
  43. package/package/acode/dist/builtins/shellCommandResult.d.ts +30 -0
  44. package/package/acode/dist/builtins/shellCommandResult.d.ts.map +1 -0
  45. package/package/acode/dist/builtins/shellCommandResult.js +71 -0
  46. package/package/acode/dist/builtins/shellCommandRunner.d.ts +14 -0
  47. package/package/acode/dist/builtins/shellCommandRunner.d.ts.map +1 -0
  48. package/package/acode/dist/builtins/shellCommandRunner.js +114 -0
  49. package/package/acode/dist/builtins/shellOutputDecoder.d.ts +5 -0
  50. package/package/acode/dist/builtins/shellOutputDecoder.d.ts.map +1 -0
  51. package/package/acode/dist/builtins/shellOutputDecoder.js +30 -0
  52. package/package/acode/dist/mcpToolNames.d.ts +11 -0
  53. package/package/acode/dist/mcpToolNames.d.ts.map +1 -0
  54. package/package/acode/dist/mcpToolNames.js +17 -0
  55. package/package/acode/dist/runtime.d.ts +19 -0
  56. package/package/acode/dist/runtime.d.ts.map +1 -1
  57. package/package/acode/dist/runtime.js +233 -35
  58. package/package/acode/dist/types.d.ts +1 -1
  59. package/package/acode/dist/types.d.ts.map +1 -1
  60. package/package/acode/package.json +1 -1
  61. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +3 -3
  62. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts.map +1 -1
  63. package/package/aws-client-agent-mcp/dist/mcp-server.js +10 -7
  64. package/package/aws-client-agent-mcp/dist/mcp-server.js.map +1 -1
  65. package/package/aws-client-agent-mcp/dist/mcp-server.test.js +47 -0
  66. package/package/aws-client-agent-mcp/dist/mcp-server.test.js.map +1 -1
  67. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +1 -36
  68. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts.map +1 -1
  69. package/package/aws-client-agent-mcp/dist/mcp-tools.js +3 -169
  70. package/package/aws-client-agent-mcp/dist/mcp-tools.js.map +1 -1
  71. package/package/aws-client-agent-mcp/dist/mcp-tools.test.d.ts +2 -0
  72. package/package/aws-client-agent-mcp/dist/mcp-tools.test.d.ts.map +1 -0
  73. package/package/aws-client-agent-mcp/dist/mcp-tools.test.js +45 -0
  74. package/package/aws-client-agent-mcp/dist/mcp-tools.test.js.map +1 -0
  75. package/package/aws-client-agent-mcp/dist/memory-tools.d.ts +11 -0
  76. package/package/aws-client-agent-mcp/dist/memory-tools.d.ts.map +1 -0
  77. package/package/aws-client-agent-mcp/dist/memory-tools.js +144 -0
  78. package/package/aws-client-agent-mcp/dist/memory-tools.js.map +1 -0
  79. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts.map +1 -1
  80. package/package/aws-client-agent-mcp/dist/websocket-client.js +1 -0
  81. package/package/aws-client-agent-mcp/dist/websocket-client.js.map +1 -1
  82. package/package/aws-client-agent-mcp/dist/websocket-client.test.js +43 -3
  83. package/package/aws-client-agent-mcp/dist/websocket-client.test.js.map +1 -1
  84. package/package.json +1 -1
@@ -17,6 +17,7 @@ type ACodeRuntimeInstance = {
17
17
  start(): Promise<void>;
18
18
  submit(message: string): Promise<void>;
19
19
  abort(): Promise<void>;
20
+ resetContext?(): Promise<void>;
20
21
  stop(): Promise<void>;
21
22
  };
22
23
  type ACodeRuntimeConstructor = new (config: {
@@ -44,6 +45,7 @@ export declare class AcodeSdkAdapter extends EventEmitter implements BaseProvide
44
45
  sendMessage(sessionId: string, message: string): Promise<void>;
45
46
  sendConfirmation(_sessionId: string, _accept: boolean): Promise<void>;
46
47
  abortCurrentTurn(sessionId: string): Promise<void>;
48
+ resetContext(sessionId: string): Promise<void>;
47
49
  terminateSession(sessionId: string): Promise<void>;
48
50
  getConversation(sessionId: string): ConversationMessage[];
49
51
  hasSession(sessionId: string): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"AcodeSdkAdapter.d.ts","sourceRoot":"","sources":["../../src/adapter/AcodeSdkAdapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AcodeSdkAdapter.d.ts","sourceRoot":"","sources":["../../src/adapter/AcodeSdkAdapter.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,7 @@ import { pathToFileURL } from "node:url";
10
10
  import { v4 as uuidv4 } from "uuid";
11
11
  import { getAcodeConfigFile, getAcodeSkillsDir, getRuntimeHomeDir, } from "../config.js";
12
12
  import { getReleasedAcodeEntryPath } from "../services/acode-package.js";
13
+ import { isMessagePollingIdleCommand, isPollMessageToolDescriptor, } from "./acode-tool-names.js";
13
14
  import { IdlePollLoop } from "./idle-poll-loop.js";
14
15
  import { getCanonicalMcpDetail, getToolActionInfo } from "./types.js";
15
16
  const ACODE_AUTO_POLL_PROMPT = [
@@ -24,15 +25,6 @@ const ACODE_AUTO_POLL_DELAY_MS = 250;
24
25
  // avoid busy-looping when the same failure recurs on every retry.
25
26
  const ACODE_AUTO_POLL_FAILURE_DELAY_MS = 2000;
26
27
  const ACODE_MESSAGE_POLLING_IDLE_PROMPT = "系统提醒:当前工作已完成或运行时已进入空闲状态。请立即调用 poll_message 工具阻塞等待新消息和流程线任务提醒;收到流程任务提醒后调用 my_task 查看已由后台静默抢占的任务详情并直接处理;完成任务后调用 submit_task_result 提交结果,然后继续 poll_message。";
27
- function isMessagePollingIdleCommand(command) {
28
- const normalized = command.trim();
29
- if (!normalized)
30
- return false;
31
- const lower = normalized.toLowerCase();
32
- return (lower.includes("poll_message") ||
33
- lower.includes("get_message") ||
34
- normalized.includes("取消息"));
35
- }
36
28
  function getAcodePackageEntryPath() {
37
29
  return path.resolve(getReleasedAcodeEntryPath());
38
30
  }
@@ -66,6 +58,24 @@ function toFiniteTokenCount(...values) {
66
58
  function toEstimatedContextTokens(data) {
67
59
  return toFiniteTokenCount(data.estimatedContextTokens, data.contextTokens, data.context_tokens, data.contextUsedTokens, data.context_used_tokens);
68
60
  }
61
+ function toCommandOutputStream(value) {
62
+ if (value === "stderr" || value === "mixed") {
63
+ return value;
64
+ }
65
+ return "stdout";
66
+ }
67
+ function toStringRecord(value) {
68
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
69
+ return undefined;
70
+ }
71
+ const headers = {};
72
+ for (const [key, headerValue] of Object.entries(value)) {
73
+ if (typeof headerValue === "string") {
74
+ headers[key] = headerValue;
75
+ }
76
+ }
77
+ return Object.keys(headers).length > 0 ? headers : undefined;
78
+ }
69
79
  /**
70
80
  * Check whether an ACode turn_complete event represents a failed turn.
71
81
  * Main flow: only explicit failed=true prevents error status from being reset to waiting_input.
@@ -194,6 +204,31 @@ export class AcodeSdkAdapter extends EventEmitter {
194
204
  async abortCurrentTurn(sessionId) {
195
205
  await this.requireSession(sessionId).runtime.abort();
196
206
  }
207
+ async resetContext(sessionId) {
208
+ const entry = this.requireSession(sessionId);
209
+ this.cancelScheduledAutoPoll(entry);
210
+ entry.failedTurnRecoveryScheduled = false;
211
+ entry.autoPollActive = false;
212
+ entry.autoPollObservedPollingTool = false;
213
+ entry.autoPollObservedAssistantText = false;
214
+ entry.stopAutoPollAfterCurrentTurn = false;
215
+ entry.idlePollLoop?.stop();
216
+ if (!entry.runtime.resetContext) {
217
+ throw new Error("ACode runtime does not support context reset");
218
+ }
219
+ await entry.runtime.resetContext();
220
+ entry.adapterSession.messages = [];
221
+ entry.adapterSession.totalUsage = { inputTokens: 0, outputTokens: 0 };
222
+ entry.adapterSession.status = "waiting_input";
223
+ this.emit("status-change", sessionId, "waiting_input", {
224
+ usage: entry.adapterSession.totalUsage,
225
+ });
226
+ if (entry.config.initialPrompt?.trim()) {
227
+ this.startInitialPromptTurn(sessionId, entry.config.initialPrompt);
228
+ return;
229
+ }
230
+ this.armIdleLoopOrAutoPoll(sessionId);
231
+ }
197
232
  async terminateSession(sessionId) {
198
233
  const entry = this.sessions.get(sessionId);
199
234
  if (!entry) {
@@ -336,6 +371,23 @@ export class AcodeSdkAdapter extends EventEmitter {
336
371
  this.emitProviderEvent(event, "thinking", { text });
337
372
  return;
338
373
  }
374
+ if (event.type === "command_output") {
375
+ this.emitProviderEvent(event, "command_output", {
376
+ text: typeof event.data.text === "string" ? event.data.text : "",
377
+ stream: toCommandOutputStream(event.data.stream),
378
+ sequence: typeof event.data.sequence === "number"
379
+ ? event.data.sequence
380
+ : undefined,
381
+ cwd: typeof event.data.cwd === "string" ? event.data.cwd : undefined,
382
+ commandLineCount: typeof event.data.commandLineCount === "number"
383
+ ? event.data.commandLineCount
384
+ : undefined,
385
+ commandFilePath: typeof event.data.commandFilePath === "string"
386
+ ? event.data.commandFilePath
387
+ : undefined,
388
+ });
389
+ return;
390
+ }
339
391
  if (event.type === "ai_request") {
340
392
  const estimatedTokens = toEstimatedContextTokens(event.data);
341
393
  if (estimatedTokens > 0) {
@@ -350,6 +402,13 @@ export class AcodeSdkAdapter extends EventEmitter {
350
402
  endpoint: typeof event.data.endpoint === "string"
351
403
  ? event.data.endpoint
352
404
  : undefined,
405
+ requestMethod: typeof event.data.requestMethod === "string"
406
+ ? event.data.requestMethod
407
+ : undefined,
408
+ requestUrl: typeof event.data.requestUrl === "string"
409
+ ? event.data.requestUrl
410
+ : undefined,
411
+ requestHeaders: toStringRecord(event.data.requestHeaders),
353
412
  stream: typeof event.data.stream === "boolean"
354
413
  ? event.data.stream
355
414
  : undefined,
@@ -459,8 +518,7 @@ export class AcodeSdkAdapter extends EventEmitter {
459
518
  // the session status.
460
519
  if (!event.data.action && Array.isArray(event.data.tools)) {
461
520
  const tools = event.data.tools;
462
- const hasPollMessage = tools.some((tool) => typeof tool?.name === "string" &&
463
- tool.name.includes("poll_message"));
521
+ const hasPollMessage = tools.some((tool) => isPollMessageToolDescriptor(tool));
464
522
  if (!hasPollMessage) {
465
523
  const message = "ACode runtime is not exposing a poll_message tool. The LLM cannot call poll_message. " +
466
524
  "Please configure an MCP server that provides poll_message (e.g. aws-mcp) in the dashboard panel for this runtime.";
@@ -549,7 +607,7 @@ export class AcodeSdkAdapter extends EventEmitter {
549
607
  return;
550
608
  }
551
609
  if (entry.idleCommands?.idleInputCommand) {
552
- entry.idlePollLoop?.start();
610
+ this.getIdlePollLoop(entry).start();
553
611
  return;
554
612
  }
555
613
  this.scheduleAutoPoll(sessionId);
@@ -562,12 +620,14 @@ export class AcodeSdkAdapter extends EventEmitter {
562
620
  getStatus: () => this.sessions.get(sessionId)?.adapterSession.status,
563
621
  getCommand: () => this.sessions.get(sessionId)?.idleCommands?.idleInputCommand,
564
622
  isPollingCommand: (command) => isMessagePollingIdleCommand(command),
565
- dispatchPollingPrompt: () => this.submitAutoPollPrompt(sessionId, ACODE_MESSAGE_POLLING_IDLE_PROMPT),
623
+ dispatchPollingPrompt: () => this.submitAutoPollPrompt(sessionId, ACODE_MESSAGE_POLLING_IDLE_PROMPT, {
624
+ keepWaitingStatus: true,
625
+ }),
566
626
  dispatchRegularIdleCommand: (command) => this.submitAutoPollPrompt(sessionId, command),
567
627
  });
568
628
  return entry.idlePollLoop;
569
629
  }
570
- submitAutoPollPrompt(sessionId, prompt) {
630
+ submitAutoPollPrompt(sessionId, prompt, options) {
571
631
  const entry = this.sessions.get(sessionId);
572
632
  if (!entry || this.isTerminalStatus(entry.adapterSession.status))
573
633
  return;
@@ -575,8 +635,10 @@ export class AcodeSdkAdapter extends EventEmitter {
575
635
  entry.autoPollObservedPollingTool = false;
576
636
  entry.autoPollObservedAssistantText = false;
577
637
  entry.stopAutoPollAfterCurrentTurn = false;
578
- entry.adapterSession.status = "thinking";
579
- this.emit("status-change", sessionId, "thinking");
638
+ if (!options?.keepWaitingStatus) {
639
+ entry.adapterSession.status = "thinking";
640
+ this.emit("status-change", sessionId, "thinking");
641
+ }
580
642
  void entry.runtime
581
643
  .submit(prompt)
582
644
  .catch((error) => {
@@ -642,7 +704,9 @@ export class AcodeSdkAdapter extends EventEmitter {
642
704
  return;
643
705
  }
644
706
  currentEntry.autoPollTimer = undefined;
645
- this.submitAutoPollPrompt(sessionId, ACODE_AUTO_POLL_PROMPT);
707
+ this.submitAutoPollPrompt(sessionId, ACODE_AUTO_POLL_PROMPT, {
708
+ keepWaitingStatus: true,
709
+ });
646
710
  }, delayMs);
647
711
  }
648
712
  cancelScheduledAutoPoll(entry) {
@@ -707,7 +771,9 @@ export class AcodeSdkAdapter extends EventEmitter {
707
771
  this.getIdlePollLoop(currentEntry).start();
708
772
  }
709
773
  else {
710
- this.submitAutoPollPrompt(sessionId, ACODE_AUTO_POLL_PROMPT);
774
+ this.submitAutoPollPrompt(sessionId, ACODE_AUTO_POLL_PROMPT, {
775
+ keepWaitingStatus: true,
776
+ });
711
777
  }
712
778
  }, ACODE_AUTO_POLL_FAILURE_DELAY_MS);
713
779
  }
@@ -211,6 +211,12 @@ class AiRequestRuntime extends EventEmitter {
211
211
  data: {
212
212
  model: "test-model",
213
213
  endpoint: "https://example.invalid/v1/chat/completions",
214
+ requestMethod: "POST",
215
+ requestUrl: "https://example.invalid/v1/chat/completions",
216
+ requestHeaders: {
217
+ "Content-Type": "application/json",
218
+ Authorization: "Bearer ***",
219
+ },
214
220
  stream: true,
215
221
  messageCount: 3,
216
222
  toolCount: 2,
@@ -257,6 +263,30 @@ class AssistantDeltaRuntime extends EventEmitter {
257
263
  async abort() { }
258
264
  async stop() { }
259
265
  }
266
+ class CommandOutputRuntime extends EventEmitter {
267
+ constructor(config) {
268
+ super();
269
+ this.config = config;
270
+ }
271
+ async start() { }
272
+ async submit(_message) {
273
+ this.emit("event", {
274
+ type: "command_output",
275
+ sessionId: this.config.sessionId,
276
+ timestamp: new Date(0).toISOString(),
277
+ data: {
278
+ text: "live command output",
279
+ stream: "stdout",
280
+ sequence: 2,
281
+ cwd: "/repo",
282
+ commandLineCount: 1,
283
+ commandFilePath: "/repo/.agentswork/acode/cmd-dist/run.cmd",
284
+ },
285
+ });
286
+ }
287
+ async abort() { }
288
+ async stop() { }
289
+ }
260
290
  class ResponseBodyTurnCompleteRuntime extends EventEmitter {
261
291
  constructor(config) {
262
292
  super();
@@ -297,6 +327,36 @@ class ProviderUsageTurnCompleteRuntime extends EventEmitter {
297
327
  async abort() { }
298
328
  async stop() { }
299
329
  }
330
+ class ResettableRuntime extends EventEmitter {
331
+ constructor(config) {
332
+ super();
333
+ this.config = config;
334
+ }
335
+ async start() { }
336
+ async submit(_message) {
337
+ this.emit("event", {
338
+ type: "assistant_delta",
339
+ sessionId: this.config.sessionId,
340
+ timestamp: new Date(0).toISOString(),
341
+ data: { text: "done" },
342
+ });
343
+ this.emit("event", {
344
+ type: "turn_complete",
345
+ sessionId: this.config.sessionId,
346
+ timestamp: new Date(0).toISOString(),
347
+ data: { usage: { inputTokens: 7, outputTokens: 3 } },
348
+ });
349
+ }
350
+ async resetContext() {
351
+ ResettableRuntime.resetCalls += 1;
352
+ }
353
+ async abort() { }
354
+ async stop() {
355
+ ResettableRuntime.stopCalls += 1;
356
+ }
357
+ }
358
+ ResettableRuntime.resetCalls = 0;
359
+ ResettableRuntime.stopCalls = 0;
300
360
  class ThinkingThenAssistantDeltaRuntime extends EventEmitter {
301
361
  constructor(config) {
302
362
  super();
@@ -643,6 +703,58 @@ class DifferentlyNamedMcpRuntime extends EventEmitter {
643
703
  async abort() { }
644
704
  async stop() { }
645
705
  }
706
+ class FakePollMessageToolRuntime extends EventEmitter {
707
+ constructor(config) {
708
+ super();
709
+ this.config = config;
710
+ }
711
+ async start() {
712
+ this.emit("event", {
713
+ type: "mcp_status",
714
+ sessionId: this.config.sessionId,
715
+ timestamp: new Date(0).toISOString(),
716
+ data: {
717
+ tools: [
718
+ {
719
+ name: "other-mcp__not_poll_message",
720
+ source: "other-mcp.not_poll_message",
721
+ },
722
+ ],
723
+ },
724
+ });
725
+ }
726
+ async submit(_message) { }
727
+ async abort() { }
728
+ async stop() { }
729
+ }
730
+ class DeferredInitialThenRegularIdleRuntime extends EventEmitter {
731
+ constructor(config) {
732
+ super();
733
+ this.config = config;
734
+ }
735
+ async start() { }
736
+ async submit(message) {
737
+ DeferredInitialThenRegularIdleRuntime.submitMessages.push(message);
738
+ if (DeferredInitialThenRegularIdleRuntime.submitMessages.length !== 1) {
739
+ return;
740
+ }
741
+ await new Promise((resolve) => {
742
+ DeferredInitialThenRegularIdleRuntime.completeInitialTurn = () => {
743
+ this.emit("event", {
744
+ type: "turn_complete",
745
+ sessionId: this.config.sessionId,
746
+ timestamp: new Date(0).toISOString(),
747
+ data: { usage: { inputTokens: 1, outputTokens: 1 } },
748
+ });
749
+ DeferredInitialThenRegularIdleRuntime.completeInitialTurn = undefined;
750
+ resolve();
751
+ };
752
+ });
753
+ }
754
+ async abort() { }
755
+ async stop() { }
756
+ }
757
+ DeferredInitialThenRegularIdleRuntime.submitMessages = [];
646
758
  describe("AcodeSdkAdapter turn completion state", () => {
647
759
  it("keeps error status for failed turn_complete events", () => {
648
760
  expect(isFailedAcodeTurnComplete({ failed: true })).toBe(true);
@@ -730,6 +842,46 @@ describe("AcodeSdkAdapter turn completion state", () => {
730
842
  usage: { inputTokens: 31, outputTokens: 58 },
731
843
  });
732
844
  });
845
+ it("resets ACode context in place without terminating the SDK session", async () => {
846
+ vi.useFakeTimers();
847
+ ResettableRuntime.resetCalls = 0;
848
+ ResettableRuntime.stopCalls = 0;
849
+ const adapter = new AcodeSdkAdapter();
850
+ adapter.setRuntimeConstructorForTest(ResettableRuntime);
851
+ const statuses = [];
852
+ adapter.on("status-change", (_sessionId, status, actionInfo) => {
853
+ statuses.push({ status, usage: actionInfo?.usage });
854
+ });
855
+ try {
856
+ await adapter.startSession("session-reset-context", {
857
+ command: "acode",
858
+ workingDirectory: process.cwd(),
859
+ autoAccept: true,
860
+ extraMcpServers: {},
861
+ envOverrides: {},
862
+ });
863
+ await adapter.sendMessage("session-reset-context", "finish work");
864
+ expect(adapter.getConversation("session-reset-context")).toHaveLength(2);
865
+ expect(statuses.at(-1)).toEqual({
866
+ status: "waiting_input",
867
+ usage: { inputTokens: 7, outputTokens: 3 },
868
+ });
869
+ await adapter.resetContext("session-reset-context");
870
+ expect(ResettableRuntime.resetCalls).toBe(1);
871
+ expect(ResettableRuntime.stopCalls).toBe(0);
872
+ expect(adapter.hasSession("session-reset-context")).toBe(true);
873
+ expect(adapter.getSessionStatus("session-reset-context")).toBe("waiting_input");
874
+ expect(adapter.getConversation("session-reset-context")).toEqual([]);
875
+ expect(statuses.at(-1)).toEqual({
876
+ status: "waiting_input",
877
+ usage: { inputTokens: 0, outputTokens: 0 },
878
+ });
879
+ }
880
+ finally {
881
+ vi.useRealTimers();
882
+ adapter.cleanup();
883
+ }
884
+ });
733
885
  it("maps ACode MCP status events to tool_using instead of thinking", async () => {
734
886
  const adapter = new AcodeSdkAdapter();
735
887
  adapter.setRuntimeConstructorForTest(McpStatusRuntime);
@@ -992,6 +1144,12 @@ describe("AcodeSdkAdapter turn completion state", () => {
992
1144
  data: {
993
1145
  model: "test-model",
994
1146
  endpoint: "https://example.invalid/v1/chat/completions",
1147
+ requestMethod: "POST",
1148
+ requestUrl: "https://example.invalid/v1/chat/completions",
1149
+ requestHeaders: {
1150
+ "Content-Type": "application/json",
1151
+ Authorization: "Bearer ***",
1152
+ },
995
1153
  stream: true,
996
1154
  messageCount: 3,
997
1155
  toolCount: 2,
@@ -1042,6 +1200,32 @@ describe("AcodeSdkAdapter turn completion state", () => {
1042
1200
  data: { text: "answer chunk" },
1043
1201
  });
1044
1202
  });
1203
+ it("forwards ACode command output as ordered realtime provider events", async () => {
1204
+ const adapter = new AcodeSdkAdapter();
1205
+ adapter.setRuntimeConstructorForTest(CommandOutputRuntime);
1206
+ const events = [];
1207
+ adapter.on("event", (event) => events.push(event));
1208
+ await adapter.startSession("session-command-output", {
1209
+ command: "acode",
1210
+ workingDirectory: process.cwd(),
1211
+ autoAccept: true,
1212
+ extraMcpServers: {},
1213
+ envOverrides: {},
1214
+ });
1215
+ await adapter.sendMessage("session-command-output", "run command");
1216
+ expect(events).toHaveLength(1);
1217
+ expect(events[0]).toMatchObject({
1218
+ type: "command_output",
1219
+ data: {
1220
+ text: "live command output",
1221
+ stream: "stdout",
1222
+ sequence: 2,
1223
+ cwd: "/repo",
1224
+ commandLineCount: 1,
1225
+ commandFilePath: "/repo/.agentswork/acode/cmd-dist/run.cmd",
1226
+ },
1227
+ });
1228
+ });
1045
1229
  it("preserves realtime thinking then answer delta order", async () => {
1046
1230
  const adapter = new AcodeSdkAdapter();
1047
1231
  adapter.setRuntimeConstructorForTest(ThinkingThenAssistantDeltaRuntime);
@@ -1146,6 +1330,43 @@ describe("AcodeSdkAdapter turn completion state", () => {
1146
1330
  expect(statuses).toEqual(["starting", "waiting_input", "thinking"]);
1147
1331
  expect(adapter.getSessionStatus("session-initial-prompt")).toBe("thinking");
1148
1332
  });
1333
+ it("runs regular idle commands configured while ACode is still busy", async () => {
1334
+ vi.useFakeTimers();
1335
+ DeferredInitialThenRegularIdleRuntime.submitMessages = [];
1336
+ DeferredInitialThenRegularIdleRuntime.completeInitialTurn = undefined;
1337
+ const adapter = new AcodeSdkAdapter();
1338
+ adapter.setRuntimeConstructorForTest(DeferredInitialThenRegularIdleRuntime);
1339
+ try {
1340
+ await adapter.startSession("session-regular-idle-busy-config", {
1341
+ command: "acode",
1342
+ workingDirectory: process.cwd(),
1343
+ autoAccept: true,
1344
+ initialPrompt: "bootstrap current task",
1345
+ extraMcpServers: {},
1346
+ envOverrides: {},
1347
+ });
1348
+ expect(DeferredInitialThenRegularIdleRuntime.submitMessages).toEqual([
1349
+ "bootstrap current task",
1350
+ ]);
1351
+ expect(adapter.getSessionStatus("session-regular-idle-busy-config")).toBe("thinking");
1352
+ adapter.setIdleCommands("session-regular-idle-busy-config", {
1353
+ idleInputCommand: "continue after idle",
1354
+ nonInputCommand: "",
1355
+ });
1356
+ const completeInitialTurn = DeferredInitialThenRegularIdleRuntime.completeInitialTurn;
1357
+ expect(completeInitialTurn).toBeDefined();
1358
+ completeInitialTurn?.();
1359
+ await vi.advanceTimersByTimeAsync(1500);
1360
+ expect(DeferredInitialThenRegularIdleRuntime.submitMessages).toEqual([
1361
+ "bootstrap current task",
1362
+ "continue after idle",
1363
+ ]);
1364
+ }
1365
+ finally {
1366
+ vi.useRealTimers();
1367
+ adapter.cleanup();
1368
+ }
1369
+ });
1149
1370
  it("continues the message loop by auto-submitting poll_message after a completed turn", async () => {
1150
1371
  vi.useFakeTimers();
1151
1372
  AutoPollRuntime.submitMessages = [];
@@ -1171,8 +1392,6 @@ describe("AcodeSdkAdapter turn completion state", () => {
1171
1392
  "waiting_input",
1172
1393
  "thinking",
1173
1394
  "waiting_input",
1174
- "thinking",
1175
- "waiting_input",
1176
1395
  ]);
1177
1396
  expect(adapter.getSessionStatus("session-auto-poll")).toBe("waiting_input");
1178
1397
  }
@@ -1181,6 +1400,31 @@ describe("AcodeSdkAdapter turn completion state", () => {
1181
1400
  adapter.cleanup();
1182
1401
  }
1183
1402
  });
1403
+ it("keeps waiting_input while dispatching an auto-poll prompt", async () => {
1404
+ vi.useFakeTimers();
1405
+ DeferredInitialPromptRuntime.submitCalls = 0;
1406
+ const adapter = new AcodeSdkAdapter();
1407
+ adapter.setRuntimeConstructorForTest(DeferredInitialPromptRuntime);
1408
+ const statuses = [];
1409
+ adapter.on("status-change", (_sessionId, status) => statuses.push(status));
1410
+ try {
1411
+ await adapter.startSession("session-auto-poll-pending", {
1412
+ command: "acode",
1413
+ workingDirectory: process.cwd(),
1414
+ autoAccept: true,
1415
+ extraMcpServers: {},
1416
+ envOverrides: {},
1417
+ });
1418
+ await vi.advanceTimersByTimeAsync(250);
1419
+ expect(DeferredInitialPromptRuntime.submitCalls).toBe(1);
1420
+ expect(adapter.getSessionStatus("session-auto-poll-pending")).toBe("waiting_input");
1421
+ expect(statuses).toEqual(["starting", "waiting_input"]);
1422
+ }
1423
+ finally {
1424
+ vi.useRealTimers();
1425
+ adapter.cleanup();
1426
+ }
1427
+ });
1184
1428
  it("stops re-arming auto-poll when the model answers without calling poll_message", async () => {
1185
1429
  vi.useFakeTimers();
1186
1430
  NonPollingAutoPollRuntime.submitMessages = [];
@@ -1324,17 +1568,12 @@ describe("AcodeSdkAdapter turn completion state", () => {
1324
1568
  });
1325
1569
  await vi.advanceTimersByTimeAsync(250);
1326
1570
  // Status sequence: starting -> waiting_input (startSession) ->
1327
- // thinking (auto-poll fires) -> waiting_input (turn_complete success
1328
- // re-arms the loop). Empty turns are allowed to retry because only a
1329
- // plain-text assistant answer indicates the model ignored poll_message.
1571
+ // waiting_input (poll turn completes and re-arms the loop). The
1572
+ // auto-poll prompt stays in waiting_input so a slow or missing
1573
+ // poll_message tool event cannot leave the dashboard on thinking.
1330
1574
  expect(AutoPollRuntime.submitMessages).toHaveLength(1);
1331
1575
  expect(AutoPollRuntime.submitMessages[0]).toContain("poll_message");
1332
- expect(statuses).toEqual([
1333
- "starting",
1334
- "waiting_input",
1335
- "thinking",
1336
- "waiting_input",
1337
- ]);
1576
+ expect(statuses).toEqual(["starting", "waiting_input", "waiting_input"]);
1338
1577
  expect(adapter.getSessionStatus("session-r1-no-initial")).toBe("waiting_input");
1339
1578
  }
1340
1579
  finally {
@@ -1368,7 +1607,6 @@ describe("AcodeSdkAdapter turn completion state", () => {
1368
1607
  expect(statuses).toEqual([
1369
1608
  "starting",
1370
1609
  "waiting_input",
1371
- "thinking",
1372
1610
  "error",
1373
1611
  "waiting_input",
1374
1612
  ]);
@@ -1408,7 +1646,6 @@ describe("AcodeSdkAdapter turn completion state", () => {
1408
1646
  expect(statuses).toEqual([
1409
1647
  "starting",
1410
1648
  "waiting_input",
1411
- "thinking",
1412
1649
  "error",
1413
1650
  "waiting_input",
1414
1651
  ]);
@@ -1557,6 +1794,31 @@ describe("AcodeSdkAdapter turn completion state", () => {
1557
1794
  adapter.cleanup();
1558
1795
  }
1559
1796
  });
1797
+ it("does not treat tools that only contain poll_message as a real listener", async () => {
1798
+ const adapter = new AcodeSdkAdapter();
1799
+ adapter.setRuntimeConstructorForTest(FakePollMessageToolRuntime);
1800
+ const events = [];
1801
+ const consoleWarn = vi
1802
+ .spyOn(console, "warn")
1803
+ .mockImplementation(() => undefined);
1804
+ adapter.on("event", (event) => events.push(event));
1805
+ try {
1806
+ await adapter.startSession("session-r3-fake-poll-message", {
1807
+ command: "acode",
1808
+ workingDirectory: process.cwd(),
1809
+ autoAccept: true,
1810
+ extraMcpServers: {},
1811
+ envOverrides: {},
1812
+ });
1813
+ expect(events.find((event) => event.type === "error")).toBeUndefined();
1814
+ expect(consoleWarn).toHaveBeenCalled();
1815
+ expect(String(consoleWarn.mock.calls[0]?.[0] ?? "")).toContain("poll_message");
1816
+ }
1817
+ finally {
1818
+ consoleWarn.mockRestore();
1819
+ adapter.cleanup();
1820
+ }
1821
+ });
1560
1822
  it("does not log a warning when the MCP server is named differently but still exposes poll_message (R3 user-scenario)", async () => {
1561
1823
  // Reproduces the production scenario from the bug report: the user
1562
1824
  // configures the AWS MCP under a non-default name (e.g. 'aws-mcp-server'
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Main flow: normalize common MCP separators, then use the final segment as
3
+ * the semantic tool name exposed to the agent.
4
+ */
5
+ export declare function getSemanticToolName(toolName: string): string;
6
+ /**
7
+ * Main flow: detect free-form idle guidance that asks the agent to enter the
8
+ * message-polling loop.
9
+ */
10
+ export declare function isMessagePollingIdleCommand(command: string): boolean;
11
+ /**
12
+ * Main flow: validate startup MCP tool descriptors against the exact
13
+ * poll_message semantic tool name instead of substring matching.
14
+ */
15
+ export declare function isPollMessageToolDescriptor(tool: Readonly<Record<string, unknown>>): boolean;
16
+ //# sourceMappingURL=acode-tool-names.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acode-tool-names.d.ts","sourceRoot":"","sources":["../../src/adapter/acode-tool-names.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAI5D;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CASpE;AASD;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACtC,OAAO,CAKT"}
@@ -0,0 +1,37 @@
1
+ const CHINESE_GET_MESSAGE_HINT = "\u53d6\u6d88\u606f";
2
+ /**
3
+ * Main flow: normalize common MCP separators, then use the final segment as
4
+ * the semantic tool name exposed to the agent.
5
+ */
6
+ export function getSemanticToolName(toolName) {
7
+ const normalized = toolName.trim().toLowerCase();
8
+ const segments = normalized.split(/__|[./]/).filter(Boolean);
9
+ return segments.at(-1) ?? normalized;
10
+ }
11
+ /**
12
+ * Main flow: detect free-form idle guidance that asks the agent to enter the
13
+ * message-polling loop.
14
+ */
15
+ export function isMessagePollingIdleCommand(command) {
16
+ const normalized = command.trim();
17
+ if (!normalized)
18
+ return false;
19
+ const lower = normalized.toLowerCase();
20
+ return (lower.includes("poll_message") ||
21
+ lower.includes("get_message") ||
22
+ normalized.includes(CHINESE_GET_MESSAGE_HINT));
23
+ }
24
+ function hasExactToolSegment(value, toolName) {
25
+ if (typeof value !== "string") {
26
+ return false;
27
+ }
28
+ return getSemanticToolName(value) === toolName;
29
+ }
30
+ /**
31
+ * Main flow: validate startup MCP tool descriptors against the exact
32
+ * poll_message semantic tool name instead of substring matching.
33
+ */
34
+ export function isPollMessageToolDescriptor(tool) {
35
+ return (hasExactToolSegment(tool.name, "poll_message") ||
36
+ hasExactToolSegment(tool.source, "poll_message"));
37
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=acode-tool-names.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acode-tool-names.test.d.ts","sourceRoot":"","sources":["../../src/adapter/acode-tool-names.test.ts"],"names":[],"mappings":""}