@xiaoso/dsh-tool-plus 0.1.7 → 0.1.8-beta.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.
Files changed (93) hide show
  1. package/lib/{abort-Caqff3M6.mjs → abort-BtBy5Svf.mjs} +1 -1
  2. package/lib/{alibaba-coding-plan-DTupMiAi.mjs → alibaba-coding-plan-oxHCHJtG.mjs} +2 -2
  3. package/lib/{alibaba-token-plan-Dj3OZhEE.mjs → alibaba-token-plan-B0WzvYnB.mjs} +2 -2
  4. package/lib/{amazon-bedrock-DbFSYXfJ.mjs → amazon-bedrock-BvfYGhrD.mjs} +6 -6
  5. package/lib/{anthropic-CXfWlp-x.mjs → anthropic-C6-vdduI.mjs} +1 -1
  6. package/lib/{anthropic-CTJ3IQVa.mjs → anthropic-Id561lwb.mjs} +13 -13
  7. package/lib/{anthropic-wire-CKuhDwZ1.mjs → anthropic-wire-Cb8AQ1tS.mjs} +13 -13
  8. package/lib/{api-key-validation-CGCJFbFr.mjs → api-key-validation-BXJKlsJg.mjs} +1 -1
  9. package/lib/{azure-openai-responses-ChFbWaGj.mjs → azure-openai-responses-CGws_ijz.mjs} +8 -8
  10. package/lib/{browser-render-9o0Rknop.mjs → browser-render-i7uYOl4f.mjs} +2 -2
  11. package/lib/client.js +2045 -19
  12. package/lib/{cloudflare-ai-gateway-BupNXyKK.mjs → cloudflare-ai-gateway-BK6eadm9.mjs} +2 -2
  13. package/lib/{cloudflare-ai-gateway-EWo0VkP5.mjs → cloudflare-ai-gateway-B_kWnF30.mjs} +1 -1
  14. package/lib/{collapse-DOR8sOGf.mjs → collapse-DU3g7d3B.mjs} +1 -1
  15. package/lib/{coreweave-Ct8cF-da.mjs → coreweave-CkR_FlQi.mjs} +2 -2
  16. package/lib/{cursor-LKGjucn2.mjs → cursor-BXx_5h4a.mjs} +2 -2
  17. package/lib/{cursor-DJV_dcgB.mjs → cursor-BcHwv8qq.mjs} +10 -10
  18. package/lib/{cursor-B95LzVWV.mjs → cursor-BjWbJJLe.mjs} +1 -1
  19. package/lib/{cursor-proto-B8Wj8bv9.mjs → cursor-proto-DPXXYx8S.mjs} +1 -1
  20. package/lib/{devin-DSp0Rw_E.mjs → devin-BZBfzyIz.mjs} +6 -6
  21. package/lib/{devin-BMTdx_hx.mjs → devin-Ce3Wz8_E.mjs} +5 -5
  22. package/lib/{devin-proto-Br8fdyNl.mjs → devin-proto-B6HwDwHK.mjs} +1 -1
  23. package/lib/{error-CORgGg5a.mjs → error-DdCn4m1q.mjs} +3 -3
  24. package/lib/{event-stream-ulcDenZD.mjs → event-stream-ldcUvOA0.mjs} +1 -1
  25. package/lib/{github-copilot-Dstq1D3s.mjs → github-copilot-BT5dkIJl.mjs} +2 -2
  26. package/lib/{github-copilot-headers-DOh1gt_w.mjs → github-copilot-headers-BGL8JO5c.mjs} +2 -2
  27. package/lib/{gitlab-duo-DSCMrU0m.mjs → gitlab-duo-B0qSYCa3.mjs} +1 -1
  28. package/lib/{google-CtsKkOQK.mjs → google-6cRgRmh0.mjs} +3 -3
  29. package/lib/{google-antigravity-z-5KsEci.mjs → google-antigravity-D1llOVad.mjs} +3 -3
  30. package/lib/{google-auth-ieLBaneO.mjs → google-auth-DYhqX1rJ.mjs} +5 -5
  31. package/lib/{google-gemini-cli-CAIPSl7e.mjs → google-gemini-cli-ByQUuKp9.mjs} +7 -7
  32. package/lib/{google-gemini-cli-C6NE5mWz.mjs → google-gemini-cli-CjHy6mFG.mjs} +3 -3
  33. package/lib/{google-oauth-shared-DhMllAkt.mjs → google-oauth-shared-CSwCT0Yl.mjs} +1 -1
  34. package/lib/{google-shared-B0aNCYEH.mjs → google-shared-DYjJp0mQ.mjs} +5 -5
  35. package/lib/{google-vertex-Bbd1tYNc.mjs → google-vertex-CbOvlE5j.mjs} +4 -4
  36. package/lib/{idle-iterator-DlUkEfzW.mjs → idle-iterator-DTBaEIbM.mjs} +2 -2
  37. package/lib/index.mjs +1278 -184
  38. package/lib/{kilo-ChJL54wq.mjs → kilo-cVG1aNZM.mjs} +1 -1
  39. package/lib/{kimi-C2c_Zq8A.mjs → kimi-BFfnFDhu.mjs} +4 -4
  40. package/lib/{launch-DKDH71En.mjs → launch-Uq7920ng.mjs} +7 -7
  41. package/lib/{markit-CmRfm4E2.mjs → markit-BmsfOFVh.mjs} +18 -18
  42. package/lib/{muse-code-Di1VZmB1.mjs → muse-code-CtcevJab.mjs} +1 -1
  43. package/lib/{ollama-B8ic3sEp.mjs → ollama-B5hR1P1p.mjs} +8 -8
  44. package/lib/{openai-codex-DuJNC99x.mjs → openai-codex-CxkPyvyt.mjs} +2 -2
  45. package/lib/{openai-codex-responses-BL29nh9K.mjs → openai-codex-responses-BbM3Q7nJ.mjs} +9 -9
  46. package/lib/{openai-completions-BK2f2dBv.mjs → openai-completions-CffXVOCL.mjs} +13 -13
  47. package/lib/{openai-reasoning-fallback-BdB3RCbj.mjs → openai-reasoning-fallback-DFdD1ok5.mjs} +2 -2
  48. package/lib/{openai-responses-CGQPlIIy.mjs → openai-responses-DgqOvSn_.mjs} +9 -9
  49. package/lib/{perplexity-TBjz3VMB.mjs → perplexity-JFp3knZN.mjs} +2 -2
  50. package/lib/{protobuf-aab1UGVn.mjs → protobuf-BJHNU9-E.mjs} +1 -1
  51. package/lib/{proxy-5nWqRL1f.mjs → proxy-B51IWEMt.mjs} +2 -2
  52. package/lib/{scrapers-CtQrQ5kG.mjs → scrapers-DU4u4-Co.mjs} +7 -7
  53. package/lib/{src-BwW51vA5.mjs → src-DUUqyo9y.mjs} +42 -42
  54. package/lib/{stream-B_7qN-bA.mjs → stream-DHdFrAG4.mjs} +54 -54
  55. package/lib/{stream-markup-healing-DKT1lnkW.mjs → stream-markup-healing-DlJ9abTw.mjs} +2 -2
  56. package/lib/{thinking-CiLa2LFB.mjs → thinking-D6LJxkz_.mjs} +1 -1
  57. package/lib/types/client/locales.d.ts +1 -1
  58. package/lib/types/config/settings.d.ts +8 -0
  59. package/lib/types/tools/ast-grep/adapter/index.d.ts +23 -0
  60. package/lib/types/tools/edit/adapter/index.d.ts +3 -0
  61. package/lib/types/tools/glob/adapter/index.d.ts +2 -0
  62. package/lib/types/tools/grep/adapter/index.d.ts +4 -0
  63. package/lib/types/tools/read/adapter/index.d.ts +18 -0
  64. package/lib/types/tools/write/adapter/index.d.ts +2 -0
  65. package/lib/types/web/client/ToolCardShell.d.ts +111 -0
  66. package/lib/types/web/client/labels.d.ts +36 -0
  67. package/lib/types/web/client/registerToolCards.d.ts +35 -0
  68. package/lib/types/web/client/row-utils.d.ts +177 -0
  69. package/lib/types/web/client/rows/AstEditRow.d.ts +22 -0
  70. package/lib/types/web/client/rows/FileMutationRow.d.ts +23 -0
  71. package/lib/types/web/client/rows/ReadRow.d.ts +31 -0
  72. package/lib/types/web/client/rows/SearchRow.d.ts +21 -0
  73. package/lib/types/web/client/rows/TerminalRow.d.ts +24 -0
  74. package/lib/types/web/client/rows/WriteRow.d.ts +22 -0
  75. package/lib/types/web/client/rows/image-card.d.ts +60 -0
  76. package/lib/types/web/contract.d.ts +249 -0
  77. package/lib/types/web/host/ast-edit.d.ts +10 -0
  78. package/lib/types/web/host/bash.d.ts +30 -0
  79. package/lib/types/web/host/edit.d.ts +33 -0
  80. package/lib/types/web/host/read.d.ts +48 -0
  81. package/lib/types/web/host/search.d.ts +41 -0
  82. package/lib/types/web/host/write.d.ts +13 -0
  83. package/lib/{types-PVueGi9S.mjs → types-DT9vgZ3S.mjs} +1 -1
  84. package/lib/{utils-CUPhpw9A.mjs → utils-BMmwLB0f.mjs} +2 -2
  85. package/lib/{utils-ECAwvaPQ.mjs → utils-C-Lo_JC6.mjs} +41 -41
  86. package/lib/{utils-DeWqNWV8.mjs → utils-D31VFael.mjs} +1 -1
  87. package/lib/{vision-guard-_XwsL1DF.mjs → vision-guard-BlAAqGUC.mjs} +1 -1
  88. package/lib/{xai-oauth-CXhnz0gO.mjs → xai-oauth-QPyScm4X.mjs} +1 -1
  89. package/lib/{xiaomi-psoUItal.mjs → xiaomi-CLzjxHAi.mjs} +1 -1
  90. package/lib/{zai-ApJ8HBgT.mjs → zai-wDp0g7VC.mjs} +1 -1
  91. package/lib/{zip-Kd602XNe.mjs → zip-CNtIFfyV.mjs} +7 -7
  92. package/package.json +3 -1
  93. package/presets/package.json +1 -1
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Web tool-card contract: the payload this plugin's Host half projects into
3
+ * `output.presentationMeta` and its browser half narrows back before drawing.
4
+ *
5
+ * Dependency-free by design (no React, no cordis, no Node built-ins): the Node
6
+ * half imports it to build metadata, the browser half imports it to validate
7
+ * it, and because it carries no React import it can never drag the browser
8
+ * bundle into the Node build.
9
+ *
10
+ * `edit` / `read` / `search` mirror the exact shapes the shipped
11
+ * `@deepseek-ai/dsh-client-ui-tool` card models accept — a `kind` tag rides on
12
+ * top, and those models ignore unknown keys — so the same payload stays
13
+ * readable if this plugin ever stops shadowing those rows. `write`,
14
+ * `ast_edit` and `terminal` are this plugin's own shapes: the shipped rows have
15
+ * no equivalent (their write card is a diff card; ours is a content preview,
16
+ * matching the OMP card the model already sees).
17
+ *
18
+ * Everything here is defensive: a card never throws. The browser half turns any
19
+ * malformed, oversized or foreign payload into `null`, and the row falls back
20
+ * to the generic shell.
21
+ *
22
+ * @module @xiaoso/dsh-tool-plus/web/contract
23
+ */
24
+ /**
25
+ * Cell-shadowing rank of every card entry this plugin registers.
26
+ *
27
+ * The shipped `tool.call.toolview` entries all register at the default
28
+ * priority 0, and the lowest live entry of a cell renders. A large negative
29
+ * constant keeps this plugin first even if a future release starts ranking its
30
+ * own rows below zero — the gap is deliberate, not a tuned value.
31
+ */
32
+ export declare const CARD_TAKEOVER_PRIORITY = -1000;
33
+ /**
34
+ * Wire tool names whose `tool.call.toolview` cell this plugin renders.
35
+ *
36
+ * `ast_grep` / `ast_edit` are this plugin's own tool names (no shipped entry
37
+ * claims those keys), so registering them is purely additive; the other six
38
+ * shadow a shipped row.
39
+ */
40
+ export declare const CARD_TOOL_KEYS: readonly ["bash", "read", "write", "edit", "grep", "glob", "ast_grep", "ast_edit"];
41
+ /** One of {@link CARD_TOOL_KEYS}. */
42
+ export type CardToolKey = (typeof CARD_TOOL_KEYS)[number];
43
+ /**
44
+ * Cap on the serialized `edit` metadata. The engine's unified diff is already
45
+ * bounded per file but unbounded across files; past this budget whole trailing
46
+ * files are dropped, and once nothing is left the call falls back to the
47
+ * generic shell rather than writing an oversized session entry.
48
+ */
49
+ export declare const EDIT_META_MAX_BYTES: number;
50
+ /** Cap on the `ast_edit` change preview (the engine's own display text). */
51
+ export declare const AST_EDIT_META_MAX_BYTES: number;
52
+ /** Cap on the serialized `read` metadata (the returned window's lines). */
53
+ export declare const READ_META_MAX_BYTES: number;
54
+ /**
55
+ * Cap on the serialized search metadata. Same value and meaning as the shipped
56
+ * search card's own `searchMetaMaxBytes`.
57
+ */
58
+ export declare const SEARCH_META_MAX_BYTES: number;
59
+ /** UTF-8 byte length of `text`, without allocating an encoder. */
60
+ export declare function utf8ByteLength(text: string): number;
61
+ /** UTF-8 byte length of a value's JSON form; the unit every cap above uses. */
62
+ export declare function jsonByteLength(value: unknown): number;
63
+ /**
64
+ * Longest prefix of `text` that fits in `cap` UTF-8 bytes, never splitting a
65
+ * surrogate pair.
66
+ * @param text - the text to bound.
67
+ * @param cap - the byte budget.
68
+ * @returns `text` when it already fits, otherwise its longest fitting prefix.
69
+ */
70
+ export declare function capText(text: string, cap: number): string;
71
+ /**
72
+ * Drop entries from the tail until the payload `wrap(retained)` serializes
73
+ * within `cap`.
74
+ *
75
+ * `wrap` receives the retained slice only, so the caller measures the real
76
+ * payload — including its fixed fields — and a single oversized entry ends as
77
+ * an empty list rather than an oversized one.
78
+ * @param items - the ordered entries to bound.
79
+ * @param cap - byte budget for `wrap`'s result.
80
+ * @param wrap - builds the payload that would be emitted for a retained slice.
81
+ * @returns the retained head, in input order.
82
+ */
83
+ export declare function capTail<T>(items: readonly T[], cap: number, wrap: (retained: readonly T[]) => unknown): T[];
84
+ /** One file's change, in the shape the shipped diff card consumes. */
85
+ export type CardDiffHunk = {
86
+ path: string;
87
+ /** Prior content, or `null` for a new file / an overwrite. */
88
+ oldText: string | null;
89
+ /** Content after the change. */
90
+ newText: string;
91
+ };
92
+ /** One line of a read window, in the shape `ReadBlock` consumes. */
93
+ export type CardReadLine = {
94
+ number: number;
95
+ /** The line's text, without its newline. */
96
+ text: string;
97
+ };
98
+ /** One matched line inside a {@link CardSearchFileGroup}. */
99
+ export type CardSearchMatchLine = {
100
+ /** 1-based line number of the match within its file. */
101
+ lineNumber: number;
102
+ /** The matched line's text. */
103
+ line: string;
104
+ };
105
+ /** One file's grouped matches, in first-seen order. */
106
+ export type CardSearchFileGroup = {
107
+ /** The file the matches belong to (display path). */
108
+ path: string;
109
+ /** The file's matched lines, in output order. */
110
+ matches: CardSearchMatchLine[];
111
+ };
112
+ /** `write` card metadata: a content preview, so only the header needs data. */
113
+ export type WriteCardMeta = {
114
+ kind: 'write';
115
+ /** The written file's model-facing path. */
116
+ path: string;
117
+ /** Grammar hint for the preview; omitted when the path names no language. */
118
+ lang?: string;
119
+ /** The write set the file's executable bit; omitted otherwise. */
120
+ madeExecutable?: boolean;
121
+ };
122
+ /** `edit` card metadata: the engine's own unified diff, already computed. */
123
+ export type EditCardMeta = {
124
+ kind: 'edit';
125
+ /** One entry per applied hunk, in file order; never empty. */
126
+ diffs: CardDiffHunk[];
127
+ };
128
+ /** `ast_edit` card metadata: the engine's change preview plus its counters. */
129
+ export type AstEditCardMeta = {
130
+ kind: 'ast_edit';
131
+ /** The engine's display text for the applied replacements. */
132
+ preview: string;
133
+ /** Files touched, with their replacement counts. */
134
+ files: {
135
+ path: string;
136
+ count: number;
137
+ }[];
138
+ /** Total replacements applied. */
139
+ replacements: number;
140
+ /** Whether the edit was applied (`false` previews a dry run). */
141
+ applied: boolean;
142
+ };
143
+ /** `read` card metadata, in the shape the shipped read card consumes. */
144
+ export type ReadCardMeta = {
145
+ kind: 'read';
146
+ /** The read file's path, selector already stripped. */
147
+ path: string;
148
+ /** 1-based first line of the returned window. */
149
+ offset: number;
150
+ /** The returned window's lines, strictly increasing by number. */
151
+ lines: CardReadLine[];
152
+ /** Total line count in the file (the window's last line when unknown). */
153
+ totalLines: number;
154
+ /** Grammar hint for the file; omitted when the path names no language. */
155
+ lang?: string;
156
+ };
157
+ /** `grep` / `ast_grep` search metadata. */
158
+ export type SearchMatchesCardMeta = {
159
+ kind: 'search';
160
+ shape: 'matches';
161
+ /** Matched lines grouped by file, in first-seen order. */
162
+ files: CardSearchFileGroup[];
163
+ /** Whether the payload was capped (the counts below are pre-cap totals). */
164
+ truncated: boolean;
165
+ /** Total matches the search found before capping. */
166
+ total: number;
167
+ };
168
+ /** `glob` search metadata. */
169
+ export type SearchPathsCardMeta = {
170
+ kind: 'search';
171
+ shape: 'paths';
172
+ /** The discovered paths, in result order. */
173
+ paths: string[];
174
+ /** Whether the payload was capped (the counts below are pre-cap totals). */
175
+ truncated: boolean;
176
+ /** Total paths the search found before capping. */
177
+ total: number;
178
+ };
179
+ /** Search metadata: one card, two `shape`-discriminated forms. */
180
+ export type SearchCardMeta = SearchMatchesCardMeta | SearchPathsCardMeta;
181
+ /** `bash` metadata for a foreground call that ran to completion. */
182
+ export type TerminalForegroundCardMeta = {
183
+ kind: 'terminal';
184
+ mode: 'foreground';
185
+ /** Settled exit code; `null` when the process died from a timeout/abort. */
186
+ exitCode: number | null;
187
+ /** The command hit its deadline. */
188
+ timedOut: boolean;
189
+ /** The call was cancelled before the command settled. */
190
+ aborted: boolean;
191
+ /** The working directory the command actually ran in, when known. */
192
+ workingDir?: string;
193
+ };
194
+ /** `bash` metadata for a call handed off to a background job. */
195
+ export type TerminalBackgroundCardMeta = {
196
+ kind: 'terminal';
197
+ mode: 'background';
198
+ /** The managed job's id. */
199
+ jobId: string;
200
+ };
201
+ /** `bash` metadata: the run state the terminal card's status pill needs. */
202
+ export type TerminalCardMeta = TerminalForegroundCardMeta | TerminalBackgroundCardMeta;
203
+ /** Any card metadata this plugin emits. */
204
+ export type CardMeta = WriteCardMeta | EditCardMeta | AstEditCardMeta | ReadCardMeta | SearchCardMeta | TerminalCardMeta;
205
+ /**
206
+ * Narrow opaque metadata to a {@link WriteCardMeta}.
207
+ * @param meta - the result node's `meta` field.
208
+ * @returns the narrowed metadata, or `null` when it is not a usable write card.
209
+ */
210
+ export declare function narrowWriteCardMeta(meta: unknown): WriteCardMeta | null;
211
+ /**
212
+ * Narrow opaque metadata to an {@link EditCardMeta}.
213
+ *
214
+ * Mirrors the shipped diff card's own validation (a hunk needs a non-blank
215
+ * `path`, an explicit `null` or string `oldText`, and a string `newText`) and
216
+ * additionally rejects a payload past {@link EDIT_META_MAX_BYTES}.
217
+ * @param meta - the result node's `meta` field.
218
+ * @returns the narrowed metadata, or `null` when it is not a usable diff card.
219
+ */
220
+ export declare function narrowEditCardMeta(meta: unknown): EditCardMeta | null;
221
+ /**
222
+ * Narrow opaque metadata to an {@link AstEditCardMeta}.
223
+ * @param meta - the result node's `meta` field.
224
+ * @returns the narrowed metadata, or `null` when it is not a usable preview.
225
+ */
226
+ export declare function narrowAstEditCardMeta(meta: unknown): AstEditCardMeta | null;
227
+ /**
228
+ * Narrow opaque metadata to a {@link ReadCardMeta}.
229
+ *
230
+ * Mirrors the shipped read card's own validation: a 1-based `offset`, lines
231
+ * strictly increasing in `number` and never past `totalLines`. A window whose
232
+ * lines were all elided therefore narrows to a card with an empty body, not to
233
+ * a malformed one.
234
+ * @param meta - the result node's `meta` field.
235
+ * @returns the narrowed metadata, or `null` when it is not a usable read card.
236
+ */
237
+ export declare function narrowReadCardMeta(meta: unknown): ReadCardMeta | null;
238
+ /**
239
+ * Narrow opaque metadata to a {@link SearchCardMeta}.
240
+ * @param meta - the result node's `meta` field.
241
+ * @returns the narrowed metadata, or `null` when it is not a usable search card.
242
+ */
243
+ export declare function narrowSearchCardMeta(meta: unknown): SearchCardMeta | null;
244
+ /**
245
+ * Narrow opaque metadata to a {@link TerminalCardMeta}.
246
+ * @param meta - the result node's `meta` field.
247
+ * @returns the narrowed metadata, or `null` when it is not a usable terminal card.
248
+ */
249
+ export declare function narrowTerminalCardMeta(meta: unknown): TerminalCardMeta | null;
@@ -0,0 +1,10 @@
1
+ import type { AstEditCardMeta } from '../contract.ts';
2
+ /**
3
+ * Project the ast_edit engine's result into card metadata.
4
+ * @param details - the engine's `displayContent` / `fileReplacements` /
5
+ * `totalReplacements` / `applied` fields (the adapter's value carries the
6
+ * same names).
7
+ * @returns the ast_edit card metadata, or `null` when the call previews no
8
+ * replacement or produced no preview text.
9
+ */
10
+ export declare function projectAstEditCardMeta(details: unknown): AstEditCardMeta | null;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Host projection for the `bash` terminal card.
3
+ *
4
+ * The call's output value is already the structured shape this card needs, so
5
+ * nothing is read back from the session and nothing is recomputed: the
6
+ * presentation metadata is a lossless narrowing of that value.
7
+ *
8
+ * Two properties matter to the card:
9
+ * - a `timeoutMs: 0` call (the documented way to disable the deadline) is a
10
+ * perfectly valid call; the shipped terminal card treats the option as
11
+ * illegal and drops the whole card, so the run state cannot come from the
12
+ * arguments;
13
+ * - a timed-out or aborted run has no exit code of its own, and its result text
14
+ * (`[timed out after …]`, `[exit code: null]`) is not something the shipped
15
+ * card parses — the run state has to travel as data.
16
+ *
17
+ * @module @xiaoso/dsh-tool-plus/web/host/bash
18
+ */
19
+ import type { TerminalCardMeta } from '../contract.ts';
20
+ /**
21
+ * Project a bash result value into terminal-card metadata.
22
+ *
23
+ * Every emitted field is a plain JSON scalar and no key is ever set to
24
+ * `undefined`: the metadata rides `presentationMeta`, where a non-lossless
25
+ * payload turns a successful call into a failed one. An unrecognized value
26
+ * yields `null`, which simply leaves the row on the generic shell.
27
+ * @param value - the tool's own output value (foreground or background arm).
28
+ * @returns the card metadata, or `null` when the value is not a usable bash result.
29
+ */
30
+ export declare function bashCardMeta(value: unknown): TerminalCardMeta | null;
@@ -0,0 +1,33 @@
1
+ import type { EditCardMeta } from '../contract.ts';
2
+ /** One hunk of a numbered diff, gutter stripped. */
3
+ export interface ParsedDiffHunk {
4
+ /** Removed rows plus context rows, in diff order. */
5
+ oldLines: string[];
6
+ /** Added rows plus context rows, in diff order. */
7
+ newLines: string[];
8
+ /** Whether the hunk carries at least one removed or added row. */
9
+ changed: boolean;
10
+ }
11
+ /**
12
+ * Parse an engine diff body into display hunks.
13
+ *
14
+ * Boundaries: a `@@ … @@` header, a blank gap row (the engine's own
15
+ * non-contiguity marker), or a line-number break after a change (how joined
16
+ * per-entry diffs and skipped context regions read). Hunks without a change are
17
+ * dropped — they would render as an empty diff.
18
+ * @param diff - `details.diff` / `details.perFileResults[].diff`.
19
+ * @returns the hunks, in diff order; empty when nothing parses.
20
+ */
21
+ export declare function parseNumberedDiffHunks(diff: string): ParsedDiffHunk[];
22
+ /**
23
+ * Project the edit engine's result details into card metadata.
24
+ *
25
+ * Multi-file results (`perFileResults`) are read file by file; single-file
26
+ * results use `path` + `diff`. The payload is capped at
27
+ * {@link EDIT_META_MAX_BYTES} by dropping whole trailing files; when nothing is
28
+ * left the call projects to `null` and falls back to the generic shell rather
29
+ * than writing an oversized session entry.
30
+ * @param details - the engine's `EditToolDetails` (or the adapter's value).
31
+ * @returns the edit card metadata, or `null` when there is no usable diff.
32
+ */
33
+ export declare function projectEditCardMeta(details: unknown): EditCardMeta | null;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Host projection for the `read` card: the OMP engine already hands the renderer
3
+ * a prefix-free window (`details.displayContent` —
4
+ * `{text, startLine, lineNumbers?}`) exactly so the UI can draw its own gutter,
5
+ * and that is what the shipped read card consumes
6
+ * (`{kind:'read', path, offset, lines, totalLines, lang?}`).
7
+ *
8
+ * Three details drive the projection:
9
+ * - the card path must be the file, never the model-facing argument: the OMP
10
+ * argument carries an inline selector (`src/foo.ts:5-16,40-80`, `:raw`), so
11
+ * the selector is stripped from whatever path source wins;
12
+ * - `lineNumbers[i] === null` marks an elided span (the body renders `…`); such
13
+ * entries carry no file line number and must be dropped, or the card's
14
+ * "strictly increasing" rule breaks;
15
+ * - only local, text-like reads take the card. Images, directories, internal
16
+ * URLs (`skill://`, `conflict://N`, …), web URLs, SQLite, archives and
17
+ * converted documents all fall back to the generic shell.
18
+ *
19
+ * The projection is bounded: past {@link READ_META_MAX_BYTES} whole trailing
20
+ * lines are dropped, and an empty window projects to `null` rather than to an
21
+ * empty card.
22
+ *
23
+ * @module @xiaoso/dsh-tool-plus/web/host/read
24
+ */
25
+ import type { ReadCardMeta } from '../contract.ts';
26
+ /**
27
+ * Strip the model-facing inline selector from a read target, leaving the file
28
+ * path the card should show.
29
+ *
30
+ * Handles `:5-16,40-80`, `:raw`, `:50+150`, `:conflicts` and the SQLite/archive
31
+ * sub-selectors (`db.sqlite:table:key`), plus the `file://` form the engine
32
+ * itself expands. Windows drive letters survive.
33
+ * @param target - the raw read target (`args.path`, or a resolved path).
34
+ * @returns the path without its selector.
35
+ */
36
+ export declare function stripReadSelector(target: string): string;
37
+ /**
38
+ * Project a read result value into read-card metadata.
39
+ *
40
+ * Every emitted field is plain JSON and no key is ever `undefined`: the metadata
41
+ * rides `presentationMeta`, where a non-lossless payload turns a successful call
42
+ * into a failed one. A non-text read, or a window without a single numbered
43
+ * line, yields `null` and leaves the row on the generic shell.
44
+ * @param args - the tool's arguments (only `path` is read).
45
+ * @param value - the tool's output value, as the adapter projects it.
46
+ * @returns the card metadata, or `null` when this read does not take the card.
47
+ */
48
+ export declare function readCardMeta(args: unknown, value: unknown): ReadCardMeta | null;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Host projection for the `grep` / `ast_grep` / `glob` search cards.
3
+ *
4
+ * The engines already render the display text the TUI used to read: the grouped
5
+ * file output (`# dir/` / `## file.ts#<tag>` headers) followed by code-frame
6
+ * body lines (`*12│text` for a match, ` 12│text` for context, `…` for a gap).
7
+ * That text is the only place the matched *line numbers* live — `details` only
8
+ * carries per-file counts — so the card is rebuilt by parsing it with the same
9
+ * `classifyGroupedLines` helper the TUI renderers used, then reading each
10
+ * `formatCodeFrameLine` gutter back.
11
+ *
12
+ * Everything is defensive and bounded:
13
+ * - an engine that explicitly reports zero (a `matchCount` of `0`, or an empty
14
+ * `paths` array backed by a zero count) is a *known empty result*: it projects
15
+ * to the empty card the client already renders, so the same tool never shows
16
+ * two different shells;
17
+ * - a display that yields no file group at all projects to `null` unless that
18
+ * zero was reported (the row then falls back to the generic shell — the result
19
+ * text stays fully visible);
20
+ * - the payload is capped at {@link SEARCH_META_MAX_BYTES} by dropping trailing
21
+ * groups/paths, with `truncated` raised and `total` left at its pre-cap value.
22
+ *
23
+ * @module @xiaoso/dsh-tool-plus/web/host/search
24
+ */
25
+ import type { SearchMatchesCardMeta, SearchPathsCardMeta } from '../contract.ts';
26
+ /**
27
+ * Project a `grep` / `ast_grep` result value into grouped-matches card metadata.
28
+ *
29
+ * @param input - the tool's output value: `displayContent`, `cwd`, `files`,
30
+ * `matchCount` and `truncated` as the adapters project them.
31
+ * @returns the card metadata, or `null` when no file group could be parsed.
32
+ */
33
+ export declare function searchMatchesCardMeta(input: unknown): SearchMatchesCardMeta | null;
34
+ /**
35
+ * Project a `glob` result value into path-list card metadata.
36
+ *
37
+ * @param input - the tool's output value: `paths`, `fileCount`, `total` and `truncated`.
38
+ * @returns the card metadata, or `null` when the value is not a glob result (no
39
+ * `paths` key, or an empty one the engine never backed with a zero count).
40
+ */
41
+ export declare function searchPathsCardMeta(input: unknown): SearchPathsCardMeta | null;
@@ -0,0 +1,13 @@
1
+ import type { WriteCardMeta } from '../contract.ts';
2
+ /**
3
+ * Project the write tool's result (and its call arguments) into card metadata.
4
+ *
5
+ * The path is the engine's resolved target when it has one, falling back to the
6
+ * authored `args.path` (matching the value the adapter already emits). A blank
7
+ * or missing path projects to `null`; an unrecognized extension omits `lang`
8
+ * instead of writing `undefined`.
9
+ * @param details - the engine's `resolvedPath` / the adapter's value (`path`).
10
+ * @param args - the tool call arguments (`path`), used only as a fallback.
11
+ * @returns the write card metadata, or `null` when no usable path is present.
12
+ */
13
+ export declare function projectWriteCardMeta(details: unknown, args?: unknown): WriteCardMeta | null;
@@ -1,6 +1,6 @@
1
1
  import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
