termdock 1.4.97 → 1.4.99

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 (81) hide show
  1. package/.desktop-dist/main.js +211 -34
  2. package/dist/client/assets/{ModelPreview-DCC_cgBs.js → ModelPreview-CJK3Nmg4.js} +165 -165
  3. package/dist/client/assets/{abnfDiagram-VRR7QNED-ByotYhVU.js → abnfDiagram-VRR7QNED-C-QKkcSr.js} +1 -1
  4. package/dist/client/assets/{arc-oaeK9Fn4.js → arc-BpjFutHZ.js} +1 -1
  5. package/dist/client/assets/{architectureDiagram-ZJ3FMSHR-CnxQD5DT.js → architectureDiagram-ZJ3FMSHR-DeeuzGsk.js} +1 -1
  6. package/dist/client/assets/{blockDiagram-677ZJIJ3-Ds7-Gi7B.js → blockDiagram-677ZJIJ3-BkDiKR3-.js} +1 -1
  7. package/dist/client/assets/{c4Diagram-LMCZKHZV-BdPTvWqP.js → c4Diagram-LMCZKHZV-BX6424vk.js} +1 -1
  8. package/dist/client/assets/channel-BiaGwVDJ.js +1 -0
  9. package/dist/client/assets/{chunk-2Q5K7J3B-BHB6J78_.js → chunk-2Q5K7J3B-DwNMfRvw.js} +1 -1
  10. package/dist/client/assets/{chunk-32BRIVSS-hzsoKeck.js → chunk-32BRIVSS-D5g3chKu.js} +1 -1
  11. package/dist/client/assets/{chunk-5VM5RSS4-MGUgwiHw.js → chunk-5VM5RSS4-B2rw8Ldu.js} +1 -1
  12. package/dist/client/assets/{chunk-EX3LRPZG-BKnPJAiI.js → chunk-EX3LRPZG-j3CVdb45.js} +1 -1
  13. package/dist/client/assets/{chunk-JWPE2WC7-Dfdv_575.js → chunk-JWPE2WC7-iHTR9CAX.js} +1 -1
  14. package/dist/client/assets/{chunk-MOJQB5TN-CKEHojX9.js → chunk-MOJQB5TN-DVD1wXze.js} +1 -1
  15. package/dist/client/assets/{chunk-RYQCIY6F-DqWvLIet.js → chunk-RYQCIY6F-zZRopnRd.js} +1 -1
  16. package/dist/client/assets/{chunk-V7JOEXUC-BtutDi_L.js → chunk-V7JOEXUC-h4EZpc4k.js} +1 -1
  17. package/dist/client/assets/{chunk-VR4S4FIN-B2cuDdQf.js → chunk-VR4S4FIN-C9MZH2Oy.js} +1 -1
  18. package/dist/client/assets/{chunk-XXDRQBXY-udLcfG1V.js → chunk-XXDRQBXY-BNPDO5fQ.js} +1 -1
  19. package/dist/client/assets/classDiagram-OUVF2IWQ-DYljVZD_.js +1 -0
  20. package/dist/client/assets/classDiagram-v2-EOCWNBFH-DYljVZD_.js +1 -0
  21. package/dist/client/assets/{cose-bilkent-JH36ORCC-DqOCMKxN.js → cose-bilkent-JH36ORCC-DlqULumX.js} +1 -1
  22. package/dist/client/assets/{cynefin-VYW2F7L2-Drck5nNi.js → cynefin-VYW2F7L2-D6pWZSwi.js} +1 -1
  23. package/dist/client/assets/{cynefinDiagram-TSTJHNR4-BHbsvV_H.js → cynefinDiagram-TSTJHNR4-B6SI7XOe.js} +1 -1
  24. package/dist/client/assets/{dagre-VKFMJZFB-27UzxTIz.js → dagre-VKFMJZFB-DXnKJ4XD.js} +1 -1
  25. package/dist/client/assets/{diagram-FQU43EPY-yrQuBDwj.js → diagram-FQU43EPY-B5NTAhw6.js} +1 -1
  26. package/dist/client/assets/{diagram-G47NLZAW-BZiJ5Qye.js → diagram-G47NLZAW-Dihaal0B.js} +1 -1
  27. package/dist/client/assets/{diagram-NH7WQ7WH-BRLMfHoI.js → diagram-NH7WQ7WH-Be987DPJ.js} +1 -1
  28. package/dist/client/assets/{diagram-OA4YK3LP-ChR7fBMa.js → diagram-OA4YK3LP-CfgTeXAJ.js} +1 -1
  29. package/dist/client/assets/{diagram-WEI45ONY-beJeXBUS.js → diagram-WEI45ONY-BgrK8rP2.js} +1 -1
  30. package/dist/client/assets/{ebnfDiagram-CCIWWBDH-BEnzKQgq.js → ebnfDiagram-CCIWWBDH-BPsH1_QO.js} +1 -1
  31. package/dist/client/assets/{erDiagram-Q63AITRT-abMcC3O5.js → erDiagram-Q63AITRT-F3s7Ytrc.js} +1 -1
  32. package/dist/client/assets/{flowDiagram-23GEKE2U-Cf_z-brB.js → flowDiagram-23GEKE2U-ByL-8svD.js} +1 -1
  33. package/dist/client/assets/{ganttDiagram-NO4QXBWP-CLGNuYtO.js → ganttDiagram-NO4QXBWP-Dtv-fi06.js} +1 -1
  34. package/dist/client/assets/{gitGraphDiagram-IHSO6WYX-DAO69bU6.js → gitGraphDiagram-IHSO6WYX-CeD48POl.js} +1 -1
  35. package/dist/client/assets/index-C82Uc6Vy.js +451 -0
  36. package/dist/client/assets/index-RO2b079_.css +1 -0
  37. package/dist/client/assets/{infoDiagram-FWYZ7A6U-ByWatnBT.js → infoDiagram-FWYZ7A6U-BxvLe33p.js} +1 -1
  38. package/dist/client/assets/{ishikawaDiagram-FXEZZL3T-Bxt5Yqg4.js → ishikawaDiagram-FXEZZL3T-XPW1aoJK.js} +1 -1
  39. package/dist/client/assets/{journeyDiagram-5HDEW3XC-Dafr7Sfu.js → journeyDiagram-5HDEW3XC-Bhiae04Z.js} +1 -1
  40. package/dist/client/assets/{kanban-definition-HUTT4EX6-D1Kng2jH.js → kanban-definition-HUTT4EX6-D5iOY3Zc.js} +1 -1
  41. package/dist/client/assets/{linear-BDTQPYjb.js → linear-PCgLsFTe.js} +1 -1
  42. package/dist/client/assets/{mermaid.core-BqsgBUDL.js → mermaid.core-DWuc-xG5.js} +4 -4
  43. package/dist/client/assets/{mindmap-definition-LN4V7U3C-WlWlxPeq.js → mindmap-definition-LN4V7U3C-C0EFK91v.js} +1 -1
  44. package/dist/client/assets/{pegDiagram-2B236MQR-CeuVjVf0.js → pegDiagram-2B236MQR-ClTz8aHa.js} +1 -1
  45. package/dist/client/assets/{pieDiagram-ENE6RG2P-DdLAXZnA.js → pieDiagram-ENE6RG2P-BuTv1DGN.js} +1 -1
  46. package/dist/client/assets/{quadrantDiagram-ABIIQ3AL-BSI4gC6Y.js → quadrantDiagram-ABIIQ3AL-FLZC-cqI.js} +1 -1
  47. package/dist/client/assets/{railroadDiagram-RFXS5EU6-DHGWP4uI.js → railroadDiagram-RFXS5EU6-DK68FlFh.js} +1 -1
  48. package/dist/client/assets/{requirementDiagram-TGXJPOKE--sP3n7Ar.js → requirementDiagram-TGXJPOKE-B_701AJ1.js} +1 -1
  49. package/dist/client/assets/{sankeyDiagram-HTMAVEWB-CTBy3q73.js → sankeyDiagram-HTMAVEWB-Bk87L7JG.js} +1 -1
  50. package/dist/client/assets/{sequenceDiagram-DBY2YBRQ-D2p6MaPI.js → sequenceDiagram-DBY2YBRQ-Biy5tPTS.js} +1 -1
  51. package/dist/client/assets/{sizeCapture-X5ZJPWSS-C-8i892J.js → sizeCapture-X5ZJPWSS-__4zzUuh.js} +1 -1
  52. package/dist/client/assets/{stateDiagram-2N3HPSRC-BfWCgCA0.js → stateDiagram-2N3HPSRC-B_400cf9.js} +1 -1
  53. package/dist/client/assets/stateDiagram-v2-6OUMAXLB-CK77br3V.js +1 -0
  54. package/dist/client/assets/{swimlanes-5IMT3BWC-Dnftro8u.js → swimlanes-5IMT3BWC-CxWZz0n0.js} +2 -2
  55. package/dist/client/assets/swimlanesDiagram-G3AALYLV-DbYe8ax3.js +8 -0
  56. package/dist/client/assets/{timeline-definition-FHXFAJF6-D7l7Wf7T.js → timeline-definition-FHXFAJF6-DSrIUp8H.js} +1 -1
  57. package/dist/client/assets/{vennDiagram-L72KCM5P-ClDuwHNb.js → vennDiagram-L72KCM5P-CdwaUmpL.js} +1 -1
  58. package/dist/client/assets/{wardleyDiagram-EHGQE667-BZ3yiEXX.js → wardleyDiagram-EHGQE667-DwxlF0Xk.js} +1 -1
  59. package/dist/client/assets/{xychartDiagram-FW5EYKEG-BGZ_BXST.js → xychartDiagram-FW5EYKEG-CQNmEc_n.js} +1 -1
  60. package/dist/client/index.html +2 -2
  61. package/dist/client/sw-notifications.js +7 -3
  62. package/dist/client/sw.js +1 -1
  63. package/dist/server/agent/automationStore.js +151 -0
  64. package/dist/server/agent/collaborationStore.js +145 -0
  65. package/dist/server/agent/installers.js +50 -12
  66. package/dist/server/agent/plugins.js +9 -0
  67. package/dist/server/agent/registry.js +1 -0
  68. package/dist/server/agent/resumeHistory.js +100 -0
  69. package/dist/server/agent/resumePersistence.js +35 -0
  70. package/dist/server/agent/sessionSearchStore.js +124 -0
  71. package/dist/server/cli.js +139 -0
  72. package/dist/server/routes/terminal.js +709 -46
  73. package/package.json +3 -2
  74. package/runtime-manifest.json +2 -2
  75. package/dist/client/assets/channel-Cpdbh5br.js +0 -1
  76. package/dist/client/assets/classDiagram-OUVF2IWQ-DWre1xlG.js +0 -1
  77. package/dist/client/assets/classDiagram-v2-EOCWNBFH-DWre1xlG.js +0 -1
  78. package/dist/client/assets/index-BYhY8AKn.css +0 -1
  79. package/dist/client/assets/index-CshWxisE.js +0 -451
  80. package/dist/client/assets/stateDiagram-v2-6OUMAXLB-DzD8Rob4.js +0 -1
  81. package/dist/client/assets/swimlanesDiagram-G3AALYLV-D8QuXUOK.js +0 -8
