@dsh-cc/tools 0.5.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.
Files changed (121) hide show
  1. package/LICENSE +201 -0
  2. package/README.i18n.yaml +6 -0
  3. package/README.md +209 -0
  4. package/README.zh.md +200 -0
  5. package/lib/abort-utils.d.ts +80 -0
  6. package/lib/abort-utils.d.ts.map +1 -0
  7. package/lib/abort-utils.js +186 -0
  8. package/lib/abort-utils.js.map +1 -0
  9. package/lib/cc-names.d.ts +100 -0
  10. package/lib/cc-names.d.ts.map +1 -0
  11. package/lib/cc-names.js +197 -0
  12. package/lib/cc-names.js.map +1 -0
  13. package/lib/code-mode.d.ts +46 -0
  14. package/lib/code-mode.d.ts.map +1 -0
  15. package/lib/code-mode.js +380 -0
  16. package/lib/code-mode.js.map +1 -0
  17. package/lib/define-tool.d.ts +103 -0
  18. package/lib/define-tool.d.ts.map +1 -0
  19. package/lib/define-tool.js +354 -0
  20. package/lib/define-tool.js.map +1 -0
  21. package/lib/index.d.ts +348 -0
  22. package/lib/index.d.ts.map +1 -0
  23. package/lib/index.js +289 -0
  24. package/lib/index.js.map +1 -0
  25. package/lib/invariant.d.ts +13 -0
  26. package/lib/invariant.d.ts.map +1 -0
  27. package/lib/invariant.js +123 -0
  28. package/lib/invariant.js.map +1 -0
  29. package/lib/json-render.d.ts +18 -0
  30. package/lib/json-render.d.ts.map +1 -0
  31. package/lib/json-render.js +111 -0
  32. package/lib/json-render.js.map +1 -0
  33. package/lib/json-schema-value.d.ts +18 -0
  34. package/lib/json-schema-value.d.ts.map +1 -0
  35. package/lib/json-schema-value.js +238 -0
  36. package/lib/json-schema-value.js.map +1 -0
  37. package/lib/json-schema.d.ts +101 -0
  38. package/lib/json-schema.d.ts.map +1 -0
  39. package/lib/json-schema.js +351 -0
  40. package/lib/json-schema.js.map +1 -0
  41. package/lib/presentation.d.ts +367 -0
  42. package/lib/presentation.d.ts.map +1 -0
  43. package/lib/presentation.js +8 -0
  44. package/lib/presentation.js.map +1 -0
  45. package/lib/py-names.d.ts +163 -0
  46. package/lib/py-names.d.ts.map +1 -0
  47. package/lib/py-names.js +236 -0
  48. package/lib/py-names.js.map +1 -0
  49. package/lib/py-render.d.ts +23 -0
  50. package/lib/py-render.d.ts.map +1 -0
  51. package/lib/py-render.js +434 -0
  52. package/lib/py-render.js.map +1 -0
  53. package/lib/py-sdk-doc.d.ts +29 -0
  54. package/lib/py-sdk-doc.d.ts.map +1 -0
  55. package/lib/py-sdk-doc.js +114 -0
  56. package/lib/py-sdk-doc.js.map +1 -0
  57. package/lib/py-types.d.ts +34 -0
  58. package/lib/py-types.d.ts.map +1 -0
  59. package/lib/py-types.js +40 -0
  60. package/lib/py-types.js.map +1 -0
  61. package/lib/run-code-defs.d.ts +77 -0
  62. package/lib/run-code-defs.d.ts.map +1 -0
  63. package/lib/run-code-defs.js +98 -0
  64. package/lib/run-code-defs.js.map +1 -0
  65. package/lib/runtime-code.d.ts +65 -0
  66. package/lib/runtime-code.d.ts.map +1 -0
  67. package/lib/runtime-code.js +129 -0
  68. package/lib/runtime-code.js.map +1 -0
  69. package/lib/runtime-core.d.ts +130 -0
  70. package/lib/runtime-core.d.ts.map +1 -0
  71. package/lib/runtime-core.js +33 -0
  72. package/lib/runtime-core.js.map +1 -0
  73. package/lib/runtime-execute.d.ts +82 -0
  74. package/lib/runtime-execute.d.ts.map +1 -0
  75. package/lib/runtime-execute.js +333 -0
  76. package/lib/runtime-execute.js.map +1 -0
  77. package/lib/runtime-registry.d.ts +131 -0
  78. package/lib/runtime-registry.d.ts.map +1 -0
  79. package/lib/runtime-registry.js +269 -0
  80. package/lib/runtime-registry.js.map +1 -0
  81. package/lib/runtime-results.d.ts +32 -0
  82. package/lib/runtime-results.d.ts.map +1 -0
  83. package/lib/runtime-results.js +163 -0
  84. package/lib/runtime-results.js.map +1 -0
  85. package/lib/runtime-schemas.d.ts +112 -0
  86. package/lib/runtime-schemas.d.ts.map +1 -0
  87. package/lib/runtime-schemas.js +222 -0
  88. package/lib/runtime-schemas.js.map +1 -0
  89. package/lib/scheduler.d.ts +22 -0
  90. package/lib/scheduler.d.ts.map +1 -0
  91. package/lib/scheduler.js +21 -0
  92. package/lib/scheduler.js.map +1 -0
  93. package/lib/schema-spec.d.ts +154 -0
  94. package/lib/schema-spec.d.ts.map +1 -0
  95. package/lib/schema-spec.js +9 -0
  96. package/lib/schema-spec.js.map +1 -0
  97. package/lib/schema.d.ts +5 -0
  98. package/lib/schema.d.ts.map +1 -0
  99. package/lib/schema.js +3 -0
  100. package/lib/schema.js.map +1 -0
  101. package/lib/testing.d.ts +25 -0
  102. package/lib/testing.d.ts.map +1 -0
  103. package/lib/testing.js +25 -0
  104. package/lib/testing.js.map +1 -0
  105. package/lib/tool-layer.d.ts +49 -0
  106. package/lib/tool-layer.d.ts.map +1 -0
  107. package/lib/tool-layer.js +57 -0
  108. package/lib/tool-layer.js.map +1 -0
  109. package/lib/tool-types.d.ts +385 -0
  110. package/lib/tool-types.d.ts.map +1 -0
  111. package/lib/tool-types.js +11 -0
  112. package/lib/tool-types.js.map +1 -0
  113. package/lib/ts-types.d.ts +37 -0
  114. package/lib/ts-types.d.ts.map +1 -0
  115. package/lib/ts-types.js +265 -0
  116. package/lib/ts-types.js.map +1 -0
  117. package/lib/types.d.ts +55 -0
  118. package/lib/types.d.ts.map +1 -0
  119. package/lib/types.js +7 -0
  120. package/lib/types.js.map +1 -0
  121. package/package.json +65 -0