2
  __installBunShim();
3
- import { c as combineSignals } from "./src-BwW51vA5.mjs";
3
+ import { c as combineSignals } from "./src-DUUqyo9y.mjs";
4
4
  import { t as ToolAbortError } from "./tool-errors-DoyxivAR.mjs";
5
5
  import { scheduler } from "node:timers/promises";
6
6
  //#region src/tools/omp/web/scrapers/types.ts
@@ -1,7 +1,7 @@
1
1
  import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
2
  __installBunShim();
3
- import { F as $flag, N as $env, _ as parseStreamingJson, b as debug, g as parseJsonWithRepair } from "./src-BwW51vA5.mjs";
4
- import { r as ValidationError } from "./error-CORgGg5a.mjs";
3
+ import { F as $flag, N as $env, _ as parseStreamingJson, b as debug, g as parseJsonWithRepair } from "./src-DUUqyo9y.mjs";
4
+ import { r as ValidationError } from "./error-DdCn4m1q.mjs";
5
5
  import { n as classifyModel } from "./taxonomy-DSIM99rS.mjs";
6
6
  import { i as getBundledProviders, r as getBundledModels } from "./models-DnXMYGcJ.mjs";
7
7
  import { t as buildModelReferenceIndex } from "./reference-CtvM4zLU.mjs";
