@huanlin/dsh-plugin-merge-tool-calls 0.4.1 → 0.4.2

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/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- //#region node_modules/.pnpm/@deepseek-ai+cosmokit@1.8.2/node_modules/@deepseek-ai/cosmokit/lib/index.js
1
+ //#region node_modules/.pnpm/@deepseek-ai+cosmokit@1.8.5/node_modules/@deepseek-ai/cosmokit/lib/index.js
2
2
  /** Return true when a value is `null` or `undefined`. */
3
3
  function isNullable(value) {
4
4
  return value === null || value === void 0;
@@ -22,6 +22,43 @@ function pick(source, keys, forced) {
22
22
  for (const key of keys) if (forced || source[key] !== void 0) result[key] = source[key];
23
23
  return result;
24
24
  }
25
+ /** Shared config references used by schema validators and plugin runtimes. */
26
+ const write = Symbol.for("cosmokit.volatile.write");
27
+ function snapshot(value, ancestors = /* @__PURE__ */ new Set()) {
28
+ if (typeof value === "function") throw new TypeError("volatile config cannot contain functions");
29
+ if (value === null || typeof value !== "object") return value;
30
+ if (ancestors.has(value)) throw new TypeError("volatile config cannot contain cycles");
31
+ ancestors.add(value);
32
+ try {
33
+ if (Array.isArray(value)) return Object.freeze(value.map((item) => snapshot(item, ancestors)));
34
+ if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) throw new TypeError("volatile config objects must be plain objects or arrays");
35
+ return Object.freeze(Object.fromEntries(Object.entries(value).map(([key, item]) => [key, snapshot(item, ancestors)])));
36
+ } finally {
37
+ ancestors.delete(value);
38
+ }
39
+ }
40
+ /**
41
+ * Create a detached reference containing an immutable copy of the supplied data.
42
+ * @param value - validated config data; class instances and functions are unsupported.
43
+ * @returns a reference whose value is updated only by its owning runtime.
44
+ */
45
+ function createVolatile(value) {
46
+ let current = snapshot(value);
47
+ return Object.freeze({
48
+ get: () => current,
49
+ [write]: (value$1) => {
50
+ current = value$1;
51
+ }
52
+ });
53
+ }
54
+ /**
55
+ * Identify references across ESM/CJS copies of the shared library.
56
+ * @param value - a parsed config value.
57
+ * @returns whether the value implements the shared reference protocol.
58
+ */
59
+ function isVolatile(value) {
60
+ return typeof value === "object" && value !== null && write in value;
61
+ }
25
62
  /** Test values using `instanceof` with a `toStringTag` fallback. */
26
63
  function is(type, value) {
27
64
  if (arguments.length === 1) return (value$1) => is(type, value$1);
@@ -106,26 +143,47 @@ function clone(source, refs = /* @__PURE__ */ new Map()) {
106
143
  }
107
144
  return result;
108
145
  }