@@ -0,0 +1,367 @@
1
+ /**
2
+ * Tool render-intent vocabulary: the provider-neutral types a tool declares via
3
+ * `ToolDefinition.presentCall`/`ToolDefinition.presentResult` to say how one of its calls
4
+ * renders in a UI (an editor's tool-call card, a CLI log line).
5
+ * @module @dsh-cc/tools/src/presentation
6
+ */
7
+ import type { ContentBlock } from '@deepseek-ai/dsh-llm';
8
+ /**
9
+ * Category of a tool call, used by a UI to pick an icon or treatment. The
10
+ * provider-neutral vocabulary lets tools describe themselves without depending
11
+ * on a particular client; `other` is the default.
12
+ */
13
+ export type ToolCallKind = 'read' | 'edit' | 'delete' | 'move' | 'search' | 'execute' | 'fetch' | 'other';
14
+ /**
15
+ * A file location a tool reads or modifies, so a capable UI can "follow along" —
16
+ * highlight or jump to the file (and line) as the tool runs. `path` is what the
17
+ * tool operated on (the model-facing path); `line` is an optional 1-based line
18
+ * to focus (e.g. a read's offset).
19
+ */
20
+ export interface FileLocation {
21
+ path: string;
22
+ line?: number;
23
+ }
24
+ /**
25
+ * A single-file change a tool is about to make, for a UI that renders inline
26
+ * diffs. `oldText` is `null` for a new-file create (nothing to diff against);
27
+ * an overwrite also uses `null`, because a call-time presenter has no access to
28
+ * the file's prior content.
29
+ */
30
+ export interface FileDiff {
31
+ path: string;
32
+ /** Prior content, or `null` for a new file / an overwrite (no prior content available at call time). */
33
+ oldText: string | null;
34
+ /** Content after the change. */
35
+ newText: string;
36
+ }
37
+ /**
38
+ * Provider-neutral pending-call presentation. Tools declare one tagged intent;
39
+ * UI bridges map it without special-casing tool names.
40
+ */
41
+ export type ToolCallView = GenericCallView | TerminalCallView | DiffCallView;
42
+ /**
43
+ * The default card: a titled tool-call row with an optional category icon, a
44
+ * salient raw input, extra content blocks, and follow-along file locations. Any
45
+ * tool whose call is not a terminal or a diff uses this.
46
+ */
47
+ export interface GenericCallView {
48
+ card: 'generic';
49
+ /**
50
+ * Human-readable, always-visible label describing what THIS call does. Keep it
51
+ * short — a UI shows it as a card header / log line.
52
+ */
53
+ title: string;
54
+ /** Category for icon/treatment; defaults to `other` when omitted. */
55
+ kind?: ToolCallKind;
56
+ /**
57
+ * The salient input to show in a detail/expanded view (e.g. a background
58
+ * job id). Omit to show nothing; a string renders as-is, an object as pretty
59
+ * JSON. NOT the full raw args object unless that is genuinely what a reader wants.
60
+ */
61
+ rawInput?: unknown;
62
+ /**
63
+ * UI-facing content blocks to show on the pending call alongside the title.
64
+ * Omit to show none. A UI maps these to its own content blocks.
65
+ */
66
+ content?: ContentBlock[];
67
+ /** Files this call reads/modifies, for editor follow-along. Omit for a call that touches no file. */
68
+ locations?: FileLocation[];
69
+ }
70
+ /**
71
+ * A call that IS a shell command running in a working directory: a capable UI
72
+ * renders it as a terminal card (cwd-headed, with the command as the title and
73
+ * live/afterward output from the {@link TerminalResultView}); an incapable UI
74
+ * falls back to a generic card whose body is the fenced command output. Set by a
75
+ * tool whose call is a foreground command (e.g. `bash`).
76
+ */
77
+ export interface TerminalCallView {
78
+ card: 'terminal';
79
+ /** The command, shown as the terminal card's title / header line. */
80
+ title: string;
81
+ /**
82
+ * A human-readable one-line summary of what the command does, rendered ABOVE
83
+ * the terminal card (the card itself has no description slot). Omit for none.
84
+ */
85
+ description?: string;
86
+ /**
87
+ * Working directory the command runs in, shown as the terminal header. An
88
+ * ABSOLUTE path is used as-is; a RELATIVE path is resolved by the UI bridge
89
+ * against the session workspace (the pure presenter can't see the session cwd).
90
+ * Omit entirely to let the bridge use the session workspace.
91
+ */
92
+ cwd?: string;
93
+ }
94
+ /**
95
+ * A call that creates or modifies files, rendered as an inline diff card by a
96
+ * capable UI. Set by a tool whose call writes/edits a file (e.g. `write`,
97
+ * `edit`). The diffs are derived from the call ARGUMENTS (a create's `oldText` is
98
+ * `null`); the tool emits a separate {@link DiffResultView} after `execute` — the
99
+ * applied change (an edit/overwrite hunk with context, or a whole-file diff for a
100
+ * create).
101
+ */
102
+ export interface DiffCallView {
103
+ card: 'diff';
104
+ /** Card header (e.g. `Write foo.txt`). */
105
+ title: string;
106
+ /** One entry per file the call changes. */
107
+ diffs: FileDiff[];
108
+ /** Files this call modifies, for editor follow-along (usually the diffs' paths). */
109
+ locations?: FileLocation[];
110
+ }
111
+ /**
112
+ * One numbered line of a file, the unit a {@link ReadResultView} carries so a
113
+ * capable UI can render a syntax-highlighted, line-numbered code view. `number`
114
+ * is the 1-based line number in the file (a window past `offset` keeps the file's
115
+ * own numbering, not a 1-based re-count); `text` is the line without its trailing
116
+ * newline, already truncated to the read tool's per-line cap.
117
+ */
118
+ export interface ReadFileLine {
119
+ number: number;
120
+ text: string;
121
+ }
122
+ /**
123
+ * How a tool wants the COMPLETED call shown — the *result* state, after `execute`
124
+ * returns. A `card`-tagged union mirroring {@link ToolCallView}: a UI switches on
125
+ * `card`. Lets the tool reformat its result for a UI distinctly from the
126
+ * model-facing text it returned from `execute`. Returned by
127
+ * `ToolDefinition.presentResult`; omitting the method keeps the pending
128
+ * title and renders the raw result content.
129
+ */
130
+ export type ToolResultView = GenericResultView | TerminalResultView | DiffResultView | SearchResultView | ReadResultView | WebResultView;
131
+ /**
132
+ * The default completed card: an optional replacement title and reformatted
133
+ * content. Omit a field to keep the pending title / render the raw result content.
134
+ */
135
+ export interface GenericResultView {
136
+ card: 'generic';
137
+ /** Replacement title for the completed call. Omit to keep the pending-state title. */
138
+ title?: string;
139
+ /**
140
+ * UI-facing result content (harness {@link ContentBlock}s), reformatted from
141
+ * the model-facing result. Omit to let the UI render the raw result content.
142
+ */
143
+ content?: ContentBlock[];
144
+ }
145
+ /**
146
+ * The completed state of a {@link TerminalCallView}: the captured output and exit
147
+ * status. A capable UI renders `output` in the terminal card and shows an
148
+ * exit-status pill; an incapable UI gets a fenced ```console fallback the BRIDGE
149
+ * derives from `output` (the tool does not double-encode it).
150
+ */
151
+ export interface TerminalResultView {
152
+ card: 'terminal';
153
+ /** Replacement title for the completed call. Omit to keep the pending-state title. */
154
+ title?: string;
155
+ /** Captured command output (stdout+stderr as the tool chooses to combine them). */
156
+ output?: string;
157
+ /**
158
+ * Process exit code, when the run ended by exiting (not a signal). Lets a
159
+ * capable UI show an exit-status pill. Omit when killed by a signal or unknown.
160
+ */
161
+ exitCode?: number;
162
+ /** Signal name that killed the process (e.g. `SIGTERM`). Mutually exclusive with `exitCode`. */
163
+ signal?: string;
164
+ }
165
+ /**
166
+ * A completed file mutation rendered as an inline diff card, the result-time
167
+ * analogue of {@link DiffCallView}. Because a completed UI update replaces the
168
+ * pending card content, mutation tools return this even when it repeats the
169
+ * call-time diff; otherwise raw result text would replace the diff.
170
+ */
171
+ export interface DiffResultView {
172
+ card: 'diff';
173
+ /** Replacement title for the completed call. Omit to keep the pending-state title. */
174
+ title?: string;
175
+ /** The change to show, in file order — applied contextual hunks, or a whole-file diff when there is no before-image. */
176
+ diffs: FileDiff[];
177
+ }
178
+ /** One matched line inside a {@link SearchFileMatches} group: its 1-based line number and text. */
179
+ export interface SearchLineMatch {
180
+ /** 1-based line number of the match within its file. */
181
+ lineNumber: number;
182
+ /** The matched line text, as the tool surfaced it (the per-line preview budget already applied). */
183
+ line: string;
184
+ }
185
+ /** One file's grouped content matches for a {@link SearchMatchesResultView}, in first-seen file order. */
186
+ export interface SearchFileMatches {
187
+ /** The file the matches belong to (the model-facing display path). */
188
+ path: string;
189
+ /** The file's matched lines, in output order. */
190
+ matches: SearchLineMatch[];
191
+ }
192
+ /**
193
+ * A completed content search (`grep`) rendered as a search card whose matches are
194
+ * grouped by file, so a capable UI can list each file as an expandable group of
195
+ * its matched lines. `shape: 'matches'` discriminates this variant from the path
196
+ * variant ({@link SearchPathsResultView}) within {@link SearchResultView}. The
197
+ * discriminant is `shape`, not `kind`, so it never collides with the
198
+ * {@link ToolCallKind} `kind` an icon-picking bridge reads off a call view.
199
+ */
200
+ export interface SearchMatchesResultView {
201
+ card: 'search';
202
+ shape: 'matches';
203
+ /** Replacement title for the completed call. Omit to keep the pending-state title. */
204
+ title?: string;
205
+ /** Matched lines grouped by file, in first-seen file order. */
206
+ files: SearchFileMatches[];
207
+ /**
208
+ * Whether the tool capped the inline result: `files` carries only the retained
209
+ * matches, not every match the search found. A UI shows a capped indicator so it
210
+ * never presents a partial group as complete.
211
+ */
212
+ truncated: boolean;
213
+ /** Total matches the search found before capping (equals the retained count when not `truncated`). */
214
+ total: number;
215
+ }
216
+ /**
217
+ * A completed path search (`glob`) rendered as a search card whose result is a flat
218
+ * path list. `shape: 'paths'` discriminates this variant from the grouped-matches
219
+ * variant ({@link SearchMatchesResultView}) within {@link SearchResultView}.
220
+ */
221
+ export interface SearchPathsResultView {
222
+ card: 'search';
223
+ shape: 'paths';
224
+ /** Replacement title for the completed call. Omit to keep the pending-state title. */
225
+ title?: string;
226
+ /** The discovered paths, in the tool's result order (the retained page when `truncated`). */
227
+ paths: string[];
228
+ /**
229
+ * Whether the tool capped the inline result: `paths` carries only the retained
230
+ * page, not every path the search found. A UI shows a capped indicator so it
231
+ * never presents a partial list as complete.
232
+ */
233
+ truncated: boolean;
234
+ /** Total paths the search found before capping (equals `paths.length` when not `truncated`). */
235
+ total: number;
236
+ }
237
+ /**
238
+ * A completed search rendered as a search card, the result-time view a discovery
239
+ * tool (`grep`, `glob`) returns from `presentResult`. One `card: 'search'` view
240
+ * with two `shape`-discriminated variants: grouped-by-file content matches
241
+ * ({@link SearchMatchesResultView}) and a flat path list
242
+ * ({@link SearchPathsResultView}). Both carry a `truncated`/`total` signal so a UI
243
+ * never presents a capped result as complete. The view carries no result text: a
244
+ * UI without a search card falls back to the raw `tool/result` content. There is
245
+ * no call-time analogue: a search call stays a {@link GenericCallView}
246
+ * (`kind: 'search'`) because the pending state has no matches or paths to show —
247
+ * the structured shape exists only after `execute`.
248
+ */
249
+ export type SearchResultView = SearchMatchesResultView | SearchPathsResultView;
250
+ /**
251
+ * A completed file read rendered as a line-numbered, optionally syntax-highlighted
252
+ * code view by a capable UI. Set by a tool whose call reads file text (e.g.
253
+ * `read`); the pending state stays a {@link GenericCallView} (`kind: 'read'`)
254
+ * because a call carries no content until `execute` returns. The structured
255
+ * `lines`/`path`/`lang`/`totalLines` fields cannot be reconstructed from the
256
+ * model-facing result text alone, so the read tool projects them through its
257
+ * `output.presentationMeta` (persisted with the session log) and `presentResult`
258
+ * narrows that metadata back into this view on live and replay paths alike. A UI
259
+ * without the read capability falls back to `content` (the model-facing text with
260
+ * its envelope stripped), so this view degrades to the generic text card.
261
+ */
262
+ export interface ReadResultView {
263
+ card: 'read';
264
+ /** Replacement title for the completed call. Omit to keep the pending-state title. */
265
+ title?: string;
266
+ /** The read file's path (the model-facing path; the bridge relativizes it). */
267
+ path: string;
268
+ /**
269
+ * The 1-based first line the window requested, preserved even when `lines` is
270
+ * empty (a byte cap below the first selected line yields an empty window) so a
271
+ * UI knows where the window starts and where a continuation resumes.
272
+ */
273
+ offset: number;
274
+ /** The returned window's lines, in file order, each keeping its file line number. */
275
+ lines: ReadFileLine[];
276
+ /** Exact total line count in the file, so a UI can show a "showing N of M" affordance. */
277
+ totalLines: number;
278
+ /**
279
+ * A syntax-highlighting language hint derived from the file extension (e.g.
280
+ * `ts`, `py`), or omitted when the extension maps to no known language so a UI
281
+ * renders the lines as plain text.
282
+ */
283
+ lang?: string;
284
+ /**
285
+ * The model-facing result content with its envelope stripped, for a UI without
286
+ * the read capability. Omit to let such a UI render the raw result content.
287
+ */
288
+ content?: ContentBlock[];
289
+ }
290
+ /**
291
+ * One citeable source in a completed {@link WebSearchResultView}, the faithful
292
+ * projection of one web-search source. The presentation projection of `dsh-web`'s
293
+ * `WebSearchSource`: that Service Definition type is authoritative (core cannot depend
294
+ * on the web Service Definition, so the two are declared separately and MUST evolve together).
295
+ * A web tool projects this shape through `output.presentationMeta` because the
296
+ * render text cannot losslessly carry it (see the web-result-card Agent Note); its
297
+ * `presentResult` reads it back.
298
+ */
299
+ export interface WebSource {
300
+ /** The source URL. */
301
+ url: string;
302
+ /** The source title, when the provider returned one. */
303
+ title?: string;
304
+ /** A short excerpt or summary, when the provider returned one. */
305
+ snippet?: string;
306
+ /** Publication/crawl timestamp as a provider-supplied ISO-8601 string, when present. */
307
+ publishedAt?: string;
308
+ }
309
+ /**
310
+ * A completed web retrieval rendered as a structured card by a capable UI. Set
311
+ * by a web tool whose call retrieves from the web (`web_search`, `web_fetch`).
312
+ * One `kind`-tagged union carries both shapes because both are web retrieval and
313
+ * a UI renders them with one component family; a UI switches on `kind`. An
314
+ * incapable UI falls back to the raw `tool/result` content (this view carries no
315
+ * `content` copy — see the web-result-card Agent Note). This is the result-time
316
+ * analogue of the `web_search`/`web_fetch` calls' generic call views
317
+ * (`kind: 'search'`/`'fetch'`); those tools keep their generic pending card and
318
+ * add only this completed card.
319
+ *
320
+ * The `kind` field here is this union's own discriminant, NOT a
321
+ * {@link ToolCallKind}: the two values deliberately match the tools' pending
322
+ * `ToolCallKind` (`'search'`/`'fetch'`) so a call and its result read as one
323
+ * category, but a new arm is a union edit plus a consumer branch, not any
324
+ * arbitrary `ToolCallKind` value.
325
+ */
326
+ export type WebResultView = WebSearchResultView | WebFetchResultView;
327
+ /**
328
+ * The completed state of a `web_search` call: the structured sources the model
329
+ * cited, an optional provider answer, and whether the source list was cut to the
330
+ * result cap. A capable UI renders the sources as a citation list; a UI without
331
+ * the `web` capability falls back to the raw `tool/result` content.
332
+ */
333
+ export interface WebSearchResultView {
334
+ card: 'web';
335
+ kind: 'search';
336
+ /** Replacement title for the completed call. Omit to keep the pending-state title. */
337
+ title?: string;
338
+ /** The faithful, structured sources — the field render text cannot losslessly carry. */
339
+ sources: WebSource[];
340
+ /** The provider-generated answer text, when any. */
341
+ answer?: string;
342
+ /** True when the web service cut the source list to honor the result cap. */
343
+ truncated: boolean;
344
+ }
345
+ /**
346
+ * The completed state of a `web_fetch` call: the fetched URL, its HTTP status,
347
+ * and whether the content was cut. The body itself is already markdown in the
348
+ * raw `tool/result` content, so this card carries only the retrieval summary and
349
+ * a UI without the `web` capability falls back to that content.
350
+ */
351
+ export interface WebFetchResultView {
352
+ card: 'web';
353
+ kind: 'fetch';
354
+ /** Replacement title for the completed call. Omit to keep the pending-state title. */
355
+ title?: string;
356
+ /** The final URL after allowed redirects. */
357
+ url: string;
358
+ /** HTTP status code of the fetched response. */
359
+ statusCode: number;
360
+ /**
361
+ * True when the provider capped the decoded body, or the output cap or a
362
+ * pre-conversion source cut trimmed the rendered text (the effective
363
+ * truncation the model-facing text also reflects).
364
+ */
365
+ truncated: boolean;
366
+ }
367
+ //# sourceMappingURL=presentation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation.d.ts","sourceRoot":"","sources":["../src/presentation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Tool render-intent vocabulary: the provider-neutral types a tool declares via
3
+ * `ToolDefinition.presentCall`/`ToolDefinition.presentResult` to say how one of its calls
4
+ * renders in a UI (an editor's tool-call card, a CLI log line).
5
+ * @module @dsh-cc/tools/src/presentation
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=presentation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation.js","sourceRoot":"","sources":["../src/presentation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Naming, state, and text-escaping machinery shared by the Python SDK renderers
3
+ * (`py-types.ts`, `py-render.ts`, `py-sdk-doc.ts`). Leaf module: imports nothing
4
+ * from its siblings, so any of them may depend on it without creating cycles.
5
+ * Split out of `py-types.ts` for the line budget.
6
+ * @module @dsh-cc/tools/src/py-names
7
+ */
8
+ /**
9
+ * Whether a name can be emitted as a bare Python identifier rather than
10
+ * routed to the subscript/`dict[str, Any]` path.
11
+ *
12
+ * Python identifiers are not ASCII: `路径` is as legal a field name as `path`,
13
+ * and rejecting it would degrade the whole enclosing object, dropping every
14
+ * field's name, requiredness, and type — information whose only source under
15
+ * `mode: 'code'` is this generated text.
16
+ *
17
+ * NFKC stability is a second and separate condition, because CPython
18
+ * normalizes identifiers at compile time while JSON keys are compared as
19
+ * written: `field` would be declared and reachable as `field`, so the SDK would
20
+ * advertise a key under a spelling the harness never accepts, and two keys
21
+ * that normalize together would collapse into one declaration. Those names
22
+ * take the subscript path, which carries their exact bytes.
23
+ *
24
+ * `IDENTIFIER` matches `str.isidentifier()` (measured on Node 22.23.1 vs
25
+ * CPython 3.9.6 tables): the equivalence holds inside the two versions' shared
26
+ * tables, and the skew characters below are exactly where that pair diverges.
27
+ * The predicate as a whole is deliberately stricter than `isidentifier()`,
28
+ * which does not test NFKC stability: `'field'.isidentifier()` is True and
29
+ * this returns false.
30
+ *
31
+ * Both conditions are evaluated against the ENGINE's Unicode tables, and the
32
+ * two sides are versioned independently — `\p{XID_Start}`/`\p{XID_Continue}`
33
+ * follow the running engine (Node 22.23.1 reports Unicode 17.0) while CPython
34
+ * follows its own (3.9.6 reports 13.0.0). The skew is not symmetric. A CPython
35
+ * older than the engine is the dangerous direction: a character added to either
36
+ * property since its tables (U+10570 Vithkuqi and U+1E290 Toto, 14.0; U+1E4D0
37
+ * Nag Mundari, 15.0; U+1C89 Cyrillic TJE, 16.0 — ages per `DerivedAge.txt`; all
38
+ * four are NFKC-stable and accepted here, and all four are `Cn` on that 3.9.6,
39
+ * which rejects them) is emitted bare and its tokenizer refuses the character,
40
+ * taking the whole SDK block down — the same parseability invariant
41
+ * {@link UNPRINTABLE}, {@link LONE_SURROGATE} and {@link MAX_LIST_NESTING}
42
+ * exist for. Both properties carry it: a character added only to `XID_Continue`
43
+ * passes the trailing `\p{XID_Continue}*` in a tail position and fails the same
44
+ * way — U+200C ZWNJ and U+200D ZWJ are that case, gaining `XID_Continue` in UCD
45
+ * 15.1 and absent from it in 13.0.0, 14.0.0 and 15.0.0, so `a\u{200C}b` is
46
+ * emitted bare here while `isidentifier()` is False on 3.9.6 and on 3.12.13
47
+ * (15.0.0). A CPython newer than the engine only routes a legal name to the
48
+ * subscript/`dict[str, Any]` path: less readable, still correct. The NFKC
49
+ * condition reduces to the same skew, since normalization stability guarantees
50
+ * an assigned character's normalization never changes afterwards.
51
+ *
52
+ * This predicate is not the only reader of engine tables. {@link camelCase}
53
+ * reads them at three further points — its split set, its head test, and its
54
+ * `toUpperCase()` case mapping — and this predicate's verdict gates none of
55
+ * them: a class name derived there reaches emitted text whenever any object
56
+ * shape in the tool's schema declares a `TypedDict`, including for a tool this
57
+ * predicate rejected. A tool named `zz-\u{1E4D0}x` with such parameters never
58
+ * reaches the skew here (the `-` rejects it outright) yet emits `class
59
+ * Zz\u{1E4D0}xArgs`, which that same 3.9.6 refuses — Nag Mundari arrived two
60
+ * releases after its tables. The case mapping is a separate table rather than
61
+ * an XID membership test, and it fails on names both conditions above accept:
62
+ * `\u{019B}` is XID_Start and NFKC-stable, so this predicate accepts it and
63
+ * `async def \u{019B}` compiles on 3.9.6, but Node uppercases it to
64
+ * `\u{A7DC}` — unassigned in that CPython, whose own `.upper()` is the identity
65
+ * here — and the declared `class \u{A7DC}Args` fails with `invalid
66
+ * non-printable character U+A7DC`. Closing the exposure therefore covers all
67
+ * four read points, not this predicate alone; it needs the target interpreter's
68
+ * version, which the backend reporting `language: 'python'` owns; the
69
+ * language-dispatch Agent Note records the deferral.
70
+ *
71
+ * The `ts-types` sibling keeps its own ASCII rule rather than sharing this
72
+ * one: ECMAScript identifiers are a different set (`$`) and are never
73
+ * normalized, so one predicate cannot be correct for both. ZWJ/ZWNJ are not
74
+ * part of that difference — both sets carry them on the engine's tables; what
75
+ * separates the two there is the CPython table version above.
76
+ * @param name - the raw schema field or tool name.
77
+ * @returns whether the name can be emitted bare.
78
+ */
79
+ export declare function isBareIdentifier(name: string): boolean;
80
+ /**
81
+ * Python hard keywords: reserved everywhere, so a tool or field named
82
+ * ``class`` or ``lambda`` is legal on the wire but not as an attribute
83
+ * (``tools.class`` would be a SyntaxError in the model program) and not as a
84
+ * class-syntax `TypedDict` field. Such a tool renders under subscript access
85
+ * and such an object degrades to ``dict[str, Any]`` — the model still reaches
86
+ * every tool and field without collisions.
87
+ * Soft keywords (``match``, ``case``, ``type``, ``_`` — the language
88
+ * reference's whole set) are deliberately ABSENT: each is special in exactly
89
+ * one syntactic position — a statement head (``match``, ``type``), a ``match``
90
+ * statement's clause head (``case``), or a pattern (``_``) — so ``match: str``
91
+ * as a field and ``async def match(...)`` as a method are both legal, and
92
+ * including them would needlessly degrade common search/regex tool fields to
93
+ * ``dict[str, Any]``. Underscore-leading names are handled separately, not
94
+ * here: a non-dunder ``__token`` name-mangles, a dunder present on
95
+ * ``object``/``type`` resolves before the proxy hook, and implicit
96
+ * special-method lookup bypasses the hook.
97
+ */
98
+ export declare const RESERVED: Set<string>;
99
+ /** `indent`-deep line prefix (four spaces per level to match PEP 8 output). */
100
+ export declare function pad(indent: number): string;
101
+ /**
102
+ * Collector threaded through the type renderer: the emitted `TypedDict` class
103
+ * declarations (nested classes precede the parent that references them), the
104
+ * class names already taken (for collision suffixing), a per-base collision
105
+ * counter, and the `typing` symbols the render actually used.
106
+ */
107
+ export interface RenderState {
108
+ readonly classes: string[];
109
+ readonly usedClassNames: Set<string>;
110
+ /** Next collision counter per capped base, so allocation is amortized O(1) instead of rescanning from `2`. */
111
+ readonly nextClassCounter: Map<string, number>;
112
+ readonly typing: Set<string>;
113
+ }
114
+ /**
115
+ * The collapsed one-line `description` of a schema node (byte-stable across
116
+ * formatting churn), or `undefined` when the node carries none. Every caller
117
+ * passes an object — a validated property node, the `ToolSdkSchema` itself, or
118
+ * the `{ description }` wrapper {@link docLines} synthesizes — so only the
119
+ * description field needs guarding. A description that collapses
120
+ * to nothing (empty, or whitespace only) is `undefined` too: it documents the
121
+ * node no better than an absent one, and emitting it would leave an empty
122
+ * `"""` docstring or a bare `# ` line in the SDK. Only ECMAScript whitespace
123
+ * folds, so a description of whitespace plus one surviving control character is
124
+ * NOT absent: it collapses to that character's visible escape.
125
+ *
126
+ * Control characters left over after the whitespace collapse are rendered as
127
+ * their `\xNN` escapes (see {@link UNPRINTABLE}) and unpaired surrogates as
128
+ * their `\uNNNN` escapes (see {@link LONE_SURROGATE}); the escape's own backslash is
129
+ * emitted literally by both consumers, since {@link docLines} doubles it into a
130
+ * Python source escape and a `#` comment carries it verbatim.
131
+ */
132
+ export declare function describe(schema: object): string | undefined;
133
+ /**
134
+ * CamelCase a name into a Python type identifier: non-identifier characters
135
+ * split words, `_` splits too (it is `XID_Continue`, so the split set names it
136
+ * explicitly), and a head that cannot start an identifier takes a `Tool`
137
+ * prefix. Unicode survives, so a `路径` field yields `路径`-based class names
138
+ * instead of collapsing to the bare prefix. A character that is not
139
+ * `XID_Continue` splits even when it is a letter, so a name whose NFKC folding
140
+ * would leave the identifier set is not carried through — the split set is the
141
+ * grammar's, not an ASCII approximation of it.
142
+ *
143
+ * The result is NFKC-normalized: these names are generated, never matched
144
+ * against a JSON key, so normalizing is free here and keeps what CPython
145
+ * compiles identical to what is emitted — unlike {@link isBareIdentifier},
146
+ * which must reject unstable names outright. Normalizing AFTER the prefix
147
+ * decision is what makes that hold at the seam the prefix creates: `Tool` +
148
+ * a combining-mark head composes there (`U+0301` gives `Tooĺ`, U+013A), so
149
+ * normalizing only the un-prefixed part would emit a name CPython compiles to
150
+ * a different symbol. The second call is idempotent on the un-prefixed arm.
151
+ *
152
+ * The split set, the head test, and `toUpperCase()` all read the engine's
153
+ * Unicode tables, so this function carries the same version skew
154
+ * {@link isBareIdentifier} documents, by paths independent of it: a class name
155
+ * derived here reaches emitted text whenever any object shape in the tool's
156
+ * schema declares a `TypedDict`, and the predicate's verdict on the tool name
157
+ * does not gate that. The case mapping is the one that can fail on a name the
158
+ * predicate accepted; the worked example is there.
159
+ * @param raw - the schema field or tool name to derive from.
160
+ * @returns a class-name segment safe to emit.
161
+ */
162
+ export declare function camelCase(raw: string): string;
163
+ //# sourceMappingURL=py-names.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"py-names.d.ts","sourceRoot":"","sources":["../src/py-names.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,QAAQ,aASnB,CAAA;AAEF,+EAA+E;AAC/E,wBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE1C;AAED;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAA;IAC1B,QAAQ,CAAC,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACpC,8GAA8G;IAC9G,QAAQ,CAAC,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9C,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAC7B;AAqDD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAS3D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAQ7C"}