@scotthuang/agent-knock-knock 0.2.47 → 0.2.48

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 (34) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +73 -50
  3. package/dist/src/approval-policy.d.ts +2 -1
  4. package/dist/src/approval-policy.js +12 -4
  5. package/dist/src/approval-policy.js.map +1 -1
  6. package/dist/src/claude-hook-store.js +17 -6
  7. package/dist/src/claude-hook-store.js.map +1 -1
  8. package/dist/src/claude-terminal-agent-adapter.js +16 -1
  9. package/dist/src/claude-terminal-agent-adapter.js.map +1 -1
  10. package/dist/src/cli.js +1037 -172
  11. package/dist/src/cli.js.map +1 -1
  12. package/dist/src/openclaw-plugin-helpers.d.ts +49 -0
  13. package/dist/src/openclaw-plugin-helpers.js +246 -0
  14. package/dist/src/openclaw-plugin-helpers.js.map +1 -0
  15. package/dist/src/openclaw-plugin.js +92 -269
  16. package/dist/src/openclaw-plugin.js.map +1 -1
  17. package/dist/src/runtime-log.js +54 -2
  18. package/dist/src/runtime-log.js.map +1 -1
  19. package/dist/src/store.js +432 -12
  20. package/dist/src/store.js.map +1 -1
  21. package/dist/src/terminal-agent-adapter.d.ts +3 -0
  22. package/dist/src/terminal-agent-adapter.js.map +1 -1
  23. package/dist/src/terminal-agent-bridge.d.ts +32 -2
  24. package/dist/src/terminal-agent-bridge.js +192 -34
  25. package/dist/src/terminal-agent-bridge.js.map +1 -1
  26. package/dist/src/terminal-control-provider.d.ts +3 -1
  27. package/dist/src/terminal-control-provider.js +41 -37
  28. package/dist/src/terminal-control-provider.js.map +1 -1
  29. package/dist/src/terminal-process-source.d.ts +12 -3
  30. package/dist/src/terminal-process-source.js +37 -6
  31. package/dist/src/terminal-process-source.js.map +1 -1
  32. package/openclaw.plugin.json +2 -2
  33. package/package.json +10 -5
  34. package/templates/openclaw-skills/agent-knock-knock/SKILL.md +4 -18
@@ -2,9 +2,10 @@ import { spawnSync } from "node:child_process";
2
2
  import path from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
5
- import { EXECUTOR_KINDS, executorDefinitionForAlias, executorDefinitionForKind, parseLeadingExecutorAlias } from "./executors.js";
5
+ import { EXECUTOR_KINDS, executorDefinitionForKind, parseLeadingExecutorAlias } from "./executors.js";
6
+ import { AKK_CALLBACK_METHOD, akkUsageText, buildAkkCommandCliArgs, formatAkkListCommandResult, parseAkkCommand, resolvePluginStoreDir, resolveConversationOverrides } from "./openclaw-plugin-helpers.js";
6
7
  import { attemptAutoApproval } from "./approval-policy.js";
7
- const CALLBACK_METHOD = "agent-knock-knock.callback";
8
+ const CALLBACK_METHOD = AKK_CALLBACK_METHOD;
8
9
  const pluginRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
9
10
  const defaultBinPath = path.join(pluginRoot, "dist", "src", "cli.js");
10
11
  const delegateParameters = {
@@ -23,11 +24,7 @@ const delegateParameters = {
23
24
  },
24
25
  workspace: {
25
26
  type: "string",
26
- description: "Workspace path for Claude Code. Defaults to plugin config or the current process directory."
27
- },
28
- storeDir: {
29
- type: "string",
30
- description: "Conversation store directory. Defaults to <workspace>/.agent-knock-knock/conversations."
27
+ description: "Workspace path for the selected coding agent. Defaults to plugin config or the Gateway process directory."
31
28
  },
32
29
  claudeSession: {
33
30
  type: "string",
@@ -117,9 +114,6 @@ const listParameters = {
117
114
  type: "boolean",
118
115
  description: "When true, include tmux terminal discovery diagnostics for debugging Gateway environment issues."
119
116
  },
120
- storeDir: {
121
- type: "string"
122
- },
123
117
  idleTimeoutMinutes: {
124
118
  type: "number"
125
119
  }
@@ -138,9 +132,6 @@ const renewParameters = {
138
132
  type: "number",
139
133
  exclusiveMinimum: 0,
140
134
  description: "New terminal inactivity timeout in minutes."
141
- },
142
- storeDir: {
143
- type: "string"
144
135
  }
145
136
  }
146
137
  };
