linkshell-cli 0.10.19 → 0.10.20

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 (105) hide show
  1. package/README.md +3 -2
  2. package/dist/cli/src/commands/screen.js +2 -2
  3. package/dist/cli/src/commands/screen.js.map +1 -1
  4. package/dist/cli/tsconfig.tsbuildinfo +1 -1
  5. package/dist/host/src/acp-settings.d.ts +12 -0
  6. package/dist/host/src/acp-settings.js +41 -0
  7. package/dist/host/src/acp-settings.js.map +1 -0
  8. package/dist/host/src/carry.js +13 -2
  9. package/dist/host/src/carry.js.map +1 -1
  10. package/dist/host/src/drivers/acp/client-services.d.ts +29 -0
  11. package/dist/host/src/drivers/acp/client-services.js +192 -0
  12. package/dist/host/src/drivers/acp/client-services.js.map +1 -0
  13. package/dist/host/src/drivers/acp/connection.d.ts +37 -8
  14. package/dist/host/src/drivers/acp/connection.js +127 -110
  15. package/dist/host/src/drivers/acp/connection.js.map +1 -1
  16. package/dist/host/src/drivers/acp/driver.d.ts +92 -2
  17. package/dist/host/src/drivers/acp/driver.js +599 -52
  18. package/dist/host/src/drivers/acp/driver.js.map +1 -1
  19. package/dist/host/src/drivers/acp/editor.d.ts +31 -0
  20. package/dist/host/src/drivers/acp/editor.js +242 -0
  21. package/dist/host/src/drivers/acp/editor.js.map +1 -0
  22. package/dist/host/src/drivers/acp/mapper.d.ts +2 -1
  23. package/dist/host/src/drivers/acp/mapper.js +88 -35
  24. package/dist/host/src/drivers/acp/mapper.js.map +1 -1
  25. package/dist/host/src/drivers/acp/mcp.d.ts +20 -0
  26. package/dist/host/src/drivers/acp/mcp.js +139 -0
  27. package/dist/host/src/drivers/acp/mcp.js.map +1 -0
  28. package/dist/host/src/drivers/acp/questions.js +14 -0
  29. package/dist/host/src/drivers/acp/questions.js.map +1 -1
  30. package/dist/host/src/drivers/acp/updates.d.ts +10 -0
  31. package/dist/host/src/drivers/acp/updates.js +137 -0
  32. package/dist/host/src/drivers/acp/updates.js.map +1 -0
  33. package/dist/host/src/drivers/claude/activity.d.ts +1 -0
  34. package/dist/host/src/drivers/claude/activity.js +17 -3
  35. package/dist/host/src/drivers/claude/activity.js.map +1 -1
  36. package/dist/host/src/drivers/claude/children.d.ts +7 -0
  37. package/dist/host/src/drivers/claude/children.js +31 -2
  38. package/dist/host/src/drivers/claude/children.js.map +1 -1
  39. package/dist/host/src/drivers/claude/driver.js +1 -0
  40. package/dist/host/src/drivers/claude/driver.js.map +1 -1
  41. package/dist/host/src/drivers/claude/tasks.d.ts +3 -3
  42. package/dist/host/src/drivers/claude/transcript.d.ts +497 -38
  43. package/dist/host/src/drivers/codex/driver.d.ts +3 -0
  44. package/dist/host/src/drivers/codex/driver.js +36 -1
  45. package/dist/host/src/drivers/codex/driver.js.map +1 -1
  46. package/dist/host/src/drivers/registry.d.ts +6 -0
  47. package/dist/host/src/drivers/registry.js +8 -0
  48. package/dist/host/src/drivers/registry.js.map +1 -1
  49. package/dist/host/src/drivers/types.d.ts +34 -1
  50. package/dist/host/src/fs.d.ts +3 -3
  51. package/dist/host/src/host.js +21 -3
  52. package/dist/host/src/host.js.map +1 -1
  53. package/dist/host/src/hub.d.ts +249 -2
  54. package/dist/host/src/hub.js +150 -9
  55. package/dist/host/src/hub.js.map +1 -1
  56. package/dist/host/src/input.d.ts +5 -3
  57. package/dist/host/src/input.js +8 -6
  58. package/dist/host/src/input.js.map +1 -1
  59. package/dist/host/src/questions.d.ts +3 -1
  60. package/dist/host/src/questions.js +33 -7
  61. package/dist/host/src/questions.js.map +1 -1
  62. package/dist/host/src/rpc/server.js +14 -0
  63. package/dist/host/src/rpc/server.js.map +1 -1
  64. package/dist/host/src/screen.js +5 -5
  65. package/dist/host/src/screen.js.map +1 -1
  66. package/dist/host/src/slim.js +15 -4
  67. package/dist/host/src/slim.js.map +1 -1
  68. package/dist/host/src/store.js +7 -2
  69. package/dist/host/src/store.js.map +1 -1
  70. package/dist/host/src/terminals.d.ts +8 -3
  71. package/dist/host/src/terminals.js +3 -2
  72. package/dist/host/src/terminals.js.map +1 -1
  73. package/dist/wire/src/acp.d.ts +510 -0
  74. package/dist/wire/src/acp.js +39 -0
  75. package/dist/wire/src/acp.js.map +1 -0
  76. package/dist/wire/src/async-questions.d.ts +2 -2
  77. package/dist/wire/src/computer-preview.d.ts +2 -2
  78. package/dist/wire/src/content.d.ts +465 -0
  79. package/dist/wire/src/content.js +58 -0
  80. package/dist/wire/src/content.js.map +1 -0
  81. package/dist/wire/src/editor.d.ts +702 -0
  82. package/dist/wire/src/editor.js +23 -0
  83. package/dist/wire/src/editor.js.map +1 -0
  84. package/dist/wire/src/index.d.ts +3 -0
  85. package/dist/wire/src/index.js +3 -0
  86. package/dist/wire/src/index.js.map +1 -1
  87. package/dist/wire/src/model.d.ts +1383 -79
  88. package/dist/wire/src/model.js +20 -1
  89. package/dist/wire/src/model.js.map +1 -1
  90. package/dist/wire/src/peer.d.ts +1 -0
  91. package/dist/wire/src/peer.js +22 -6
  92. package/dist/wire/src/peer.js.map +1 -1
  93. package/dist/wire/src/questions.d.ts +3 -0
  94. package/dist/wire/src/questions.js +65 -0
  95. package/dist/wire/src/questions.js.map +1 -0
  96. package/dist/wire/src/relay.d.ts +4 -4
  97. package/dist/wire/src/rpc.d.ts +19023 -2518
  98. package/dist/wire/src/rpc.js +41 -3
  99. package/dist/wire/src/rpc.js.map +1 -1
  100. package/dist/wire/src/updates.d.ts +3848 -1114
  101. package/dist/wire/src/updates.js +42 -40
  102. package/dist/wire/src/updates.js.map +1 -1
  103. package/dist/wire/src/workflow.d.ts +22 -22
  104. package/package.json +4 -4
  105. package/src/commands/screen.ts +2 -2