@@ -181,6 +181,14 @@ Short commands:
181
181
  agent-event <slug> <event> [status]
182
182
  Emit one lifecycle/status event from an Agent hook.
183
183
  pi Same as agent-plugin
184
+ collab status Show this Session's collaboration groups and peers
185
+ collab inbox Read and acknowledge collaboration messages
186
+ collab send <session-id> <message>
187
+ Send a durable message to a related Session
188
+ collab handoff <session-id> <summary>
189
+ Hand off work and context to another Session
190
+ collab reply <message-id> <message>
191
+ Reply in the original collaboration thread
184
192
  plugin-create <file>
185
193
  Same as --plugin-create <file>
186
194
  plugin-install <source>
@@ -543,6 +551,7 @@ function parseArgs(argv) {
543
551
  let pluginHooks;
544
552
  let pluginRemove;
545
553
  let agentEvent;
554
+ let collab;
546
555
  // Short command aliases for the common path. Keep these positional-only so
547
556
  // long-form flags remain the single source of truth for option semantics.
548
557
  if (argv[0] && !argv[0].startsWith('-')) {
@@ -659,6 +668,27 @@ function parseArgs(argv) {
659
668
  process.exit(1);
660
669
  }
661
670
  }
671
+ else if (command === 'collab') {
672
+ const action = (next || 'status');
673
+ const json = argv.includes('--json');
674
+ if (action === 'status' || action === 'inbox') {
675
+ collab = { action, json };
676
+ }
677
+ else if (action === 'send' || action === 'handoff' || action === 'reply') {
678
+ const target = argv[2];
679
+ const message = argv.slice(3).filter((part) => part !== '--json').join(' ').trim();
680
+ if (!target || !message) {
681
+ console.error(`${ICON.err} ${c.red(`Usage: td collab ${action} <${action === 'reply' ? 'message-id' : 'session-id'}> <message>`)}`);
682
+ process.exit(1);
683
+ }
684
+ collab = { action, target, message, json };
685
+ }
686
+ else {
687
+ console.error(`${ICON.err} ${c.red('Usage: td collab <status|inbox|send|handoff|reply>')}`);
688
+ process.exit(1);
689
+ }
690
+ argv = [];
691
+ }
662
692
  else if (command === 'pcreate' || command === 'plugin-create') {
663
693
  if (next && !next.startsWith('-')) {
664
694
  pluginCreate = next;
@@ -1020,6 +1050,7 @@ function parseArgs(argv) {
1020
1050
  pluginHooks,
1021
1051
  pluginRemove,
1022
1052
  agentEvent,
1053
+ collab,
1023
1054
  };
1024
1055
  }
1025
1056
  // Reads a single line from stdin without echoing keystrokes. Used for password
@@ -1204,6 +1235,98 @@ async function getLocalJson(baseUrl, token, endpoint) {
1204
1235
  req.end();
1205
1236
  });
1206
1237
  }
