@slatesvideo/shared 0.6.3 → 0.6.5

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 (79) hide show
  1. package/dist/api-url.d.ts +11 -0
  2. package/dist/api-url.js +11 -0
  3. package/dist/auth.d.ts +13 -1
  4. package/dist/auth.js +9 -5
  5. package/dist/clients/cloud.d.ts +3 -0
  6. package/dist/clients/cloud.js +34 -3
  7. package/dist/clients/desktop.js +3 -0
  8. package/dist/index.d.ts +7 -2
  9. package/dist/index.js +20 -2
  10. package/dist/manual/content.d.ts +2 -0
  11. package/dist/manual/content.js +3 -0
  12. package/dist/manual/index.d.ts +5 -0
  13. package/dist/manual/index.js +20 -0
  14. package/dist/operations/index.d.ts +253 -30
  15. package/dist/operations/index.js +1387 -141
  16. package/dist/operations/surface.d.ts +69 -0
  17. package/dist/operations/surface.js +227 -0
  18. package/dist/prompts/agent-doctrine.js +8 -0
  19. package/dist/prompts/asset-label.d.ts +23 -0
  20. package/dist/prompts/asset-label.js +70 -0
  21. package/dist/prompts/banned-tokens.d.ts +15 -3
  22. package/dist/prompts/banned-tokens.js +76 -9
  23. package/dist/prompts/character-sheet.d.ts +0 -2
  24. package/dist/prompts/character-sheet.js +0 -2
  25. package/dist/prompts/craft-cards.d.ts +20 -0
  26. package/dist/prompts/craft-cards.js +82 -0
  27. package/dist/prompts/environment-sheet.js +16 -0
  28. package/dist/prompts/index.d.ts +1 -0
  29. package/dist/prompts/index.js +4 -0
  30. package/dist/prompts/model-capabilities.d.ts +52 -0
  31. package/dist/prompts/model-capabilities.js +42 -0
  32. package/dist/prompts/model-facts.d.ts +0 -4
  33. package/dist/prompts/model-facts.js +8 -4
  34. package/dist/prompts/partials.generated.js +2 -1
  35. package/dist/prompts/prompting-tips.d.ts +1 -1
  36. package/dist/prompts/prompting-tips.js +58 -0
  37. package/dist/prompts/reference-composer.d.ts +36 -7
  38. package/dist/prompts/reference-composer.js +75 -20
  39. package/dist/prompts/reference-rules.d.ts +15 -26
  40. package/dist/prompts/reference-rules.js +15 -93
  41. package/dist/prompts/shot-grammar.d.ts +154 -0
  42. package/dist/prompts/shot-grammar.js +184 -0
  43. package/dist/prompts/shot-spec.d.ts +278 -0
  44. package/dist/prompts/shot-spec.js +319 -0
  45. package/dist/skills/content.js +25 -23
  46. package/exports/slates-prompt-builder/generated/reference-content-policy.md +6 -0
  47. package/exports/slates-prompt-builder/generated/reference-kling.md +22 -0
  48. package/exports/slates-prompt-builder/generated/reference-nano-banana.md +17 -0
  49. package/exports/slates-prompt-builder/generated/reference-seedance.md +17 -0
  50. package/exports/slates-prompt-builder/generated/slates-prompt-builder-manifest.json +15 -15
  51. package/exports/slates-prompt-builder/generated/slates-prompt-builder.skill +0 -0
  52. package/package.json +83 -73
  53. package/skills/_partials/decision-log.md +5 -4
  54. package/skills/_partials/thresholds.md +19 -0
  55. package/skills/slates-content-policy.md +15 -1
  56. package/skills/slates-cost-discipline.md +26 -4
  57. package/skills/slates-model-selection.md +4 -3
  58. package/skills/slates-one-prompt-film.md +20 -12
  59. package/skills/slates-project-organization.md +1 -1
  60. package/skills/slates-prompting-elevenlabs.md +61 -2
  61. package/skills/slates-prompting-flux-2-max.md +39 -0
  62. package/skills/slates-prompting-gpt-image-2.md +109 -70
  63. package/skills/slates-prompting-inworld-tts.md +174 -0
  64. package/skills/slates-prompting-kling-v3.md +39 -0
  65. package/skills/slates-prompting-lip-sync.md +38 -0
  66. package/skills/slates-prompting-ltx-2-5.md +38 -0
  67. package/skills/slates-prompting-minimax-h3.md +39 -0
  68. package/skills/slates-prompting-motion-transfer.md +38 -0
  69. package/skills/slates-prompting-nano-banana-2.md +26 -0
  70. package/skills/slates-prompting-omni-flash.md +41 -0
  71. package/skills/slates-prompting-seed-audio.md +39 -1
  72. package/skills/slates-prompting-seedance-2-5.md +38 -0
  73. package/skills/slates-prompting-seedance.md +26 -0
  74. package/skills/slates-prompting-seedream-5-lite.md +38 -0
  75. package/skills/slates-prompting-veo-3.md +39 -0
  76. package/skills/slates-shot-variety.md +53 -0
  77. package/skills/slates-storyboard-from-script.md +31 -15
  78. package/skills/slates-style-prompting.md +1 -1
  79. package/skills/slates-vision-feedback-loop.md +1 -1
