@deepseek-harness-tui/dsh-tui 0.8.6 → 0.8.7

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 +13 -3
  2. package/bin/dsh-tui.js +269 -218
  3. package/cordis.patch.yml +48 -22
  4. package/lib/types/cc/figures.d.ts.map +1 -1
  5. package/lib/types/cc/figures.js +14 -13
  6. package/lib/types/cc/syntaxRuns.d.ts +16 -0
  7. package/lib/types/cc/syntaxRuns.d.ts.map +1 -0
  8. package/lib/types/cc/syntaxRuns.js +79 -0
  9. package/lib/types/commands.d.ts +14 -0
  10. package/lib/types/commands.d.ts.map +1 -1
  11. package/lib/types/commands.js +20 -1
  12. package/lib/types/components/Chat/SubagentMessage.d.ts +19 -0
  13. package/lib/types/components/Chat/SubagentMessage.d.ts.map +1 -0
  14. package/lib/types/components/Chat/SubagentMessage.js +75 -0
  15. package/lib/types/components/EffortInputBorder.d.ts.map +1 -1
  16. package/lib/types/components/EffortInputBorder.js +2 -2
  17. package/lib/types/components/EffortTierBadge.js +1 -1
  18. package/lib/types/components/HelpMenu.d.ts +8 -1
  19. package/lib/types/components/HelpMenu.d.ts.map +1 -1
  20. package/lib/types/components/HelpMenu.js +15 -4
  21. package/lib/types/components/LogoV2.d.ts +3 -1
  22. package/lib/types/components/LogoV2.d.ts.map +1 -1
  23. package/lib/types/components/LogoV2.js +2 -2
  24. package/lib/types/components/MessageList.d.ts +6 -2
  25. package/lib/types/components/MessageList.d.ts.map +1 -1
  26. package/lib/types/components/MessageList.js +17 -6
  27. package/lib/types/components/ModelPicker.js +2 -2
  28. package/lib/types/components/PromptInput.d.ts +1 -1
  29. package/lib/types/components/PromptInput.d.ts.map +1 -1
  30. package/lib/types/components/PromptInput.js +75 -15
  31. package/lib/types/components/SkillsPicker.js +2 -2
  32. package/lib/types/components/SplitDiffView.d.ts +1 -13
  33. package/lib/types/components/SplitDiffView.d.ts.map +1 -1
  34. package/lib/types/components/SplitDiffView.js +6 -105
  35. package/lib/types/components/SubagentCard.d.ts +9 -0
  36. package/lib/types/components/SubagentCard.d.ts.map +1 -0
  37. package/lib/types/components/SubagentCard.js +26 -0
  38. package/lib/types/components/SubagentDashboard.d.ts +13 -0
  39. package/lib/types/components/SubagentDashboard.d.ts.map +1 -0
  40. package/lib/types/components/SubagentDashboard.js +50 -0
  41. package/lib/types/components/SubagentDetailScene.d.ts +16 -0
  42. package/lib/types/components/SubagentDetailScene.d.ts.map +1 -0
  43. package/lib/types/components/SubagentDetailScene.js +141 -0
  44. package/lib/types/components/SyntaxText.d.ts +15 -0
  45. package/lib/types/components/SyntaxText.d.ts.map +1 -0
  46. package/lib/types/components/SyntaxText.js +34 -0
  47. package/lib/types/components/ThinkingToggle.d.ts +3 -10
  48. package/lib/types/components/ThinkingToggle.d.ts.map +1 -1
  49. package/lib/types/components/ThinkingToggle.js +4 -9
  50. package/lib/types/components/design-system/ListItem.d.ts.map +1 -1
  51. package/lib/types/components/design-system/ListItem.js +1 -1
  52. package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
  53. package/lib/types/components/messages/AssistantThinkingMessage.js +18 -7
  54. package/lib/types/components/messages/AssistantToolUseMessage.d.ts +2 -0
  55. package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
  56. package/lib/types/components/messages/AssistantToolUseMessage.js +42 -6
  57. package/lib/types/components/messages/UserPromptMessage.d.ts.map +1 -1
  58. package/lib/types/components/messages/UserPromptMessage.js +15 -2
  59. package/lib/types/dsh-adapter/channel.d.ts +53 -2
  60. package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
  61. package/lib/types/dsh-adapter/channel.js +294 -7
  62. package/lib/types/dsh-adapter/contract.d.ts +27 -4
  63. package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
  64. package/lib/types/dsh-adapter/contract.js +56 -10
  65. package/lib/types/dsh-adapter/index.d.ts.map +1 -1
  66. package/lib/types/dsh-adapter/index.js +9 -3
  67. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
  68. package/lib/types/dsh-adapter/plugin.js +38 -0
  69. package/lib/types/dsh-adapter/shortcuts.js +3 -3
  70. package/lib/types/dsh-adapter/subagents.d.ts +87 -0
  71. package/lib/types/dsh-adapter/subagents.d.ts.map +1 -0
  72. package/lib/types/dsh-adapter/subagents.js +204 -0
  73. package/lib/types/herdr.d.ts +28 -0
  74. package/lib/types/herdr.d.ts.map +1 -0
  75. package/lib/types/herdr.js +133 -0
  76. package/lib/types/i18n.d.ts +215 -31
  77. package/lib/types/i18n.d.ts.map +1 -1
  78. package/lib/types/i18n.js +65 -14
  79. package/lib/types/ink/ink.d.ts +4 -0
  80. package/lib/types/ink/ink.d.ts.map +1 -1
  81. package/lib/types/ink/ink.js +46 -15
  82. package/lib/types/minimalMode.d.ts +13 -0
  83. package/lib/types/minimalMode.d.ts.map +1 -0
  84. package/lib/types/minimalMode.js +17 -0
  85. package/lib/types/screens/Chat.d.ts +1 -1
  86. package/lib/types/screens/Chat.d.ts.map +1 -1
  87. package/lib/types/screens/Chat.js +94 -43
  88. package/lib/types/screens/StatusLine.d.ts.map +1 -1
  89. package/lib/types/screens/StatusLine.js +6 -2
  90. package/lib/types/screens/TrajectoryScene.d.ts.map +1 -1
  91. package/lib/types/screens/TrajectoryScene.js +4 -2
  92. package/lib/types/theme.d.ts +8 -0
  93. package/lib/types/theme.d.ts.map +1 -1
  94. package/lib/types/theme.js +38 -14
  95. package/lib/types/tips.js +3 -3
  96. package/lib/types/update.d.ts +18 -0
  97. package/lib/types/update.d.ts.map +1 -1
  98. package/lib/types/update.js +73 -2
  99. package/lib/types/utils/execFileNoThrow.d.ts +3 -20
  100. package/lib/types/utils/execFileNoThrow.d.ts.map +1 -1
  101. package/lib/types/utils/execFileNoThrow.js +53 -32
  102. package/lib/types/utils/externalEditor.d.ts +12 -11
  103. package/lib/types/utils/externalEditor.d.ts.map +1 -1
  104. package/lib/types/utils/externalEditor.js +11 -11
  105. package/package.json +64 -58
