framer-dalton 0.0.29 → 0.0.31

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/cli.js CHANGED
@@ -12,7 +12,7 @@ import net from 'net';
12
12
  import { fileURLToPath } from 'url';
13
13
  import { createTRPCClient, httpLink } from '@trpc/client';
14
14
 
15
- /* @framer/ai CLI v0.0.29 */
15
+ /* @framer/ai CLI v0.0.31 */
16
16
  var __defProp = Object.defineProperty;
17
17
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
18
18
 
@@ -375,7 +375,7 @@ __name(markTelemetryNoticeShown, "markTelemetryNoticeShown");
375
375
  // src/version.ts
376
376
  var VERSION = (
377
377
  // typeof is used to ensure this can be used just via tsx or node etc. without build
378
- "0.0.29"
378
+ "0.0.31"
379
379
  );
380
380
  var trackingEndpoint = "https://events.framer.com/track";
381
381
  var inProgressTrackings = /* @__PURE__ */ new Set();
@@ -1070,6 +1070,114 @@ var types = {
1070
1070
  }
1071
1071
  ]
1072
1072
  },
1073
+ agentbranch: {
1074
+ name: "AgentBranch",
1075
+ description: "",
1076
+ kind: "interface",
1077
+ references: [],
1078
+ members: [
1079
+ {
1080
+ name: "id",
1081
+ type: "string",
1082
+ description: "",
1083
+ optional: false
1084
+ },
1085
+ {
1086
+ name: "title",
1087
+ type: "string",
1088
+ description: "",
1089
+ optional: false
1090
+ },
1091
+ {
1092
+ name: "url",
1093
+ type: "string",
1094
+ description: "",
1095
+ optional: false
1096
+ },
1097
+ {
1098
+ name: "baseId",
1099
+ type: "string",
1100
+ description: "",
1101
+ optional: true
1102
+ },
1103
+ {
1104
+ name: "joined",
1105
+ type: "boolean",
1106
+ description: "",
1107
+ optional: false
1108
+ }
1109
+ ]
1110
+ },
1111
+ agentbranchchange: {
1112
+ name: "AgentBranchChange",
1113
+ description: "",
1114
+ kind: "interface",
1115
+ references: ["AgentBranchCollectionItemChange"],
1116
+ members: [
1117
+ {
1118
+ name: "type",
1119
+ type: '"page" | "collection" | "designPage" | "siteSettings" | "component" | "layoutTemplate"',
1120
+ description: "",
1121
+ optional: false
1122
+ },
1123
+ {
1124
+ name: "nodeId",
1125
+ type: "string",
1126
+ description: "",
1127
+ optional: false
1128
+ },
1129
+ {
1130
+ name: "name",
1131
+ type: "string",
1132
+ description: "",
1133
+ optional: false
1134
+ },
1135
+ {
1136
+ name: "isRemoved",
1137
+ type: "boolean",
1138
+ description: "",
1139
+ optional: false
1140
+ },
1141
+ {
1142
+ name: "items",
1143
+ type: "AgentBranchCollectionItemChange[]",
1144
+ description: "",
1145
+ optional: true
1146
+ },
1147
+ {
1148
+ name: "settingsTab",
1149
+ type: '"general" | "redirects"',
1150
+ description: "",
1151
+ optional: true
1152
+ }
1153
+ ]
1154
+ },
1155
+ agentbranchcollectionitemchange: {
1156
+ name: "AgentBranchCollectionItemChange",
1157
+ description: "",
1158
+ kind: "interface",
1159
+ references: [],
1160
+ members: [
1161
+ {
1162
+ name: "nodeId",
1163
+ type: "string",
1164
+ description: "",
1165
+ optional: false
1166
+ },
1167
+ {
1168
+ name: "name",
1169
+ type: "string",
1170
+ description: "",
1171
+ optional: false
1172
+ },
1173
+ {
1174
+ name: "isRemoved",
1175
+ type: "boolean",
1176
+ description: "",
1177
+ optional: false
1178
+ }
1179
+ ]
1180
+ },
1073
1181
  agentclarificationanswer: {
1074
1182
  name: "AgentClarificationAnswer",
1075
1183
  description: "",
@@ -4374,6 +4482,20 @@ var types = {
4374
4482
  alias: "PixelNumber | `${PixelNumber} ${PixelNumber} ${PixelNumber} ${PixelNumber}`",
4375
4483
  references: ["PixelNumber"]
4376
4484
  },
4485
+ framerreconnectoptions: {
4486
+ name: "FramerReconnectOptions",
4487
+ description: "",
4488
+ kind: "interface",
4489
+ references: [],
4490
+ members: [
4491
+ {
4492
+ name: "expectedInitialBranchId",
4493
+ type: "string",
4494
+ description: "",
4495
+ optional: true
4496
+ }
4497
+ ]
4498
+ },
4377
4499
  fusednumber: {
4378
4500
  name: "FusedNumber",
4379
4501
  description: "",
@@ -7338,6 +7460,66 @@ var types = {
7338
7460
  description: "@alpha",
7339
7461
  optional: false
7340
7462
  },
7463
+ {
7464
+ name: "getActiveBranchForAgent",
7465
+ type: "() => Promise<AgentBranch>",
7466
+ description: "@alpha",
7467
+ optional: false
7468
+ },
7469
+ {
7470
+ name: "getBranchesForAgent",
7471
+ type: "() => Promise<AgentBranch[]>",
7472
+ description: "@alpha",
7473
+ optional: false
7474
+ },
7475
+ {
7476
+ name: "getBranchChangesForAgent",
7477
+ type: "(branchId: string) => Promise<AgentBranchChange[]>",
7478
+ description: "@alpha",
7479
+ optional: false
7480
+ },
7481
+ {
7482
+ name: "switchBranchForAgent",
7483
+ type: "(branchId: string) => Promise<void>",
7484
+ description: "@alpha",
7485
+ optional: false
7486
+ },
7487
+ {
7488
+ name: "createBranchForAgent",
7489
+ type: "(title?: string) => Promise<AgentBranch>",
7490
+ description: "@alpha",
7491
+ optional: false
7492
+ },
7493
+ {
7494
+ name: "mergeBranchForAgent",
7495
+ type: "(targetBranchId?: string) => Promise<void>",
7496
+ description: "@alpha",
7497
+ optional: false
7498
+ },
7499
+ {
7500
+ name: "joinBranchForAgent",
7501
+ type: "(branchId: string) => Promise<void>",
7502
+ description: "@alpha",
7503
+ optional: false
7504
+ },
7505
+ {
7506
+ name: "leaveBranchForAgent",
7507
+ type: "(branchId: string) => Promise<void>",
7508
+ description: "@alpha",
7509
+ optional: false
7510
+ },
7511
+ {
7512
+ name: "renameBranchForAgent",
7513
+ type: "(branchId: string, title: string) => Promise<void>",
7514
+ description: "@alpha",
7515
+ optional: false
7516
+ },
7517
+ {
7518
+ name: "deleteBranchForAgent",
7519
+ type: "(branchId: string) => Promise<void>",
7520
+ description: "@alpha",
7521
+ optional: false
7522
+ },
7341
7523
  {
7342
7524
  name: "readProjectForAgent",
7343
7525
  type: "(queries: Record<string, unknown>[], options?: {\n pagePath?: string;\n }) => Promise<{\n results: unknown[];\n }>",
@@ -7941,9 +8123,9 @@ var types = {
7941
8123
  optional: false
7942
8124
  },
7943
8125
  {
7944
- name: "userAgentModel",
8126
+ name: "framerAgentModel",
7945
8127
  type: "string",
7946
- description: "Inner Framer Agent model override. Defaults to `model` when omitted. Supports the same `model=effort` syntax.",
8128
+ description: "Inner Framer Agent model override. Defaults to `model` when omitted.\n\nSupports the same `model=effort` syntax. Omitting effort is equivalent to `none`.",
7947
8129
  optional: true
7948
8130
  },
7949
8131
  {
@@ -7996,6 +8178,18 @@ var types = {
7996
8178
  description: "JSONL string with one training row per inner-agent step, present when `captureTrainingData` was set.",
7997
8179
  optional: true
7998
8180
  },
8181
+ {
8182
+ name: "traceFilename",
8183
+ type: "string",
8184
+ description: "Replay trace filename, present when the inner agent produced at least one model step.",
8185
+ optional: true
8186
+ },
8187
+ {
8188
+ name: "traceJson",
8189
+ type: "string",
8190
+ description: "Replay trace JSON with system, tools, and final ModelMessage conversation.",
8191
+ optional: true
8192
+ },
7999
8193
  {
8000
8194
  name: "fixtureFilename",
8001
8195
  type: "string",
@@ -13933,6 +14127,20 @@ var methodsByCategory = {
13933
14127
  description: 'Applies commands to the canvas to create, update, remove, move, or duplicate nodes.\n\nThe command syntax is documented in the string returned by {@link getSystemPrompt}.\nEach call is scoped to a single page.\n\n@param dsl - A string of commands separated by `;`. See {@link getSystemPrompt} for syntax.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.',
13934
14128
  references: []
13935
14129
  },
14130
+ {
14131
+ name: "createBranch",
14132
+ category: "FramerAgentAPI",
14133
+ signature: "createBranch(title?: string): Promise<AgentBranch>",
14134
+ description: "Creates a branch and switches to it.\n\n@param title - Optional branch title. The new branch is created from the active branch.\n@returns The created branch.",
14135
+ references: ["AgentBranch"]
14136
+ },
14137
+ {
14138
+ name: "deleteBranch",
14139
+ category: "FramerAgentAPI",
14140
+ signature: "deleteBranch(branchId: string): Promise<void>",
14141
+ description: "Deletes a branch.\n\n@param branchId - Branch id to delete.",
14142
+ references: []
14143
+ },
13936
14144
  {
13937
14145
  name: "flattenComponentInstance",
13938
14146
  category: "FramerAgentAPI",
@@ -13940,6 +14148,13 @@ var methodsByCategory = {
13940
14148
  description: 'Flattens a local component instance into raw editable layers.\n\n@param input - `{ id }`: the id of the component instance to flatten.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns The flatten result \u2014 `success` with a `replacementId`, or `blocked` with a reason.',
13941
14149
  references: []
13942
14150
  },
14151
+ {
14152
+ name: "getActiveBranch",
14153
+ category: "FramerAgentAPI",
14154
+ signature: "getActiveBranch(): Promise<AgentBranch>",
14155
+ description: "Returns the active project branch.\n\n@returns Branch metadata for the active branch.",
14156
+ references: ["AgentBranch"]
14157
+ },
13943
14158
  {
13944
14159
  name: "getAncestors",
13945
14160
  category: "FramerAgentAPI",
@@ -13947,11 +14162,25 @@ var methodsByCategory = {
13947
14162
  description: 'Get every ancestor of a node, from the direct parent up to the page root.\n\n@param input - `{ id }`: the id of the node to start from.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns The ancestors ordered from closest parent to the page root.',
13948
14163
  references: []
13949
14164
  },
14165
+ {
14166
+ name: "getBranchChanges",
14167
+ category: "FramerAgentAPI",
14168
+ signature: "getBranchChanges(branchId: string): Promise<AgentBranchChange[]>",
14169
+ description: "Returns a summarized changelog for a branch.\n\n@param branchId - Branch id.",
14170
+ references: ["AgentBranchChange"]
14171
+ },
14172
+ {
14173
+ name: "getBranches",
14174
+ category: "FramerAgentAPI",
14175
+ signature: "getBranches(): Promise<AgentBranch[]>",
14176
+ description: "Returns the project branches.\n\n@returns Branch metadata for each available branch.",
14177
+ references: ["AgentBranch"]
14178
+ },
13950
14179
  {
13951
14180
  name: "getContext",
13952
14181
  category: "FramerAgentAPI",
13953
- signature: "getContext(options?: { pagePath?: string; }): Promise<string>",
13954
- description: 'Returns the dynamic project context as a string.\n\nThe context includes project-specific data:\n- **Available fonts** \u2014 font families loaded in the project.\n- **Components** \u2014 component names and their controls.\n- **Design tokens** \u2014 color tokens defined in the project.\n- **Style presets** \u2014 text style presets defined in the project.\n- **Icon sets** \u2014 available icon sets and their definitions.\n\nThis data changes per project and page. Pair with the static prompt\nfrom {@link getSystemPrompt} for complete agent context.\n\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns A string containing the project context.',
14182
+ signature: "getContext(): Promise<string>",
14183
+ description: "Returns the dynamic project context as a string.\n\nThe context includes project-specific data:\n- **Available fonts** \u2014 font families loaded in the project.\n- **Components** \u2014 component names and their controls.\n- **Design tokens** \u2014 color tokens defined in the project.\n- **Style presets** \u2014 text style presets defined in the project.\n- **Icon sets** \u2014 available icon sets and their definitions.\n\nThis data changes per project. Pair with the static prompt\nfrom {@link getSystemPrompt} for complete agent context.\n\n@returns A string containing the project context.",
13955
14184
  references: []
13956
14185
  },
13957
14186
  {
@@ -14003,6 +14232,20 @@ var methodsByCategory = {
14003
14232
  description: "Returns the static agent system prompt as a string.\n\nThe prompt includes:\n- **Command reference** \u2014 syntax for adding, updating, removing, moving, and duplicating nodes.\n- **Design rules** \u2014 spacing, layout, typography, and responsive design guidance.\n- **Examples** \u2014 common UI patterns expressed as commands.\n- **`readProject` query reference** \u2014 available query types and their parameters.\n\nThis is the sole documentation for the command syntax used by {@link applyChanges}\nand the query types used by {@link readProject}.\n\nThe prompt is static and does not depend on any specific project.\nCall {@link getContext} to get the project-specific context.\n\n@returns A string containing the agent system prompt.",
14004
14233
  references: []
14005
14234
  },
14235
+ {
14236
+ name: "joinBranch",
14237
+ category: "FramerAgentAPI",
14238
+ signature: "joinBranch(branchId: string): Promise<void>",
14239
+ description: "Joins a branch as a contributor so the current user can edit it when permissions allow.\n\n@param branchId - Branch id to join.",
14240
+ references: []
14241
+ },
14242
+ {
14243
+ name: "leaveBranch",
14244
+ category: "FramerAgentAPI",
14245
+ signature: "leaveBranch(branchId: string): Promise<void>",
14246
+ description: "Leaves a branch as a contributor.\n\n@param branchId - Branch id to leave.",
14247
+ references: []
14248
+ },
14006
14249
  {
14007
14250
  name: "makeExternalComponentLocal",
14008
14251
  category: "FramerAgentAPI",
@@ -14010,6 +14253,13 @@ var methodsByCategory = {
14010
14253
  description: 'Converts an external component into a local project component.\n\n@param input - `{ id, replaceAll? }`: the id of the external instance, and whether to replace all instances.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns `success` (with the local component name), `needs_confirmation` (retry with `replaceAll`), or `blocked` with a reason.',
14011
14254
  references: []
14012
14255
  },
14256
+ {
14257
+ name: "mergeBranch",
14258
+ category: "FramerAgentAPI",
14259
+ signature: "mergeBranch(targetBranchId?: string): Promise<void>",
14260
+ description: 'Merges the active branch into its base or a target branch and switches to the target.\n\n@param targetBranchId - Optional target branch id. Use `"main"` for the main branch.',
14261
+ references: []
14262
+ },
14013
14263
  {
14014
14264
  name: "paginate",
14015
14265
  category: "FramerAgentAPI",
@@ -14034,29 +14284,29 @@ var methodsByCategory = {
14034
14284
  {
14035
14285
  name: "readComponentControls",
14036
14286
  category: "FramerAgentAPI",
14037
- signature: "readComponentControls(input: { componentIds: readonly string[]; }, options?: { pagePath?: string; }): Promise<unknown>",
14038
- description: 'Reads control definitions for project components.\n\n@param input - `{ componentIds }`: component ids from project context or previous reads.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns The matching component control definitions.',
14287
+ signature: "readComponentControls(input: { componentIds: readonly string[]; }): Promise<unknown>",
14288
+ description: "Reads control definitions for project components.\n\n@param input - `{ componentIds }`: component ids from project context or previous reads.\n@returns The matching component control definitions.",
14039
14289
  references: []
14040
14290
  },
14041
14291
  {
14042
14292
  name: "readIcons",
14043
14293
  category: "FramerAgentAPI",
14044
- signature: "readIcons(input: { iconSetName: string; }, options?: { pagePath?: string; }): Promise<string[]>",
14045
- description: 'Reads exact icon names for an icon set.\n\n@param input - `{ iconSetName }`: icon set name from project context or previous reads.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns The available icon names in that set.',
14294
+ signature: "readIcons(input: { iconSetName: string; }): Promise<string[]>",
14295
+ description: "Reads exact icon names for an icon set.\n\n@param input - `{ iconSetName }`: icon set name from project context or previous reads.\n@returns The available icon names in that set.",
14046
14296
  references: []
14047
14297
  },
14048
14298
  {
14049
14299
  name: "readIconSetControls",
14050
14300
  category: "FramerAgentAPI",
14051
- signature: "readIconSetControls(input: { iconSetNames: readonly string[]; }, options?: { pagePath?: string; }): Promise<unknown>",
14052
- description: 'Reads icon-set control definitions.\n\n@param input - `{ iconSetNames }`: icon set names from project context or previous reads.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns The matching icon-set control definitions.',
14301
+ signature: "readIconSetControls(input: { iconSetNames: readonly string[]; }): Promise<unknown>",
14302
+ description: "Reads icon-set control definitions.\n\n@param input - `{ iconSetNames }`: icon set names from project context or previous reads.\n@returns The matching icon-set control definitions.",
14053
14303
  references: []
14054
14304
  },
14055
14305
  {
14056
14306
  name: "readLayoutTemplateControls",
14057
14307
  category: "FramerAgentAPI",
14058
- signature: "readLayoutTemplateControls(input: { layoutTemplateIds: readonly string[]; }, options?: { pagePath?: string; }): Promise<unknown>",
14059
- description: 'Reads layout-template control definitions.\n\n@param input - `{ layoutTemplateIds }`: layout template ids from project context or previous reads.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns The matching layout-template control definitions.',
14308
+ signature: "readLayoutTemplateControls(input: { layoutTemplateIds: readonly string[]; }): Promise<unknown>",
14309
+ description: "Reads layout-template control definitions.\n\n@param input - `{ layoutTemplateIds }`: layout template ids from project context or previous reads.\n@returns The matching layout-template control definitions.",
14060
14310
  references: []
14061
14311
  },
14062
14312
  {
@@ -14069,15 +14319,22 @@ var methodsByCategory = {
14069
14319
  {
14070
14320
  name: "readShaderControls",
14071
14321
  category: "FramerAgentAPI",
14072
- signature: "readShaderControls(input: { shaderNames: readonly string[]; }, options?: { pagePath?: string; }): Promise<unknown>",
14073
- description: 'Reads shader control definitions.\n\n@param input - `{ shaderNames }`: shader names from project context or previous reads.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns The matching shader control definitions.',
14322
+ signature: "readShaderControls(input: { shaderNames: readonly string[]; }): Promise<unknown>",
14323
+ description: "Reads shader control definitions.\n\n@param input - `{ shaderNames }`: shader names from project context or previous reads.\n@returns The matching shader control definitions.",
14324
+ references: []
14325
+ },
14326
+ {
14327
+ name: "renameBranch",
14328
+ category: "FramerAgentAPI",
14329
+ signature: "renameBranch(branchId: string, title: string): Promise<void>",
14330
+ description: "Renames a branch.\n\n@param branchId - Branch id to rename.\n@param title - New branch title.",
14074
14331
  references: []
14075
14332
  },
14076
14333
  {
14077
14334
  name: "reviewChanges",
14078
14335
  category: "FramerAgentAPI",
14079
- signature: "reviewChanges(options?: { pagePath?: string; }): Promise<unknown>",
14080
- description: "Reviews changes made by prior {@link applyChanges} calls in this session.\n\nConsumes accumulated diagnostics from the session's agent context.\n\n@param options.pagePath - Target page path (e.g. `\"/about\"`). Defaults to the active page.\n@returns The session's accumulated changes, errors, warnings, and deferred trait reports.",
14336
+ signature: "reviewChanges(): Promise<unknown>",
14337
+ description: "Reviews changes made by prior {@link applyChanges} calls in this session.\n\nConsumes accumulated diagnostics from the session's agent context.\n\n@returns The session's accumulated changes, errors, warnings, and deferred trait reports.",
14081
14338
  references: []
14082
14339
  },
14083
14340
  {
@@ -14093,6 +14350,13 @@ var methodsByCategory = {
14093
14350
  signature: "serializeNodes(input: { ids: readonly string[]; depth?: number; attributeFilter?: readonly string[]; ancestorPath?: boolean; }, options?: { pagePath?: string; }): Promise<unknown>",
14094
14351
  description: 'Serialize multiple nodes on the page. Ids that don\'t resolve to a node are skipped.\n\n@param input - `{ ids }` plus optional serialization options:\n - `depth` \u2014 limit how many descendant levels to include.\n - `attributeFilter` \u2014 only return the listed attributes per node.\n - `ancestorPath` \u2014 also return the path of ancestors up to the page root.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns The serialized nodes that were found, in input order.',
14095
14352
  references: []
14353
+ },
14354
+ {
14355
+ name: "switchBranch",
14356
+ category: "FramerAgentAPI",
14357
+ signature: "switchBranch(branchId: string): Promise<void>",
14358
+ description: 'Switches the active project branch.\n\n@param branchId - Branch id. Use `"main"` for the main branch.',
14359
+ references: []
14096
14360
  }
14097
14361
  ],
14098
14362
  framerapierror: [
@@ -16814,6 +17078,10 @@ async function execAndPrint(sessionId, code) {
16814
17078
  for (const line of result.output) {
16815
17079
  print(line);
16816
17080
  }
17081
+ if (result.branchChange) {
17082
+ const { title, id, url } = result.branchChange.activeBranch;
17083
+ print(`[FRAMER_BRANCH_CHANGE] title="${title}" id="${id}" url="${url}"`);
17084
+ }
16817
17085
  if (result.error) {
16818
17086
  printError(
16819
17087
  `Error: ${formatErrorForUser(errorWithRef(result.error, result.errorRef), { fromExecResult: true })}`
@@ -14,7 +14,7 @@ import { z } from 'zod';
14
14
  import { createRequire } from 'module';
15
15
  import * as vm from 'vm';
16
16
 
17
- /* @framer/ai relay server v0.0.29 */
17
+ /* @framer/ai relay server v0.0.31 */
18
18
  var __defProp = Object.defineProperty;
19
19
  var __knownSymbol = (name2, symbol) => (symbol = Symbol[name2]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name2);
20
20
  var __typeError = (msg) => {
@@ -199,7 +199,7 @@ __name(debug, "debug");
199
199
  // src/version.ts
200
200
  var VERSION = (
201
201
  // typeof is used to ensure this can be used just via tsx or node etc. without build
202
- "0.0.29"
202
+ "0.0.31"
203
203
  );
204
204
 
205
205
  // src/relay-client.ts
@@ -602,6 +602,7 @@ __name(sandboxedImport, "sandboxedImport");
602
602
  async function execute(session, code, options = {}) {
603
603
  const { cwd } = options;
604
604
  const output = [];
605
+ const previousBranch = await readActiveBranch(session);
605
606
  const customConsole = {
606
607
  log: /* @__PURE__ */ __name((...args) => {
607
608
  output.push(args.map((arg) => formatValue(arg)).join(" "));
@@ -669,7 +670,8 @@ async function execute(session, code, options = {}) {
669
670
  if (result !== void 0) {
670
671
  output.push(formatValue(result));
671
672
  }
672
- return { output };
673
+ const branchChange = await getBranchChange(session, previousBranch);
674
+ return { output, branchChange };
673
675
  } catch (err) {
674
676
  const errorMessage = err instanceof Error ? err.message : String(err);
675
677
  const retryable = isRetryableError(err);
@@ -677,17 +679,33 @@ async function execute(session, code, options = {}) {
677
679
  session.connection.markDisconnected();
678
680
  }
679
681
  const errorRef = getErrorRef(err);
680
- return {
681
- output,
682
- error: errorMessage,
683
- ...errorRef ? { errorRef } : {},
684
- ...retryable ? { retryable: true } : {}
685
- };
682
+ const branchChange = await getBranchChange(session, previousBranch);
683
+ return { output, error: errorMessage, errorRef, retryable, branchChange };
686
684
  } finally {
687
685
  if (timeoutId) clearTimeout(timeoutId);
688
686
  }
689
687
  }
690
688
  __name(execute, "execute");
689
+ async function readActiveBranch(session) {
690
+ try {
691
+ const branch = await session.connection.framer.agent.getActiveBranch();
692
+ session.connection.setActiveBranchId(branch.id);
693
+ return branch;
694
+ } catch {
695
+ return void 0;
696
+ }
697
+ }
698
+ __name(readActiveBranch, "readActiveBranch");
699
+ async function getBranchChange(session, previousBranch) {
700
+ if (!previousBranch) return void 0;
701
+ const activeBranch = await readActiveBranch(session);
702
+ if (!activeBranch || previousBranch.id === activeBranch.id) return void 0;
703
+ return {
704
+ previousBranch,
705
+ activeBranch
706
+ };
707
+ }
708
+ __name(getBranchChange, "getBranchChange");
691
709
  function isReconnectable(err) {
692
710
  return isRetryableError(err) || isConnectionError(err instanceof Error ? err.message : String(err));
693
711
  }
@@ -743,15 +761,19 @@ async function executeWithReconnect(session, code, options, execId) {
743
761
  log(
744
762
  `reconnect.failed exec=${execId} session=${session.id} req=${session.connection.framer.requestId} error="${err instanceof Error ? err.message : String(err)}"`
745
763
  );
746
- return connectionFailureResult(
764
+ const failureResult = connectionFailureResult(
747
765
  "Connection lost and failed to reconnect",
748
766
  err
749
767
  );
768
+ failureResult.branchChange = result.branchChange;
769
+ return failureResult;
750
770
  }
751
771
  log(
752
772
  `reconnect.success exec=${execId} session=${session.id} req=${session.connection.framer.requestId}`
753
773
  );
754
- return execute(session, code, options);
774
+ const retryResult = await execute(session, code, options);
775
+ retryResult.branchChange ??= result.branchChange;
776
+ return retryResult;
755
777
  }
756
778
  __name(executeWithReconnect, "executeWithReconnect");
757
779
  function formatValue(value) {
@@ -1093,6 +1115,7 @@ var Connection = class _Connection {
1093
1115
  sessions = [];
1094
1116
  status = "connected";
1095
1117
  pendingReconnect;
1118
+ activeBranchId;
1096
1119
  static async open(projectId, userId, apiKey, headlessServerUrl) {
1097
1120
  const framer = await connect(projectId, apiKey, {
1098
1121
  clientId: `dalton/${VERSION}`,
@@ -1106,6 +1129,9 @@ var Connection = class _Connection {
1106
1129
  markDisconnected() {
1107
1130
  this.status = "disconnected";
1108
1131
  }
1132
+ setActiveBranchId(branchId) {
1133
+ this.activeBranchId = branchId;
1134
+ }
1109
1135
  getServerSessionId() {
1110
1136
  return this.framer.sessionId ?? MISSING_SERVER_SESSION_ID;
1111
1137
  }
@@ -1149,7 +1175,7 @@ var Connection = class _Connection {
1149
1175
  (session) => session.inflight === 0 && now - session.lastActivityAt >= timeoutMs
1150
1176
  );
1151
1177
  }
1152
- async reconnect() {
1178
+ async reconnect(expectedInitialBranchId = this.activeBranchId) {
1153
1179
  if (this.status === "connected") {
1154
1180
  return;
1155
1181
  }
@@ -1157,7 +1183,7 @@ var Connection = class _Connection {
1157
1183
  return this.pendingReconnect;
1158
1184
  }
1159
1185
  this.status = "reconnecting";
1160
- this.pendingReconnect = this.framer.reconnect().then(() => {
1186
+ this.pendingReconnect = this.framer.reconnect({ expectedInitialBranchId }).then(() => {
1161
1187
  this.status = "connected";
1162
1188
  trackConnectionReconnect({
1163
1189
  projectId: this.projectId,
@@ -36,13 +36,12 @@ Always save results you'll need again. Don't repeat API calls.
36
36
 
37
37
  ## Method Selection
38
38
 
39
- Choose the highest-priority interface available for the task:
39
+ Prefer the agent-specific methods `framer.agent.*` over regular plugin API methods (`framer.*`).
40
40
 
41
- 1. Subcommands, such as `npx @framer/agent@latest read-project` and `npx @framer/agent@latest apply-changes`
42
- 2. Agent-specific methods, such as `framer.agent.readProject`, `framer.agent.applyChanges`, and `framer.agent.publish`
43
- 3. Generic plugin API methods, such as top-level `framer.*` methods
41
+ For `framer.agent.readProject` and `framer.agent.applyChanges` calls, use the `npx @framer/agent@latest read-project` and `npx @framer/agent@latest apply-changes` subcommands when possible. It's still ok to call those methods in exec scripts if you require something more complex than a plain method call.
44
42
 
45
- - Use `framer.agent.readProject`, `framer.agent.getNode`, `framer.agent.getNodes`, `framer.agent.getNodesOfTypes`, `framer.agent.getScopeNode`, `framer.agent.getGroundNode`, `framer.agent.getParentNode`, `framer.agent.getAncestors`, `framer.agent.serialize`, `framer.agent.serializeNodes`, and `framer.agent.paginate` for project tree reads.
43
+ - Use `framer.agent.getNode`, `framer.agent.getNodes`, `framer.agent.getNodesOfTypes`, `framer.agent.getScopeNode`, `framer.agent.getGroundNode`, `framer.agent.getParentNode`, `framer.agent.getAncestors`, `framer.agent.serialize`, `framer.agent.serializeNodes`, and `framer.agent.paginate` for project tree reads.
44
+ - Do not use `npx @framer/agent@latest read-project` or `framer.agent.readProject` for node tree reads unless you have just checked current docs and confirmed the exact query type. Query shapes such as `{ type: "node-by-id" }` are not valid for the current local API.
46
45
  - Use `framer.agent.readComponentControls`, `framer.agent.readIconSetControls`, `framer.agent.readIcons`, `framer.agent.readLayoutTemplateControls`, and `framer.agent.readShaderControls` for reading the controls of components, icon sets, icons, layout templates, and shaders.
47
46
  - Use `framer.agent.applyChanges` for page and layout edits. Do not use low-level node APIs like `createNode`, `setAttributes`, or `setRect` for design/layout work.
48
47
  - Use `framer.agent.publish` for publishing. Do not use `publish`, `getDeployments`, or `deploy` for normal agent publishing flows.
@@ -57,6 +56,7 @@ During normal task execution, do not call `framer.agent.getSystemPrompt()` or `f
57
56
 
58
57
  - Be concise. Don't narrate implementation details like field IDs, escaping, or internal steps. Just do the work and report what was accomplished in user-facing terms.
59
58
  - Use `framer.*` for plugin API calls. Top-level methods are not globals.
59
+ - If command output includes `[FRAMER_BRANCH_CHANGE]`, tell the user the active branch changed and include the `url` value.
60
60
  - Before making changes that add/update/delete content that the user has not clearly and explicitly requested in this conversation, inform the user of what you plan to do and why, and ask them to confirm.
61
61
  - You do not need to ask for confirmation when carrying out a specific add/update/delete change that the user has already clearly requested (this counts as explicit consent).
62
62
  - You do not need to explain or ask for confirmation for non-destructive calls like reading project state.
@@ -262,7 +262,7 @@ const commands = rows.flatMap((row, i) => {
262
262
  return [`+CollectionItemNode ${itemId} parent="${collectionId}";`, `SET ${itemId} ${sets.join(" ")};`];
263
263
  });
264
264
 
265
- await framer.agent.applyChanges(commands.join(" "));
265
+ console.log(await framer.agent.applyChanges(commands.join(" ")));
266
266
  ```
267
267
 
268
268
  #### Writing enum fields
@@ -275,10 +275,10 @@ const collection = (await framer.agent.getNodesOfTypes({ types: ["CollectionNode
275
275
  const statusField = collection.variables.find((v) => v.name === "Status");
276
276
  const status = statusField.cases.find((name) => name === "New");
277
277
 
278
- await framer.agent.applyChanges(
278
+ console.log(await framer.agent.applyChanges(
279
279
  `+CollectionItemNode newPost parent="${collection.id}";
280
280
  SET newPost $control__slug="hello-world" ${statusField.key}="${status}";`,
281
- );
281
+ ));
282
282
  ```
283
283
 
284
284
  #### Sync external data
@@ -306,7 +306,7 @@ const commands = source.flatMap((row, i) => {
306
306
  });
307
307
  existing.filter((item) => !seen.has(item.id)).forEach((item) => commands.push(`DEL ${item.id};`));
308
308
 
309
- await framer.agent.applyChanges(commands.join(" "));
309
+ console.log(await framer.agent.applyChanges(commands.join(" ")));
310
310
  ```
311
311
 
312
312
  #### Field Types
@@ -383,10 +383,10 @@ console.log(state.diagnostics);
383
383
  state.component = state.codeFile.exports.find(
384
384
  (exportItem) => exportItem.type === "component" && exportItem.isDefaultExport,
385
385
  );
386
- await framer.agent.applyChanges(
386
+ console.log(await framer.agent.applyChanges(
387
387
  `+ComponentInstanceNode badge parent="wrapper" component="${state.component.componentId}"; SET badge width=120 height=48;`,
388
388
  { pagePath: "/" },
389
- );
389
+ ));
390
390
  ```
391
391
 
392
392
  #### Editing
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "framer-dalton",
3
- "version": "0.0.29",
3
+ "version": "0.0.31",
4
4
  "type": "module",
5
5
  "bin": "./dist/cli.js",
6
6
  "main": "./dist/cli.js",
@@ -24,13 +24,13 @@
24
24
  "@trpc/client": "^11.17.0",
25
25
  "@trpc/server": "^11.17.0",
26
26
  "commander": "^12.1.0",
27
- "framer-api": "0.1.14",
27
+ "framer-api": "^0.1.16",
28
28
  "zod": "^4.4.3"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@biomejs/biome": "^2.4.13",
32
32
  "@framerjs/framer-events": "0.0.185",
33
- "@types/node": "24.12.4",
33
+ "@types/node": "24.13.0",
34
34
  "tsup": "^8.0.2",
35
35
  "tsx": "^4.22.3",
36
36
  "typescript": "^5.9.2",