@huanlin/dsh-plugin-merge-tool-calls 0.2.2 → 0.4.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.
- package/README.md +97 -94
- package/lib/client.js +2051 -1637
- package/lib/client.js.map +1 -1
- package/lib/types/client/card-model.d.ts +77 -77
- package/lib/types/client/dictionaries.d.ts +22 -15
- package/lib/types/client/index.d.ts +29 -29
- package/lib/types/client/locales.d.ts +103 -57
- package/lib/types/client/merge-run.d.ts +49 -46
- package/lib/types/client/rows.d.ts +77 -73
- package/package.json +15 -22
- package/lib/invariant.js +0 -11
- package/lib/types/invariant.d.ts +0 -12
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pure card/row derivation from a frozen call slice, mirroring ui-tool's
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
export type
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
*/
|
|
23
|
-
type DistributiveOmit<
|
|
24
|
-
/** Search-card props plus the capped-result recovery locator (mirrors ui-tool). */
|
|
25
|
-
export interface SearchCardModel {
|
|
26
|
-
readonly card:
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
readonly
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
/** True when a settled terminal card reports a failing exit (mirrors ui-tool). */
|
|
42
|
-
export declare function terminalFailed(model: TerminalCardModel): boolean;
|
|
43
|
-
/** Everything a merged row needs, derived once from the frozen slice. */
|
|
44
|
-
export interface CallRowModel {
|
|
45
|
-
readonly state: RowState;
|
|
46
|
-
readonly variant: ToolVariant;
|
|
47
|
-
/** Row title: variant title, or the tool-owned title when it refines one. */
|
|
48
|
-
readonly title: string;
|
|
49
|
-
/** Args/result-derived one-line summary (path for file tools, query for searches, …). */
|
|
50
|
-
readonly summary: string;
|
|
51
|
-
/** Expanded-body input text (pretty args); null = no input section. */
|
|
52
|
-
readonly body: string | null;
|
|
53
|
-
/** Flattened result text; null while running or when the result carries no text. */
|
|
54
|
-
readonly output: string | null;
|
|
55
|
-
/** First result line on an error row (the collapsed summary's error text). */
|
|
56
|
-
readonly errorSummary: string | null;
|
|
57
|
-
/** Openable workspace path from args; absent for non-file tools and errors. */
|
|
58
|
-
readonly filePath: string | undefined;
|
|
59
|
-
/** Whether the row has anything to expand (a card, args body, or output). */
|
|
60
|
-
readonly expandable: boolean;
|
|
61
|
-
/** Expanded-body content cards, mutually exclusive, or null when absent. */
|
|
62
|
-
readonly terminal: TerminalCardModel | null;
|
|
63
|
-
readonly diff: DiffCardModel | null;
|
|
64
|
-
readonly read: ReadCardModel | null;
|
|
65
|
-
readonly search: SearchCardModel | null;
|
|
66
|
-
readonly web:
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Flatten a settled result's content blocks to display text.
|
|
70
|
-
* @param node - settled result node.
|
|
71
|
-
* @returns joined text (may be empty).
|
|
72
|
-
*/
|
|
73
|
-
export declare function resultText(node: ToolResultNode): string;
|
|
74
|
-
/** Strip the workspace root from a workspace-rooted absolute path (display only). */
|
|
75
|
-
export declare function relativizeToCwd(text: string, cwd: string | undefined): string;
|
|
76
|
-
/** Derive the row model for one call of a grouped tool. */
|
|
77
|
-
export declare function callRowModel(toolName: string, block: ToolCallBlock, cwd: string | undefined): CallRowModel;
|
|
1
|
+
/**
|
|
2
|
+
* Pure card/row derivation from a frozen call slice, mirroring ui-tool's
|
|
3
|
+
* meta-based card models (read/search/diff/terminal/web) at the plugin
|
|
4
|
+
* boundary (those models are ui-tool internals and cannot be imported
|
|
5
|
+
* cross-package). Same wire contract, same defensive treatment of untrusted
|
|
6
|
+
* result metadata: cards derive from the call arguments plus the persisted
|
|
7
|
+
* result `meta` and single text block. A merged row renders the same surface
|
|
8
|
+
* the built-in row would: a variant title/icon plus a card primitive or IN/OUT
|
|
9
|
+
* text. The localized label props each primitive now requires are supplied by
|
|
10
|
+
* the render site (`rows.tsx`), not here.
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
import type { ToolCallBlock, ToolResultNode } from '@deepseek-ai/dsh-client-ui-chat/client';
|
|
14
|
+
import type { DiffBlockProps, ReadBlockProps, SearchBlockProps, TerminalBlockProps, WebBlockProps } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
15
|
+
import { type ToolVariant } from './tool-names.ts';
|
|
16
|
+
/** Row state semantic, mirroring ui-tool's ToolRowState. */
|
|
17
|
+
export type RowState = 'running' | 'ok' | 'error' | 'stopped';
|
|
18
|
+
export type { ToolVariant } from './tool-names.ts';
|
|
19
|
+
/** Read-card props the ReadBlock primitive draws (per-render maxLines owned by the caller). */
|
|
20
|
+
export type ReadCardModel = Pick<ReadBlockProps, 'label' | 'lines' | 'totalLines' | 'lang'>;
|
|
21
|
+
type DistributiveOmit<T, K extends keyof T> = T extends unknown ? Omit<T, K> : never;
|
|
22
|
+
/** Search-card props (the primitive's own union minus the render site's fields). */
|
|
23
|
+
type SearchCardModelProps = DistributiveOmit<SearchBlockProps, 'labels' | 'maxLines' | 'className'>;
|
|
24
|
+
/** Search-card props plus the capped-result recovery locator (mirrors ui-tool). */
|
|
25
|
+
export interface SearchCardModel {
|
|
26
|
+
readonly card: SearchCardModelProps;
|
|
27
|
+
readonly recovery: string | undefined;
|
|
28
|
+
}
|
|
29
|
+
/** Diff-card props (mirrors ui-tool; maxLines/labels/className belong to the render site). */
|
|
30
|
+
export interface DiffCardModel {
|
|
31
|
+
readonly card: Pick<DiffBlockProps, 'diffs'>;
|
|
32
|
+
}
|
|
33
|
+
/** Terminal-card props (mirrors ui-tool; maxLines/labels/className belong to the render site). */
|
|
34
|
+
export interface TerminalCardModel {
|
|
35
|
+
readonly card: Pick<TerminalBlockProps, 'command' | 'cwd' | 'output' | 'exitCode' | 'signal' | 'running'>;
|
|
36
|
+
/** The call's model-authored description shown above the card. */
|
|
37
|
+
readonly description: string | undefined;
|
|
38
|
+
}
|
|
39
|
+
/** Web-card props (the primitive's own union minus the render site's fields). */
|
|
40
|
+
export type WebCardModel = DistributiveOmit<WebBlockProps, 'labels' | 'className'>;
|
|
41
|
+
/** True when a settled terminal card reports a failing exit (mirrors ui-tool). */
|
|
42
|
+
export declare function terminalFailed(model: TerminalCardModel): boolean;
|
|
43
|
+
/** Everything a merged row needs, derived once from the frozen slice. */
|
|
44
|
+
export interface CallRowModel {
|
|
45
|
+
readonly state: RowState;
|
|
46
|
+
readonly variant: ToolVariant;
|
|
47
|
+
/** Row title: variant title, or the tool-owned title when it refines one. */
|
|
48
|
+
readonly title: string;
|
|
49
|
+
/** Args/result-derived one-line summary (path for file tools, query for searches, …). */
|
|
50
|
+
readonly summary: string;
|
|
51
|
+
/** Expanded-body input text (pretty args); null = no input section. */
|
|
52
|
+
readonly body: string | null;
|
|
53
|
+
/** Flattened result text; null while running or when the result carries no text. */
|
|
54
|
+
readonly output: string | null;
|
|
55
|
+
/** First result line on an error row (the collapsed summary's error text). */
|
|
56
|
+
readonly errorSummary: string | null;
|
|
57
|
+
/** Openable workspace path from args; absent for non-file tools and errors. */
|
|
58
|
+
readonly filePath: string | undefined;
|
|
59
|
+
/** Whether the row has anything to expand (a card, args body, or output). */
|
|
60
|
+
readonly expandable: boolean;
|
|
61
|
+
/** Expanded-body content cards, mutually exclusive, or null when absent. */
|
|
62
|
+
readonly terminal: TerminalCardModel | null;
|
|
63
|
+
readonly diff: DiffCardModel | null;
|
|
64
|
+
readonly read: ReadCardModel | null;
|
|
65
|
+
readonly search: SearchCardModel | null;
|
|
66
|
+
readonly web: WebCardModel | null;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Flatten a settled result's content blocks to display text.
|
|
70
|
+
* @param node - settled result node.
|
|
71
|
+
* @returns joined text (may be empty).
|
|
72
|
+
*/
|
|
73
|
+
export declare function resultText(node: ToolResultNode): string;
|
|
74
|
+
/** Strip the workspace root from a workspace-rooted absolute path (display only). */
|
|
75
|
+
export declare function relativizeToCwd(text: string, cwd: string | undefined): string;
|
|
76
|
+
/** Derive the row model for one call of a grouped tool. */
|
|
77
|
+
export declare function callRowModel(toolName: string, block: ToolCallBlock, cwd: string | undefined, home: string | undefined): CallRowModel;
|
|
@@ -1,15 +1,22 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The 19 better-locale override languages for the merged tool-call row copy,
|
|
3
|
-
* keyed by language id.
|
|
4
|
-
* in
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The 19 better-locale override languages for the merged tool-call row copy,
|
|
3
|
+
* keyed by language id. Values keep `{placeholder}` interpolation (e.g. `{n}`
|
|
4
|
+
* in `mergedCount`), matching the better-locale store's `LocaleDict`
|
|
5
|
+
* contract.
|
|
6
|
+
*
|
|
7
|
+
* Each dictionary is PARTIAL: languages carry the keys they translate, and a
|
|
8
|
+
* missing key falls through the locale lookup chain to the base `en`/`zh`
|
|
9
|
+
* dictionary registered by the plugin. Dictionaries written before the
|
|
10
|
+
* v0.1.2-alpha.1 adaptation predate the read/search/diff/web card-label keys
|
|
11
|
+
* (`read.*` / `search.*` / `diff.*` / `web.*` / `markdown.*` / `copy` /
|
|
12
|
+
* `copied`); those render in English under an override language until a
|
|
13
|
+
* translation lands here.
|
|
14
|
+
*
|
|
15
|
+
* The apply function registers these into `ctx.betterLocale` (the override
|
|
16
|
+
* store) under `NS`, so when the user selects an override language through
|
|
17
|
+
* dsh-plugin-better-locale (and DSH is on 'en', whose slot the override
|
|
18
|
+
* borrows), the row copy renders in the override language.
|
|
19
|
+
*/
|
|
20
|
+
import type { MergeToolCallsKey } from './locales.ts';
|
|
21
|
+
/** All override-language dictionaries for the `NS` namespace. */
|
|
22
|
+
export declare const dicts: Record<string, Partial<Record<MergeToolCallsKey, string>>>;
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* merge-tool-calls — browser half.
|
|
3
|
-
*
|
|
4
|
-
* Shadows the shipped `tool.call.toolview` entries for every grouped tool at
|
|
5
|
-
* priority -1 (the keyed slot's shadowing rule: lowest priority renders). An
|
|
6
|
-
* empty `tools` config means every built-in generic-family tool
|
|
7
|
-
* (see {@link ALL_TOOL_NAMES}); a non-empty list is an explicit whitelist.
|
|
8
|
-
* The shadowed component merges consecutive calls of one tool in the chat flow
|
|
9
|
-
* into a single card with compact child rows.
|
|
10
|
-
*
|
|
11
|
-
* @module @dsh-external/dsh-plugin-merge-tool-calls/client
|
|
12
|
-
*/
|
|
13
|
-
import type { ClientContext } from '@deepseek-ai/
|
|
14
|
-
import { type MergeToolCallsConfig } from '../types.ts';
|
|
15
|
-
import { type MergeToolCallsKey } from './locales.ts';
|
|
16
|
-
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
17
|
-
interface LocaleNamespaceMap {
|
|
18
|
-
/** Copy for the merged tool-call rows. */
|
|
19
|
-
'merge-tool-calls': MergeToolCallsKey;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
/** Required services: the slot registry (toolview shadowing) and locale. */
|
|
23
|
-
export declare const inject: string[];
|
|
24
|
-
/**
|
|
25
|
-
* Register one shadowed toolview per grouped tool.
|
|
26
|
-
* @param ctx - client root context.
|
|
27
|
-
* @param config - row config; defaults apply when the loader passes none.
|
|
28
|
-
*/
|
|
29
|
-
export declare function apply(ctx: ClientContext, config?: Partial<MergeToolCallsConfig>): void;
|
|
1
|
+
/**
|
|
2
|
+
* merge-tool-calls — browser half.
|
|
3
|
+
*
|
|
4
|
+
* Shadows the shipped `tool.call.toolview` entries for every grouped tool at
|
|
5
|
+
* priority -1 (the keyed slot's shadowing rule: lowest priority renders). An
|
|
6
|
+
* empty `tools` config means every built-in generic-family tool
|
|
7
|
+
* (see {@link ALL_TOOL_NAMES}); a non-empty list is an explicit whitelist.
|
|
8
|
+
* The shadowed component merges consecutive calls of one tool in the chat flow
|
|
9
|
+
* into a single card with compact child rows.
|
|
10
|
+
*
|
|
11
|
+
* @module @dsh-external/dsh-plugin-merge-tool-calls/client
|
|
12
|
+
*/
|
|
13
|
+
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
14
|
+
import { type MergeToolCallsConfig } from '../types.ts';
|
|
15
|
+
import { type MergeToolCallsKey } from './locales.ts';
|
|
16
|
+
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
17
|
+
interface LocaleNamespaceMap {
|
|
18
|
+
/** Copy for the merged tool-call rows. */
|
|
19
|
+
'merge-tool-calls': MergeToolCallsKey;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** Required services: the slot registry (toolview shadowing) and locale. */
|
|
23
|
+
export declare const inject: string[];
|
|
24
|
+
/**
|
|
25
|
+
* Register one shadowed toolview per grouped tool.
|
|
26
|
+
* @param ctx - client root context.
|
|
27
|
+
* @param config - row config; defaults apply when the loader passes none.
|
|
28
|
+
*/
|
|
29
|
+
export declare function apply(ctx: ClientContext, config?: Partial<MergeToolCallsConfig>): void;
|
|
@@ -1,57 +1,103 @@
|
|
|
1
|
-
/** Product copy for the merged tool-call rows. */
|
|
2
|
-
export declare const zh: {
|
|
3
|
-
running: string;
|
|
4
|
-
failed: string;
|
|
5
|
-
stopped: string;
|
|
6
|
-
expand: string;
|
|
7
|
-
collapse: string;
|
|
8
|
-
more: string;
|
|
9
|
-
showLess: string;
|
|
10
|
-
mergedCount: string;
|
|
11
|
-
countFiles: string;
|
|
12
|
-
countQueries: string;
|
|
13
|
-
countCommands: string;
|
|
14
|
-
countPrograms: string;
|
|
15
|
-
countCalls: string;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
'terminal.
|
|
19
|
-
'terminal.
|
|
20
|
-
'terminal.
|
|
21
|
-
'terminal.
|
|
22
|
-
'terminal.
|
|
23
|
-
'terminal.
|
|
24
|
-
'terminal.
|
|
25
|
-
'terminal.
|
|
26
|
-
'terminal.
|
|
27
|
-
'terminal.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
'
|
|
45
|
-
'
|
|
46
|
-
'
|
|
47
|
-
'
|
|
48
|
-
'
|
|
49
|
-
'
|
|
50
|
-
'
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
1
|
+
/** Product copy for the merged tool-call rows. */
|
|
2
|
+
export declare const zh: {
|
|
3
|
+
running: string;
|
|
4
|
+
failed: string;
|
|
5
|
+
stopped: string;
|
|
6
|
+
expand: string;
|
|
7
|
+
collapse: string;
|
|
8
|
+
more: string;
|
|
9
|
+
showLess: string;
|
|
10
|
+
mergedCount: string;
|
|
11
|
+
countFiles: string;
|
|
12
|
+
countQueries: string;
|
|
13
|
+
countCommands: string;
|
|
14
|
+
countPrograms: string;
|
|
15
|
+
countCalls: string;
|
|
16
|
+
copy: string;
|
|
17
|
+
copied: string;
|
|
18
|
+
'terminal.signal': string;
|
|
19
|
+
'terminal.exitCode': string;
|
|
20
|
+
'terminal.running': string;
|
|
21
|
+
'terminal.failed': string;
|
|
22
|
+
'terminal.done': string;
|
|
23
|
+
'terminal.copy': string;
|
|
24
|
+
'terminal.copied': string;
|
|
25
|
+
'terminal.noOutput': string;
|
|
26
|
+
'terminal.collapseAria': string;
|
|
27
|
+
'terminal.collapse': string;
|
|
28
|
+
'terminal.expandAria': string;
|
|
29
|
+
'terminal.expandRest': string;
|
|
30
|
+
'read.window': string;
|
|
31
|
+
'read.collapseAria': string;
|
|
32
|
+
'read.expandAria': string;
|
|
33
|
+
'read.expandRest': string;
|
|
34
|
+
'search.paths': string;
|
|
35
|
+
'search.paths.truncated': string;
|
|
36
|
+
'search.matches': string;
|
|
37
|
+
'search.matches.truncated': string;
|
|
38
|
+
'search.noResults': string;
|
|
39
|
+
'search.collapseAria': string;
|
|
40
|
+
'search.expandAria': string;
|
|
41
|
+
'search.expandRest': string;
|
|
42
|
+
'diff.collapseAria': string;
|
|
43
|
+
'diff.expandAria': string;
|
|
44
|
+
'diff.expandRest': string;
|
|
45
|
+
'diff.files': string;
|
|
46
|
+
'web.noResults': string;
|
|
47
|
+
'web.sourcesTruncated': string;
|
|
48
|
+
'web.http': string;
|
|
49
|
+
'web.contentTruncated': string;
|
|
50
|
+
'markdown.footnotes': string;
|
|
51
|
+
};
|
|
52
|
+
export type MergeToolCallsKey = keyof typeof zh;
|
|
53
|
+
export declare const en: {
|
|
54
|
+
running: string;
|
|
55
|
+
failed: string;
|
|
56
|
+
stopped: string;
|
|
57
|
+
expand: string;
|
|
58
|
+
collapse: string;
|
|
59
|
+
more: string;
|
|
60
|
+
showLess: string;
|
|
61
|
+
mergedCount: string;
|
|
62
|
+
countFiles: string;
|
|
63
|
+
countQueries: string;
|
|
64
|
+
countCommands: string;
|
|
65
|
+
countPrograms: string;
|
|
66
|
+
countCalls: string;
|
|
67
|
+
copy: string;
|
|
68
|
+
copied: string;
|
|
69
|
+
'terminal.signal': string;
|
|
70
|
+
'terminal.exitCode': string;
|
|
71
|
+
'terminal.running': string;
|
|
72
|
+
'terminal.failed': string;
|
|
73
|
+
'terminal.done': string;
|
|
74
|
+
'terminal.copy': string;
|
|
75
|
+
'terminal.copied': string;
|
|
76
|
+
'terminal.noOutput': string;
|
|
77
|
+
'terminal.collapseAria': string;
|
|
78
|
+
'terminal.collapse': string;
|
|
79
|
+
'terminal.expandAria': string;
|
|
80
|
+
'terminal.expandRest': string;
|
|
81
|
+
'read.window': string;
|
|
82
|
+
'read.collapseAria': string;
|
|
83
|
+
'read.expandAria': string;
|
|
84
|
+
'read.expandRest': string;
|
|
85
|
+
'search.paths': string;
|
|
86
|
+
'search.paths.truncated': string;
|
|
87
|
+
'search.matches': string;
|
|
88
|
+
'search.matches.truncated': string;
|
|
89
|
+
'search.noResults': string;
|
|
90
|
+
'search.collapseAria': string;
|
|
91
|
+
'search.expandAria': string;
|
|
92
|
+
'search.expandRest': string;
|
|
93
|
+
'diff.collapseAria': string;
|
|
94
|
+
'diff.expandAria': string;
|
|
95
|
+
'diff.expandRest': string;
|
|
96
|
+
'diff.files': string;
|
|
97
|
+
'web.noResults': string;
|
|
98
|
+
'web.sourcesTruncated': string;
|
|
99
|
+
'web.http': string;
|
|
100
|
+
'web.contentTruncated': string;
|
|
101
|
+
'markdown.footnotes': string;
|
|
102
|
+
};
|
|
103
|
+
export declare const NS = "merge-tool-calls";
|
|
@@ -1,46 +1,49 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pure detection of a consecutive run of grouped tool calls in the chat flow,
|
|
3
|
-
* and the per-seat merged-group partition over it.
|
|
4
|
-
*
|
|
5
|
-
* A pure function of the chat snapshot (order + node store), so the merged
|
|
6
|
-
* display is deterministic under replay: the web layer recomputes it per frame.
|
|
7
|
-
* @module
|
|
8
|
-
*/
|
|
9
|
-
import type { ChatNodeStore, ToolCallBlock } from '@deepseek-ai/dsh-client-
|
|
10
|
-
import type { MergeGroupMode } from '../types.ts';
|
|
11
|
-
/** The wire tool name of a call in either lifecycle form (mirrors ui-tool). */
|
|
12
|
-
export declare function callNameOf(block: ToolCallBlock): string;
|
|
13
|
-
/** Whether the call's wire name is one of the grouped tools (empty = all). */
|
|
14
|
-
export declare function isGroupedTool(name: string, tools: readonly string[]): boolean;
|
|
15
|
-
/** One merged group: the group's first call plus its consecutive continuations. */
|
|
16
|
-
export interface ReadRun {
|
|
17
|
-
/** Whether this seat is the group's rendering head (the only seat that shows the card). */
|
|
18
|
-
readonly isFirst: boolean;
|
|
19
|
-
/** The group's root blocks in flow order (first + continuations). */
|
|
20
|
-
readonly blocks: readonly ToolCallBlock[];
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Compute the merged group this call belongs to.
|
|
24
|
-
*
|
|
25
|
-
* 1. Locates this call's node in the chat order; null when it is not a chat
|
|
26
|
-
* tool-call node (e.g. a read dispatched as a subcall).
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* @param
|
|
42
|
-
* @param
|
|
43
|
-
* @param
|
|
44
|
-
* @
|
|
45
|
-
|
|
46
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Pure detection of a consecutive run of grouped tool calls in the chat flow,
|
|
3
|
+
* and the per-seat merged-group partition over it.
|
|
4
|
+
*
|
|
5
|
+
* A pure function of the chat snapshot (order + node store), so the merged
|
|
6
|
+
* display is deterministic under replay: the web layer recomputes it per frame.
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import type { ChatNodeStore, ToolCallBlock } from '@deepseek-ai/dsh-client-ui-chat/client';
|
|
10
|
+
import type { MergeGroupMode } from '../types.ts';
|
|
11
|
+
/** The wire tool name of a call in either lifecycle form (mirrors ui-tool). */
|
|
12
|
+
export declare function callNameOf(block: ToolCallBlock): string;
|
|
13
|
+
/** Whether the call's wire name is one of the grouped tools (empty = all). */
|
|
14
|
+
export declare function isGroupedTool(name: string, tools: readonly string[]): boolean;
|
|
15
|
+
/** One merged group: the group's first call plus its consecutive continuations. */
|
|
16
|
+
export interface ReadRun {
|
|
17
|
+
/** Whether this seat is the group's rendering head (the only seat that shows the card). */
|
|
18
|
+
readonly isFirst: boolean;
|
|
19
|
+
/** The group's root blocks in flow order (first + continuations). */
|
|
20
|
+
readonly blocks: readonly ToolCallBlock[];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Compute the merged group this call belongs to.
|
|
24
|
+
*
|
|
25
|
+
* 1. Locates this call's node in the chat order; null when it is not a chat
|
|
26
|
+
* tool-call node (e.g. a read dispatched as a subcall). The node key
|
|
27
|
+
* format stays a ui-conversation internal, so the seat finds itself by
|
|
28
|
+
* scanning the store for the tool-call node owning its call id instead of
|
|
29
|
+
* recomputing the key.
|
|
30
|
+
* 2. Walks backward/forward to the maximal consecutive run containing it. A
|
|
31
|
+
* call continues the run when it is a grouped tool AND same-tool-same-run:
|
|
32
|
+
* the identical wire name, or a sibling of the same known variant family
|
|
33
|
+
* (grep+glob, bash+pwsh, read+web_fetch…). Unknown names (variant
|
|
34
|
+
* `others`) only merge with themselves, so unrelated tools never share a
|
|
35
|
+
* card (`adjacent`: any consecutive run; `step`: same agent step as this
|
|
36
|
+
* call).
|
|
37
|
+
* 3. Partitions the run into `maxGroupSize`-sized groups; this call is the
|
|
38
|
+
* group's first only when it heads one of those partitions. Truncation
|
|
39
|
+
* therefore never orphans a call: the excess starts its own group.
|
|
40
|
+
*
|
|
41
|
+
* @param order - chat node key order.
|
|
42
|
+
* @param nodes - chat node store.
|
|
43
|
+
* @param myCallId - the call id of the seat asking about itself.
|
|
44
|
+
* @param tools - grouped wire tool names; empty means every tool.
|
|
45
|
+
* @param groupBy - grouping mode.
|
|
46
|
+
* @param maxGroupSize - per-group cap.
|
|
47
|
+
* @returns the group partition, or null when the call is not a chat tool-call node.
|
|
48
|
+
*/
|
|
49
|
+
export declare function readRun(order: readonly string[], nodes: ChatNodeStore, myCallId: string, tools: readonly string[], groupBy: MergeGroupMode, maxGroupSize: number): ReadRun | null;
|