@superdoc-dev/sdk 1.0.0-alpha.4 → 1.0.0-alpha.41

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 (43) hide show
  1. package/README.md +124 -0
  2. package/dist/generated/client.cjs +479 -0
  3. package/dist/generated/client.d.ts +11940 -1167
  4. package/dist/generated/client.d.ts.map +1 -1
  5. package/dist/generated/client.js +433 -25
  6. package/dist/generated/contract.cjs +123158 -0
  7. package/dist/generated/contract.d.ts +30 -13672
  8. package/dist/generated/contract.d.ts.map +1 -1
  9. package/dist/generated/contract.js +116698 -11334
  10. package/dist/helpers/format.d.ts +79 -0
  11. package/dist/helpers/format.d.ts.map +1 -0
  12. package/dist/helpers/format.js +121 -0
  13. package/dist/index.cjs +45 -0
  14. package/dist/index.d.ts +3 -3
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +1 -1
  17. package/dist/runtime/embedded-cli.cjs +100 -0
  18. package/dist/runtime/errors.cjs +22 -0
  19. package/dist/runtime/host.cjs +352 -0
  20. package/dist/runtime/host.d.ts +2 -1
  21. package/dist/runtime/host.d.ts.map +1 -1
  22. package/dist/runtime/host.js +3 -1
  23. package/dist/runtime/process.cjs +32 -0
  24. package/dist/runtime/process.d.ts +1 -1
  25. package/dist/runtime/process.d.ts.map +1 -1
  26. package/dist/runtime/transport-common.cjs +79 -0
  27. package/dist/runtime/transport-common.d.ts +6 -1
  28. package/dist/runtime/transport-common.d.ts.map +1 -1
  29. package/dist/runtime/transport-common.js +13 -4
  30. package/dist/skills.cjs +148 -0
  31. package/dist/tools.cjs +312 -0
  32. package/dist/tools.d.ts +42 -65
  33. package/dist/tools.d.ts.map +1 -1
  34. package/dist/tools.js +75 -134
  35. package/package.json +15 -14
  36. package/skills/editing-docx.md +31 -0
  37. package/tools/catalog.json +59826 -15216
  38. package/tools/tool-name-map.json +300 -71
  39. package/tools/tools-policy.json +79 -82
  40. package/tools/tools.anthropic.json +25742 -2983
  41. package/tools/tools.generic.json +58182 -15148
  42. package/tools/tools.openai.json +26715 -3266
  43. package/tools/tools.vercel.json +26715 -3266
