narraleaf-studio 1.4.5 → 1.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.
package/dist/_api.d.ts CHANGED
@@ -78,6 +78,104 @@ type FileDetails = {
78
78
  type TextEncodingId = "utf8" | "utf8bom" | "utf16le" | "utf16be" | "gbk" | "gb18030" | "big5" | "shiftjis" | "euckr" | "windows1252" | "iso88591";
79
79
  type PersistedTextEol = "lf" | "crlf";
80
80
  type FsTextEncoding = BufferEncoding | TextEncodingId;
81
+ type AgentErrorCode =
82
+ /** The arguments do not fit the tool's schema. */
83
+ "invalid_args"
84
+ /** No tool by that name. */
85
+ | "unknown_tool"
86
+ /** No workspace window has the project open, or more than one does and none was named. */
87
+ | "no_workspace"
88
+ /** The author has not switched on write access for agents. */
89
+ | "writes_disabled"
90
+ /** The author paused the agent from the status bar. */
91
+ | "paused"
92
+ /** The project is frozen for writing (a version-control operation, a recovery, a reload). */
93
+ | "frozen"
94
+ /** A Team live session is running; agent writes would race the room. */
95
+ | "live_session"
96
+ /** The page or scene changed since the agent read it - read it again and redo the edit. */
97
+ | "stale_revision"
98
+ /** The source did not compile, or the check found something at error severity. Nothing was written. */
99
+ | "check_failed"
100
+ /** A surface, scene, element, asset or character the call names does not exist. */
101
+ | "not_found"
102
+ /**
103
+ * A file path outside the directories the author allowed agents to read, or a folder agents are
104
+ * never handed at all - to read from or to write into (Studio's own folders, the home folder
105
+ * itself, a file-system root).
106
+ */
107
+ | "path_not_allowed"
108
+ /** The project is not trusted, so its code may not run (play-test, build). */
109
+ | "untrusted"
110
+ /** The call is valid but the operation is not possible in this state. */
111
+ | "unavailable"
112
+ /** Something broke that is not the agent's fault. */
113
+ | "internal";
114
+ type AgentJsonSchema = {
115
+ type?: "object" | "string" | "number" | "integer" | "boolean" | "array" | "null";
116
+ description?: string;
117
+ properties?: Record<string, AgentJsonSchema>;
118
+ required?: string[];
119
+ items?: AgentJsonSchema;
120
+ enum?: readonly (string | number)[];
121
+ additionalProperties?: boolean | AgentJsonSchema;
122
+ minimum?: number;
123
+ maximum?: number;
124
+ default?: unknown;
125
+ oneOf?: AgentJsonSchema[];
126
+ };
127
+ /** Refusal codes a plugin may answer with. The gate's own codes (paused, frozen…) are Studio's alone. */
128
+ export type PluginAgentToolErrorCode = Extract<AgentErrorCode, "invalid_args" | "not_found" | "check_failed" | "stale_revision" | "unavailable">;
129
+ /** An answer: text the model reads, optionally the same facts as data, optionally one picture. */
130
+ export type PluginAgentToolAnswer = {
131
+ text: string;
132
+ /** Sent as MCP `structuredContent`. Plain JSON; dropped when larger than 60 000 characters. */
133
+ data?: Record<string, unknown>;
134
+ /** One PNG or JPEG, base64 without a `data:` prefix. */
135
+ image?: {
136
+ mimeType: "image/png" | "image/jpeg";
137
+ data: string;
138
+ };
139
+ };
140
+ /** A refusal the agent can act on: what is wrong, and what to do about it. */
141
+ export type PluginAgentToolRefusal = {
142
+ error: {
143
+ code?: PluginAgentToolErrorCode;
144
+ message: string;
145
+ hint?: string;
146
+ };
147
+ };
148
+ /** A bare string is a text answer. */
149
+ export type PluginAgentToolResult = string | PluginAgentToolAnswer | PluginAgentToolRefusal;
150
+ /** What a plugin tool's handler is given besides its arguments. Deliberately nothing that reaches Studio. */
151
+ export type PluginAgentToolContext = {
152
+ /** The name the MCP client gave (`clientInfo.name`), when it gave one. */
153
+ readonly clientName: string | null;
154
+ };
155
+ /** The JSON-schema subset a plugin tool's arguments are described in; see {@link checkAgentPluginToolSchema}. */
156
+ export type PluginAgentJsonSchema = AgentJsonSchema;
157
+ /** One tool a plugin offers AI agents connected to Studio. */
158
+ export type PluginAgentToolDef = {
159
+ /** `<pluginId>.<tool>`, `[a-z0-9_.-]`, declared in `contributes.agentTools`. */
160
+ name: string;
161
+ /** Short, shown in the author's Agent log. At most 80 characters. */
162
+ title: string;
163
+ /** Written for the model: what it is for, when to use it, the mistake to avoid. At most 1200 characters. */
164
+ description: string;
165
+ /** The arguments, checked before the handler runs. Studio adds `project` itself. */
166
+ inputSchema: PluginAgentJsonSchema & {
167
+ type: "object";
168
+ };
169
+ /**
170
+ * Changes the project. Marked `true`: refused unless the author allowed agent writes, and while
171
+ * paused, frozen or in a live session; while it runs, every `writeJson` is captured into one step
172
+ * of undo. Marked `false`: none of that gating applies, and the only thing refused while it runs
173
+ * is `services.storage.writeJson` - the host cannot see the plugin's other routes to the project,
174
+ * so a tool that changes it by any of them must be marked `true`.
175
+ */
176
+ write: boolean;
177
+ handler(args: Record<string, unknown>, context: PluginAgentToolContext): PluginAgentToolResult | Promise<PluginAgentToolResult>;
178
+ };
81
179
  type StoryExprBinaryOp = "+" | "-" | "*" | "/" | "%" | "==" | "!=" | "<" | "<=" | ">" | ">=" | "&&" | "||";
82
180
  type StoryExprUnaryOp = "-" | "!";
83
181
  declare const STORY_EXPR_FUNCTIONS: readonly [
@@ -229,6 +327,74 @@ type StoryExpression = {
229
327
  source: string;
230
328
  ast: StoryExpr;
231
329
  };
330
+ type StoryRumblePresetId = "tap" | "pulse" | "impact" | "quake" | "alert" | "custom";
331
+ type StoryInputWaitFields = {
332
+ /**
333
+ * The project input action this row waits for (`UIDocument.actions` key). Absent means any of
334
+ * them: the first action the player performs, whichever it is.
335
+ */
336
+ actionId?: string;
337
+ /**
338
+ * Give up after this long. Absent waits for as long as it takes - which is the right default for a
339
+ * row whose whole point is the player's gesture, and the reason a row that wants a deadline has to
340
+ * say so.
341
+ */
342
+ timeoutMs?: number;
343
+ /**
344
+ * A boolean variable to write the outcome into: `true` when the player did it in time, `false` when
345
+ * the deadline passed first. Absent leaves nothing behind, so a row without a deadline does not
346
+ * need one.
347
+ */
348
+ resultTarget?: StoryVariableRef;
349
+ };
350
+ type StoryInputActionPayload = {
351
+ action: "input";
352
+ /** Shake every connected pad. */
353
+ operation: "rumble";
354
+ preset?: StoryRumblePresetId;
355
+ /** Overrides the preset's left motor (or, under `custom`, is the left motor). */
356
+ strongMagnitude?: number;
357
+ /** Overrides the preset's right motor. */
358
+ weakMagnitude?: number;
359
+ /** Overrides the preset's length. */
360
+ durationMs?: number;
361
+ /** Hold the story until the rumble has finished. Absent lets the story move on at once. */
362
+ wait?: boolean;
363
+ } | {
364
+ action: "input";
365
+ /** End any rumble still running. */
366
+ operation: "stopRumble";
367
+ } | {
368
+ action: "input";
369
+ /**
370
+ * Take the story out of the player's hands: a click, the advance key, auto-forward and
371
+ * skipping all do nothing until an `unlock` row runs. Rows that do not wait for the player
372
+ * go on playing, which is what makes a locked passage a cutscene rather than a frozen frame -
373
+ * and why a dialogue line inside one strands the player.
374
+ *
375
+ * Its own member rather than `"lock" | "unlock"` on one, so a check of the two narrows the
376
+ * union the way every other operation here does.
377
+ */
378
+ operation: "lock";
379
+ } | {
380
+ action: "input";
381
+ /** Give the story back to the player. */
382
+ operation: "unlock";
383
+ } | ({
384
+ action: "input";
385
+ /** Wait for one press of the action. */
386
+ operation: "wait";
387
+ } & StoryInputWaitFields) | ({
388
+ action: "input";
389
+ /** Wait for the action to be held down, unbroken, for `holdMs`. */
390
+ operation: "hold";
391
+ holdMs: number;
392
+ } & StoryInputWaitFields) | ({
393
+ action: "input";
394
+ /** Wait for the action to be pressed `count` times. */
395
+ operation: "mash";
396
+ count: number;
397
+ } & StoryInputWaitFields);
232
398
  type AssetAxisResidency = "build" | "runtime";
233
399
  type AssetSetAxisKind = "locale" | "release";
234
400
  interface AssetSetAxis {
@@ -540,7 +706,8 @@ type StoryActionPayload = {
540
706
  value: StoryLiteralValue;
541
707
  /**
542
708
  * A computed right-hand side (`/set gold gold + 1`). **When present it wins**, and `value`
543
- * is only the last literal the row held - never read by the compiler.
709
+ * is never read by the compiler. A row written with an expression stores `null` there;
710
+ * older rows may hold the `true` a new assignment block starts with.
544
711
  *
545
712
  * Why not fold the literal case in here too: `/set gold 100` is the overwhelmingly common
546
713
  * row, `value` is what the inspector's literal editor binds to, and every document written
@@ -653,12 +820,18 @@ type StoryActionPayload = {
653
820
  transform?: StoryTransformRef;
654
821
  } | {
655
822
  action: "layer";
656
- operation: "create" | "setZIndex" | "show" | "hide" | "transform";
657
- objectName: string;
658
823
  /**
659
- * Which layer non-`create` ops act on - a built-in (`background`/`displayable`) or a custom
660
- * layer bound by its create block. `create` names a new custom layer via `objectName`.
824
+ * A step the story takes with one of the scene's layers. Declaring a layer is not one: the
825
+ * scene's layers are `StoryScene.layers` (v30), and `create` / `setDepth` are gone with it.
826
+ *
827
+ * `setZIndex` is kept for the rows that hold it and is no longer offered: it moves a layer in
828
+ * the stacking order part way through a scene, which the scene's stack - one order, the same
829
+ * as the layers' distances - has no way to say. A row that holds it still plays as it did.
661
830
  */
831
+ operation: "setZIndex" | "show" | "hide" | "transform";
832
+ /** The layer's name as the row was written, the fallback when {@link target} does not resolve. */
833
+ objectName: string;
834
+ /** Which layer the row acts on - a built-in (`background` / `displayable`) or one of the scene's own. */
662
835
  target?: StoryLayerRef;
663
836
  zIndex?: number;
664
837
  transform?: StoryTransformRef;
@@ -880,7 +1053,9 @@ type StoryActionPayload = {
880
1053
  * JSON, which is what makes the row survive a round trip through the project file.
881
1054
  */
882
1055
  params: Record<string, StoryPluginActionParamValue>;
883
- };
1056
+ }
1057
+ /** The player's hands: a pad that shakes, a locked passage, a row that waits for a gesture. */
1058
+ | StoryInputActionPayload;
884
1059
  type StoryPluginActionParamValue = string | number | boolean | null | StoryPluginActionParamValue[] | {
885
1060
  [key: string]: StoryPluginActionParamValue;
886
1061
  };
@@ -1177,9 +1352,10 @@ type StoryDisplayableTargetRef = {
1177
1352
  label?: string;
1178
1353
  /**
1179
1354
  * Stable identity of the displayable: the id of the action block that introduced it
1180
- * (character enter / image / text / layer). Displayables can only be declared statically,
1181
- * so this always points at a real creator block. When present it is the source of truth -
1182
- * the current stage name is resolved from that block, so the reference survives renames.
1355
+ * (character enter / image / text), or for a layer the id of the scene layer (v30: a layer is
1356
+ * declared by the scene, under the id its `create` row had). Displayables can only be declared
1357
+ * statically, so this always points at a real declaration. When present it is the source of
1358
+ * truth - the current stage name is resolved from it, so the reference survives renames.
1183
1359
  * `name` remains as a legacy fallback and last-known label when the source is unresolvable.
1184
1360
  */
1185
1361
  sourceBlockId?: StoryBlockId;
@@ -1194,9 +1370,10 @@ type StoryLayerRef = {
1194
1370
  layer: "background" | "displayable";
1195
1371
  } | {
1196
1372
  kind: "custom";
1197
- sourceBlockId?: StoryBlockId;
1373
+ sourceBlockId?: StorySceneLayerId;
1198
1374
  name?: string;
1199
1375
  };
1376
+ type StorySceneLayerId = string;
1200
1377
  type StoryActionableBuiltin = "bgm";
1201
1378
  type StoryActionableTargetRef = {
1202
1379
  /**
@@ -1817,6 +1994,10 @@ declare const en: {
1817
1994
  readonly one: "{count} warning";
1818
1995
  readonly other: "{count} warnings";
1819
1996
  };
1997
+ readonly minorWarnings: {
1998
+ readonly one: "{count} minor warning";
1999
+ readonly other: "{count} minor warnings";
2000
+ };
1820
2001
  readonly infos: {
1821
2002
  readonly one: "{count} info";
1822
2003
  readonly other: "{count} info";
@@ -1831,6 +2012,7 @@ declare const en: {
1831
2012
  readonly down: "down";
1832
2013
  readonly left: "left";
1833
2014
  readonly right: "right";
2015
+ readonly overview: "Overview";
1834
2016
  };
1835
2017
  };
1836
2018
  readonly menu: {
@@ -1889,9 +2071,9 @@ declare const en: {
1889
2071
  readonly minimize: "Minimize";
1890
2072
  readonly zoom: "Zoom";
1891
2073
  readonly front: "Bring All to Front";
1892
- readonly leftSidebar: "Show Left Bar";
1893
- readonly bottomPanel: "Show Bottom Bar";
1894
- readonly rightSidebar: "Show Right Bar";
2074
+ readonly leftSidebar: "Toggle Left Bar";
2075
+ readonly bottomPanel: "Toggle Bottom Bar";
2076
+ readonly rightSidebar: "Toggle Right Bar";
1895
2077
  };
1896
2078
  readonly help: {
1897
2079
  readonly title: "Help";
@@ -1968,6 +2150,10 @@ declare const en: {
1968
2150
  readonly label: "Network";
1969
2151
  readonly description: "Where Studio downloads plugins, templates and build tooling from.";
1970
2152
  };
2153
+ readonly agent: {
2154
+ readonly label: "Agent access";
2155
+ readonly description: "Let AI agents connect to Studio over MCP and work on the open project.";
2156
+ };
1971
2157
  readonly data: {
1972
2158
  readonly label: "Data";
1973
2159
  readonly description: "Cached files, resetting preferences, and moving them between machines.";
@@ -2147,8 +2333,18 @@ declare const en: {
2147
2333
  readonly label: "Download address rewrites";
2148
2334
  };
2149
2335
  readonly useSystemProxy: {
2150
- readonly label: "Use this computer's proxy";
2151
- readonly description: "Studio downloads follow the proxy this computer already uses.";
2336
+ readonly label: "Use system proxy settings";
2337
+ readonly description: "Studio downloads connect through the proxy set in the operating system.";
2338
+ };
2339
+ readonly storeSource: {
2340
+ readonly label: "Store download source";
2341
+ readonly description: "Where the plugin store, the template store and spelling dictionaries are downloaded from. Automatic connects to GitHub and GitCode at once and uses the first to respond.";
2342
+ readonly options: {
2343
+ readonly auto: "Automatic";
2344
+ readonly gitcode: "GitCode (mainland China)";
2345
+ readonly custom: "Custom";
2346
+ };
2347
+ readonly customOnly: "Used when the store download source is Custom.";
2152
2348
  };
2153
2349
  readonly pluginRegistryUrl: {
2154
2350
  readonly label: "Plugin registry URL";
@@ -2226,6 +2422,13 @@ declare const en: {
2226
2422
  readonly keybindings: {
2227
2423
  readonly label: "Keyboard shortcuts";
2228
2424
  };
2425
+ readonly agentAccess: {
2426
+ readonly label: "MCP endpoint";
2427
+ };
2428
+ readonly agentFollow: {
2429
+ readonly label: "Follow the agent's edits";
2430
+ readonly description: "Open each page, scene or blueprint an agent changes, bring it to the front and outline the change.";
2431
+ };
2229
2432
  readonly projectTrust: {
2230
2433
  readonly label: "Trusted projects";
2231
2434
  readonly description: "Projects that Studio did not create, and whether they may run.";
@@ -2333,6 +2536,65 @@ declare const en: {
2333
2536
  readonly unknown: "The server could not be added.";
2334
2537
  };
2335
2538
  };
2539
+ readonly agent: {
2540
+ readonly loading: "Reading\u2026";
2541
+ readonly enable: "Allow agents to connect";
2542
+ readonly enableHint: "Serves an MCP endpoint on this computer for AI agents such as Claude Code and opencode.";
2543
+ readonly allowWrites: "Allow agents to change projects";
2544
+ readonly allowWritesHint: "When off, agents can read projects but every change they try is refused.";
2545
+ readonly fullAccess: "Allow agents full access";
2546
+ readonly fullAccessHint: "Agents may change projects and read any folder without asking, except Studio's own folders, the home folder as a whole and drive roots.";
2547
+ readonly endpoint: "Endpoint address";
2548
+ readonly running: "Listening.";
2549
+ readonly portMoved: "The endpoint moved to port {port}. Copy the connection configuration again for clients set up before.";
2550
+ readonly copyAddress: "Copy address";
2551
+ readonly stopped: "Not running.";
2552
+ readonly failed: "Could not start: {message}";
2553
+ readonly token: "Access token";
2554
+ readonly tokenHint: "Every request must carry it. It is part of the copied configuration.";
2555
+ readonly show: "Show";
2556
+ readonly hide: "Hide";
2557
+ readonly regenerate: "Regenerate access token";
2558
+ readonly regenerateHint: "Clients set up with the current token stop being let in.";
2559
+ readonly regenerateAction: "Regenerate";
2560
+ readonly copied: "Copied";
2561
+ readonly importRoots: "Folders agents may import from";
2562
+ readonly importRootsHint: "Agents can always import files from inside the project. When an agent needs another folder, Studio asks you and adds it here.";
2563
+ readonly importRootsEmpty: "No other folders.";
2564
+ readonly addFolder: "Add folder\u2026";
2565
+ readonly removeFolder: "Remove";
2566
+ readonly pluginTools: "Plugin tools";
2567
+ readonly pluginToolsHint: "Tools the enabled plugins offer agents. A plugin switched off here has its tools hidden from agents and their calls refused.";
2568
+ readonly pluginToolsEmpty: "No enabled plugin offers agent tools.";
2569
+ readonly pluginToolsCount: "{tools} tools, {writes} of which can change the project";
2570
+ readonly pluginToolsAllow: "Allow the agent tools of {plugin}";
2571
+ readonly guide: {
2572
+ readonly app: "Agent application";
2573
+ readonly appHint: "The connection configuration and Agent Skill below are for this application.";
2574
+ readonly other: "Other";
2575
+ readonly connection: "Connection configuration";
2576
+ readonly offHint: "Available once \"Allow agents to connect\" is on.";
2577
+ readonly runCommand: "Run in a terminal.";
2578
+ readonly mergeInto: "Merge into {file}.";
2579
+ readonly claudeDesktop: "Merge into claude_desktop_config.json (Settings \u25B8 Developer \u25B8 Edit Config in Claude), then restart Claude.";
2580
+ readonly otherClient: "Streamable HTTP. Enter this address and header in the client's MCP settings.";
2581
+ readonly skill: "Agent Skill";
2582
+ readonly skillFolder: "Installs into {path}. Other skills there are kept.";
2583
+ readonly skillInstall: "Install Agent Skill";
2584
+ readonly skillReinstall: "Reinstall";
2585
+ readonly skillInstalled: "Installed in {path}.";
2586
+ readonly skillUpload: "Saves a zip file to upload in Claude under Settings \u25B8 Capabilities \u25B8 Skills.";
2587
+ readonly skillSave: "Save zip file\u2026";
2588
+ readonly skillSaved: "Saved to {path}.";
2589
+ readonly skillServed: "Other applications read the same guide from Studio's MCP server.";
2590
+ readonly skillExport: "Export Agent Skill\u2026";
2591
+ readonly skillExported: "Exported to {path}.";
2592
+ readonly copyFailed: "The connection configuration could not be copied: {error}";
2593
+ readonly installFailed: "The Agent Skill could not be installed: {error}";
2594
+ readonly saveFailed: "The Agent Skill could not be saved: {error}";
2595
+ readonly exportFailed: "The Agent Skill could not be exported: {error}";
2596
+ };
2597
+ };
2336
2598
  readonly data: {
2337
2599
  readonly projectTrust: {
2338
2600
  readonly loading: "Reading\u2026";
@@ -2403,6 +2665,10 @@ declare const en: {
2403
2665
  readonly label: "PSD import working files";
2404
2666
  readonly description: "Layer images written while importing a PSD.";
2405
2667
  };
2668
+ readonly payloadReaders: {
2669
+ readonly label: "Protected build readers";
2670
+ readonly description: "Readers copied from builds with asset protection to export a patch or DLC. Copied again the next time one is exported.";
2671
+ };
2406
2672
  readonly logs: {
2407
2673
  readonly label: "Logs";
2408
2674
  readonly description: "The logs an exported diagnostics file is built from.";
@@ -2973,6 +3239,217 @@ declare const en: {
2973
3239
  readonly surfaceEdit: "interface edit";
2974
3240
  readonly blueprintEdit: "blueprint edit";
2975
3241
  readonly replaceText: "text replacement";
3242
+ readonly agentEdit: "agent edit";
3243
+ readonly agentPluginEdit: "agent: {tool}";
3244
+ };
3245
+ };
3246
+ readonly agent: {
3247
+ readonly status: {
3248
+ readonly editing: "Agent editing: {name}";
3249
+ readonly working: "Agent working";
3250
+ readonly connected: "Agent: {client}";
3251
+ readonly edited: "Agent edited: {name}";
3252
+ readonly unknownClient: "external agent";
3253
+ readonly paused: "Agent paused";
3254
+ };
3255
+ readonly menu: {
3256
+ readonly pause: "Pause agent";
3257
+ readonly resume: "Resume agent";
3258
+ readonly follow: "Follow the agent's edits";
3259
+ };
3260
+ readonly tooltip: "Agent options";
3261
+ readonly appMenu: {
3262
+ readonly title: "Agent";
3263
+ readonly status: "Agent: {client} \u00B7 {state}";
3264
+ readonly statusOff: "Agent access: Off";
3265
+ readonly notConnected: "Not connected";
3266
+ readonly state: {
3267
+ readonly working: "Working";
3268
+ readonly idle: "Idle";
3269
+ readonly paused: "Paused";
3270
+ };
3271
+ readonly log: "Agent log";
3272
+ readonly enable: "Enable agent access";
3273
+ readonly allowWrites: "Allow agents to change projects";
3274
+ readonly fullAccess: "Allow agents full access";
3275
+ readonly copyConfig: "Copy connection configuration";
3276
+ readonly exportSkill: "Export Agent Skill\u2026";
3277
+ readonly settings: "Agent access settings\u2026";
3278
+ readonly notice: {
3279
+ readonly copied: "Configuration for {client} copied";
3280
+ readonly copyFailed: "The configuration could not be copied: {error}";
3281
+ readonly toggleFailed: "Agent access could not be changed: {error}";
3282
+ readonly exported: "Agent Skill exported to {path}";
3283
+ readonly exportFailed: "The Agent Skill could not be exported: {error}";
3284
+ };
3285
+ };
3286
+ readonly confirm: {
3287
+ readonly window: "Agent Access";
3288
+ readonly loadError: "The request could not be read.";
3289
+ readonly enable: {
3290
+ readonly message: "Turn on agent access?";
3291
+ readonly detail: "Agents connected to Studio can then read every project open in Studio. Changing projects needs a separate permission.";
3292
+ readonly allow: "Turn on";
3293
+ };
3294
+ readonly allowWrites: {
3295
+ readonly message: "Allow agents to change projects?";
3296
+ readonly detail: "Connected agents can then create, change and delete content in open projects. Most changes can be undone.";
3297
+ readonly allow: "Allow";
3298
+ };
3299
+ readonly exportSkill: {
3300
+ readonly title: "Export Agent Skill";
3301
+ readonly existsMessage: "This folder already contains {folder}";
3302
+ readonly existsDetail: "Files with the same name are replaced. Other files in the folder are kept.";
3303
+ readonly replace: "Replace";
3304
+ };
3305
+ readonly installSkill: {
3306
+ readonly title: "Install Agent Skill";
3307
+ readonly changedOne: "This folder holds a SKILL.md that differs from Studio's";
3308
+ readonly changedMany: "These folders hold a SKILL.md that differs from Studio's";
3309
+ readonly changedDetail: "Files with the same name are replaced with this version of Studio's Agent Skill. Other skills are kept.";
3310
+ readonly replace: "Replace";
3311
+ };
3312
+ readonly folderAccess: {
3313
+ readonly title: "Allow agents to read folders?";
3314
+ readonly messageOne: "{client} wants to read this folder";
3315
+ readonly messageMany: "{client} wants to read these folders";
3316
+ readonly detail: "The agent reads the files there to import them into this project. Nothing outside the project is changed.";
3317
+ readonly reason: "Purpose stated by the agent: {reason}";
3318
+ readonly settings: "Allowed folders stay allowed for every agent until removed in Settings \u25B8 Agent access, which also offers full access.";
3319
+ readonly allowOne: "Allow this folder";
3320
+ readonly allowMany: "Allow these folders";
3321
+ readonly deny: "Deny";
3322
+ readonly unknownClient: "An external agent";
3323
+ };
3324
+ readonly fullAccess: {
3325
+ readonly message: "Allow agents full access?";
3326
+ readonly detail: "Connected agents can then change projects and read files in any folder without asking, except Studio's own folders, the home folder as a whole and drive roots. Turn it off in the Agent menu or in Settings \u25B8 Agent access.";
3327
+ readonly allow: "Allow full access";
3328
+ };
3329
+ };
3330
+ readonly log: {
3331
+ readonly pluginTool: "A tool of the plugin {plugin}";
3332
+ readonly target: {
3333
+ readonly standardScreens: "Standard screens";
3334
+ };
3335
+ readonly filter: {
3336
+ readonly all: "All calls";
3337
+ readonly writes: "Changes only";
3338
+ readonly failures: "Failures only";
3339
+ };
3340
+ readonly filterAria: "Filter calls";
3341
+ readonly listAria: "Agent calls";
3342
+ readonly export: "Export\u2026";
3343
+ readonly exportHint: "Export as JSON Lines";
3344
+ readonly empty: "No agent calls";
3345
+ readonly emptyHint: "Agents connect through Agent access in Settings.";
3346
+ readonly emptyFiltered: "No calls match this filter";
3347
+ readonly running: "Running";
3348
+ readonly ok: "Succeeded";
3349
+ readonly durationMs: "{value} ms";
3350
+ readonly durationS: "{value} s";
3351
+ readonly showChange: "Show the change";
3352
+ readonly targetGone: "That item no longer exists";
3353
+ readonly message: "Reply sent to the agent";
3354
+ readonly hint: "Hint sent to the agent";
3355
+ readonly exported: "Agent log exported to {path}";
3356
+ readonly exportFailed: "The Agent log could not be exported: {error}";
3357
+ readonly exportEmpty: "The Agent log is empty";
3358
+ readonly code: {
3359
+ readonly invalid_args: "Invalid arguments";
3360
+ readonly unknown_tool: "Unknown tool";
3361
+ readonly no_workspace: "No open project";
3362
+ readonly writes_disabled: "Changes not allowed";
3363
+ readonly paused: "Paused";
3364
+ readonly frozen: "Project frozen";
3365
+ readonly live_session: "Live session running";
3366
+ readonly stale_revision: "Changed since read";
3367
+ readonly check_failed: "Check failed";
3368
+ readonly not_found: "Not found";
3369
+ readonly path_not_allowed: "Folder not allowed";
3370
+ readonly untrusted: "Project not trusted";
3371
+ readonly unavailable: "Unavailable";
3372
+ readonly internal: "Internal error";
3373
+ };
3374
+ };
3375
+ readonly tool: {
3376
+ readonly agent_status: "Studio status";
3377
+ readonly agent_guide: "Read the guide";
3378
+ readonly request_folder_access: "Ask for folder access";
3379
+ readonly project_create: "Create a project";
3380
+ readonly project_open: "Open a project";
3381
+ readonly project_info: "Project overview";
3382
+ readonly project_settings_set: "Change project settings";
3383
+ readonly assets_list: "List assets";
3384
+ readonly assets_import: "Import files";
3385
+ readonly assets_placeholder: "Make a placeholder image";
3386
+ readonly asset_delete: "Delete an asset";
3387
+ readonly characters_list: "List characters";
3388
+ readonly character_upsert: "Create or update a character";
3389
+ readonly character_layered_set: "Lay out a layered character";
3390
+ readonly character_layers_import: "Build a layered character from files";
3391
+ readonly character_preview: "Preview a character look";
3392
+ readonly variables_list: "List variables";
3393
+ readonly variable_upsert: "Create or update a variable";
3394
+ readonly variable_delete: "Delete a variable";
3395
+ readonly audio_tracks_list: "List audio tracks";
3396
+ readonly story_commands: "Story command catalog";
3397
+ readonly story_command: "Story command details";
3398
+ readonly story_targets: "Names a story line can use";
3399
+ readonly story_list: "List stories and scenes";
3400
+ readonly story_rename: "Rename a story";
3401
+ readonly story_show: "Read a scene as text";
3402
+ readonly story_apply: "Write a scene";
3403
+ readonly scene_create: "Create a scene";
3404
+ readonly scene_rename: "Rename a scene";
3405
+ readonly scene_set_entry: "Set the entry scene";
3406
+ readonly scene_delete: "Delete a scene";
3407
+ readonly character_delete: "Delete a character";
3408
+ readonly ui_widgets: "Widget catalog";
3409
+ readonly ui_widget: "Widget details";
3410
+ readonly ui_usage: "Widget usage examples";
3411
+ readonly ui_surfaces: "List pages and components";
3412
+ readonly ui_show: "Read a page as text";
3413
+ readonly ui_selection: "What the author selected";
3414
+ readonly ui_screenshot: "Look at a page";
3415
+ readonly ui_apply: "Write pages";
3416
+ readonly ui_patch: "Edit elements";
3417
+ readonly ui_templates: "Interface templates";
3418
+ readonly ui_template_apply: "Apply a template";
3419
+ readonly ui_page_rename: "Rename a page";
3420
+ readonly ui_page_delete: "Delete a page";
3421
+ readonly ui_page_set_entry: "Set the entry page";
3422
+ readonly ui_install_standard_screens: "Install the standard screens";
3423
+ readonly brand_get: "Read the palette";
3424
+ readonly brand_set: "Change the palette";
3425
+ readonly blueprint_nodes: "Blueprint node catalog";
3426
+ readonly blueprint_node: "Blueprint node details";
3427
+ readonly blueprint_list: "List blueprints";
3428
+ readonly blueprint_show: "Read a blueprint as text";
3429
+ readonly blueprint_apply: "Write blueprints";
3430
+ readonly blueprint_remove: "Remove a blueprint";
3431
+ readonly localization_status: "Translation progress";
3432
+ readonly localization_list: "List text to translate";
3433
+ readonly localization_set: "Write translations";
3434
+ readonly voice_status: "Voice-over progress";
3435
+ readonly voice_list: "List voiced lines";
3436
+ readonly voice_link: "Link voice takes";
3437
+ readonly voice_auto_link: "Link takes by name";
3438
+ readonly voice_settings_set: "Change voice settings";
3439
+ readonly lint: "Check the project";
3440
+ readonly test: "Run a project test";
3441
+ readonly playtest_start: "Play the game";
3442
+ readonly playtest_advance: "Advance the game";
3443
+ readonly playtest_screenshot: "Look at the game";
3444
+ readonly asset_usage: "Where an asset is used";
3445
+ readonly chapter_rename: "Rename a chapter";
3446
+ readonly chapter_delete: "Delete a chapter";
3447
+ readonly playtest_click: "Click in the game";
3448
+ readonly playtest_hover: "Hover in the game";
3449
+ readonly playtest_key: "Press a key in the game";
3450
+ readonly playtest_stop: "Stop playing";
3451
+ readonly console_read: "Read Studio's console";
3452
+ readonly build: "Build the game";
2976
3453
  };
2977
3454
  };
2978
3455
  readonly shell: {
@@ -3125,9 +3602,6 @@ declare const en: {
3125
3602
  readonly closeSplit: "Close split";
3126
3603
  readonly reopenClosed: "Reopen closed tab";
3127
3604
  };
3128
- readonly toggleLeftSidebar: "Toggle left sidebar";
3129
- readonly toggleRightSidebar: "Toggle right sidebar";
3130
- readonly toggleBottomPanel: "Toggle bottom panel";
3131
3605
  readonly mainMenu: {
3132
3606
  readonly label: "Main menu";
3133
3607
  readonly modes: {
@@ -3201,6 +3675,8 @@ declare const en: {
3201
3675
  readonly editorPlateOpacity: "Editor background opacity";
3202
3676
  readonly sidebarPlate: "Sidebar background";
3203
3677
  readonly sidebarPlateOpacity: "Sidebar background opacity";
3678
+ readonly framePlate: "Frame background";
3679
+ readonly framePlateOpacity: "Frame background opacity";
3204
3680
  readonly fill: {
3205
3681
  readonly cover: "Scale to fill";
3206
3682
  readonly contain: "Fit";
@@ -3222,6 +3698,7 @@ declare const en: {
3222
3698
  readonly asset: "Asset";
3223
3699
  readonly blueprint: "Blueprint";
3224
3700
  };
3701
+ readonly ordinal: "Item {n}";
3225
3702
  };
3226
3703
  readonly statusBar: {
3227
3704
  readonly distrusted: {
@@ -3283,6 +3760,7 @@ declare const en: {
3283
3760
  readonly textEncoding: "Text encoding";
3284
3761
  readonly textLineEnding: "Line ending";
3285
3762
  readonly textSelection: "Cursor position";
3763
+ readonly agent: "Agent";
3286
3764
  };
3287
3765
  };
3288
3766
  readonly save: {
@@ -3631,6 +4109,7 @@ declare const en: {
3631
4109
  readonly openSettings: "Customize Keyboard Shortcuts";
3632
4110
  readonly cheatSheetTitle: "Shortcuts and Mouse Actions";
3633
4111
  readonly cheatSheetCustomize: "Customize\u2026";
4112
+ readonly cheatSheetFocused: "Focused: {name}";
3634
4113
  readonly categories: {
3635
4114
  readonly general: "General";
3636
4115
  readonly run: "Run";
@@ -3703,13 +4182,36 @@ declare const en: {
3703
4182
  readonly storyMotion: {
3704
4183
  readonly undo: "Undo";
3705
4184
  readonly redo: "Redo";
3706
- readonly delete: "Delete Keyframe";
4185
+ readonly delete: "Delete Selected Keyframes";
3707
4186
  readonly prevFrame: "Step Playhead Back One Frame";
3708
4187
  readonly nextFrame: "Step Playhead Forward One Frame";
3709
4188
  readonly prevFrames: "Step Playhead Back Ten Frames";
3710
4189
  readonly nextFrames: "Step Playhead Forward Ten Frames";
3711
4190
  readonly playheadStart: "Move Playhead to Start";
3712
4191
  readonly playheadEnd: "Move Playhead to End";
4192
+ readonly playPause: "Play or Pause";
4193
+ readonly playReverse: "Play Backwards";
4194
+ readonly stop: "Stop";
4195
+ readonly playForward: "Play Forwards";
4196
+ readonly loop: "Toggle Loop";
4197
+ readonly prevKeyframe: "Go to Previous Keyframe";
4198
+ readonly nextKeyframe: "Go to Next Keyframe";
4199
+ readonly insertKeyframe: "Add Keyframes at Playhead";
4200
+ readonly selectAll: "Select All Keyframes";
4201
+ readonly clearSelection: "Clear Selection";
4202
+ readonly copy: "Copy Keyframes";
4203
+ readonly cut: "Cut Keyframes";
4204
+ readonly paste: "Paste Keyframes at Playhead";
4205
+ readonly nudgeLeft: "Move Keyframes Back One Frame";
4206
+ readonly nudgeRight: "Move Keyframes Forward One Frame";
4207
+ readonly nudgeLeftLarge: "Move Keyframes Back Ten Frames";
4208
+ readonly nudgeRightLarge: "Move Keyframes Forward Ten Frames";
4209
+ readonly zoomIn: "Zoom Timeline In";
4210
+ readonly zoomOut: "Zoom Timeline Out";
4211
+ readonly zoomFit: "Fit Motion in Timeline";
4212
+ readonly libraryRename: "Rename Motion";
4213
+ readonly libraryDuplicate: "Duplicate Selected Motions";
4214
+ readonly libraryDelete: "Delete Selected Motions";
3713
4215
  };
3714
4216
  };
3715
4217
  readonly gestures: {
@@ -3742,7 +4244,11 @@ declare const en: {
3742
4244
  readonly doubleClickGroupTitle: "Double-click a group's title";
3743
4245
  readonly middleClickTitle: "Middle-click the title row";
3744
4246
  readonly doubleClickTrack: "Double-click a track";
4247
+ readonly dragKeyframe: "Drag a keyframe";
4248
+ readonly clickKeyframe: "Click a keyframe";
4249
+ readonly dragAcrossTracks: "Drag across the tracks";
3745
4250
  readonly clickAsset: "Click an asset";
4251
+ readonly clickMotion: "Click a motion";
3746
4252
  readonly doubleClick: "Double-click";
3747
4253
  readonly dragToEditorArea: "Drag into the editor area";
3748
4254
  readonly dragOntoGroup: "Drag onto a group";
@@ -3790,11 +4296,17 @@ declare const en: {
3790
4296
  readonly renameGroup: "Rename a Group";
3791
4297
  };
3792
4298
  readonly storyMotion: {
3793
- readonly noFrameSnap: "Drag Without Frame Snapping";
4299
+ readonly noFrameSnap: "Drag Without Snapping";
4300
+ readonly moveKeyframes: "Move Keyframes";
4301
+ readonly boxSelect: "Select Keyframes in a Box";
4302
+ readonly selectTrack: "Select a Track's Keyframes";
3794
4303
  readonly addKeyframe: "Add a Keyframe";
3795
4304
  readonly panPreview: "Pan the Preview";
3796
4305
  readonly zoom: "Zoom the Preview or Timeline";
3797
4306
  readonly scrollTimeline: "Scroll the Timeline Sideways";
4307
+ readonly openMotion: "Open a Motion";
4308
+ readonly selectMotionRange: "Select a Range of Motions";
4309
+ readonly selectAllMotions: "Select All Motions";
3798
4310
  };
3799
4311
  readonly assets: {
3800
4312
  readonly selectAssetRange: "Select a Range of Assets";
@@ -3808,6 +4320,9 @@ declare const en: {
3808
4320
  readonly clearMarker: "Clear a Marker";
3809
4321
  readonly videoZoom: "Zoom the Picture";
3810
4322
  readonly videoActualSize: "Switch Between Fit and Actual Pixels";
4323
+ readonly moveSelection: "Move the Selection";
4324
+ readonly extendSelection: "Extend the Selection";
4325
+ readonly moveThroughGroupTree: "Move Through the Group Tree";
3811
4326
  };
3812
4327
  };
3813
4328
  };
@@ -4052,6 +4567,7 @@ declare const en: {
4052
4567
  };
4053
4568
  readonly reason: {
4054
4569
  readonly blueprintAction: "A blueprint runs this row, and a blueprint has no script form.";
4570
+ readonly inputAction: "This row works with the player's input or the controller's rumble, and has no script form.";
4055
4571
  readonly blueprintCondition: "A blueprint decides this condition.";
4056
4572
  readonly blueprintInterpolation: "A blueprint computes a value inside this text.";
4057
4573
  readonly inlineEvent: "The text carries an event that fires while it is being typed out.";
@@ -4077,6 +4593,7 @@ declare const en: {
4077
4593
  readonly danglingBranch: "This branch has no condition above it.";
4078
4594
  readonly badTag: "This line carries a formatting tag that is unknown, or left open.";
4079
4595
  readonly badExpression: "This expression does not resolve.";
4596
+ readonly layerDeclaration: "A script cannot declare a layer. Add it to the scene's layers";
4080
4597
  };
4081
4598
  readonly view: {
4082
4599
  readonly open: "Read as a script";
@@ -4308,10 +4825,35 @@ declare const en: {
4308
4825
  };
4309
4826
  readonly layerField: {
4310
4827
  readonly label: "Layer";
4311
- readonly defaultName: "Displayable layer";
4312
- readonly notOnStageTitle: "No layer with this name is declared earlier in this scene. Pick an existing layer";
4313
- readonly hint: "Layer";
4828
+ readonly defaultName: "Base layer";
4829
+ readonly notOnStageTitle: "This scene has no layer with this name. Pick one of its layers";
4314
4830
  readonly createNew: "Create new layer";
4831
+ readonly backgroundName: "Background layer";
4832
+ readonly displayableHint: "The default layer, always at distance 1";
4833
+ readonly backgroundHint: "No nearer than the base layer";
4834
+ readonly manage: "Manage layers\u2026";
4835
+ };
4836
+ readonly sceneLayers: {
4837
+ readonly open: "Scene layers";
4838
+ readonly unnamed: "Unnamed layer";
4839
+ readonly defaultName: "Layer {index}";
4840
+ readonly distance: "Distance {value}";
4841
+ readonly distanceColumn: "Distance";
4842
+ readonly distanceTip: "Measured from the base layer, which is at 1. Larger values are farther away and move less with the camera; at \u221E the layer stays still";
4843
+ readonly distanceInvalid: "Enter a value from 0.5 to 100, or \u221E";
4844
+ readonly levelKeepsBase: "The base layer stays at 1; the other layers at this level move together";
4845
+ readonly frontToBack: "Front to back";
4846
+ readonly fixedTip: "The base layer is always at distance 1; every other distance is measured from it";
4847
+ readonly backgroundDragTip: "Drag to change the layer's distance; the background layer cannot come nearer than the base layer";
4848
+ readonly dragTip: "Drag to change the layer's distance";
4849
+ readonly remove: "Remove layer";
4850
+ readonly inUseOne: "1 row uses this layer";
4851
+ readonly inUseMany: "{count} rows use this layer";
4852
+ readonly nameTaken: "This scene already has a layer with this name";
4853
+ readonly nameReserved: "This name refers to a built-in layer";
4854
+ readonly swayCaption: "Camera moving";
4855
+ readonly framingCaption: "This row's shot";
4856
+ readonly lookHint: "The camera follows the pointer; scroll to zoom";
4315
4857
  };
4316
4858
  readonly appearance: {
4317
4859
  readonly noPoses: "This character has no poses yet.";
@@ -4445,6 +4987,16 @@ declare const en: {
4445
4987
  readonly labelName: "Label";
4446
4988
  readonly endingName: "Ending";
4447
4989
  readonly quitPage: "Page";
4990
+ readonly rumblePreset: "Shape";
4991
+ readonly rumbleLeft: "Left Motor";
4992
+ readonly rumbleRight: "Right Motor";
4993
+ readonly rumbleWait: "Wait for the rumble";
4994
+ readonly inputLock: "Lock / Unlock";
4995
+ readonly inputAction: "Input Action";
4996
+ readonly inputTimeout: "Time Limit";
4997
+ readonly inputResult: "Result Variable";
4998
+ readonly holdDuration: "Hold Seconds";
4999
+ readonly mashCount: "Presses";
4448
5000
  readonly scene: "Scene";
4449
5001
  readonly track: "Audio Track";
4450
5002
  readonly appTag: "Build Variant";
@@ -4470,7 +5022,8 @@ declare const en: {
4470
5022
  readonly hold: "Hold Seconds";
4471
5023
  readonly opacity: "Opacity";
4472
5024
  readonly size: "Font Size";
4473
- readonly z: "Z-Index";
5025
+ readonly xOffset: "X Offset px";
5026
+ readonly yOffset: "Y Offset px";
4474
5027
  readonly zoom: "Zoom";
4475
5028
  readonly scale: "Scale";
4476
5029
  readonly scaleX: "Scale X";
@@ -4508,6 +5061,15 @@ declare const en: {
4508
5061
  readonly conceal: "Conceal";
4509
5062
  };
4510
5063
  readonly enumValue: {
5064
+ readonly tap: "tap";
5065
+ readonly pulse: "pulse";
5066
+ readonly impact: "impact";
5067
+ readonly quake: "quake";
5068
+ readonly alert: "alert";
5069
+ readonly custom: "custom";
5070
+ readonly stop: "stop";
5071
+ readonly lock: "lock";
5072
+ readonly unlock: "unlock";
4511
5073
  readonly loop: "loop";
4512
5074
  readonly reverse: "reverse";
4513
5075
  readonly mirror: "mirror";
@@ -4692,6 +5254,7 @@ declare const en: {
4692
5254
  readonly label: "Label in this scene";
4693
5255
  readonly appTag: "Build variant";
4694
5256
  readonly surface: "Page";
5257
+ readonly inputAction: "Input action";
4695
5258
  readonly variable: "Variable";
4696
5259
  readonly content: "New content, typed by the target";
4697
5260
  readonly color: "Color";
@@ -4735,8 +5298,6 @@ declare const en: {
4735
5298
  };
4736
5299
  readonly insert: "Insert a blank row after this one";
4737
5300
  readonly delete: "Delete this row";
4738
- readonly insertTitle: "Insert a blank row after this one ({keys})";
4739
- readonly deleteTitle: "Delete this row ({keys})";
4740
5301
  readonly playFromRow: "Play from this row";
4741
5302
  readonly playBranch: "Play this branch";
4742
5303
  readonly insertPlaceholder: "Type narration, {trigger} for actions, # for characters\u2026";
@@ -4804,6 +5365,8 @@ declare const en: {
4804
5365
  readonly dock: "Dock in the scene editor";
4805
5366
  readonly pip: "Picture-in-picture";
4806
5367
  readonly skipTyping: "Skip typing animation";
5368
+ readonly viewStage: "Stage";
5369
+ readonly viewLayers: "Layers";
4807
5370
  readonly selectRow: "Select a story row to preview its stage state.";
4808
5371
  readonly failed: "Preview failed";
4809
5372
  readonly settleTimeout: "The stage did not finish setting up in time.";
@@ -4916,7 +5479,7 @@ declare const en: {
4916
5479
  readonly notOnStage: {
4917
5480
  readonly image: "Image \u201C{name}\u201D is not on stage; an earlier row has to create it.";
4918
5481
  readonly text: "Text \u201C{name}\u201D is not on stage; an earlier row has to create it.";
4919
- readonly layer: "Layer \u201C{name}\u201D is not on stage; an earlier row has to create it.";
5482
+ readonly layer: "This scene has no layer \u201C{name}\u201D.";
4920
5483
  readonly video: "Video \u201C{name}\u201D is not on stage; an earlier row has to play it.";
4921
5484
  readonly ambience: "Ambience effect \u201C{name}\u201D is not on stage; an earlier row has to create it.";
4922
5485
  readonly character: "Character \u201C{name}\u201D is not on stage; an earlier row has to bring it on stage.";
@@ -5101,7 +5664,7 @@ declare const en: {
5101
5664
  };
5102
5665
  readonly layer: {
5103
5666
  readonly label: "Layer";
5104
- readonly detail: "Create a render layer";
5667
+ readonly detail: "Add a layer to this scene";
5105
5668
  };
5106
5669
  readonly swap: {
5107
5670
  readonly label: "Swap";
@@ -5235,6 +5798,26 @@ declare const en: {
5235
5798
  readonly label: "Quit to page";
5236
5799
  readonly detail: "End this playthrough at this line and show a page. No ending is recorded";
5237
5800
  };
5801
+ readonly rumble: {
5802
+ readonly label: "Rumble";
5803
+ readonly detail: "Vibrate the player's controller. Pick a preset, or set each motor";
5804
+ };
5805
+ readonly input: {
5806
+ readonly label: "Input lock";
5807
+ readonly detail: "Lock or unlock player input. While locked, clicking to advance, the advance key, auto-forward and skipping do nothing; choices can still be picked. Unlock before the next line of dialogue";
5808
+ };
5809
+ readonly waitInput: {
5810
+ readonly label: "Wait for input";
5811
+ readonly detail: "Wait until the player performs an input action, optionally within a time limit";
5812
+ };
5813
+ readonly hold: {
5814
+ readonly label: "Hold";
5815
+ readonly detail: "Wait until the player holds an input action down for a number of seconds";
5816
+ };
5817
+ readonly mash: {
5818
+ readonly label: "Mash";
5819
+ readonly detail: "Wait until the player presses an input action a number of times";
5820
+ };
5238
5821
  readonly blueprint: {
5239
5822
  readonly label: "Blueprint";
5240
5823
  readonly detail: "Run a Story Action Blueprint";
@@ -5297,6 +5880,8 @@ declare const en: {
5297
5880
  readonly cut: "Cut point";
5298
5881
  readonly ending: "Ending";
5299
5882
  readonly quit: "Quit to page";
5883
+ readonly rumble: "Rumble";
5884
+ readonly input: "Input";
5300
5885
  readonly jump: "Jump";
5301
5886
  readonly note: "Note";
5302
5887
  readonly invalid: "Invalid";
@@ -5341,6 +5926,7 @@ declare const en: {
5341
5926
  readonly image: "{operation} image {name}";
5342
5927
  readonly text: "{operation} text {name}";
5343
5928
  readonly layer: "{operation} layer {name}";
5929
+ readonly layerZIndex: "Layer {name} to z-index {z}";
5344
5930
  readonly video: "{operation} video {name}";
5345
5931
  readonly vfx: "{operation} ambience {name}";
5346
5932
  readonly nvl: "NVL block";
@@ -5362,6 +5948,17 @@ declare const en: {
5362
5948
  readonly cutUnknown: "Cut point";
5363
5949
  readonly ending: "Ending {name}";
5364
5950
  readonly quit: "Quit to {page}";
5951
+ readonly rumble: "Rumble: {shape}";
5952
+ readonly rumbleStop: "Stop rumble";
5953
+ readonly inputLock: "Lock player input";
5954
+ readonly inputUnlock: "Unlock player input";
5955
+ readonly inputActionNamed: "\"{name}\"";
5956
+ readonly inputAnyAction: "any input";
5957
+ readonly inputActionUnknown: "an input action";
5958
+ readonly inputActionNotFound: "unknown input action";
5959
+ readonly inputWait: "Wait for {action}";
5960
+ readonly inputHold: "Hold {action} for {seconds}s";
5961
+ readonly inputMash: "Press {action} {count} times";
5365
5962
  readonly quitUnset: "Quit to page";
5366
5963
  readonly jump: "Jump {scene}";
5367
5964
  readonly note: "Note";
@@ -5404,6 +6001,7 @@ declare const en: {
5404
6001
  readonly history: {
5405
6002
  readonly deleteScene: "delete scene {name}";
5406
6003
  readonly deleteChapter: "delete chapter {name}";
6004
+ readonly renameChapter: "rename chapter {name}";
5407
6005
  readonly deleteStory: "delete story {name}";
5408
6006
  readonly deleteAnimation: "delete motion {name}";
5409
6007
  readonly moveScene: "move scene {name}";
@@ -5503,6 +6101,11 @@ declare const en: {
5503
6101
  duplicateVariable: string;
5504
6102
  compoundWithoutTarget: string;
5505
6103
  };
6104
+ assetType: {
6105
+ image: string;
6106
+ audio: string;
6107
+ video: string;
6108
+ };
5506
6109
  reason: {
5507
6110
  unknownCommand: string;
5508
6111
  unknownCommandNear: string;
@@ -5519,17 +6122,22 @@ declare const en: {
5519
6122
  unknownLabel: string;
5520
6123
  unknownAppTag: string;
5521
6124
  unknownSurface: string;
6125
+ unknownInputAction: string;
5522
6126
  unknownVariable: string;
5523
6127
  unknownForm: string;
5524
6128
  notPuppetCharacter: string;
5525
6129
  ambiguousName: string;
5526
6130
  conflictingParams: string;
6131
+ positionOutOfRange: string;
6132
+ offsetWithoutPosition: string;
5527
6133
  repeatTimesAndUntil: string;
5528
6134
  expressionError: string;
5529
6135
  expressionNotBoolean: string;
5530
6136
  expressionTypeMismatch: string;
5531
6137
  duplicateVariable: string;
5532
6138
  reservedVariableName: string;
6139
+ duplicateLayer: string;
6140
+ reservedLayerName: string;
5533
6141
  unknownTarget: string;
5534
6142
  unsupportedTarget: string;
5535
6143
  unsupportedTargetLayer: string;
@@ -5940,6 +6548,9 @@ declare const en: {
5940
6548
  readonly targetScene: "Target scene";
5941
6549
  readonly returnable: "Return after the target scene";
5942
6550
  };
6551
+ readonly setVariable: {
6552
+ readonly missingScene: "Missing scene";
6553
+ };
5943
6554
  readonly note: {
5944
6555
  readonly label: "Note";
5945
6556
  };
@@ -5972,8 +6583,8 @@ declare const en: {
5972
6583
  readonly text: "Text";
5973
6584
  };
5974
6585
  readonly layer: {
5975
- readonly layerName: "Layer name";
5976
6586
  readonly zIndex: "Z-index";
6587
+ readonly zIndexRowHint: "A layer's starting order is set by the scene's layers.";
5977
6588
  };
5978
6589
  readonly video: {
5979
6590
  readonly videoName: "Video name";
@@ -5984,6 +6595,20 @@ declare const en: {
5984
6595
  readonly waitForEnd: "Wait for the video";
5985
6596
  readonly skipHint: "The player can end the video early by clicking or pressing the skip key.";
5986
6597
  };
6598
+ readonly input: {
6599
+ readonly shape: "Shape";
6600
+ readonly leftMotor: "Left motor (0-1)";
6601
+ readonly rightMotor: "Right motor (0-1)";
6602
+ readonly waitForRumble: "Wait for the rumble to end";
6603
+ readonly state: "State";
6604
+ readonly action: "Input action";
6605
+ readonly anyAction: "Any input action";
6606
+ readonly holdSeconds: "Hold (s)";
6607
+ readonly pressCount: "Presses";
6608
+ readonly timeout: "Time limit (s)";
6609
+ readonly result: "Result variable";
6610
+ readonly noResult: "None";
6611
+ };
5987
6612
  readonly nvl: {
5988
6613
  readonly hint: "Child rows run in NVL mode. The transform below animates the NVL layer as it enters.";
5989
6614
  readonly motionLabel: "NVL enter animation";
@@ -6647,11 +7272,17 @@ declare const en: {
6647
7272
  readonly zoomIn: "Zoom In";
6648
7273
  readonly zoomOut: "Zoom Out";
6649
7274
  readonly resetView: "Reset View";
7275
+ readonly keybindings: {
7276
+ readonly zoomIn: "Zoom image in";
7277
+ readonly zoomOut: "Zoom image out";
7278
+ readonly resetView: "Reset image view";
7279
+ };
6650
7280
  };
6651
7281
  readonly shortcuts: {
6652
7282
  readonly copy: "Copy selected assets";
6653
7283
  readonly cut: "Cut selected assets";
6654
7284
  readonly paste: "Paste assets";
7285
+ readonly delete: "Delete selected assets or groups";
6655
7286
  readonly rename: "Rename selected asset or group";
6656
7287
  };
6657
7288
  readonly previewEditor: {
@@ -6899,6 +7530,9 @@ declare const en: {
6899
7530
  readonly node: {
6900
7531
  readonly contextInvalid: "Node \"{name}\" is not allowed in {owner}.{hint}";
6901
7532
  readonly contextValueReturnHint: " Return Value only belongs in Blueprint Value graphs.";
7533
+ readonly elementOtherSurface: "\"{node}\" refers to {element} on another page or Game UI. A blueprint reaches only the elements of its own page or component, and at run time this node is refused. Move the change to a blueprint on that page.";
7534
+ readonly elementNamed: "\"{name}\"";
7535
+ readonly elementUnnamed: "an unnamed element";
6902
7536
  readonly contextListItemHint: " It reads the list row it runs for, and nothing here draws one.";
6903
7537
  readonly noRuntime: "Node \"{node}\" has no runtime.";
6904
7538
  readonly inputMissing: "\"{node}\" has nothing connected to \"{pin}\".";
@@ -6906,6 +7540,7 @@ declare const en: {
6906
7540
  readonly stepLimitGlobal: "\"{head}\" in App logic stopped at \"{node}\" after {steps} steps without a wait.";
6907
7541
  readonly unknownType: "Unknown node type \"{type}\". Its plugin may be uninstalled or disabled.";
6908
7542
  readonly variableIdInvalid: "Node \"{node}\": pick a variable.";
7543
+ readonly loopBodyNotClosed: "\"{node}\" runs its loop body once. The end of the body is not connected back to this node's In. To run the next pass, connect the end of the body to \"{node}\".";
6909
7544
  readonly persistentVariableIdInvalid: "Node \"{node}\": pick a persistent variable.";
6910
7545
  readonly savedVariableIdInvalid: "Node \"{node}\": pick a saved variable.";
6911
7546
  readonly fieldMissing: "\"{node}\": {struct} has no field \"{field}\".";
@@ -7361,6 +7996,7 @@ declare const en: {
7361
7996
  readonly slider: "Slider";
7362
7997
  readonly sound: "Sound";
7363
7998
  readonly switch: "Switch";
7999
+ readonly video: "Video";
7364
8000
  readonly text: "Text";
7365
8001
  readonly textInput: "Text Input";
7366
8002
  readonly variables: "Variables";
@@ -7451,6 +8087,9 @@ declare const en: {
7451
8087
  readonly heightPct: "Height %";
7452
8088
  readonly insert: "Insert";
7453
8089
  readonly isPlaying: "Is Playing";
8090
+ readonly isEnded: "Is Ended";
8091
+ readonly muted: "Muted";
8092
+ readonly speed: "Speed";
7454
8093
  readonly keys: "Keys";
7455
8094
  readonly label: "Label";
7456
8095
  readonly leftPct: "Left %";
@@ -7635,6 +8274,7 @@ declare const en: {
7635
8274
  readonly success: "Success";
7636
8275
  readonly string: "String";
7637
8276
  readonly switch: "Switch";
8277
+ readonly video: "Video";
7638
8278
  readonly targetElement: "Target element";
7639
8279
  readonly targetPage: "Target page";
7640
8280
  readonly text: "Text";
@@ -7962,6 +8602,7 @@ declare const en: {
7962
8602
  readonly getNametag: "Get Nametag";
7963
8603
  readonly getNormalizedValue: "Get Normalized Value";
7964
8604
  readonly getNotifications: "Get Notifications";
8605
+ readonly postNotification: "Post Notification";
7965
8606
  readonly getOpacity: "Get Opacity";
7966
8607
  readonly getPageParam: "Get Page Param";
7967
8608
  readonly getPageProps: "Get Page Props";
@@ -8234,6 +8875,21 @@ declare const en: {
8234
8875
  readonly turnSwitchOn: "Turn Switch On";
8235
8876
  readonly turnedOff: "Turned Off";
8236
8877
  readonly turnedOn: "Turned On";
8878
+ readonly playbackEnded: "Playback Ended";
8879
+ readonly playVideo: "Play Video";
8880
+ readonly pauseVideo: "Pause Video";
8881
+ readonly stopVideo: "Stop Video";
8882
+ readonly seekVideo: "Seek Video";
8883
+ readonly getVideoTime: "Get Video Time";
8884
+ readonly getVideoDuration: "Get Video Duration";
8885
+ readonly isVideoPlaying: "Is Video Playing";
8886
+ readonly isVideoEnded: "Is Video Ended";
8887
+ readonly setVideoVolume: "Set Video Volume";
8888
+ readonly setVideoMuted: "Set Video Muted";
8889
+ readonly setVideoLoop: "Set Video Loop";
8890
+ readonly setVideoSpeed: "Set Video Speed";
8891
+ readonly getVideoVolume: "Get Video Volume";
8892
+ readonly isVideoMuted: "Is Video Muted";
8237
8893
  readonly undoLastHistoryEntry: "Undo Last History Entry";
8238
8894
  readonly unmount: "Unmount";
8239
8895
  readonly valueChanged: "Value Changed";
@@ -8281,11 +8937,27 @@ declare const en: {
8281
8937
  readonly goBack: "Closes the current page and returns to the page beneath it. On the bottom page it does nothing.";
8282
8938
  readonly replacePage: "Opens a page in place of the current page, and closes the current page. Go back and Go Page set to None do not return to it.";
8283
8939
  readonly isGameOverlay: "True when this page, layer or Game UI is shown over a running game. In App logic, true while a page or a modal layer covers the story.";
8940
+ readonly postNotification: "Shows Message as a notification in the running game, in the same place as the game's own notices. A project with a Notifications Game UI shows it there. Duration is in seconds, and 3 seconds when left empty. Get Notifications lists the notification until it closes. Needs a running game.";
8284
8941
  readonly localizationGetText: "Gets a translation key's text in the player's current language, or its source text when that language has no translation. A key that does not exist gives its name. Translation Key Text gives the same text and can also be used in Blueprint Value and functions.";
8285
8942
  readonly translationKeyText: "A translation key's text in the player's current language, or its source text when that language has no translation. A key that does not exist gives its name. The same text as Get Text, and also usable in Blueprint Value and functions. A Blueprint Value that shows it updates when the player changes language.";
8286
8943
  readonly format: "Replaces the placeholders in Template with values: {0}, {1} and so on with the items of an array, {name} with the field of that name in an object. A placeholder with no value becomes empty. A translated template comes from Translation Key Text.";
8287
8944
  readonly formatText: "Replaces {0}, {1} and so on in Text with the items of Values. Format does the same, also fills {name} from an object, and can be used in Blueprint Value and functions.";
8288
8945
  readonly getField: "One field of the struct wired into Object, picked from that struct's fields. Inside a list row, leave Object unwired to read the row. Use Get JSON Field for an object whose fields are not declared.";
8946
+ readonly playbackEnded: "Runs each time the clip plays to its end. Does not run while Loop is on, when the clip is replaced, or when the page closes before the end.";
8947
+ readonly playVideo: "Starts the video, or resumes it from where it was paused. After the clip has ended, plays it again from the start. Plays at the volume the player has set, as Autoplay does. A clip that has not loaded yet starts once it has.";
8948
+ readonly pauseVideo: "Pauses the video where it is. Play Video resumes it from there.";
8949
+ readonly stopVideo: "Pauses the video and returns it to the start of the clip.";
8950
+ readonly seekVideo: "Moves the video to Time, in seconds from the start of the clip. A time past the end moves it to the end, and a negative time to the start. A playing video keeps playing and a paused one stays paused. A playing video moved to its end runs Playback Ended.";
8951
+ readonly getVideoTime: "Where the video is, in seconds from the start of the clip. 0 while there is no clip on screen.";
8952
+ readonly getVideoDuration: "How long the clip is, in seconds. 0 until the clip has loaded.";
8953
+ readonly isVideoPlaying: "True while the video is playing. False while it is paused, stopped or at its end, and while there is no clip on screen.";
8954
+ readonly isVideoEnded: "True once the clip has played to its end, until it is played or moved again. Never true while Loop is on.";
8955
+ readonly setVideoVolume: "Sets the video's volume, from 0 to 1, in place of the volume set on the widget. The player's volume settings and the audio track still apply on top.";
8956
+ readonly setVideoMuted: "Mutes or unmutes the video. A muted video plays silently at any volume.";
8957
+ readonly setVideoLoop: "Turns Loop on or off. While Loop is on, the clip starts over at its end and Playback Ended does not run.";
8958
+ readonly setVideoSpeed: "Sets how fast the video plays: 1 is normal speed, 2 twice as fast, 0.5 half as fast. Kept between 0.0625 and 16.";
8959
+ readonly getVideoVolume: "The video's volume, from 0 to 1: the one set on the widget, or by Set Video Volume. The player's volume settings are not included.";
8960
+ readonly isVideoMuted: "True while the video is muted.";
8289
8961
  };
8290
8962
  readonly live: {
8291
8963
  readonly nodeClaimed: "{name} is editing this node";
@@ -8346,6 +9018,8 @@ declare const en: {
8346
9018
  readonly history: {
8347
9019
  readonly deleteCharacter: "delete character {name}";
8348
9020
  readonly renameCharacter: "rename character {name}";
9021
+ readonly createCharacter: "create character {name}";
9022
+ readonly editCharacter: "edit character {name}";
8349
9023
  readonly deleteGroup: "delete group {name}";
8350
9024
  };
8351
9025
  readonly create: {
@@ -8625,6 +9299,17 @@ declare const en: {
8625
9299
  readonly backgroundImage: "Background Image";
8626
9300
  readonly animation: "Animation";
8627
9301
  readonly logic: "Logic";
9302
+ readonly navigation: {
9303
+ readonly title: "Navigation";
9304
+ readonly defaultFocus: "Starting focus";
9305
+ readonly defaultFocusAuto: "Automatic";
9306
+ readonly autoFocus: "Focus on open";
9307
+ readonly autoFocusTip: "Whether a control takes the focus when this interface opens. By default only when the player last used a keyboard or a gamepad.";
9308
+ readonly autoFocusDevice: "Keyboard or gamepad";
9309
+ readonly autoFocusAlways: "Always";
9310
+ readonly autoFocusNever: "Never";
9311
+ readonly wrap: "Loop at edges";
9312
+ };
8628
9313
  readonly input: {
8629
9314
  readonly title: "Input";
8630
9315
  readonly actions: "Actions answered";
@@ -8663,6 +9348,27 @@ declare const en: {
8663
9348
  readonly uiElement: "UI Element";
8664
9349
  readonly linkedComponent: "Linked Component";
8665
9350
  };
9351
+ readonly navigation: {
9352
+ readonly title: "Navigation";
9353
+ readonly focusable: "Focusable";
9354
+ readonly focusableTip: "Whether keyboard and gamepad navigation can move onto this element. Controls can by default. Never also excludes every element inside it.";
9355
+ readonly focusableAuto: "Automatic";
9356
+ readonly focusableAlways: "Always";
9357
+ readonly focusableNever: "Never";
9358
+ readonly preferredOnEntry: "Use as starting focus";
9359
+ readonly preferredOnEntryTip: "The focus starts on this element when the interface opens, unless the interface's Starting focus names another.";
9360
+ readonly region: "Navigation group";
9361
+ readonly regionTip: "Navigation stays inside this element while a control inside lies in the pressed direction.";
9362
+ readonly wrap: "Loop at edges";
9363
+ readonly rememberLast: "Remember last focus";
9364
+ readonly up: "Up";
9365
+ readonly down: "Down";
9366
+ readonly left: "Left";
9367
+ readonly right: "Right";
9368
+ readonly byLayout: "By layout";
9369
+ readonly neighborsTip: "Where each direction goes when the focus leaves this element. By layout picks the nearest control in that direction.";
9370
+ readonly numbered: "{name} {index}";
9371
+ };
8666
9372
  readonly interactionSound: {
8667
9373
  readonly title: "Sound";
8668
9374
  readonly hover: "Hover";
@@ -9021,42 +9727,74 @@ declare const en: {
9021
9727
  readonly motionAsset: "Motion asset";
9022
9728
  readonly choosePlaceholder: "Choose motion\u2026";
9023
9729
  };
9024
- readonly panel: {
9730
+ readonly library: {
9025
9731
  readonly searchPlaceholder: "Search motions";
9026
- readonly libraryActions: "Import and export";
9027
- readonly createMotion: "Create motion";
9028
- readonly empty: "No motions.";
9732
+ readonly targetKind: "Target";
9733
+ readonly allKinds: "All targets";
9029
9734
  readonly newMotion: "New Motion";
9030
- readonly motionActions: "Motion actions";
9031
- readonly repeat: "Repeat";
9032
- readonly repeatDelaySeconds: "Repeat delay (s)";
9033
- readonly actionUses: "Current action uses {name}";
9034
- readonly actionUsesMissing: "Current action uses a motion this project no longer has";
9035
- readonly previewAssetMissing: "Missing image";
9036
- readonly actionNoMotion: "Current action has no motion asset";
9037
- readonly bindToAction: "Bind to action";
9038
- readonly target: "Target";
9039
- readonly background: "Background";
9040
- readonly previewTarget: "Preview target";
9041
- readonly previewBackground: "Preview background";
9042
- readonly previewTargetTitle: "Preview target image (editor only)";
9043
- readonly previewBackgroundTitle: "Preview background image (editor only)";
9044
- readonly selectOrCreate: "Select or create a story motion.";
9045
- readonly deleteConfirm: "Delete motion \"{name}\"?";
9735
+ readonly blankMotion: "Blank motion";
9736
+ readonly noMatches: "No matching motions.";
9737
+ readonly unreadable: "Could not be read";
9738
+ readonly repeats: {
9739
+ readonly one: "Repeats once";
9740
+ readonly other: "Repeats {count} times";
9741
+ };
9742
+ readonly inUseTip: "The current row uses this motion.";
9743
+ readonly copyName: "{name} copy";
9744
+ readonly deleteOne: "Delete motion \"{name}\"?";
9745
+ readonly deleteMany: "Delete {count} motions?";
9046
9746
  readonly deleteDetail: "The motion asset is removed and related editors are closed.";
9047
- readonly clearAria: "Clear {name}";
9747
+ readonly useOnRow: "Use on Current Row";
9748
+ readonly useOnRowTip: "Sets the selected motion on the row focused in the story editor.";
9749
+ readonly useOnRowNeedsOne: "Select one motion.";
9750
+ readonly useOnRowWrongKind: "The current row takes a {kind} motion.";
9751
+ readonly useOnRowAlready: "The current row already uses this motion.";
9752
+ readonly selected: {
9753
+ readonly one: "{count} selected";
9754
+ readonly other: "{count} selected";
9755
+ };
9756
+ readonly count: {
9757
+ readonly one: "{count} motion";
9758
+ readonly other: "{count} motions";
9759
+ };
9760
+ };
9761
+ readonly inspector: {
9762
+ readonly target: "Target";
9763
+ readonly duration: "Duration";
9764
+ readonly properties: "Properties";
9765
+ readonly noProperties: "None";
9766
+ readonly listSeparator: ", ";
9767
+ readonly playback: "Playback";
9768
+ readonly repeat: "Repeats";
9769
+ readonly repeatDelaySeconds: "Pause between repeats (s)";
9770
+ readonly previewImages: "Preview pictures";
9771
+ readonly previewImagesTip: "Drawn only in the editor's previews. In the game the row's own object moves.";
9772
+ readonly previewTarget: "Object";
9773
+ readonly previewBackground: "Background";
9048
9774
  };
9049
9775
  readonly editor: {
9050
9776
  readonly loading: "Loading motion asset\u2026";
9051
9777
  readonly assetDeleted: "Motion asset was deleted.";
9052
9778
  readonly play: "Play";
9053
9779
  readonly pause: "Pause";
9054
- readonly animatedProperties: "Animated properties";
9780
+ readonly toStart: "Go to start";
9781
+ readonly previousFrame: "Previous frame";
9782
+ readonly nextFrame: "Next frame";
9783
+ readonly loop: "Loop";
9784
+ readonly stageZoom: "Stage zoom";
9785
+ readonly zoomFit: "Fit";
9786
+ readonly resizeTimeline: "Resize timeline";
9787
+ readonly frame: "Frame {frame} of {total}";
9788
+ readonly keyframesSelected: "{count} keyframes";
9055
9789
  readonly addProperty: "Add property";
9056
9790
  readonly addKeyframeAtPlayhead: "Add keyframe at playhead";
9791
+ readonly addKeyframeHere: "Add keyframe here";
9057
9792
  readonly addKeyframeAria: "Add {property} keyframe at playhead";
9793
+ readonly removeKeyframeAria: "Remove {property} keyframe at playhead";
9794
+ readonly previousKeyframe: "Previous keyframe";
9795
+ readonly nextKeyframe: "Next keyframe";
9796
+ readonly selectTrackKeyframes: "Select keyframes on this track";
9058
9797
  readonly deleteTrack: "Delete track";
9059
- readonly deleteTrackAria: "Delete {property} track";
9060
9798
  };
9061
9799
  readonly keyframe: {
9062
9800
  readonly loading: "Loading keyframe\u2026";
@@ -9283,6 +10021,21 @@ declare const en: {
9283
10021
  readonly one: "{count} interface";
9284
10022
  readonly other: "{count} interfaces";
9285
10023
  };
10024
+ readonly navigationTitle: "Focus navigation";
10025
+ readonly navigation: {
10026
+ readonly up: "Move up";
10027
+ readonly down: "Move down";
10028
+ readonly left: "Move left";
10029
+ readonly right: "Move right";
10030
+ readonly next: "Next control";
10031
+ readonly previous: "Previous control";
10032
+ readonly confirm: "Confirm";
10033
+ readonly cancel: "Back";
10034
+ readonly menu: "Quick menu";
10035
+ };
10036
+ readonly navigationNone: "None";
10037
+ readonly navigationTag: "Focus navigation: {slot}";
10038
+ readonly fillNavigationSlots: "Add actions for empty slots";
9286
10039
  readonly noBindings: "No bindings";
9287
10040
  readonly addBinding: "Add binding";
9288
10041
  readonly removeBinding: "Remove {binding}";
@@ -9800,6 +10553,37 @@ declare const en: {
9800
10553
  readonly image: {
9801
10554
  readonly title: "Image";
9802
10555
  };
10556
+ readonly inputHints: {
10557
+ readonly title: "Input Hints";
10558
+ readonly sectionContent: "Content";
10559
+ readonly sectionStyle: "Style";
10560
+ readonly sectionWords: "Words";
10561
+ readonly showFor: "Show for";
10562
+ readonly showForKeysAndGamepad: "Keyboard and gamepad";
10563
+ readonly showForGamepad: "Gamepad only";
10564
+ readonly showForAlways: "Every device";
10565
+ readonly showForTip: "The inputs the bar shows hints for. While any other input is in use, it shows none.";
10566
+ readonly glyphStyle: "Button glyphs";
10567
+ readonly glyphAuto: "Match the connected controller";
10568
+ readonly glyphXbox: "Xbox";
10569
+ readonly glyphPlayStation: "PlayStation";
10570
+ readonly glyphNintendo: "Nintendo";
10571
+ readonly align: "Alignment";
10572
+ readonly alignStart: "Start";
10573
+ readonly alignCenter: "Center";
10574
+ readonly alignEnd: "End";
10575
+ readonly fontSize: "Font size";
10576
+ readonly color: "Text color";
10577
+ readonly glyphBackground: "Glyph fill";
10578
+ readonly glyphColor: "Glyph text";
10579
+ readonly gap: "Spacing";
10580
+ readonly wordsTip: "Left empty, each hint uses Studio's own word in the player's language. Actions the project declares are named by their own names.";
10581
+ readonly wordSelect: "Select";
10582
+ readonly wordConfirm: "Confirm";
10583
+ readonly wordBack: "Back";
10584
+ readonly wordAdvance: "Advance";
10585
+ readonly wordStageControls: "Quick menu";
10586
+ };
9803
10587
  readonly video: {
9804
10588
  readonly title: "Video";
9805
10589
  readonly sectionSource: "Source";
@@ -9818,7 +10602,7 @@ declare const en: {
9818
10602
  readonly loop: "Loop";
9819
10603
  readonly muted: "Muted";
9820
10604
  readonly autoplay: "Autoplay";
9821
- readonly autoplayHint: "Applies in the game. The editor canvas stays paused; use the docker bar to preview.";
10605
+ readonly autoplayHint: "Applies in the game. The editor canvas stays paused; use the toolbar to preview.";
9822
10606
  readonly volume: "Volume";
9823
10607
  readonly volumeHint: "0 to 1. A blueprint volume pin overrides this at runtime.";
9824
10608
  readonly audioTrack: "Audio Track";
@@ -9836,6 +10620,7 @@ declare const en: {
9836
10620
  readonly previewPlay: "Preview playback";
9837
10621
  readonly previewPause: "Pause preview";
9838
10622
  readonly previewRestart: "Back to first frame";
10623
+ readonly playRefused: "Video \u201C{name}\u201D did not start playing. A video with sound plays only after the player has clicked or pressed a key; a muted one plays at once.";
9839
10624
  };
9840
10625
  readonly puppet: {
9841
10626
  readonly title: "Model";
@@ -9917,6 +10702,9 @@ declare const en: {
9917
10702
  readonly nameText: "{name} text";
9918
10703
  };
9919
10704
  readonly defaults: {
10705
+ readonly inputHints: {
10706
+ readonly name: "Input Hints";
10707
+ };
9920
10708
  readonly button: {
9921
10709
  readonly name: "Button";
9922
10710
  readonly label: "Button";
@@ -10388,6 +11176,8 @@ declare const en: {
10388
11176
  readonly buildDescription: "Build, packaging, and preview pipeline output";
10389
11177
  readonly storyDescription: "Story scene preview diagnostics and warnings";
10390
11178
  readonly storageDescription: "Project file writes: failed saves, retries, and recoveries";
11179
+ readonly agent: "Agent";
11180
+ readonly agentDescription: "Calls from AI agents connected to Studio";
10391
11181
  };
10392
11182
  readonly sources: {
10393
11183
  readonly blueprintLog: "Blueprint Log";
@@ -10989,11 +11779,12 @@ declare const en: {
10989
11779
  readonly identity: "Author";
10990
11780
  readonly team: "Team";
10991
11781
  readonly story: "Story editor";
11782
+ readonly agent: "Agent access";
10992
11783
  readonly done: "Done";
10993
11784
  };
10994
11785
  readonly welcome: {
10995
11786
  readonly title: "Welcome";
10996
- readonly expectation: "Six interface and story-editor settings. Each one takes effect immediately and remains available in Settings.";
11787
+ readonly expectation: "Seven settings for the interface, the story editor and agent access. Each one takes effect immediately and remains available in Settings.";
10997
11788
  readonly haveSettings: "Settings from another installation";
10998
11789
  };
10999
11790
  readonly language: {
@@ -11027,6 +11818,11 @@ declare const en: {
11027
11818
  readonly title: "Story editor";
11028
11819
  readonly expectation: "How the scene editor is read and typed in.";
11029
11820
  };
11821
+ readonly agent: {
11822
+ readonly title: "Agent access";
11823
+ readonly expectation: "An AI agent connects to Studio over MCP and edits the open project. An agent is optional.";
11824
+ readonly toggleFailed: "Agent access could not be changed: {error}";
11825
+ };
11030
11826
  readonly import: {
11031
11827
  readonly action: "Import settings\u2026";
11032
11828
  readonly leaves: "Applying these settings ends setup and opens Studio.";
@@ -11197,6 +11993,7 @@ declare const en: {
11197
11993
  readonly assets: "Assets";
11198
11994
  readonly console: "Console";
11199
11995
  readonly problems: "Problems";
11996
+ readonly agentLog: "Agent Log";
11200
11997
  readonly storyMotion: "Story Motion";
11201
11998
  readonly dashboard: "Dashboard";
11202
11999
  readonly audioPreview: "Audio Preview";
@@ -11273,9 +12070,9 @@ declare const en: {
11273
12070
  readonly name: "Project Name";
11274
12071
  readonly namePlaceholder: "Project name";
11275
12072
  readonly appIdPlaceholder: "App identifier";
11276
- readonly appIdHelper: "Lowercase letters, digits and hyphens only. Cannot be changed after creation.";
12073
+ readonly appIdHelper: "Lowercase letters, digits and hyphens, or a reverse-domain id such as com.studio.game. Cannot be changed after creation.";
11277
12074
  readonly appIdRequired: "App ID is required";
11278
- readonly appIdInvalid: "App ID can only contain lowercase letters, numbers, and hyphens";
12075
+ readonly appIdInvalid: "App ID can only contain lowercase letters, numbers and hyphens, with dots only between the parts of a reverse-domain id such as com.studio.game";
11279
12076
  readonly locationPlaceholder: "Project location";
11280
12077
  readonly browseLocation: "Choose folder";
11281
12078
  readonly validatingDirectory: "Checking the folder\u2026";
@@ -11628,8 +12425,18 @@ declare const en: {
11628
12425
  readonly network: "Data the game requests";
11629
12426
  readonly networkNote: "This plugin requests data from these addresses while the game runs.";
11630
12427
  readonly studio: "Studio permissions";
12428
+ readonly agentTools: "AI agents";
11631
12429
  };
11632
12430
  readonly sidecarPlatforms: "Runs on {platforms}";
12431
+ readonly agentToolsSummary: "{tools} ({writes})";
12432
+ readonly agentTools: {
12433
+ readonly one: "Offers {count} tool to AI agents connected to Studio";
12434
+ readonly other: "Offers {count} tools to AI agents connected to Studio";
12435
+ };
12436
+ readonly agentToolsWrites: {
12437
+ readonly one: "{count} can change the project";
12438
+ readonly other: "{count} can change the project";
12439
+ };
11633
12440
  readonly sidecarKind: {
11634
12441
  readonly executable: "Runs as a separate program";
11635
12442
  readonly node: "Runs the plugin's own code as part of the game";
@@ -12692,6 +13499,19 @@ declare const en: {
12692
13499
  readonly deleted: "The page this row names is no longer in the project, so the playthrough ends with nothing on screen";
12693
13500
  readonly help: string;
12694
13501
  };
13502
+ readonly storyInputActionMissing: {
13503
+ readonly title: "Wait for a missing input action";
13504
+ readonly description: "A /waitinput, /hold or /mash row naming an input action the project no longer has";
13505
+ readonly message: "The input action this row waits for is no longer in the project, so the story stops here for good";
13506
+ readonly timed: "The input action this row waits for is no longer in the project, so the row always fails when its time limit ends";
13507
+ readonly help: string;
13508
+ };
13509
+ readonly storyInputLockedDialogue: {
13510
+ readonly title: "Line inside a locked passage";
13511
+ readonly description: "A line or /wait click after /input lock with no /input unlock before it";
13512
+ readonly message: "Player input is locked here, so this row cannot be advanced. Add /input unlock before it";
13513
+ readonly help: string;
13514
+ };
12695
13515
  readonly storyEndingNameDuplicate: {
12696
13516
  readonly title: "Two endings with one name";
12697
13517
  readonly description: "More than one ending sharing a display name";
@@ -12715,6 +13535,7 @@ declare const en: {
12715
13535
  readonly description: "A row acting on an object no row in the scene creates";
12716
13536
  readonly message: "No row in this scene creates {object}, so this row has nothing to act on";
12717
13537
  readonly messageCharacter: "No row in this scene brings {object} on stage, so this row has nothing to act on";
13538
+ readonly messageLayer: "This scene has no layer {object}, so this row has nothing to act on";
12718
13539
  readonly help: string;
12719
13540
  };
12720
13541
  readonly storyDeclaredNeverShown: {
@@ -13113,6 +13934,7 @@ declare const en: {
13113
13934
  readonly severity: {
13114
13935
  readonly error: "Error";
13115
13936
  readonly warning: "Warning";
13937
+ readonly minor: "Minor warning";
13116
13938
  readonly info: "Info";
13117
13939
  readonly off: "Off";
13118
13940
  };
@@ -13120,7 +13942,7 @@ declare const en: {
13120
13942
  readonly title: "Problems";
13121
13943
  readonly empty: "No problems found";
13122
13944
  readonly running: "Checking\u2026";
13123
- readonly counts: "{errors}, {warnings}, {infos}";
13945
+ readonly counts: "{errors}, {warnings}, {minorWarnings}, {infos}";
13124
13946
  readonly filtered: "{shown} of {total}";
13125
13947
  readonly rerun: "Run again";
13126
13948
  readonly filterAll: "All";
@@ -13148,7 +13970,7 @@ declare const en: {
13148
13970
  readonly jumpFailed: "This location can no longer be opened";
13149
13971
  };
13150
13972
  readonly statusBar: {
13151
- readonly counts: "Problems: {errors}, {warnings}, {infos}";
13973
+ readonly counts: "Problems: {errors}, {warnings}, {minorWarnings}, {infos}";
13152
13974
  };
13153
13975
  readonly command: {
13154
13976
  readonly runProject: "Check project";
@@ -14504,6 +15326,13 @@ declare const en: {
14504
15326
  };
14505
15327
  };
14506
15328
  readonly game: {
15329
+ readonly inputHints: {
15330
+ readonly select: "Select";
15331
+ readonly confirm: "Confirm";
15332
+ readonly back: "Back";
15333
+ readonly advance: "Next";
15334
+ readonly stageControls: "Menu";
15335
+ };
14507
15336
  readonly saveLoad: {
14508
15337
  readonly refused: "This save could not be loaded. The game continues from the current point.";
14509
15338
  readonly refusedOtherStory: "This save was written from a different version of the story. The game continues from the current point.";
@@ -14744,7 +15573,7 @@ type PluginFileSystemPermissionMode = "read" | "write" | "readwrite";
14744
15573
  * - **Author-declared** (`filesystem`, `api`) — privileged Studio controls the
14745
15574
  * plugin asks for explicitly in `permissions[]`.
14746
15575
  * - **Derived** (`runtime`, `sidecar`, `buildDependency`, `externalLink`,
14747
- * `network`) — computed from `contributes` by {@link validatePluginManifest}
15576
+ * `network`, `agentTools`) — computed from `contributes` by {@link validatePluginManifest}
14748
15577
  * and *rejected* if written by
14749
15578
  * hand. A capability is declared in exactly one place, so what the prompt shows
14750
15579
  * and what the plugin can actually reach cannot drift apart. Adding a
@@ -14817,6 +15646,21 @@ export type PluginInstallPermission = {
14817
15646
  */
14818
15647
  kind: "network";
14819
15648
  patterns: string[];
15649
+ } | {
15650
+ /**
15651
+ * Derived from `contributes.agentTools`: tools this plugin offers the AI agents an author
15652
+ * connects to Studio. Informational more than it is a power - every call still passes the
15653
+ * author's own switches (agent access, write access, pause) - but it is code an outside
15654
+ * program can start, and the author hears about it here, by count, before it can happen.
15655
+ *
15656
+ * Names rather than a count, so a later version that adds a tool, or turns a reading tool
15657
+ * into one that changes the project, widens the set and asks again.
15658
+ */
15659
+ kind: "agentTools";
15660
+ /** Every declared tool. */
15661
+ tools: string[];
15662
+ /** The ones that change the project; a subset of `tools`. */
15663
+ writeTools: string[];
14820
15664
  };
14821
15665
  type PluginSidecarKind = "executable" | "node";
14822
15666
  declare const PluginRuntimeCapability: {
@@ -15219,6 +16063,31 @@ export type PluginContributes = {
15219
16063
  * any plugin code runs. Ids must start with the plugin id.
15220
16064
  */
15221
16065
  structs?: PluginStructContribution[];
16066
+ /**
16067
+ * Tools this plugin offers the AI agents an author connects to Studio (the built-in MCP
16068
+ * endpoint), registered by the studio entry with `app.services.agent.registerTool`.
16069
+ *
16070
+ * Declared here, and refused at registration when not, for the reason `tests` are: the install
16071
+ * prompt is read before any plugin code runs, and an outside program reaching into the plugin is
16072
+ * something the author should be told about there. Unlike `tests` it derives an install
16073
+ * permission (`kind: "agentTools"`), because a tool is callable by somebody other than the author
16074
+ * the moment the plugin loads - and `write` is part of the declaration, so a tool that starts
16075
+ * changing the project in a later version asks again.
16076
+ */
16077
+ agentTools?: PluginAgentToolContribution[];
16078
+ /**
16079
+ * Package-relative path to a Markdown chapter for agents (`agent/guide.md`), served by
16080
+ * `agent_guide` as `plugin:<pluginId>` and as the resource `narraleaf://guide/plugin/<pluginId>`.
16081
+ * Empty when the plugin ships none.
16082
+ */
16083
+ agentGuide?: string;
16084
+ };
16085
+ /** One tool a plugin offers AI agents, as its manifest declares it. */
16086
+ export type PluginAgentToolContribution = {
16087
+ /** `<pluginId>.<tool>`: lower case, digits, `_`, `.` and `-`. */
16088
+ name: string;
16089
+ /** The tool changes the project. Must match the registration. */
16090
+ write: boolean;
15222
16091
  };
15223
16092
  type PluginStructContribution = {
15224
16093
  /** Prefixed with the plugin id: `narraleaf.gallery.entry`. */
@@ -15527,6 +16396,59 @@ type GameProcessMemoryReading = {
15527
16396
  /** The sum of every process's private bytes, or null where the platform does not report them. */
15528
16397
  privateBytes: number | null;
15529
16398
  };
16399
+ declare const UI_NAVIGATION_DIRECTIONS: readonly [
16400
+ "up",
16401
+ "down",
16402
+ "left",
16403
+ "right"
16404
+ ];
16405
+ type UINavigationDirection = (typeof UI_NAVIGATION_DIRECTIONS)[number];
16406
+ declare const UI_FOCUSABILITY_VALUES: readonly [
16407
+ "auto",
16408
+ "always",
16409
+ "never"
16410
+ ];
16411
+ type UIFocusability = (typeof UI_FOCUSABILITY_VALUES)[number];
16412
+ type UINavigationRegion = {
16413
+ /** Moving past the last control inside comes back round to the first, rather than leaving. */
16414
+ wrap?: boolean;
16415
+ /** Coming back into the group lands on the control the player left it from. */
16416
+ rememberLast?: boolean;
16417
+ };
16418
+ type UIElementNavigation = {
16419
+ focusable?: UIFocusability;
16420
+ /** Where one direction goes from here, by element id, overriding what the layout would say. */
16421
+ neighbors?: Partial<Record<UINavigationDirection, UIElementId>>;
16422
+ /** Present makes this element a group. Only meaningful on an element that holds children. */
16423
+ region?: UINavigationRegion;
16424
+ /** Where the focus lands when the surface opens, unless the surface names an element itself. */
16425
+ preferredOnEntry?: boolean;
16426
+ };
16427
+ declare const UI_NAVIGATION_AUTO_FOCUS_VALUES: readonly [
16428
+ "device",
16429
+ "always",
16430
+ "never"
16431
+ ];
16432
+ type UINavigationAutoFocus = (typeof UI_NAVIGATION_AUTO_FOCUS_VALUES)[number];
16433
+ type UISurfaceNavigation = {
16434
+ /** The element the focus starts on. Absent: the one marked `preferredOnEntry`, else the first. */
16435
+ defaultFocusElementId?: UIElementId;
16436
+ autoFocus?: UINavigationAutoFocus;
16437
+ /** Moving past the edge of the surface comes back round from the other side. */
16438
+ wrap?: boolean;
16439
+ };
16440
+ declare const UI_NAVIGATION_SLOTS: readonly [
16441
+ "up",
16442
+ "down",
16443
+ "left",
16444
+ "right",
16445
+ "next",
16446
+ "previous",
16447
+ "confirm",
16448
+ "cancel",
16449
+ "menu"
16450
+ ];
16451
+ type UINavigationSlot = (typeof UI_NAVIGATION_SLOTS)[number];
15530
16452
  declare const UI_INPUT_POINTER_GESTURES: readonly [
15531
16453
  "click",
15532
16454
  "doubleClick",
@@ -15555,6 +16477,12 @@ type UIInputActionDef = {
15555
16477
  name: string;
15556
16478
  /** The bindings a surface gets unless it overrides them. */
15557
16479
  bindings: UIInputBinding[];
16480
+ /**
16481
+ * The navigation operation this intent performs, if any (see `navigation.ts`): its bindings move
16482
+ * the focus, confirm, back out. One intent per slot - the library keeps the first that claims
16483
+ * one - and absent on every intent of a project that has no keyboard or pad navigation.
16484
+ */
16485
+ navigationSlot?: UINavigationSlot;
15558
16486
  };
15559
16487
  type UISurfaceActionEnablement = {
15560
16488
  actionId: string;
@@ -15730,6 +16658,8 @@ type UISurfaceSettings = {
15730
16658
  */
15731
16659
  backgroundImage?: UISurfaceBackgroundImage;
15732
16660
  pageAnimation?: UIPageAnimationSettings;
16661
+ /** Where the focus starts when this Surface opens, and whether it is put there. See `navigation.ts`. */
16662
+ navigation?: UISurfaceNavigation;
15733
16663
  /**
15734
16664
  * What the asset set this Surface's own background names resolves to, per locale. Build-written
15735
16665
  * exactly as {@link UIElement.assetVariants} is, and here rather than on the Surface so the
@@ -15790,6 +16720,15 @@ type UIElement = {
15790
16720
  * even though its props come from the definition.
15791
16721
  */
15792
16722
  animation?: UIPageAnimationSettings;
16723
+ /**
16724
+ * How the player reaches this element without a pointer - whether it can hold the focus, where
16725
+ * a direction goes from it, whether it is a group. Absent on almost every element: a control is
16726
+ * reachable without saying so. Read it through `navigation.ts`.
16727
+ *
16728
+ * Its own field for the reason {@link animation} is: it belongs to the placement, every type has
16729
+ * one, and a linked component instance may set it.
16730
+ */
16731
+ navigation?: UIElementNavigation;
15793
16732
  extra?: Record<string, unknown>;
15794
16733
  /**
15795
16734
  * What each asset set THIS element names resolves to, per locale.
@@ -17166,6 +18105,15 @@ declare class Character {
17166
18105
  * same way. Both would break if a record were a new object.
17167
18106
  */
17168
18107
  adopt(config: CharacterConfig): void;
18108
+ /**
18109
+ * Tell this character's own subscribers that it changed, after an {@link adopt} that told nobody.
18110
+ *
18111
+ * The service's change handler is deliberately left out: whoever adopted a record has already
18112
+ * decided whether it is dirty and announced it to the cast. What is left is the editor holding
18113
+ * this object, which re-renders only from these listeners - without this it would go on drawing
18114
+ * the record from before an undo.
18115
+ */
18116
+ notifySubscribers(): void;
17169
18117
  setOnChange(handler: (() => void) | null): void;
17170
18118
  setOnAssetChange(handler: AssetChangeCallback | null): void;
17171
18119
  /**
@@ -17183,6 +18131,9 @@ type StoryBlockSelection = {
17183
18131
  /** The focused row, or null when the scene itself is the subject. */
17184
18132
  blockId: StoryBlockId | null;
17185
18133
  };
18134
+ type StoryMotionAssetSelection = {
18135
+ animationId: string;
18136
+ };
17186
18137
  type StoryMotionKeyframeSelection = {
17187
18138
  editor: "story-motion";
17188
18139
  tabId: string;
@@ -17352,6 +18303,9 @@ type SelectionState = {
17352
18303
  | {
17353
18304
  type: "scene";
17354
18305
  data: UISurfaceId;
18306
+ } | {
18307
+ type: "storyMotion";
18308
+ data: StoryMotionAssetSelection;
17355
18309
  } | {
17356
18310
  type: "storyMotionKeyframe";
17357
18311
  data: StoryMotionKeyframeSelection;
@@ -17429,6 +18383,10 @@ type LiveUIOp =
17429
18383
  */
17430
18384
  updates?: readonly LiveUIElementRef[];
17431
18385
  };
18386
+ type HistoryLabel = {
18387
+ key: TranslationKey;
18388
+ params?: Record<string, string | number>;
18389
+ };
17432
18390
  type MoveRejectReason = "invalid_surface" | "invalid_target" | "invalid_movers" | "cycle" | "root_locked";
17433
18391
  type MoveUiElementsResult = {
17434
18392
  ok: true;
@@ -17507,6 +18465,21 @@ type ImportTemplateResult = {
17507
18465
  skippedSlots: UIStageSlotId[];
17508
18466
  /** Components copied into the project's library; empty for surface-only templates. */
17509
18467
  importedComponents: UIComponentDefinition[];
18468
+ /** Each imported surface's id in this document, by its id in the source. Skipped ones are absent. */
18469
+ surfaceIdMap: Record<string, string>;
18470
+ /**
18471
+ * Input actions the arriving surfaces answer that this project's vocabulary lacked, adopted under
18472
+ * the source's ids. Unlike the files and translations, they go with the import's undo step (the
18473
+ * caller's, when it records the step itself): an action left behind is not inert - its bindings
18474
+ * keep answering keys - so it is taken back with the surfaces that brought it, unless something
18475
+ * else in the project has come to answer or name it by then.
18476
+ */
18477
+ adoptedActionIds: string[];
18478
+ /**
18479
+ * Key and pad-button bindings of the adopted actions that were left off, by action id, because the
18480
+ * project already gives that key or button a meaning of its own (`adoptArrivingInputActions`).
18481
+ */
18482
+ heldBackBindings: Record<string, UIInputBinding[]>;
17510
18483
  };
17511
18484
  declare const IMPORT_PLACEMENT_FROM_SOURCE: "sourceSurface";
17512
18485
  type ImportTemplatePlacement = UITemplateSurfacePlacement | typeof IMPORT_PLACEMENT_FROM_SOURCE;
@@ -17546,6 +18519,8 @@ declare class UIDocumentService extends Service<UIDocumentService> implements IU
17546
18519
  /** Where edits go instead of into the document, when something else owns them. See {@link UIOpSink}. */
17547
18520
  private opSink;
17548
18521
  private historySuppressionDepth;
18522
+ /** How deep inside {@link runDetachedDraft} this is: edits then land on a private copy and nowhere else. */
18523
+ private draftDepth;
17549
18524
  private readonly contentRevisions;
17550
18525
  /** What the v13 step changed that an author can see, until the workspace has said so. */
17551
18526
  private textSourceMigrationChanges;
@@ -17613,7 +18588,76 @@ declare class UIDocumentService extends Service<UIDocumentService> implements IU
17613
18588
  restoreDocumentFromHistory(document: UIDocument, options?: {
17614
18589
  skipAfterMutateHook?: boolean;
17615
18590
  }): void;
17616
- runSurfaceHistoryTransaction(surfaceId: string, action: () => void): void;
18591
+ /**
18592
+ * Run several of this service's own edits as one undo step on `surfaceId`'s stack.
18593
+ *
18594
+ * `label` names the step in the Edit menu when it is something more particular than an edit to
18595
+ * the surface - an agent's batch of edits says so, so the author can tell it from their own.
18596
+ */
18597
+ runSurfaceHistoryTransaction(surfaceId: string, action: () => void, options?: {
18598
+ label?: HistoryLabel;
18599
+ }): void;
18600
+ /**
18601
+ * {@link runSurfaceHistoryTransaction}, all or nothing: when `action` throws, `surfaceId`'s slice
18602
+ * of both documents - its elements and its widgets' blueprints - is put back exactly as the
18603
+ * editor's own undo would put it, nothing is recorded, and the error is rethrown.
18604
+ *
18605
+ * Through the history snapshot rather than a copy of the interface document, because the edits
18606
+ * inside have already run the blueprint reconcile: a deleted widget's graph is gone, and putting
18607
+ * the element back alone would have the reconcile give it a fresh, empty graph under the same id.
18608
+ */
18609
+ runAtomicSurfaceTransaction(surfaceId: string, action: () => void, options?: {
18610
+ label?: HistoryLabel;
18611
+ }): void;
18612
+ /**
18613
+ * Run this service's own edits against a private copy of the document, then throw the copy away.
18614
+ *
18615
+ * What a dry run needs: every check an edit makes runs exactly as it would for real, against the
18616
+ * document as the earlier edits in the same run left it, and nothing outside this service hears of
18617
+ * any of it - no `documentChanged`, no auto-save, no undo step, no live-session message and, above
18618
+ * all, no blueprint reconcile. The reconcile is not undone by putting the document back: it deletes
18619
+ * the graph of every widget the copy lost, and then gives the restored widget an empty one.
18620
+ *
18621
+ * The document's revision does not move, so nothing that reads it should be asked inside.
18622
+ */
18623
+ runDetachedDraft<T>(action: () => T): T;
18624
+ /**
18625
+ * An edit made by an agent connected over MCP, written as one step of undo.
18626
+ *
18627
+ * Through the private mutator like every gesture, which is the whole point: the canvas redraws
18628
+ * on `documentChanged`, auto-save picks the change up, the blueprint reconcile hook runs, and the
18629
+ * author's Ctrl+Z takes it back - an agent's edit is an edit like any other.
18630
+ *
18631
+ * `scope` says which stack the step belongs on. One page or one component definition: that
18632
+ * editor's own stack, as a snapshot of its slice, so Ctrl+Z inside its tab undoes it. Null - an
18633
+ * edit across several pages, or to a table the pages share - goes on the project's stack as a
18634
+ * command over the delta, diffed both ways, because no one editor's slice covers it (the shape
18635
+ * {@link pushLibraryStep} uses for library operations) - with the private blueprints the write's
18636
+ * reconcile created or deleted, which a delta of interface records alone would leave behind (see
18637
+ * `reconciledBlueprintOwners.ts`).
18638
+ *
18639
+ * Not for a live session: {@link applyLiveOp} is the path for somebody else's edit, and records
18640
+ * nothing. Agent writes are refused while a session runs, before they get here.
18641
+ */
18642
+ applyAgentMutation(scope: {
18643
+ surfaceId: string;
18644
+ } | {
18645
+ componentId: string;
18646
+ } | null, label: HistoryLabel, mutator: (document: UIDocument) => void): void;
18647
+ /**
18648
+ * Write a compiled `.ui` document's pages and definitions, as one step of undo.
18649
+ *
18650
+ * The compile and the write itself belong to the agent core, which hands its writer in as
18651
+ * `mutate` so this service does not depend on it. What is decided here is only where the step is
18652
+ * recorded: one page or one definition goes on that editor's stack, anything wider on the
18653
+ * project's - see {@link applyAgentMutation}.
18654
+ */
18655
+ applyCompiledUi(input: {
18656
+ surfaceIds: readonly string[];
18657
+ componentIds: readonly string[];
18658
+ label: HistoryLabel;
18659
+ mutate: (document: UIDocument) => void;
18660
+ }): void;
17617
18661
  isDirty(): boolean;
17618
18662
  getRevision(): number;
17619
18663
  /**
@@ -17751,6 +18795,22 @@ declare class UIDocumentService extends Service<UIDocumentService> implements IU
17751
18795
  * being a project-level table; a surface that had said otherwise keeps what it said.
17752
18796
  */
17753
18797
  setInputActionBindings(actionId: string, bindings: readonly UIInputBinding[]): void;
18798
+ /**
18799
+ * Put an intent in a navigation slot, or take it out of the one it fills (`slot` null).
18800
+ *
18801
+ * A slot holds one intent, so the intent that held it before gives it up in the same step: the
18802
+ * panel offers every intent for every slot, and picking one is the whole of moving it.
18803
+ */
18804
+ setInputActionNavigationSlot(actionId: string, slot: UINavigationSlot | null): void;
18805
+ /**
18806
+ * Give every empty navigation slot an intent of its own, bound to the keys and pad buttons a
18807
+ * player expects (`UI_NAVIGATION_SLOT_PRESET_BINDINGS`), named in the author's language.
18808
+ *
18809
+ * The way an existing project takes up keyboard and pad navigation: the bindings are written into
18810
+ * the project as the template's are, and are the author's from then on. A slot already filled is
18811
+ * left as the author filled it. Returns how many intents were made.
18812
+ */
18813
+ fillEmptyNavigationSlots(names: Readonly<Record<UINavigationSlot, string>>): number;
17754
18814
  /**
17755
18815
  * Drop one vocabulary entry, and every surface's answer to it, in one transaction.
17756
18816
  *
@@ -17824,7 +18884,24 @@ declare class UIDocumentService extends Service<UIDocumentService> implements IU
17824
18884
  updateElementAnimation(elementId: string, animation: UIPageAnimationSettings | null, options?: {
17825
18885
  mergeKey?: string;
17826
18886
  }): void;
18887
+ /**
18888
+ * How the player reaches this element without a pointer. `null` clears it.
18889
+ *
18890
+ * Allowed on a linked component instance, as its animation is: it belongs to where the instance
18891
+ * was placed. Which element is up from a Back button depends on the page it is on.
18892
+ */
18893
+ updateElementNavigation(elementId: string, navigation: UIElementNavigation | null, options?: {
18894
+ mergeKey?: string;
18895
+ }): void;
17827
18896
  updateElementExtra(elementId: string, extraPatch: Record<string, unknown>): void;
18897
+ /**
18898
+ * Merge CSS overrides into an element's `style`; a `null` value removes that override.
18899
+ *
18900
+ * The renderer spreads `style` over the widget's own styles (`extractStyleOverrides`), so this is
18901
+ * the bag a `.ui` file's `style.*` lines write. Nothing in the editor's panels writes it; the
18902
+ * agent's `ui_patch` does, with the same refusal for a placed component that props have.
18903
+ */
18904
+ updateElementStyle(elementId: string, stylePatch: Record<string, unknown>): void;
17828
18905
  reorderChildren(parentId: string, orderedChildIds: string[]): void;
17829
18906
  moveElementsInSurface(surfaceId: string, elementIds: string[], targetParentId: string, beforeChildId: string | null): MoveUiElementsResult;
17830
18907
  /**
@@ -17937,6 +19014,30 @@ declare class UIDocumentService extends Service<UIDocumentService> implements IU
17937
19014
  * operation sink taking the gesture looks like (the reasoning {@link reorderSurfaces} gives).
17938
19015
  */
17939
19016
  private recordLibraryAddition;
19017
+ /**
19018
+ * Take input actions an import adopted back out of the vocabulary, and return them as they stood.
19019
+ *
19020
+ * Only the ones nothing left in the project answers or names. This runs after the import's own
19021
+ * surfaces and blueprints have gone, so an action a surface still answers, or a blueprint node
19022
+ * still picks, is one the author has put to use since - taking it would leave that surface or node
19023
+ * answering nothing (the rule an agent's outline step keeps for a chapter it added). Empty when
19024
+ * nothing left this copy of the document: an operation sink took the gesture.
19025
+ */
19026
+ private takeAdoptedInputActions;
19027
+ /**
19028
+ * Remove vocabulary entries by id, recording nothing. A vocabulary left empty is left out of the
19029
+ * document, as it is in one that never had an action - so taking back the import that brought a
19030
+ * project its first actions gives back the document it had.
19031
+ */
19032
+ private dropInputActions;
19033
+ /**
19034
+ * Put actions {@link takeAdoptedInputActions} returned back. An id the vocabulary has gained in
19035
+ * the meantime keeps what it holds, and a navigation slot another action has come to fill stays
19036
+ * with that one - the rule the adoption itself follows.
19037
+ */
19038
+ private putInputActions;
19039
+ /** Every input action id a node of any blueprint in the project picks. */
19040
+ private inputActionIdsPickedByBlueprints;
17940
19041
  private getElementSurfaceId;
17941
19042
  private getCommonSurfaceIdForElements;
17942
19043
  private filterLinkedComponentLayoutPatch;
@@ -18034,6 +19135,36 @@ declare class UIDocumentService extends Service<UIDocumentService> implements IU
18034
19135
  * the way to delete the page it starts on is to make another page the entry first.
18035
19136
  */
18036
19137
  deleteSurface(surfaceId: string): void;
19138
+ /**
19139
+ * Take surfaces out of the project with their trees and their blueprints, as one step on the
19140
+ * project's undo stack - the shape {@link deleteComponents} gives definitions. Undo puts each one
19141
+ * back where it stood, blueprints first.
19142
+ *
19143
+ * The entry page is refused for the reason {@link deleteSurface} gives, and nothing is taken when
19144
+ * one of the ids is it. Returns the surfaces taken, empty when nothing was.
19145
+ */
19146
+ deleteSurfaces(surfaceIds: readonly string[], label: HistoryLabel): UISurface[];
19147
+ /**
19148
+ * Bring a bundle in, in place of some of the project's surfaces, and make one of its pages the
19149
+ * entry - as one step on the project's undo stack.
19150
+ *
19151
+ * What `importTemplateBundle` does on its own leaves the rest of such a change as separate steps,
19152
+ * and an undo that took back only the import would leave a project with neither the surfaces it
19153
+ * removed nor the ones it brought. Here one Ctrl+Z puts back exactly what was there: the removed
19154
+ * surfaces with their blueprints, the entry page as the document named it, and none of the
19155
+ * arrivals - the input actions the import adopted included, as for a plain import. Files and
19156
+ * translations stay, as they do for a plain import.
19157
+ *
19158
+ * `removeSurfaceIds` may name the entry page; `entrySourceSurfaceId` names a page of the bundle by
19159
+ * its id there. When it is absent or did not arrive, the entry is left to the document's own rule.
19160
+ */
19161
+ installBundle(input: Omit<ImportTemplateBundleInput, "history"> & {
19162
+ removeSurfaceIds: readonly string[];
19163
+ entrySourceSurfaceId?: string;
19164
+ label: HistoryLabel;
19165
+ }): ImportTemplateResult & {
19166
+ removedSurfaces: UISurface[];
19167
+ };
18037
19168
  /**
18038
19169
  * Put the surfaces in the order given.
18039
19170
  *
@@ -18071,7 +19202,16 @@ declare class UIDocumentService extends Service<UIDocumentService> implements IU
18071
19202
  setEntrySurface(surfaceId: string): void;
18072
19203
  private applyEntrySurface;
18073
19204
  private applySurfaceOrder;
18074
- renameSurface(surfaceId: string, name: string): void;
19205
+ /**
19206
+ * Rename a surface, as a step on its own undo stack.
19207
+ *
19208
+ * `label` is for a rename nobody typed - an agent's - and makes it a step of its own under that
19209
+ * name. Merged into the author's typing, as a typed name is merged a keystroke at a time, one
19210
+ * Ctrl+Z would take back the author's rename and the agent's together.
19211
+ */
19212
+ renameSurface(surfaceId: string, name: string, options?: {
19213
+ label?: HistoryLabel;
19214
+ }): void;
18075
19215
  /**
18076
19216
  * Edit a surface's own record - its name, its background, its page animation, its slot.
18077
19217
  *
@@ -18111,6 +19251,31 @@ declare class UIDocumentService extends Service<UIDocumentService> implements IU
18111
19251
  * or clobbering a surface.
18112
19252
  */
18113
19253
  importTemplateBundle(input: ImportTemplateBundleInput): ImportTemplateResult;
19254
+ /**
19255
+ * Give this project's input vocabulary the actions the arriving surfaces answer and it lacks.
19256
+ *
19257
+ * A surface keeps its replies to the project's actions (`surface.actions`) when it is copied in -
19258
+ * a dialogue box that advances on a click or Space does so because it answers `advance` - and a
19259
+ * reply to an action the project has never declared answers nothing. So each such action comes
19260
+ * along under its own id, with its bindings. One the project already has is the project's, and
19261
+ * keeps the author's bindings; a navigation slot another of the project's actions claims stays
19262
+ * with that one.
19263
+ *
19264
+ * So does a key or a pad button the project already binds to an action of its own: the arriving
19265
+ * action comes without that binding, and keeps the rest. A key is aimed at no place - it reaches
19266
+ * whatever answers it - so a second action bound to the author's key would change what that key
19267
+ * does in the author's game, which a page brought in must not do behind their back; the author can
19268
+ * bind it on purpose under Input Actions. The action still arrives, so the surface answers it by
19269
+ * its remaining bindings, and nothing is lost that adding it unbound would have kept.
19270
+ *
19271
+ * Two kinds of binding are not held back, because sharing them is how the vocabulary is meant to
19272
+ * be used. A pointer gesture lands on whatever surface is under the pointer and fires what that
19273
+ * surface answers. And a key the project gives to a navigation intent (a focus move, Confirm,
19274
+ * Cancel) is shared with the actions surfaces answer by design - the starter template binds Space
19275
+ * to both Advance and Confirm - so a project that took up keyboard navigation still gets a
19276
+ * dialogue box that reads on with Space.
19277
+ */
19278
+ private adoptArrivingInputActions;
18114
19279
  /**
18115
19280
  * Copy a template's component library into this project, under fresh ids.
18116
19281
  *
@@ -18253,7 +19418,12 @@ declare class UIDocumentService extends Service<UIDocumentService> implements IU
18253
19418
  updateComponentElementAnimation(componentId: string, elementId: string, animation: UIPageAnimationSettings | null, options?: {
18254
19419
  mergeKey?: string;
18255
19420
  }): void;
19421
+ updateComponentElementNavigation(componentId: string, elementId: string, navigation: UIElementNavigation | null, options?: {
19422
+ mergeKey?: string;
19423
+ }): void;
18256
19424
  updateComponentElementExtra(componentId: string, elementId: string, extraPatch: Record<string, unknown>): void;
19425
+ /** The component-definition counterpart of {@link updateElementStyle}. */
19426
+ updateComponentElementStyle(componentId: string, elementId: string, stylePatch: Record<string, unknown>): void;
18257
19427
  renameComponentElement(componentId: string, elementId: string, name: string): void;
18258
19428
  reorderComponentChildren(componentId: string, parentId: string, orderedChildIds: string[]): void;
18259
19429
  deleteComponentElements(componentId: string, elementIds: string[]): void;
@@ -18283,9 +19453,17 @@ declare class UIDocumentService extends Service<UIDocumentService> implements IU
18283
19453
  * placement look as they did, and the root can now be given siblings.
18284
19454
  */
18285
19455
  wrapComponentRoot(componentId: string): string | null;
19456
+ /**
19457
+ * An element id a caller asked for, checked against every pool it could collide in - the
19458
+ * project's elements and every component definition's - or null when none was asked for.
19459
+ */
19460
+ private claimElementId;
18286
19461
  /** An element as an Edit menu step names it: its own name, or its widget's. */
18287
19462
  private describeElementForHistory;
18288
- createComponentElement(componentId: string, parentId: string, type: string, layoutPatch?: Partial<UILayout>): UIElement | null;
19463
+ /** `options.id`: see {@link createElement}. */
19464
+ createComponentElement(componentId: string, parentId: string, type: string, layoutPatch?: Partial<UILayout>, options?: {
19465
+ id?: string;
19466
+ }): UIElement | null;
18289
19467
  pasteComponentClipboardPayload(componentId: string, targetParentId: string, beforeChildId: string | null, incoming: UIEditorClipboardPayload): {
18290
19468
  ok: true;
18291
19469
  newRootIds: string[];
@@ -18293,9 +19471,18 @@ declare class UIDocumentService extends Service<UIDocumentService> implements IU
18293
19471
  ok: false;
18294
19472
  reason: "invalid_clipboard" | "invalid_target";
18295
19473
  };
18296
- createComponentInstance(parentId: string, componentId: string, layoutPatch?: Partial<UILayout>): UIElement;
19474
+ /** `options.id`: see {@link createElement}. */
19475
+ createComponentInstance(parentId: string, componentId: string, layoutPatch?: Partial<UILayout>, options?: {
19476
+ id?: string;
19477
+ }): UIElement;
18297
19478
  unlinkComponentInstance(elementId: string): string[];
18298
- createElement(parentId: string, type: string, layoutPatch?: Partial<UILayout>): UIElement;
19479
+ /**
19480
+ * `options.id` gives the new element an id of the caller's choosing - an agent naming an element
19481
+ * so a blueprint it writes next can refer to it. Refused when the id is already in use.
19482
+ */
19483
+ createElement(parentId: string, type: string, layoutPatch?: Partial<UILayout>, options?: {
19484
+ id?: string;
19485
+ }): UIElement;
18299
19486
  pasteClipboardPayload(surfaceId: string, targetParentId: string, beforeChildId: string | null, incoming: UIEditorClipboardPayload): {
18300
19487
  ok: true;
18301
19488
  newRootIds: string[];
@@ -19305,6 +20492,19 @@ export type TestFinding = {
19305
20492
  severity: TestFindingSeverity;
19306
20493
  message: TestText;
19307
20494
  target?: SearchJumpTarget;
20495
+ /**
20496
+ * A stable, machine-readable name for the rule or check that produced this finding (for the
20497
+ * project-diagnostics test, the lint rule id such as `story/dead-end`). Optional: a finding
20498
+ * without one is still a finding. Never translated, so a script or an agent can match on it.
20499
+ */
20500
+ ruleId?: string;
20501
+ /**
20502
+ * The message in English, for machine readers (Studio's agent connection hands findings to
20503
+ * agents whose tool descriptions are English). Optional; when absent the agent gets `message`
20504
+ * rendered as well as it can be. Never shown in Studio's own report, which follows the editor
20505
+ * language through `message`.
20506
+ */
20507
+ englishMessage?: string;
19308
20508
  };
19309
20509
  /**
19310
20510
  * What `run` may return. Note the absence of `cancelled` and `errored`: see the header.
@@ -19652,7 +20852,11 @@ declare enum Services {
19652
20852
  /** "The working tree changed under the editors": drops in-memory documents and re-reads them */
19653
20853
  WorkspaceReload = "workspaceReload",
19654
20854
  /** Recovery mode's own state: which subsystems have been tried, and what they said */
19655
- Recovery = "recovery"
20855
+ Recovery = "recovery",
20856
+ /** What the author sees of a connected AI agent, and the pause and follow switches over it */
20857
+ AgentFollow = "agentFollow",
20858
+ /** Carries out the calls an AI agent makes over Studio's MCP endpoint; see `agent/AgentBridgeService` */
20859
+ AgentBridge = "agentBridge"
19656
20860
  }
19657
20861
  interface IUIDocumentService extends IService {
19658
20862
  load(): Promise<UIDocument>;
@@ -22156,6 +23360,40 @@ export type PluginLocalizationService = {
22156
23360
  */
22157
23361
  registerWords(source: PluginWordsSource): PluginCleanup;
22158
23362
  };
23363
+ /**
23364
+ * Tools this plugin offers the AI agents an author connects to Studio's MCP endpoint (Claude Code,
23365
+ * Codex, Cursor and the like).
23366
+ *
23367
+ * Each tool is declared by name and `write` in the manifest's `contributes.agentTools` - registering
23368
+ * an undeclared one throws - and is advertised to agents as `<plugin id>__<tool>`, with every `.`
23369
+ * and `-` turned into `_` (`acme.notes.add_note` is `acme_notes__add_note`). A Markdown chapter at
23370
+ * `contributes.agentGuide` is served to agents as `agent_guide {chapter: "plugin:<plugin id>"}`.
23371
+ *
23372
+ * What the host does around every call, so the plugin does not have to:
23373
+ *
23374
+ * - **Gates it** exactly as it gates Studio's own tools: a `write: true` tool is refused unless the
23375
+ * author allowed agent writes, and while they paused the agent, the project is frozen or a live
23376
+ * session runs. The author can also switch a plugin's tools off in Settings > Agent access.
23377
+ * - **Checks the arguments** against `inputSchema` before the handler runs, and removes `project`
23378
+ * (the host's routing argument).
23379
+ * - **Holds a reading tool to its plugin storage:** while a `write: false` tool runs,
23380
+ * `storage.writeJson` throws. That is the whole of it - a `write: false` tool is not gated by the
23381
+ * author's write switch, and anything else your `app` can do, its handler can do too. Declare a
23382
+ * tool `write: true` if it changes the project by any route.
23383
+ * - **Makes a writing tool's edit one undo step:** every `storage.writeJson` it does is captured,
23384
+ * and Ctrl+Z puts every namespace back as it was, then calls the reloader you registered with
23385
+ * `workspace.registerReloader` - so register one, or undo will change the file and not your
23386
+ * memory of it.
23387
+ * - **Caps the answer:** text past 60 000 characters is cut, `data` past 60 000 characters of JSON
23388
+ * is left out, and at most one image is passed on.
23389
+ *
23390
+ * A handler receives the arguments and the client's name, nothing else: whatever it does, it does
23391
+ * with this plugin's own `app`.
23392
+ */
23393
+ export type PluginAgentService = {
23394
+ registerTool(def: PluginAgentToolDef): PluginCleanup;
23395
+ registerTools(defs: PluginAgentToolDef[]): PluginCleanup;
23396
+ };
22159
23397
  export type PluginServices = {
22160
23398
  storage: PluginStorageService;
22161
23399
  assets: PluginAssetsService;
@@ -22170,6 +23408,8 @@ export type PluginServices = {
22170
23408
  localization: PluginLocalizationService;
22171
23409
  /** Contribute checks to Run > Test; see {@link PluginTestService}. */
22172
23410
  tests: PluginTestService;
23411
+ /** Offer tools to AI agents connected to Studio; see {@link PluginAgentService}. */
23412
+ agent: PluginAgentService;
22173
23413
  ui: {
22174
23414
  panels: {
22175
23415
  register<TPayload = unknown>(panel: PanelDefinition<TPayload>): PluginCleanup;