@@ -1,40 +1,40 @@
1
1
  import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
2
  __installBunShim();
3
3
  import { n as fs_promises_shim_exports } from "./fs-promises-shim-Bx0fpxuk.mjs";
4
- import { $ as isEnoent, B as USER_AGENT, C as warn, F as $flag, K as getDocumentConversionCacheDir, L as isBunTestRuntime, N as $env, R as isTerminalHeadless, W as getDebugLogPath, Z as getToolsDir, b as debug, c as combineSignals, d as $which, f as register, it as untilAborted, l as exec, q as getInstallId, r as TempDir, x as error, z as isWsl } from "./src-BwW51vA5.mjs";
5
- import { V as ProviderHttpError, a as isTransientStatus, f as OAuthError } from "./error-CORgGg5a.mjs";
6
- import "./utils-CUPhpw9A.mjs";
4
+ import { $ as isEnoent, B as USER_AGENT, C as warn, F as $flag, K as getDocumentConversionCacheDir, L as isBunTestRuntime, N as $env, R as isTerminalHeadless, W as getDebugLogPath, Z as getToolsDir, b as debug, c as combineSignals, d as $which, f as register, it as untilAborted, l as exec, q as getInstallId, r as TempDir, x as error, z as isWsl } from "./src-DUUqyo9y.mjs";
5
+ import { V as ProviderHttpError, a as isTransientStatus, f as OAuthError } from "./error-DdCn4m1q.mjs";
6
+ import "./utils-BMmwLB0f.mjs";
7
7
  import { n as isRecord } from "./type-guards-CttAANEx.mjs";