@@ -7,7 +7,7 @@ import { SessionId } from '@deepseek-ai/dsh-session';
7
7
  import { renderContextSections, renderPrompt } from '@deepseek-ai/dsh-system-prompt';
8
8
  import { loadBaselineInstructions } from '@deepseek-ai/dsh-agent-instructions';
9
9
  import { extname, isAbsolute, join } from 'node:path';
10
- import { completeCommands, isLocalCommandName, LOCAL_COMMANDS, parseCommandName } from '../commands.js';
10
+ import { completeCommands, HIDDEN_COMMAND_NAMES, isLocalCommandName, LOCAL_COMMANDS, parseCommandName } from '../commands.js';
11
11
  import { clearResumeTarget, forgetSession, readResumeTarget, touchSession, writeResumeTarget } from '../sessionHistory.js';
12
12
  import { appendSessionTitle, deleteSessionLog, ensureLegacySessionEventTypes, sessionsRoots } from './compat/index.js';
13
13
  import { listSummaries, locateSession, noteBranch, previewSession, } from './sessions/index.js';
@@ -25,8 +25,10 @@ import { extractMentions } from '../utils/mentions.js';
25
25
  import { t } from '../i18n.js';
26
26
  import { modeDisplayName, resolveSessionModes } from '../sessionModes.js';
27
27
  import { normalizeStatusBar, normalizeToolBackground } from '../tuiDisplayPrefs.js';
28
+ import { SubagentActivityStore } from './subagents.js';
28
29
  import { ActivityTracker } from 'dsh-working-activity/status';
29
30
  import { featureOn } from 'dsh-working-activity/config';
31
+ import { setMinimalMode } from '../minimalMode.js';
30
32
  import { readActivityConfig } from '../activityPrefs.js';
31
33
  import { attachSessionToWorkspace } from './workspace.js';
32
34
  import { createLocalWorkspaceRuntime, getHostWorkspaceRuntime } from './workspaces.js';
@@ -40,6 +42,7 @@ import { installDecisionGuard } from './decision-guard.js';
40
42
  import { commandOwner } from './command-attribution.js';
41
43
  import { readGrantStore } from './grants.js';
42
44
  import { hasCommandErrorCode, mapCommandError } from './command-errors.js';
45
+ import { installedLineOf } from './contract.js';
43
46
  import { pluginsInfoLines } from './plugins-info.js';
44
47
  import { cleanRenderText, cleanScalarText } from './sanitize.js';
45
48
  /** `tui/input` return normalization: transform/handled/cancel or no opinion.
@@ -136,6 +139,20 @@ function normalizeRewindDoneSummary(result, warn) {
136
139
  * observation (a provider whose directory watcher is still warming).
137
140
  */
138
141
  const SKILL_COMMAND_RETRY_MS = 800;
142
+ /** Names the subagent delegation tools ship under (preset `toolName` values
143
+ * plus the CLI default); each renders as a live subagent card, never a plain
144
+ * tool card. */
145
+ const SUBAGENT_TOOL_NAMES = new Set([
146
+ 'task',
147
+ 'subagent',
148
+ 'subagent_fork',
149
+ 'subagent_claude_code',
150
+ 'subagent_codex',
151
+ 'spawn_task',
152
+ ]);
153
+ function isSubagentToolName(name) {
154
+ return SUBAGENT_TOOL_NAMES.has(name.toLowerCase());
155
+ }
139
156
  const ARGS_PREVIEW_LIMIT = 160;
140
157
  const RESULT_PREVIEW_LIMIT = 240;
141
158
  /** Local `!`-command output cap (mirrors the result preview limit). */