package/dist/tools.js CHANGED
@@ -80,24 +80,10 @@ async function loadToolNameMap() {
80
80
  async function loadCatalog() {
81
81
  return readJson('catalog.json');
82
82
  }
83
- function normalizeFeatures(features) {
84
- return {
85
- hasTables: Boolean(features?.hasTables),
86
- hasLists: Boolean(features?.hasLists),
87
- hasComments: Boolean(features?.hasComments),
88
- hasTrackedChanges: Boolean(features?.hasTrackedChanges),
89
- isEmptyDocument: Boolean(features?.isEmptyDocument),
90
- };
91
- }
92
- function stableSortByPhasePriority(entries, priorityOrder) {
93
- const priority = new Map(priorityOrder.map((category, index) => [category, index]));
94
- return [...entries].sort((a, b) => {
95
- const aPriority = priority.get(a.category) ?? Number.MAX_SAFE_INTEGER;
96
- const bPriority = priority.get(b.category) ?? Number.MAX_SAFE_INTEGER;
97
- if (aPriority !== bPriority)
98
- return aPriority - bPriority;
99
- return a.toolName.localeCompare(b.toolName);
100
- });
83
+ /** All available tool groups from the policy. */
84
+ export function getAvailableGroups() {
85
+ const policy = loadPolicy();
86
+ return policy.groups;
101
87
  }
102
88
  const OPERATION_INDEX = Object.fromEntries(Object.entries(CONTRACT.operations).map(([id, op]) => [id, op]));
103
89
  function validateDispatchArgs(operationId, args) {
@@ -190,26 +176,16 @@ function resolveDocApiMethod(client, operationId) {
190
176
  }
191
177
  return cursor;
192
178
  }
193
- export async function getToolCatalog(options = {}) {
194
- const catalog = await loadCatalog();
195
- if (!options.profile)
196
- return catalog;
197
- return {
198
- ...catalog,
199
- profiles: {
200
- intent: options.profile === 'intent' ? catalog.profiles.intent : { name: 'intent', tools: [] },
201
- operation: options.profile === 'operation' ? catalog.profiles.operation : { name: 'operation', tools: [] },
202
- },
203
- };
179
+ export async function getToolCatalog() {
180
+ return loadCatalog();
204
181
  }
205
- export async function listTools(provider, options = {}) {
206
- const profile = options.profile ?? 'intent';
182
+ export async function listTools(provider) {
207
183
  const bundle = await loadProviderBundle(provider);
208
- const tools = bundle.profiles[profile];
184
+ const tools = bundle.tools;
209
185
  if (!Array.isArray(tools)) {
210
- throw new SuperDocCliError('Tool provider bundle is missing profile tools.', {
186
+ throw new SuperDocCliError('Tool provider bundle is missing tools array.', {
211
187
  code: 'TOOLS_ASSET_INVALID',
212
- details: { provider, profile },
188
+ details: { provider },
213
189
  });
214
190
  }
215
191
  return tools;
@@ -218,103 +194,60 @@ export async function resolveToolOperation(toolName) {
218
194
  const map = await loadToolNameMap();
219
195
  return typeof map[toolName] === 'string' ? map[toolName] : null;
220
196
  }
221
- export function inferDocumentFeatures(infoResult) {
222
- if (!isRecord(infoResult)) {
223
- return {
224
- hasTables: false,
225
- hasLists: false,
226
- hasComments: false,
227
- hasTrackedChanges: false,
228
- isEmptyDocument: false,
229
- };
230
- }
231
- const counts = isRecord(infoResult.counts) ? infoResult.counts : {};
232
- const words = typeof counts.words === 'number' ? counts.words : 0;
233
- const paragraphs = typeof counts.paragraphs === 'number' ? counts.paragraphs : 0;
234
- const tables = typeof counts.tables === 'number' ? counts.tables : 0;
235
- const comments = typeof counts.comments === 'number' ? counts.comments : 0;
236
- const lists = typeof counts.lists === 'number' ? counts.lists : typeof counts.listItems === 'number' ? counts.listItems : 0;
237
- const trackedChanges = typeof counts.trackedChanges === 'number'
238
- ? counts.trackedChanges
239
- : typeof counts.tracked_changes === 'number'
240
- ? counts.tracked_changes
241
- : 0;
242
- return {
243
- hasTables: tables > 0,
244
- hasLists: lists > 0,
245
- hasComments: comments > 0,
246
- hasTrackedChanges: trackedChanges > 0,
247
- isEmptyDocument: words === 0 && paragraphs <= 1,
248
- };
249
- }
197
+ /**
198
+ * Select tools for a specific provider.
199
+ *
200
+ * **mode='essential'** (default): Returns only essential tools + discover_tools.
201
+ * Pass `groups` to additionally load all tools from those categories.
202
+ *
203
+ * **mode='all'**: Returns all tools from requested groups (or all groups if
204
+ * `groups` is omitted). No discover_tools included by default.
205
+ *
206
+ * @example
207
+ * ```ts
208
+ * // Default: 5 essential tools + discover_tools
209
+ * const { tools } = await chooseTools({ provider: 'openai' });
210
+ *
211
+ * // Essential + all comment tools
212
+ * const { tools } = await chooseTools({ provider: 'openai', groups: ['comments'] });
213
+ *
214
+ * // All tools (old behavior)
215
+ * const { tools } = await chooseTools({ provider: 'openai', mode: 'all' });
216
+ * ```
217
+ */
250
218
  export async function chooseTools(input) {
251
219
  const catalog = await loadCatalog();
252
220
  const policy = loadPolicy();
253
- const profile = input.profile ?? 'intent';
254
- const phase = input.taskContext?.phase ?? 'read';
255
- const phasePolicy = policy.phases[phase];
256
- const featureMap = normalizeFeatures(input.documentFeatures);
257
- const maxTools = Math.max(1, input.budget?.maxTools ?? policy.defaults.maxToolsByProfile[profile]);
258
- const minReadTools = Math.max(0, input.budget?.minReadTools ?? policy.defaults.minReadTools);
259
- const includeCategories = new Set(input.policy?.includeCategories ?? phasePolicy.include);
260
- const excludeCategories = new Set([...(input.policy?.excludeCategories ?? []), ...phasePolicy.exclude]);
261
- const allowMutatingTools = input.policy?.allowMutatingTools ?? phase === 'mutate';
262
- const excluded = [];
263
- const profileTools = catalog.profiles[profile].tools;
264
- const indexByToolName = new Map(profileTools.map((tool) => [tool.toolName, tool]));
265
- let candidates = profileTools.filter((tool) => {
266
- if (tool.requiredCapabilities.some((capability) => !featureMap[capability])) {
267
- excluded.push({ toolName: tool.toolName, reason: 'missing-required-capability' });
221
+ const mode = input.mode ?? policy.defaults.mode ?? 'essential';
222
+ const includeDiscover = input.includeDiscoverTool ?? mode === 'essential';
223
+ let selected;
224
+ if (mode === 'essential') {
225
+ // Essential tools + any explicitly requested groups
226
+ const essentialNames = new Set(policy.essentialTools ?? []);
227
+ const requestedGroups = input.groups ? new Set(input.groups) : null;
228
+ selected = catalog.tools.filter((tool) => {
229
+ if (essentialNames.has(tool.toolName))
230
+ return true;
231
+ if (requestedGroups && requestedGroups.has(tool.category))
232
+ return true;
268
233
  return false;
269
- }
270
- if (!allowMutatingTools && tool.mutates) {
271
- excluded.push({ toolName: tool.toolName, reason: 'mutations-disabled' });
272
- return false;
273
- }
274
- if (includeCategories.size > 0 && !includeCategories.has(tool.category)) {
275
- excluded.push({ toolName: tool.toolName, reason: 'category-not-included' });
276
- return false;
277
- }
278
- if (excludeCategories.has(tool.category)) {
279
- excluded.push({ toolName: tool.toolName, reason: 'phase-category-excluded' });
280
- return false;
281
- }
282
- return true;
283
- });
284
- const forceExclude = new Set(input.policy?.forceExclude ?? []);
285
- candidates = candidates.filter((tool) => {
286
- if (!forceExclude.has(tool.toolName))
287
- return true;
288
- excluded.push({ toolName: tool.toolName, reason: 'force-excluded' });
289
- return false;
290
- });
291
- for (const forcedToolName of input.policy?.forceInclude ?? []) {
292
- const forced = indexByToolName.get(forcedToolName);
293
- if (!forced) {
294
- excluded.push({ toolName: forcedToolName, reason: 'not-in-profile' });
295
- continue;
296
- }
297
- candidates.push(forced);
298
- }
299
- candidates = [...new Map(candidates.map((tool) => [tool.toolName, tool])).values()];
300
- const selected = [];
301
- const foundationalIds = new Set(policy.defaults.foundationalOperationIds);
302
- const foundational = candidates.filter((tool) => foundationalIds.has(tool.operationId));
303
- for (const tool of foundational) {
304
- if (selected.length >= minReadTools || selected.length >= maxTools)
305
- break;
306
- selected.push(tool);
234
+ });
307
235
  }
308
- const remaining = stableSortByPhasePriority(candidates.filter((tool) => !selected.some((entry) => entry.toolName === tool.toolName)), phasePolicy.priority);
309
- for (const tool of remaining) {
310
- if (selected.length >= maxTools) {
311
- excluded.push({ toolName: tool.toolName, reason: 'budget-trim' });
312
- continue;
236
+ else {
237
+ // mode='all': original behavior filter by groups
238
+ const alwaysInclude = new Set(policy.defaults.alwaysInclude ?? ['core']);
239
+ let groups;
240
+ if (input.groups) {
241
+ groups = new Set([...input.groups, ...alwaysInclude]);
313
242
  }
314
- selected.push(tool);
243
+ else {
244
+ groups = new Set(policy.groups);
245
+ }
246
+ selected = catalog.tools.filter((tool) => groups.has(tool.category));
315
247
  }
248
+ // Build provider-formatted tools from the provider bundle
316
249
  const bundle = await loadProviderBundle(input.provider);
317
- const providerTools = Array.isArray(bundle.profiles[profile]) ? bundle.profiles[profile] : [];
250
+ const providerTools = Array.isArray(bundle.tools) ? bundle.tools : [];
318
251
  const providerIndex = new Map(providerTools
319
252
  .filter((tool) => isRecord(tool))
320
253
  .map((tool) => [extractProviderToolName(tool), tool])
@@ -322,6 +255,14 @@ export async function chooseTools(input) {
322
255
  const selectedProviderTools = selected
323
256
  .map((tool) => providerIndex.get(tool.toolName))
324
257
  .filter((tool) => Boolean(tool));
258
+ // Append discover_tools if requested
259
+ if (includeDiscover) {
260
+ const discoverTool = providerIndex.get('discover_tools');
261
+ if (discoverTool) {
262
+ selectedProviderTools.push(discoverTool);
263
+ }
264
+ }
265
+ const resolvedGroups = mode === 'essential' ? (input.groups ?? []) : (input.groups ?? policy.groups);
325
266
  return {
326
267
  tools: selectedProviderTools,
327
268
  selected: selected.map((tool) => ({
@@ -329,17 +270,12 @@ export async function chooseTools(input) {
329
270
  toolName: tool.toolName,
330
271
  category: tool.category,
331
272
  mutates: tool.mutates,
332
- profile: tool.profile,
333
273
  })),
334
- excluded,
335
- selectionMeta: {
336
- profile,
337
- phase,
338
- maxTools,
339
- minReadTools,
340
- selectedCount: selected.length,
341
- decisionVersion: policy.defaults.chooserDecisionVersion,
274
+ meta: {
342
275
  provider: input.provider,
276
+ mode,
277
+ groups: [...resolvedGroups],
278
+ selectedCount: selectedProviderTools.length,
343
279
  },
344
280
  };
345
281
  }
@@ -354,7 +290,12 @@ export async function dispatchSuperDocTool(client, toolName, args = {}, invokeOp
354
290
  if (!isRecord(args)) {
355
291
  invalidArgument(`Tool arguments for ${toolName} must be an object.`);
356
292
  }
357
- validateDispatchArgs(operationId, args);
293
+ // Strip doc/sessionId — the SDK client manages session targeting after doc.open().
294
+ // Models fill these in because the tool schemas expose them, but passing them
295
+ // alongside an active session causes "stateless input.doc cannot be combined
296
+ // with a session target" errors.
297
+ const { doc: _doc, sessionId: _sid, ...cleanArgs } = args;
298
+ validateDispatchArgs(operationId, cleanArgs);
358
299
  const method = resolveDocApiMethod(client, operationId);
359
- return method(args, invokeOptions);
300
+ return method(cleanArgs, invokeOptions);
360
301
  }
package/package.json CHANGED
@@ -1,40 +1,41 @@
1
1
  {
2
2
  "name": "@superdoc-dev/sdk",
3
- "version": "1.0.0-alpha.4",
3
+ "version": "1.0.0-alpha.41",
4
4
  "private": false,
5
5
  "type": "module",
6
- "main": "./dist/index.js",
6
+ "main": "./dist/index.cjs",
7
7
  "module": "./dist/index.js",
8
8
  "types": "./dist/index.d.ts",
9
9
  "exports": {
10
10
  ".": {
11
- "import": {
12
- "types": "./dist/index.d.ts",
13
- "default": "./dist/index.js"
14
- }
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
15
14
  }
16
15
  },
17
16
  "files": [
18
17
  "dist",
18
+ "skills",
19
19
  "tools"
20
20
  ],
21
- "optionalDependencies": {
22
- "@superdoc-dev/sdk-darwin-arm64": "1.0.0-alpha.4",
23
- "@superdoc-dev/sdk-darwin-x64": "1.0.0-alpha.4",
24
- "@superdoc-dev/sdk-linux-arm64": "1.0.0-alpha.4",
25
- "@superdoc-dev/sdk-linux-x64": "1.0.0-alpha.4",
26
- "@superdoc-dev/sdk-windows-x64": "1.0.0-alpha.4"
27
- },
28
21
  "devDependencies": {
29
22
  "@types/bun": "^1.3.8",
30
23
  "@types/node": "22.19.2",
24
+ "rollup": "^4.31.0",
31
25
  "typescript": "^5.9.2"
32
26
  },
27
+ "optionalDependencies": {
28
+ "@superdoc-dev/sdk-darwin-arm64": "1.0.0-alpha.41",
29
+ "@superdoc-dev/sdk-linux-x64": "1.0.0-alpha.41",
30
+ "@superdoc-dev/sdk-darwin-x64": "1.0.0-alpha.41",
31
+ "@superdoc-dev/sdk-windows-x64": "1.0.0-alpha.41",
32
+ "@superdoc-dev/sdk-linux-arm64": "1.0.0-alpha.41"
33
+ },
33
34
  "publishConfig": {
34
35
  "access": "public"
35
36
  },
36
37
  "scripts": {
37
- "build": "tsc",
38
+ "build": "tsc && rollup -c rollup.cjs.config.mjs",
38
39
  "typecheck": "tsc --noEmit"
39
40
  }
40
41
  }
@@ -0,0 +1,31 @@
1
+ # Editing DOCX Documents with SuperDoc SDK
2
+
3
+ You are a document editing assistant using the SuperDoc SDK. You have access to tools
4
+ that let you open, read, search, and modify `.docx` files programmatically.
5
+
6
+ ## Workflow
7
+
8
+ 1. **Open** the document with `doc.open`
9
+ 2. **Inspect** it with `doc.info` to understand structure
10
+ 3. **Find** content with `doc.find` using text search or node type queries
11
+ 4. **Modify** content using `doc.insert`, `doc.replace`, `doc.delete`, or formatting operations
12
+ 5. **Save** changes with `doc.save`
13
+ 6. **Close** when done with `doc.close`
14
+
15
+ ## Key Operations
16
+
17
+ - `doc.find` — Search by text pattern, node type, or structured query
18
+ - `doc.getNode` — Get a specific node by address
19
+ - `doc.insert` — Insert text at a position
20
+ - `doc.replace` — Replace content at a position
21
+ - `doc.delete` — Delete content at a position
22
+ - `doc.format.*` — Apply bold, italic, underline, strikethrough
23
+ - `doc.comments.*` — Add, edit, resolve, remove comments
24
+ - `doc.trackChanges.*` — Accept/reject tracked changes
25
+
26
+ ## Best Practices
27
+
28
+ - Always open before operating, save when done
29
+ - Use `doc.find` to locate content before modifying
30
+ - Use `doc.info` to check document capabilities
31
+ - Handle errors gracefully — operations may fail if targets are invalid