8
8
  import { t as ToolAbortError } from "./tool-errors-DoyxivAR.mjs";
9
- import { n as extractArchive } from "./zip-Kd602XNe.mjs";
10
- import { a as CODEX_BASE_URL, jt as quotaTierFor, n as getEnvApiKey } from "./stream-B_7qN-bA.mjs";
9
+ import { n as extractArchive } from "./zip-CNtIFfyV.mjs";
10
+ import { a as CODEX_BASE_URL, jt as quotaTierFor, n as getEnvApiKey } from "./stream-DHdFrAG4.mjs";
11
11
  import { n as ALIBABA_TOKEN_PLAN_CN_BASE_URL, r as parseAlibabaTokenPlanCredential } from "./alibaba-token-plan-CHGyWOfX.mjs";
12
- import { a as toNumber, i as toBoolean$1 } from "./utils-DeWqNWV8.mjs";
13
- import "./cloudflare-ai-gateway-EWo0VkP5.mjs";
14
- import { u as COPILOT_GITHUB_HEADERS } from "./github-copilot-headers-DOh1gt_w.mjs";
15
- import "./vision-guard-_XwsL1DF.mjs";
16
- import "./event-stream-ulcDenZD.mjs";
17
- import { o as claudeCodeVersion } from "./anthropic-CXfWlp-x.mjs";
18
- import { n as parseMuseCodeCredential, r as requestMuseCodeKey } from "./muse-code-Di1VZmB1.mjs";
12
+ import { a as toNumber, i as toBoolean$1 } from "./utils-D31VFael.mjs";
13
+ import "./cloudflare-ai-gateway-B_kWnF30.mjs";
14
+ import { u as COPILOT_GITHUB_HEADERS } from "./github-copilot-headers-BGL8JO5c.mjs";
15
+ import "./vision-guard-BlAAqGUC.mjs";
16
+ import "./event-stream-ldcUvOA0.mjs";
17
+ import { o as claudeCodeVersion } from "./anthropic-C6-vdduI.mjs";
18
+ import { n as parseMuseCodeCredential, r as requestMuseCodeKey } from "./muse-code-CtcevJab.mjs";
19
19
  import { n as getAntigravityUserAgent, r as getGeminiCliHeaders } from "./gemini-headers-Co9cVvex.mjs";