@@ -152,9 +143,6 @@ const retryCallbackParameters = {
152
143
  conversation_id: {
153
144
  type: "string",
154
145
  description: "AKK-managed conversation whose persisted callback delivery is pending or failed."
155
- },
156
- storeDir: {
157
- type: "string"
158
146
  }
159
147
  }
160
148
  };
@@ -167,9 +155,6 @@ const statusParameters = {
167
155
  type: "string",
168
156
  description: "AKK-managed conversation id, or a terminal-controlled id from AKK list such as terminal:v2:tmux:codex:codex-work:0.1:33389."
169
157
  },
170
- storeDir: {
171
- type: "string"
172
- },
173
158
  idleTimeoutMinutes: {
174
159
  type: "number"
175
160
  },
@@ -191,9 +176,6 @@ const describeParameters = {
191
176
  type: "string",
192
177
  description: "AKK-managed conversation id, native Codex id, or terminal-controlled id from AKK list. Use this when the user asks what a listed AKK/Codex session is about."
193
178
  },
194
- storeDir: {
195
- type: "string"
196
- },
197
179
  idleTimeoutMinutes: {
198
180
  type: "number"
199
181
  },
@@ -230,9 +212,6 @@ const sendParameters = {
230
212
  model: {
231
213
  type: "string"
232
214
  },
233
- storeDir: {
234
- type: "string"
235
- },
236
215
  idleTimeoutMinutes: {
237
216
  type: "number"
238
217
  },
@@ -259,9 +238,6 @@ const cancelParameters = {
259
238
  allProxy: {
260
239
  type: "string"
261
240
  },
262
- storeDir: {
263
- type: "string"
264
- },
265
241
  idleTimeoutMinutes: {
266
242
  type: "number"
267
243
  }
@@ -284,9 +260,6 @@ const recoveryParameters = {
284
260
  model: {
285
261
  type: "string"
286
262
  },
287
- storeDir: {
288
- type: "string"
289
- },
290
263
  idleTimeoutMinutes: {
291
264
  type: "number"
292
265
  }
@@ -302,9 +275,6 @@ const closeParameters = {
302
275
  },
303
276
  reason: {
304
277
  type: "string"
305
- },
306
- storeDir: {
307
- type: "string"
308
278
  }
309
279
  }
310
280
  };
@@ -359,10 +329,6 @@ const agentTakeoverParameters = {
359
329
  type: "string",
360
330
  description: "Required when strategy=fork and createConversation=true. OpenClaw-approved summary of the bounded source context to inject into the new forked AKK session."
361
331
  },
362
- storeDir: {
363
- type: "string",
364
- description: "Conversation store directory. Defaults to plugin config or <workspace>/.agent-knock-knock/conversations."
365
- },
366
332
  openclawSession: {
367
333
  type: "string",
368
334
  description: "OpenClaw session label recorded in the created AKK conversation."
@@ -397,9 +363,6 @@ const approveParameters = {
397
363
  expected_approval_fingerprint: {
398
364
  type: "string",
399
365
  description: "Exact approval fingerprint returned by the latest status or approval-required callback. The prompt is captured again and must still match before keys are sent."
400
- },
401
- storeDir: {
402
- type: "string"
403
366
  }
404
367
  }
405
368
  };
@@ -422,6 +385,31 @@ export default definePluginEntry({
422
385
  });
423
386
  }
424
387
  }, { scope: "operator.write" });