@@ -405,6 +422,26 @@ async function waitForTurnEnd(session, fromSeq, timeoutMs) {
405
422
  export function createChannel(ctx, initialAgent, options) {
406
423
  let agent = initialAgent;
407
424
  let currentHandle = options.handle;
425
+ const subagentControl = {
426
+ interrupt(agentId) {
427
+ const child = subagentStore.get(agentId);
428
+ const target = child?.sessionId ?? agentId;
429
+ const runtime = ctx.subagents;
430
+ if (!runtime?.interrupt || !target)
431
+ return false;
432
+ try {
433
+ runtime.interrupt(target, { kind: 'ancestor', agent });
434
+ subagentStore.onCancelled(agentId, 'interrupted');
435
+ state.subagents = subagentStore.snapshot();
436
+ syncSubagentRows();
437
+ state.emit();
438
+ return true;
439
+ }
440
+ catch {
441
+ return false;
442
+ }
443
+ },
444
+ };
408
445
  // D-7 backstop: the extensions row installs the decision-subscription
409
446
  // gate, but the channel IS the dispatch path — a stale patch without that
410
447
  // row (or a bare embed mounting neither) would otherwise leave tui/input
@@ -418,6 +455,55 @@ export function createChannel(ctx, initialAgent, options) {
418
455
  const fallbackGrantStore = readGrantStore();
419
456
  const currentGrantStore = () => ctx.get('tuiPluginHost')?.grants ?? fallbackGrantStore;
420
457
  installDecisionGuard(ctx, currentGrantStore());
458
+ // Subagent activity tracking: collects agent/subagent/*, session/event for
459
+ // subagents, and exposes live snapshots for the UI.
460
+ const subagentStore = new SubagentActivityStore();
461
+ // Subagent ChatRow tracking: maps agentId to its ChatRow for live updates.
462
+ const subagentRowsByAgentId = new Map();
463
+ // Task tool descriptions, queued in call order; each subagent/start consumes
464
+ // the oldest one so the card shows the user-visible task label.
465
+ const pendingTaskDescriptions = [];
466
+ /**
467
+ * Sync subagentStore state into ChatRows (insert/update in state.rows).
468
+ * Called whenever subagent state changes (spawned/completed/failed/output).
469
+ */
470
+ const syncSubagentRows = () => {
471
+ const snapshot = subagentStore.snapshot();
472
+ for (const sub of snapshot) {
473
+ let row = subagentRowsByAgentId.get(sub.agentId);
474
+ if (!row) {
475
+ // New subagent: insert a new ChatRow after the last user or assistant message
476
+ row = {
477
+ id: nextRowId++,
478
+ kind: 'subagent',
479
+ text: sub.description,
480
+ subagent: undefined, // will be filled below
481
+ };
482
+ subagentRowsByAgentId.set(sub.agentId, row);
483
+ state.rows.push(row);
484
+ }
485
+ const subagentRow = {
486
+ agentId: sub.agentId,
487
+ runId: sub.runId,
488
+ description: sub.description,
489
+ provider: sub.provider,
490
+ model: sub.model || 'default',
491
+ effort: sub.effort,
492
+ status: sub.status,
493
+ startedAt: sub.startedAt,
494
+ completedAt: sub.completedAt,
495
+ durationMs: sub.completedAt ? sub.completedAt - sub.startedAt : Date.now() - sub.startedAt,
496
+ outputLines: sub.output.slice(-3),
497
+ toolCalls: sub.toolCalls,
498
+ tokens: sub.tokens,
499
+ summary: sub.summary,
500
+ stopReason: sub.stopReason,
501
+ error: sub.error,
502
+ };
503
+ row.subagent = subagentRow;
504
+ row.text = sub.description;
505
+ }
506
+ };
421
507
  // The DSH slash-command registry (optional service): /plan, /goal and
422
508
  // friends register here; the TUI merges their descriptors into the slash
423
509
  // menu and dispatches through `execute` (which logs the paired
@@ -686,6 +772,12 @@ export function createChannel(ctx, initialAgent, options) {
686
772
  /** Monotonic token: only the latest `interruptAndDeliver` re-queues, so a
687
773
  * second interrupt while the abort settles cannot double-deliver. */
688
774
  let interruptSeq = 0;
775
+ // Cancellation is asynchronous: a fast second Esc can arrive after the
776
+ // driver has accepted the first abort but before its turn/end event lands.
777
+ // Do not cancel the same driver twice, or the second cancel can swallow the
778
+ // replacement work queued by interruptAndDeliver and leave the UI gated on
779
+ // a working flag that has not observed turn/end yet.
780
+ let cancelInFlight = false;
689
781
  /** The llm runtime seam (dsh-llm LlmRuntime): route metadata resolution. */
690
782
  const llmRuntime = ctx.get('llm');
691
783
  /** Mutable per-agent model selection (dsh-agent's routing override seam).
@@ -818,6 +910,16 @@ export function createChannel(ctx, initialAgent, options) {
818
910
  applyEffort(found);
819
911
  return true;
820
912
  };
913
+ /** Whether the installed command service takes composer images: rc line
914
+ * gate with a structural fallback, so a failed manifest probe (bundlers,
915
+ * exotic loaders) still lands on the 4-param rc.8 shape at runtime. */
916
+ const commandServiceSupportsImages = (service) => {
917
+ const line = installedLineOf('@deepseek-ai/dsh-commands');
918
+ if (line !== undefined)
919
+ return line >= 8;
920
+ return typeof service.execute?.length === 'number'
921
+ && service.execute.length >= 4;
922
+ };
821
923
  /** Run one DSH registry command (`/plan`, …) on the live agent; the text
822
924
  * of its result, '' when the result is textless, undefined when the
823
925
  * command is not registered, and the error message when it throws. */
@@ -864,7 +966,22 @@ export function createChannel(ctx, initialAgent, options) {
864
966
  return t('command-invoke-denied-owner', { name, owner: owner.componentId });
865
967
  }
866
968
  try {
867
- const execution = await commandService.execute(agent, `/${name}${rawInput}`, new AbortController().signal);
969
+ const signal = new AbortController().signal;
970
+ const line = `/${name}${rawInput}`;
971
+ const images = await registryCommandImages(commandService, definition, line, signal);
972
+ // rc.8 moved the signal to the 4th parameter and added composer
973
+ // images; older lines (rc.7/rc.6) take (agent, line, signal).
974
+ const execution = images === undefined
975
+ ? await commandService.execute(agent, line, signal)
976
+ : await commandService.execute(agent, line, images.images, signal);
977
+ if (images !== undefined && images.dropped.length > 0) {
978
+ // Loud-drop policy mirrors the submit pipeline (mentions-missing):
979
+ // a referenced image that never reached the command must be visible.
980
+ state.notify(t('mentions-missing', { paths: images.dropped.join(' ') }), {
981
+ color: 'warning',
982
+ timeoutMs: 4000,
983
+ });
984
+ }
868
985
  // `undefined` = not registered; a handler error surfaces as its
869
986
  // message so the user sees why the command failed.
870
987
  return execution?.result.text ?? '';
@@ -873,6 +990,51 @@ export function createChannel(ctx, initialAgent, options) {
873
990
  return error instanceof Error ? error.message : String(error);
874
991
  }
875
992
  };
993
+ /** Encode the staged `@`-mention images the user pasted for THIS command
994
+ * line into rc.8's `EncodedImageAttachment` payloads; undefined = the
995
+ * installed dsh-commands line predates composer images (rc.7/rc.6), so
996
+ * the caller uses the legacy 3-arg invoke. Matches the submit pipeline's
997
+ * token rule (expandMentions): a staged image attaches only when the
998
+ * line references its token. A command that does not declare
999
+ * `input.images` gets NO images — rc.8 admission settles such a batch
1000
+ * as an error, and upstream sends images only to image-capable commands.
1001
+ * A failing read drops just that image (reported via the returned
1002
+ * tokens) while the command still runs. */
1003
+ const registryCommandImages = async (service, definition, line, signal) => {
1004
+ if (!commandServiceSupportsImages(service))
1005
+ return undefined;
1006
+ const declaresImages = definition?.input?.images === true;
1007
+ if (!declaresImages || stagedImages.size === 0)
1008
+ return { images: [], dropped: [] };
1009
+ const store = mentionAttachments(ctx);
1010
+ if (typeof store?.readImage !== 'function')
1011
+ return { images: [], dropped: [] };
1012
+ const images = [];
1013
+ const dropped = [];
1014
+ for (const [token, attachment] of stagedImages) {
1015
+ if (!line.includes(token))
1016
+ continue;
1017
+ try {
1018
+ const stored = await store.readImage(attachment, signal);
1019
+ if (stored?.data instanceof Uint8Array && stored.data.byteLength > 0) {
1020
+ images.push({
1021
+ mediaType: attachment.mediaType,
1022
+ data: Buffer.from(stored.data).toString('base64'),
1023
+ name: attachment.name,
1024
+ });
1025
+ }
1026
+ else {
1027
+ dropped.push(token);
1028
+ }
1029
+ }
1030
+ catch {
1031
+ // One unreadable staged image is dropped — same loud policy as the
1032
+ // submit pipeline's mentions-missing warning (deliverUserText).
1033
+ dropped.push(token);
1034
+ }
1035
+ }
1036
+ return { images, dropped };
1037
+ };
876
1038
  // Session-mode folds: last-wins projections over the session log. The
877
1039
  // event types are registered by dsh-plan-mode / dsh-sandbox-policy /
878
1040
  // dsh-user-approval and are NOT in this package's typed SessionEvent
@@ -1001,6 +1163,8 @@ export function createChannel(ctx, initialAgent, options) {
1001
1163
  thinkingFold: options.thinkingFold ?? 'preview',
1002
1164
  toolBackground: normalizeToolBackground(options.toolBackground),
1003
1165
  statusBar: normalizeStatusBar(options.statusBar),
1166
+ whale: options.whale !== false,
1167
+ minimal: options.minimal === true,
1004
1168
  activityEnabled: options.activity !== false,
1005
1169
  contextBarEnabled: options.contextBar !== false,
1006
1170
  agentPreset: options.agentPreset,
@@ -1042,6 +1206,8 @@ export function createChannel(ctx, initialAgent, options) {
1042
1206
  thinking: 0,
1043
1207
  tools: 0,
1044
1208
  },
1209
+ subagents: [],
1210
+ subagentControl,
1045
1211
  subscribe(listener) {
1046
1212
  listeners.add(listener);
1047
1213
  return () => {
@@ -1165,6 +1331,11 @@ export function createChannel(ctx, initialAgent, options) {
1165
1331
  cancel() {
1166
1332
  // Keep the staged queue: an interrupt aborts the running turn but the
1167
1333
  // queued/steered messages are delivered as the next turn (web parity).
1334
+ // Cancellation converges asynchronously; ignore a repeated Esc/Ctrl+C
1335
+ // until the aborted turn has produced its terminal event.
1336
+ if (cancelInFlight)
1337
+ return;
1338
+ cancelInFlight = true;
1168
1339
  agent.cancel({ kind: 'user' }, { keepInbox: true });
1169
1340
  },
1170
1341
  interruptAndDeliver(texts) {
@@ -1176,8 +1347,13 @@ export function createChannel(ctx, initialAgent, options) {
1176
1347
  // followup. dsh-agent's cancel-convergence wake latch accepts this
1177
1348
  // wake immediately after cancel and starts it once the aborted turn
1178
1349
  // retires; waiting for whenIdle is unsafe because it also follows
1179
- // replacement work and may never settle.
1180
- agent.cancel({ kind: 'user' });
1350
+ // replacement work and may never settle. If cancellation is already
1351
+ // in flight, keep the existing abort and still replace the pending
1352
+ // interrupt delivery; fake/embedded agents may not emit turn/end.
1353
+ if (!cancelInFlight) {
1354
+ cancelInFlight = true;
1355
+ agent.cancel({ kind: 'user' });
1356
+ }
1181
1357
  const token = ++interruptSeq;
1182
1358
  const deliver = () => {
1183
1359
  // A second interrupt while the abort is still settling must not
@@ -1985,6 +2161,19 @@ export function createChannel(ctx, initialAgent, options) {
1985
2161
  state.statusBar = next;
1986
2162
  state.emit();
1987
2163
  },
2164
+ setWhale(visible) {
2165
+ if (visible === state.whale)
2166
+ return;
2167
+ state.whale = visible;
2168
+ state.emit();
2169
+ },
2170
+ setMinimal(enabled) {
2171
+ setMinimalMode(enabled);
2172
+ if (enabled === state.minimal)
2173
+ return;
2174
+ state.minimal = enabled;
2175
+ state.emit();
2176
+ },
1988
2177
  setActivityFrames(name) {
1989
2178
  if (!isPresetName(name)) {
1990
2179
  state.notify(t('unknown-activity-preset', { name }), { color: 'error' });
@@ -2098,13 +2287,15 @@ export function createChannel(ctx, initialAgent, options) {
2098
2287
  // snapshot() over list(): only a COMPLETE observation is authoritative
2099
2288
  // (same contract as the skill-command merge above) — a partial catalog
2100
2289
  // must surface as "failed", not as a misleading near-empty picker.
2101
- const registry = skillRegistryFor(agent);
2290
+ const target = agent;
2291
+ const registry = skillRegistryFor(target);
2102
2292
  if (registry === undefined)
2103
2293
  return [];
2104
2294
  try {
2105
- const observation = await registry.snapshot(skillViewOptions(agent));
2106
- if (!observation.complete)
2295
+ const observation = await registry.snapshot(skillViewOptions(target));
2296
+ if (target !== agent || !observation.complete) {
2107
2297
  return undefined;
2298
+ }
2108
2299
  return observation.skills.map(skill => ({
2109
2300
  name: skill.name,
2110
2301
  description: skill.description,
@@ -2717,6 +2908,10 @@ export function createChannel(ctx, initialAgent, options) {
2717
2908
  const merged = [...LOCAL_COMMANDS];
2718
2909
  if (commandService) {
2719
2910
  for (const descriptor of commandService.list(target)) {
2911
+ // Hidden TUI commands (e.g. /deepseek) stay out of the public
2912
+ // command catalog even if a plugin/skill happens to share the name.
2913
+ if (HIDDEN_COMMAND_NAMES.has(descriptor.name))
2914
+ continue;
2720
2915
  if (merged.some(command => command.name === descriptor.name))
2721
2916
  continue;
2722
2917
  const descriptions = commandTrees?.descriptions(descriptor.name);
@@ -3559,6 +3754,22 @@ ${output}
3559
3754
  // no card is a no-op below.
3560
3755
  if (event.data.name === 'ask_user_question')
3561
3756
  break;
3757
+ // The Task tool's plain card is replaced by the live subagent card
3758
+ // (Kimi Code semantics): the delegation itself renders as a subagent
3759
+ // row, so the raw args/result card would only duplicate it. The call
3760
+ // still runs - only its transcript rendering is suppressed.
3761
+ if (isSubagentToolName(event.data.name)) {
3762
+ try {
3763
+ const args = JSON.parse(event.data.arguments);
3764
+ if (typeof args.description === 'string' && args.description)
3765
+ pendingTaskDescriptions.push(args.description);
3766
+ }
3767
+ catch {
3768
+ // Unparseable args leave the queue untouched; the card falls back
3769
+ // to the provider label.
3770
+ }
3771
+ break;
3772
+ }
3562
3773
  // Reasoning that led to a tool call is done thinking — fold the
3563
3774
  // preview now, before the tool card grows the transcript past it
3564
3775
  // (see foldLiveReasoning).
@@ -3629,6 +3840,7 @@ ${output}
3629
3840
  break;
3630
3841
  }
3631
3842
  case 'turn/start': {
3843
+ cancelInFlight = false;
3632
3844
  state.working = true;
3633
3845
  state.turnStart = Date.now();
3634
3846
  state.responseChars = 0;
@@ -3644,6 +3856,7 @@ ${output}
3644
3856
  break;
3645
3857
  }
3646
3858
  case 'turn/end': {
3859
+ cancelInFlight = false;
3647
3860
  settleStreaming();
3648
3861
  state.working = false;
3649
3862
  state.activeToolCount = 0;
@@ -3910,6 +4123,19 @@ ${output}
3910
4123
  };
3911
4124
  })(),
3912
4125
  ctx.on('session/event', (session, event) => {
4126
+ // First check if this is a subagent session
4127
+ const subagentId = subagentStore.getSubagentIdBySession(session);
4128
+ if (subagentId) {
4129
+ subagentStore.onSessionEvent(subagentId, event);
4130
+ state.subagents = subagentStore.snapshot();
4131
+ syncSubagentRows();
4132
+ if (event.type === 'assistant/chunk')
4133
+ state.emitStream();
4134
+ else
4135
+ state.emit();
4136
+ return;
4137
+ }
4138
+ // Otherwise handle main agent session
3913
4139
  if (session !== agent.session)
3914
4140
  return;
3915
4141
  // Observation broker (C-042): maps user/message + assistant/message
@@ -3940,6 +4166,67 @@ ${output}
3940
4166
  else
3941
4167
  state.emit();
3942
4168
  }),
4169
+ // Subagent lifecycle tracking. The dsh-subagent service publishes scoped
4170
+ // observe-only events as `subagent/start` and `subagent/end`; the parent
4171
+ // Agent is carried by Cordis scope dispatch, not included in the payload.
4172
+ (() => {
4173
+ const disposeStart = ctx.on('subagent/start', (info) => {
4174
+ if (!info?.id)
4175
+ return;
4176
+ subagentStore.onSpawned(info.id, info.provider || 'subagent', info.provider, {
4177
+ runId: info.runId ?? info.id,
4178
+ local: info.local,
4179
+ description: pendingTaskDescriptions.shift() ?? `${info.provider || 'subagent'} task`,
4180
+ });
4181
+ // In-process providers publish a child Agent during this notification.
4182
+ // Resolve through ctx.get('agents') (the property proxy is
4183
+ // topology-sensitive); the child carries its session (live output
4184
+ // stream) and its provider/model route for the card header.
4185
+ try {
4186
+ const agents = ctx.get('agents');
4187
+ const child = agents?.get(info.id);
4188
+ if (child?.session) {
4189
+ subagentStore.linkSession(info.id, child.session);
4190
+ const model = child.options?.model ?? child.options?.provider;
4191
+ if (model)
4192
+ subagentStore.patch(info.id, { model, provider: child.options?.provider ?? info.provider });
4193
+ }
4194
+ }
4195
+ catch {
4196
+ // Session discovery is best-effort and must not break the parent turn.
4197
+ }
4198
+ state.subagents = subagentStore.snapshot();
4199
+ syncSubagentRows();
4200
+ state.emit();
4201
+ });
4202
+ const disposeEnd = ctx.on('subagent/end', (info) => {
4203
+ if (!info?.id)
4204
+ return;
4205
+ const output = Array.isArray(info.lastAssistantMessage)
4206
+ ? info.lastAssistantMessage
4207
+ .map(block => typeof block === 'object' && block !== null && 'text' in block ? String(block.text ?? '') : '')
4208
+ .filter(Boolean)
4209
+ .join('\n')
4210
+ : '';
4211
+ // The final assistant output becomes the card's summary only; the
4212
+ // running waterfall came from the child session stream, so echoing
4213
+ // it into the output buffer would duplicate it on the collapsed card.
4214
+ subagentStore.flushOutput(info.id);
4215
+ if (info.stopReason === 'completed')
4216
+ subagentStore.onCompleted(info.id, output, info.stopReason);
4217
+ else if (info.stopReason === 'cancelled' || info.stopReason === 'aborted')
4218
+ subagentStore.onCancelled(info.id, info.stopReason, output);
4219
+ else
4220
+ subagentStore.onFailed(info.id, info.stopReason || 'Unknown error');
4221
+ state.subagents = subagentStore.snapshot();
4222
+ syncSubagentRows();
4223
+ state.emit();
4224
+ });
4225
+ return () => {
4226
+ disposeStart();
4227
+ disposeEnd();
4228
+ };
4229
+ })(),
3943
4230
  ];
3944
4231
  };
3945
4232
  // Subagents inherit provider/model from AgentOptions, but resumed TUI
@@ -1,20 +1,43 @@
1
- export declare const UPSTREAM_VALIDATED_VERSION = "0.1.0-rc.7";
1
+ /** Primary validated upstream line (newest). */
2
+ export declare const UPSTREAM_VALIDATED_VERSION = "0.1.0-rc.8";
3
+ /** Every upstream rc line the adapter has been validated against.
4
+ *
5
+ * rc.8 = primary; rc.7 = previous line (full CI coverage); rc.6 = legacy
6
+ * line (install- and type-level compatibility, feature surface may lack
7
+ * rc.7/rc.8 additions — new features must degrade gracefully there).
8
+ * The peer range in package.json is deliberately wider than this list: an
9
+ * install on an older line is allowed but reports drift at boot.
10
+ */
11
+ export declare const UPSTREAM_VALIDATED_RC_LINES: readonly [6, 7, 8];
2
12
  /**
3
13
  * Framework packages version on their own lines; the contract validates
4
14
  * their MAJOR (breaking surface), not the harness rc number.
5
15
  */
6
16
  export declare const UPSTREAM_FRAMEWORK_MAJORS: Record<string, number>;
7
17
  /** Official packages the adapter consumes at runtime or as types. */
8
- export declare const UPSTREAM_BLESSED_PACKAGES: readonly ["@deepseek-ai/cordis", "@deepseek-ai/schemastery", "@deepseek-ai/dsh-invariants", "@deepseek-ai/dsh-agent", "@deepseek-ai/dsh-agent-instructions", "@deepseek-ai/dsh-agent-presets", "@deepseek-ai/dsh-atomic-write", "@deepseek-ai/dsh-commands", "@deepseek-ai/dsh-cordis-host-runner", "@deepseek-ai/dsh-llm", "@deepseek-ai/dsh-persona", "@deepseek-ai/dsh-session", "@deepseek-ai/dsh-skill", "@deepseek-ai/dsh-storage", "@deepseek-ai/dsh-storage-domain", "@deepseek-ai/dsh-storage-json", "@deepseek-ai/dsh-workspace", "@deepseek-ai/dsh-system-prompt", "@deepseek-ai/dsh-terminal", "@deepseek-ai/dsh-terminal-bash", "@deepseek-ai/dsh-tool-ask-user", "@deepseek-ai/dsh-tool-bash-persistent", "@deepseek-ai/dsh-tool-cordis", "@deepseek-ai/dsh-user-approval", "@deepseek-ai/dsh-user-questions"];
18
+ export declare const UPSTREAM_BLESSED_PACKAGES: readonly ["@deepseek-ai/cordis", "@deepseek-ai/schemastery", "@deepseek-ai/dsh-invariants", "@deepseek-ai/dsh-agent", "@deepseek-ai/dsh-agent-instructions", "@deepseek-ai/dsh-agent-presets", "@deepseek-ai/dsh-atomic-write", "@deepseek-ai/dsh-commands", "@deepseek-ai/dsh-cordis-host-runner", "@deepseek-ai/dsh-llm", "@deepseek-ai/dsh-persona", "@deepseek-ai/dsh-session", "@deepseek-ai/dsh-settings", "@deepseek-ai/dsh-skill", "@deepseek-ai/dsh-storage", "@deepseek-ai/dsh-storage-domain", "@deepseek-ai/dsh-storage-json", "@deepseek-ai/dsh-workspace", "@deepseek-ai/dsh-system-prompt", "@deepseek-ai/dsh-terminal", "@deepseek-ai/dsh-terminal-bash", "@deepseek-ai/dsh-tool-ask-user", "@deepseek-ai/dsh-tool-bash-persistent", "@deepseek-ai/dsh-tool-cordis", "@deepseek-ai/dsh-user-approval", "@deepseek-ai/dsh-user-questions"];
9
19
  export interface UpstreamDriftEntry {
10
20
  package: string;
11
21
  installed: string | undefined;
12
22
  validated: string;
13
23
  }
24
+ /** Human-readable summary of the validated lines, e.g. `0.1.0-rc.8 (rc.6/rc.7/rc.8)`. */
25
+ export declare const UPSTREAM_VALIDATED_LABEL: string;
14
26
  export declare function installedUpstreamVersions(): Record<string, string | undefined>;
27
+ /** The installed upstream rc line of one blessed package (undefined when
28
+ * missing or not on the 0.1.0-rc line). Feature gates compare this against
29
+ * the line a behavior was introduced on, so the adapter degrades on older
30
+ * installs instead of calling APIs they do not have. */
31
+ export declare function installedLineOf(packageName: string): number | undefined;
32
+ /** The distinct upstream rc lines installed across the blessed harness
33
+ * packages (framework packages excluded). One line = coherent install;
34
+ * several = a mixed tree, which the per-package drift check cannot see.
35
+ * Empty when nothing (or no harness package) is installed. */
36
+ export declare function installedUpstreamLines(): number[];
15
37
  /**
16
- * Report every blessed package whose installed version is NOT the validated
17
- * release line. Empty array = the running install matches the contract.
38
+ * Report every blessed package whose installed version is NOT one of the
39
+ * validated release lines. Empty array = the running install matches the
40
+ * contract.
18
41
  */
19
42
  export declare function upstreamDrift(): UpstreamDriftEntry[];
20
43
  //# sourceMappingURL=contract.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/contract.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,0BAA0B,eAAe,CAAA;AAEtD;;;GAGG;AACH,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAG5D,CAAA;AAED,qEAAqE;AACrE,eAAO,MAAM,yBAAyB,8xBA0B5B,CAAA;AAEV,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,SAAS,EAAE,MAAM,CAAA;CAClB;AAWD,wBAAgB,yBAAyB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAgB9E;AAOD;;;GAGG;AACH,wBAAgB,aAAa,IAAI,kBAAkB,EAAE,CAsBpD"}
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/contract.ts"],"names":[],"mappings":"AAgBA,gDAAgD;AAChD,eAAO,MAAM,0BAA0B,eAAe,CAAA;AAEtD;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,oBAAqB,CAAA;AAE7D;;;GAGG;AACH,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAG5D,CAAA;AAED,qEAAqE;AACrE,eAAO,MAAM,yBAAyB,2zBA2B5B,CAAA;AAEV,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,yFAAyF;AACzF,eAAO,MAAM,wBAAwB,QAAmG,CAAA;AAYxI,wBAAgB,yBAAyB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAqB9E;AAED;;;yDAGyD;AACzD,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEvE;AAOD;;;+DAG+D;AAC/D,wBAAgB,sBAAsB,IAAI,MAAM,EAAE,CAQjD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,kBAAkB,EAAE,CAuBpD"}
@@ -1,9 +1,11 @@
1
1
  /**
2
2
  * Upstream compatibility contract.
3
3
  *
4
- * The TUI is validated against one upstream release line (0.1.0-rc.7).
5
- * Every official package this adapter touches is blessed here; anything
6
- * else must go through upstream channels or the adapter, never the UI.
4
+ * The TUI is validated against a set of upstream release lines — the
5
+ * current primary (0.1.0-rc.8) plus older lines kept in backward
6
+ * compatibility (0.1.0-rc.7, 0.1.0-rc.6). Every official package this
7
+ * adapter touches is blessed here; anything else must go through upstream
8
+ * channels or the adapter, never the UI.
7
9
  *
8
10
  * `upstreamDrift()` powers both the boot-time warning (dev visibility) and
9
11
  * the CI gate (scripts/verify-upstream-contract.ts) so a mismatched
@@ -11,7 +13,17 @@
11
13
  */
12
14
  import { readFileSync } from 'node:fs';
13
15
  import { fileURLToPath } from 'node:url';
14
- export const UPSTREAM_VALIDATED_VERSION = '0.1.0-rc.7';
16
+ /** Primary validated upstream line (newest). */
17
+ export const UPSTREAM_VALIDATED_VERSION = '0.1.0-rc.8';
18
+ /** Every upstream rc line the adapter has been validated against.
19
+ *
20
+ * rc.8 = primary; rc.7 = previous line (full CI coverage); rc.6 = legacy
21
+ * line (install- and type-level compatibility, feature surface may lack
22
+ * rc.7/rc.8 additions — new features must degrade gracefully there).
23
+ * The peer range in package.json is deliberately wider than this list: an
24
+ * install on an older line is allowed but reports drift at boot.
25
+ */
26
+ export const UPSTREAM_VALIDATED_RC_LINES = [6, 7, 8];
15
27
  /**
16
28
  * Framework packages version on their own lines; the contract validates
17
29
  * their MAJOR (breaking surface), not the harness rc number.
@@ -34,6 +46,7 @@ export const UPSTREAM_BLESSED_PACKAGES = [
34
46
  '@deepseek-ai/dsh-llm',
35
47
  '@deepseek-ai/dsh-persona',
36
48
  '@deepseek-ai/dsh-session',
49
+ '@deepseek-ai/dsh-settings',
37
50
  '@deepseek-ai/dsh-skill',
38
51
  '@deepseek-ai/dsh-storage',
39
52
  '@deepseek-ai/dsh-storage-domain',
@@ -48,6 +61,8 @@ export const UPSTREAM_BLESSED_PACKAGES = [
48
61
  '@deepseek-ai/dsh-user-approval',
49
62
  '@deepseek-ai/dsh-user-questions',
50
63
  ];
64
+ /** Human-readable summary of the validated lines, e.g. `0.1.0-rc.8 (rc.6/rc.7/rc.8)`. */
65
+ export const UPSTREAM_VALIDATED_LABEL = `${UPSTREAM_VALIDATED_VERSION} (${UPSTREAM_VALIDATED_RC_LINES.map((n) => `rc.${n}`).join('/')})`;
51
66
  function resolvePackageJson(packageName) {
52
67
  try {
53
68
  const path = import.meta.resolve(`${packageName}/package.json`);
@@ -57,7 +72,13 @@ function resolvePackageJson(packageName) {
57
72
  return undefined;
58
73
  }
59
74
  }
75
+ let cachedVersions;
60
76
  export function installedUpstreamVersions() {
77
+ // Package manifests do not change mid-process; memoize so per-call gates
78
+ // (e.g. the command-images line check) stay cheap. Frozen so callers can
79
+ // never corrupt the shared cache.
80
+ if (cachedVersions !== undefined)
81
+ return cachedVersions;
61
82
  const result = {};
62
83
  for (const packageName of UPSTREAM_BLESSED_PACKAGES) {
63
84
  let version;
@@ -73,15 +94,39 @@ export function installedUpstreamVersions() {
73
94
  }
74
95
  result[packageName] = version;
75
96
  }
76
- return result;
97
+ cachedVersions = Object.freeze(result);
98
+ return cachedVersions;
99
+ }
100
+ /** The installed upstream rc line of one blessed package (undefined when
101
+ * missing or not on the 0.1.0-rc line). Feature gates compare this against
102
+ * the line a behavior was introduced on, so the adapter degrades on older
103
+ * installs instead of calling APIs they do not have. */
104
+ export function installedLineOf(packageName) {
105
+ return rcNumber(installedUpstreamVersions()[packageName]);
77
106
  }
78
107
  function rcNumber(version) {
79
- const match = /0\.1\.0-rc\.(\d+)/u.exec(version ?? '');
108
+ const match = /^0\.1\.0-rc\.(\d+)$/u.exec(version ?? '');
80
109
  return match === null ? undefined : Number(match[1]);
81
110
  }
111
+ /** The distinct upstream rc lines installed across the blessed harness
112
+ * packages (framework packages excluded). One line = coherent install;
113
+ * several = a mixed tree, which the per-package drift check cannot see.
114
+ * Empty when nothing (or no harness package) is installed. */
115
+ export function installedUpstreamLines() {
116
+ const lines = new Set();
117
+ for (const packageName of UPSTREAM_BLESSED_PACKAGES) {
118
+ if (UPSTREAM_FRAMEWORK_MAJORS[packageName] !== undefined)
119
+ continue;
120
+ const line = rcNumber(installedUpstreamVersions()[packageName]);
121
+ if (line !== undefined)
122
+ lines.add(line);
123
+ }
124
+ return [...lines].sort((a, b) => a - b);
125
+ }
82
126
  /**
83
- * Report every blessed package whose installed version is NOT the validated
84
- * release line. Empty array = the running install matches the contract.
127
+ * Report every blessed package whose installed version is NOT one of the
128
+ * validated release lines. Empty array = the running install matches the
129
+ * contract.
85
130
  */
86
131
  export function upstreamDrift() {
87
132
  const drift = [];
@@ -96,13 +141,14 @@ export function upstreamDrift() {
96
141
  matches = installedMajor === frameworkMajor;
97
142
  }
98
143
  else {
99
- matches = rcNumber(installed) === rcNumber(UPSTREAM_VALIDATED_VERSION);
144
+ const installedLine = rcNumber(installed);
145
+ matches = installedLine !== undefined && UPSTREAM_VALIDATED_RC_LINES.includes(installedLine);
100
146
  }
101
147
  if (!matches) {
102
148
  drift.push({
103
149
  package: packageName,
104
150
  installed,
105
- validated: frameworkMajor !== undefined ? `major ${frameworkMajor}` : UPSTREAM_VALIDATED_VERSION,
151
+ validated: frameworkMajor !== undefined ? `major ${frameworkMajor}` : UPSTREAM_VALIDATED_LABEL,
106
152
  });
107
153
  }
108
154
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,MAAM,MAAM,0BAA0B,CAAA;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAsB,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAErG,eAAO,MAAM,IAAI,YAAY,CAAA;AAU7B,eAAO,MAAM,MAAM,UAAa,CAAA;AAEhC;;;GAGG;AACH,MAAM,WAAW,MAAM;IACrB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;yEAKqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;gDAC4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;gFAE4E;IAC5E,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;oCACgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;sBAIkB;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;4BAGwB;IACxB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;wDAEoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;kFAC8E;IAC9E,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;gCAG4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;6DAEyD;IACzD,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAA;IACzC;;8EAE0E;IAC1E,YAAY,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IACjC,sEAAsE;IACtE,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,2EAA2E;IAC3E,SAAS,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAA;IACpC;;;yDAGqD;IACrD,KAAK,CAAC,EAAE,eAAe,EAAE,CAAA;CAC1B;AAED,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,CA8ChC,CAAA;AAEF;;;;;;GAMG;AACH,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAWvE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,MAAM,MAAM,0BAA0B,CAAA;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAsB,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAErG,eAAO,MAAM,IAAI,YAAY,CAAA;AAU7B,eAAO,MAAM,MAAM,UAAa,CAAA;AAEhC;;;GAGG;AACH,MAAM,WAAW,MAAM;IACrB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;yEAKqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;gDAC4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;gFAE4E;IAC5E,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;oCACgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;sBAIkB;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;4BAGwB;IACxB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;wDAEoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;kFAC8E;IAC9E,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;gCAG4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;6DAEyD;IACzD,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAA;IACzC;;8EAE0E;IAC1E,YAAY,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IACjC,sEAAsE;IACtE,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,2EAA2E;IAC3E,SAAS,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAA;IACpC;;;yDAGqD;IACrD,KAAK,CAAC,EAAE,eAAe,EAAE,CAAA;CAC1B;AAED,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,CA8ChC,CAAA;AAEF;;;;;;GAMG;AACH,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBvE"}