20
20
  import { n as clinePassClientHeaders, t as CLINEPASS_API_BASE_URL } from "./cline-pass-Bwg3esu9.mjs";
21
21
  import { i as normalizeDevinSessionToken, n as devinCliMetadata } from "./devin-ExGIghmx.mjs";
22
- import { t as getKimiCommonHeaders } from "./kimi-C2c_Zq8A.mjs";
23
- import { n as extractCursorAccessTokenUserId } from "./cursor-B95LzVWV.mjs";
24
- import { o as toBinary, t as create } from "./protobuf-aab1UGVn.mjs";
25
- import { b as TeamsTier, g as GetUserStatusResponseSchema, h as GetUserStatusRequestSchema, t as decodeDevinUnaryMessage, v as MetadataSchema } from "./devin-proto-Br8fdyNl.mjs";
26
- import { i as getXAICliBillingHeaders, n as extractXAIAccessTokenSubject, r as fetchXAIOAuthIdentity, t as buildXAICliBillingUrl } from "./xai-oauth-CXhnz0gO.mjs";
27
- import "./openai-codex-responses-BL29nh9K.mjs";
28
- import "./anthropic-CTJ3IQVa.mjs";
29
- import "./azure-openai-responses-ChFbWaGj.mjs";
30
- import "./ollama-B8ic3sEp.mjs";
31
- import "./openai-completions-BK2f2dBv.mjs";
32
- import "./openai-responses-CGQPlIIy.mjs";
33
- import { t as MAX_BYTES } from "./types-PVueGi9S.mjs";
22
+ import { t as getKimiCommonHeaders } from "./kimi-BFfnFDhu.mjs";
23
+ import { n as extractCursorAccessTokenUserId } from "./cursor-BjWbJJLe.mjs";
24
+ import { o as toBinary, t as create } from "./protobuf-BJHNU9-E.mjs";
25
+ import { b as TeamsTier, g as GetUserStatusResponseSchema, h as GetUserStatusRequestSchema, t as decodeDevinUnaryMessage, v as MetadataSchema } from "./devin-proto-B6HwDwHK.mjs";
26
+ import { i as getXAICliBillingHeaders, n as extractXAIAccessTokenSubject, r as fetchXAIOAuthIdentity, t as buildXAICliBillingUrl } from "./xai-oauth-QPyScm4X.mjs";
27
+ import "./openai-codex-responses-BbM3Q7nJ.mjs";
28
+ import "./anthropic-Id561lwb.mjs";
29
+ import "./azure-openai-responses-CGws_ijz.mjs";
30
+ import "./ollama-B5hR1P1p.mjs";
31
+ import "./openai-completions-CffXVOCL.mjs";
32
+ import "./openai-responses-DgqOvSn_.mjs";
33
+ import { t as MAX_BYTES } from "./types-DT9vgZ3S.mjs";
34
34
  import * as fs from "node:fs";
