@agi-fans/dsh-tui 0.26.0 → 0.27.0

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.
@@ -169,7 +169,7 @@ async function run(ctx, tui, cancelled) {
169
169
  await Promise.race([agent.whenIdle(), stopped.promise]);
170
170
  if (cancelled.aborted)
171
171
  break;
172
- const joined = await Promise.race([ctx.get('subagents')?.waitForChildren(agent), stopped.promise]);
172
+ const joined = await Promise.race([ctx.get('subagents')?.waitForTreeWork(agent), stopped.promise]);
173
173
  if (!joined)
174
174
  break;
175
175
  }
@@ -8,6 +8,7 @@ export interface AgentActivityStatus {
8
8
  export type TerminalProgramState = AgentActivityState | 'done' | 'error';
9
9
  export interface TerminalProgramStatus {
10
10
  readonly state: TerminalProgramState;
11
+ readonly title?: string;
11
12
  readonly message?: string;
12
13
  readonly kind?: TerminalAttentionKind;
13
14
  }
@@ -24,13 +25,15 @@ export declare function terminalProgressSequence(state: TerminalProgramState | '
24
25
  /** These lifecycle reports can themselves create a terminal notification. */
25
26
  export declare function programStatusNeedsAttention(state: TerminalProgramState): boolean;
26
27
  export declare function settledProgramState(reason?: string): 'idle' | 'done' | 'error';
27
- export declare function terminalTitle(mode: TerminalTitleMode, status: TerminalProgramStatus, session: string | undefined, cwd: string, branch?: string): string;
28
+ export declare function terminalTitle(mode: TerminalTitleMode, status: TerminalProgramStatus, session: string | undefined, cwd: string, branch?: string, nativeStatus?: boolean): string;
28
29
  export declare class AgentActivityController {
29
30
  #private;
30
31
  get current(): AgentActivityStatus;
31
32
  get program(): TerminalProgramStatus;
32
33
  start(): AgentActivityStatus;
33
34
  setRunning(running: boolean): AgentActivityStatus | undefined;
35
+ compactionStart(id?: string): AgentActivityStatus | undefined;
36
+ compactionEnd(id?: string, error?: string): AgentActivityStatus | undefined;
34
37
  settled(reason: string): void;
35
38
  resetResult(): void;
36
39
  prompt(message?: string, kind?: TerminalAttentionKind): AgentActivityStatus | undefined;
@@ -15,9 +15,10 @@ function clean(value, limit) {
15
15
  export function programStatusSequence(status) {
16
16
  if (status === 'clear')
17
17
  return '\x1b]7501;state=clear:app=omdsh\x1b\\';
18
+ const title = clean(status.title, 240);
18
19
  const message = clean(status.message, 240);
19
20
  const kind = status.state === 'blocked' && status.kind !== undefined ? `:kind=${status.kind}` : '';
20
- return `\x1b]7501;state=${status.state}:app=omdsh${kind}${message === undefined ? '' : `:msg=${Buffer.from(message).toString('base64')}`}\x1b\\`;
21
+ return `\x1b]7501;state=${status.state}:app=omdsh${kind}${title === undefined ? '' : `:title=${Buffer.from(title).toString('base64')}`}${message === undefined ? '' : `:msg=${Buffer.from(message).toString('base64')}`}\x1b\\`;
21
22
  }
22
23
  export function workingDirectorySequence(cwd) {
23
24
  // A directory separator also preserves trailing control bytes in Node's URL conversion.
@@ -45,22 +46,28 @@ export function settledProgramState(reason = 'completed') {
45
46
  return 'error';
46
47
  }
47
48
  const STATE_LABELS = { idle: 'Ready', working: 'Working', blocked: 'Needs input', done: 'Done', error: 'Failed' };
48
- export function terminalTitle(mode, status, session, cwd, branch) {
49
+ export function terminalTitle(mode, status, session, cwd, branch, nativeStatus = false) {
49
50
  if (mode === 'off')
50
51
  return '';
51
- if (mode === 'session')
52
+ if (mode === 'session' || (mode === 'status' && nativeStatus))
52
53
  return clean(session, 120) ?? '';
53
- const subject = mode === 'workspace' ? [basename(cwd), branch].filter(Boolean).join(' · ') : session ?? basename(cwd);
54
+ const workspace = [basename(cwd), branch].filter(Boolean).join(' · ');
55
+ if (nativeStatus)
56
+ return clean(workspace, 120) ?? '';
57
+ const subject = mode === 'workspace' ? workspace : session ?? basename(cwd);
54
58
  return clean([STATE_LABELS[status.state], subject, 'omdsh'].filter(Boolean).join(' · '), 120) ?? '';
55
59
  }
56
60
  export class AgentActivityController {
57
61
  #running = false;
62
+ #compacting;
58
63
  #prompts = [];
59
64
  #last;
60
65
  #result = 'idle';
61
66
  get current() {
62
67
  const prompt = this.#prompts.at(-1);
63
- return prompt === undefined ? { state: this.#running ? 'working' : 'idle' } : { state: 'blocked', ...prompt };
68
+ return prompt === undefined
69
+ ? { state: this.#running || this.#compacting !== undefined ? 'working' : 'idle' }
70
+ : { state: 'blocked', ...prompt };
64
71
  }
65
72
  get program() {
66
73
  const current = this.current;
@@ -68,13 +75,27 @@ export class AgentActivityController {
68
75
  }
69
76
  start() { return this.#publish(true); }
70
77
  setRunning(running) {
71
- if (running && !this.#running)
78
+ if (running && !this.#running && this.#compacting === undefined)
72
79
  this.#result = 'idle';
73
80
  this.#running = running;
74
81
  return this.#publish();
75
82
  }
83
+ compactionStart(id = '') {
84
+ if (!this.#running && this.#compacting === undefined)
85
+ this.#result = 'idle';
86
+ this.#compacting = id;
87
+ return this.#publish();
88
+ }
89
+ compactionEnd(id, error) {
90
+ if (this.#compacting === undefined || (id !== undefined && this.#compacting !== id))
91
+ return undefined;
92
+ this.#compacting = undefined;
93
+ if (!this.#running)
94
+ this.#result = error === undefined ? 'done' : 'error';
95
+ return this.#publish();
96
+ }
76
97
  settled(reason) { this.#result = settledProgramState(reason); }
77
- resetResult() { this.#result = 'idle'; }
98
+ resetResult() { this.#result = 'idle'; this.#compacting = undefined; }
78
99
  prompt(message, kind = 'question') {
79
100
  const text = clean(message, 240);
80
101
  this.#prompts.push({ kind, ...(text === undefined ? {} : { message: text }) });
@@ -1 +1 @@
1
- {"version":3,"file":"terminal-state.js","sourceRoot":"","sources":["../../src/runtime/terminal-state.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"terminal-state.js","sourceRoot":"","sources":["../../src/runtime/terminal-state.ts"],"names":[],"mappings":"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"}
@@ -20,7 +20,6 @@ import { isModelInvocable, isUserInvocable } from '@deepseek-ai/dsh-skill';
20
20
  import { BUILTIN_SLASH_COMMANDS } from "../views/autocomplete.js";
21
21
  import { readColdSessionLog } from '@deepseek-ai/dsh-session-query';
22
22
  import { appendPluginRecord, pluginRecordOf, SessionId, SessionLogOffset } from '@deepseek-ai/dsh-session';
23
- import { queueHostSubagentPrompt, steerHostSubagentPrompt } from '@deepseek-ai/dsh-subagent/internal';
24
23
  import { firstVisibleStreamTime } from "../views/stream-time.js";
25
24
  import { LiveAttemptTracker } from "./live-attempt-tracker.js";
26
25
  import { blocksText } from "./content-text.js";
@@ -364,6 +363,47 @@ export async function createSubmissionMessage(submission, attachments) {
364
363
  throw new Error('Cannot submit an empty message.');
365
364
  return createUserMessage({ content, source: { kind: 'user' } });
366
365
  }
366
+ /**
367
+ * Build the host prompt parts for a subagent continuation. Unlike an ordinary
368
+ * Session prompt, the subagent Host admits browser images itself, so the draft
369
+ * crosses the seam as encoded bytes and files are refused here.
370
+ */
371
+ function submissionPromptContent(submission) {
372
+ const imagePart = (image) => ({
373
+ type: 'image',
374
+ mediaType: image.mediaType,
375
+ data: Buffer.from(image.data).toString('base64'),
376
+ ...(image.name === undefined ? {} : { name: image.name }),
377
+ });
378
+ const rejectFiles = () => {
379
+ throw new Error('Subagent follow-up does not accept files.');
380
+ };
381
+ const parts = [];
382
+ if (submission.segments === undefined || submission.segments.length === 0) {
383
+ if (submission.text !== '')
384
+ parts.push({ type: 'text', text: submission.text });
385
+ for (const image of submission.images)
386
+ parts.push(imagePart(image));
387
+ if ((submission.files?.length ?? 0) > 0)
388
+ rejectFiles();
389
+ return parts;
390
+ }
391
+ for (const segment of submission.segments) {
392
+ if (segment.kind === 'text') {
393
+ if (segment.text !== '')
394
+ parts.push({ type: 'text', text: segment.text });
395
+ }
396
+ else if (segment.kind === 'image') {
397
+ const image = submission.images[segment.index];
398
+ if (image !== undefined)
399
+ parts.push(imagePart(image));
400
+ }
401
+ else {
402
+ rejectFiles();
403
+ }
404
+ }
405
+ return parts;
406
+ }
367
407
  /** Rehydrate one durable human inbox message into an editable composer draft. */
368
408
  export async function restoreSubmissionMessage(message, attachments) {
369
409
  const text = blocksText(message.content);
@@ -468,7 +508,14 @@ export class SessionRuntime {
468
508
  },
469
509
  agentStatus: id => this.#ctx.get('agents')?.get(SessionId(id))?.status,
470
510
  sessions: () => this.#ctx.get('sessions')?.list() ?? [],
471
- listChildren: rootId => this.#ctx.get('subagents')?.listChildren(SessionId(rootId)),
511
+ listChildren: rootId => this.#ctx.get('subagents')?.listDescendants(SessionId(rootId))
512
+ .then(entries => entries
513
+ .filter((entry) => entry.kind === 'child' && entry.depth === 1)
514
+ .map((entry) => ({
515
+ id: entry.id,
516
+ mode: entry.mode,
517
+ ...(entry.label === undefined ? {} : { label: entry.label }),
518
+ }))),
472
519
  publish: (roster) => {
473
520
  this.#tui.setSubagents(this.#workflows.roster(roster));
474
521
  if (this.#inspectedId === undefined)
@@ -584,6 +631,22 @@ export class SessionRuntime {
584
631
  if (session === active.handle.agent.session) {
585
632
  if (event.type === 'turn/end')
586
633
  tui.setStatus(active.handle.agent.status, { root: true, outcome: event.data.reason.kind });
634
+ else if (this.#inspectedId !== undefined && event.type === 'compaction/start') {
635
+ tui.setStatus(active.handle.agent.status, {
636
+ root: true,
637
+ compaction: { phase: 'start', id: event.data.compactionId },
638
+ });
639
+ }
640
+ else if (this.#inspectedId !== undefined && event.type === 'compaction/end') {
641
+ tui.setStatus(active.handle.agent.status, {
642
+ root: true,
643
+ compaction: {
644
+ phase: 'end',
645
+ id: event.data.compactionId,
646
+ ...(event.data.error === undefined ? {} : { error: event.data.error }),
647
+ },
648
+ });
649
+ }
587
650
  if (this.#workflows.apply(event))
588
651
  tui.setSubagents(this.#workflows.roster(this.#tracker.snapshot()));
589
652
  if (this.#inspectedId === undefined) {
@@ -679,20 +742,19 @@ export class SessionRuntime {
679
742
  return true;
680
743
  }
681
744
  #isOwnedDescendant(agent, root) {
745
+ if (agent === root)
746
+ return false;
682
747
  const agents = this.#ctx.get('agents');
683
- if (agents?.get(agent.id) !== agent
684
- || descendantDepth(agent.session, root.id, this.#lookupSession) === undefined)
748
+ if (agents?.get(agent.id) !== agent || agents.get(root.id) !== root)
749
+ return false;
750
+ try {
751
+ // Runtime tree membership replaced registry ownership; durable lineage
752
+ // alone still matches an independently resumed runtime root.
753
+ return this.#ctx.get('subagents')?.rootOf(agent) === root;
754
+ }
755
+ catch {
685
756
  return false;
686
- // Durable lineage alone also matches an independently resumed runtime root.
687
- let child = agent;
688
- while (child !== root) {
689
- const parentId = child.session.header.parentSession;
690
- const parent = parentId === undefined ? undefined : agents.get(parentId);
691
- if (parent === undefined || !agents.isOwnedBy(child.id, parent))
692
- return false;
693
- child = parent;
694
757
  }
695
- return true;
696
758
  }
697
759
  /** Accept only live descendants of the active root for shared approval prompts. */
698
760
  beginSubagentApproval(agent) {
@@ -1972,18 +2034,10 @@ export class SessionRuntime {
1972
2034
  this.#tui.notice('This subagent is a completed run and cannot take more messages.');
1973
2035
  return;
1974
2036
  }
1975
- const live = this.#ctx.get('sessions')?.get(SessionId(childId));
1976
- const rosterParent = this.#tracker.snapshot()?.agents.find(agent => agent.id === childId)?.parentId;
1977
- const parentId = live?.header.parentSession ?? rosterParent;
1978
- const parent = parentId === undefined || parentId === root.id
1979
- ? root
1980
- : this.#ctx.get('agents')?.get(SessionId(parentId));
1981
2037
  const subagents = this.#ctx.get('subagents');
1982
- if (parent === undefined || subagents === undefined) {
2038
+ if (subagents === undefined) {
1983
2039
  this.#tui.restoreInput(submission, childId);
1984
- this.#tui.notice(parent === undefined
1985
- ? 'The parent of this subagent is not live, so it cannot take a follow-up.'
1986
- : 'Subagent follow-up is unavailable in this composition.');
2040
+ this.#tui.notice('Subagent follow-up is unavailable in this composition.');
1987
2041
  return;
1988
2042
  }
1989
2043
  const previous = this.#inspectDeliveryTail;
@@ -1991,24 +2045,24 @@ export class SessionRuntime {
1991
2045
  this.#inspectDeliveryTail = new Promise(resolve => { release = resolve; });
1992
2046
  const delivery = new AbortController();
1993
2047
  this.#inspectDeliveries.add(delivery);
1994
- let cancelUpload = () => { };
2048
+ let cancelWait = () => { };
1995
2049
  const cancelled = new Promise((_resolve, reject) => {
1996
- cancelUpload = () => { reject(delivery.signal.reason); };
1997
- delivery.signal.addEventListener('abort', cancelUpload, { once: true });
2050
+ cancelWait = () => { reject(delivery.signal.reason); };
2051
+ delivery.signal.addEventListener('abort', cancelWait, { once: true });
1998
2052
  });
1999
2053
  try {
2000
2054
  // Recalled messages can include attachments; admission must retain submission order.
2001
2055
  await Promise.race([previous, cancelled]);
2002
2056
  delivery.signal.throwIfAborted();
2003
- // Attachment storage need not support cancellation; release the draft now
2004
- // and ignore a later upload result before crossing Harness admission.
2005
- const message = await Promise.race([createSubmissionMessage(submission, this.#ctx.get('attachments')), cancelled]);
2006
- delivery.signal.removeEventListener('abort', cancelUpload);
2007
- delivery.signal.throwIfAborted();
2008
2057
  if (this.#inspectedId !== childId || this.#active?.handle.agent !== root)
2009
2058
  throw new Error('The viewed session changed before delivery.');
2010
- const send = submission.delivery === 'steer' ? steerHostSubagentPrompt : queueHostSubagentPrompt;
2011
- const messageId = await send(subagents, parent, SessionId(childId), message.content, { kind: 'user' }, delivery.signal);
2059
+ const content = submissionPromptContent(submission);
2060
+ const messageId = (await subagents.prompt({
2061
+ requestId: randomUUID(),
2062
+ childSessionId: SessionId(childId),
2063
+ delivery: submission.delivery === 'steer' ? 'steer' : 'queue',
2064
+ content,
2065
+ }, delivery.signal)).messageId;
2012
2066
  this.#tui.pendingInputs?.prepare?.(submission, messageId);
2013
2067
  this.#tui.pendingInputs?.acknowledge?.(submission);
2014
2068
  }
@@ -2018,7 +2072,7 @@ export class SessionRuntime {
2018
2072
  this.#tui.notice(error instanceof Error ? error.message : String(error), { level: 'error' });
2019
2073
  }
2020
2074
  finally {
2021
- delivery.signal.removeEventListener('abort', cancelUpload);
2075
+ delivery.signal.removeEventListener('abort', cancelWait);
2022
2076
  this.#inspectDeliveries.delete(delivery);
2023
2077
  release();
2024
2078
  }