@@ -0,0 +1,20 @@
1
+ import { APP_MANUAL } from './content.js';
2
+ export { APP_MANUAL };
3
+ /** Return whole heading sections, never a truncated sentence or invented UI step. */
4
+ export function appManualSections(query) {
5
+ if (!query?.trim())
6
+ return APP_MANUAL;
7
+ const terms = query.toLowerCase().match(/[\p{L}\p{N}]+/gu) ?? [];
8
+ const sections = APP_MANUAL.split(/(?=^#{1,6} )/m);
9
+ const ranked = sections.map((text, index) => {
10
+ const lower = text.toLowerCase();
11
+ const heading = lower.split('\n', 1)[0];
12
+ const score = terms.reduce((sum, term) => sum + (heading.includes(term) ? 4 : lower.includes(term) ? 1 : 0), 0);
13
+ return { text, index, score };
14
+ }).filter((s) => s.score > 0).sort((a, b) => b.score - a.score || a.index - b.index);
15
+ if (!ranked.length)
16
+ return 'No matching manual section. Available headings:\n' + sections
17
+ .map((s) => s.split('\n', 1)[0]).filter((s) => s.startsWith('#')).join('\n');
18
+ return ranked.slice(0, 5).map((s) => s.text.trim()).join('\n\n');
19
+ }
20
+ //# sourceMappingURL=index.js.map
@@ -2,11 +2,30 @@ import { z } from 'zod';
2
2
  import { SlatesCloudClient } from '../clients/cloud.js';
3
3
  import { SlatesDesktopClient } from '../clients/desktop.js';
4
4
  import { type AspectRatio, type VideoResolution } from '../prompts/model-capabilities.js';
5
+ import { type OrderedAttachmentRole, type ShotParams } from '../prompts/shot-spec.js';
5
6
  export interface OperationContext {
6
7
  cloud: () => SlatesCloudClient;
7
8
  desktop: () => SlatesDesktopClient;
9
+ /**
10
+ * Cancellation, propagated from the caller.
11
+ *
12
+ * 🚨 THIS IS WHAT MAKES "STOP" MEAN STOP. Escape in the desktop Studio Agent
13
+ * aborted the brain stream and marked the *remaining* tool calls cancelled,
14
+ * but the op already running got no signal at all — so a sequential batch
15
+ * (`slates_generate_from_shots`, the largest spender on the surface) kept
16
+ * firing generations after the user had cancelled. Ops that loop over items,
17
+ * or block on a long provider call, check it; everything else may ignore it.
18
+ *
19
+ * Optional so an older caller that does not pass one still type-checks.
20
+ */
21
+ signal?: AbortSignal;
8
22
  }
9
23
  export declare function defaultContext(): OperationContext;
24
+ /** Thrown by an op that noticed `ctx.signal` had aborted mid-work. */
25
+ export declare class OperationCancelledError extends Error {
26
+ code: string;
27
+ constructor(detail?: string);
28
+ }
10
29
  export interface OperationResult {
11
30
  text: string;
12
31
  images?: Array<{
@@ -20,9 +39,118 @@ export interface Operation<I> {
20
39
  description: string;
21
40
  input: z.ZodType<I>;
22
41
  run: (input: I, ctx: OperationContext) => Promise<OperationResult>;
42
+ /**
43
+ * This op causes a provider call the user pays for.
44
+ *
45
+ * 🚨 IT IS THE DESKTOP'S CONSENT GATE, DECLARED WHERE THE OP IS WRITTEN.
46
+ * `slate/src/main/studio-agent/loop.ts` refuses a billable name until
47
+ * `present_plan` has been approved, and refreshes the balance-derived spend
48
+ * after each one so the deviation pause can fire. That list used to live only
49
+ * in the desktop, one repo away from the op it gated — and both
50
+ * `slates_generate_audio` and `slates_generate_from_shots` shipped without an
51
+ * entry, so the in-app agent could spend on either with no approved plan and
52
+ * no ledger entry. Set it HERE, beside the description, and the desktop takes
53
+ * the union of this and its own list (union, so an older published package can
54
+ * only ever gate MORE, never less).
55
+ *
56
+ * Set it on anything that spends INDIRECTLY too —
57
+ * `slates_generate_from_shots` fires N generations of its own.
58
+ *
59
+ * NOT part of the tool schema: it never reaches the model, so it costs no
60
+ * prefix bytes.
61
+ */
62
+ billable?: boolean;
63
+ /**
64
+ * MCP tool annotations (spec 2025-06-18), emitted in ListTools.
65
+ *
66
+ * 🚨 THIS IS WHAT LETS A HOST TELL A READ FROM A DELETE. Without them a
67
+ * Claude Desktop or Cursor user is prompted for `slates_list_assets` exactly
68
+ * the way they are prompted for `slates_delete_project`, and the destructive
69
+ * ops get no extra warning — so every prompt looks the same and the user
70
+ * learns to click through all of them.
71
+ *
72
+ * Never hand-set: `annotate()` derives all four from the op id below, and
73
+ * `scripts/agent-surface-lockstep-check.mjs` re-derives them INDEPENDENTLY
74
+ * from the op's own transport verbs. A `readOnlyHint` on an op whose `run`
75
+ * body posts is a lie that lets a host auto-approve a mutation, so the check
76
+ * has to be able to catch it.
77
+ */
78
+ annotations?: OperationAnnotations;
79
+ /**
80
+ * Which tier of the desktop tool surface this op belongs to.
81
+ *
82
+ * `core` is sent on every Studio Agent turn; `extended` is deferred behind
83
+ * `slates_load_tools` and appended to the tool list for the rest of the run
84
+ * once a group loads. The MCP server registers everything as before — hosts
85
+ * there do their own deferral (Claude Code defers stdio tool schemas through
86
+ * its tool search) and a stdio server has no run to append to.
87
+ *
88
+ * Defaults to `core` when absent, so a new op is visible until someone
89
+ * deliberately defers it.
90
+ */
91
+ tier?: OperationTier;
92
+ /** The `slates_load_tools` group this op arrives in. Required on `extended`. */
93
+ group?: OperationGroup;
94
+ }
95
+ /** MCP tool annotations. All four are declared on every op — a missing hint is
96
+ * indistinguishable from `false` to a host, which is the wrong default for
97
+ * `destructiveHint`. */
98
+ export interface OperationAnnotations {
99
+ readOnlyHint: boolean;
100
+ destructiveHint: boolean;
101
+ idempotentHint: boolean;
102
+ openWorldHint: boolean;
23
103
  }
104
+ export type OperationTier = 'core' | 'extended';
105
+ export type OperationGroup = 'library' | 'timeline' | 'admin' | 'blender';
106
+ export declare const CONFIRM_CREDITS = 17;
107
+ /**
108
+ * The desktop deviation guard's ceiling multiplier: the Studio Agent pauses and
109
+ * re-asks when projected generation spend exceeds the approved ledger by more
110
+ * than this factor.
111
+ *
112
+ * 🚨 EXPORTED BECAUSE THE NUMBER IS QUOTED DOWNSTREAM. `slates-cost-discipline`
113
+ * told the agent the threshold was 25% while `loop.ts` paused at 20% — a skill
114
+ * contradicting the code on the one number that decides whether a run stops.
115
+ * The skill now renders it from here through `_partials/thresholds.md`; the
116
+ * desktop loop imports it instead of declaring its own.
117
+ */
118
+ export declare const DEVIATION_FACTOR = 1.2;
119
+ /**
120
+ * Per-surface bounds and defaults.
121
+ *
122
+ * 🚨 THESE FOUR NUMBERS PER SURFACE LIVE IN THREE REPOS. A change is a
123
+ * three-site edit, every time:
124
+ * 1. HERE (`audioCostKey`, the agent's pre-flight quote)
125
+ * 2. `slate/src/shared/pricing.ts` → MODEL_REGISTRY `audio.durationSeconds`
126
+ * (min/max/default), read by `clampAudioDuration` + `audioCreditKey`
127
+ * 3. `slates-api/src/lib/audio-keys.ts` → the server's fail-closed bounds
128
+ * `slates-api/scripts/pricing-consistency-check.mjs` §4 asserts 1 and 2 agree
129
+ * at EVERY value including out-of-range ones; the gate check covers 3.
130
+ *
131
+ * The MINs used to be missing here, and the clamp floor was a hardcoded 1. That
132
+ * made `slates_estimate_generation_cost({model:'seed-audio', duration:2})`
133
+ * quote a real `seed-audio-2s` price for a generation the desktop would bill as
134
+ * 3s and the proxy would REJECT outright. Same for an omitted duration, which
135
+ * quoted `seed-audio-1s` against the desktop's `seed-audio-15s`.
136
+ */
137
+ export declare const SEED_AUDIO_MIN_SECONDS = 3;
138
+ export declare const SEED_AUDIO_MAX_SECONDS = 120;
139
+ export declare const SEED_AUDIO_DEFAULT_SECONDS = 15;
140
+ export declare const ELEVEN_SFX_MIN_SECONDS = 1;
141
+ export declare const ELEVEN_SFX_MAX_SECONDS = 22;
142
+ export declare const ELEVEN_SFX_DEFAULT_SECONDS = 4;
143
+ export declare const TTS_MODEL: "inworld-tts-2";
144
+ export declare const TTS_BUCKET_CHARS = 250;
145
+ export declare const TTS_MAX_CHARACTERS: number;
146
+ export declare const TTS_BUCKET_COUNT: number;
147
+ /** The seat's cloning spec — reference-clip bounds, the design-prompt bounds
148
+ * and the workspace-wide clone rate — read from the SSOT for the same reason
149
+ * as the cap: every number in it was MEASURED and lives in exactly one row. */
150
+ export declare const TTS_VOICE_CLONE: import("../prompts/model-capabilities.js").VoiceCloneCapability;
24
151
  export declare const getWorkspaceState: Operation<{
25
152
  projectId?: string;
153
+ limit?: number;
26
154
  }>;
27
155
  export declare const getMe: Operation<Record<string, never>>;
28
156
  export declare const getCreditBalance: Operation<Record<string, never>>;
@@ -39,6 +167,9 @@ export declare const estimateGenerationCost: Operation<{
39
167
  model: string;
40
168
  quantity?: number;
41
169
  duration?: number;
170
+ /** inworld-tts-2 only — the character count of the text, which is what it
171
+ * bills on. That surface has no duration dimension at all. */
172
+ characters?: number;
42
173
  /** The FULL union — the runtime Zod enum is generated from MODEL_CAPABILITIES
43
174
  * and `assertVideoCapabilities` is the per-model narrowing authority. */
44
175
  videoResolution?: VideoResolution;
@@ -227,36 +358,14 @@ export declare function seedanceEditCostKey(input: {
227
358
  seedanceFace?: boolean;
228
359
  seedanceRealFace?: boolean;
229
360
  }): string;
230
- export declare const AUDIO_MODELS: readonly ["seed-audio", "eleven-sfx"];
361
+ export declare const AUDIO_MODELS: readonly ["seed-audio", "eleven-sfx", "inworld-tts-2"];
231
362
  export type AudioModel = (typeof AUDIO_MODELS)[number];
232
- /**
233
- * Per-surface bounds and defaults.
234
- *
235
- * 🚨 THESE FOUR NUMBERS PER SURFACE LIVE IN THREE REPOS. A change is a
236
- * three-site edit, every time:
237
- * 1. HERE (`audioCostKey`, the agent's pre-flight quote)
238
- * 2. `slate/src/shared/pricing.ts` → MODEL_REGISTRY `audio.durationSeconds`
239
- * (min/max/default), read by `clampAudioDuration` + `audioCreditKey`
240
- * 3. `slates-api/src/lib/audio-keys.ts` → the server's fail-closed bounds
241
- * `slates-api/scripts/pricing-consistency-check.mjs` §4 asserts 1 and 2 agree
242
- * at EVERY value including out-of-range ones; the gate check covers 3.
243
- *
244
- * The MINs used to be missing here, and the clamp floor was a hardcoded 1. That
245
- * made `slates_estimate_generation_cost({model:'seed-audio', duration:2})`
246
- * quote a real `seed-audio-2s` price for a generation the desktop would bill as
247
- * 3s and the proxy would REJECT outright. Same for an omitted duration, which
248
- * quoted `seed-audio-1s` against the desktop's `seed-audio-15s`.
249
- */
250
- export declare const SEED_AUDIO_MIN_SECONDS = 3;
251
- export declare const SEED_AUDIO_MAX_SECONDS = 120;
252
- export declare const SEED_AUDIO_DEFAULT_SECONDS = 15;
253
- export declare const ELEVEN_SFX_MIN_SECONDS = 1;
254
- export declare const ELEVEN_SFX_MAX_SECONDS = 22;
255
- export declare const ELEVEN_SFX_DEFAULT_SECONDS = 4;
256
363
  export declare function audioCostKey(input: {
257
364
  model: AudioModel;
258
365
  /** seed-audio + eleven-sfx: the REQUESTED duration in seconds (ceiled). */
259
366
  durationSeconds?: number;
367
+ /** inworld-tts-2 ONLY: the character count of the text being spoken. */
368
+ characters?: number;
260
369
  }): string;
261
370
  export declare const generateVideo: Operation<{
262
371
  prompt: string;
@@ -288,12 +397,27 @@ export declare const generateVideo: Operation<{
288
397
  background?: boolean;
289
398
  confirm?: boolean;
290
399
  }>;
400
+ /**
401
+ * AGENT PARITY for the voice picker. The desktop browses stock voices by
402
+ * gender, accent and age and plays each one; until this op the agent could
403
+ * only pass a `voiceId` it had no way to discover. Disk reads on the desktop,
404
+ * never a vendor call — browsing is free on every surface.
405
+ */
406
+ export declare const listVoices: Operation<{
407
+ gender?: string;
408
+ accent?: string;
409
+ age?: string;
410
+ query?: string;
411
+ }>;
291
412
  export declare const generateAudio: Operation<{
292
413
  projectId: string;
293
414
  model: AudioModel;
294
415
  prompt: string;
295
416
  durationSeconds?: number;
296
417
  voice?: string;
418
+ voiceId?: string;
419
+ voiceReferenceAssetId?: string;
420
+ voiceDescription?: string;
297
421
  speed?: number;
298
422
  volume?: number;
299
423
  pitch?: number;
@@ -447,6 +571,7 @@ export declare const updateCharacter: Operation<{
447
571
  name?: string;
448
572
  description?: string;
449
573
  style?: string;
574
+ voiceAssetId?: string | null;
450
575
  }>;
451
576
  export declare const deleteCharacter: Operation<{
452
577
  characterId: string;
@@ -505,8 +630,6 @@ export declare const updateFrame: Operation<{
505
630
  assetId?: string | null;
506
631
  sceneId?: string | null;
507
632
  position?: number;
508
- frameType?: 'first' | 'last' | 'ingredient' | null;
509
- motionPrompt?: string | null;
510
633
  }>;
511
634
  /**
512
635
  * Batch form of `slates_update_frame`.
@@ -529,15 +652,115 @@ export declare const batchUpdateFrames: Operation<{
529
652
  assetId?: string | null;
530
653
  sceneId?: string | null;
531
654
  position?: number;
532
- frameType?: 'first' | 'last' | 'ingredient' | null;
533
- motionPrompt?: string | null;
534
655
  }[];
535
656
  }>;
536
657
  export declare const deleteFrame: Operation<{
537
658
  frameId: string;
538
659
  }>;
660
+ interface ShotOpScript {
661
+ speaker?: string | null;
662
+ line?: string | null;
663
+ delivery?: string | null;
664
+ action?: string | null;
665
+ prop?: string | null;
666
+ shotSize?: string | null;
667
+ camera?: string | null;
668
+ continues?: boolean;
669
+ }
670
+ interface ShotOpRefs {
671
+ refs?: Partial<Record<OrderedAttachmentRole, string[]>>;
672
+ firstFrameAssetId?: string;
673
+ lastFrameAssetId?: string;
674
+ audioRefSpokenText?: string[];
675
+ characterIds?: string[];
676
+ environmentIds?: string[];
677
+ styleIds?: string[];
678
+ }
679
+ type ShotOpParams = Pick<ShotParams, 'aspectRatio' | 'duration' | 'videoResolution' | 'imageResolution' | 'gptQuality' | 'imageQuantity' | 'negativePrompt' | 'sound' | 'seedanceFace' | 'audioDurationSeconds' | 'voiceId' | 'voiceReferenceAssetId' | 'voiceDescription'> & {
680
+ aspectRatio?: AspectRatio;
681
+ videoResolution?: VideoResolution;
682
+ imageResolution?: '1k' | '2k' | '3k' | '4k';
683
+ };
684
+ export declare const createShot: Operation<ShotOpRefs & ShotOpScript & {
685
+ projectId: string;
686
+ name?: string;
687
+ prompt: string;
688
+ model?: string;
689
+ params?: ShotOpParams;
690
+ frameId?: string;
691
+ sceneId?: string;
692
+ }>;
693
+ export declare const updateShot: Operation<ShotOpRefs & ShotOpScript & {
694
+ shotId: string;
695
+ projectId: string;
696
+ name?: string;
697
+ prompt?: string;
698
+ model?: string;
699
+ params?: ShotOpParams;
700
+ attachFrameId?: string;
701
+ detachFrameId?: string;
702
+ posterAssetId?: string | null;
703
+ }>;
704
+ export declare const duplicateShot: Operation<{
705
+ shotId: string;
706
+ name?: string;
707
+ prompt?: string;
708
+ model?: string;
709
+ params?: ShotOpParams;
710
+ frameId?: string | null;
711
+ }>;
712
+ export declare const listShots: Operation<{
713
+ projectId: string;
714
+ storyboardId?: string;
715
+ frameId?: string;
716
+ }>;
717
+ export declare const getShot: Operation<{
718
+ shotId: string;
719
+ }>;
720
+ /**
721
+ * SPLIT and MERGE — the chop decision, and the only two cross-row operations on
722
+ * this surface.
723
+ *
724
+ * 🔑 THIS IS THE EXECUTIVE CALL, AND IT IS WHY THEY ARE OPS. *"Sometimes you
725
+ * might be using more dialogue in one single 30-second generation. Sometimes it
726
+ * might just be a 4-second generation of one line."* Merging five lines into
727
+ * one long take or splitting them into five short ones changes the rhythm AND
728
+ * the price, and the agent has to be able to re-chop what it wrote.
729
+ *
730
+ * 🚨 NEITHER EDITS TEXT AS A SIDE EFFECT. Split moves the text after a caret
731
+ * the caller placed; merge joins two texts at their boundary. Nothing else in
732
+ * either row is rewritten. That property is what keeps a finished script
733
+ * finished, and it is the acceptance test for anything added here later.
734
+ */
735
+ export declare const splitShot: Operation<{
736
+ shotId: string;
737
+ caret?: number;
738
+ }>;
739
+ export declare const mergeShots: Operation<{
740
+ firstId: string;
741
+ secondId: string;
742
+ }>;
743
+ export declare const generateFromShots: Operation<{
744
+ shotIds: string[];
745
+ confirm?: boolean;
746
+ }>;
539
747
  export declare const getPromptingGuide: Operation<{
540
748
  topic: string;
749
+ depth?: 'card' | 'full';
750
+ query?: string;
751
+ }>;
752
+ /**
753
+ * The one op that changes what OTHER ops are visible.
754
+ *
755
+ * 🚨 IT EXISTS BECAUSE THE SURFACE IS 112 KB AND EVERY TURN PAYS FOR ALL OF IT.
756
+ * The desktop Studio Agent sends `core` plus this; a group arrives when the
757
+ * work needs it and stays for the rest of the run. On the MCP surface every op
758
+ * is registered up front (a stdio server has no run to append to), so this
759
+ * returns the same definitions as a plain listing — useful either way, since
760
+ * it is also how an agent asks "what else can you do".
761
+ */
762
+ export declare const loadTools: Operation<{
763
+ group: OperationGroup;
541
764
  }>;
542
765
  export declare const blenderStatus: Operation<Record<string, never>>;
543
766
  export declare const blenderExecute: Operation<{
@@ -563,5 +786,5 @@ export declare const blenderRenderBlocking: Operation<{
563
786
  basename?: string;
564
787
  }>;
565
788
  export declare const ALL_OPERATIONS: ReadonlyArray<Operation<unknown>>;
566
- export {};
789
+ export { toolDefinitions, toolDefinition, groupFor, tierFor, OPERATION_GROUPS, GROUP_SUMMARY, type ToolDefinition } from './surface.js';
567
790
  //# sourceMappingURL=index.d.ts.map