@@ -3,7 +3,8 @@ import { homedir, hostname, platform } from "node:os";
3
3
  import { join } from "node:path";
4
4
  import { createHash, randomUUID } from "node:crypto";
5
5
  import { DEFAULT_ICE_SERVERS } from "@linkshell/wire";
6
- import { defaultDrivers } from "./drivers/registry.js";
6
+ import { defaultDrivers, remoteDriver } from "./drivers/registry.js";
7
+ import { AcpSettingsStore } from "./acp-settings.js";
7
8
  import { SessionHub } from "./hub.js";
8
9
  import { connectHost } from "./rpc/client.js";
9
10
  import { HostRpcServer } from "./rpc/server.js";
@@ -82,11 +83,13 @@ export async function startHost(options) {
82
83
  const machineId = loadMachineId(paths.home);
83
84
  // Agents and terminals start clean even when LinkShell ran inside a Claude Code session.
84
85
  const env = withoutClaudeSession(options.env ?? process.env);
86
+ const acpSettings = new AcpSettingsStore(join(paths.home, "acp.json"));
85
87
  if (!options.drivers)
86
88
  removeLegacyCopilotHooks(join(homedir(), ".copilot", "hooks"), log);
87
89
  const drivers = options.drivers
88
90
  ? options.drivers(paths)
89
91
  : defaultDrivers({
92
+ agents: acpSettings.agents(),
90
93
  env,
91
94
  hostVersion: options.version,
92
95
  codexSocket: paths.codexSocket,
@@ -95,7 +98,23 @@ export async function startHost(options) {
95
98
  claudeAdapter: options.claudeAdapter,
96
99
  });
97
100
  const store = new HostStore(paths.database);
98
- const hub = new SessionHub(store, drivers, log, paths.home);
101
+ const terminals = new TerminalManager(env, store);
102
+ const hub = new SessionHub(store, drivers, log, paths.home, {
103
+ settings: acpSettings,
104
+ createDriver: (agent) => remoteDriver(agent, { env, hostVersion: options.version }),
105
+ loginTerminal: async (_agent, launch) => {
106
+ const terminal = terminals.create({ launch, cols: 100, rows: 30 });
107
+ const exited = new Promise((resolve) => {
108
+ const stop = terminals.onChange((info, closed) => {
109
+ if (info.id === terminal.id && (closed || info.exitCode !== undefined)) {
110
+ stop();
111
+ resolve(info.exitCode ?? null);
112
+ }
113
+ });
114
+ });
115
+ return { terminalId: terminal.id, exited };
116
+ },
117
+ });
99
118
  await hub.start({ discoveryIntervalMs: options.discoveryIntervalMs });
100
119
  const iceServers = options.iceServers ?? iceServersFromEnv(process.env.LINKSHELL_ICE_SERVERS);
101
120
  const machineInfo = () => ({
@@ -109,7 +128,6 @@ export async function startHost(options) {
109
128
  // LINKSHELL_ICE_SERVERS: STUN servers for the direct channel, comma separated ("off": never direct).
110
129
  ...(iceServers ? { direct: { iceServers } } : {}),
111
130
  });
112
- const terminals = new TerminalManager(env, store);
113
131
  const server = new HostRpcServer({
114
132
  hub,
115
133
  terminals,
@@ -1 +1 @@
1
- {"version":3,"file":"host.js","sourceRoot":"","sources":["../../../../host/src/host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxF,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAwC,MAAM,iBAAiB,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,4DAA4D;AAC5D,MAAM,eAAe,GAAG,GAAG,CAAC;AAU5B,wEAAwE;AACxE,MAAM,UAAU,WAAW;IACzB,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAI,GAAG,WAAW,EAAE;IAC5C,IAAI,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC/B,IAAI,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;QACxD,2FAA2F;QAC3F,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACxE,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,aAAa,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO;QACL,IAAI;QACJ,MAAM;QACN,UAAU,EAAE,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC;QACrC,WAAW,EAAE,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC;QACvC,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC;KACjC,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAA4B,CAAC;QACjF,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS;YAAE,OAAO,MAAM,CAAC,SAAS,CAAC;IACxF,CAAC;IAAC,MAAM,CAAC;QACP,oDAAoD;IACtD,CAAC;IACD,MAAM,SAAS,GAAG,UAAU,EAAE,CAAC;IAC/B,aAAa,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACzH,OAAO,SAAS,CAAC;AACnB,CAAC;AA6CD,4DAA4D;AAC5D,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,UAAkB;IACpD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,CAAC;QAC7C,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAyB;IAClD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,mBAAmB,CAAC;IACpD,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IACvD,OAAO,KAAK;SACT,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SAC5B,MAAM,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAoB;IAClD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,OAAe,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC,CAAC;IACvF,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC1D,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC/B,IAAI,MAAM,aAAa,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,wCAAwC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC;IAC/E,CAAC;IAED,MAAM,SAAS,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5C,yFAAyF;IACzF,MAAM,GAAG,GAAG,oBAAoB,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC;IAC7D,IAAI,CAAC,OAAO,CAAC,OAAO;QAAE,wBAAwB,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1F,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO;QAC7B,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC;QACxB,CAAC,CAAC,cAAc,CAAC;YACb,GAAG;YACH,WAAW,EAAE,OAAO,CAAC,OAAO;YAC5B,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,aAAa,EAAE,OAAO,CAAC,aAAa;SACrC,CAAC,CAAC;IACP,MAAM,KAAK,GAAG,IAAI,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5D,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,mBAAmB,EAAE,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAEtE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;IAC9F,MAAM,WAAW,GAAG,GAAgB,EAAE,CAAC,CAAC;QACtC,SAAS;QACT,0FAA0F;QAC1F,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,QAAQ,EAAE;QAC1D,QAAQ,EAAE,QAAQ,EAAE;QACpB,WAAW,EAAE,OAAO,CAAC,OAAO;QAC5B,IAAI,EAAE,OAAO,EAAE;QACf,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE;QACpB,qGAAqG;QACrG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAClD,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,IAAI,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC;QAC/B,GAAG;QACH,SAAS;QACT,WAAW;QACX,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,GAAG;KACJ,CAAC,CAAC;IACH,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IAErB,IAAI,OAAgC,CAAC;IACrC,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAC/B,mGAAmG;IACnG,MAAM,WAAW,GAAG,GAAkB,EAAE;QACtC,MAAM,GAAG,GAAG,OAAO,MAAM,EAAE,GAAG,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC;QAC3E,IAAI,OAAO,IAAI,OAAO,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;YACnC,OAAO,CAAC,cAAc,EAAE,CAAC;YACzB,OAAO,OAAO,CAAC,MAAM,EAAE,CAAC;QAC1B,CAAC;QACD,MAAM,QAAQ,GAAG,OAAO,CAAC;QACzB,OAAO,GAAG,GAAG;YACX,CAAC,CAAC,IAAI,WAAW,CAAC;gBACd,GAAG;gBACH,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,KAAK,EAAE,MAAM,EAAE,KAAK;gBACpB,IAAI,EAAE,MAAM,EAAE,IAAI;gBAClB,KAAK,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC;gBAC/C,oDAAoD;gBACpD,QAAQ,EAAE,CAAC,MAAM,EAAE,EAAE;oBACnB,IAAI,OAAO,EAAE,GAAG,KAAK,GAAG;wBAAE,MAAM,CAAC,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;gBACxE,CAAC;gBACD,QAAQ,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,CAAC;gBAClE,GAAG;aACJ,CAAC;YACJ,CAAC,CAAC,SAAS,CAAC;QACd,QAAQ,EAAE,IAAI,EAAE,CAAC;QACjB,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAC3B,OAAO,EAAE,KAAK,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAc,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QAC5E,IAAI,QAAQ;YAAE,MAAM,CAAC,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;QAC1D,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IACF,MAAM,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;IACrC,WAAW,EAAE,CAAC;IAEd,IAAI,QAAmC,CAAC;IACxC,OAAO;QACL,KAAK;QACL,GAAG;QACH,MAAM;QACN,IAAI,OAAO;YACT,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,WAAW;QACX,IAAI;YACF,QAAQ,KAAK,CAAC,KAAK,IAAI,EAAE;gBACvB,OAAO,EAAE,IAAI,EAAE,CAAC;gBAChB,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBACpB,SAAS,CAAC,IAAI,EAAE,CAAC;gBACjB,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;gBACjB,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,CAAC,CAAC,EAAE,CAAC;YACL,OAAO,QAAQ,CAAC;QAClB,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"host.js","sourceRoot":"","sources":["../../../../host/src/host.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,11 @@
1
- import { type GoalChange, type BackgroundTask, type AgentInfo, type ContentBlock, type SessionEvent, type SessionSummary, type SubagentInfo, type QuestionAnswer, type GitInfo, type ProjectSummary, type WorktreeEntry } from "@linkshell/wire";
1
+ import { type GoalChange, type BackgroundTask, type AgentInfo, type ContentBlock, type SessionEvent, type SessionSummary, type SubagentInfo, type QuestionAnswer, type GitInfo, type ProjectSummary, type WorktreeEntry, type SessionNotice, type AcpAgentSettings, type AcpRemoteAgent, type PendingPermissionSummary, type EditorRequest } from "@linkshell/wire";
2
+ import type { AcpSettingsStore } from "./acp-settings.js";
2
3
  import type { AgentDriver, DesktopController, DesktopLaunchContext, DriverHost, LaunchSpec } from "./drivers/types.js";
3
4
  import { type HostStore } from "./store.js";
4
5
  import { ComputerPreviews } from "./computer-preview.js";
5
6
  export interface Subscriber {
6
7
  event(event: SessionEvent): void;
8
+ notice?(notice: SessionNotice): void;
7
9
  /** The backlog that follows starts after `startSeq`, not where the subscriber left off. */
8
10
  window?(startSeq: number): void;
9
11
  }
@@ -17,10 +19,13 @@ export declare class SessionHub {
17
19
  private readonly log;
18
20
  /** Where the host keeps its own files: worktrees go under it. */
19
21
  private readonly home;
22
+ private readonly acpServices?;
20
23
  private readonly drivers;
21
24
  private readonly live;
22
25
  private readonly summaryListeners;
23
26
  private readonly removedListeners;
27
+ private readonly interactionListeners;
28
+ private readonly agentListeners;
24
29
  private readonly auth;
25
30
  /** Terminals (`linkshell <agent>`) currently driving handoff sessions. */
26
31
  private readonly desktops;
@@ -32,7 +37,14 @@ export declare class SessionHub {
32
37
  readonly driverHost: DriverHost;
33
38
  constructor(store: HostStore, drivers: AgentDriver[], log?: (message: string) => void,
34
39
  /** Where the host keeps its own files: worktrees go under it. */
35
- home?: string);
40
+ home?: string, acpServices?: {
41
+ settings: AcpSettingsStore;
42
+ createDriver(agent: AcpRemoteAgent): AgentDriver;
43
+ loginTerminal(agent: string, launch: LaunchSpec): Promise<{
44
+ terminalId: string;
45
+ exited: Promise<number | null>;
46
+ }>;
47
+ } | undefined);
36
48
  start(options?: {
37
49
  discoveryIntervalMs?: number;
38
50
  }): Promise<void>;
@@ -41,6 +53,240 @@ export declare class SessionHub {
41
53
  private refreshArchives;
42
54
  stop(): Promise<void>;
43
55
  agents(): AgentInfo[];
56
+ onInteraction(listener: (agent: string, request: PendingPermissionSummary | {
57
+ requestId: string;
58
+ resolved: true;
59
+ }) => void): () => void;
60
+ onAgent(listener: (agent: AgentInfo) => void): () => void;
61
+ acpInfo(agent: string, sessionId?: string): Promise<{
62
+ features: import("@linkshell/wire").AcpFeatures;
63
+ settings: AcpAgentSettings;
64
+ interactions: PendingPermissionSummary[];
65
+ }>;
66
+ pendingInteractions(): {
67
+ agent: string;
68
+ request: {
69
+ options: {
70
+ name: string;
71
+ kind: "allow_once" | "allow_always" | "reject_once" | "reject_always";
72
+ optionId: string;
73
+ }[];
74
+ title: string;
75
+ requestId: string;
76
+ toolCallId?: string | undefined;
77
+ tool?: {
78
+ title?: string | undefined;
79
+ kind?: "search" | "delete" | "other" | "read" | "edit" | "move" | "execute" | "think" | "fetch" | "switch_mode" | undefined;
80
+ content?: ({
81
+ type: "content";
82
+ content: {
83
+ type: "text";
84
+ text: string;
85
+ annotations?: import("zod").objectOutputType<{
86
+ audience: import("zod").ZodEffects<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodArray<import("zod").ZodEnum<["user", "assistant"]>, "many">>>, ("user" | "assistant")[] | undefined, ("user" | "assistant")[] | null | undefined>;
87
+ priority: import("zod").ZodEffects<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodNumber>>, number | undefined, number | null | undefined>;
88
+ lastModified: import("zod").ZodEffects<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>, string | undefined, string | null | undefined>;
89
+ }, import("zod").ZodTypeAny, "passthrough"> | undefined;
90
+ _meta?: Record<string, unknown> | undefined;
91
+ } | {
92
+ type: "image";
93
+ mimeType: string;
94
+ annotations?: import("zod").objectOutputType<{
95
+ audience: import("zod").ZodEffects<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodArray<import("zod").ZodEnum<["user", "assistant"]>, "many">>>, ("user" | "assistant")[] | undefined, ("user" | "assistant")[] | null | undefined>;
96
+ priority: import("zod").ZodEffects<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodNumber>>, number | undefined, number | null | undefined>;
97
+ lastModified: import("zod").ZodEffects<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>, string | undefined, string | null | undefined>;
98
+ }, import("zod").ZodTypeAny, "passthrough"> | undefined;
99
+ _meta?: Record<string, unknown> | undefined;
100
+ data?: string | undefined;
101
+ uri?: string | undefined;
102
+ } | {
103
+ type: "audio";
104
+ mimeType: string;
105
+ annotations?: import("zod").objectOutputType<{
106
+ audience: import("zod").ZodEffects<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodArray<import("zod").ZodEnum<["user", "assistant"]>, "many">>>, ("user" | "assistant")[] | undefined, ("user" | "assistant")[] | null | undefined>;
107
+ priority: import("zod").ZodEffects<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodNumber>>, number | undefined, number | null | undefined>;
108
+ lastModified: import("zod").ZodEffects<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>, string | undefined, string | null | undefined>;
109
+ }, import("zod").ZodTypeAny, "passthrough"> | undefined;
110
+ _meta?: Record<string, unknown> | undefined;
111
+ data?: string | undefined;
112
+ uri?: string | undefined;
113
+ } | {
114
+ type: "resource";
115
+ resource: {
116
+ uri: string;
117
+ text?: string | undefined;
118
+ _meta?: Record<string, unknown> | undefined;
119
+ mimeType?: string | undefined;
120
+ blob?: string | undefined;
121
+ assetUri?: string | undefined;
122
+ };
123
+ annotations?: import("zod").objectOutputType<{
124
+ audience: import("zod").ZodEffects<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodArray<import("zod").ZodEnum<["user", "assistant"]>, "many">>>, ("user" | "assistant")[] | undefined, ("user" | "assistant")[] | null | undefined>;
125
+ priority: import("zod").ZodEffects<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodNumber>>, number | undefined, number | null | undefined>;
126
+ lastModified: import("zod").ZodEffects<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>, string | undefined, string | null | undefined>;
127
+ }, import("zod").ZodTypeAny, "passthrough"> | undefined;
128
+ _meta?: Record<string, unknown> | undefined;
129
+ } | {
130
+ type: "resource_link";
131
+ uri: string;
132
+ name: string;
133
+ annotations?: import("zod").objectOutputType<{
134
+ audience: import("zod").ZodEffects<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodArray<import("zod").ZodEnum<["user", "assistant"]>, "many">>>, ("user" | "assistant")[] | undefined, ("user" | "assistant")[] | null | undefined>;
135
+ priority: import("zod").ZodEffects<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodNumber>>, number | undefined, number | null | undefined>;
136
+ lastModified: import("zod").ZodEffects<import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>, string | undefined, string | null | undefined>;
137
+ }, import("zod").ZodTypeAny, "passthrough"> | undefined;
138
+ _meta?: Record<string, unknown> | undefined;
139
+ mimeType?: string | undefined;
140
+ title?: string | undefined;
141
+ description?: string | undefined;
142
+ size?: number | undefined;
143
+ kind?: "file" | "skill" | "agent" | undefined;
144
+ };
145
+ } | {
146
+ path: string;
147
+ type: "diff";
148
+ newText: string;
149
+ oldText?: string | null | undefined;
150
+ } | {
151
+ path: string;
152
+ type: "patch";
153
+ diff: string;
154
+ change: "add" | "delete" | "update";
155
+ movePath?: string | undefined;
156
+ } | {
157
+ type: "terminal";
158
+ terminalId: string;
159
+ })[] | undefined;
160
+ rawInput?: unknown;
161
+ locations?: {
162
+ path: string;
163
+ line?: number | undefined;
164
+ }[] | undefined;
165
+ } | undefined;
166
+ detail?: string | undefined;
167
+ questions?: {
168
+ text: string;
169
+ kind: "text" | "choice" | "choices";
170
+ id: string;
171
+ options?: {
172
+ value: string;
173
+ label: string;
174
+ description?: string | undefined;
175
+ }[] | undefined;
176
+ other?: boolean | undefined;
177
+ constraints?: {
178
+ type: "string" | "number" | "boolean" | "integer" | "array";
179
+ minimum?: number | undefined;
180
+ maximum?: number | undefined;
181
+ minLength?: number | undefined;
182
+ maxLength?: number | undefined;
183
+ minItems?: number | undefined;
184
+ maxItems?: number | undefined;
185
+ pattern?: string | undefined;
186
+ format?: string | undefined;
187
+ } | undefined;
188
+ defaults?: string[] | undefined;
189
+ header?: string | undefined;
190
+ secret?: boolean | undefined;
191
+ required?: boolean | undefined;
192
+ }[] | undefined;
193
+ childSessionId?: string | undefined;
194
+ url?: {
195
+ url: string;
196
+ elicitationId: string;
197
+ } | undefined;
198
+ };
199
+ }[];
200
+ editor(input: EditorRequest): Promise<{
201
+ path?: string | undefined;
202
+ text?: string | undefined;
203
+ version?: number | undefined;
204
+ preview?: {
205
+ path: string;
206
+ kind: "edit" | "jump" | "searchAndReplace";
207
+ id: string;
208
+ before: string;
209
+ after: string;
210
+ position?: {
211
+ line: number;
212
+ character: number;
213
+ } | undefined;
214
+ } | undefined;
215
+ position?: {
216
+ line: number;
217
+ character: number;
218
+ } | undefined;
219
+ editorId?: string | undefined;
220
+ suggestions?: ({
221
+ uri: string;
222
+ kind: "edit";
223
+ id: string;
224
+ edits: {
225
+ newText: string;
226
+ range: {
227
+ start: {
228
+ line: number;
229
+ character: number;
230
+ };
231
+ end: {
232
+ line: number;
233
+ character: number;
234
+ };
235
+ };
236
+ }[];
237
+ cursorPosition?: {
238
+ line: number;
239
+ character: number;
240
+ } | null | undefined;
241
+ } | {
242
+ uri: string;
243
+ kind: "jump";
244
+ id: string;
245
+ position: {
246
+ line: number;
247
+ character: number;
248
+ };
249
+ } | {
250
+ uri: string;
251
+ kind: "rename";
252
+ id: string;
253
+ position: {
254
+ line: number;
255
+ character: number;
256
+ };
257
+ newName: string;
258
+ } | {
259
+ replace: string;
260
+ search: string;
261
+ uri: string;
262
+ kind: "searchAndReplace";
263
+ id: string;
264
+ isRegex?: boolean | null | undefined;
265
+ })[] | undefined;
266
+ }>;
267
+ configureAcp(agent: string, settings: AcpAgentSettings, sessionId?: string): Promise<void>;
268
+ authenticate(agent: string, methodId?: string, logout?: boolean): Promise<{
269
+ terminalId?: string;
270
+ }>;
271
+ respondInteraction(agent: string, requestId: string, response: {
272
+ optionId?: string;
273
+ answers?: QuestionAnswer[];
274
+ }): Promise<void>;
275
+ providers(agent: string, operation: "list" | "set" | "disable", config?: {
276
+ providerId: string;
277
+ apiType?: string;
278
+ baseUrl?: string;
279
+ headers?: Record<string, string>;
280
+ }): Promise<{
281
+ required: boolean;
282
+ providerId: string;
283
+ supported: string[];
284
+ current?: {
285
+ apiType: string;
286
+ baseUrl: string;
287
+ } | null | undefined;
288
+ }[]>;
289
+ customAgents(save?: AcpRemoteAgent, remove?: string): Promise<AcpRemoteAgent[]>;
44
290
  /** Re-checks login state in the background when the cached answer is older than `maxAgeMs`. */
45
291
  refreshAuthIfStale(maxAgeMs?: number): Promise<void>;
46
292
  private refreshAuth;
@@ -127,6 +373,7 @@ export declare class SessionHub {
127
373
  stopTask(sessionId: string, taskId: string): Promise<void>;
128
374
  /** The sub-agents the session started, newest first. */
129
375
  subagents(sessionId: string): SubagentInfo[];
376
+ cancelSubagent(sessionId: string, nativeSessionId: string): Promise<void>;
130
377
  private subagentsOf;
131
378
  /** Keeps the sub-agent tally current; true when it changed. */
132
379
  private trackSubagent;
@@ -1,4 +1,4 @@
1
- import { RpcError, questionReplies, updateAsyncQuestions, sessionIdFor, } from "@linkshell/wire";
1
+ import { RpcError, questionReplies, questionAnswerError, updateAsyncQuestions, sessionIdFor, } from "@linkshell/wire";
2
2
  import { inOrder } from "./drivers/acp/driver.js";
3
3
  import { homedir } from "node:os";
4
4
  import { join } from "node:path";
@@ -91,10 +91,13 @@ export class SessionHub {
91
91
  store;
92
92
  log;
93
93
  home;
94
+ acpServices;
94
95
  drivers = new Map();
95
96
  live = new Map();
96
97
  summaryListeners = new Set();
97
98
  removedListeners = new Set();
99
+ interactionListeners = new Set();
100
+ agentListeners = new Set();
98
101
  auth = new Map();
99
102
  /** Terminals (`linkshell <agent>`) currently driving handoff sessions. */
100
103
  desktops = new Map();
@@ -104,6 +107,29 @@ export class SessionHub {
104
107
  authRefreshing;
105
108
  previews;
106
109
  driverHost = {
110
+ authChanged: (agent) => {
111
+ const driver = this.drivers.get(agent);
112
+ if (!driver)
113
+ return;
114
+ void this.refreshAuth(driver).then(() => { const info = this.agents().find((entry) => entry.id === agent); if (info)
115
+ for (const listener of this.agentListeners)
116
+ listener(info); }).catch(() => { });
117
+ },
118
+ agentSettings: (agent) => this.acpServices.settings.settings(agent),
119
+ loginTerminal: async (agent, launch) => {
120
+ if (!this.acpServices)
121
+ throw RpcError.app("not_supported", "终端登录不可用");
122
+ return this.acpServices.loginTerminal(agent, launch);
123
+ },
124
+ interaction: (agent, request) => { for (const listener of this.interactionListeners)
125
+ listener(agent, request); },
126
+ notice: (agent, nativeId, notice) => {
127
+ const live = this.live.get(sessionIdFor(agent, nativeId));
128
+ if (!live || live.importing)
129
+ return;
130
+ for (const subscriber of live.subscribers)
131
+ subscriber.notice?.(notice);
132
+ },
107
133
  tasks: (agent, nativeId) => {
108
134
  const id = sessionIdFor(agent, nativeId);
109
135
  return this.store.getSession(id) ? this.tasks(id) : [];
@@ -151,10 +177,13 @@ export class SessionHub {
151
177
  };
152
178
  constructor(store, drivers, log = () => { },
153
179
  /** Where the host keeps its own files: worktrees go under it. */
154
- home = join(homedir(), ".linkshell")) {
180
+ home = join(homedir(), ".linkshell"), acpServices) {
155
181
  this.store = store;
156
182
  this.log = log;
157
183
  this.home = home;
184
+ this.acpServices = acpServices;
185
+ if (!acpServices)
186
+ this.driverHost.agentSettings = undefined;
158
187
  const capture = process.platform === "darwin" ? new MacPreviewCapture(log) : undefined;
159
188
  this.previews = new ComputerPreviews({
160
189
  load: (id) => store.getDriverState(id, "computer-preview"),
@@ -241,6 +270,85 @@ export class SessionHub {
241
270
  };
242
271
  });
243
272
  }
273
+ onInteraction(listener) {
274
+ this.interactionListeners.add(listener);
275
+ return () => { this.interactionListeners.delete(listener); };
276
+ }
277
+ onAgent(listener) { this.agentListeners.add(listener); return () => { this.agentListeners.delete(listener); }; }
278
+ async acpInfo(agent, sessionId) {
279
+ const driver = this.requireDriver(agent);
280
+ if (!driver.acpInfo)
281
+ throw RpcError.app("not_supported", "这个 AI 不使用 ACP");
282
+ const session = sessionId ? this.getSession(sessionId) : undefined;
283
+ if (session && session.agent !== agent)
284
+ throw RpcError.app("invalid_params", "会话与 AI 不匹配");
285
+ return driver.acpInfo(session?.nativeId);
286
+ }
287
+ pendingInteractions() { return [...this.drivers.values()].flatMap((driver) => (driver.pendingInteractions?.() ?? []).map((request) => ({ agent: driver.id, request }))); }
288
+ async editor(input) {
289
+ const driver = this.requireDriver(input.agent);
290
+ if (!driver.editor)
291
+ throw RpcError.app("not_supported", "这个 AI 不支持编辑建议");
292
+ return driver.editor(input);
293
+ }
294
+ async configureAcp(agent, settings, sessionId) {
295
+ const driver = this.requireDriver(agent);
296
+ if (!driver.configureAcp || !this.acpServices)
297
+ throw RpcError.app("not_supported", "这个 AI 不支持 ACP 配置");
298
+ const session = sessionId ? this.getSession(sessionId) : undefined;
299
+ if (session && session.agent !== agent)
300
+ throw RpcError.app("invalid_params", "会话与 AI 不匹配");
301
+ await driver.configureAcp(settings, session?.nativeId);
302
+ if (!session)
303
+ this.acpServices.settings.setSettings(agent, settings);
304
+ }
305
+ async authenticate(agent, methodId, logout) {
306
+ const driver = this.requireDriver(agent);
307
+ if (!driver.authenticate)
308
+ throw RpcError.app("not_supported", "这个 AI 不支持 ACP 登录");
309
+ const result = await driver.authenticate(methodId, logout);
310
+ await this.refreshAuth(driver);
311
+ return result;
312
+ }
313
+ async respondInteraction(agent, requestId, response) {
314
+ const driver = this.requireDriver(agent);
315
+ if (!driver.respondInteraction)
316
+ throw RpcError.app("not_supported", "这个 AI 不支持此交互");
317
+ await driver.respondInteraction(requestId, response);
318
+ }
319
+ async providers(agent, operation, config) {
320
+ const driver = this.requireDriver(agent);
321
+ if (!driver.providers)
322
+ throw RpcError.app("not_supported", "这个 AI 不支持供应商配置");
323
+ return driver.providers(operation, config);
324
+ }
325
+ async customAgents(save, remove) {
326
+ const services = this.acpServices;
327
+ if (!services)
328
+ throw RpcError.app("not_supported", "自定义 ACP 配置不可用");
329
+ if (save && remove)
330
+ throw RpcError.app("invalid_params", "不能同时保存和移除 Agent");
331
+ const id = save?.id ?? remove;
332
+ if (id) {
333
+ const existing = this.drivers.get(id);
334
+ if (existing && !services.settings.agents().some((agent) => agent.id === id))
335
+ throw RpcError.app("invalid_params", "不能覆盖或移除内置 AI");
336
+ const driver = save ? services.createDriver(save) : undefined;
337
+ if (existing) {
338
+ await existing.configureAcp?.(services.settings.settings(id));
339
+ await existing.stop();
340
+ this.drivers.delete(id);
341
+ }
342
+ if (save && driver) {
343
+ services.settings.saveAgent(save);
344
+ this.drivers.set(id, driver);
345
+ await driver.start(this.driverHost);
346
+ }
347
+ else
348
+ services.settings.removeAgent(id);
349
+ }
350
+ return services.settings.agents();
351
+ }
244
352
  /** Re-checks login state in the background when the cached answer is older than `maxAgeMs`. */
245
353
  refreshAuthIfStale(maxAgeMs = 60_000) {
246
354
  if (this.authRefreshing)
@@ -352,9 +460,12 @@ export class SessionHub {
352
460
  if (first) {
353
461
  decorated.permission = {
354
462
  requestId: first.requestId,
463
+ childSessionId: first.childSessionId,
355
464
  toolCallId: first.toolCallId,
356
465
  title: first.title,
357
466
  detail: first.detail,
467
+ tool: first.tool,
468
+ url: first.url,
358
469
  options: first.options,
359
470
  questions: first.questions,
360
471
  };
@@ -674,6 +785,8 @@ export class SessionHub {
674
785
  task: detail?.task ?? call.title,
675
786
  agentType: detail?.agentType,
676
787
  name: detail?.name,
788
+ nativeSessionId: detail?.nativeSessionId,
789
+ canCancel: detail?.canCancel,
677
790
  running,
678
791
  failed: (workflow?.state ? workflow.state === "failed" : detail?.state ? detail.state === "failed" : state.status === "failed") || undefined,
679
792
  startedAt: workflow?.startedAt ?? event.ts,
@@ -685,6 +798,13 @@ export class SessionHub {
685
798
  }
686
799
  return [...agents.values()].reverse();
687
800
  }
801
+ async cancelSubagent(sessionId, nativeSessionId) {
802
+ const session = this.getSession(sessionId), driver = this.requireDriver(session.agent);
803
+ if (!driver.cancelSubagent)
804
+ throw RpcError.app("not_supported", "这个 AI 不支持单独停止子代理");
805
+ await this.ensureAttached(sessionId);
806
+ await driver.cancelSubagent(session.nativeId, nativeSessionId);
807
+ }
688
808
  subagentsOf(sessionId, live) {
689
809
  if (!live.subagents) {
690
810
  live.subagents = new Map();
@@ -1032,9 +1152,11 @@ export class SessionHub {
1032
1152
  const other = question.other ? answer.other?.trim() || undefined : undefined;
1033
1153
  return [{ id: question.id, values, other }];
1034
1154
  });
1035
- const missing = request.questions.find((question) => question.required && !kept.some((answer) => answer.id === question.id && (answer.values.some(Boolean) || answer.other)));
1036
- if (missing)
1037
- throw RpcError.app("invalid_params", `还没回答:${missing.header ?? missing.text}`);
1155
+ for (const question of request.questions) {
1156
+ const error = questionAnswerError(question, kept.find((answer) => answer.id === question.id));
1157
+ if (error)
1158
+ throw RpcError.app("invalid_params", error);
1159
+ }
1038
1160
  await driver.answerQuestion(summary.nativeId, requestId, kept);
1039
1161
  }
1040
1162
  async desktopLaunch(agent, args, sessionId, context) {
@@ -1267,6 +1389,8 @@ export class SessionHub {
1267
1389
  // A finished turn can't still be waiting on approvals; clear stale cards.
1268
1390
  if (update.sessionUpdate === "ls_turn" && update.state === "ended" && !update.parentToolCallId) {
1269
1391
  for (const requestId of [...live.permissions.keys()]) {
1392
+ if (live.permissions.get(requestId)?.childSessionId)
1393
+ continue;
1270
1394
  this.commit(sessionId, { sessionUpdate: "ls_permission_resolved", requestId });
1271
1395
  }
1272
1396
  if (!live.importing)
@@ -1303,6 +1427,18 @@ export class SessionHub {
1303
1427
  activityChanged = true;
1304
1428
  };
1305
1429
  switch (update.sessionUpdate) {
1430
+ case "ls_message": {
1431
+ if (update.parentToolCallId || !update.content)
1432
+ break;
1433
+ const text = update.content.filter((block) => block.type === "text").map((block) => block.text).join("");
1434
+ if (update.role === "user" && !before.title && text.trim())
1435
+ patch.title = compact(text, TITLE_LENGTH);
1436
+ if (update.role === "agent" && text.trim())
1437
+ patch.preview = compact(text, PREVIEW_LENGTH);
1438
+ if (live.turnActive && update.role === "agent")
1439
+ setActivity({ kind: "responding" });
1440
+ break;
1441
+ }
1306
1442
  case "user_message_chunk": {
1307
1443
  const text = update.content.type === "text" ? update.content.text : "";
1308
1444
  if (text && !before.title)
@@ -1340,12 +1476,12 @@ export class SessionHub {
1340
1476
  live.turnActive = update.state === "started";
1341
1477
  setActivity(live.turnActive ? { kind: "thinking" } : undefined);
1342
1478
  // Leftover permissions are cleared right after a turn ends (see commit).
1343
- patch.state = live.turnActive ? "running" : update.stopReason === "error" ? "error" : "idle";
1479
+ patch.state = live.turnActive ? "running" : [...live.permissions.values()].some((permission) => permission.childSessionId) ? "waiting" : update.stopReason === "error" ? "error" : "idle";
1344
1480
  break;
1345
1481
  case "ls_status":
1346
1482
  patch.state = update.state;
1347
1483
  if (!live.importing) {
1348
- live.turnActive = update.state === "running" || update.state === "waiting";
1484
+ live.turnActive = update.turnActive ?? (update.state === "running" || update.state === "waiting");
1349
1485
  if (!live.turnActive)
1350
1486
  setActivity(undefined);
1351
1487
  }
@@ -1362,8 +1498,13 @@ export class SessionHub {
1362
1498
  patch.state = live.turnActive ? "running" : "idle";
1363
1499
  break;
1364
1500
  case "session_info_update":
1365
- if (update.title)
1366
- patch.title = compact(update.title, TITLE_LENGTH);
1501
+ if (update.title !== undefined)
1502
+ patch.title = update.title === null ? null : compact(update.title, TITLE_LENGTH);
1503
+ if (update.updatedAt !== undefined) {
1504
+ const updatedAt = update.updatedAt === null ? before.createdAt : Date.parse(update.updatedAt);
1505
+ if (Number.isFinite(updatedAt))
1506
+ patch.updatedAt = updatedAt;
1507
+ }
1367
1508
  if (update.model)
1368
1509
  patch.model = update.model;
1369
1510
  break;