109
- /** Deeply compare arrays, dates, regexps, buffers, and plain object fields. */
146
+ /**
147
+ * Compare values recursively, treating two volatile references as equal regardless of value.
148
+ * Strict comparison distinguishes null/undefined, treats opaque objects by identity,
149
+ * compares URLs by normalized href, treats array holes as undefined, and considers distinct cyclic structures unequal.
150
+ * @param a - first value.
151
+ * @param b - second value.
152
+ * @param strict - whether to require strict data equality outside volatile references.
153
+ * @returns whether the values compare equal.
154
+ */
110
155
  function deepEqual(a, b, strict) {
111
- if (a === b) return true;
112
- if (!strict && isNullable(a) && isNullable(b)) return true;
113
- if (typeof a !== typeof b) return false;
114
- if (typeof a !== "object") return false;
115
- if (!a || !b) return false;
116
- function check(test, then) {
117
- return test(a) ? test(b) ? then(a, b) : false : test(b) ? false : void 0;
118
- }
119
- return check(Array.isArray, (a$1, b$1) => a$1.length === b$1.length && a$1.every((item, index) => deepEqual(item, b$1[index]))) ?? check(is("Date"), (a$1, b$1) => a$1.valueOf() === b$1.valueOf()) ?? check(is("RegExp"), (a$1, b$1) => a$1.source === b$1.source && a$1.flags === b$1.flags) ?? check(isArrayBufferLike, (a$1, b$1) => {
120
- if (a$1.byteLength !== b$1.byteLength) return false;
121
- const viewA = new Uint8Array(a$1);
122
- const viewB = new Uint8Array(b$1);
123
- for (let i = 0; i < viewA.length; i++) if (viewA[i] !== viewB[i]) return false;
124
- return true;
125
- }) ?? Object.keys({
126
- ...a,
127
- ...b
128
- }).every((key) => deepEqual(a[key], b[key], strict));
156
+ const ancestors = /* @__PURE__ */ new Set();
157
+ function compare(a$1, b$1) {
158
+ if (a$1 === b$1) return true;
159
+ if (isVolatile(a$1) || isVolatile(b$1)) return isVolatile(a$1) && isVolatile(b$1);
160
+ if (!strict && isNullable(a$1) && isNullable(b$1)) return true;
161
+ if (typeof a$1 !== typeof b$1 || typeof a$1 !== "object" || !a$1 || !b$1) return false;
162
+ if (ancestors.has(a$1)) return false;
163
+ function check(test, then) {
164
+ return test(a$1) ? test(b$1) ? then(a$1, b$1) : false : test(b$1) ? false : void 0;
165
+ }
166
+ ancestors.add(a$1);
167
+ try {
168
+ return check(Array.isArray, (a$2, b$2) => {
169
+ if (a$2.length !== b$2.length) return false;
170
+ for (let index = 0; index < a$2.length; index++) if (!compare(a$2[index], b$2[index])) return false;
171
+ return true;
172
+ }) ?? check(is("Date"), (a$2, b$2) => a$2.valueOf() === b$2.valueOf()) ?? check(is("URL"), (a$2, b$2) => a$2.href === b$2.href) ?? check(is("RegExp"), (a$2, b$2) => a$2.source === b$2.source && a$2.flags === b$2.flags) ?? check(isArrayBufferLike, (a$2, b$2) => {
173
+ if (a$2.byteLength !== b$2.byteLength) return false;
174
+ const viewA = new Uint8Array(a$2);
175
+ const viewB = new Uint8Array(b$2);
176
+ for (let i = 0; i < viewA.length; i++) if (viewA[i] !== viewB[i]) return false;
177
+ return true;
178
+ }) ?? ((!strict || [a$1, b$1].every((value) => Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)) && Object.keys({
179
+ ...a$1,
180
+ ...b$1
181
+ }).every((key) => compare(a$1[key], b$1[key])));
182
+ } finally {
183
+ ancestors.delete(a$1);
184
+ }
185
+ }
186
+ return compare(a, b);
129
187
  }
130
188
  /** Time constants plus parsing and formatting helpers. */
131
189
  var Time;
@@ -199,7 +257,7 @@ var Time;
199
257
  })(Time || (Time = {}));
200
258
 
201
259
  //#endregion
202
- //#region node_modules/.pnpm/@deepseek-ai+schemastery@3.18.1/node_modules/@deepseek-ai/schemastery/lib/index.mjs
260
+ //#region node_modules/.pnpm/@deepseek-ai+schemastery@3.18.4/node_modules/@deepseek-ai/schemastery/lib/index.mjs
203
261
  const kSchema = Symbol.for("schemastery");
204
262
  const kValidationError = Symbol.for("ValidationError");
205
263
  globalThis.__schemastery_index__ ??= 0;
@@ -375,6 +433,7 @@ Schema.prototype.pattern = function pattern(regexp) {
375
433
  return schema;
376
434
  };