35
35
  import { existsSync, unlinkSync } from "node:fs";
36
36
  import { Ellipsis, Ellipsis as Ellipsis$1, extractSegments, matchesKey, sliceWithWidth, truncateToWidth } from "@oh-my-pi/pi-natives";
37
- import * as path from "node:path";
37
+ import * as path$1 from "node:path";
38
38
  import * as os from "node:os";
39
39
  import { scheduler } from "node:timers/promises";
40
40
  import "node:crypto";
@@ -362,7 +362,7 @@ function hasLinuxDesktopSession(platform = process.platform, env = Bun.env, file
362
362
  if (platform !== "linux") return false;
363
363
  if (env.DBUS_SESSION_BUS_ADDRESS) return true;
364
364
  const runtimeDir = env.XDG_RUNTIME_DIR;
365
- return Boolean(runtimeDir && fileExists(path.join(runtimeDir, "bus")));
365
+ return Boolean(runtimeDir && fileExists(path$1.join(runtimeDir, "bus")));
366
366
  }
367
367
  /**
368
368
  * Whether `sendNotification` should also dispatch a D-Bus toast for this
@@ -6085,7 +6085,7 @@ function shortenPath(filePath, homeDir) {
6085
6085
  const home = homeDir ?? os.homedir();
6086
6086
  if (home && filePath.startsWith(home)) {
6087
6087
  const suffix = filePath.slice(home.length);
6088
- if (suffix === "" || suffix.startsWith(path.posix.sep) || suffix.startsWith(path.win32.sep)) return `~${suffix.replaceAll(path.win32.sep, path.posix.sep)}`;
6088
+ if (suffix === "" || suffix.startsWith(path$1.posix.sep) || suffix.startsWith(path$1.win32.sep)) return `~${suffix.replaceAll(path$1.win32.sep, path$1.posix.sep)}`;
6089
6089
  }
6090
6090
  return filePath;
6091
6091
  }
@@ -6267,7 +6267,7 @@ const settings = {
6267
6267
  };
6268
6268
  //#endregion
6269
6269
  //#region package.json
6270
- var version = "0.1.7";
6270
+ var version = "0.1.8-beta.2";
6271
6271
  /** `.tmp` files older than this are treated as orphaned writes and swept. */