388
+ try {
389
+ api.registerService?.({
390
+ id: "agent-knock-knock-monitor-reconciliation",
391
+ start() {
392
+ try {
393
+ const config = isRecord(api.pluginConfig) ? api.pluginConfig : {};
394
+ const args = ["reconcile-monitors"];
395
+ pushOptional(args, "--store-dir", resolvePluginStoreDir(config));
396
+ const result = runCli(api, args);
397
+ api.logger.info?.("agent-knock-knock monitor reconciliation: " +
398
+ `checked=${result.checked ?? 0} launched=${result.launched ?? 0} ` +
399
+ `already_running=${result.already_running ?? 0} skipped=${result.skipped ?? 0} ` +
400
+ `errors=${result.errors ?? 0}`);
401
+ }
402
+ catch (error) {
403
+ const message = error instanceof Error ? error.message : String(error);
404
+ api.logger.warn?.(`agent-knock-knock monitor reconciliation skipped after startup error: ${message}`);
405
+ }
406
+ }
407
+ });
408
+ }
409
+ catch (error) {
410
+ const message = error instanceof Error ? error.message : String(error);
411
+ api.logger.warn?.(`agent-knock-knock monitor reconciliation service was not registered: ${message}`);
412
+ }
425
413
  api.registerCommand?.({
426
414
  name: "akk",
427
415
  description: "Delegate coding work to Agent Knock Knock, list tasks, send follow-ups, cancel running work, and close tasks.",
@@ -457,7 +445,7 @@ export default definePluginEntry({
457
445
  parameters: listParameters,
458
446
  buildArgs: (params) => {
459
447
  const args = ["list"];
460
- pushOptional(args, "--store-dir", stringValue(params.storeDir) ?? stringValue(api.pluginConfig?.storeDir));
448
+ pushOptional(args, "--store-dir", resolvePluginStoreDir(isRecord(api.pluginConfig) ? api.pluginConfig : {}));
461
449
  pushOptional(args, "--idle-timeout-minutes", numberString(params.idleTimeoutMinutes) ?? numberString(api.pluginConfig?.idleTimeoutMinutes));
462
450
  pushOptional(args, "--agent", stringValue(params.agent));
463
451
  pushOptional(args, "--status", stringValue(params.status));
@@ -482,7 +470,7 @@ export default definePluginEntry({
482
470
  parameters: statusParameters,
483
471
  buildArgs: (params) => {
484
472
  const args = ["status", "--conversation", requiredString(params.conversation_id, "conversation_id")];
485
- pushOptional(args, "--store-dir", stringValue(params.storeDir) ?? stringValue(api.pluginConfig?.storeDir));
473
+ pushOptional(args, "--store-dir", resolvePluginStoreDir(isRecord(api.pluginConfig) ? api.pluginConfig : {}));
486
474
  pushOptional(args, "--idle-timeout-minutes", numberString(params.idleTimeoutMinutes) ?? numberString(api.pluginConfig?.idleTimeoutMinutes));
487
475
  if (params.trace === true) {
488
476
  args.push("--trace");
@@ -496,7 +484,7 @@ export default definePluginEntry({
496
484
  parameters: describeParameters,
497
485
  buildArgs: (params) => {
498
486
  const args = ["describe", "--conversation", requiredString(params.conversation_id, "conversation_id")];
499
- pushOptional(args, "--store-dir", stringValue(params.storeDir) ?? stringValue(api.pluginConfig?.storeDir));
487
+ pushOptional(args, "--store-dir", resolvePluginStoreDir(isRecord(api.pluginConfig) ? api.pluginConfig : {}));
500
488
  pushOptional(args, "--idle-timeout-minutes", numberString(params.idleTimeoutMinutes) ?? numberString(api.pluginConfig?.idleTimeoutMinutes));
501
489
  pushOptional(args, "--max-messages", numberString(params.maxMessages));
502
490
  pushOptional(args, "--max-commands", numberString(params.maxCommands));
@@ -522,15 +510,14 @@ export default definePluginEntry({
522
510
  "--background"
523
511
  ];
524
512
  pushOptional(args, "--type", stringValue(params.type));
525
- pushOptional(args, "--all-proxy", stringValue(params.allProxy) ?? stringValue(config.codexAllProxy) ?? stringValue(config.allProxy));
526
- pushOptional(args, "--model", stringValue(params.model) ?? stringValue(config.codexModel) ?? stringValue(config.model));
527
- pushOptional(args, "--store-dir", stringValue(params.storeDir) ?? stringValue(config.storeDir));
513
+ const overrides = resolveConversationOverrides(params, config);
514
+ pushOptional(args, "--all-proxy", overrides.allProxy);
515
+ pushOptional(args, "--model", overrides.model);
516
+ pushOptional(args, "--store-dir", resolvePluginStoreDir(config));
528
517
  pushOptional(args, "--idle-timeout-minutes", numberString(params.idleTimeoutMinutes) ?? numberString(config.idleTimeoutMinutes));
529
518
  pushOptional(args, "--agent-timeout-minutes", numberString(params.agentTimeoutMinutes) ?? numberString(config.agentTimeoutMinutes));
530
519
  pushOptional(args, "--agent-hard-timeout-minutes", numberString(params.agentHardTimeoutMinutes) ?? numberString(config.agentHardTimeoutMinutes));
531
520
  pushOptional(args, "--openclaw-session", openclawSession);
532
- pushOptional(args, "--gateway-url", stringValue(config.gatewayUrl));
533
- pushOptional(args, "--token", stringValue(config.gatewayToken));
534
521
  pushOptional(args, "--gateway-method", CALLBACK_METHOD);
535
522
  pushOptional(args, "--gateway-session", openclawSession);
536
523
  pushOptional(args, "--openclaw-bin", stringValue(config.openclawBin));
@@ -547,7 +534,7 @@ export default definePluginEntry({
547
534
  buildArgs: (params) => {
548
535
  const args = ["approve", "--conversation", requiredString(params.conversation_id, "conversation_id")];
549
536
  pushOptional(args, "--expected-approval-fingerprint", requiredString(params.expected_approval_fingerprint, "expected_approval_fingerprint"));
550
- pushOptional(args, "--store-dir", stringValue(params.storeDir) ?? stringValue(api.pluginConfig?.storeDir));
537
+ pushOptional(args, "--store-dir", resolvePluginStoreDir(isRecord(api.pluginConfig) ? api.pluginConfig : {}));
551
538
  return args;
552
539
  }
553
540
  });
@@ -559,7 +546,7 @@ export default definePluginEntry({
559
546
  const config = isRecord(api.pluginConfig) ? api.pluginConfig : {};
560
547
  const args = ["renew", "--conversation", requiredString(params.conversation_id, "conversation_id")];
561
548
  pushOptional(args, "--minutes", numberString(params.minutes) ?? numberString(config.agentTimeoutMinutes));
562
- pushOptional(args, "--store-dir", stringValue(params.storeDir) ?? stringValue(config.storeDir));
549
+ pushOptional(args, "--store-dir", resolvePluginStoreDir(config));
563
550
  return args;
564
551
  }
565
552
  });
@@ -570,7 +557,7 @@ export default definePluginEntry({
570
557
  buildArgs: (params) => {
571
558
  const config = isRecord(api.pluginConfig) ? api.pluginConfig : {};
572
559
  const args = ["retry-callback", "--conversation", requiredString(params.conversation_id, "conversation_id")];
573
- pushOptional(args, "--store-dir", stringValue(params.storeDir) ?? stringValue(config.storeDir));
560
+ pushOptional(args, "--store-dir", resolvePluginStoreDir(config));
574
561
  return args;
575
562
  }
576
563
  });
@@ -579,10 +566,12 @@ export default definePluginEntry({
579
566
  description: "Cancel an existing Agent Knock Knock Codex, Claude, or Cursor task. Delegated sessions use cooperative ACPX cancellation. Terminal-controlled Claude denies a pending structured permission or sends Escape; other adapters use their declared interrupt keys. The underlying tmux pane remains open.",
580
567
  parameters: cancelParameters,
581
568
  buildArgs: (params) => {
569
+ const config = isRecord(api.pluginConfig) ? api.pluginConfig : {};
570
+ const overrides = resolveConversationOverrides(params, config);
582
571
  const args = ["cancel", "--conversation", requiredString(params.conversation_id, "conversation_id")];
583
- pushOptional(args, "--all-proxy", stringValue(params.allProxy) ?? stringValue(api.pluginConfig?.codexAllProxy) ?? stringValue(api.pluginConfig?.allProxy));
584
- pushOptional(args, "--store-dir", stringValue(params.storeDir) ?? stringValue(api.pluginConfig?.storeDir));
585
- pushOptional(args, "--idle-timeout-minutes", numberString(params.idleTimeoutMinutes) ?? numberString(api.pluginConfig?.idleTimeoutMinutes));
572
+ pushOptional(args, "--all-proxy", overrides.allProxy);
573
+ pushOptional(args, "--store-dir", resolvePluginStoreDir(config));
574
+ pushOptional(args, "--idle-timeout-minutes", numberString(params.idleTimeoutMinutes) ?? numberString(config.idleTimeoutMinutes));
586
575
  return args;
587
576
  }
588
577
  });
@@ -599,7 +588,7 @@ export default definePluginEntry({
599
588
  buildArgs: (params) => {
600
589
  const args = ["close", "--conversation", requiredString(params.conversation_id, "conversation_id")];
601
590
  pushOptional(args, "--reason", stringValue(params.reason));
602
- pushOptional(args, "--store-dir", stringValue(params.storeDir) ?? stringValue(api.pluginConfig?.storeDir));
591
+ pushOptional(args, "--store-dir", resolvePluginStoreDir(isRecord(api.pluginConfig) ? api.pluginConfig : {}));
603
592
  return args;
604
593
  }
605
594
  });
@@ -639,10 +628,8 @@ export default definePluginEntry({
639
628
  pushOptional(args, "--terminal-target", stringValue(params.terminalTarget));
640
629
  pushOptional(args, "--request", stringValue(params.request));
641
630
  pushOptional(args, "--fork-summary", stringValue(params.forkSummary));
642
- pushOptional(args, "--store-dir", stringValue(params.storeDir) ?? stringValue(config.storeDir));
631
+ pushOptional(args, "--store-dir", resolvePluginStoreDir(config));
643
632
  pushOptional(args, "--openclaw-session", openclawSession);
644
- pushOptional(args, "--gateway-url", stringValue(config.gatewayUrl));
645
- pushOptional(args, "--token", stringValue(config.gatewayToken));
646
633
  pushOptional(args, "--gateway-method", CALLBACK_METHOD);
647
634
  pushOptional(args, "--gateway-session", openclawSession);
648
635
  pushOptional(args, "--openclaw-bin", stringValue(config.openclawBin));
@@ -674,88 +661,34 @@ async function handleAkkCommand(api, ctx) {
674
661
  });
675
662
  return { text: formatDelegateCommandResult(result) };
676
663
  }
677
- if (parsed.action === "list") {
678
- const result = runCli(api, ["list"]);
679
- return { text: formatListCommandResult(result) };
680
- }
681
- if (parsed.action === "status") {
682
- const result = runCli(api, ["status", "--conversation", parsed.conversationId]);
683
- return { text: formatStatusCommandResult(result) };
684
- }
685
- if (parsed.action === "describe") {
686
- const result = runCli(api, ["describe", "--conversation", parsed.conversationId]);
687
- return { text: formatDescribeCommandResult(result) };
688
- }
689
- if (parsed.action === "send") {
690
- const args = [
691
- "send",
692
- "--conversation",
693
- parsed.conversationId,
694
- "--message",
695
- parsed.message,
696
- "--background"
697
- ];
698
- const config = isRecord(api.pluginConfig) ? api.pluginConfig : {};
699
- pushOptional(args, "--all-proxy", stringValue(config.codexAllProxy) ?? stringValue(config.allProxy));
700
- pushOptional(args, "--model", stringValue(config.codexModel) ?? stringValue(config.model));
701
- pushOptional(args, "--idle-timeout-minutes", numberString(config.idleTimeoutMinutes));
702
- pushOptional(args, "--agent-timeout-minutes", numberString(config.agentTimeoutMinutes));
703
- pushOptional(args, "--agent-hard-timeout-minutes", numberString(config.agentHardTimeoutMinutes));
704
- const result = runCli(api, args);
705
- return { text: formatSendCommandResult(result) };
706
- }
707
- if (parsed.action === "renew") {
708
- const config = isRecord(api.pluginConfig) ? api.pluginConfig : {};
709
- const args = ["renew", "--conversation", parsed.conversationId];
710
- pushOptional(args, "--minutes", parsed.minutes ?? numberString(config.agentTimeoutMinutes));
711
- pushOptional(args, "--store-dir", stringValue(config.storeDir));
712
- const result = runCli(api, args);
713
- return { text: formatRenewCommandResult(result) };
714
- }
715
- if (parsed.action === "retry-callback" || parsed.action === "retry") {
716
- const config = isRecord(api.pluginConfig) ? api.pluginConfig : {};
717
- const args = ["retry-callback", "--conversation", parsed.conversationId];
718
- pushOptional(args, "--store-dir", stringValue(config.storeDir));
719
- const result = runCli(api, args);
720
- return { text: formatRetryCallbackCommandResult(result) };
721
- }
722
- if (parsed.action === "cancel") {
723
- const args = [
724
- "cancel",
725
- "--conversation",
726
- parsed.conversationId
727
- ];
728
- const config = isRecord(api.pluginConfig) ? api.pluginConfig : {};
729
- pushOptional(args, "--all-proxy", stringValue(config.codexAllProxy) ?? stringValue(config.allProxy));
730
- pushOptional(args, "--idle-timeout-minutes", numberString(config.idleTimeoutMinutes));
731
- const result = runCli(api, args);
732
- return { text: formatCancelCommandResult(result) };
733
- }
734
- if (parsed.action === "recover") {
735
- const config = isRecord(api.pluginConfig) ? api.pluginConfig : {};
736
- const args = [
737
- "recover",
738
- "--conversation",
739
- parsed.conversationId,
740
- "--background"
741
- ];
742
- pushOptional(args, "--all-proxy", stringValue(config.codexAllProxy) ?? stringValue(config.allProxy));
743
- pushOptional(args, "--model", stringValue(config.codexModel) ?? stringValue(config.model));
744
- pushOptional(args, "--idle-timeout-minutes", numberString(config.idleTimeoutMinutes));
745
- const result = runCli(api, args);
746
- return { text: formatRecoveryCommandResult(result) };
664
+ const config = isRecord(api.pluginConfig) ? api.pluginConfig : {};
665
+ const args = buildAkkCommandCliArgs(parsed, config, {
666
+ sessionKey: ctx.sessionKey
667
+ });
668
+ if (!args) {
669
+ return { text: akkUsageText(), isError: true };
747
670
  }
748
- if (parsed.action === "close") {
749
- const result = runCli(api, [
750
- "close",
751
- "--conversation",
752
- parsed.conversationId,
753
- "--reason",
754
- parsed.reason
755
- ]);
756
- return { text: formatCloseCommandResult(result) };
671
+ const result = runCli(api, args);
672
+ switch (parsed.action) {
673
+ case "list":
674
+ return { text: formatAkkListCommandResult(result) };
675
+ case "status":
676
+ return { text: formatStatusCommandResult(result) };
677
+ case "describe":
678
+ return { text: formatDescribeCommandResult(result) };
679
+ case "send":
680
+ return { text: formatSendCommandResult(result) };
681
+ case "renew":
682
+ return { text: formatRenewCommandResult(result) };
683
+ case "retry-callback":
684
+ return { text: formatRetryCallbackCommandResult(result) };
685
+ case "cancel":
686
+ return { text: formatCancelCommandResult(result) };
687
+ case "recover":
688
+ return { text: formatRecoveryCommandResult(result) };
689
+ case "close":
690
+ return { text: formatCloseCommandResult(result) };
757
691
  }
758
- return { text: akkUsageText(), isError: true };
759
692
  }
760
693
  catch (error) {
761
694
  const message = error instanceof Error ? error.message : String(error);
@@ -765,109 +698,14 @@ async function handleAkkCommand(api, ctx) {
765
698
  };
766
699
  }
767
700
  }
768
- function parseAkkCommand(args) {
769
- const input = String(args ?? "").trim();
770
- if (!input || input === "help" || input === "-h" || input === "--help") {
771
- return { action: "help" };
772
- }
773
- const { token, rest } = takeToken(input);
774
- const action = String(token).toLowerCase();
775
- if (action === "list" || action === "ls" || action === "tasks") {
776
- return { action: "list" };
777
- }
778
- if (action === "status" || action === "show") {
779
- const { token: conversationId } = takeRequiredToken(rest, "Usage: /akk status <conversation-id>");
780
- return { action: "status", conversationId };
781
- }
782
- if (action === "describe" || action === "summary" || action === "about") {
783
- const { token: conversationId } = takeRequiredToken(rest, "Usage: /akk describe <conversation-id>");
784
- return { action: "describe", conversationId };
785
- }
786
- if (action === "send" || action === "reply") {
787
- const { token: conversationId, rest: message } = takeRequiredToken(rest, "Usage: /akk send <conversation-id> <message>");
788
- const body = message.trim();
789
- if (!body) {
790
- throw new Error("Usage: /akk send <conversation-id> <message>");
791
- }
792
- return { action: "send", conversationId, message: body };
793
- }
794
- if (action === "cancel" || action === "stop") {
795
- const { token: conversationId } = takeRequiredToken(rest, "Usage: /akk cancel <conversation-id>");
796
- return { action: "cancel", conversationId };
797
- }
798
- if (action === "renew") {
799
- const { token: conversationId, rest: minutesInput } = takeRequiredToken(rest, "Usage: /akk renew <conversation-id> [minutes]");
800
- const minutes = minutesInput.trim();
801
- if (minutes && (!Number.isFinite(Number(minutes)) || Number(minutes) <= 0)) {
802
- throw new Error("Usage: /akk renew <conversation-id> [positive-minutes]");
803
- }
804
- return { action: "renew", conversationId, minutes: minutes || undefined };
805
- }
806
- if (action === "retry-callback" || action === "retry") {
807
- const { token: conversationId } = takeRequiredToken(rest, "Usage: /akk retry-callback <conversation-id>");
808
- return { action: "retry-callback", conversationId };
809
- }
810
- if (action === "recover") {
811
- const { token: conversationId } = takeRequiredToken(rest, "Usage: /akk recover <conversation-id>");
812
- return { action: "recover", conversationId };
813
- }
814
- if (action === "close" || action === "done") {
815
- const { token: conversationId, rest: reason } = takeRequiredToken(rest, "Usage: /akk close <conversation-id> [reason]");
816
- return { action: "close", conversationId, reason: reason.trim() || "Closed from /akk command" };
817
- }
818
- const executorDefinition = executorDefinitionForAlias(action);
819
- if (executorDefinition) {
820
- const request = rest.trim();
821
- if (!request) {
822
- throw new Error(`Usage: /akk ${executorDefinition.kind} <task>`);
823
- }
824
- return { action: "delegate", agent: executorDefinition.kind, request };
825
- }
826
- return { action: "delegate", agent: "codex", request: input };
827
- }
828
- function takeRequiredToken(input, usage) {
829
- const parsed = takeToken(input);
830
- if (!parsed.token) {
831
- throw new Error(usage);
832
- }
833
- return parsed;
834
- }
835
- function takeToken(input) {
836
- const value = String(input ?? "").trimStart();
837
- const match = value.match(/^(\S+)(?:\s+([\s\S]*))?$/);
838
- if (!match) {
839
- return { token: "", rest: "" };
840
- }
841
- return {
842
- token: match[1],
843
- rest: match[2] ?? ""
844
- };
845
- }
846
- function akkUsageText() {
847
- return [
848
- "AKK usage:",
849
- "/akk <task>",
850
- "/akk codex <task>",
851
- "/akk claude <task>",
852
- "/akk list",
853
- "/akk status <conversation-id>",
854
- "/akk describe <conversation-id>",
855
- "/akk send <conversation-id> <message>",
856
- "/akk cancel <conversation-id>",
857
- "/akk renew <conversation-id> [minutes]",
858
- "/akk retry-callback <conversation-id>",
859
- "/akk recover <conversation-id>",
860
- "/akk close <conversation-id> [reason]"
861
- ].join("\n");
862
- }
863
701
  function formatDelegateCommandResult(result) {
864
702
  const agent = executorDisplayName(result.agent);
865
703
  return [
866
- `AKK 已交给 ${agent}。`,
704
+ `AKK delegated the task to ${agent}.`,
867
705
  `conversation: ${result.conversation_id ?? "unknown"}`,
868
706
  `session: ${result.session ?? "unknown"}`,
869
707
  `status: ${result.conversation_status ?? result.status ?? "unknown"}`,
870
- "结果会通过 OpenClaw 回调返回当前会话。"
708
+ "The result will return to this OpenClaw session through the callback."
871
709
  ].join("\n");
872
710
  }
873
711
  function executorDisplayName(kind) {
@@ -878,23 +716,15 @@ function executorDisplayName(kind) {
878
716
  return String(kind ?? "agent");
879
717
  }
880
718
  }
881
- function formatListCommandResult(result) {
882
- const tasks = Array.isArray(result.tasks) ? result.tasks : [];
883
- if (!tasks.length) {
884
- return "AKK 当前没有打开的会话。";
885
- }
886
- return [
887
- `AKK open sessions (${tasks.length}):`,
888
- ...tasks.slice(0, 20).map(formatTaskLine)
889
- ].join("\n");
890
- }
891
719
  function formatStatusCommandResult(result) {
892
- const summary = result.summary ?? result.conversation ?? {};
720
+ const summary = result.summary ?? result.conversation ?? result ?? {};
721
+ const terminalStatus = isRecord(result.terminal_status) ? result.terminal_status : {};
722
+ const terminalControl = isRecord(result.terminal_control) ? result.terminal_control : {};
893
723
  const lines = [
894
- `AKK status: ${summary.conversation_id ?? "unknown"}`,
895
- `agent: ${summary.agent ?? summary.executor?.kind ?? "unknown"}`,
896
- `status: ${summary.status ?? "unknown"}`,
897
- `session: ${summary.session ?? summary.executor?.session ?? "unknown"}`
724
+ `AKK status: ${summary.conversation_id ?? result.conversation_id ?? "unknown"}`,
725
+ `agent: ${summary.agent ?? summary.executor?.kind ?? terminalStatus.agent ?? "unknown"}`,
726
+ `status: ${summary.status ?? terminalStatus.activity_state ?? "unknown"}`,
727
+ `session: ${summary.session ?? summary.executor?.session ?? terminalControl.target ?? "unknown"}`
898
728
  ];
899
729
  if (summary.request) {
900
730
  lines.push(`request: ${truncateText(summary.request, 180)}`);
@@ -953,12 +783,13 @@ function formatSendCommandResult(result) {
953
783
  }
954
784
  function formatCancelCommandResult(result) {
955
785
  const conversation = result.conversation ?? {};
786
+ const terminalControl = isRecord(result.terminal_control) ? result.terminal_control : {};
956
787
  return [
957
788
  "AKK cancel requested.",
958
- `conversation: ${conversation.conversation_id ?? "unknown"}`,
789
+ `conversation: ${conversation.conversation_id ?? result.conversation_id ?? "unknown"}`,
959
790
  `agent: ${result.executor?.kind ?? conversation.executor?.kind ?? "unknown"}`,
960
- `session: ${result.executor?.session ?? conversation.executor?.session ?? "unknown"}`,
961
- `status: ${conversation.status ?? "unknown"}`
791
+ `session: ${result.executor?.session ?? conversation.executor?.session ?? terminalControl.target ?? "unknown"}`,
792
+ `status: ${conversation.status ?? (result.cancel_requested === true ? "cancel requested" : "not cancelled")}`
962
793
  ].join("\n");
963
794
  }
964
795
  function formatRecoveryCommandResult(result) {
@@ -979,14 +810,6 @@ function formatCloseCommandResult(result) {
979
810
  `status: ${conversation.status ?? "unknown"}`
980
811
  ].join("\n");
981
812
  }
982
- function formatTaskLine(task) {
983
- return [
984
- task.conversation_id ?? "unknown",
985
- task.agent ?? task.executor?.kind ?? "agent",
986
- task.status ?? "unknown",
987
- truncateText(task.request ?? "", 90)
988
- ].filter(Boolean).join(" | ");
989
- }
990
813
  function runDelegate(api, params, toolContext) {
991
814
  const config = isRecord(api.pluginConfig) ? api.pluginConfig : {};
992
815
  const binPath = stringValue(config.binPath) ?? defaultBinPath;
@@ -1022,13 +845,11 @@ function runDelegate(api, params, toolContext) {
1022
845
  workspace,
1023
846
  "--background"
1024
847
  ];
1025
- pushOptional(args, "--store-dir", stringValue(params.storeDir) ?? stringValue(config.storeDir));
848
+ pushOptional(args, "--store-dir", resolvePluginStoreDir(config));
1026
849
  pushOptional(args, "--session", agentSession);
1027
850
  pushOptional(args, "--all-proxy", allProxy);
1028
851
  pushOptional(args, "--model", model);
1029
852
  pushOptional(args, "--openclaw-session", openclawSession);
1030
- pushOptional(args, "--gateway-url", stringValue(config.gatewayUrl));
1031
- pushOptional(args, "--token", stringValue(config.gatewayToken));
1032
853
  pushOptional(args, "--gateway-method", CALLBACK_METHOD);
1033
854
  pushOptional(args, "--gateway-session", openclawSession);
1034
855
  pushOptional(args, "--openclaw-bin", stringValue(config.openclawBin));
@@ -1096,12 +917,14 @@ function registerCliTool(api, { name, description, parameters, buildArgs }) {
1096
917
  }), { name, optional: true });
1097
918
  }
1098
919
  function buildRecoveryArgs(api, command, params) {
920
+ const config = isRecord(api.pluginConfig) ? api.pluginConfig : {};
921
+ const overrides = resolveConversationOverrides(params, config);
1099
922
  const args = [command, "--conversation", requiredString(params.conversation_id, "conversation_id"), "--background"];
1100
923
  pushOptional(args, "--session", stringValue(params.session));
1101
- pushOptional(args, "--all-proxy", stringValue(params.allProxy) ?? stringValue(api.pluginConfig?.codexAllProxy) ?? stringValue(api.pluginConfig?.allProxy));
1102
- pushOptional(args, "--model", stringValue(params.model) ?? stringValue(api.pluginConfig?.codexModel) ?? stringValue(api.pluginConfig?.model));
1103
- pushOptional(args, "--store-dir", stringValue(params.storeDir) ?? stringValue(api.pluginConfig?.storeDir));
1104
- pushOptional(args, "--idle-timeout-minutes", numberString(params.idleTimeoutMinutes) ?? numberString(api.pluginConfig?.idleTimeoutMinutes));
924
+ pushOptional(args, "--all-proxy", overrides.allProxy);
925
+ pushOptional(args, "--model", overrides.model);
926
+ pushOptional(args, "--store-dir", resolvePluginStoreDir(config));
927
+ pushOptional(args, "--idle-timeout-minutes", numberString(params.idleTimeoutMinutes) ?? numberString(config.idleTimeoutMinutes));
1105
928
  return args;
1106
929
  }
1107
930
  function runCli(api, cliArgs, { cwd = process.cwd() } = {}) {