377
435
  Schema.prototype.simplify = function simplify(value) {
436
+ if (isVolatile(value)) value = value.get();
378
437
  if (deepEqual(value, this.meta.default, this.type === "dict")) return null;
379
438
  if (isNullable(value)) return value;
380
439
  if (this.type === "object" || this.type === "dict") {
@@ -431,12 +490,49 @@ for (const key of [
431
490
  };
432
491
  return schema;
433
492
  } });
493
+ Schema.prototype.volatile = function volatile() {
494
+ if (this.meta.volatile) throw new TypeError("volatile schema is already wrapped");
495
+ return this.extra("volatile", true);
496
+ };
434
497
  const resolvers = {};
498
+ const checkedVolatile = Symbol("checked-volatile-schema");
499
+ function validateVolatileSchema(schema, path = [], blocked = false, seen = /* @__PURE__ */ new Map()) {
500
+ const states = seen.get(schema) ?? /* @__PURE__ */ new Set();
501
+ if (states.has(blocked)) return;
502
+ states.add(blocked);
503
+ seen.set(schema, states);
504
+ if (schema.meta?.volatile && blocked) throw new ValidationError("volatile fields require a fixed object path without an enclosing volatile field", { path });
505
+ const nested = blocked || !!schema.meta?.volatile;
506
+ if (schema.dict) for (const [key, child] of Object.entries(schema.dict)) validateVolatileSchema(child, [...path, key], nested, seen);
507
+ if (schema.sKey) validateVolatileSchema(schema.sKey, [...path, "<key>"], true, seen);
508
+ if (schema.inner && (schema.type !== "lazy" || schema.inner[kSchema])) validateVolatileSchema(schema.inner, [...path, "*"], true, seen);
509
+ if (schema.list) for (let index = 0; index < schema.list.length; index++) validateVolatileSchema(schema.list[index], [...path, String(index)], true, seen);
510
+ }
435
511
  Schema.extend = function extend(type, resolve) {
436
512
  resolvers[type] = resolve;
437
513
  };
438
514
  Schema.resolve = function resolve(data, schema, options = {}, strict = false) {
439
515
  if (!schema) return [data];
516
+ if (!options[checkedVolatile]) {
517
+ validateVolatileSchema(schema, options.path);
518
+ options = {
519
+ ...options,
520
+ [checkedVolatile]: true
521
+ };
522
+ }
523
+ if (schema.meta?.volatile) {
524
+ const inner = Schema(schema);
525
+ inner.meta = {
526
+ ...schema.meta,
527
+ volatile: false
528
+ };
529
+ const [value, adapted] = Schema.resolve(data, inner, options, strict);
530
+ try {
531
+ return [createVolatile(value), adapted];
532
+ } catch (error) {
533
+ throw new ValidationError(error instanceof Error ? error.message : String(error), options);
534
+ }
535
+ }
440
536
  if (options.ignore?.(data, schema)) return [data];
441
537
  if (isNullable(data) && schema.type !== "lazy") {
442
538
  if (schema.meta.required) throw new ValidationError(`missing required value`, options);
@@ -539,6 +635,7 @@ Schema.extend("lazy", (data, schema, options, strict) => {
539
635
  ...schema.meta,
540
636
  ...schema.inner.meta
541
637
  };
638
+ validateVolatileSchema(schema.inner, options.path, true);
542
639
  }
543
640
  return Schema.resolve(data, schema.inner, options, strict);
544
641
  });
@@ -638,7 +735,7 @@ function property(data, key, schema, options) {
638
735
  } catch (e) {
639
736
  if (!options?.autofix) throw e;
640
737
  delete data[key];
641
- return schema.meta.default;
738
+ return schema.meta.volatile ? createVolatile(schema.meta.default) : schema.meta.default;
642
739
  }
643
740
  }
644
741
  Schema.extend("array", (data, { inner, meta }, options) => {
@@ -1,77 +1,77 @@
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
+ /**
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,22 +1,22 @@
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
+ /**
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 { 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
+ /**
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;