framer-dalton 0.0.21 → 0.0.22
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 +358 -48
- package/dist/start-relay-server.js +167 -58
- package/docs/skills/framer-canvas-editing-project.md +6 -14
- package/docs/skills/framer.md +28 -289
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import fs7 from 'fs';
|
|
3
|
+
import path7 from 'path';
|
|
4
4
|
import { Command } from 'commander';
|
|
5
5
|
import crypto, { randomUUID } from 'crypto';
|
|
6
6
|
import http from 'http';
|
|
@@ -10,7 +10,7 @@ import os from 'os';
|
|
|
10
10
|
import { fileURLToPath } from 'url';
|
|
11
11
|
import { createTRPCClient, httpLink } from '@trpc/client';
|
|
12
12
|
|
|
13
|
-
/* @framer/ai CLI v0.0.
|
|
13
|
+
/* @framer/ai CLI v0.0.22 */
|
|
14
14
|
var __defProp = Object.defineProperty;
|
|
15
15
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
16
16
|
|
|
@@ -50,27 +50,27 @@ function openUrl(url) {
|
|
|
50
50
|
__name(openUrl, "openUrl");
|
|
51
51
|
function getConfigDir() {
|
|
52
52
|
if (process.env.XDG_CONFIG_HOME) {
|
|
53
|
-
return
|
|
53
|
+
return path7.join(process.env.XDG_CONFIG_HOME, "framer");
|
|
54
54
|
}
|
|
55
55
|
if (process.platform === "win32") {
|
|
56
|
-
return
|
|
56
|
+
return path7.join(process.env.APPDATA || os.homedir(), "framer");
|
|
57
57
|
}
|
|
58
|
-
return
|
|
58
|
+
return path7.join(os.homedir(), ".config", "framer");
|
|
59
59
|
}
|
|
60
60
|
__name(getConfigDir, "getConfigDir");
|
|
61
61
|
function ensureConfigDir() {
|
|
62
62
|
const configDir = getConfigDir();
|
|
63
|
-
|
|
63
|
+
fs7.mkdirSync(configDir, { recursive: true, mode: 448 });
|
|
64
64
|
}
|
|
65
65
|
__name(ensureConfigDir, "ensureConfigDir");
|
|
66
66
|
|
|
67
67
|
// src/config/projects.ts
|
|
68
68
|
function getProjectsConfigPath() {
|
|
69
|
-
return
|
|
69
|
+
return path7.join(getConfigDir(), "projects.json");
|
|
70
70
|
}
|
|
71
71
|
__name(getProjectsConfigPath, "getProjectsConfigPath");
|
|
72
72
|
function getLegacyCredentialsPath() {
|
|
73
|
-
return
|
|
73
|
+
return path7.join(getConfigDir(), "credentials.json");
|
|
74
74
|
}
|
|
75
75
|
__name(getLegacyCredentialsPath, "getLegacyCredentialsPath");
|
|
76
76
|
var ProjectsConfigSchema = z.object({
|
|
@@ -88,7 +88,7 @@ var ProjectsConfigSchema = z.object({
|
|
|
88
88
|
var LegacyCredentialsSchema = z.record(z.string(), z.string());
|
|
89
89
|
function readJsonFile(filePath) {
|
|
90
90
|
try {
|
|
91
|
-
return JSON.parse(
|
|
91
|
+
return JSON.parse(fs7.readFileSync(filePath, "utf-8"));
|
|
92
92
|
} catch (_error) {
|
|
93
93
|
return null;
|
|
94
94
|
}
|
|
@@ -96,7 +96,7 @@ function readJsonFile(filePath) {
|
|
|
96
96
|
__name(readJsonFile, "readJsonFile");
|
|
97
97
|
function writeProjectsConfig(config) {
|
|
98
98
|
ensureConfigDir();
|
|
99
|
-
|
|
99
|
+
fs7.writeFileSync(
|
|
100
100
|
getProjectsConfigPath(),
|
|
101
101
|
JSON.stringify(config, null, " "),
|
|
102
102
|
{
|
|
@@ -123,7 +123,7 @@ function migrateLegacyCredentials() {
|
|
|
123
123
|
}
|
|
124
124
|
const config = { version: 2, projects };
|
|
125
125
|
writeProjectsConfig(config);
|
|
126
|
-
|
|
126
|
+
fs7.rmSync(getLegacyCredentialsPath(), { force: true });
|
|
127
127
|
return config;
|
|
128
128
|
}
|
|
129
129
|
__name(migrateLegacyCredentials, "migrateLegacyCredentials");
|
|
@@ -136,7 +136,7 @@ function readProjectsConfig() {
|
|
|
136
136
|
return result.data;
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
|
-
if (
|
|
139
|
+
if (fs7.existsSync(getLegacyCredentialsPath())) {
|
|
140
140
|
return migrateLegacyCredentials();
|
|
141
141
|
}
|
|
142
142
|
return { version: 2, projects: {} };
|
|
@@ -219,7 +219,7 @@ var SettingsWatcher = class {
|
|
|
219
219
|
__name(this, "SettingsWatcher");
|
|
220
220
|
}
|
|
221
221
|
start(callback) {
|
|
222
|
-
|
|
222
|
+
fs7.watchFile(
|
|
223
223
|
this.settingsPath,
|
|
224
224
|
{ persistent: false, interval: fsPollIntervalMs },
|
|
225
225
|
(curr, prev) => {
|
|
@@ -236,7 +236,7 @@ var SettingsWatcher = class {
|
|
|
236
236
|
return this;
|
|
237
237
|
}
|
|
238
238
|
stop() {
|
|
239
|
-
|
|
239
|
+
fs7.unwatchFile(this.settingsPath);
|
|
240
240
|
return this;
|
|
241
241
|
}
|
|
242
242
|
};
|
|
@@ -254,7 +254,7 @@ var SettingsFileSchema = z.object({
|
|
|
254
254
|
telemetryNoticeShown: z.boolean().optional()
|
|
255
255
|
});
|
|
256
256
|
function getSettingsPath() {
|
|
257
|
-
return
|
|
257
|
+
return path7.join(getConfigDir(), "settings.json");
|
|
258
258
|
}
|
|
259
259
|
__name(getSettingsPath, "getSettingsPath");
|
|
260
260
|
var settings;
|
|
@@ -273,7 +273,7 @@ __name(getSettings, "getSettings");
|
|
|
273
273
|
function readSettingsFile() {
|
|
274
274
|
const settingsPath = getSettingsPath();
|
|
275
275
|
try {
|
|
276
|
-
const raw = JSON.parse(
|
|
276
|
+
const raw = JSON.parse(fs7.readFileSync(settingsPath, "utf-8"));
|
|
277
277
|
const result = SettingsFileSchema.parse(raw);
|
|
278
278
|
return {
|
|
279
279
|
machineId: result.machineId ?? DEFAULT_SETTINGS.machineId,
|
|
@@ -292,7 +292,7 @@ function setSettings(newSettings) {
|
|
|
292
292
|
__name(setSettings, "setSettings");
|
|
293
293
|
function writeSettingsFile(settings2) {
|
|
294
294
|
ensureConfigDir();
|
|
295
|
-
|
|
295
|
+
fs7.writeFileSync(getSettingsPath(), JSON.stringify(settings2, null, " "), {
|
|
296
296
|
mode: 384
|
|
297
297
|
});
|
|
298
298
|
}
|
|
@@ -328,7 +328,7 @@ __name(markTelemetryNoticeShown, "markTelemetryNoticeShown");
|
|
|
328
328
|
// src/version.ts
|
|
329
329
|
var VERSION = (
|
|
330
330
|
// typeof is used to ensure this can be used just via tsx or node etc. without build
|
|
331
|
-
"0.0.
|
|
331
|
+
"0.0.22"
|
|
332
332
|
);
|
|
333
333
|
var trackingEndpoint = "https://events.framer.com/track";
|
|
334
334
|
var inProgressTrackings = /* @__PURE__ */ new Set();
|
|
@@ -7133,12 +7133,78 @@ var types = {
|
|
|
7133
7133
|
description: "@alpha",
|
|
7134
7134
|
optional: false
|
|
7135
7135
|
},
|
|
7136
|
+
{
|
|
7137
|
+
name: "publishForAgent",
|
|
7138
|
+
type: "(input?: Record<string, unknown>) => Promise<unknown>",
|
|
7139
|
+
description: "@alpha",
|
|
7140
|
+
optional: false
|
|
7141
|
+
},
|
|
7142
|
+
{
|
|
7143
|
+
name: "queryImagesForAgent",
|
|
7144
|
+
type: "(input: Record<string, unknown>) => Promise<unknown>",
|
|
7145
|
+
description: "@alpha",
|
|
7146
|
+
optional: false
|
|
7147
|
+
},
|
|
7136
7148
|
{
|
|
7137
7149
|
name: "reviewChangesForAgent",
|
|
7138
7150
|
type: "(options?: {\n pagePath?: string;\n }) => Promise<unknown>",
|
|
7139
7151
|
description: "@alpha",
|
|
7140
7152
|
optional: false
|
|
7141
7153
|
},
|
|
7154
|
+
{
|
|
7155
|
+
name: "flattenComponentInstanceForAgent",
|
|
7156
|
+
type: "(input: {\n id: string;\n }, options?: {\n pagePath?: string;\n }) => Promise<unknown>",
|
|
7157
|
+
description: "@alpha",
|
|
7158
|
+
optional: false
|
|
7159
|
+
},
|
|
7160
|
+
{
|
|
7161
|
+
name: "makeExternalComponentLocalForAgent",
|
|
7162
|
+
type: "(input: {\n id: string;\n replaceAll?: boolean;\n }, options?: {\n pagePath?: string;\n }) => Promise<unknown>",
|
|
7163
|
+
description: "@alpha",
|
|
7164
|
+
optional: false
|
|
7165
|
+
},
|
|
7166
|
+
{
|
|
7167
|
+
name: "getNodeForAgent",
|
|
7168
|
+
type: "(input: {\n id: string;\n }, options?: {\n pagePath?: string;\n }) => Promise<unknown>",
|
|
7169
|
+
description: "@alpha",
|
|
7170
|
+
optional: false
|
|
7171
|
+
},
|
|
7172
|
+
{
|
|
7173
|
+
name: "getNodesForAgent",
|
|
7174
|
+
type: "(input: {\n ids: readonly string[];\n }, options?: {\n pagePath?: string;\n }) => Promise<unknown>",
|
|
7175
|
+
description: "@alpha",
|
|
7176
|
+
optional: false
|
|
7177
|
+
},
|
|
7178
|
+
{
|
|
7179
|
+
name: "getNodesOfTypesForAgent",
|
|
7180
|
+
type: "(input: {\n types: readonly string[];\n }, options?: {\n pagePath?: string;\n }) => Promise<unknown>",
|
|
7181
|
+
description: "@alpha",
|
|
7182
|
+
optional: false
|
|
7183
|
+
},
|
|
7184
|
+
{
|
|
7185
|
+
name: "getScopeNodeForAgent",
|
|
7186
|
+
type: "(input: {\n id: string;\n }, options?: {\n pagePath?: string;\n }) => Promise<unknown>",
|
|
7187
|
+
description: "@alpha",
|
|
7188
|
+
optional: false
|
|
7189
|
+
},
|
|
7190
|
+
{
|
|
7191
|
+
name: "getGroundNodeForAgent",
|
|
7192
|
+
type: "(input: {\n id: string;\n }, options?: {\n pagePath?: string;\n }) => Promise<unknown>",
|
|
7193
|
+
description: "@alpha",
|
|
7194
|
+
optional: false
|
|
7195
|
+
},
|
|
7196
|
+
{
|
|
7197
|
+
name: "getParentNodeForAgent",
|
|
7198
|
+
type: "(input: {\n id: string;\n }, options?: {\n pagePath?: string;\n }) => Promise<unknown>",
|
|
7199
|
+
description: "@alpha",
|
|
7200
|
+
optional: false
|
|
7201
|
+
},
|
|
7202
|
+
{
|
|
7203
|
+
name: "getAncestorsForAgent",
|
|
7204
|
+
type: "(input: {\n id: string;\n }, options?: {\n pagePath?: string;\n }) => Promise<unknown>",
|
|
7205
|
+
description: "@alpha",
|
|
7206
|
+
optional: false
|
|
7207
|
+
},
|
|
7142
7208
|
{
|
|
7143
7209
|
name: "startAgentConversation",
|
|
7144
7210
|
type: "(prompt: string, options?: StartAgentConversationOptions) => Promise<StartAgentConversationResult>",
|
|
@@ -7157,6 +7223,12 @@ var types = {
|
|
|
7157
7223
|
description: "@alpha",
|
|
7158
7224
|
optional: false
|
|
7159
7225
|
},
|
|
7226
|
+
{
|
|
7227
|
+
name: "runSupervisorAgentCommand",
|
|
7228
|
+
type: "(options: RunSupervisorAgentCommandOptions) => Promise<RunSupervisorAgentCommandResult>",
|
|
7229
|
+
description: "@alpha",
|
|
7230
|
+
optional: false
|
|
7231
|
+
},
|
|
7160
7232
|
{
|
|
7161
7233
|
name: "[getAiServiceInfoMessageType]",
|
|
7162
7234
|
type: "(version?: AiServiceVersion) => Promise<AiServiceInfo>",
|
|
@@ -7579,6 +7651,58 @@ var types = {
|
|
|
7579
7651
|
alias: '"auto" | "lossless" | "small" | "medium" | "large" | "full"',
|
|
7580
7652
|
references: []
|
|
7581
7653
|
},
|
|
7654
|
+
runsupervisoragentcommandoptions: {
|
|
7655
|
+
name: "RunSupervisorAgentCommandOptions",
|
|
7656
|
+
description: "",
|
|
7657
|
+
kind: "interface",
|
|
7658
|
+
references: [],
|
|
7659
|
+
members: [
|
|
7660
|
+
{
|
|
7661
|
+
name: "goal",
|
|
7662
|
+
type: "string",
|
|
7663
|
+
description: "",
|
|
7664
|
+
optional: false
|
|
7665
|
+
},
|
|
7666
|
+
{
|
|
7667
|
+
name: "model",
|
|
7668
|
+
type: "string",
|
|
7669
|
+
description: "",
|
|
7670
|
+
optional: false
|
|
7671
|
+
},
|
|
7672
|
+
{
|
|
7673
|
+
name: "pagePath",
|
|
7674
|
+
type: "string",
|
|
7675
|
+
description: "",
|
|
7676
|
+
optional: true
|
|
7677
|
+
},
|
|
7678
|
+
{
|
|
7679
|
+
name: "maxSteps",
|
|
7680
|
+
type: "number",
|
|
7681
|
+
description: "",
|
|
7682
|
+
optional: true
|
|
7683
|
+
}
|
|
7684
|
+
]
|
|
7685
|
+
},
|
|
7686
|
+
runsupervisoragentcommandresult: {
|
|
7687
|
+
name: "RunSupervisorAgentCommandResult",
|
|
7688
|
+
description: "",
|
|
7689
|
+
kind: "interface",
|
|
7690
|
+
references: [],
|
|
7691
|
+
members: [
|
|
7692
|
+
{
|
|
7693
|
+
name: "filename",
|
|
7694
|
+
type: "string",
|
|
7695
|
+
description: "",
|
|
7696
|
+
optional: false
|
|
7697
|
+
},
|
|
7698
|
+
{
|
|
7699
|
+
name: "archiveBase64",
|
|
7700
|
+
type: "string",
|
|
7701
|
+
description: "",
|
|
7702
|
+
optional: false
|
|
7703
|
+
}
|
|
7704
|
+
]
|
|
7705
|
+
},
|
|
7582
7706
|
screenshotoptions: {
|
|
7583
7707
|
name: "ScreenshotOptions",
|
|
7584
7708
|
description: "",
|
|
@@ -12891,6 +13015,13 @@ var methodsByCategory = {
|
|
|
12891
13015
|
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 getAgentSystemPrompt}.\nEach call is scoped to a single page.\n\n@param dsl - A string of commands separated by `;`. See {@link getAgentSystemPrompt} for syntax.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.',
|
|
12892
13016
|
references: []
|
|
12893
13017
|
},
|
|
13018
|
+
{
|
|
13019
|
+
name: "[$framerApiOnly.flattenComponentInstanceForAgent]",
|
|
13020
|
+
category: "framer",
|
|
13021
|
+
signature: "[$framerApiOnly.flattenComponentInstanceForAgent](input: { id: string; }, options?: { pagePath?: string; }): Promise<unknown>",
|
|
13022
|
+
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.',
|
|
13023
|
+
references: []
|
|
13024
|
+
},
|
|
12894
13025
|
{
|
|
12895
13026
|
name: "[$framerApiOnly.getAgentContext]",
|
|
12896
13027
|
category: "framer",
|
|
@@ -12905,6 +13036,76 @@ var methodsByCategory = {
|
|
|
12905
13036
|
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- **`readProjectForAgent` query reference** \u2014 available query types and their parameters.\n\nThis is the sole documentation for the command syntax used by {@link applyAgentChanges}\nand the query types used by {@link readProjectForAgent}.\n\nThe prompt is static and does not depend on any specific project.\nCall {@link getAgentContext} to get the project-specific context.\n\n@returns A string containing the agent system prompt.",
|
|
12906
13037
|
references: []
|
|
12907
13038
|
},
|
|
13039
|
+
{
|
|
13040
|
+
name: "[$framerApiOnly.getAncestorsForAgent]",
|
|
13041
|
+
category: "framer",
|
|
13042
|
+
signature: "[$framerApiOnly.getAncestorsForAgent](input: { id: string; }, options?: { pagePath?: string; }): Promise<unknown>",
|
|
13043
|
+
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.',
|
|
13044
|
+
references: []
|
|
13045
|
+
},
|
|
13046
|
+
{
|
|
13047
|
+
name: "[$framerApiOnly.getGroundNodeForAgent]",
|
|
13048
|
+
category: "framer",
|
|
13049
|
+
signature: "[$framerApiOnly.getGroundNodeForAgent](input: { id: string; }, options?: { pagePath?: string; }): Promise<unknown>",
|
|
13050
|
+
description: 'Get the top-level node on the canvas that contains the given node.\n\n@param input - `{ id }`: the id of a descendant node.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns The top-level node, or `null` if none applies.',
|
|
13051
|
+
references: []
|
|
13052
|
+
},
|
|
13053
|
+
{
|
|
13054
|
+
name: "[$framerApiOnly.getNodeForAgent]",
|
|
13055
|
+
category: "framer",
|
|
13056
|
+
signature: "[$framerApiOnly.getNodeForAgent](input: { id: string; }, options?: { pagePath?: string; }): Promise<unknown>",
|
|
13057
|
+
description: 'Get a single node on the page, including its children.\n\n@param input - `{ id }`: the id of the node to read.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns The node, or `null` if no node with that id exists on the page.',
|
|
13058
|
+
references: []
|
|
13059
|
+
},
|
|
13060
|
+
{
|
|
13061
|
+
name: "[$framerApiOnly.getNodesForAgent]",
|
|
13062
|
+
category: "framer",
|
|
13063
|
+
signature: "[$framerApiOnly.getNodesForAgent](input: { ids: readonly string[]; }, options?: { pagePath?: string; }): Promise<unknown>",
|
|
13064
|
+
description: 'Get multiple nodes on the page, including their children.\nIds that don\'t resolve to a node are skipped.\n\n@param input - `{ ids }`: the ids of the nodes to read.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns The nodes that were found, in input order.',
|
|
13065
|
+
references: []
|
|
13066
|
+
},
|
|
13067
|
+
{
|
|
13068
|
+
name: "[$framerApiOnly.getNodesOfTypesForAgent]",
|
|
13069
|
+
category: "framer",
|
|
13070
|
+
signature: "[$framerApiOnly.getNodesOfTypesForAgent](input: { types: readonly string[]; }, options?: { pagePath?: string; }): Promise<unknown>",
|
|
13071
|
+
description: 'Get every node on the page of one or more kinds (e.g. `"FrameNode"`, `"RichTextNode"`, `"ComponentInstanceNode"`).\n\n@param input - `{ types }`: the node kinds to match.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns The matching nodes without their children.',
|
|
13072
|
+
references: []
|
|
13073
|
+
},
|
|
13074
|
+
{
|
|
13075
|
+
name: "[$framerApiOnly.getParentNodeForAgent]",
|
|
13076
|
+
category: "framer",
|
|
13077
|
+
signature: "[$framerApiOnly.getParentNodeForAgent](input: { id: string; }, options?: { pagePath?: string; }): Promise<unknown>",
|
|
13078
|
+
description: 'Get the direct parent of a node.\n\n@param input - `{ id }`: the id of the child node.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns The parent node, or `null` if the node has no parent or doesn\'t exist.',
|
|
13079
|
+
references: []
|
|
13080
|
+
},
|
|
13081
|
+
{
|
|
13082
|
+
name: "[$framerApiOnly.getScopeNodeForAgent]",
|
|
13083
|
+
category: "framer",
|
|
13084
|
+
signature: "[$framerApiOnly.getScopeNodeForAgent](input: { id: string; }, options?: { pagePath?: string; }): Promise<unknown>",
|
|
13085
|
+
description: 'Get the scope node (page or component) that contains the given node.\n\n@param input - `{ id }`: the id of a node inside the scope.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns The enclosing scope node, or `null` if the node isn\'t in any scope.',
|
|
13086
|
+
references: []
|
|
13087
|
+
},
|
|
13088
|
+
{
|
|
13089
|
+
name: "[$framerApiOnly.makeExternalComponentLocalForAgent]",
|
|
13090
|
+
category: "framer",
|
|
13091
|
+
signature: "[$framerApiOnly.makeExternalComponentLocalForAgent](input: { id: string; replaceAll?: boolean; }, options?: { pagePath?: string; }): Promise<unknown>",
|
|
13092
|
+
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.',
|
|
13093
|
+
references: []
|
|
13094
|
+
},
|
|
13095
|
+
{
|
|
13096
|
+
name: "[$framerApiOnly.publishForAgent]",
|
|
13097
|
+
category: "framer",
|
|
13098
|
+
signature: "[$framerApiOnly.publishForAgent](input?: Record<string, unknown>): Promise<unknown>",
|
|
13099
|
+
description: "Executes the publish flow on behalf of an agent.\n\nThe input schema is documented in the string returned by {@link getAgentSystemPrompt}.\n\n@param input - Action-discriminated input object (preview / confirm_publish / deploy_to_production).\n@returns The action's result \u2014 status, publish URLs, and any errors, warnings, or changes.",
|
|
13100
|
+
references: []
|
|
13101
|
+
},
|
|
13102
|
+
{
|
|
13103
|
+
name: "[$framerApiOnly.queryImagesForAgent]",
|
|
13104
|
+
category: "framer",
|
|
13105
|
+
signature: "[$framerApiOnly.queryImagesForAgent](input: Record<string, unknown>): Promise<unknown>",
|
|
13106
|
+
description: 'Searches for stock images to use on the canvas (e.g. `"FrameNode"` `fill` values). Returns\ncandidate images with preview thumbnails and a `url` field for each. The returned URLs are\nregistered as trusted for this session so they can be applied directly via `fill="<url>"`\nin a subsequent {@link applyAgentChanges} DSL command. Without calling this method first,\nexternal image URLs are rejected at apply time.\n\nThe input schema is documented in the string returned by {@link getAgentSystemPrompt}.\n\n@param input - Search input object (source / query / count / orientation).\n@returns An object describing the candidates or an error.',
|
|
13107
|
+
references: []
|
|
13108
|
+
},
|
|
12908
13109
|
{
|
|
12909
13110
|
name: "[$framerApiOnly.readProjectForAgent]",
|
|
12910
13111
|
category: "framer",
|
|
@@ -13121,6 +13322,13 @@ var methodsByCategory = {
|
|
|
13121
13322
|
description: "",
|
|
13122
13323
|
references: []
|
|
13123
13324
|
},
|
|
13325
|
+
{
|
|
13326
|
+
name: "flattenComponentInstanceForAgent",
|
|
13327
|
+
category: "framer",
|
|
13328
|
+
signature: "flattenComponentInstanceForAgent(input: { id: string; }, options?: { pagePath?: string; }): Promise<unknown>",
|
|
13329
|
+
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.',
|
|
13330
|
+
references: []
|
|
13331
|
+
},
|
|
13124
13332
|
{
|
|
13125
13333
|
name: "getAgentContext",
|
|
13126
13334
|
category: "framer",
|
|
@@ -13135,6 +13343,13 @@ var methodsByCategory = {
|
|
|
13135
13343
|
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- **`readProjectForAgent` query reference** \u2014 available query types and their parameters.\n\nThis is the sole documentation for the command syntax used by {@link applyAgentChanges}\nand the query types used by {@link readProjectForAgent}.\n\nThe prompt is static and does not depend on any specific project.\nCall {@link getAgentContext} to get the project-specific context.\n\n@returns A string containing the agent system prompt.",
|
|
13136
13344
|
references: []
|
|
13137
13345
|
},
|
|
13346
|
+
{
|
|
13347
|
+
name: "getAncestorsForAgent",
|
|
13348
|
+
category: "framer",
|
|
13349
|
+
signature: "getAncestorsForAgent(input: { id: string; }, options?: { pagePath?: string; }): Promise<unknown>",
|
|
13350
|
+
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.',
|
|
13351
|
+
references: []
|
|
13352
|
+
},
|
|
13138
13353
|
{
|
|
13139
13354
|
name: "getCanvasRoot",
|
|
13140
13355
|
category: "framer",
|
|
@@ -13247,6 +13462,13 @@ var methodsByCategory = {
|
|
|
13247
13462
|
description: "Get all available fonts.\n\nUnlike the Font Picker which groups fonts by typeface, this lists\nindividual fonts for each weight and style (each representing a separate\nfont file).\n\nNote: Custom fonts are not available to plugins.\n\n@returns An array of all available fonts.\n\n@example\n```ts\nconst fonts = await framer.getFonts()\n```\n@category canvas",
|
|
13248
13463
|
references: ["Font"]
|
|
13249
13464
|
},
|
|
13465
|
+
{
|
|
13466
|
+
name: "getGroundNodeForAgent",
|
|
13467
|
+
category: "framer",
|
|
13468
|
+
signature: "getGroundNodeForAgent(input: { id: string; }, options?: { pagePath?: string; }): Promise<unknown>",
|
|
13469
|
+
description: 'Get the top-level node on the canvas that contains the given node.\n\n@param input - `{ id }`: the id of a descendant node.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns The top-level node, or `null` if none applies.',
|
|
13470
|
+
references: []
|
|
13471
|
+
},
|
|
13250
13472
|
{
|
|
13251
13473
|
name: "getImage",
|
|
13252
13474
|
category: "framer",
|
|
@@ -13296,6 +13518,27 @@ var methodsByCategory = {
|
|
|
13296
13518
|
description: "Get a node by its id.\n@category canvas",
|
|
13297
13519
|
references: ["AnyNode"]
|
|
13298
13520
|
},
|
|
13521
|
+
{
|
|
13522
|
+
name: "getNodeForAgent",
|
|
13523
|
+
category: "framer",
|
|
13524
|
+
signature: "getNodeForAgent(input: { id: string; }, options?: { pagePath?: string; }): Promise<unknown>",
|
|
13525
|
+
description: 'Get a single node on the page, including its children.\n\n@param input - `{ id }`: the id of the node to read.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns The node, or `null` if no node with that id exists on the page.',
|
|
13526
|
+
references: []
|
|
13527
|
+
},
|
|
13528
|
+
{
|
|
13529
|
+
name: "getNodesForAgent",
|
|
13530
|
+
category: "framer",
|
|
13531
|
+
signature: "getNodesForAgent(input: { ids: readonly string[]; }, options?: { pagePath?: string; }): Promise<unknown>",
|
|
13532
|
+
description: 'Get multiple nodes on the page, including their children.\nIds that don\'t resolve to a node are skipped.\n\n@param input - `{ ids }`: the ids of the nodes to read.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns The nodes that were found, in input order.',
|
|
13533
|
+
references: []
|
|
13534
|
+
},
|
|
13535
|
+
{
|
|
13536
|
+
name: "getNodesOfTypesForAgent",
|
|
13537
|
+
category: "framer",
|
|
13538
|
+
signature: "getNodesOfTypesForAgent(input: { types: readonly string[]; }, options?: { pagePath?: string; }): Promise<unknown>",
|
|
13539
|
+
description: 'Get every node on the page of one or more kinds (e.g. `"FrameNode"`, `"RichTextNode"`, `"ComponentInstanceNode"`).\n\n@param input - `{ types }`: the node kinds to match.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns The matching nodes without their children.',
|
|
13540
|
+
references: []
|
|
13541
|
+
},
|
|
13299
13542
|
{
|
|
13300
13543
|
name: "getNodesWithAttribute",
|
|
13301
13544
|
category: "framer",
|
|
@@ -13324,6 +13567,13 @@ var methodsByCategory = {
|
|
|
13324
13567
|
description: "Get the parent of a node.\n@category canvas",
|
|
13325
13568
|
references: ["AnyNode"]
|
|
13326
13569
|
},
|
|
13570
|
+
{
|
|
13571
|
+
name: "getParentNodeForAgent",
|
|
13572
|
+
category: "framer",
|
|
13573
|
+
signature: "getParentNodeForAgent(input: { id: string; }, options?: { pagePath?: string; }): Promise<unknown>",
|
|
13574
|
+
description: 'Get the direct parent of a node.\n\n@param input - `{ id }`: the id of the child node.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns The parent node, or `null` if the node has no parent or doesn\'t exist.',
|
|
13575
|
+
references: []
|
|
13576
|
+
},
|
|
13327
13577
|
{
|
|
13328
13578
|
name: "getProjectInfo",
|
|
13329
13579
|
category: "framer",
|
|
@@ -13352,6 +13602,13 @@ var methodsByCategory = {
|
|
|
13352
13602
|
description: "Get all Redirects in the project.\n\n@returns All of the Redirects in the project.\n\n@example\n```ts\nconst redirects = await framer.getRedirects()\n```\n@category settings",
|
|
13353
13603
|
references: ["Redirect"]
|
|
13354
13604
|
},
|
|
13605
|
+
{
|
|
13606
|
+
name: "getScopeNodeForAgent",
|
|
13607
|
+
category: "framer",
|
|
13608
|
+
signature: "getScopeNodeForAgent(input: { id: string; }, options?: { pagePath?: string; }): Promise<unknown>",
|
|
13609
|
+
description: 'Get the scope node (page or component) that contains the given node.\n\n@param input - `{ id }`: the id of a node inside the scope.\n@param options.pagePath - Target page path (e.g. `"/about"`). Defaults to the active page.\n@returns The enclosing scope node, or `null` if the node isn\'t in any scope.',
|
|
13610
|
+
references: []
|
|
13611
|
+
},
|
|
13355
13612
|
{
|
|
13356
13613
|
name: "getText",
|
|
13357
13614
|
category: "framer",
|
|
@@ -13380,6 +13637,13 @@ var methodsByCategory = {
|
|
|
13380
13637
|
description: "Get all available vector sets.\n\n@alpha",
|
|
13381
13638
|
references: ["VectorSet"]
|
|
13382
13639
|
},
|
|
13640
|
+
{
|
|
13641
|
+
name: "makeExternalComponentLocalForAgent",
|
|
13642
|
+
category: "framer",
|
|
13643
|
+
signature: "makeExternalComponentLocalForAgent(input: { id: string; replaceAll?: boolean; }, options?: { pagePath?: string; }): Promise<unknown>",
|
|
13644
|
+
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.',
|
|
13645
|
+
references: []
|
|
13646
|
+
},
|
|
13383
13647
|
{
|
|
13384
13648
|
name: "mode",
|
|
13385
13649
|
category: "framer",
|
|
@@ -13394,6 +13658,20 @@ var methodsByCategory = {
|
|
|
13394
13658
|
description: "",
|
|
13395
13659
|
references: ["PublishResult"]
|
|
13396
13660
|
},
|
|
13661
|
+
{
|
|
13662
|
+
name: "publishForAgent",
|
|
13663
|
+
category: "framer",
|
|
13664
|
+
signature: "publishForAgent(input?: Record<string, unknown>): Promise<unknown>",
|
|
13665
|
+
description: "Executes the publish flow on behalf of an agent.\n\nThe input schema is documented in the string returned by {@link getAgentSystemPrompt}.\n\n@param input - Action-discriminated input object (preview / confirm_publish / deploy_to_production).\n@returns The action's result \u2014 status, publish URLs, and any errors, warnings, or changes.",
|
|
13666
|
+
references: []
|
|
13667
|
+
},
|
|
13668
|
+
{
|
|
13669
|
+
name: "queryImagesForAgent",
|
|
13670
|
+
category: "framer",
|
|
13671
|
+
signature: "queryImagesForAgent(input: Record<string, unknown>): Promise<unknown>",
|
|
13672
|
+
description: 'Searches for stock images to use on the canvas (e.g. `"FrameNode"` `fill` values). Returns\ncandidate images with preview thumbnails and a `url` field for each. The returned URLs are\nregistered as trusted for this session so they can be applied directly via `fill="<url>"`\nin a subsequent {@link applyAgentChanges} DSL command. Without calling this method first,\nexternal image URLs are rejected at apply time.\n\nThe input schema is documented in the string returned by {@link getAgentSystemPrompt}.\n\n@param input - Search input object (source / query / count / orientation).\n@returns An object describing the candidates or an error.',
|
|
13673
|
+
references: []
|
|
13674
|
+
},
|
|
13397
13675
|
{
|
|
13398
13676
|
name: "readProjectForAgent",
|
|
13399
13677
|
category: "framer",
|
|
@@ -13436,6 +13714,16 @@ var methodsByCategory = {
|
|
|
13436
13714
|
description: "Reviews changes made by prior {@link applyAgentChanges} 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.",
|
|
13437
13715
|
references: []
|
|
13438
13716
|
},
|
|
13717
|
+
{
|
|
13718
|
+
name: "runSupervisorAgentCommand",
|
|
13719
|
+
category: "framer",
|
|
13720
|
+
signature: "runSupervisorAgentCommand(options: RunSupervisorAgentCommandOptions): Promise<RunSupervisorAgentCommandResult>",
|
|
13721
|
+
description: "",
|
|
13722
|
+
references: [
|
|
13723
|
+
"RunSupervisorAgentCommandOptions",
|
|
13724
|
+
"RunSupervisorAgentCommandResult"
|
|
13725
|
+
]
|
|
13726
|
+
},
|
|
13439
13727
|
{
|
|
13440
13728
|
name: "screenshot",
|
|
13441
13729
|
category: "framer",
|
|
@@ -15737,13 +16025,35 @@ function inferHeadlessServerUrl(projectUrlOrId) {
|
|
|
15737
16025
|
}
|
|
15738
16026
|
}
|
|
15739
16027
|
__name(inferHeadlessServerUrl, "inferHeadlessServerUrl");
|
|
16028
|
+
function getRelayTokenPath() {
|
|
16029
|
+
return path7.join(getConfigDir(), "relay-token");
|
|
16030
|
+
}
|
|
16031
|
+
__name(getRelayTokenPath, "getRelayTokenPath");
|
|
16032
|
+
function readRelayToken() {
|
|
16033
|
+
try {
|
|
16034
|
+
const token = fs7.readFileSync(getRelayTokenPath(), "utf-8").trim();
|
|
16035
|
+
return token.length > 0 ? token : null;
|
|
16036
|
+
} catch {
|
|
16037
|
+
return null;
|
|
16038
|
+
}
|
|
16039
|
+
}
|
|
16040
|
+
__name(readRelayToken, "readRelayToken");
|
|
16041
|
+
|
|
16042
|
+
// src/relay-client.ts
|
|
15740
16043
|
var __filename$1 = fileURLToPath(import.meta.url);
|
|
15741
|
-
var __dirname$1 =
|
|
16044
|
+
var __dirname$1 = path7.dirname(__filename$1);
|
|
15742
16045
|
var RELAY_PORT = Number(process.env.FRAMER_CLI_PORT) || 19988;
|
|
15743
16046
|
var client = createTRPCClient({
|
|
15744
16047
|
links: [
|
|
15745
16048
|
httpLink({
|
|
15746
|
-
url: `http://127.0.0.1:${RELAY_PORT}
|
|
16049
|
+
url: `http://127.0.0.1:${RELAY_PORT}`,
|
|
16050
|
+
headers() {
|
|
16051
|
+
const token = readRelayToken();
|
|
16052
|
+
if (!token) {
|
|
16053
|
+
return {};
|
|
16054
|
+
}
|
|
16055
|
+
return { Authorization: `Bearer ${token}` };
|
|
16056
|
+
}
|
|
15747
16057
|
})
|
|
15748
16058
|
]
|
|
15749
16059
|
});
|
|
@@ -15806,7 +16116,7 @@ async function ensureRelayServerRunning(options = {}) {
|
|
|
15806
16116
|
logger?.log("Relay server not running, starting it...");
|
|
15807
16117
|
}
|
|
15808
16118
|
const isRunningFromSource = __filename$1.endsWith(".ts");
|
|
15809
|
-
const scriptPath = isRunningFromSource ?
|
|
16119
|
+
const scriptPath = isRunningFromSource ? path7.resolve(__dirname$1, "./start-relay-server.ts") : path7.resolve(__dirname$1, "./start-relay-server.js");
|
|
15810
16120
|
debug("relay", `spawning server process: ${scriptPath}`);
|
|
15811
16121
|
const serverProcess = spawn(
|
|
15812
16122
|
isRunningFromSource ? "tsx" : process.execPath,
|
|
@@ -15833,19 +16143,19 @@ async function ensureRelayServerRunning(options = {}) {
|
|
|
15833
16143
|
throw new Error("Failed to start relay server after 5 seconds");
|
|
15834
16144
|
}
|
|
15835
16145
|
__name(ensureRelayServerRunning, "ensureRelayServerRunning");
|
|
15836
|
-
var FRAMER_TEMPORARY_DIR =
|
|
16146
|
+
var FRAMER_TEMPORARY_DIR = path7.join(os.tmpdir(), "framer");
|
|
15837
16147
|
function ensureTemporaryDir() {
|
|
15838
|
-
|
|
16148
|
+
fs7.mkdirSync(FRAMER_TEMPORARY_DIR, { recursive: true });
|
|
15839
16149
|
}
|
|
15840
16150
|
__name(ensureTemporaryDir, "ensureTemporaryDir");
|
|
15841
16151
|
function cleanupStaleSessionCodeFiles(activeSessionIds) {
|
|
15842
|
-
if (!
|
|
16152
|
+
if (!fs7.existsSync(FRAMER_TEMPORARY_DIR)) return;
|
|
15843
16153
|
const activeSessionIdsSet = new Set(activeSessionIds);
|
|
15844
|
-
for (const entry of
|
|
16154
|
+
for (const entry of fs7.readdirSync(FRAMER_TEMPORARY_DIR)) {
|
|
15845
16155
|
const [sessionId] = entry.split("-");
|
|
15846
16156
|
if (activeSessionIdsSet.has(sessionId)) continue;
|
|
15847
|
-
const filePath =
|
|
15848
|
-
|
|
16157
|
+
const filePath = path7.join(FRAMER_TEMPORARY_DIR, entry);
|
|
16158
|
+
fs7.rmSync(filePath, { recursive: true, force: true, maxRetries: 2 });
|
|
15849
16159
|
}
|
|
15850
16160
|
}
|
|
15851
16161
|
__name(cleanupStaleSessionCodeFiles, "cleanupStaleSessionCodeFiles");
|
|
@@ -15853,10 +16163,10 @@ __name(cleanupStaleSessionCodeFiles, "cleanupStaleSessionCodeFiles");
|
|
|
15853
16163
|
// src/skills.ts
|
|
15854
16164
|
var META_SKILL_NAME = "framer";
|
|
15855
16165
|
var CODE_COMPONENTS_SKILL_NAME = "framer-code-components";
|
|
15856
|
-
var __dirname2 =
|
|
15857
|
-
var skillsDocsDir =
|
|
16166
|
+
var __dirname2 = path7.dirname(fileURLToPath(import.meta.url));
|
|
16167
|
+
var skillsDocsDir = path7.join(__dirname2, "..", "docs", "skills");
|
|
15858
16168
|
function readSkillDoc(name2) {
|
|
15859
|
-
return
|
|
16169
|
+
return fs7.readFileSync(path7.join(skillsDocsDir, name2), "utf-8").trimEnd();
|
|
15860
16170
|
}
|
|
15861
16171
|
__name(readSkillDoc, "readSkillDoc");
|
|
15862
16172
|
function buildMetaSkill() {
|
|
@@ -15899,27 +16209,27 @@ function buildProjectCanvasSkill(projectId, agentContext, canvasPrompt) {
|
|
|
15899
16209
|
}
|
|
15900
16210
|
__name(buildProjectCanvasSkill, "buildProjectCanvasSkill");
|
|
15901
16211
|
function writeSkill(root, skillName, content) {
|
|
15902
|
-
|
|
15903
|
-
const rootStat =
|
|
16212
|
+
fs7.mkdirSync(root, { recursive: true });
|
|
16213
|
+
const rootStat = fs7.statSync(root);
|
|
15904
16214
|
if (!rootStat.isDirectory()) {
|
|
15905
16215
|
throw new Error(`Skill root is not a directory: ${root}`);
|
|
15906
16216
|
}
|
|
15907
|
-
const skillDir =
|
|
15908
|
-
const filePath =
|
|
15909
|
-
const current =
|
|
16217
|
+
const skillDir = path7.join(root, skillName);
|
|
16218
|
+
const filePath = path7.join(skillDir, "SKILL.md");
|
|
16219
|
+
const current = fs7.lstatSync(skillDir, { throwIfNoEntry: false });
|
|
15910
16220
|
if (current && (current.isSymbolicLink() || !current.isDirectory())) {
|
|
15911
|
-
|
|
16221
|
+
fs7.rmSync(skillDir, { recursive: true, force: true });
|
|
15912
16222
|
}
|
|
15913
|
-
|
|
15914
|
-
|
|
16223
|
+
fs7.mkdirSync(skillDir, { recursive: true });
|
|
16224
|
+
fs7.writeFileSync(filePath, content, "utf-8");
|
|
15915
16225
|
return filePath;
|
|
15916
16226
|
}
|
|
15917
16227
|
__name(writeSkill, "writeSkill");
|
|
15918
16228
|
function getDefaultSkillRoots() {
|
|
15919
16229
|
const home = os.homedir();
|
|
15920
16230
|
return [
|
|
15921
|
-
|
|
15922
|
-
|
|
16231
|
+
path7.join(home, ".agents", "skills"),
|
|
16232
|
+
path7.join(home, ".claude", "skills")
|
|
15923
16233
|
];
|
|
15924
16234
|
}
|
|
15925
16235
|
__name(getDefaultSkillRoots, "getDefaultSkillRoots");
|
|
@@ -15929,14 +16239,14 @@ function cleanupStaleSkills(activeProjectIds, skillRoots) {
|
|
|
15929
16239
|
[...activeProjectIds].map(toSafeProjectId)
|
|
15930
16240
|
);
|
|
15931
16241
|
for (const root of roots) {
|
|
15932
|
-
if (!
|
|
15933
|
-
for (const entry of
|
|
16242
|
+
if (!fs7.existsSync(root)) continue;
|
|
16243
|
+
for (const entry of fs7.readdirSync(root)) {
|
|
15934
16244
|
if (!entry.startsWith(CANVAS_SKILL_PREFIX)) continue;
|
|
15935
16245
|
const sanitizedProjectId = entry.slice(CANVAS_SKILL_PREFIX.length);
|
|
15936
16246
|
const isActive = sanitizedActiveProjectIds.has(sanitizedProjectId);
|
|
15937
16247
|
if (isActive) continue;
|
|
15938
|
-
const skillDir =
|
|
15939
|
-
|
|
16248
|
+
const skillDir = path7.join(root, entry);
|
|
16249
|
+
fs7.rmSync(skillDir, { recursive: true, force: true, maxRetries: 2 });
|
|
15940
16250
|
}
|
|
15941
16251
|
}
|
|
15942
16252
|
}
|
|
@@ -15997,8 +16307,8 @@ function printSetupSummary(results) {
|
|
|
15997
16307
|
const installLocations = /* @__PURE__ */ new Set();
|
|
15998
16308
|
for (const result of results) {
|
|
15999
16309
|
for (const filePath of result.paths) {
|
|
16000
|
-
const skillDir =
|
|
16001
|
-
const root =
|
|
16310
|
+
const skillDir = path7.dirname(filePath);
|
|
16311
|
+
const root = path7.dirname(skillDir);
|
|
16002
16312
|
installLocations.add(root);
|
|
16003
16313
|
}
|
|
16004
16314
|
}
|
|
@@ -16173,7 +16483,7 @@ program.command("exec").description("Execute code in a session").requiredOption(
|
|
|
16173
16483
|
let code = evalCode;
|
|
16174
16484
|
if (!code && filePath) {
|
|
16175
16485
|
try {
|
|
16176
|
-
code =
|
|
16486
|
+
code = fs7.readFileSync(filePath, "utf-8");
|
|
16177
16487
|
} catch (err) {
|
|
16178
16488
|
printError(`Failed to read file: ${formatError(err)}`);
|
|
16179
16489
|
await waitForTrackingToFinish();
|