1238
+ async function runCollab(command) {
1239
+ const runningState = getRunningState();
1240
+ if (!runningState?.localApiToken) {
1241
+ console.error(`${ICON.err} ${c.red('Termdock is not running or its local API token is unavailable.')}`);
1242
+ process.exit(1);
1243
+ }
1244
+ const backendSessionId = process.env.TERMDOCK_BACKEND_SESSION_ID?.trim() || null;
1245
+ let tmuxSessionName = null;
1246
+ if (!backendSessionId && process.env.TMUX) {
1247
+ try {
1248
+ const { stdout } = await execFileAsync(process.env.TMUX_BIN || 'tmux', ['display-message', '-p', '#S'], {
1249
+ timeout: 2_000,
1250
+ maxBuffer: 16 * 1024,
1251
+ });
1252
+ const detected = stdout.trim();
1253
+ if (detected && !detected.includes('\n') && detected.length <= 128)
1254
+ tmuxSessionName = detected;
1255
+ }
1256
+ catch {
1257
+ // The explicit backend id remains the primary path; tmux is a fallback
1258
+ // for managed panes whose inner shell predates the attach wrapper env.
1259
+ }
1260
+ }
1261
+ if (!backendSessionId && !tmuxSessionName) {
1262
+ console.error(`${ICON.err} ${c.red('td collab must run inside a Termdock-managed Session.')}`);
1263
+ process.exit(1);
1264
+ }
1265
+ const context = backendSessionId ? { backendSessionId } : { tmuxSessionName };
1266
+ const contextQuery = new URLSearchParams(Object.entries(context).filter((entry) => typeof entry[1] === 'string')).toString();
1267
+ const baseUrl = runningState.localUrl
1268
+ ?? `${runningState.scheme ?? 'http'}://${runningState.host === '0.0.0.0' ? 'localhost' : runningState.host}:${runningState.port}`;
1269
+ let response;
1270
+ if (command.action === 'status') {
1271
+ response = await getLocalJson(baseUrl, runningState.localApiToken, `/api/terminal/operations/orchestration/peers?${contextQuery}`);
1272
+ }
1273
+ else if (command.action === 'inbox') {
1274
+ response = await getLocalJson(baseUrl, runningState.localApiToken, `/api/terminal/operations/orchestration/inbox?${contextQuery}&markRead=true`);
1275
+ }
1276
+ else if (command.action === 'reply') {
1277
+ response = await postLocalJson(baseUrl, runningState.localApiToken, '/api/terminal/operations/orchestration/reply', {
1278
+ ...context,
1279
+ messageId: command.target,
1280
+ content: command.message,
1281
+ });
1282
+ }
1283
+ else {
1284
+ response = await postLocalJson(baseUrl, runningState.localApiToken, '/api/terminal/operations/orchestration/send', {
1285
+ ...context,
1286
+ targetSessionId: command.target,
1287
+ message: command.message,
1288
+ kind: command.action === 'handoff' ? 'handoff' : 'message',
1289
+ });
1290
+ }
1291
+ let body = {};
1292
+ try {
1293
+ body = JSON.parse(response.body || '{}');
1294
+ }
1295
+ catch { /* handled below */ }
1296
+ if (response.statusCode < 200 || response.statusCode >= 300) {
1297
+ console.error(`${ICON.err} ${c.red(typeof body.error === 'string' ? body.error : 'Collaboration request failed')}`);
1298
+ process.exit(1);
1299
+ }
1300
+ if (command.json) {
1301
+ console.log(JSON.stringify(body, null, 2));
1302
+ return;
1303
+ }
1304
+ if (command.action === 'status') {
1305
+ const groups = Array.isArray(body.groups) ? body.groups : [];
1306
+ const peers = Array.isArray(body.peers) ? body.peers : [];
1307
+ console.log(`${ICON.ok} ${c.green(`Collaboration: ${groups.length} group(s), ${peers.length} peer(s)`)}`);
1308
+ for (const peer of peers) {
1309
+ console.log(` ${c.cyan(peer.name ?? peer.sessionId ?? 'Session')} ${c.dim(`[${peer.sessionId ?? ''}]`)}`);
1310
+ console.log(` ${peer.status ?? 'offline'} · ${peer.capability ?? ''}`);
1311
+ if (peer.currentTask)
1312
+ console.log(` ${c.dim(peer.currentTask)}`);
1313
+ }
1314
+ return;
1315
+ }
1316
+ if (command.action === 'inbox') {
1317
+ const messages = Array.isArray(body.messages) ? body.messages : [];
1318
+ if (messages.length === 0) {
1319
+ console.log(`${ICON.ok} ${c.dim('Collaboration inbox is empty.')}`);
1320
+ return;
1321
+ }
1322
+ for (const message of messages) {
1323
+ console.log(`${c.cyan(message.kind ?? 'message')} ${c.dim(`#${message.id ?? ''}`)} from ${message.fromSessionId ?? 'user'}`);
1324
+ console.log(` ${message.content ?? ''}`);
1325
+ }
1326
+ return;
1327
+ }
1328
+ console.log(`${ICON.ok} ${c.green(command.action === 'reply' ? 'Reply sent.' : command.action === 'handoff' ? 'Handoff sent.' : 'Message sent.')}`);
1329
+ }
1207
1330
  async function runInjectChangeAudit(source) {
1208
1331
  const raw = source === true
1209
1332
  ? await readStdinText()
@@ -1809,6 +1932,7 @@ const AGENT_PLUGIN_EXAMPLE = {
1809
1932
  slug: 'my-agent',
1810
1933
  displayName: 'My Agent',
1811
1934
  aliases: ['my-agent'],
1935
+ capabilities: ['code-review', 'testing'],
1812
1936
  accentColor: '#4385BE',
1813
1937
  iconMode: 'mask',
1814
1938
  statuses: [
@@ -1872,6 +1996,11 @@ function runPluginInitJson() {
1872
1996
  indicator: 'Theme-safe visual indicator.',
1873
1997
  tone: 'Theme token; arbitrary status colors are not accepted.',
1874
1998
  },
1999
+ collaboration: {
2000
+ capabilities: 'Optional routing hints shown beside this Agent in collaboration groups.',
2001
+ universalTransport: 'Every detected Agent receives durable inbox messages through its PTY and can use td collab when it has shell access.',
2002
+ hooks: 'Hooks add busy/idle awareness so Termdock can defer delivery until a turn finishes; they are not required for collaboration.',
2003
+ },
1875
2004
  security: {
1876
2005
  source: 'Only public HTTPS repository roots on approved Git hosts or explicit local paths are accepted; URL credentials are rejected.',
1877
2006
  package: 'Symlinks, active/external SVG content, oversized files, submodules, and excessive unpacked size are rejected.',
@@ -1906,6 +2035,7 @@ function runPluginInitJson() {
1906
2035
  'If the Agent hook format is not a Claude-style hooks map, configure native hooks to call td agent-event directly.',
1907
2036
  'Map the completed-turn hook to event "stop"; this is also the automatic-title trigger when the user enables titles for the Agent.',
1908
2037
  'Optionally declare titleNamer so this Agent can generate titles and dynamically publish its own model catalog.',
2038
+ 'Optionally declare capabilities so users and peer Agents can see what this Agent is suited for.',
1909
2039
  'Put optional model flags in titleNamer.modelArgs; keep the always-present prompt invocation in titleNamer.args.',
1910
2040
  'Run td plugin-doctor <slug> --json and fix every warning before sharing the repository.',
1911
2041
  'Tell the user that enabling a plugin title provider executes that plugin\'s declared CLI; installation alone never does.',
@@ -1972,6 +2102,9 @@ ${c.dim('───────────────────')}
1972
2102
  ${c.dim('// First alias is the primary binary name; extras match npm/pip wrappers.')}
1973
2103
  "aliases": ["trae", "traecli"],
1974
2104
 
2105
+ ${c.dim('// Optional collaboration routing hints (max 32 short names).')}
2106
+ "capabilities": ["code-review", "frontend", "testing"],
2107
+
1975
2108
  ${c.dim('// Brand accent color as 6-digit hex. Used for avatar background in mask mode,')}
1976
2109
  ${c.dim('// and as the status-dot color. Must be Flexoki-family or brand theme-safe.')}
1977
2110
  "accentColor": "#4385BE",
@@ -2181,6 +2314,8 @@ async function runPluginList(json = false) {
2181
2314
  if (p.updateAvailable)
2182
2315
  flags.push('update');
2183
2316
  console.log(` ${c.cyan(p.slug)} ${c.dim(p.displayName)} ${c.gray(p.accentColor)} ${c.dim(flags.length > 0 ? `[${flags.join(', ')}]` : '')}`);
2317
+ if (p.capabilities?.length)
2318
+ console.log(` ${c.dim(`capabilities: ${p.capabilities.join(', ')}`)}`);
2184
2319
  if (p.source)
2185
2320
  console.log(` ${c.dim(`${p.sourceType ?? 'source'}: ${p.source}${p.revision ? ` @ ${p.revision.slice(0, 8)}` : ''}`)}`);
2186
2321
  }
@@ -3239,6 +3374,10 @@ async function main() {
3239
3374
  if (options.agentEvent) {
3240
3375
  runAgentEvent(options.agentEvent);
3241
3376
  }
3377
+ if (options.collab) {
3378
+ await runCollab(options.collab);
3379
+ process.exit(0);
3380
+ }
3242
3381
  if (options.pluginInit) {
3243
3382
  if (options.pluginInitJson)
3244
3383
  runPluginInitJson();