6272
6272
  const TMP_ORPHAN_MAX_AGE_MS = 3e5;
6273
6273
  function markitConversionCacheKey(bytes, extension) {
@@ -6275,7 +6275,7 @@ function markitConversionCacheKey(bytes, extension) {
6275
6275
  return `v1-${version.replace(/[^a-z0-9]+/gi, "_")}-${safeExtension}-${new Bun.CryptoHasher("sha256").update(bytes).digest("hex")}`;
6276
6276
  }
6277
6277
  function cacheEntryPath(key) {
6278
- return path.join(getDocumentConversionCacheDir(), `${key}.json`);
6278
+ return path$1.join(getDocumentConversionCacheDir(), `${key}.json`);
6279
6279
  }
6280
6280
  function errorMessage(error) {
6281
6281
  return error instanceof Error ? error.message : String(error);
@@ -6327,7 +6327,7 @@ async function pruneMarkitConversionCache(cacheDir) {
6327
6327
  const entries = [];
6328
6328
  let totalBytes = 0;
6329
6329
  for (const name of names) {
6330
- const entryPath = path.join(cacheDir, name);
6330
+ const entryPath = path$1.join(cacheDir, name);
6331
6331
  let stat;
6332
6332
  try {
6333
6333
  stat = await fs_promises_shim_exports.stat(entryPath);
@@ -6362,8 +6362,8 @@ async function pruneMarkitConversionCache(cacheDir) {
6362
6362
  }
6363
6363
  async function writeMarkitConversionCache(key, content) {
6364
6364
  const cacheDir = getDocumentConversionCacheDir();
6365
- const target = path.join(cacheDir, `${key}.json`);
6366
- const tempPath = path.join(cacheDir, `${key}.${process.pid}.${Date.now()}.${crypto.randomUUID()}.tmp`);
6365
+ const target = path$1.join(cacheDir, `${key}.json`);
6366
+ const tempPath = path$1.join(cacheDir, `${key}.${process.pid}.${Date.now()}.${crypto.randomUUID()}.tmp`);
6367
6367
  const payload = JSON.stringify({
6368
6368
  version: 1,
6369
6369
  content
@@ -6401,7 +6401,7 @@ const CONVERTIBLE_EXTENSIONS = /* @__PURE__ */ new Set([
6401
6401
  ".epub"
6402
6402
  ]);
6403
6403
  let markit = async () => {
6404
- const promise = import("./markit-CmRfm4E2.mjs").then(({ Markit }) => {
6404
+ const promise = import("./markit-BmsfOFVh.mjs").then(({ Markit }) => {
6405
6405
  const instance = new Markit();
6406
6406
  markit = () => instance;
6407
6407
  return instance;
@@ -6508,8 +6508,8 @@ async function convertFileWithMarkit(filePath, signal, options) {
6508
6508
  }
6509
6509
  const streamInfo = {
6510
6510
  localPath: filePath,
6511
- extension: path.extname(filePath).toLowerCase(),
6512
- filename: path.basename(filePath)
6511
+ extension: path$1.extname(filePath).toLowerCase(),
6512
+ filename: path$1.basename(filePath)
6513
6513
  };
6514
6514
  return runCachedBufferConversion(bytes, streamInfo, signal, true);
6515
6515
  }
@@ -6612,7 +6612,7 @@ function getToolPath(tool) {
6612
6612
  if (pythonConfig) return $which(pythonConfig.binaryName);
6613
6613
  const config = TOOLS[tool];
6614
6614
  if (!config) return null;
6615
- const localPath = path.join(TOOLS_DIR, config.binaryName + (os.platform() === "win32" ? ".exe" : ""));
6615
+ const localPath = path$1.join(TOOLS_DIR, config.binaryName + (os.platform() === "win32" ? ".exe" : ""));
6616
6616
  if (fs.existsSync(localPath)) return localPath;
6617
6617
  return $which(config.binaryName);
6618
6618
  }
@@ -6655,13 +6655,13 @@ async function downloadTool(tool, signal) {
6655
6655
  await fs.promises.mkdir(TOOLS_DIR, { recursive: true });
6656
6656
  const downloadUrl = `https://github.com/${config.repo}/releases/download/${config.tagPrefix}${version}/${assetName}`;
6657
6657
  const binaryExt = plat === "win32" ? ".exe" : "";
6658
- const binaryPath = path.join(TOOLS_DIR, config.binaryName + binaryExt);
6658
+ const binaryPath = path$1.join(TOOLS_DIR, config.binaryName + binaryExt);
6659
6659
  if (config.isDirectBinary) {
6660
6660
  await downloadFile(downloadUrl, binaryPath, signal);
6661
6661
  if (plat !== "win32") await fs.promises.chmod(binaryPath, 493);
6662
6662
  return binaryPath;
6663
6663
  }
6664
- const archivePath = path.join(TOOLS_DIR, assetName);
6664
+ const archivePath = path$1.join(TOOLS_DIR, assetName);
6665
6665
  await downloadFile(downloadUrl, archivePath, signal);
6666
6666
  const tmp = await TempDir.create("@omp-tools-extract-");
6667
6667
  try {
@@ -6672,10 +6672,10 @@ async function downloadTool(tool, signal) {
6672
6672
  throw new Error(`Failed to extract ${assetName}: ${err instanceof Error ? err.message : String(err)}`);
6673
6673
  }
6674
6674
  let extractedBinary;
6675
- if (tool === "sg") extractedBinary = path.join(tmp.path(), config.binaryName + binaryExt);
6675
+ if (tool === "sg") extractedBinary = path$1.join(tmp.path(), config.binaryName + binaryExt);
6676
6676
  else {
6677
- const extractedDir = path.join(tmp.path(), assetName.replace(/\.(tar\.gz|zip)$/, ""));
6678
- extractedBinary = path.join(extractedDir, config.binaryName + binaryExt);
6677
+ const extractedDir = path$1.join(tmp.path(), assetName.replace(/\.(tar\.gz|zip)$/, ""));
6678
+ extractedBinary = path$1.join(extractedDir, config.binaryName + binaryExt);
6679
6679
  }
6680
6680
  if (fs.existsSync(extractedBinary)) await fs.promises.rename(extractedBinary, binaryPath);
6681
6681
  else throw new Error(`Binary not found in archive: ${extractedBinary}`);
@@ -1,6 +1,6 @@
1
1
  import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
2
  __installBunShim();
3
- import { n as wrapFetchForExtraCa } from "./src-BwW51vA5.mjs";
3
+ import { n as wrapFetchForExtraCa } from "./src-DUUqyo9y.mjs";
4
4
  //#region node_modules/.pnpm/@oh-my-pi+pi-catalog@18.1.17/node_modules/@oh-my-pi/pi-catalog/src/utils.ts
5
5
  /**
6
6
  * Fetch implementation for catalog discovery probes: the caller's override
@@ -1,6 +1,6 @@
1
1
  import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
2
  __installBunShim();
3
- import "./src-BwW51vA5.mjs";
3
+ import "./src-DUUqyo9y.mjs";
4
4
  import "./effort-BdtQMN-_.mjs";
5
5
  //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/types.ts
6
6
  /**