windmill-cli 1.691.1 → 1.692.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/README.md +1 -0
- package/esm/main.js +1784 -282
- package/package.json +1 -1
package/esm/main.js
CHANGED
|
@@ -16224,6 +16224,14 @@ var execFile5, __dirname2, localXdgOpenPath, platform, arch, pTryEach = async (a
|
|
|
16224
16224
|
}
|
|
16225
16225
|
subprocess.unref();
|
|
16226
16226
|
return subprocess;
|
|
16227
|
+
}, open = (target, options) => {
|
|
16228
|
+
if (typeof target !== "string") {
|
|
16229
|
+
throw new TypeError("Expected a `target`");
|
|
16230
|
+
}
|
|
16231
|
+
return baseOpen({
|
|
16232
|
+
...options,
|
|
16233
|
+
target
|
|
16234
|
+
});
|
|
16227
16235
|
}, openApp = (name, options) => {
|
|
16228
16236
|
if (typeof name !== "string" && !Array.isArray(name)) {
|
|
16229
16237
|
throw new TypeError("Expected a valid `name`");
|
|
@@ -16239,7 +16247,7 @@ var execFile5, __dirname2, localXdgOpenPath, platform, arch, pTryEach = async (a
|
|
|
16239
16247
|
arguments: appArguments
|
|
16240
16248
|
}
|
|
16241
16249
|
});
|
|
16242
|
-
}, apps;
|
|
16250
|
+
}, apps, open_default;
|
|
16243
16251
|
var init_open = __esm(() => {
|
|
16244
16252
|
init_wsl_utils();
|
|
16245
16253
|
init_default_browser();
|
|
@@ -16285,6 +16293,7 @@ var init_open = __esm(() => {
|
|
|
16285
16293
|
}));
|
|
16286
16294
|
defineLazyProperty(apps, "browser", () => "browser");
|
|
16287
16295
|
defineLazyProperty(apps, "browserPrivate", () => "browserPrivate");
|
|
16296
|
+
open_default = open;
|
|
16288
16297
|
});
|
|
16289
16298
|
|
|
16290
16299
|
// node_modules/@cliffy/prompt/secret.js
|
|
@@ -16408,7 +16417,7 @@ async function browserLogin(baseUrl) {
|
|
|
16408
16417
|
const url = `${baseUrl}user/cli?port=${port}`;
|
|
16409
16418
|
info(`Login by going to ${url}`);
|
|
16410
16419
|
try {
|
|
16411
|
-
|
|
16420
|
+
open_default(url).catch((error2) => {
|
|
16412
16421
|
console.error(`Failed to open browser, please navigate to ${url}, error: ${error2}`);
|
|
16413
16422
|
});
|
|
16414
16423
|
info("Opened browser for you");
|
|
@@ -16701,7 +16710,7 @@ var init_OpenAPI = __esm(() => {
|
|
|
16701
16710
|
PASSWORD: undefined,
|
|
16702
16711
|
TOKEN: getEnv3("WM_TOKEN"),
|
|
16703
16712
|
USERNAME: undefined,
|
|
16704
|
-
VERSION: "1.
|
|
16713
|
+
VERSION: "1.692.0",
|
|
16705
16714
|
WITH_CREDENTIALS: true,
|
|
16706
16715
|
interceptors: {
|
|
16707
16716
|
request: new Interceptors,
|
|
@@ -26226,9 +26235,6 @@ function getFolderSuffixes() {
|
|
|
26226
26235
|
function getFolderSuffix(type) {
|
|
26227
26236
|
return getFolderSuffixes()[type];
|
|
26228
26237
|
}
|
|
26229
|
-
function getFolderSuffixWithSep(type) {
|
|
26230
|
-
return getFolderSuffixes()[type] + SEP2;
|
|
26231
|
-
}
|
|
26232
26238
|
function getMetadataFileName(type, format6) {
|
|
26233
26239
|
return METADATA_FILES[type][format6];
|
|
26234
26240
|
}
|
|
@@ -30232,6 +30238,74 @@ return schema
|
|
|
30232
30238
|
rawAppWmillTs_exports = /* @__PURE__ */ __export2({ default: () => rawAppWmillTs_default }, 1);
|
|
30233
30239
|
});
|
|
30234
30240
|
|
|
30241
|
+
// src/utils/port-probe.ts
|
|
30242
|
+
import { createServer as createServer2 } from "node:net";
|
|
30243
|
+
import { execSync as execSync4 } from "node:child_process";
|
|
30244
|
+
function isPortFree(port, host) {
|
|
30245
|
+
return new Promise((resolve6) => {
|
|
30246
|
+
const s = createServer2();
|
|
30247
|
+
s.once("error", (err) => {
|
|
30248
|
+
const code2 = err.code ?? "";
|
|
30249
|
+
resolve6(code2 !== "EADDRINUSE" && code2 !== "EACCES");
|
|
30250
|
+
});
|
|
30251
|
+
s.once("listening", () => s.close(() => resolve6(true)));
|
|
30252
|
+
s.listen(port, host);
|
|
30253
|
+
});
|
|
30254
|
+
}
|
|
30255
|
+
async function isPortFreeOnBothStacks(port) {
|
|
30256
|
+
if (!await isPortFree(port, "0.0.0.0"))
|
|
30257
|
+
return false;
|
|
30258
|
+
if (!await isPortFree(port, "::"))
|
|
30259
|
+
return false;
|
|
30260
|
+
return true;
|
|
30261
|
+
}
|
|
30262
|
+
function findPortHolder(port) {
|
|
30263
|
+
try {
|
|
30264
|
+
const out = execSync4(`lsof -nP -iTCP:${port} -sTCP:LISTEN -F pc 2>/dev/null`, {
|
|
30265
|
+
encoding: "utf-8",
|
|
30266
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
30267
|
+
});
|
|
30268
|
+
let pid;
|
|
30269
|
+
let cmd;
|
|
30270
|
+
for (const line of out.split(`
|
|
30271
|
+
`)) {
|
|
30272
|
+
if (line.startsWith("p"))
|
|
30273
|
+
pid = parseInt(line.slice(1), 10);
|
|
30274
|
+
else if (line.startsWith("c"))
|
|
30275
|
+
cmd = line.slice(1);
|
|
30276
|
+
if (pid && cmd)
|
|
30277
|
+
return { pid, command: cmd };
|
|
30278
|
+
}
|
|
30279
|
+
} catch {}
|
|
30280
|
+
try {
|
|
30281
|
+
const out = execSync4(`ss -ltnp 2>/dev/null | awk '$4 ~ /:${port}$/ { print $NF }'`, {
|
|
30282
|
+
encoding: "utf-8",
|
|
30283
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
30284
|
+
}).trim();
|
|
30285
|
+
const m = out.match(/\("([^"]+)",pid=(\d+)/);
|
|
30286
|
+
if (m)
|
|
30287
|
+
return { pid: parseInt(m[2], 10), command: m[1] };
|
|
30288
|
+
} catch {}
|
|
30289
|
+
return;
|
|
30290
|
+
}
|
|
30291
|
+
async function resolveBindPort(requested, flagLabel, log) {
|
|
30292
|
+
const MAX_SHIFT = 20;
|
|
30293
|
+
for (let port = requested;port < requested + MAX_SHIFT; port++) {
|
|
30294
|
+
if (await isPortFreeOnBothStacks(port)) {
|
|
30295
|
+
if (port !== requested) {
|
|
30296
|
+
const holder = findPortHolder(requested);
|
|
30297
|
+
const holderHint = holder ? ` (held by PID ${holder.pid} \`${holder.command}\`)` : "";
|
|
30298
|
+
log.warn(`Port ${requested} is already in use${holderHint}. Using port ${port} instead.`);
|
|
30299
|
+
log.info(`If you need port ${requested} stable (e.g. a launch.json entry pinned to it), stop the holder and re-run with ${flagLabel} ${requested}.`);
|
|
30300
|
+
}
|
|
30301
|
+
return port;
|
|
30302
|
+
}
|
|
30303
|
+
}
|
|
30304
|
+
throw new Error(`Could not find a free port in the range ${requested}-${requested + MAX_SHIFT - 1}. Stop a holder or pass ${flagLabel} <other>.`);
|
|
30305
|
+
}
|
|
30306
|
+
var BIND_HOST = "0.0.0.0";
|
|
30307
|
+
var init_port_probe = () => {};
|
|
30308
|
+
|
|
30235
30309
|
// node_modules/ws/lib/stream.js
|
|
30236
30310
|
var require_stream = __commonJS((exports, module) => {
|
|
30237
30311
|
var { Duplex } = __require("stream");
|
|
@@ -30296,7 +30370,7 @@ var require_stream = __commonJS((exports, module) => {
|
|
|
30296
30370
|
};
|
|
30297
30371
|
duplex._final = function(callback) {
|
|
30298
30372
|
if (ws.readyState === ws.CONNECTING) {
|
|
30299
|
-
ws.once("open", function
|
|
30373
|
+
ws.once("open", function open2() {
|
|
30300
30374
|
duplex._final(callback);
|
|
30301
30375
|
});
|
|
30302
30376
|
return;
|
|
@@ -30320,7 +30394,7 @@ var require_stream = __commonJS((exports, module) => {
|
|
|
30320
30394
|
};
|
|
30321
30395
|
duplex._write = function(chunk, encoding, callback) {
|
|
30322
30396
|
if (ws.readyState === ws.CONNECTING) {
|
|
30323
|
-
ws.once("open", function
|
|
30397
|
+
ws.once("open", function open2() {
|
|
30324
30398
|
duplex._write(chunk, encoding, callback);
|
|
30325
30399
|
});
|
|
30326
30400
|
return;
|
|
@@ -34923,10 +34997,10 @@ globstar while`, file, fr, pattern, pr, swallowee);
|
|
|
34923
34997
|
}
|
|
34924
34998
|
return filtered.join("/");
|
|
34925
34999
|
}).join("|");
|
|
34926
|
-
const [
|
|
34927
|
-
re = "^" +
|
|
35000
|
+
const [open2, close] = set.length > 1 ? ["(?:", ")"] : ["", ""];
|
|
35001
|
+
re = "^" + open2 + re + close + "$";
|
|
34928
35002
|
if (this.partial) {
|
|
34929
|
-
re = "^(?:\\/|" +
|
|
35003
|
+
re = "^(?:\\/|" + open2 + re.slice(1, -1) + close + ")$";
|
|
34930
35004
|
}
|
|
34931
35005
|
if (this.negate)
|
|
34932
35006
|
re = "^(?!" + re + ").+$";
|
|
@@ -61383,7 +61457,7 @@ import { Buffer as Buffer4 } from "node:buffer";
|
|
|
61383
61457
|
import { sep as SEP4 } from "node:path";
|
|
61384
61458
|
import * as path7 from "node:path";
|
|
61385
61459
|
import fs8 from "node:fs";
|
|
61386
|
-
import { execSync as
|
|
61460
|
+
import { execSync as execSync5 } from "node:child_process";
|
|
61387
61461
|
function isRawAppBackendPath2(filePath) {
|
|
61388
61462
|
return isRawAppBackendPath(filePath);
|
|
61389
61463
|
}
|
|
@@ -61484,7 +61558,7 @@ async function handleFile(path8, workspace, alreadySynced, message, opts, rawWor
|
|
|
61484
61558
|
let outputFiles = [];
|
|
61485
61559
|
if (codebase.customBundler) {
|
|
61486
61560
|
info(`Using custom bundler ${codebase.customBundler} for ${path8}`);
|
|
61487
|
-
bundleContent =
|
|
61561
|
+
bundleContent = execSync5(codebase.customBundler + " " + path8, {
|
|
61488
61562
|
maxBuffer: 1024 * 1024 * 50
|
|
61489
61563
|
}).toString();
|
|
61490
61564
|
info("Custom bundler executed for " + path8);
|
|
@@ -62177,7 +62251,7 @@ async function preview(opts, filePath) {
|
|
|
62177
62251
|
if (!opts.silent) {
|
|
62178
62252
|
info(`Using custom bundler ${codebase.customBundler} for preview`);
|
|
62179
62253
|
}
|
|
62180
|
-
bundledContent =
|
|
62254
|
+
bundledContent = execSync5(codebase.customBundler + " " + filePath, {
|
|
62181
62255
|
maxBuffer: 52428800
|
|
62182
62256
|
}).toString();
|
|
62183
62257
|
} else {
|
|
@@ -68608,10 +68682,14 @@ async function dev(opts, appFolder) {
|
|
|
68608
68682
|
const rawApp = await yamlParseFile(rawAppPath);
|
|
68609
68683
|
const appPath = rawApp?.custom_path ?? "u/unknown/newapp";
|
|
68610
68684
|
const esbuild = await import("esbuild");
|
|
68611
|
-
const
|
|
68685
|
+
const host = opts.host ?? DEFAULT_HOST;
|
|
68686
|
+
const probeBothStacks = host === DEFAULT_HOST;
|
|
68687
|
+
const port = opts.port !== undefined ? probeBothStacks ? await resolveBindPort(opts.port, "--port", {
|
|
68688
|
+
info: (m) => info(m),
|
|
68689
|
+
warn: (m) => warn(m)
|
|
68690
|
+
}) : opts.port : await getPorts({
|
|
68612
68691
|
port: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((p) => p + DEFAULT_PORT)
|
|
68613
68692
|
});
|
|
68614
|
-
const host = opts.host ?? DEFAULT_HOST;
|
|
68615
68693
|
const shouldOpen = opts.open ?? true;
|
|
68616
68694
|
const frameworks = detectFrameworks(process16.cwd());
|
|
68617
68695
|
const defaultEntry = frameworks.svelte || frameworks.vue ? "index.ts" : "index.tsx";
|
|
@@ -69714,6 +69792,7 @@ var init_dev = __esm(async () => {
|
|
|
69714
69792
|
init_log();
|
|
69715
69793
|
init_lib_es();
|
|
69716
69794
|
init_get_port();
|
|
69795
|
+
init_port_probe();
|
|
69717
69796
|
init_open();
|
|
69718
69797
|
init_wrapper();
|
|
69719
69798
|
init_services_gen();
|
|
@@ -69880,8 +69959,9 @@ var init_lint2 = __esm(async () => {
|
|
|
69880
69959
|
});
|
|
69881
69960
|
|
|
69882
69961
|
// src/commands/app/new.ts
|
|
69883
|
-
import { stat as stat9, writeFile as writeFile10, mkdir as mkdir7 } from "node:fs/promises";
|
|
69962
|
+
import { stat as stat9, writeFile as writeFile10, mkdir as mkdir7, rm as rm3 } from "node:fs/promises";
|
|
69884
69963
|
import path17 from "node:path";
|
|
69964
|
+
import { execSync as execSync6, exec, execFile as execFile6 } from "node:child_process";
|
|
69885
69965
|
function validateAppPath(appPath) {
|
|
69886
69966
|
if (!appPath.startsWith("u/") && !appPath.startsWith("f/")) {
|
|
69887
69967
|
return {
|
|
@@ -69948,16 +70028,25 @@ async function newApp(opts) {
|
|
|
69948
70028
|
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
69949
70029
|
warn(colors.yellow(`Could not fetch datatables: ${errorMessage}`));
|
|
69950
70030
|
}
|
|
69951
|
-
|
|
69952
|
-
|
|
69953
|
-
|
|
69954
|
-
|
|
69955
|
-
|
|
69956
|
-
return "Summary cannot be empty";
|
|
69957
|
-
}
|
|
69958
|
-
return true;
|
|
70031
|
+
let summary;
|
|
70032
|
+
if (opts.summary !== undefined) {
|
|
70033
|
+
if (opts.summary.trim().length === 0) {
|
|
70034
|
+
error(colors.red("--summary cannot be empty"));
|
|
70035
|
+
return;
|
|
69959
70036
|
}
|
|
69960
|
-
|
|
70037
|
+
summary = opts.summary;
|
|
70038
|
+
} else {
|
|
70039
|
+
summary = await Input.prompt({
|
|
70040
|
+
message: "App summary (short description):",
|
|
70041
|
+
minLength: 1,
|
|
70042
|
+
validate: (value) => {
|
|
70043
|
+
if (value.trim().length === 0) {
|
|
70044
|
+
return "Summary cannot be empty";
|
|
70045
|
+
}
|
|
70046
|
+
return true;
|
|
70047
|
+
}
|
|
70048
|
+
});
|
|
70049
|
+
}
|
|
69961
70050
|
const buildPathSuggestions = (input) => {
|
|
69962
70051
|
const suggestions = [];
|
|
69963
70052
|
if (input.length < 2) {
|
|
@@ -69974,27 +70063,46 @@ async function newApp(opts) {
|
|
|
69974
70063
|
return suggestions;
|
|
69975
70064
|
};
|
|
69976
70065
|
let appPath;
|
|
69977
|
-
|
|
69978
|
-
|
|
69979
|
-
|
|
69980
|
-
|
|
69981
|
-
|
|
69982
|
-
}
|
|
69983
|
-
|
|
69984
|
-
|
|
69985
|
-
|
|
70066
|
+
if (opts.path !== undefined) {
|
|
70067
|
+
const validation = validateAppPath(opts.path);
|
|
70068
|
+
if (!validation.valid) {
|
|
70069
|
+
error(colors.red(`Invalid --path: ${validation.error}`));
|
|
70070
|
+
return;
|
|
70071
|
+
}
|
|
70072
|
+
appPath = opts.path;
|
|
70073
|
+
} else {
|
|
70074
|
+
while (true) {
|
|
70075
|
+
appPath = await Input.prompt({
|
|
70076
|
+
message: "App path (e.g., f/my_folder/my_app or u/username/my_app):",
|
|
70077
|
+
minLength: 1,
|
|
70078
|
+
suggestions: buildPathSuggestions
|
|
70079
|
+
});
|
|
70080
|
+
const validation = validateAppPath(appPath);
|
|
70081
|
+
if (validation.valid) {
|
|
70082
|
+
break;
|
|
70083
|
+
}
|
|
70084
|
+
error(colors.red(`Invalid path: ${validation.error}`));
|
|
69986
70085
|
}
|
|
69987
|
-
error(colors.red(`Invalid path: ${validation.error}`));
|
|
69988
70086
|
}
|
|
69989
|
-
const
|
|
69990
|
-
|
|
69991
|
-
|
|
69992
|
-
|
|
69993
|
-
|
|
69994
|
-
|
|
69995
|
-
|
|
69996
|
-
|
|
69997
|
-
}
|
|
70087
|
+
const VALID_FRAMEWORKS = ["react19", "react18", "svelte5", "vue"];
|
|
70088
|
+
let framework;
|
|
70089
|
+
if (opts.framework !== undefined) {
|
|
70090
|
+
if (!VALID_FRAMEWORKS.includes(opts.framework)) {
|
|
70091
|
+
error(colors.red(`Invalid --framework: ${opts.framework}. Must be one of: ${VALID_FRAMEWORKS.join(", ")}`));
|
|
70092
|
+
return;
|
|
70093
|
+
}
|
|
70094
|
+
framework = opts.framework;
|
|
70095
|
+
} else {
|
|
70096
|
+
framework = await Select.prompt({
|
|
70097
|
+
message: "Select a framework:",
|
|
70098
|
+
options: [
|
|
70099
|
+
{ name: "React 19 (Recommended)", value: "react19" },
|
|
70100
|
+
{ name: "React 18", value: "react18" },
|
|
70101
|
+
{ name: "Svelte 5", value: "svelte5" },
|
|
70102
|
+
{ name: "Vue 3", value: "vue" }
|
|
70103
|
+
]
|
|
70104
|
+
});
|
|
70105
|
+
}
|
|
69998
70106
|
const template = templates[framework];
|
|
69999
70107
|
if (!template) {
|
|
70000
70108
|
error(colors.red(`Unknown framework: ${framework}`));
|
|
@@ -70003,7 +70111,29 @@ async function newApp(opts) {
|
|
|
70003
70111
|
let dataConfig = {};
|
|
70004
70112
|
let createSchemaSQL;
|
|
70005
70113
|
let schemaName;
|
|
70006
|
-
|
|
70114
|
+
const nonInteractive = opts.summary !== undefined || opts.path !== undefined || opts.framework !== undefined;
|
|
70115
|
+
if (opts.datatable !== undefined) {
|
|
70116
|
+
if (datatables.length > 0 && !datatables.includes(opts.datatable)) {
|
|
70117
|
+
warn(colors.yellow(`--datatable '${opts.datatable}' is not in the workspace's datatable list (${datatables.join(", ")}). Continuing anyway.`));
|
|
70118
|
+
}
|
|
70119
|
+
dataConfig.datatable = opts.datatable;
|
|
70120
|
+
if (opts.schema !== undefined) {
|
|
70121
|
+
if (!/^[a-z_][a-z0-9_]*$/.test(opts.schema)) {
|
|
70122
|
+
error(colors.red(`--schema must start with a letter or underscore and contain only lowercase letters, numbers, and underscores: ${opts.schema}`));
|
|
70123
|
+
return;
|
|
70124
|
+
}
|
|
70125
|
+
schemaName = opts.schema;
|
|
70126
|
+
dataConfig.schema = schemaName;
|
|
70127
|
+
const existingSchemas = datatableSchemas.get(opts.datatable) ?? [];
|
|
70128
|
+
if (!existingSchemas.includes(schemaName)) {
|
|
70129
|
+
createSchemaSQL = `-- Create schema for ${summary}
|
|
70130
|
+
-- This will be executed when you run 'wmill app dev' and confirm in the modal
|
|
70131
|
+
CREATE SCHEMA IF NOT EXISTS ${schemaName};
|
|
70132
|
+
`;
|
|
70133
|
+
}
|
|
70134
|
+
}
|
|
70135
|
+
dataConfig.tables = [];
|
|
70136
|
+
} else if (nonInteractive) {} else if (datatables.length > 0) {
|
|
70007
70137
|
info("");
|
|
70008
70138
|
info(colors.bold.cyan("Data Configuration"));
|
|
70009
70139
|
info(colors.gray("Configure datatables to enable AI to create and query database tables."));
|
|
@@ -70087,17 +70217,29 @@ CREATE SCHEMA IF NOT EXISTS ${schemaName};
|
|
|
70087
70217
|
await loadNonDottedPathsSetting();
|
|
70088
70218
|
const folderName2 = buildFolderPath(appPath, "raw_app");
|
|
70089
70219
|
const appDir = path17.join(process.cwd(), folderName2);
|
|
70220
|
+
let dirExists = false;
|
|
70090
70221
|
try {
|
|
70091
70222
|
await stat9(appDir);
|
|
70092
|
-
|
|
70093
|
-
|
|
70094
|
-
|
|
70095
|
-
|
|
70096
|
-
|
|
70097
|
-
|
|
70223
|
+
dirExists = true;
|
|
70224
|
+
} catch {}
|
|
70225
|
+
if (dirExists) {
|
|
70226
|
+
if (opts.overwrite) {
|
|
70227
|
+
warn(colors.yellow(`Overwriting existing '${folderName2}' (--overwrite)`));
|
|
70228
|
+
} else if (nonInteractive) {
|
|
70229
|
+
error(colors.red(`Directory '${folderName2}' already exists. Pass --overwrite to replace it.`));
|
|
70098
70230
|
return;
|
|
70231
|
+
} else {
|
|
70232
|
+
const overwrite = await Confirm.prompt({
|
|
70233
|
+
message: `Directory '${folderName2}' already exists. Overwrite?`,
|
|
70234
|
+
default: false
|
|
70235
|
+
});
|
|
70236
|
+
if (!overwrite) {
|
|
70237
|
+
info(colors.yellow("Aborted."));
|
|
70238
|
+
return;
|
|
70239
|
+
}
|
|
70099
70240
|
}
|
|
70100
|
-
|
|
70241
|
+
await rm3(appDir, { recursive: true, force: true });
|
|
70242
|
+
}
|
|
70101
70243
|
await mkdir7(appDir, { recursive: true });
|
|
70102
70244
|
await mkdir7(path17.join(appDir, "backend"), { recursive: true });
|
|
70103
70245
|
await mkdir7(path17.join(appDir, "sql_to_apply"), { recursive: true });
|
|
@@ -70202,6 +70344,69 @@ This folder is for SQL migration files that will be applied to datatables during
|
|
|
70202
70344
|
}
|
|
70203
70345
|
info("");
|
|
70204
70346
|
info(colors.gray(" 4. wmill sync push (to deploy when ready)"));
|
|
70347
|
+
let hasClaudeDesktop = false;
|
|
70348
|
+
if (process.platform === "darwin") {
|
|
70349
|
+
try {
|
|
70350
|
+
execSync6("ls /Applications/Claude.app", { stdio: "ignore" });
|
|
70351
|
+
hasClaudeDesktop = true;
|
|
70352
|
+
} catch {}
|
|
70353
|
+
}
|
|
70354
|
+
if (hasClaudeDesktop && !nonInteractive && opts.openInDesktop !== false) {
|
|
70355
|
+
info("");
|
|
70356
|
+
const openInDesktop = await Confirm.prompt({
|
|
70357
|
+
message: "Open in Claude Desktop?",
|
|
70358
|
+
default: true
|
|
70359
|
+
});
|
|
70360
|
+
if (openInDesktop) {
|
|
70361
|
+
try {
|
|
70362
|
+
const absAppDir = path17.resolve(appDir);
|
|
70363
|
+
const claudeDir = path17.join(absAppDir, ".claude");
|
|
70364
|
+
const launchPath = path17.join(claudeDir, "launch.json");
|
|
70365
|
+
if (!await stat9(launchPath).catch(() => null)) {
|
|
70366
|
+
const launchJson = JSON.stringify({
|
|
70367
|
+
version: "0.0.1",
|
|
70368
|
+
configurations: [{
|
|
70369
|
+
name: `windmill: ${appPath}`,
|
|
70370
|
+
runtimeExecutable: "bash",
|
|
70371
|
+
runtimeArgs: ["-c", "wmill app dev --no-open --port ${PORT:-4000}"],
|
|
70372
|
+
port: 4000,
|
|
70373
|
+
autoPort: true
|
|
70374
|
+
}]
|
|
70375
|
+
}, null, 2) + `
|
|
70376
|
+
`;
|
|
70377
|
+
await mkdir7(claudeDir, { recursive: true });
|
|
70378
|
+
await writeFile10(launchPath, launchJson, "utf-8");
|
|
70379
|
+
info(colors.gray(`Seeded ${path17.relative(process.cwd(), launchPath)}`));
|
|
70380
|
+
}
|
|
70381
|
+
const sessionId = crypto.randomUUID();
|
|
70382
|
+
const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
70383
|
+
let i = 0;
|
|
70384
|
+
const spinner = setInterval(() => {
|
|
70385
|
+
process.stdout.write(`\r${colors.gray(`${frames[i++ % frames.length]} Creating Claude session...`)}`);
|
|
70386
|
+
}, 80);
|
|
70387
|
+
try {
|
|
70388
|
+
await new Promise((resolve8, reject) => {
|
|
70389
|
+
exec(`claude --session-id "${sessionId}" -p "Say: Your app is ready, click on preview to test it!"`, { cwd: absAppDir }, (error2) => error2 ? reject(error2) : resolve8());
|
|
70390
|
+
});
|
|
70391
|
+
} finally {
|
|
70392
|
+
clearInterval(spinner);
|
|
70393
|
+
process.stdout.write("\r" + " ".repeat(40) + "\r");
|
|
70394
|
+
}
|
|
70395
|
+
const deepLink = `claude://resume?session=${sessionId}&cwd=${encodeURIComponent(absAppDir)}`;
|
|
70396
|
+
execFile6("open", [deepLink], (err) => {
|
|
70397
|
+
if (err) {
|
|
70398
|
+
warn(colors.yellow(`Could not open Claude Desktop deep link (${err.message}). Open it manually: ${deepLink}`));
|
|
70399
|
+
} else {
|
|
70400
|
+
info(colors.bold.green("Opened in Claude Desktop!"));
|
|
70401
|
+
}
|
|
70402
|
+
});
|
|
70403
|
+
} catch (error2) {
|
|
70404
|
+
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
70405
|
+
warn(colors.yellow(`Could not open in Claude Desktop: ${errorMessage}`));
|
|
70406
|
+
info(colors.gray("You can manually run: cd " + folderName2 + " && claude"));
|
|
70407
|
+
}
|
|
70408
|
+
}
|
|
70409
|
+
}
|
|
70205
70410
|
}
|
|
70206
70411
|
var import_yaml22, reactIndex = `
|
|
70207
70412
|
import React from 'react'
|
|
@@ -70272,7 +70477,18 @@ const msg = ref('world');
|
|
|
70272
70477
|
import App from './App.vue'
|
|
70273
70478
|
import "./index.css";
|
|
70274
70479
|
|
|
70275
|
-
createApp(App).mount('#root')`, indexCss =
|
|
70480
|
+
createApp(App).mount('#root')`, indexCss = `body {
|
|
70481
|
+
margin: 0;
|
|
70482
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
70483
|
+
background-color: #f5f5f5;
|
|
70484
|
+
color: #1a1a1a;
|
|
70485
|
+
}
|
|
70486
|
+
|
|
70487
|
+
#root {
|
|
70488
|
+
padding: 24px;
|
|
70489
|
+
}
|
|
70490
|
+
|
|
70491
|
+
.myclass {
|
|
70276
70492
|
border: 1px solid gray;
|
|
70277
70493
|
padding: 2px;
|
|
70278
70494
|
}`, templates, command11, new_default;
|
|
@@ -70360,7 +70576,7 @@ var init_new = __esm(async () => {
|
|
|
70360
70576
|
}
|
|
70361
70577
|
}
|
|
70362
70578
|
};
|
|
70363
|
-
command11 = new Command().description("create a new raw app from a template").action(newApp);
|
|
70579
|
+
command11 = new Command().description("create a new raw app from a template").option("--summary <summary:string>", "App summary (short description). Skips the prompt when provided. Triggers non-interactive mode.").option("--path <path:string>", "App path (e.g., f/folder/my_app or u/username/my_app). Skips the prompt when provided. Triggers non-interactive mode.").option("--framework <framework:string>", "Framework template: react19 | react18 | svelte5 | vue. Skips the prompt when provided. Triggers non-interactive mode.").option("--datatable <datatable:string>", "Datatable to wire up. Without this flag in non-interactive mode, no datatable is configured.").option("--schema <schema:string>", "Schema to use with --datatable. Created (CREATE SCHEMA IF NOT EXISTS) if it doesn't already exist.").option("--overwrite", "Overwrite the target directory if it already exists, without prompting.").option("--no-open-in-desktop", "Do not prompt to open the new app in Claude Desktop.").action(newApp);
|
|
70364
70580
|
new_default = command11;
|
|
70365
70581
|
});
|
|
70366
70582
|
|
|
@@ -71826,7 +72042,7 @@ var init_settings = __esm(async () => {
|
|
|
71826
72042
|
});
|
|
71827
72043
|
|
|
71828
72044
|
// src/commands/instance/instance.ts
|
|
71829
|
-
import { writeFile as writeFile15, readdir as readdir9, mkdir as mkdir11, rm as
|
|
72045
|
+
import { writeFile as writeFile15, readdir as readdir9, mkdir as mkdir11, rm as rm4, stat as stat14 } from "node:fs/promises";
|
|
71830
72046
|
import { appendFile } from "node:fs/promises";
|
|
71831
72047
|
import * as path18 from "node:path";
|
|
71832
72048
|
async function allInstances() {
|
|
@@ -72092,7 +72308,7 @@ Pulling workspace ` + remoteWorkspace.id);
|
|
|
72092
72308
|
if (confirmDelete) {
|
|
72093
72309
|
for (const workspace of localWorkspacesToDelete) {
|
|
72094
72310
|
await removeWorkspace(workspace.id, false, {});
|
|
72095
|
-
await
|
|
72311
|
+
await rm4(path18.join(rootDir, workspace.dir), {
|
|
72096
72312
|
recursive: true
|
|
72097
72313
|
});
|
|
72098
72314
|
}
|
|
@@ -74176,6 +74392,10 @@ async function bootstrap2(opts, flowPath) {
|
|
|
74176
74392
|
const metadataFile = getMetadataFileName("flow", "yaml");
|
|
74177
74393
|
const flowYamlPath = `${flowDirFullPath}/${metadataFile}`;
|
|
74178
74394
|
writeFileSync6(flowYamlPath, newFlowDefinitionYaml, { flag: "wx", encoding: "utf-8" });
|
|
74395
|
+
info(colors.green(`Created flow at ${flowDirFullPath}`));
|
|
74396
|
+
info("");
|
|
74397
|
+
info(colors.bold("To preview this flow:"));
|
|
74398
|
+
info(colors.gray(` wmill dev --path ${flowPath}`));
|
|
74179
74399
|
}
|
|
74180
74400
|
async function history2(opts, flowPath) {
|
|
74181
74401
|
if (opts.json)
|
|
@@ -75224,22 +75444,22 @@ var init_gitsync_settings = __esm(async () => {
|
|
|
75224
75444
|
async function uploadScripts(tree, workspace) {
|
|
75225
75445
|
const scriptHashes = {};
|
|
75226
75446
|
const workspaceDeps = [];
|
|
75227
|
-
for (const
|
|
75228
|
-
const content = tree.getContent(
|
|
75229
|
-
const itemType = tree.getItemType(
|
|
75447
|
+
for (const path21 of tree.allPaths()) {
|
|
75448
|
+
const content = tree.getContent(path21);
|
|
75449
|
+
const itemType = tree.getItemType(path21);
|
|
75230
75450
|
if (itemType === "dependencies") {
|
|
75231
75451
|
if (content === undefined)
|
|
75232
75452
|
continue;
|
|
75233
|
-
const info2 = workspaceDependenciesPathToLanguageAndFilename(
|
|
75453
|
+
const info2 = workspaceDependenciesPathToLanguageAndFilename(path21);
|
|
75234
75454
|
if (info2) {
|
|
75235
75455
|
const hash2 = await generateHash(content);
|
|
75236
|
-
workspaceDeps.push({ path:
|
|
75456
|
+
workspaceDeps.push({ path: path21, language: info2.language, name: info2.name, hash: hash2 });
|
|
75237
75457
|
}
|
|
75238
75458
|
} else if (itemType === "script") {
|
|
75239
75459
|
if (!content)
|
|
75240
75460
|
continue;
|
|
75241
75461
|
const hash2 = await generateHash(content);
|
|
75242
|
-
scriptHashes[
|
|
75462
|
+
scriptHashes[path21] = hash2;
|
|
75243
75463
|
}
|
|
75244
75464
|
}
|
|
75245
75465
|
if (Object.keys(scriptHashes).length === 0 && workspaceDeps.length === 0)
|
|
@@ -75251,19 +75471,19 @@ async function uploadScripts(tree, workspace) {
|
|
|
75251
75471
|
workspace_deps: workspaceDeps
|
|
75252
75472
|
}
|
|
75253
75473
|
});
|
|
75254
|
-
for (const
|
|
75255
|
-
const content = tree.getContent(
|
|
75256
|
-
const itemType = tree.getItemType(
|
|
75474
|
+
for (const path21 of mismatched) {
|
|
75475
|
+
const content = tree.getContent(path21);
|
|
75476
|
+
const itemType = tree.getItemType(path21);
|
|
75257
75477
|
if (itemType === "dependencies") {
|
|
75258
75478
|
if (content !== undefined) {
|
|
75259
|
-
tree.setContentHash(
|
|
75479
|
+
tree.setContentHash(path21, "mismatched");
|
|
75260
75480
|
}
|
|
75261
75481
|
} else if (content) {
|
|
75262
75482
|
const hash2 = await storeRawScriptTemp({
|
|
75263
75483
|
workspace: workspace.workspaceId,
|
|
75264
75484
|
requestBody: content
|
|
75265
75485
|
});
|
|
75266
|
-
tree.setContentHash(
|
|
75486
|
+
tree.setContentHash(path21, hash2);
|
|
75267
75487
|
}
|
|
75268
75488
|
}
|
|
75269
75489
|
}
|
|
@@ -75274,12 +75494,12 @@ class DoubleLinkedDependencyTree {
|
|
|
75274
75494
|
setWorkspaceDeps(deps) {
|
|
75275
75495
|
this.workspaceDeps = deps;
|
|
75276
75496
|
}
|
|
75277
|
-
async addNode(
|
|
75497
|
+
async addNode(path21, content, language, metadata, imports, itemType, folder, originalPath, isDirectlyStale, isRawApp) {
|
|
75278
75498
|
const hasWorkspaceDeps = itemType === "script" || itemType === "inline_script";
|
|
75279
75499
|
const filteredDeps = hasWorkspaceDeps ? filterWorkspaceDependencies(this.workspaceDeps, content, language) : {};
|
|
75280
75500
|
const stalenessHash = await generateScriptHash({}, content, metadata);
|
|
75281
|
-
if (!this.nodes.has(
|
|
75282
|
-
this.nodes.set(
|
|
75501
|
+
if (!this.nodes.has(path21)) {
|
|
75502
|
+
this.nodes.set(path21, {
|
|
75283
75503
|
content: "",
|
|
75284
75504
|
stalenessHash: "",
|
|
75285
75505
|
language: "deno",
|
|
@@ -75292,7 +75512,7 @@ class DoubleLinkedDependencyTree {
|
|
|
75292
75512
|
isDirectlyStale: false
|
|
75293
75513
|
});
|
|
75294
75514
|
}
|
|
75295
|
-
const node = this.nodes.get(
|
|
75515
|
+
const node = this.nodes.get(path21);
|
|
75296
75516
|
node.content = content;
|
|
75297
75517
|
node.stalenessHash = stalenessHash;
|
|
75298
75518
|
node.language = language;
|
|
@@ -75339,59 +75559,59 @@ class DoubleLinkedDependencyTree {
|
|
|
75339
75559
|
isDirectlyStale: false
|
|
75340
75560
|
});
|
|
75341
75561
|
}
|
|
75342
|
-
this.nodes.get(importPath).importedBy.add(
|
|
75562
|
+
this.nodes.get(importPath).importedBy.add(path21);
|
|
75343
75563
|
}
|
|
75344
75564
|
}
|
|
75345
|
-
getContent(
|
|
75346
|
-
return this.nodes.get(
|
|
75565
|
+
getContent(path21) {
|
|
75566
|
+
return this.nodes.get(path21)?.content;
|
|
75347
75567
|
}
|
|
75348
|
-
getStalenessHash(
|
|
75349
|
-
return this.nodes.get(
|
|
75568
|
+
getStalenessHash(path21) {
|
|
75569
|
+
return this.nodes.get(path21)?.stalenessHash;
|
|
75350
75570
|
}
|
|
75351
|
-
getContentHash(
|
|
75352
|
-
return this.nodes.get(
|
|
75571
|
+
getContentHash(path21) {
|
|
75572
|
+
return this.nodes.get(path21)?.contentHash;
|
|
75353
75573
|
}
|
|
75354
|
-
setContentHash(
|
|
75355
|
-
const node = this.nodes.get(
|
|
75574
|
+
setContentHash(path21, hash2) {
|
|
75575
|
+
const node = this.nodes.get(path21);
|
|
75356
75576
|
if (node) {
|
|
75357
75577
|
node.contentHash = hash2;
|
|
75358
75578
|
}
|
|
75359
75579
|
}
|
|
75360
|
-
getLanguage(
|
|
75361
|
-
return this.nodes.get(
|
|
75580
|
+
getLanguage(path21) {
|
|
75581
|
+
return this.nodes.get(path21)?.language;
|
|
75362
75582
|
}
|
|
75363
|
-
getMetadata(
|
|
75364
|
-
return this.nodes.get(
|
|
75583
|
+
getMetadata(path21) {
|
|
75584
|
+
return this.nodes.get(path21)?.metadata;
|
|
75365
75585
|
}
|
|
75366
|
-
getStaleReason(
|
|
75367
|
-
return this.nodes.get(
|
|
75586
|
+
getStaleReason(path21) {
|
|
75587
|
+
return this.nodes.get(path21)?.staleReason;
|
|
75368
75588
|
}
|
|
75369
|
-
getItemType(
|
|
75370
|
-
return this.nodes.get(
|
|
75589
|
+
getItemType(path21) {
|
|
75590
|
+
return this.nodes.get(path21)?.itemType;
|
|
75371
75591
|
}
|
|
75372
|
-
getFolder(
|
|
75373
|
-
return this.nodes.get(
|
|
75592
|
+
getFolder(path21) {
|
|
75593
|
+
return this.nodes.get(path21)?.folder;
|
|
75374
75594
|
}
|
|
75375
|
-
getIsRawApp(
|
|
75376
|
-
return this.nodes.get(
|
|
75595
|
+
getIsRawApp(path21) {
|
|
75596
|
+
return this.nodes.get(path21)?.isRawApp;
|
|
75377
75597
|
}
|
|
75378
|
-
getIsDirectlyStale(
|
|
75379
|
-
return this.nodes.get(
|
|
75598
|
+
getIsDirectlyStale(path21) {
|
|
75599
|
+
return this.nodes.get(path21)?.isDirectlyStale ?? false;
|
|
75380
75600
|
}
|
|
75381
|
-
getOriginalPath(
|
|
75382
|
-
return this.nodes.get(
|
|
75601
|
+
getOriginalPath(path21) {
|
|
75602
|
+
return this.nodes.get(path21)?.originalPath;
|
|
75383
75603
|
}
|
|
75384
|
-
getImports(
|
|
75385
|
-
return this.nodes.get(
|
|
75604
|
+
getImports(path21) {
|
|
75605
|
+
return this.nodes.get(path21)?.imports;
|
|
75386
75606
|
}
|
|
75387
|
-
isStale(
|
|
75388
|
-
return this.nodes.get(
|
|
75607
|
+
isStale(path21) {
|
|
75608
|
+
return this.nodes.get(path21)?.staleReason !== undefined;
|
|
75389
75609
|
}
|
|
75390
75610
|
propagateStaleness() {
|
|
75391
75611
|
const directlyStale = new Set;
|
|
75392
|
-
for (const [
|
|
75612
|
+
for (const [path21, node] of this.nodes.entries()) {
|
|
75393
75613
|
if (node.isDirectlyStale) {
|
|
75394
|
-
directlyStale.add(
|
|
75614
|
+
directlyStale.add(path21);
|
|
75395
75615
|
node.staleReason = "content changed";
|
|
75396
75616
|
}
|
|
75397
75617
|
}
|
|
@@ -75443,20 +75663,20 @@ class DoubleLinkedDependencyTree {
|
|
|
75443
75663
|
return this.nodes.keys();
|
|
75444
75664
|
}
|
|
75445
75665
|
*stalePaths() {
|
|
75446
|
-
for (const [
|
|
75666
|
+
for (const [path21, node] of this.nodes.entries()) {
|
|
75447
75667
|
if (node.staleReason) {
|
|
75448
|
-
yield
|
|
75668
|
+
yield path21;
|
|
75449
75669
|
}
|
|
75450
75670
|
}
|
|
75451
75671
|
}
|
|
75452
|
-
has(
|
|
75453
|
-
return this.nodes.has(
|
|
75672
|
+
has(path21) {
|
|
75673
|
+
return this.nodes.has(path21);
|
|
75454
75674
|
}
|
|
75455
75675
|
getMismatchedWorkspaceDeps() {
|
|
75456
75676
|
const result2 = {};
|
|
75457
|
-
for (const [
|
|
75677
|
+
for (const [path21, node] of this.nodes.entries()) {
|
|
75458
75678
|
if (node.itemType === "dependencies" && node.contentHash && node.content !== undefined) {
|
|
75459
|
-
result2[
|
|
75679
|
+
result2[path21] = node.content;
|
|
75460
75680
|
}
|
|
75461
75681
|
}
|
|
75462
75682
|
return result2;
|
|
@@ -75471,11 +75691,11 @@ class DoubleLinkedDependencyTree {
|
|
|
75471
75691
|
return result2;
|
|
75472
75692
|
}
|
|
75473
75693
|
async persistDepsHashes(depsPaths) {
|
|
75474
|
-
for (const
|
|
75475
|
-
const node = this.nodes.get(
|
|
75694
|
+
for (const path21 of depsPaths) {
|
|
75695
|
+
const node = this.nodes.get(path21);
|
|
75476
75696
|
if (node?.itemType === "dependencies" && node.content !== undefined) {
|
|
75477
|
-
const hash2 = await generateHash(node.content +
|
|
75478
|
-
await updateMetadataGlobalLock(
|
|
75697
|
+
const hash2 = await generateHash(node.content + path21);
|
|
75698
|
+
await updateMetadataGlobalLock(path21, hash2);
|
|
75479
75699
|
}
|
|
75480
75700
|
}
|
|
75481
75701
|
}
|
|
@@ -76867,9 +77087,11 @@ await init_lint();
|
|
|
76867
77087
|
init_mod3();
|
|
76868
77088
|
init_log();
|
|
76869
77089
|
init_wrapper();
|
|
76870
|
-
init_get_port();
|
|
76871
77090
|
init_open();
|
|
76872
77091
|
init_script_common();
|
|
77092
|
+
init_extractor();
|
|
77093
|
+
init_path_assigner();
|
|
77094
|
+
init_port_probe();
|
|
76873
77095
|
await __promiseAll([
|
|
76874
77096
|
init_yaml(),
|
|
76875
77097
|
init_utils(),
|
|
@@ -76884,13 +77106,223 @@ await __promiseAll([
|
|
|
76884
77106
|
init_codebase(),
|
|
76885
77107
|
init_local_path_scripts()
|
|
76886
77108
|
]);
|
|
77109
|
+
var import_yaml40 = __toESM(require_dist(), 1);
|
|
76887
77110
|
import { sep as SEP20 } from "node:path";
|
|
76888
77111
|
import * as http3 from "node:http";
|
|
76889
|
-
import
|
|
77112
|
+
import * as https from "node:https";
|
|
77113
|
+
import { access, readdir as readdir10, realpath, stat as stat17, unlink, writeFile as writeFile19 } from "node:fs/promises";
|
|
76890
77114
|
import { watch as watch2 } from "node:fs";
|
|
77115
|
+
import * as path20 from "node:path";
|
|
77116
|
+
import * as fs13 from "node:fs";
|
|
77117
|
+
|
|
77118
|
+
// src/commands/dev/pathscript-restore.ts
|
|
77119
|
+
var TAG_KEY = "_originalPathScript";
|
|
77120
|
+
function walkModules(modules, visitor) {
|
|
77121
|
+
for (const module of modules) {
|
|
77122
|
+
if (!module.value)
|
|
77123
|
+
continue;
|
|
77124
|
+
const val = module.value;
|
|
77125
|
+
if (val.type === "forloopflow" || val.type === "whileloopflow") {
|
|
77126
|
+
walkModules(val.modules, visitor);
|
|
77127
|
+
} else if (val.type === "branchall") {
|
|
77128
|
+
for (const branch of val.branches ?? []) {
|
|
77129
|
+
walkModules(branch.modules, visitor);
|
|
77130
|
+
}
|
|
77131
|
+
} else if (val.type === "branchone") {
|
|
77132
|
+
for (const branch of val.branches ?? []) {
|
|
77133
|
+
walkModules(branch.modules, visitor);
|
|
77134
|
+
}
|
|
77135
|
+
if (val.default) {
|
|
77136
|
+
walkModules(val.default, visitor);
|
|
77137
|
+
}
|
|
77138
|
+
} else if (val.type === "aiagent") {
|
|
77139
|
+
for (const tool of val.tools ?? []) {
|
|
77140
|
+
visitor.onTool(tool);
|
|
77141
|
+
}
|
|
77142
|
+
} else {
|
|
77143
|
+
visitor.onModule(module);
|
|
77144
|
+
}
|
|
77145
|
+
}
|
|
77146
|
+
}
|
|
77147
|
+
function walkFlow(flowValue, visitor) {
|
|
77148
|
+
if (flowValue?.modules)
|
|
77149
|
+
walkModules(flowValue.modules, visitor);
|
|
77150
|
+
if (flowValue?.failure_module)
|
|
77151
|
+
walkModules([flowValue.failure_module], visitor);
|
|
77152
|
+
if (flowValue?.preprocessor_module)
|
|
77153
|
+
walkModules([flowValue.preprocessor_module], visitor);
|
|
77154
|
+
}
|
|
77155
|
+
function snapshotPathScripts(flowValue) {
|
|
77156
|
+
walkFlow(flowValue, {
|
|
77157
|
+
onModule(module) {
|
|
77158
|
+
if (module.value.type === "script") {
|
|
77159
|
+
module[TAG_KEY] = JSON.parse(JSON.stringify(module.value));
|
|
77160
|
+
}
|
|
77161
|
+
},
|
|
77162
|
+
onTool(tool) {
|
|
77163
|
+
const tv = tool.value;
|
|
77164
|
+
if (tv && "tool_type" in tv && tv.tool_type === "flowmodule" && tv.type === "script") {
|
|
77165
|
+
tool[TAG_KEY] = JSON.parse(JSON.stringify(tv));
|
|
77166
|
+
}
|
|
77167
|
+
}
|
|
77168
|
+
});
|
|
77169
|
+
}
|
|
77170
|
+
function tagReplacedPathScripts(flowValue) {
|
|
77171
|
+
walkFlow(flowValue, {
|
|
77172
|
+
onModule(module) {
|
|
77173
|
+
if (module[TAG_KEY] && module.value.type === "rawscript") {
|
|
77174
|
+
module.value[TAG_KEY] = module[TAG_KEY];
|
|
77175
|
+
delete module[TAG_KEY];
|
|
77176
|
+
} else if (module[TAG_KEY]) {
|
|
77177
|
+
delete module[TAG_KEY];
|
|
77178
|
+
}
|
|
77179
|
+
},
|
|
77180
|
+
onTool(tool) {
|
|
77181
|
+
const tv = tool.value;
|
|
77182
|
+
if (tool[TAG_KEY] && tv && "tool_type" in tv && tv.tool_type === "flowmodule" && tv.type === "rawscript") {
|
|
77183
|
+
tv[TAG_KEY] = tool[TAG_KEY];
|
|
77184
|
+
delete tool[TAG_KEY];
|
|
77185
|
+
} else if (tool[TAG_KEY]) {
|
|
77186
|
+
delete tool[TAG_KEY];
|
|
77187
|
+
}
|
|
77188
|
+
}
|
|
77189
|
+
});
|
|
77190
|
+
}
|
|
77191
|
+
function restorePathScripts(flowValue) {
|
|
77192
|
+
walkFlow(flowValue, {
|
|
77193
|
+
onModule(module) {
|
|
77194
|
+
if (module.value[TAG_KEY]) {
|
|
77195
|
+
module.value = module.value[TAG_KEY];
|
|
77196
|
+
}
|
|
77197
|
+
},
|
|
77198
|
+
onTool(tool) {
|
|
77199
|
+
if (tool.value?.[TAG_KEY]) {
|
|
77200
|
+
tool.value = tool.value[TAG_KEY];
|
|
77201
|
+
}
|
|
77202
|
+
}
|
|
77203
|
+
});
|
|
77204
|
+
}
|
|
77205
|
+
|
|
77206
|
+
// src/commands/dev/dev.ts
|
|
76891
77207
|
var PORT = 3001;
|
|
77208
|
+
var FLOW_SUFFIXES = [".flow", "__flow"];
|
|
77209
|
+
var APP_SUFFIXES = [".app", "__app", ".raw_app", "__raw_app"];
|
|
77210
|
+
var INLINE_SCRIPT_EXTS = new Set([
|
|
77211
|
+
...exts.map((e) => path20.extname("x" + e)).filter((e) => e !== ".yml"),
|
|
77212
|
+
".js"
|
|
77213
|
+
]);
|
|
77214
|
+
function stripFolderSuffix(rel, suffixes) {
|
|
77215
|
+
for (const s of suffixes) {
|
|
77216
|
+
if (rel.endsWith(s))
|
|
77217
|
+
return rel.slice(0, -s.length);
|
|
77218
|
+
}
|
|
77219
|
+
return rel;
|
|
77220
|
+
}
|
|
77221
|
+
function isFlowFolderName(name) {
|
|
77222
|
+
return FLOW_SUFFIXES.some((s) => name.endsWith(s));
|
|
77223
|
+
}
|
|
77224
|
+
function normalizeWmPath(p) {
|
|
77225
|
+
return stripFolderSuffix(p.replace(/\/$/, ""), FLOW_SUFFIXES);
|
|
77226
|
+
}
|
|
77227
|
+
function isInsideFlowFolder(cpath) {
|
|
77228
|
+
return cpath.split("/").some(isFlowFolderName);
|
|
77229
|
+
}
|
|
77230
|
+
function findFlowFolderPrefix(cpath) {
|
|
77231
|
+
const segs = cpath.split("/");
|
|
77232
|
+
for (let i = 0;i < segs.length; i++) {
|
|
77233
|
+
if (isFlowFolderName(segs[i])) {
|
|
77234
|
+
return segs.slice(0, i + 1).join("/") + "/";
|
|
77235
|
+
}
|
|
77236
|
+
}
|
|
77237
|
+
return;
|
|
77238
|
+
}
|
|
77239
|
+
async function listWorkspacePaths() {
|
|
77240
|
+
const items = [];
|
|
77241
|
+
async function walk(dir, rel) {
|
|
77242
|
+
let entries;
|
|
77243
|
+
try {
|
|
77244
|
+
entries = await readdir10(dir, { withFileTypes: true });
|
|
77245
|
+
} catch {
|
|
77246
|
+
return;
|
|
77247
|
+
}
|
|
77248
|
+
for (const entry of entries) {
|
|
77249
|
+
if (entry.name.startsWith(".") || entry.name === "node_modules")
|
|
77250
|
+
continue;
|
|
77251
|
+
const childRel = rel ? `${rel}/${entry.name}` : entry.name;
|
|
77252
|
+
const childAbs = path20.join(dir, entry.name);
|
|
77253
|
+
if (entry.isDirectory()) {
|
|
77254
|
+
if (isFlowFolderName(entry.name)) {
|
|
77255
|
+
items.push({
|
|
77256
|
+
path: stripFolderSuffix(childRel, FLOW_SUFFIXES),
|
|
77257
|
+
kind: "flow",
|
|
77258
|
+
_metaPath: path20.join(childAbs, "flow.yaml")
|
|
77259
|
+
});
|
|
77260
|
+
continue;
|
|
77261
|
+
}
|
|
77262
|
+
if (APP_SUFFIXES.some((s) => entry.name.endsWith(s))) {
|
|
77263
|
+
items.push({ path: stripFolderSuffix(childRel, APP_SUFFIXES), kind: "raw_app" });
|
|
77264
|
+
continue;
|
|
77265
|
+
}
|
|
77266
|
+
await walk(childAbs, childRel);
|
|
77267
|
+
} else if (entry.isFile()) {
|
|
77268
|
+
const matchedExt = exts.find((ext2) => entry.name.endsWith(ext2));
|
|
77269
|
+
if (matchedExt) {
|
|
77270
|
+
const noExtAbs = childAbs.slice(0, -matchedExt.length);
|
|
77271
|
+
items.push({
|
|
77272
|
+
path: childRel.slice(0, -matchedExt.length),
|
|
77273
|
+
kind: "script",
|
|
77274
|
+
_metaPath: noExtAbs + ".script.yaml"
|
|
77275
|
+
});
|
|
77276
|
+
}
|
|
77277
|
+
}
|
|
77278
|
+
}
|
|
77279
|
+
}
|
|
77280
|
+
await walk(process.cwd(), "");
|
|
77281
|
+
await Promise.all(items.map(async (item) => {
|
|
77282
|
+
if (!item._metaPath)
|
|
77283
|
+
return;
|
|
77284
|
+
try {
|
|
77285
|
+
const meta = await yamlParseFile(item._metaPath);
|
|
77286
|
+
if (typeof meta?.summary === "string" && meta.summary.length > 0) {
|
|
77287
|
+
item.summary = meta.summary;
|
|
77288
|
+
}
|
|
77289
|
+
} catch {}
|
|
77290
|
+
}));
|
|
77291
|
+
items.sort((a, b) => a.path.localeCompare(b.path));
|
|
77292
|
+
return items.map(({ _metaPath, ...item }) => item);
|
|
77293
|
+
}
|
|
76892
77294
|
async function dev2(opts) {
|
|
77295
|
+
if (!opts.path) {
|
|
77296
|
+
const cwd = process.cwd();
|
|
77297
|
+
const cwdBasename = path20.basename(cwd);
|
|
77298
|
+
await loadNonDottedPathsSetting();
|
|
77299
|
+
if (isFlowFolderName(cwdBasename)) {
|
|
77300
|
+
GLOBAL_CONFIG_OPT.noCdToRoot = true;
|
|
77301
|
+
let searchDir = cwd;
|
|
77302
|
+
let workspaceRoot;
|
|
77303
|
+
while (true) {
|
|
77304
|
+
const wmillYaml = path20.join(searchDir, "wmill.yaml");
|
|
77305
|
+
if (fs13.existsSync(wmillYaml)) {
|
|
77306
|
+
workspaceRoot = searchDir;
|
|
77307
|
+
break;
|
|
77308
|
+
}
|
|
77309
|
+
const parentDir = path20.dirname(searchDir);
|
|
77310
|
+
if (parentDir === searchDir)
|
|
77311
|
+
break;
|
|
77312
|
+
searchDir = parentDir;
|
|
77313
|
+
}
|
|
77314
|
+
if (workspaceRoot) {
|
|
77315
|
+
const relPath = path20.relative(workspaceRoot, cwd).replaceAll("\\", "/");
|
|
77316
|
+
opts.path = stripFolderSuffix(relPath, FLOW_SUFFIXES);
|
|
77317
|
+
info(`Detected flow folder, path: ${opts.path}`);
|
|
77318
|
+
process.chdir(workspaceRoot);
|
|
77319
|
+
}
|
|
77320
|
+
}
|
|
77321
|
+
}
|
|
76893
77322
|
opts = await mergeConfigWithConfigFile(opts);
|
|
77323
|
+
if (opts.path) {
|
|
77324
|
+
opts.path = normalizeWmPath(opts.path);
|
|
77325
|
+
}
|
|
76894
77326
|
const workspace = await resolveWorkspace(opts);
|
|
76895
77327
|
await requireLogin(opts);
|
|
76896
77328
|
info("Started dev mode");
|
|
@@ -76922,39 +77354,50 @@ async function dev2(opts) {
|
|
|
76922
77354
|
});
|
|
76923
77355
|
});
|
|
76924
77356
|
}
|
|
76925
|
-
const flowFolderSuffix = getFolderSuffixWithSep("flow");
|
|
76926
77357
|
const flowMetadataFile = getMetadataFileName("flow", "yaml");
|
|
76927
77358
|
async function loadPaths(pathsToLoad) {
|
|
76928
|
-
const paths = pathsToLoad.filter((
|
|
77359
|
+
const paths = pathsToLoad.filter((p) => exts.some((ext2) => p.endsWith(ext2) || p.endsWith(".flow/" + flowMetadataFile) || p.endsWith("__flow/" + flowMetadataFile)));
|
|
76929
77360
|
if (paths.length == 0) {
|
|
76930
77361
|
return;
|
|
76931
77362
|
}
|
|
76932
77363
|
const nativePath = (await realpath(paths[0])).replace(base + SEP20, "");
|
|
76933
77364
|
const cpath = nativePath.replaceAll("\\", "/");
|
|
76934
|
-
|
|
76935
|
-
|
|
77365
|
+
const insideFlow = isInsideFlowFolder(cpath);
|
|
77366
|
+
if (insideFlow || !ignore(nativePath, false)) {
|
|
77367
|
+
let typ;
|
|
77368
|
+
if (insideFlow) {
|
|
77369
|
+
typ = "flow";
|
|
77370
|
+
} else {
|
|
77371
|
+
typ = getTypeStrFromPath(cpath);
|
|
77372
|
+
}
|
|
76936
77373
|
info("Detected change in " + cpath + " (" + typ + ")");
|
|
76937
77374
|
if (typ == "flow") {
|
|
76938
|
-
|
|
77375
|
+
let localPath = extractFolderPath(cpath, "flow") ?? findFlowFolderPrefix(cpath);
|
|
77376
|
+
if (!localPath)
|
|
77377
|
+
return;
|
|
77378
|
+
const wmFlowPath = stripFolderSuffix(localPath.replace(/\/$/, ""), FLOW_SUFFIXES);
|
|
76939
77379
|
const localFlow = await yamlParseFile(localPath + "flow.yaml");
|
|
76940
|
-
await replaceInlineScripts(localFlow.value.modules, async (
|
|
77380
|
+
await replaceInlineScripts(localFlow.value.modules, async (path21) => await readTextFile(localPath + path21), exports_log, localPath, SEP20, undefined);
|
|
77381
|
+
snapshotPathScripts(localFlow.value);
|
|
76941
77382
|
const localScriptReader = createPreviewLocalScriptReader({
|
|
76942
77383
|
exts,
|
|
76943
77384
|
defaultTs: opts.defaultTs,
|
|
76944
77385
|
codebases
|
|
76945
77386
|
});
|
|
76946
77387
|
await replaceAllPathScriptsWithLocal(localFlow.value, localScriptReader, exports_log);
|
|
77388
|
+
tagReplacedPathScripts(localFlow.value);
|
|
76947
77389
|
currentLastEdit = {
|
|
76948
77390
|
type: "flow",
|
|
76949
77391
|
flow: localFlow,
|
|
76950
|
-
uriPath: localPath
|
|
77392
|
+
uriPath: localPath,
|
|
77393
|
+
path: wmFlowPath
|
|
76951
77394
|
};
|
|
76952
|
-
info("Updated " +
|
|
77395
|
+
info("Updated " + wmFlowPath);
|
|
76953
77396
|
broadcastChanges(currentLastEdit);
|
|
76954
77397
|
} else if (typ == "script") {
|
|
76955
|
-
const content = await readTextFile(cpath);
|
|
76956
77398
|
const splitted = cpath.split(".");
|
|
76957
77399
|
const wmPath = splitted[0];
|
|
77400
|
+
const content = await readTextFile(cpath);
|
|
76958
77401
|
const lang = inferContentTypeFromFilePath(cpath, opts.defaultTs);
|
|
76959
77402
|
const typed = (await parseMetadataFile(removeExtensionToPath(cpath), undefined))?.payload;
|
|
76960
77403
|
currentLastEdit = {
|
|
@@ -76970,29 +77413,164 @@ async function dev2(opts) {
|
|
|
76970
77413
|
}
|
|
76971
77414
|
}
|
|
76972
77415
|
}
|
|
77416
|
+
async function loadWmPath(wmPath) {
|
|
77417
|
+
wmPath = normalizeWmPath(wmPath);
|
|
77418
|
+
let flowDir;
|
|
77419
|
+
let flowYaml;
|
|
77420
|
+
for (const suffix of [".flow", "__flow"]) {
|
|
77421
|
+
const candidate = wmPath + suffix + "/";
|
|
77422
|
+
try {
|
|
77423
|
+
await access(candidate + "flow.yaml");
|
|
77424
|
+
flowDir = candidate;
|
|
77425
|
+
flowYaml = candidate + "flow.yaml";
|
|
77426
|
+
break;
|
|
77427
|
+
} catch {}
|
|
77428
|
+
}
|
|
77429
|
+
try {
|
|
77430
|
+
if (!flowDir || !flowYaml)
|
|
77431
|
+
throw new Error("not a flow");
|
|
77432
|
+
const localFlow = await yamlParseFile(flowYaml);
|
|
77433
|
+
await replaceInlineScripts(localFlow.value.modules, async (p) => await readTextFile(flowDir + p), exports_log, flowDir, SEP20, undefined);
|
|
77434
|
+
snapshotPathScripts(localFlow.value);
|
|
77435
|
+
const localScriptReader = createPreviewLocalScriptReader({
|
|
77436
|
+
exts,
|
|
77437
|
+
defaultTs: opts.defaultTs,
|
|
77438
|
+
codebases
|
|
77439
|
+
});
|
|
77440
|
+
await replaceAllPathScriptsWithLocal(localFlow.value, localScriptReader, exports_log);
|
|
77441
|
+
tagReplacedPathScripts(localFlow.value);
|
|
77442
|
+
const edit = {
|
|
77443
|
+
type: "flow",
|
|
77444
|
+
flow: localFlow,
|
|
77445
|
+
uriPath: flowDir,
|
|
77446
|
+
path: wmPath
|
|
77447
|
+
};
|
|
77448
|
+
currentLastEdit = edit;
|
|
77449
|
+
return edit;
|
|
77450
|
+
} catch {}
|
|
77451
|
+
for (const ext2 of exts) {
|
|
77452
|
+
const filePath = wmPath + ext2;
|
|
77453
|
+
try {
|
|
77454
|
+
await access(filePath);
|
|
77455
|
+
const content = await readTextFile(filePath);
|
|
77456
|
+
const lang = inferContentTypeFromFilePath(filePath, opts.defaultTs);
|
|
77457
|
+
const typed = (await parseMetadataFile(removeExtensionToPath(filePath), undefined))?.payload;
|
|
77458
|
+
const edit = {
|
|
77459
|
+
type: "script",
|
|
77460
|
+
content,
|
|
77461
|
+
path: wmPath,
|
|
77462
|
+
language: lang,
|
|
77463
|
+
tag: typed?.tag,
|
|
77464
|
+
lock: typed?.lock
|
|
77465
|
+
};
|
|
77466
|
+
currentLastEdit = edit;
|
|
77467
|
+
return edit;
|
|
77468
|
+
} catch {
|
|
77469
|
+
continue;
|
|
77470
|
+
}
|
|
77471
|
+
}
|
|
77472
|
+
error(`Could not find file for path: ${wmPath}`);
|
|
77473
|
+
return;
|
|
77474
|
+
}
|
|
77475
|
+
async function handleFlowRoundTrip(data3) {
|
|
77476
|
+
if (!data3.uriPath || !data3.flow?.value)
|
|
77477
|
+
return;
|
|
77478
|
+
let flowDir = data3.uriPath;
|
|
77479
|
+
if (!flowDir.endsWith("/"))
|
|
77480
|
+
flowDir += "/";
|
|
77481
|
+
if (flowDir.includes("://")) {
|
|
77482
|
+
flowDir = new URL(flowDir).pathname;
|
|
77483
|
+
}
|
|
77484
|
+
restorePathScripts(data3.flow.value);
|
|
77485
|
+
const flowYamlPath = flowDir + "flow.yaml";
|
|
77486
|
+
let currentLoadedFlow;
|
|
77487
|
+
let currentLoadedFailureModule;
|
|
77488
|
+
let currentLoadedPreprocessorModule;
|
|
77489
|
+
try {
|
|
77490
|
+
const currentFlow = await yamlParseFile(flowYamlPath);
|
|
77491
|
+
currentLoadedFlow = currentFlow.value?.modules;
|
|
77492
|
+
currentLoadedFailureModule = currentFlow.value?.failure_module;
|
|
77493
|
+
currentLoadedPreprocessorModule = currentFlow.value?.preprocessor_module;
|
|
77494
|
+
} catch {}
|
|
77495
|
+
const inlineScriptMapping = {};
|
|
77496
|
+
extractCurrentMapping(currentLoadedFlow, inlineScriptMapping, currentLoadedFailureModule, currentLoadedPreprocessorModule);
|
|
77497
|
+
const extractOptions = { skipInlineScriptSuffix: getNonDottedPaths() };
|
|
77498
|
+
const pathAssigner = newPathAssigner(opts.defaultTs ?? "bun", extractOptions);
|
|
77499
|
+
const allExtracted = extractInlineScripts(data3.flow.value.modules ?? [], inlineScriptMapping, "/", opts.defaultTs ?? "bun", pathAssigner, extractOptions);
|
|
77500
|
+
if (data3.flow.value.failure_module?.value?.type === "rawscript") {
|
|
77501
|
+
allExtracted.push(...extractInlineScripts([data3.flow.value.failure_module], inlineScriptMapping, "/", opts.defaultTs ?? "bun", pathAssigner, extractOptions));
|
|
77502
|
+
}
|
|
77503
|
+
if (data3.flow.value.preprocessor_module?.value?.type === "rawscript") {
|
|
77504
|
+
allExtracted.push(...extractInlineScripts([data3.flow.value.preprocessor_module], inlineScriptMapping, "/", opts.defaultTs ?? "bun", pathAssigner, extractOptions));
|
|
77505
|
+
}
|
|
77506
|
+
for (const s of allExtracted) {
|
|
77507
|
+
const filePath = flowDir + s.path;
|
|
77508
|
+
if (s.content.startsWith("!inline ")) {
|
|
77509
|
+
try {
|
|
77510
|
+
await stat17(filePath);
|
|
77511
|
+
} catch {
|
|
77512
|
+
await writeFile19(filePath, "", "utf-8");
|
|
77513
|
+
}
|
|
77514
|
+
continue;
|
|
77515
|
+
}
|
|
77516
|
+
let needsWrite = true;
|
|
77517
|
+
try {
|
|
77518
|
+
const existing = await readTextFile(filePath);
|
|
77519
|
+
if (existing === s.content)
|
|
77520
|
+
needsWrite = false;
|
|
77521
|
+
} catch {}
|
|
77522
|
+
if (needsWrite) {
|
|
77523
|
+
await writeFile19(filePath, s.content, "utf-8");
|
|
77524
|
+
info(`Wrote inline script: ${filePath}`);
|
|
77525
|
+
}
|
|
77526
|
+
}
|
|
77527
|
+
const flowYaml = import_yaml40.stringify(data3.flow);
|
|
77528
|
+
let currentYaml;
|
|
77529
|
+
try {
|
|
77530
|
+
currentYaml = await readTextFile(flowYamlPath);
|
|
77531
|
+
} catch {}
|
|
77532
|
+
if (currentYaml?.trimEnd() !== flowYaml.trimEnd()) {
|
|
77533
|
+
await writeFile19(flowYamlPath, flowYaml, "utf-8");
|
|
77534
|
+
info(`Wrote flow: ${flowYamlPath}`);
|
|
77535
|
+
}
|
|
77536
|
+
const extractedPaths = new Set(allExtracted.map((s) => s.path));
|
|
77537
|
+
try {
|
|
77538
|
+
const dirFiles = await readdir10(flowDir);
|
|
77539
|
+
for (const file of dirFiles) {
|
|
77540
|
+
if (file === "flow.yaml" || file === "flow.json" || file.startsWith("."))
|
|
77541
|
+
continue;
|
|
77542
|
+
if (!INLINE_SCRIPT_EXTS.has(path20.extname(file)))
|
|
77543
|
+
continue;
|
|
77544
|
+
if (!extractedPaths.has(file)) {
|
|
77545
|
+
await unlink(flowDir + file);
|
|
77546
|
+
info(`Removed orphaned file: ${flowDir + file}`);
|
|
77547
|
+
}
|
|
77548
|
+
}
|
|
77549
|
+
} catch {}
|
|
77550
|
+
}
|
|
76973
77551
|
const connectedClients = new Set;
|
|
76974
77552
|
function broadcastChanges(lastEdit) {
|
|
77553
|
+
if (opts.path && normalizeWmPath(lastEdit.path) !== opts.path) {
|
|
77554
|
+
return;
|
|
77555
|
+
}
|
|
76975
77556
|
for (const client of connectedClients.values()) {
|
|
76976
77557
|
client.send(JSON.stringify(lastEdit));
|
|
76977
77558
|
}
|
|
76978
77559
|
}
|
|
76979
|
-
|
|
76980
|
-
const server = http3.createServer((_req, res) => {
|
|
76981
|
-
res.writeHead(200);
|
|
76982
|
-
res.end();
|
|
76983
|
-
});
|
|
76984
|
-
const wss = new import_websocket_server.default({ server });
|
|
77560
|
+
function setupDevWs(wss) {
|
|
76985
77561
|
wss.on("connection", (ws) => {
|
|
76986
77562
|
connectedClients.add(ws);
|
|
76987
|
-
console.log("New client connected");
|
|
76988
|
-
ws.
|
|
76989
|
-
|
|
76990
|
-
|
|
77563
|
+
console.log("New dev client connected");
|
|
77564
|
+
if (currentLastEdit && ws.readyState === import_websocket.default.OPEN) {
|
|
77565
|
+
try {
|
|
77566
|
+
ws.send(JSON.stringify(currentLastEdit));
|
|
77567
|
+
} catch (e) {
|
|
77568
|
+
console.error("Failed to push initial state to new client:", e);
|
|
76991
77569
|
}
|
|
76992
|
-
}
|
|
77570
|
+
}
|
|
76993
77571
|
ws.on("close", () => {
|
|
76994
77572
|
connectedClients.delete(ws);
|
|
76995
|
-
console.log("
|
|
77573
|
+
console.log("Dev client disconnected");
|
|
76996
77574
|
});
|
|
76997
77575
|
ws.on("message", (message) => {
|
|
76998
77576
|
let data3;
|
|
@@ -77004,29 +77582,184 @@ async function dev2(opts) {
|
|
|
77004
77582
|
}
|
|
77005
77583
|
if (data3.type === "load") {
|
|
77006
77584
|
loadPaths([data3.path]);
|
|
77585
|
+
} else if (data3.type === "flow") {
|
|
77586
|
+
handleFlowRoundTrip(data3).catch((err) => {
|
|
77587
|
+
error(`Failed to write flow changes: ${err}`);
|
|
77588
|
+
});
|
|
77589
|
+
} else if (data3.type === "loadWmPath") {
|
|
77590
|
+
loadWmPath(data3.path).then((edit) => {
|
|
77591
|
+
if (edit && ws.readyState === import_websocket.default.OPEN) {
|
|
77592
|
+
ws.send(JSON.stringify(edit));
|
|
77593
|
+
}
|
|
77594
|
+
}).catch((err) => {
|
|
77595
|
+
error(`Failed to load path ${data3.path}: ${err}`);
|
|
77596
|
+
});
|
|
77597
|
+
} else if (data3.type === "listPaths") {
|
|
77598
|
+
listWorkspacePaths().then((items) => {
|
|
77599
|
+
if (ws.readyState === import_websocket.default.OPEN) {
|
|
77600
|
+
ws.send(JSON.stringify({ type: "paths", items }));
|
|
77601
|
+
}
|
|
77602
|
+
}).catch((err) => {
|
|
77603
|
+
error(`Failed to list paths: ${err}`);
|
|
77604
|
+
});
|
|
77007
77605
|
}
|
|
77008
77606
|
});
|
|
77009
77607
|
});
|
|
77010
|
-
|
|
77011
|
-
|
|
77012
|
-
|
|
77608
|
+
}
|
|
77609
|
+
function maybeOpenBrowser(url) {
|
|
77610
|
+
if (opts.open === false)
|
|
77611
|
+
return;
|
|
77013
77612
|
try {
|
|
77014
|
-
|
|
77613
|
+
open_default(url).catch((error2) => {
|
|
77015
77614
|
console.error(`Failed to open browser, please navigate to ${url}, error: ${error2}`);
|
|
77016
77615
|
});
|
|
77017
|
-
console.log(
|
|
77616
|
+
console.log(`Opened browser at ${url}`);
|
|
77018
77617
|
} catch (error2) {
|
|
77019
77618
|
console.error(`Failed to open browser, please navigate to ${url}, ${error2}`);
|
|
77020
77619
|
}
|
|
77021
|
-
|
|
77022
|
-
|
|
77023
|
-
|
|
77620
|
+
}
|
|
77621
|
+
async function startProxyServer(requestedPort) {
|
|
77622
|
+
const proxyPort = await resolveBindPort(requestedPort, "--proxy-port", {
|
|
77623
|
+
info: (m) => console.log(m),
|
|
77624
|
+
warn: (m) => console.warn(m)
|
|
77625
|
+
});
|
|
77626
|
+
const remote = new URL(workspace.remote);
|
|
77627
|
+
const isHttps = remote.protocol === "https:";
|
|
77628
|
+
const remoteHost = remote.hostname;
|
|
77629
|
+
const remotePort = remote.port ? parseInt(remote.port) : isHttps ? 443 : 80;
|
|
77630
|
+
const httpModule = isHttps ? https : http3;
|
|
77631
|
+
const devWss = new import_websocket_server.default({ noServer: true });
|
|
77632
|
+
setupDevWs(devWss);
|
|
77633
|
+
const proxyWss = new import_websocket_server.default({ noServer: true });
|
|
77634
|
+
const proxyServer = http3.createServer((clientReq, clientRes) => {
|
|
77635
|
+
const parsedUrl = new URL(clientReq.url ?? "/", `http://localhost`);
|
|
77636
|
+
if (parsedUrl.pathname === "/" || parsedUrl.pathname === "") {
|
|
77637
|
+
let devUrl = `/dev?workspace=${workspace.workspaceId}&local=true&wm_token=${workspace.token}&port=${proxyPort}`;
|
|
77638
|
+
if (opts.path) {
|
|
77639
|
+
devUrl += `&path=${opts.path}`;
|
|
77640
|
+
}
|
|
77641
|
+
clientRes.writeHead(302, { Location: devUrl });
|
|
77642
|
+
clientRes.end();
|
|
77643
|
+
return;
|
|
77644
|
+
}
|
|
77645
|
+
const fwdHeaders = {
|
|
77646
|
+
...clientReq.headers,
|
|
77647
|
+
host: remote.host
|
|
77648
|
+
};
|
|
77649
|
+
delete fwdHeaders["connection"];
|
|
77650
|
+
delete fwdHeaders["keep-alive"];
|
|
77651
|
+
delete fwdHeaders["transfer-encoding"];
|
|
77652
|
+
delete fwdHeaders["accept-encoding"];
|
|
77653
|
+
const proxyOpts = {
|
|
77654
|
+
hostname: remoteHost,
|
|
77655
|
+
port: remotePort,
|
|
77656
|
+
path: clientReq.url,
|
|
77657
|
+
method: clientReq.method,
|
|
77658
|
+
headers: fwdHeaders
|
|
77659
|
+
};
|
|
77660
|
+
const proxyReq = httpModule.request(proxyOpts, (proxyRes) => {
|
|
77661
|
+
const setCookie = proxyRes.headers["set-cookie"];
|
|
77662
|
+
if (setCookie) {
|
|
77663
|
+
proxyRes.headers["set-cookie"] = setCookie.map((cookie) => cookie.replace(/domain=[^;]+/gi, "domain=localhost"));
|
|
77664
|
+
}
|
|
77665
|
+
clientRes.writeHead(proxyRes.statusCode ?? 502, proxyRes.headers);
|
|
77666
|
+
proxyRes.pipe(clientRes, { end: true });
|
|
77667
|
+
});
|
|
77668
|
+
proxyReq.on("error", (err) => {
|
|
77669
|
+
console.error("Proxy error:", err.message);
|
|
77670
|
+
clientRes.writeHead(502);
|
|
77671
|
+
clientRes.end("Bad Gateway");
|
|
77672
|
+
});
|
|
77673
|
+
clientReq.pipe(proxyReq, { end: true });
|
|
77674
|
+
});
|
|
77675
|
+
proxyServer.on("upgrade", (req, socket, head) => {
|
|
77676
|
+
const pathname = req.url?.split("?")[0] ?? "";
|
|
77677
|
+
if (pathname === "/ws_dev" || pathname === "/ws") {
|
|
77678
|
+
devWss.handleUpgrade(req, socket, head, (ws) => {
|
|
77679
|
+
devWss.emit("connection", ws, req);
|
|
77680
|
+
});
|
|
77681
|
+
return;
|
|
77682
|
+
}
|
|
77683
|
+
if (pathname.startsWith("/ws/") || pathname.startsWith("/ws_mp/") || pathname.startsWith("/ws_debug/")) {
|
|
77684
|
+
const wsProtocol = isHttps ? "wss" : "ws";
|
|
77685
|
+
const remoteWsUrl = `${wsProtocol}://${remote.host}${req.url}`;
|
|
77686
|
+
const remoteWs = new import_websocket.default(remoteWsUrl, {
|
|
77687
|
+
headers: {
|
|
77688
|
+
...req.headers,
|
|
77689
|
+
host: remote.host
|
|
77690
|
+
}
|
|
77691
|
+
});
|
|
77692
|
+
remoteWs.on("open", () => {
|
|
77693
|
+
proxyWss.handleUpgrade(req, socket, head, (clientWs) => {
|
|
77694
|
+
clientWs.on("message", (data3) => {
|
|
77695
|
+
if (remoteWs.readyState === import_websocket.default.OPEN) {
|
|
77696
|
+
remoteWs.send(data3);
|
|
77697
|
+
}
|
|
77698
|
+
});
|
|
77699
|
+
remoteWs.on("message", (data3) => {
|
|
77700
|
+
if (clientWs.readyState === import_websocket.default.OPEN) {
|
|
77701
|
+
clientWs.send(data3);
|
|
77702
|
+
}
|
|
77703
|
+
});
|
|
77704
|
+
clientWs.on("close", () => remoteWs.close());
|
|
77705
|
+
remoteWs.on("close", () => clientWs.close());
|
|
77706
|
+
});
|
|
77707
|
+
});
|
|
77708
|
+
remoteWs.on("error", (err) => {
|
|
77709
|
+
console.error("WebSocket proxy error:", err.message);
|
|
77710
|
+
socket.destroy();
|
|
77711
|
+
});
|
|
77712
|
+
return;
|
|
77713
|
+
}
|
|
77714
|
+
socket.destroy();
|
|
77715
|
+
});
|
|
77716
|
+
return new Promise((resolve8) => {
|
|
77717
|
+
proxyServer.listen(proxyPort, BIND_HOST, () => {
|
|
77718
|
+
console.log(`Dev proxy listening on http://localhost:${proxyPort}`);
|
|
77719
|
+
if (opts.path) {
|
|
77720
|
+
console.log(`Watching ${opts.path} — edits will live-reload in the dev page`);
|
|
77721
|
+
} else {
|
|
77722
|
+
console.log("Open the dev page and pick a flow or script to preview — edits will live-reload");
|
|
77723
|
+
console.log("(pass --path <path> to skip the picker)");
|
|
77724
|
+
}
|
|
77725
|
+
maybeOpenBrowser(`http://localhost:${proxyPort}/`);
|
|
77726
|
+
resolve8();
|
|
77727
|
+
});
|
|
77728
|
+
});
|
|
77729
|
+
}
|
|
77730
|
+
async function startDirectServer() {
|
|
77731
|
+
const server = http3.createServer((_req, res) => {
|
|
77732
|
+
res.writeHead(200);
|
|
77733
|
+
res.end();
|
|
77734
|
+
});
|
|
77735
|
+
const wss = new import_websocket_server.default({ server });
|
|
77736
|
+
setupDevWs(wss);
|
|
77737
|
+
const port = await resolveBindPort(PORT, "wmill dev", {
|
|
77738
|
+
info: (m) => console.log(m),
|
|
77739
|
+
warn: (m) => console.warn(m)
|
|
77740
|
+
});
|
|
77741
|
+
const url = `${workspace.remote}dev?workspace=${workspace.workspaceId}&local=true&wm_token=${workspace.token}` + (port === PORT ? "" : `&port=${port}`) + (opts.path ? `&path=${opts.path}` : "");
|
|
77742
|
+
if (opts.open === false) {
|
|
77743
|
+
console.log(`Go to ${url}`);
|
|
77744
|
+
}
|
|
77745
|
+
maybeOpenBrowser(url);
|
|
77746
|
+
if (opts.path) {
|
|
77747
|
+
console.log(`Watching ${opts.path} — edits will live-reload in the dev page`);
|
|
77748
|
+
} else {
|
|
77749
|
+
console.log("Open the dev page and pick a flow or script to preview — edits will live-reload");
|
|
77750
|
+
}
|
|
77751
|
+
server.listen(port, BIND_HOST, () => {
|
|
77752
|
+
console.log(`Dev WebSocket listening on ws://localhost:${port}/ws`);
|
|
77024
77753
|
});
|
|
77025
77754
|
}
|
|
77026
|
-
|
|
77755
|
+
if (opts.path) {
|
|
77756
|
+
await loadWmPath(opts.path);
|
|
77757
|
+
}
|
|
77758
|
+
const startServer = opts.proxyPort ? () => startProxyServer(opts.proxyPort) : () => startDirectServer();
|
|
77759
|
+
await Promise.all([startServer(), watchChanges()]);
|
|
77027
77760
|
console.log("Stopped dev mode");
|
|
77028
77761
|
}
|
|
77029
|
-
var command24 = new Command().description("
|
|
77762
|
+
var command24 = new Command().description("Watch local file changes and live-reload the dev page for preview. Does NOT deploy to the remote workspace — use wmill sync push for that.").option("--includes <pattern...:string>", "Filter paths given a glob pattern or path").option("--proxy-port <port:number>", "Port for a localhost reverse proxy to the remote Windmill server").option("--path <path:string>", "Watch a specific windmill path (e.g., u/admin/my_script or f/my_flow)").option("--no-open", "Do not open the browser automatically").action(dev2);
|
|
77030
77763
|
var dev_default2 = command24;
|
|
77031
77764
|
|
|
77032
77765
|
// src/main.ts
|
|
@@ -77268,12 +78001,12 @@ await __promiseAll([
|
|
|
77268
78001
|
init_workspace(),
|
|
77269
78002
|
init_resource_type()
|
|
77270
78003
|
]);
|
|
77271
|
-
import { stat as
|
|
78004
|
+
import { stat as stat19, writeFile as writeFile21, rm as rm5 } from "node:fs/promises";
|
|
77272
78005
|
|
|
77273
78006
|
// src/guidance/writer.ts
|
|
77274
78007
|
await init_utils();
|
|
77275
|
-
import { cp, mkdir as mkdir13, readdir as
|
|
77276
|
-
import { join as
|
|
78008
|
+
import { cp, mkdir as mkdir13, readdir as readdir11, stat as stat18, writeFile as writeFile20 } from "node:fs/promises";
|
|
78009
|
+
import { join as join18 } from "node:path";
|
|
77277
78010
|
|
|
77278
78011
|
// src/guidance/core.ts
|
|
77279
78012
|
function generateAgentsMdContent(skillsReference) {
|
|
@@ -77293,11 +78026,12 @@ You MUST use the \`write-script-<language>\` skill to write or modify scripts in
|
|
|
77293
78026
|
## Flow Writing Guide
|
|
77294
78027
|
|
|
77295
78028
|
You MUST use the \`write-flow\` skill to create or modify flows.
|
|
78029
|
+
When a new flow needs to be created, YOU run \`wmill flow new <path>\` yourself (with \`--summary\` and optional \`--description\`) to scaffold the folder and \`flow.yaml\`, then edit \`flow.yaml\` to fill in modules and schema. Do NOT scaffold the folder + yaml by hand and do NOT tell the user to run \`wmill flow new\`. If path or summary are missing from the user's request, ask via \`AskUserQuestion\` (one call, all missing fields) — never invent them. See the \`write-flow\` skill for the procedure.
|
|
77296
78030
|
|
|
77297
78031
|
## Raw App Development
|
|
77298
78032
|
|
|
77299
78033
|
You MUST use the \`raw-app\` skill to create or modify raw apps.
|
|
77300
|
-
|
|
78034
|
+
When a new app needs to be created, YOU run \`wmill app new\` yourself with \`--summary\`, \`--path\`, and \`--framework\` flags (and any other relevant flags). Do NOT ask the user to run it. If you don't have the values for those flags, ask the user via \`AskUserQuestion\` (one call, all missing fields) — never invent them. See the \`raw-app\` skill for the full procedure.
|
|
77301
78035
|
|
|
77302
78036
|
## Triggers
|
|
77303
78037
|
|
|
@@ -77311,6 +78045,10 @@ You MUST use the \`schedules\` skill to configure cron schedules.
|
|
|
77311
78045
|
|
|
77312
78046
|
You MUST use the \`resources\` skill to manage resource types and credentials.
|
|
77313
78047
|
|
|
78048
|
+
## Visual Preview
|
|
78049
|
+
|
|
78050
|
+
You MUST use the \`preview\` skill any time the user wants to see/open/visualize/preview a flow, script, or app in the dev page — and after writing one, when offering visual verification. The skill picks between an MCP-embedded proxy (one named \`launch.json\` entry per target) and direct mode (URL handed to the user) based on what tools you have.
|
|
78051
|
+
|
|
77314
78052
|
## CLI Reference
|
|
77315
78053
|
|
|
77316
78054
|
You MUST use the \`cli-commands\` skill to use the CLI.
|
|
@@ -77363,7 +78101,8 @@ var SKILLS = [
|
|
|
77363
78101
|
{ name: "triggers", description: "MUST use when configuring triggers." },
|
|
77364
78102
|
{ name: "schedules", description: "MUST use when configuring schedules." },
|
|
77365
78103
|
{ name: "resources", description: "MUST use when managing resources." },
|
|
77366
|
-
{ name: "cli-commands", description: "MUST use when using the CLI, including debugging job failures and inspecting run history via `wmill job`." }
|
|
78104
|
+
{ name: "cli-commands", description: "MUST use when using the CLI, including debugging job failures and inspecting run history via `wmill job`." },
|
|
78105
|
+
{ name: "preview", description: "MUST use when opening the Windmill dev page / visual preview of a flow, script, or app. Triggers on words like preview, open, navigate to, visualize, see the flow/app/script, and after writing a flow/script/app for visual verification." }
|
|
77367
78106
|
];
|
|
77368
78107
|
var SKILL_CONTENT = {
|
|
77369
78108
|
"write-script-bash": `---
|
|
@@ -77373,11 +78112,36 @@ description: MUST use when writing Bash scripts.
|
|
|
77373
78112
|
|
|
77374
78113
|
## CLI Commands
|
|
77375
78114
|
|
|
77376
|
-
Place scripts in a folder.
|
|
77377
|
-
|
|
77378
|
-
|
|
78115
|
+
Place scripts in a folder.
|
|
78116
|
+
|
|
78117
|
+
After writing, tell the user which command fits what they want to do:
|
|
78118
|
+
|
|
78119
|
+
- \`wmill script preview <script_path>\` — **default when iterating on a local script.** Runs the local file without deploying.
|
|
78120
|
+
- \`wmill script run <path>\` — runs the script **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
78121
|
+
- \`wmill generate-metadata\` — generate \`.script.yaml\` and \`.lock\` files for the script you modified.
|
|
78122
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
78123
|
+
|
|
78124
|
+
### Preview vs run — choose by intent, not habit
|
|
78125
|
+
|
|
78126
|
+
If the user says "run the script", "try it", "test it", "does it work" while there are **local edits to the script file**, use \`script preview\`. Do NOT push the script to then \`script run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
78127
|
+
|
|
78128
|
+
Only use \`script run\` when:
|
|
78129
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
78130
|
+
- There is no local script being edited (you're just invoking an existing script).
|
|
78131
|
+
|
|
78132
|
+
Only use \`sync push\` when:
|
|
78133
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
78134
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
78135
|
+
|
|
78136
|
+
### After writing — offer to test, don't wait passively
|
|
77379
78137
|
|
|
77380
|
-
|
|
78138
|
+
If the user hasn't already told you to run/test/preview the script, offer it as a one-sentence next step (e.g. "Want me to run \`wmill script preview\` with sample args?"). Do not present a multi-option menu.
|
|
78139
|
+
|
|
78140
|
+
If the user already asked to test/run/try the script in their original request, skip the offer and just execute \`wmill script preview <path> -d '<args>'\` directly — pick plausible args from the script's declared parameters. The shape varies by language: \`main(...)\` for code languages, the SQL dialect's own placeholder syntax (\`$1\` for PostgreSQL, \`?\` for MySQL/Snowflake, \`@P1\` for MSSQL, \`@name\` for BigQuery, etc.), positional \`$1\`, \`$2\`, … for Bash, \`param(...)\` for PowerShell.
|
|
78141
|
+
|
|
78142
|
+
\`wmill script preview\` does not deploy, but it still executes script code and may cause side effects; run it yourself when the user asked to test/preview (or after confirming that execution is intended). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
78143
|
+
|
|
78144
|
+
For a **visual** open-the-script-in-the-dev-page preview (rather than \`script preview\`'s run-and-print-result), use the \`preview\` skill.
|
|
77381
78145
|
|
|
77382
78146
|
Use \`wmill resource-type list --schema\` to discover available resource types.
|
|
77383
78147
|
|
|
@@ -77438,11 +78202,36 @@ description: MUST use when writing BigQuery queries.
|
|
|
77438
78202
|
|
|
77439
78203
|
## CLI Commands
|
|
77440
78204
|
|
|
77441
|
-
Place scripts in a folder.
|
|
77442
|
-
|
|
77443
|
-
|
|
78205
|
+
Place scripts in a folder.
|
|
78206
|
+
|
|
78207
|
+
After writing, tell the user which command fits what they want to do:
|
|
78208
|
+
|
|
78209
|
+
- \`wmill script preview <script_path>\` — **default when iterating on a local script.** Runs the local file without deploying.
|
|
78210
|
+
- \`wmill script run <path>\` — runs the script **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
78211
|
+
- \`wmill generate-metadata\` — generate \`.script.yaml\` and \`.lock\` files for the script you modified.
|
|
78212
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
78213
|
+
|
|
78214
|
+
### Preview vs run — choose by intent, not habit
|
|
78215
|
+
|
|
78216
|
+
If the user says "run the script", "try it", "test it", "does it work" while there are **local edits to the script file**, use \`script preview\`. Do NOT push the script to then \`script run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
78217
|
+
|
|
78218
|
+
Only use \`script run\` when:
|
|
78219
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
78220
|
+
- There is no local script being edited (you're just invoking an existing script).
|
|
78221
|
+
|
|
78222
|
+
Only use \`sync push\` when:
|
|
78223
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
78224
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
78225
|
+
|
|
78226
|
+
### After writing — offer to test, don't wait passively
|
|
78227
|
+
|
|
78228
|
+
If the user hasn't already told you to run/test/preview the script, offer it as a one-sentence next step (e.g. "Want me to run \`wmill script preview\` with sample args?"). Do not present a multi-option menu.
|
|
77444
78229
|
|
|
77445
|
-
|
|
78230
|
+
If the user already asked to test/run/try the script in their original request, skip the offer and just execute \`wmill script preview <path> -d '<args>'\` directly — pick plausible args from the script's declared parameters. The shape varies by language: \`main(...)\` for code languages, the SQL dialect's own placeholder syntax (\`$1\` for PostgreSQL, \`?\` for MySQL/Snowflake, \`@P1\` for MSSQL, \`@name\` for BigQuery, etc.), positional \`$1\`, \`$2\`, … for Bash, \`param(...)\` for PowerShell.
|
|
78231
|
+
|
|
78232
|
+
\`wmill script preview\` does not deploy, but it still executes script code and may cause side effects; run it yourself when the user asked to test/preview (or after confirming that execution is intended). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
78233
|
+
|
|
78234
|
+
For a **visual** open-the-script-in-the-dev-page preview (rather than \`script preview\`'s run-and-print-result), use the \`preview\` skill.
|
|
77446
78235
|
|
|
77447
78236
|
Use \`wmill resource-type list --schema\` to discover available resource types.
|
|
77448
78237
|
|
|
@@ -77465,11 +78254,36 @@ description: MUST use when writing Bun/TypeScript scripts.
|
|
|
77465
78254
|
|
|
77466
78255
|
## CLI Commands
|
|
77467
78256
|
|
|
77468
|
-
Place scripts in a folder.
|
|
77469
|
-
|
|
77470
|
-
|
|
78257
|
+
Place scripts in a folder.
|
|
78258
|
+
|
|
78259
|
+
After writing, tell the user which command fits what they want to do:
|
|
78260
|
+
|
|
78261
|
+
- \`wmill script preview <script_path>\` — **default when iterating on a local script.** Runs the local file without deploying.
|
|
78262
|
+
- \`wmill script run <path>\` — runs the script **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
78263
|
+
- \`wmill generate-metadata\` — generate \`.script.yaml\` and \`.lock\` files for the script you modified.
|
|
78264
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
78265
|
+
|
|
78266
|
+
### Preview vs run — choose by intent, not habit
|
|
78267
|
+
|
|
78268
|
+
If the user says "run the script", "try it", "test it", "does it work" while there are **local edits to the script file**, use \`script preview\`. Do NOT push the script to then \`script run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
78269
|
+
|
|
78270
|
+
Only use \`script run\` when:
|
|
78271
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
78272
|
+
- There is no local script being edited (you're just invoking an existing script).
|
|
78273
|
+
|
|
78274
|
+
Only use \`sync push\` when:
|
|
78275
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
78276
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
78277
|
+
|
|
78278
|
+
### After writing — offer to test, don't wait passively
|
|
78279
|
+
|
|
78280
|
+
If the user hasn't already told you to run/test/preview the script, offer it as a one-sentence next step (e.g. "Want me to run \`wmill script preview\` with sample args?"). Do not present a multi-option menu.
|
|
78281
|
+
|
|
78282
|
+
If the user already asked to test/run/try the script in their original request, skip the offer and just execute \`wmill script preview <path> -d '<args>'\` directly — pick plausible args from the script's declared parameters. The shape varies by language: \`main(...)\` for code languages, the SQL dialect's own placeholder syntax (\`$1\` for PostgreSQL, \`?\` for MySQL/Snowflake, \`@P1\` for MSSQL, \`@name\` for BigQuery, etc.), positional \`$1\`, \`$2\`, … for Bash, \`param(...)\` for PowerShell.
|
|
77471
78283
|
|
|
77472
|
-
|
|
78284
|
+
\`wmill script preview\` does not deploy, but it still executes script code and may cause side effects; run it yourself when the user asked to test/preview (or after confirming that execution is intended). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
78285
|
+
|
|
78286
|
+
For a **visual** open-the-script-in-the-dev-page preview (rather than \`script preview\`'s run-and-print-result), use the \`preview\` skill.
|
|
77473
78287
|
|
|
77474
78288
|
Use \`wmill resource-type list --schema\` to discover available resource types.
|
|
77475
78289
|
|
|
@@ -78132,11 +78946,36 @@ description: MUST use when writing Bun Native scripts.
|
|
|
78132
78946
|
|
|
78133
78947
|
## CLI Commands
|
|
78134
78948
|
|
|
78135
|
-
Place scripts in a folder.
|
|
78136
|
-
|
|
78137
|
-
|
|
78949
|
+
Place scripts in a folder.
|
|
78950
|
+
|
|
78951
|
+
After writing, tell the user which command fits what they want to do:
|
|
78952
|
+
|
|
78953
|
+
- \`wmill script preview <script_path>\` — **default when iterating on a local script.** Runs the local file without deploying.
|
|
78954
|
+
- \`wmill script run <path>\` — runs the script **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
78955
|
+
- \`wmill generate-metadata\` — generate \`.script.yaml\` and \`.lock\` files for the script you modified.
|
|
78956
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
78957
|
+
|
|
78958
|
+
### Preview vs run — choose by intent, not habit
|
|
78959
|
+
|
|
78960
|
+
If the user says "run the script", "try it", "test it", "does it work" while there are **local edits to the script file**, use \`script preview\`. Do NOT push the script to then \`script run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
78961
|
+
|
|
78962
|
+
Only use \`script run\` when:
|
|
78963
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
78964
|
+
- There is no local script being edited (you're just invoking an existing script).
|
|
78965
|
+
|
|
78966
|
+
Only use \`sync push\` when:
|
|
78967
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
78968
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
78969
|
+
|
|
78970
|
+
### After writing — offer to test, don't wait passively
|
|
78971
|
+
|
|
78972
|
+
If the user hasn't already told you to run/test/preview the script, offer it as a one-sentence next step (e.g. "Want me to run \`wmill script preview\` with sample args?"). Do not present a multi-option menu.
|
|
78973
|
+
|
|
78974
|
+
If the user already asked to test/run/try the script in their original request, skip the offer and just execute \`wmill script preview <path> -d '<args>'\` directly — pick plausible args from the script's declared parameters. The shape varies by language: \`main(...)\` for code languages, the SQL dialect's own placeholder syntax (\`$1\` for PostgreSQL, \`?\` for MySQL/Snowflake, \`@P1\` for MSSQL, \`@name\` for BigQuery, etc.), positional \`$1\`, \`$2\`, … for Bash, \`param(...)\` for PowerShell.
|
|
78975
|
+
|
|
78976
|
+
\`wmill script preview\` does not deploy, but it still executes script code and may cause side effects; run it yourself when the user asked to test/preview (or after confirming that execution is intended). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
78138
78977
|
|
|
78139
|
-
|
|
78978
|
+
For a **visual** open-the-script-in-the-dev-page preview (rather than \`script preview\`'s run-and-print-result), use the \`preview\` skill.
|
|
78140
78979
|
|
|
78141
78980
|
Use \`wmill resource-type list --schema\` to discover available resource types.
|
|
78142
78981
|
|
|
@@ -78797,11 +79636,36 @@ description: MUST use when writing C# scripts.
|
|
|
78797
79636
|
|
|
78798
79637
|
## CLI Commands
|
|
78799
79638
|
|
|
78800
|
-
Place scripts in a folder.
|
|
78801
|
-
|
|
78802
|
-
|
|
79639
|
+
Place scripts in a folder.
|
|
79640
|
+
|
|
79641
|
+
After writing, tell the user which command fits what they want to do:
|
|
79642
|
+
|
|
79643
|
+
- \`wmill script preview <script_path>\` — **default when iterating on a local script.** Runs the local file without deploying.
|
|
79644
|
+
- \`wmill script run <path>\` — runs the script **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
79645
|
+
- \`wmill generate-metadata\` — generate \`.script.yaml\` and \`.lock\` files for the script you modified.
|
|
79646
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
79647
|
+
|
|
79648
|
+
### Preview vs run — choose by intent, not habit
|
|
79649
|
+
|
|
79650
|
+
If the user says "run the script", "try it", "test it", "does it work" while there are **local edits to the script file**, use \`script preview\`. Do NOT push the script to then \`script run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
79651
|
+
|
|
79652
|
+
Only use \`script run\` when:
|
|
79653
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
79654
|
+
- There is no local script being edited (you're just invoking an existing script).
|
|
79655
|
+
|
|
79656
|
+
Only use \`sync push\` when:
|
|
79657
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
79658
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
79659
|
+
|
|
79660
|
+
### After writing — offer to test, don't wait passively
|
|
79661
|
+
|
|
79662
|
+
If the user hasn't already told you to run/test/preview the script, offer it as a one-sentence next step (e.g. "Want me to run \`wmill script preview\` with sample args?"). Do not present a multi-option menu.
|
|
79663
|
+
|
|
79664
|
+
If the user already asked to test/run/try the script in their original request, skip the offer and just execute \`wmill script preview <path> -d '<args>'\` directly — pick plausible args from the script's declared parameters. The shape varies by language: \`main(...)\` for code languages, the SQL dialect's own placeholder syntax (\`$1\` for PostgreSQL, \`?\` for MySQL/Snowflake, \`@P1\` for MSSQL, \`@name\` for BigQuery, etc.), positional \`$1\`, \`$2\`, … for Bash, \`param(...)\` for PowerShell.
|
|
79665
|
+
|
|
79666
|
+
\`wmill script preview\` does not deploy, but it still executes script code and may cause side effects; run it yourself when the user asked to test/preview (or after confirming that execution is intended). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
78803
79667
|
|
|
78804
|
-
|
|
79668
|
+
For a **visual** open-the-script-in-the-dev-page preview (rather than \`script preview\`'s run-and-print-result), use the \`preview\` skill.
|
|
78805
79669
|
|
|
78806
79670
|
Use \`wmill resource-type list --schema\` to discover available resource types.
|
|
78807
79671
|
|
|
@@ -78854,11 +79718,36 @@ description: MUST use when writing Deno/TypeScript scripts.
|
|
|
78854
79718
|
|
|
78855
79719
|
## CLI Commands
|
|
78856
79720
|
|
|
78857
|
-
Place scripts in a folder.
|
|
78858
|
-
- \`wmill generate-metadata\` - Generate .script.yaml and .lock files
|
|
78859
|
-
- \`wmill sync push\` - Deploy to Windmill
|
|
79721
|
+
Place scripts in a folder.
|
|
78860
79722
|
|
|
78861
|
-
|
|
79723
|
+
After writing, tell the user which command fits what they want to do:
|
|
79724
|
+
|
|
79725
|
+
- \`wmill script preview <script_path>\` — **default when iterating on a local script.** Runs the local file without deploying.
|
|
79726
|
+
- \`wmill script run <path>\` — runs the script **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
79727
|
+
- \`wmill generate-metadata\` — generate \`.script.yaml\` and \`.lock\` files for the script you modified.
|
|
79728
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
79729
|
+
|
|
79730
|
+
### Preview vs run — choose by intent, not habit
|
|
79731
|
+
|
|
79732
|
+
If the user says "run the script", "try it", "test it", "does it work" while there are **local edits to the script file**, use \`script preview\`. Do NOT push the script to then \`script run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
79733
|
+
|
|
79734
|
+
Only use \`script run\` when:
|
|
79735
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
79736
|
+
- There is no local script being edited (you're just invoking an existing script).
|
|
79737
|
+
|
|
79738
|
+
Only use \`sync push\` when:
|
|
79739
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
79740
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
79741
|
+
|
|
79742
|
+
### After writing — offer to test, don't wait passively
|
|
79743
|
+
|
|
79744
|
+
If the user hasn't already told you to run/test/preview the script, offer it as a one-sentence next step (e.g. "Want me to run \`wmill script preview\` with sample args?"). Do not present a multi-option menu.
|
|
79745
|
+
|
|
79746
|
+
If the user already asked to test/run/try the script in their original request, skip the offer and just execute \`wmill script preview <path> -d '<args>'\` directly — pick plausible args from the script's declared parameters. The shape varies by language: \`main(...)\` for code languages, the SQL dialect's own placeholder syntax (\`$1\` for PostgreSQL, \`?\` for MySQL/Snowflake, \`@P1\` for MSSQL, \`@name\` for BigQuery, etc.), positional \`$1\`, \`$2\`, … for Bash, \`param(...)\` for PowerShell.
|
|
79747
|
+
|
|
79748
|
+
\`wmill script preview\` does not deploy, but it still executes script code and may cause side effects; run it yourself when the user asked to test/preview (or after confirming that execution is intended). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
79749
|
+
|
|
79750
|
+
For a **visual** open-the-script-in-the-dev-page preview (rather than \`script preview\`'s run-and-print-result), use the \`preview\` skill.
|
|
78862
79751
|
|
|
78863
79752
|
Use \`wmill resource-type list --schema\` to discover available resource types.
|
|
78864
79753
|
|
|
@@ -79525,11 +80414,36 @@ description: MUST use when writing DuckDB queries.
|
|
|
79525
80414
|
|
|
79526
80415
|
## CLI Commands
|
|
79527
80416
|
|
|
79528
|
-
Place scripts in a folder.
|
|
79529
|
-
|
|
79530
|
-
|
|
80417
|
+
Place scripts in a folder.
|
|
80418
|
+
|
|
80419
|
+
After writing, tell the user which command fits what they want to do:
|
|
80420
|
+
|
|
80421
|
+
- \`wmill script preview <script_path>\` — **default when iterating on a local script.** Runs the local file without deploying.
|
|
80422
|
+
- \`wmill script run <path>\` — runs the script **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
80423
|
+
- \`wmill generate-metadata\` — generate \`.script.yaml\` and \`.lock\` files for the script you modified.
|
|
80424
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
80425
|
+
|
|
80426
|
+
### Preview vs run — choose by intent, not habit
|
|
80427
|
+
|
|
80428
|
+
If the user says "run the script", "try it", "test it", "does it work" while there are **local edits to the script file**, use \`script preview\`. Do NOT push the script to then \`script run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
80429
|
+
|
|
80430
|
+
Only use \`script run\` when:
|
|
80431
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
80432
|
+
- There is no local script being edited (you're just invoking an existing script).
|
|
80433
|
+
|
|
80434
|
+
Only use \`sync push\` when:
|
|
80435
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
80436
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
80437
|
+
|
|
80438
|
+
### After writing — offer to test, don't wait passively
|
|
79531
80439
|
|
|
79532
|
-
|
|
80440
|
+
If the user hasn't already told you to run/test/preview the script, offer it as a one-sentence next step (e.g. "Want me to run \`wmill script preview\` with sample args?"). Do not present a multi-option menu.
|
|
80441
|
+
|
|
80442
|
+
If the user already asked to test/run/try the script in their original request, skip the offer and just execute \`wmill script preview <path> -d '<args>'\` directly — pick plausible args from the script's declared parameters. The shape varies by language: \`main(...)\` for code languages, the SQL dialect's own placeholder syntax (\`$1\` for PostgreSQL, \`?\` for MySQL/Snowflake, \`@P1\` for MSSQL, \`@name\` for BigQuery, etc.), positional \`$1\`, \`$2\`, … for Bash, \`param(...)\` for PowerShell.
|
|
80443
|
+
|
|
80444
|
+
\`wmill script preview\` does not deploy, but it still executes script code and may cause side effects; run it yourself when the user asked to test/preview (or after confirming that execution is intended). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
80445
|
+
|
|
80446
|
+
For a **visual** open-the-script-in-the-dev-page preview (rather than \`script preview\`'s run-and-print-result), use the \`preview\` skill.
|
|
79533
80447
|
|
|
79534
80448
|
Use \`wmill resource-type list --schema\` to discover available resource types.
|
|
79535
80449
|
|
|
@@ -79592,11 +80506,36 @@ description: MUST use when writing Go scripts.
|
|
|
79592
80506
|
|
|
79593
80507
|
## CLI Commands
|
|
79594
80508
|
|
|
79595
|
-
Place scripts in a folder.
|
|
79596
|
-
|
|
79597
|
-
|
|
80509
|
+
Place scripts in a folder.
|
|
80510
|
+
|
|
80511
|
+
After writing, tell the user which command fits what they want to do:
|
|
80512
|
+
|
|
80513
|
+
- \`wmill script preview <script_path>\` — **default when iterating on a local script.** Runs the local file without deploying.
|
|
80514
|
+
- \`wmill script run <path>\` — runs the script **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
80515
|
+
- \`wmill generate-metadata\` — generate \`.script.yaml\` and \`.lock\` files for the script you modified.
|
|
80516
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
80517
|
+
|
|
80518
|
+
### Preview vs run — choose by intent, not habit
|
|
80519
|
+
|
|
80520
|
+
If the user says "run the script", "try it", "test it", "does it work" while there are **local edits to the script file**, use \`script preview\`. Do NOT push the script to then \`script run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
80521
|
+
|
|
80522
|
+
Only use \`script run\` when:
|
|
80523
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
80524
|
+
- There is no local script being edited (you're just invoking an existing script).
|
|
79598
80525
|
|
|
79599
|
-
|
|
80526
|
+
Only use \`sync push\` when:
|
|
80527
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
80528
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
80529
|
+
|
|
80530
|
+
### After writing — offer to test, don't wait passively
|
|
80531
|
+
|
|
80532
|
+
If the user hasn't already told you to run/test/preview the script, offer it as a one-sentence next step (e.g. "Want me to run \`wmill script preview\` with sample args?"). Do not present a multi-option menu.
|
|
80533
|
+
|
|
80534
|
+
If the user already asked to test/run/try the script in their original request, skip the offer and just execute \`wmill script preview <path> -d '<args>'\` directly — pick plausible args from the script's declared parameters. The shape varies by language: \`main(...)\` for code languages, the SQL dialect's own placeholder syntax (\`$1\` for PostgreSQL, \`?\` for MySQL/Snowflake, \`@P1\` for MSSQL, \`@name\` for BigQuery, etc.), positional \`$1\`, \`$2\`, … for Bash, \`param(...)\` for PowerShell.
|
|
80535
|
+
|
|
80536
|
+
\`wmill script preview\` does not deploy, but it still executes script code and may cause side effects; run it yourself when the user asked to test/preview (or after confirming that execution is intended). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
80537
|
+
|
|
80538
|
+
For a **visual** open-the-script-in-the-dev-page preview (rather than \`script preview\`'s run-and-print-result), use the \`preview\` skill.
|
|
79600
80539
|
|
|
79601
80540
|
Use \`wmill resource-type list --schema\` to discover available resource types.
|
|
79602
80541
|
|
|
@@ -79666,11 +80605,36 @@ description: MUST use when writing GraphQL queries.
|
|
|
79666
80605
|
|
|
79667
80606
|
## CLI Commands
|
|
79668
80607
|
|
|
79669
|
-
Place scripts in a folder.
|
|
79670
|
-
|
|
79671
|
-
|
|
80608
|
+
Place scripts in a folder.
|
|
80609
|
+
|
|
80610
|
+
After writing, tell the user which command fits what they want to do:
|
|
80611
|
+
|
|
80612
|
+
- \`wmill script preview <script_path>\` — **default when iterating on a local script.** Runs the local file without deploying.
|
|
80613
|
+
- \`wmill script run <path>\` — runs the script **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
80614
|
+
- \`wmill generate-metadata\` — generate \`.script.yaml\` and \`.lock\` files for the script you modified.
|
|
80615
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
80616
|
+
|
|
80617
|
+
### Preview vs run — choose by intent, not habit
|
|
79672
80618
|
|
|
79673
|
-
Do NOT run
|
|
80619
|
+
If the user says "run the script", "try it", "test it", "does it work" while there are **local edits to the script file**, use \`script preview\`. Do NOT push the script to then \`script run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
80620
|
+
|
|
80621
|
+
Only use \`script run\` when:
|
|
80622
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
80623
|
+
- There is no local script being edited (you're just invoking an existing script).
|
|
80624
|
+
|
|
80625
|
+
Only use \`sync push\` when:
|
|
80626
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
80627
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
80628
|
+
|
|
80629
|
+
### After writing — offer to test, don't wait passively
|
|
80630
|
+
|
|
80631
|
+
If the user hasn't already told you to run/test/preview the script, offer it as a one-sentence next step (e.g. "Want me to run \`wmill script preview\` with sample args?"). Do not present a multi-option menu.
|
|
80632
|
+
|
|
80633
|
+
If the user already asked to test/run/try the script in their original request, skip the offer and just execute \`wmill script preview <path> -d '<args>'\` directly — pick plausible args from the script's declared parameters. The shape varies by language: \`main(...)\` for code languages, the SQL dialect's own placeholder syntax (\`$1\` for PostgreSQL, \`?\` for MySQL/Snowflake, \`@P1\` for MSSQL, \`@name\` for BigQuery, etc.), positional \`$1\`, \`$2\`, … for Bash, \`param(...)\` for PowerShell.
|
|
80634
|
+
|
|
80635
|
+
\`wmill script preview\` does not deploy, but it still executes script code and may cause side effects; run it yourself when the user asked to test/preview (or after confirming that execution is intended). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
80636
|
+
|
|
80637
|
+
For a **visual** open-the-script-in-the-dev-page preview (rather than \`script preview\`'s run-and-print-result), use the \`preview\` skill.
|
|
79674
80638
|
|
|
79675
80639
|
Use \`wmill resource-type list --schema\` to discover available resource types.
|
|
79676
80640
|
|
|
@@ -79727,11 +80691,36 @@ description: MUST use when writing Java scripts.
|
|
|
79727
80691
|
|
|
79728
80692
|
## CLI Commands
|
|
79729
80693
|
|
|
79730
|
-
Place scripts in a folder.
|
|
79731
|
-
|
|
79732
|
-
|
|
80694
|
+
Place scripts in a folder.
|
|
80695
|
+
|
|
80696
|
+
After writing, tell the user which command fits what they want to do:
|
|
80697
|
+
|
|
80698
|
+
- \`wmill script preview <script_path>\` — **default when iterating on a local script.** Runs the local file without deploying.
|
|
80699
|
+
- \`wmill script run <path>\` — runs the script **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
80700
|
+
- \`wmill generate-metadata\` — generate \`.script.yaml\` and \`.lock\` files for the script you modified.
|
|
80701
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
80702
|
+
|
|
80703
|
+
### Preview vs run — choose by intent, not habit
|
|
80704
|
+
|
|
80705
|
+
If the user says "run the script", "try it", "test it", "does it work" while there are **local edits to the script file**, use \`script preview\`. Do NOT push the script to then \`script run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
80706
|
+
|
|
80707
|
+
Only use \`script run\` when:
|
|
80708
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
80709
|
+
- There is no local script being edited (you're just invoking an existing script).
|
|
80710
|
+
|
|
80711
|
+
Only use \`sync push\` when:
|
|
80712
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
80713
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
80714
|
+
|
|
80715
|
+
### After writing — offer to test, don't wait passively
|
|
80716
|
+
|
|
80717
|
+
If the user hasn't already told you to run/test/preview the script, offer it as a one-sentence next step (e.g. "Want me to run \`wmill script preview\` with sample args?"). Do not present a multi-option menu.
|
|
80718
|
+
|
|
80719
|
+
If the user already asked to test/run/try the script in their original request, skip the offer and just execute \`wmill script preview <path> -d '<args>'\` directly — pick plausible args from the script's declared parameters. The shape varies by language: \`main(...)\` for code languages, the SQL dialect's own placeholder syntax (\`$1\` for PostgreSQL, \`?\` for MySQL/Snowflake, \`@P1\` for MSSQL, \`@name\` for BigQuery, etc.), positional \`$1\`, \`$2\`, … for Bash, \`param(...)\` for PowerShell.
|
|
79733
80720
|
|
|
79734
|
-
|
|
80721
|
+
\`wmill script preview\` does not deploy, but it still executes script code and may cause side effects; run it yourself when the user asked to test/preview (or after confirming that execution is intended). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
80722
|
+
|
|
80723
|
+
For a **visual** open-the-script-in-the-dev-page preview (rather than \`script preview\`'s run-and-print-result), use the \`preview\` skill.
|
|
79735
80724
|
|
|
79736
80725
|
Use \`wmill resource-type list --schema\` to discover available resource types.
|
|
79737
80726
|
|
|
@@ -79781,11 +80770,36 @@ description: MUST use when writing MS SQL Server queries.
|
|
|
79781
80770
|
|
|
79782
80771
|
## CLI Commands
|
|
79783
80772
|
|
|
79784
|
-
Place scripts in a folder.
|
|
79785
|
-
|
|
79786
|
-
|
|
80773
|
+
Place scripts in a folder.
|
|
80774
|
+
|
|
80775
|
+
After writing, tell the user which command fits what they want to do:
|
|
80776
|
+
|
|
80777
|
+
- \`wmill script preview <script_path>\` — **default when iterating on a local script.** Runs the local file without deploying.
|
|
80778
|
+
- \`wmill script run <path>\` — runs the script **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
80779
|
+
- \`wmill generate-metadata\` — generate \`.script.yaml\` and \`.lock\` files for the script you modified.
|
|
80780
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
80781
|
+
|
|
80782
|
+
### Preview vs run — choose by intent, not habit
|
|
80783
|
+
|
|
80784
|
+
If the user says "run the script", "try it", "test it", "does it work" while there are **local edits to the script file**, use \`script preview\`. Do NOT push the script to then \`script run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
80785
|
+
|
|
80786
|
+
Only use \`script run\` when:
|
|
80787
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
80788
|
+
- There is no local script being edited (you're just invoking an existing script).
|
|
80789
|
+
|
|
80790
|
+
Only use \`sync push\` when:
|
|
80791
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
80792
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
80793
|
+
|
|
80794
|
+
### After writing — offer to test, don't wait passively
|
|
79787
80795
|
|
|
79788
|
-
|
|
80796
|
+
If the user hasn't already told you to run/test/preview the script, offer it as a one-sentence next step (e.g. "Want me to run \`wmill script preview\` with sample args?"). Do not present a multi-option menu.
|
|
80797
|
+
|
|
80798
|
+
If the user already asked to test/run/try the script in their original request, skip the offer and just execute \`wmill script preview <path> -d '<args>'\` directly — pick plausible args from the script's declared parameters. The shape varies by language: \`main(...)\` for code languages, the SQL dialect's own placeholder syntax (\`$1\` for PostgreSQL, \`?\` for MySQL/Snowflake, \`@P1\` for MSSQL, \`@name\` for BigQuery, etc.), positional \`$1\`, \`$2\`, … for Bash, \`param(...)\` for PowerShell.
|
|
80799
|
+
|
|
80800
|
+
\`wmill script preview\` does not deploy, but it still executes script code and may cause side effects; run it yourself when the user asked to test/preview (or after confirming that execution is intended). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
80801
|
+
|
|
80802
|
+
For a **visual** open-the-script-in-the-dev-page preview (rather than \`script preview\`'s run-and-print-result), use the \`preview\` skill.
|
|
79789
80803
|
|
|
79790
80804
|
Use \`wmill resource-type list --schema\` to discover available resource types.
|
|
79791
80805
|
|
|
@@ -79808,11 +80822,36 @@ description: MUST use when writing MySQL queries.
|
|
|
79808
80822
|
|
|
79809
80823
|
## CLI Commands
|
|
79810
80824
|
|
|
79811
|
-
Place scripts in a folder.
|
|
79812
|
-
|
|
79813
|
-
|
|
80825
|
+
Place scripts in a folder.
|
|
80826
|
+
|
|
80827
|
+
After writing, tell the user which command fits what they want to do:
|
|
80828
|
+
|
|
80829
|
+
- \`wmill script preview <script_path>\` — **default when iterating on a local script.** Runs the local file without deploying.
|
|
80830
|
+
- \`wmill script run <path>\` — runs the script **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
80831
|
+
- \`wmill generate-metadata\` — generate \`.script.yaml\` and \`.lock\` files for the script you modified.
|
|
80832
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
80833
|
+
|
|
80834
|
+
### Preview vs run — choose by intent, not habit
|
|
80835
|
+
|
|
80836
|
+
If the user says "run the script", "try it", "test it", "does it work" while there are **local edits to the script file**, use \`script preview\`. Do NOT push the script to then \`script run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
80837
|
+
|
|
80838
|
+
Only use \`script run\` when:
|
|
80839
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
80840
|
+
- There is no local script being edited (you're just invoking an existing script).
|
|
79814
80841
|
|
|
79815
|
-
|
|
80842
|
+
Only use \`sync push\` when:
|
|
80843
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
80844
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
80845
|
+
|
|
80846
|
+
### After writing — offer to test, don't wait passively
|
|
80847
|
+
|
|
80848
|
+
If the user hasn't already told you to run/test/preview the script, offer it as a one-sentence next step (e.g. "Want me to run \`wmill script preview\` with sample args?"). Do not present a multi-option menu.
|
|
80849
|
+
|
|
80850
|
+
If the user already asked to test/run/try the script in their original request, skip the offer and just execute \`wmill script preview <path> -d '<args>'\` directly — pick plausible args from the script's declared parameters. The shape varies by language: \`main(...)\` for code languages, the SQL dialect's own placeholder syntax (\`$1\` for PostgreSQL, \`?\` for MySQL/Snowflake, \`@P1\` for MSSQL, \`@name\` for BigQuery, etc.), positional \`$1\`, \`$2\`, … for Bash, \`param(...)\` for PowerShell.
|
|
80851
|
+
|
|
80852
|
+
\`wmill script preview\` does not deploy, but it still executes script code and may cause side effects; run it yourself when the user asked to test/preview (or after confirming that execution is intended). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
80853
|
+
|
|
80854
|
+
For a **visual** open-the-script-in-the-dev-page preview (rather than \`script preview\`'s run-and-print-result), use the \`preview\` skill.
|
|
79816
80855
|
|
|
79817
80856
|
Use \`wmill resource-type list --schema\` to discover available resource types.
|
|
79818
80857
|
|
|
@@ -79835,11 +80874,36 @@ description: MUST use when writing Native TypeScript scripts.
|
|
|
79835
80874
|
|
|
79836
80875
|
## CLI Commands
|
|
79837
80876
|
|
|
79838
|
-
Place scripts in a folder.
|
|
79839
|
-
|
|
79840
|
-
|
|
80877
|
+
Place scripts in a folder.
|
|
80878
|
+
|
|
80879
|
+
After writing, tell the user which command fits what they want to do:
|
|
80880
|
+
|
|
80881
|
+
- \`wmill script preview <script_path>\` — **default when iterating on a local script.** Runs the local file without deploying.
|
|
80882
|
+
- \`wmill script run <path>\` — runs the script **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
80883
|
+
- \`wmill generate-metadata\` — generate \`.script.yaml\` and \`.lock\` files for the script you modified.
|
|
80884
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
80885
|
+
|
|
80886
|
+
### Preview vs run — choose by intent, not habit
|
|
80887
|
+
|
|
80888
|
+
If the user says "run the script", "try it", "test it", "does it work" while there are **local edits to the script file**, use \`script preview\`. Do NOT push the script to then \`script run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
79841
80889
|
|
|
79842
|
-
|
|
80890
|
+
Only use \`script run\` when:
|
|
80891
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
80892
|
+
- There is no local script being edited (you're just invoking an existing script).
|
|
80893
|
+
|
|
80894
|
+
Only use \`sync push\` when:
|
|
80895
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
80896
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
80897
|
+
|
|
80898
|
+
### After writing — offer to test, don't wait passively
|
|
80899
|
+
|
|
80900
|
+
If the user hasn't already told you to run/test/preview the script, offer it as a one-sentence next step (e.g. "Want me to run \`wmill script preview\` with sample args?"). Do not present a multi-option menu.
|
|
80901
|
+
|
|
80902
|
+
If the user already asked to test/run/try the script in their original request, skip the offer and just execute \`wmill script preview <path> -d '<args>'\` directly — pick plausible args from the script's declared parameters. The shape varies by language: \`main(...)\` for code languages, the SQL dialect's own placeholder syntax (\`$1\` for PostgreSQL, \`?\` for MySQL/Snowflake, \`@P1\` for MSSQL, \`@name\` for BigQuery, etc.), positional \`$1\`, \`$2\`, … for Bash, \`param(...)\` for PowerShell.
|
|
80903
|
+
|
|
80904
|
+
\`wmill script preview\` does not deploy, but it still executes script code and may cause side effects; run it yourself when the user asked to test/preview (or after confirming that execution is intended). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
80905
|
+
|
|
80906
|
+
For a **visual** open-the-script-in-the-dev-page preview (rather than \`script preview\`'s run-and-print-result), use the \`preview\` skill.
|
|
79843
80907
|
|
|
79844
80908
|
Use \`wmill resource-type list --schema\` to discover available resource types.
|
|
79845
80909
|
|
|
@@ -80467,11 +81531,36 @@ description: MUST use when writing PHP scripts.
|
|
|
80467
81531
|
|
|
80468
81532
|
## CLI Commands
|
|
80469
81533
|
|
|
80470
|
-
Place scripts in a folder.
|
|
80471
|
-
|
|
80472
|
-
|
|
81534
|
+
Place scripts in a folder.
|
|
81535
|
+
|
|
81536
|
+
After writing, tell the user which command fits what they want to do:
|
|
81537
|
+
|
|
81538
|
+
- \`wmill script preview <script_path>\` — **default when iterating on a local script.** Runs the local file without deploying.
|
|
81539
|
+
- \`wmill script run <path>\` — runs the script **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
81540
|
+
- \`wmill generate-metadata\` — generate \`.script.yaml\` and \`.lock\` files for the script you modified.
|
|
81541
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
80473
81542
|
|
|
80474
|
-
|
|
81543
|
+
### Preview vs run — choose by intent, not habit
|
|
81544
|
+
|
|
81545
|
+
If the user says "run the script", "try it", "test it", "does it work" while there are **local edits to the script file**, use \`script preview\`. Do NOT push the script to then \`script run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
81546
|
+
|
|
81547
|
+
Only use \`script run\` when:
|
|
81548
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
81549
|
+
- There is no local script being edited (you're just invoking an existing script).
|
|
81550
|
+
|
|
81551
|
+
Only use \`sync push\` when:
|
|
81552
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
81553
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
81554
|
+
|
|
81555
|
+
### After writing — offer to test, don't wait passively
|
|
81556
|
+
|
|
81557
|
+
If the user hasn't already told you to run/test/preview the script, offer it as a one-sentence next step (e.g. "Want me to run \`wmill script preview\` with sample args?"). Do not present a multi-option menu.
|
|
81558
|
+
|
|
81559
|
+
If the user already asked to test/run/try the script in their original request, skip the offer and just execute \`wmill script preview <path> -d '<args>'\` directly — pick plausible args from the script's declared parameters. The shape varies by language: \`main(...)\` for code languages, the SQL dialect's own placeholder syntax (\`$1\` for PostgreSQL, \`?\` for MySQL/Snowflake, \`@P1\` for MSSQL, \`@name\` for BigQuery, etc.), positional \`$1\`, \`$2\`, … for Bash, \`param(...)\` for PowerShell.
|
|
81560
|
+
|
|
81561
|
+
\`wmill script preview\` does not deploy, but it still executes script code and may cause side effects; run it yourself when the user asked to test/preview (or after confirming that execution is intended). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
81562
|
+
|
|
81563
|
+
For a **visual** open-the-script-in-the-dev-page preview (rather than \`script preview\`'s run-and-print-result), use the \`preview\` skill.
|
|
80475
81564
|
|
|
80476
81565
|
Use \`wmill resource-type list --schema\` to discover available resource types.
|
|
80477
81566
|
|
|
@@ -80540,11 +81629,36 @@ description: MUST use when writing PostgreSQL queries.
|
|
|
80540
81629
|
|
|
80541
81630
|
## CLI Commands
|
|
80542
81631
|
|
|
80543
|
-
Place scripts in a folder.
|
|
80544
|
-
|
|
80545
|
-
|
|
81632
|
+
Place scripts in a folder.
|
|
81633
|
+
|
|
81634
|
+
After writing, tell the user which command fits what they want to do:
|
|
81635
|
+
|
|
81636
|
+
- \`wmill script preview <script_path>\` — **default when iterating on a local script.** Runs the local file without deploying.
|
|
81637
|
+
- \`wmill script run <path>\` — runs the script **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
81638
|
+
- \`wmill generate-metadata\` — generate \`.script.yaml\` and \`.lock\` files for the script you modified.
|
|
81639
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
81640
|
+
|
|
81641
|
+
### Preview vs run — choose by intent, not habit
|
|
81642
|
+
|
|
81643
|
+
If the user says "run the script", "try it", "test it", "does it work" while there are **local edits to the script file**, use \`script preview\`. Do NOT push the script to then \`script run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
81644
|
+
|
|
81645
|
+
Only use \`script run\` when:
|
|
81646
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
81647
|
+
- There is no local script being edited (you're just invoking an existing script).
|
|
81648
|
+
|
|
81649
|
+
Only use \`sync push\` when:
|
|
81650
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
81651
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
81652
|
+
|
|
81653
|
+
### After writing — offer to test, don't wait passively
|
|
81654
|
+
|
|
81655
|
+
If the user hasn't already told you to run/test/preview the script, offer it as a one-sentence next step (e.g. "Want me to run \`wmill script preview\` with sample args?"). Do not present a multi-option menu.
|
|
80546
81656
|
|
|
80547
|
-
|
|
81657
|
+
If the user already asked to test/run/try the script in their original request, skip the offer and just execute \`wmill script preview <path> -d '<args>'\` directly — pick plausible args from the script's declared parameters. The shape varies by language: \`main(...)\` for code languages, the SQL dialect's own placeholder syntax (\`$1\` for PostgreSQL, \`?\` for MySQL/Snowflake, \`@P1\` for MSSQL, \`@name\` for BigQuery, etc.), positional \`$1\`, \`$2\`, … for Bash, \`param(...)\` for PowerShell.
|
|
81658
|
+
|
|
81659
|
+
\`wmill script preview\` does not deploy, but it still executes script code and may cause side effects; run it yourself when the user asked to test/preview (or after confirming that execution is intended). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
81660
|
+
|
|
81661
|
+
For a **visual** open-the-script-in-the-dev-page preview (rather than \`script preview\`'s run-and-print-result), use the \`preview\` skill.
|
|
80548
81662
|
|
|
80549
81663
|
Use \`wmill resource-type list --schema\` to discover available resource types.
|
|
80550
81664
|
|
|
@@ -80567,11 +81681,36 @@ description: MUST use when writing PowerShell scripts.
|
|
|
80567
81681
|
|
|
80568
81682
|
## CLI Commands
|
|
80569
81683
|
|
|
80570
|
-
Place scripts in a folder.
|
|
80571
|
-
|
|
80572
|
-
|
|
81684
|
+
Place scripts in a folder.
|
|
81685
|
+
|
|
81686
|
+
After writing, tell the user which command fits what they want to do:
|
|
81687
|
+
|
|
81688
|
+
- \`wmill script preview <script_path>\` — **default when iterating on a local script.** Runs the local file without deploying.
|
|
81689
|
+
- \`wmill script run <path>\` — runs the script **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
81690
|
+
- \`wmill generate-metadata\` — generate \`.script.yaml\` and \`.lock\` files for the script you modified.
|
|
81691
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
81692
|
+
|
|
81693
|
+
### Preview vs run — choose by intent, not habit
|
|
81694
|
+
|
|
81695
|
+
If the user says "run the script", "try it", "test it", "does it work" while there are **local edits to the script file**, use \`script preview\`. Do NOT push the script to then \`script run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
81696
|
+
|
|
81697
|
+
Only use \`script run\` when:
|
|
81698
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
81699
|
+
- There is no local script being edited (you're just invoking an existing script).
|
|
81700
|
+
|
|
81701
|
+
Only use \`sync push\` when:
|
|
81702
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
81703
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
80573
81704
|
|
|
80574
|
-
|
|
81705
|
+
### After writing — offer to test, don't wait passively
|
|
81706
|
+
|
|
81707
|
+
If the user hasn't already told you to run/test/preview the script, offer it as a one-sentence next step (e.g. "Want me to run \`wmill script preview\` with sample args?"). Do not present a multi-option menu.
|
|
81708
|
+
|
|
81709
|
+
If the user already asked to test/run/try the script in their original request, skip the offer and just execute \`wmill script preview <path> -d '<args>'\` directly — pick plausible args from the script's declared parameters. The shape varies by language: \`main(...)\` for code languages, the SQL dialect's own placeholder syntax (\`$1\` for PostgreSQL, \`?\` for MySQL/Snowflake, \`@P1\` for MSSQL, \`@name\` for BigQuery, etc.), positional \`$1\`, \`$2\`, … for Bash, \`param(...)\` for PowerShell.
|
|
81710
|
+
|
|
81711
|
+
\`wmill script preview\` does not deploy, but it still executes script code and may cause side effects; run it yourself when the user asked to test/preview (or after confirming that execution is intended). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
81712
|
+
|
|
81713
|
+
For a **visual** open-the-script-in-the-dev-page preview (rather than \`script preview\`'s run-and-print-result), use the \`preview\` skill.
|
|
80575
81714
|
|
|
80576
81715
|
Use \`wmill resource-type list --schema\` to discover available resource types.
|
|
80577
81716
|
|
|
@@ -80638,11 +81777,36 @@ description: MUST use when writing Python scripts.
|
|
|
80638
81777
|
|
|
80639
81778
|
## CLI Commands
|
|
80640
81779
|
|
|
80641
|
-
Place scripts in a folder.
|
|
80642
|
-
|
|
80643
|
-
|
|
81780
|
+
Place scripts in a folder.
|
|
81781
|
+
|
|
81782
|
+
After writing, tell the user which command fits what they want to do:
|
|
81783
|
+
|
|
81784
|
+
- \`wmill script preview <script_path>\` — **default when iterating on a local script.** Runs the local file without deploying.
|
|
81785
|
+
- \`wmill script run <path>\` — runs the script **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
81786
|
+
- \`wmill generate-metadata\` — generate \`.script.yaml\` and \`.lock\` files for the script you modified.
|
|
81787
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
81788
|
+
|
|
81789
|
+
### Preview vs run — choose by intent, not habit
|
|
81790
|
+
|
|
81791
|
+
If the user says "run the script", "try it", "test it", "does it work" while there are **local edits to the script file**, use \`script preview\`. Do NOT push the script to then \`script run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
80644
81792
|
|
|
80645
|
-
|
|
81793
|
+
Only use \`script run\` when:
|
|
81794
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
81795
|
+
- There is no local script being edited (you're just invoking an existing script).
|
|
81796
|
+
|
|
81797
|
+
Only use \`sync push\` when:
|
|
81798
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
81799
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
81800
|
+
|
|
81801
|
+
### After writing — offer to test, don't wait passively
|
|
81802
|
+
|
|
81803
|
+
If the user hasn't already told you to run/test/preview the script, offer it as a one-sentence next step (e.g. "Want me to run \`wmill script preview\` with sample args?"). Do not present a multi-option menu.
|
|
81804
|
+
|
|
81805
|
+
If the user already asked to test/run/try the script in their original request, skip the offer and just execute \`wmill script preview <path> -d '<args>'\` directly — pick plausible args from the script's declared parameters. The shape varies by language: \`main(...)\` for code languages, the SQL dialect's own placeholder syntax (\`$1\` for PostgreSQL, \`?\` for MySQL/Snowflake, \`@P1\` for MSSQL, \`@name\` for BigQuery, etc.), positional \`$1\`, \`$2\`, … for Bash, \`param(...)\` for PowerShell.
|
|
81806
|
+
|
|
81807
|
+
\`wmill script preview\` does not deploy, but it still executes script code and may cause side effects; run it yourself when the user asked to test/preview (or after confirming that execution is intended). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
81808
|
+
|
|
81809
|
+
For a **visual** open-the-script-in-the-dev-page preview (rather than \`script preview\`'s run-and-print-result), use the \`preview\` skill.
|
|
80646
81810
|
|
|
80647
81811
|
Use \`wmill resource-type list --schema\` to discover available resource types.
|
|
80648
81812
|
|
|
@@ -81464,11 +82628,36 @@ description: MUST use when writing R scripts.
|
|
|
81464
82628
|
|
|
81465
82629
|
## CLI Commands
|
|
81466
82630
|
|
|
81467
|
-
Place scripts in a folder.
|
|
81468
|
-
|
|
81469
|
-
|
|
82631
|
+
Place scripts in a folder.
|
|
82632
|
+
|
|
82633
|
+
After writing, tell the user which command fits what they want to do:
|
|
82634
|
+
|
|
82635
|
+
- \`wmill script preview <script_path>\` — **default when iterating on a local script.** Runs the local file without deploying.
|
|
82636
|
+
- \`wmill script run <path>\` — runs the script **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
82637
|
+
- \`wmill generate-metadata\` — generate \`.script.yaml\` and \`.lock\` files for the script you modified.
|
|
82638
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
82639
|
+
|
|
82640
|
+
### Preview vs run — choose by intent, not habit
|
|
82641
|
+
|
|
82642
|
+
If the user says "run the script", "try it", "test it", "does it work" while there are **local edits to the script file**, use \`script preview\`. Do NOT push the script to then \`script run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
82643
|
+
|
|
82644
|
+
Only use \`script run\` when:
|
|
82645
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
82646
|
+
- There is no local script being edited (you're just invoking an existing script).
|
|
82647
|
+
|
|
82648
|
+
Only use \`sync push\` when:
|
|
82649
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
82650
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
82651
|
+
|
|
82652
|
+
### After writing — offer to test, don't wait passively
|
|
82653
|
+
|
|
82654
|
+
If the user hasn't already told you to run/test/preview the script, offer it as a one-sentence next step (e.g. "Want me to run \`wmill script preview\` with sample args?"). Do not present a multi-option menu.
|
|
82655
|
+
|
|
82656
|
+
If the user already asked to test/run/try the script in their original request, skip the offer and just execute \`wmill script preview <path> -d '<args>'\` directly — pick plausible args from the script's declared parameters. The shape varies by language: \`main(...)\` for code languages, the SQL dialect's own placeholder syntax (\`$1\` for PostgreSQL, \`?\` for MySQL/Snowflake, \`@P1\` for MSSQL, \`@name\` for BigQuery, etc.), positional \`$1\`, \`$2\`, … for Bash, \`param(...)\` for PowerShell.
|
|
82657
|
+
|
|
82658
|
+
\`wmill script preview\` does not deploy, but it still executes script code and may cause side effects; run it yourself when the user asked to test/preview (or after confirming that execution is intended). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
81470
82659
|
|
|
81471
|
-
|
|
82660
|
+
For a **visual** open-the-script-in-the-dev-page preview (rather than \`script preview\`'s run-and-print-result), use the \`preview\` skill.
|
|
81472
82661
|
|
|
81473
82662
|
Use \`wmill resource-type list --schema\` to discover available resource types.
|
|
81474
82663
|
|
|
@@ -81565,11 +82754,36 @@ description: MUST use when writing Rust scripts.
|
|
|
81565
82754
|
|
|
81566
82755
|
## CLI Commands
|
|
81567
82756
|
|
|
81568
|
-
Place scripts in a folder.
|
|
81569
|
-
- \`wmill generate-metadata\` - Generate .script.yaml and .lock files
|
|
81570
|
-
- \`wmill sync push\` - Deploy to Windmill
|
|
82757
|
+
Place scripts in a folder.
|
|
81571
82758
|
|
|
81572
|
-
|
|
82759
|
+
After writing, tell the user which command fits what they want to do:
|
|
82760
|
+
|
|
82761
|
+
- \`wmill script preview <script_path>\` — **default when iterating on a local script.** Runs the local file without deploying.
|
|
82762
|
+
- \`wmill script run <path>\` — runs the script **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
82763
|
+
- \`wmill generate-metadata\` — generate \`.script.yaml\` and \`.lock\` files for the script you modified.
|
|
82764
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
82765
|
+
|
|
82766
|
+
### Preview vs run — choose by intent, not habit
|
|
82767
|
+
|
|
82768
|
+
If the user says "run the script", "try it", "test it", "does it work" while there are **local edits to the script file**, use \`script preview\`. Do NOT push the script to then \`script run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
82769
|
+
|
|
82770
|
+
Only use \`script run\` when:
|
|
82771
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
82772
|
+
- There is no local script being edited (you're just invoking an existing script).
|
|
82773
|
+
|
|
82774
|
+
Only use \`sync push\` when:
|
|
82775
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
82776
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
82777
|
+
|
|
82778
|
+
### After writing — offer to test, don't wait passively
|
|
82779
|
+
|
|
82780
|
+
If the user hasn't already told you to run/test/preview the script, offer it as a one-sentence next step (e.g. "Want me to run \`wmill script preview\` with sample args?"). Do not present a multi-option menu.
|
|
82781
|
+
|
|
82782
|
+
If the user already asked to test/run/try the script in their original request, skip the offer and just execute \`wmill script preview <path> -d '<args>'\` directly — pick plausible args from the script's declared parameters. The shape varies by language: \`main(...)\` for code languages, the SQL dialect's own placeholder syntax (\`$1\` for PostgreSQL, \`?\` for MySQL/Snowflake, \`@P1\` for MSSQL, \`@name\` for BigQuery, etc.), positional \`$1\`, \`$2\`, … for Bash, \`param(...)\` for PowerShell.
|
|
82783
|
+
|
|
82784
|
+
\`wmill script preview\` does not deploy, but it still executes script code and may cause side effects; run it yourself when the user asked to test/preview (or after confirming that execution is intended). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
82785
|
+
|
|
82786
|
+
For a **visual** open-the-script-in-the-dev-page preview (rather than \`script preview\`'s run-and-print-result), use the \`preview\` skill.
|
|
81573
82787
|
|
|
81574
82788
|
Use \`wmill resource-type list --schema\` to discover available resource types.
|
|
81575
82789
|
|
|
@@ -81656,11 +82870,36 @@ description: MUST use when writing Snowflake queries.
|
|
|
81656
82870
|
|
|
81657
82871
|
## CLI Commands
|
|
81658
82872
|
|
|
81659
|
-
Place scripts in a folder.
|
|
81660
|
-
|
|
81661
|
-
|
|
82873
|
+
Place scripts in a folder.
|
|
82874
|
+
|
|
82875
|
+
After writing, tell the user which command fits what they want to do:
|
|
82876
|
+
|
|
82877
|
+
- \`wmill script preview <script_path>\` — **default when iterating on a local script.** Runs the local file without deploying.
|
|
82878
|
+
- \`wmill script run <path>\` — runs the script **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
82879
|
+
- \`wmill generate-metadata\` — generate \`.script.yaml\` and \`.lock\` files for the script you modified.
|
|
82880
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
82881
|
+
|
|
82882
|
+
### Preview vs run — choose by intent, not habit
|
|
82883
|
+
|
|
82884
|
+
If the user says "run the script", "try it", "test it", "does it work" while there are **local edits to the script file**, use \`script preview\`. Do NOT push the script to then \`script run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
82885
|
+
|
|
82886
|
+
Only use \`script run\` when:
|
|
82887
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
82888
|
+
- There is no local script being edited (you're just invoking an existing script).
|
|
82889
|
+
|
|
82890
|
+
Only use \`sync push\` when:
|
|
82891
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
82892
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
82893
|
+
|
|
82894
|
+
### After writing — offer to test, don't wait passively
|
|
81662
82895
|
|
|
81663
|
-
|
|
82896
|
+
If the user hasn't already told you to run/test/preview the script, offer it as a one-sentence next step (e.g. "Want me to run \`wmill script preview\` with sample args?"). Do not present a multi-option menu.
|
|
82897
|
+
|
|
82898
|
+
If the user already asked to test/run/try the script in their original request, skip the offer and just execute \`wmill script preview <path> -d '<args>'\` directly — pick plausible args from the script's declared parameters. The shape varies by language: \`main(...)\` for code languages, the SQL dialect's own placeholder syntax (\`$1\` for PostgreSQL, \`?\` for MySQL/Snowflake, \`@P1\` for MSSQL, \`@name\` for BigQuery, etc.), positional \`$1\`, \`$2\`, … for Bash, \`param(...)\` for PowerShell.
|
|
82899
|
+
|
|
82900
|
+
\`wmill script preview\` does not deploy, but it still executes script code and may cause side effects; run it yourself when the user asked to test/preview (or after confirming that execution is intended). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
82901
|
+
|
|
82902
|
+
For a **visual** open-the-script-in-the-dev-page preview (rather than \`script preview\`'s run-and-print-result), use the \`preview\` skill.
|
|
81664
82903
|
|
|
81665
82904
|
Use \`wmill resource-type list --schema\` to discover available resource types.
|
|
81666
82905
|
|
|
@@ -81683,15 +82922,77 @@ description: MUST use when creating flows.
|
|
|
81683
82922
|
|
|
81684
82923
|
# Windmill Flow Building Guide
|
|
81685
82924
|
|
|
81686
|
-
##
|
|
82925
|
+
## Creating a Flow
|
|
82926
|
+
|
|
82927
|
+
**You — the AI agent — scaffold the flow yourself by running \`wmill flow new <path>\` with the right flags. Do NOT hand-create the folder + \`flow.yaml\`, and do NOT tell the user to "run \`wmill flow new\` and follow the prompts".**
|
|
82928
|
+
|
|
82929
|
+
\`wmill flow new\` creates the folder with the correct suffix (\`{{FLOW_SUFFIX}}\` or \`.flow\` depending on the workspace's \`nonDottedPaths\` setting), writes a minimal \`flow.yaml\` shell, and prints Claude-specific next-step hints. Scaffolding by hand skips all of that and often picks the wrong suffix.
|
|
82930
|
+
|
|
82931
|
+
### Step 1 — Gather path + summary by asking the user
|
|
82932
|
+
|
|
82933
|
+
You need two things:
|
|
82934
|
+
|
|
82935
|
+
1. **path** — the windmill path, e.g. \`f/folder/my_flow\` or \`u/username/my_flow\`.
|
|
82936
|
+
2. **summary** — a short description of the flow.
|
|
82937
|
+
|
|
82938
|
+
If the user's request didn't supply both, ask for both in a single round-trip. Use whichever interactive question facility your runtime provides — a structured multi-choice tool if available, otherwise plain chat — and provide one or two example values for each (with an "Other" / free-form fallback). Do not guess paths or summaries.
|
|
82939
|
+
|
|
82940
|
+
### Step 2 — Run the command yourself
|
|
82941
|
+
|
|
82942
|
+
\`\`\`bash
|
|
82943
|
+
wmill flow new f/folder/my_flow --summary "Short description"
|
|
82944
|
+
\`\`\`
|
|
82945
|
+
|
|
82946
|
+
Add \`--description "..."\` when the user provided a longer explanation worth preserving separately from the summary.
|
|
82947
|
+
|
|
82948
|
+
### Step 3 — Fill in \`flow.yaml\`
|
|
82949
|
+
|
|
82950
|
+
Open the generated \`flow.yaml\` (under the folder the command just created) and replace the empty \`value.modules\` + \`schema\` with the real flow definition.
|
|
81687
82951
|
|
|
81688
|
-
Create a folder ending with \`{{FLOW_SUFFIX}}\` and add a \`flow.yaml\` file with the flow definition.
|
|
81689
82952
|
For rawscript modules, use \`!inline path/to/script.ts\` for the content key. {{INLINE_SCRIPT_NAMING}}
|
|
81690
|
-
After writing, tell the user they can run:
|
|
81691
|
-
- \`wmill generate-metadata\` - Generate lock files for the flow you modified
|
|
81692
|
-
- \`wmill sync push\` - Deploy to Windmill
|
|
81693
82953
|
|
|
81694
|
-
|
|
82954
|
+
Once the flow has real content, **offer** to open the visual preview as a one-sentence next step (e.g. "Want me to open the visual preview?"). Don't auto-open — opening the dev page has side effects (browser window, possibly a \`launch.json\` entry) and the user should consent.
|
|
82955
|
+
|
|
82956
|
+
### Anti-patterns to avoid
|
|
82957
|
+
|
|
82958
|
+
- ❌ Hand-creating the \`{{FLOW_SUFFIX}}\` folder + \`flow.yaml\` instead of running \`wmill flow new\`. You'll miss the suffix-setting resolution, the default shape, and the Claude hints.
|
|
82959
|
+
- ❌ Telling the user to "run \`wmill flow new <path>\`" — you can and should run it yourself.
|
|
82960
|
+
- ❌ Inventing a path/summary instead of asking the user.
|
|
82961
|
+
|
|
82962
|
+
## CLI Commands — running, previewing, deploying
|
|
82963
|
+
|
|
82964
|
+
After writing, tell the user which command fits what they want to do:
|
|
82965
|
+
|
|
82966
|
+
- \`wmill flow preview <flow_path>\` — **default when iterating on a local flow.** Runs the local \`flow.yaml\` against local inline scripts without deploying. Add \`--remote\` to use deployed workspace scripts for PathScript steps instead of local files.
|
|
82967
|
+
- \`wmill flow run <path>\` — runs the flow **already deployed** in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.
|
|
82968
|
+
- \`wmill generate-metadata\` — regenerate stale \`.lock\` and \`.script.yaml\` files. By default it scans **scripts, flows, and apps** across the workspace; pass \`--skip-flows --skip-apps\` (or run from a subdirectory) to limit the scope when you only care about the flow you edited.
|
|
82969
|
+
- \`wmill sync push\` — deploy local changes to the workspace. Only suggest/run this when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
|
|
82970
|
+
|
|
82971
|
+
### Preview vs run — choose by intent, not habit
|
|
82972
|
+
|
|
82973
|
+
If the user says "run the flow", "try it", "test it", "does it work" while there are **local edits to a \`flow.yaml\`**, use \`flow preview\`. Do NOT push the flow to then \`flow run\` it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
|
|
82974
|
+
|
|
82975
|
+
Only use \`flow run\` when:
|
|
82976
|
+
- The user explicitly says "run the deployed version" / "run what's on the server".
|
|
82977
|
+
- There is no local \`flow.yaml\` being edited (you're just invoking an existing flow).
|
|
82978
|
+
|
|
82979
|
+
Only use \`sync push\` when:
|
|
82980
|
+
- The user explicitly asks to deploy, publish, push, or ship.
|
|
82981
|
+
- The preview has already validated the change and the user wants it in the workspace.
|
|
82982
|
+
|
|
82983
|
+
### After writing — offer to run, don't wait passively
|
|
82984
|
+
|
|
82985
|
+
This is about **programmatic execution** (\`wmill flow preview -d '<args>'\`), which actually runs the flow and has side effects. Visual preview (the \`preview\` skill) is offered separately — see "Visual preview" below.
|
|
82986
|
+
|
|
82987
|
+
If the user hasn't already told you to run/test the flow, offer it as a one-sentence next step (e.g. "Want me to run \`wmill flow preview\` with sample args?"). Do not present a multi-option menu.
|
|
82988
|
+
|
|
82989
|
+
If the user already asked to test/run/try the flow in their original request, skip the offer and just execute \`wmill flow preview <path> -d '<args>'\` directly — pick plausible args from the flow's input schema.
|
|
82990
|
+
|
|
82991
|
+
\`wmill flow preview\` is safe to run yourself (it does not deploy). \`wmill sync push\` and \`wmill generate-metadata\` modify workspace state or local files — only run these when the user explicitly asks; otherwise tell them which to run.
|
|
82992
|
+
|
|
82993
|
+
### Visual preview
|
|
82994
|
+
|
|
82995
|
+
To open the flow visually in the dev page (graph + live reload), use the \`preview\` skill. Always **offer** it as a one-sentence next step (e.g. "Want me to open the visual preview?") rather than opening it automatically — opening the dev page has side effects (browser window, possibly a \`launch.json\` entry under MCP-preview branches) the user should consent to. If the user already asked to see/preview/visualize the flow in their original request, skip the offer and just invoke the skill.
|
|
81695
82996
|
|
|
81696
82997
|
## OpenFlow Schema
|
|
81697
82998
|
|
|
@@ -82000,11 +83301,70 @@ Raw apps let you build custom frontends with React, Svelte, or Vue that connect
|
|
|
82000
83301
|
|
|
82001
83302
|
## Creating a Raw App
|
|
82002
83303
|
|
|
83304
|
+
**You — the AI agent — create the app yourself by running \`wmill app new\` with the right flags. Do NOT tell the user to "run \`wmill app new\` and follow the prompts" or wait for them to do it.** The bare \`wmill app new\` is an interactive wizard that hangs waiting for stdin in any non-TTY context (which includes you). Always pass flags.
|
|
83305
|
+
|
|
83306
|
+
### Step 1 — Gather the three required values by asking the user
|
|
83307
|
+
|
|
83308
|
+
You need three things to run the command:
|
|
83309
|
+
|
|
83310
|
+
1. **summary** — a short description of the app
|
|
83311
|
+
2. **path** — the windmill path, e.g. \`f/folder/my_app\` or \`u/username/my_app\`
|
|
83312
|
+
3. **framework** — one of \`react19\` (recommended), \`react18\`, \`svelte5\`, \`vue\`
|
|
83313
|
+
|
|
83314
|
+
If the user's request did not supply *every* one of these explicitly, ask. Do not guess values, do not invent paths, do not pick a framework on the user's behalf, do not "just use react19 because it's the default".
|
|
83315
|
+
|
|
83316
|
+
Use whichever interactive question facility your runtime provides — a structured multi-choice tool if available, otherwise plain chat — and group all missing fields into a single round-trip so the user answers them at once:
|
|
83317
|
+
|
|
83318
|
+
- For \`framework\` — multiple-choice with the four allowed values; mark \`react19\` as \`(Recommended)\` and put it first.
|
|
83319
|
+
- For \`summary\` and \`path\` — provide one or two example values as multiple-choice options (the user can pick "Other" to type a free-form answer).
|
|
83320
|
+
|
|
83321
|
+
Only proceed once you have concrete values for all three. If the user replies with something ambiguous, ask again rather than guessing.
|
|
83322
|
+
|
|
83323
|
+
### Step 2 — Run the command yourself
|
|
83324
|
+
|
|
83325
|
+
Once you have summary + path + framework, run it:
|
|
83326
|
+
|
|
83327
|
+
\`\`\`bash
|
|
83328
|
+
wmill app new \\
|
|
83329
|
+
--summary "Customer dashboard" \\
|
|
83330
|
+
--path f/sales/dashboard \\
|
|
83331
|
+
--framework react19
|
|
83332
|
+
\`\`\`
|
|
83333
|
+
|
|
83334
|
+
That's the minimum. The datatable wizard and the "Open in Claude Desktop?" prompt are skipped silently because passing any of \`--summary\`/\`--path\`/\`--framework\` puts the command in non-interactive mode.
|
|
83335
|
+
|
|
83336
|
+
### Optional flags
|
|
83337
|
+
|
|
83338
|
+
Layer these in only when the user asked for them:
|
|
83339
|
+
|
|
83340
|
+
| Flag | When to add it |
|
|
83341
|
+
|---|---|
|
|
83342
|
+
| \`--datatable <name>\` | The user wants this app wired to a specific Windmill datatable. Without it, the app is created with no datatable. |
|
|
83343
|
+
| \`--schema <name>\` | Together with \`--datatable\`. Creates the schema with \`CREATE SCHEMA IF NOT EXISTS\` if it doesn't already exist. |
|
|
83344
|
+
| \`--overwrite\` | The target directory already exists and the user said it's OK to replace. Without it, non-interactive mode aborts with an error so you don't clobber existing work. |
|
|
83345
|
+
| \`--no-open-in-desktop\` | Already implied in non-interactive mode; only needed if you're somehow running interactively. |
|
|
83346
|
+
|
|
83347
|
+
### Step 3 — Offer the visual preview
|
|
83348
|
+
|
|
83349
|
+
After \`wmill app new\` and any initial edits to \`App.tsx\` / \`index.tsx\`, **offer** to open the visual preview as a one-sentence next step (e.g. "Want me to open the visual preview?"). Don't auto-open — opening the dev page has side effects (browser window, possibly a \`launch.json\` entry when an embedded preview tool is in play) the user should consent to.
|
|
83350
|
+
|
|
83351
|
+
For apps the preview command runs from the app folder (\`cd <app_path>__raw_app && wmill app dev …\`); the \`preview\` skill picks the proxy vs direct branch based on whether the runtime exposes a tool that can embed a localhost URL. If the user already asked to see/preview/visualize the app in their original request, skip the offer and just invoke the skill.
|
|
83352
|
+
|
|
83353
|
+
### Anti-patterns to avoid
|
|
83354
|
+
|
|
83355
|
+
- ❌ Running \`wmill app new\` with no flags (the prompt will hang).
|
|
83356
|
+
- ❌ Telling the user to "run \`wmill app new\` and follow the prompts" — that's a step backwards from what you can do directly.
|
|
83357
|
+
- ❌ Inventing a path/summary/framework instead of asking the user.
|
|
83358
|
+
- ❌ Defaulting to \`react19\` because the user didn't say — even sensible defaults must be confirmed.
|
|
83359
|
+
- ❌ Passing \`--overwrite\` automatically when the directory exists — confirm with the user first.
|
|
83360
|
+
|
|
83361
|
+
### Interactive (only when a human is at the terminal)
|
|
83362
|
+
|
|
82003
83363
|
\`\`\`bash
|
|
82004
83364
|
wmill app new
|
|
82005
83365
|
\`\`\`
|
|
82006
83366
|
|
|
82007
|
-
This
|
|
83367
|
+
This is the wizard. It only works when run by a human in a real terminal. Don't call it this way from an agent.
|
|
82008
83368
|
|
|
82009
83369
|
## App Structure
|
|
82010
83370
|
|
|
@@ -82228,12 +83588,13 @@ data:
|
|
|
82228
83588
|
|
|
82229
83589
|
## CLI Commands
|
|
82230
83590
|
|
|
82231
|
-
|
|
83591
|
+
\`wmill app new\` is the exception: you run it yourself, with flags, per the "Creating a Raw App" section above.
|
|
83592
|
+
|
|
83593
|
+
For everything else, tell the user which command fits their intent and let them run it — these touch the workspace or local lock files, and the user should consent each time:
|
|
82232
83594
|
|
|
82233
83595
|
| Command | Description |
|
|
82234
83596
|
|---------|-------------|
|
|
82235
|
-
| \`wmill app
|
|
82236
|
-
| \`wmill app dev\` | Start dev server with live reload |
|
|
83597
|
+
| \`wmill app dev\` | Start dev server with live reload (see the \`preview\` skill for the full open-the-app-in-the-IDE-pane procedure). |
|
|
82237
83598
|
| \`wmill app generate-agents\` | Refresh AGENTS.md and DATATABLES.md |
|
|
82238
83599
|
| \`wmill generate-metadata\` | Generate lock files for backend runnables |
|
|
82239
83600
|
| \`wmill sync push\` | Deploy app to Windmill |
|
|
@@ -82622,6 +83983,13 @@ app related commands
|
|
|
82622
83983
|
- \`app lint [app_folder:string]\` - Lint a raw app folder to validate structure and buildability
|
|
82623
83984
|
- \`--fix\` - Attempt to fix common issues (not implemented yet)
|
|
82624
83985
|
- \`app new\` - create a new raw app from a template
|
|
83986
|
+
- \`--summary <summary:string>\` - App summary (short description). Skips the prompt when provided. Triggers non-interactive mode.
|
|
83987
|
+
- \`--path <path:string>\` - App path (e.g., f/folder/my_app or u/username/my_app). Skips the prompt when provided. Triggers non-interactive mode.
|
|
83988
|
+
- \`--framework <framework:string>\` - Framework template: react19 | react18 | svelte5 | vue. Skips the prompt when provided. Triggers non-interactive mode.
|
|
83989
|
+
- \`--datatable <datatable:string>\` - Datatable to wire up. Without this flag in non-interactive mode, no datatable is configured.
|
|
83990
|
+
- \`--schema <schema:string>\` - Schema to use with --datatable. Created (CREATE SCHEMA IF NOT EXISTS) if it doesn't already exist.
|
|
83991
|
+
- \`--overwrite\` - Overwrite the target directory if it already exists, without prompting.
|
|
83992
|
+
- \`--no-open-in-desktop\` - Do not prompt to open the new app in Claude Desktop.
|
|
82625
83993
|
- \`app generate-agents [app_folder:string]\` - regenerate AGENTS.md and DATATABLES.md from remote workspace
|
|
82626
83994
|
- \`app set-permissioned-as <path:string> <email:string>\` - Set the on_behalf_of_email for an app (requires admin or wm_deployers group)
|
|
82627
83995
|
|
|
@@ -82658,10 +84026,13 @@ workspace dependencies related commands
|
|
|
82658
84026
|
|
|
82659
84027
|
### dev
|
|
82660
84028
|
|
|
82661
|
-
|
|
84029
|
+
Watch local file changes and live-reload the dev page for preview. Does NOT deploy to the remote workspace — use wmill sync push for that.
|
|
82662
84030
|
|
|
82663
84031
|
**Options:**
|
|
82664
|
-
- \`--includes <pattern...:string>\` - Filter paths
|
|
84032
|
+
- \`--includes <pattern...:string>\` - Filter paths given a glob pattern or path
|
|
84033
|
+
- \`--proxy-port <port:number>\` - Port for a localhost reverse proxy to the remote Windmill server
|
|
84034
|
+
- \`--path <path:string>\` - Watch a specific windmill path (e.g., u/admin/my_script or f/my_flow)
|
|
84035
|
+
- \`--no-open\` - Do not open the browser automatically
|
|
82665
84036
|
|
|
82666
84037
|
### docs
|
|
82667
84038
|
|
|
@@ -83207,6 +84578,133 @@ workspace related commands
|
|
|
83207
84578
|
- \`--team-name <team_name:string>\` - Slack team name
|
|
83208
84579
|
- \`workspace disconnect-slack\`
|
|
83209
84580
|
|
|
84581
|
+
`,
|
|
84582
|
+
preview: `---
|
|
84583
|
+
name: preview
|
|
84584
|
+
description: MUST use when opening the Windmill dev page / visual preview of a flow, script, or app. Triggers on words like preview, open, navigate to, visualize, see the flow/app/script, and after writing a flow/script/app for visual verification.
|
|
84585
|
+
---
|
|
84586
|
+
|
|
84587
|
+
# Windmill Preview Workflow
|
|
84588
|
+
|
|
84589
|
+
Use this skill any time the user wants to **see**, **open**, **navigate to**, **visualize**, or **preview** a flow, script, or app — and any time you've just finished writing one and want to offer visual verification.
|
|
84590
|
+
|
|
84591
|
+
The Windmill dev page renders the flow graph / script editor, lets the user step through steps, and live-reloads on every save. It runs locally via \`wmill dev\` and is reached on a localhost port.
|
|
84592
|
+
|
|
84593
|
+
## Two independent decisions
|
|
84594
|
+
|
|
84595
|
+
### 1. Mode: proxy or direct?
|
|
84596
|
+
|
|
84597
|
+
\`wmill dev\` runs in two modes; pick by asking what kind of URL whatever will display the preview needs.
|
|
84598
|
+
|
|
84599
|
+
- **Proxy** (\`--proxy-port <port>\`) — exposes the dev page on \`http://localhost:<port>/\`. Use it when the embedder you'll hand the URL to **only accepts localhost URLs** (most in-IDE / in-chat preview embedders do, because they sandbox cross-origin loads).
|
|
84600
|
+
- **Direct** (default) — the user's browser loads the dev page from the remote workspace's HTTPS URL; the local \`wmill dev\` only runs the WebSocket back-channel for live reload. Use it when the URL will be opened in a regular browser tab.
|
|
84601
|
+
|
|
84602
|
+
Default to **direct** unless you have a specific embedder that needs localhost.
|
|
84603
|
+
|
|
84604
|
+
### 2. Who starts the server?
|
|
84605
|
+
|
|
84606
|
+
- **You start it** in the background. Spawn \`wmill dev …\` (or \`wmill app dev …\`) yourself, capture the URL it prints, do whatever's next (open a tab, hand the URL to an embedder).
|
|
84607
|
+
- **The runtime starts it from \`.claude/launch.json\`.** Some runtimes (currently the Claude Desktop / Claude Code MCP preview integration — tools prefixed with \`mcp__Claude_Preview__\`) can read a \`launch.json\` configuration and launch the dev server on demand when you invoke their preview tool. **Only take this path if you actually have such a tool** — otherwise nothing reads the file and \`wmill dev\` never starts.
|
|
84608
|
+
|
|
84609
|
+
The two decisions compose. The common cases:
|
|
84610
|
+
|
|
84611
|
+
| Embedder | Needs localhost? | launch.json runtime? | What to do |
|
|
84612
|
+
|---|---|---|---|
|
|
84613
|
+
| Regular browser tab | No | n/a | Direct mode, you start it, give URL to user |
|
|
84614
|
+
| IDE / chat preview pane that takes any URL | No | No | Direct mode, you start it, point the embedder at the printed URL |
|
|
84615
|
+
| IDE / chat preview pane that only accepts localhost | Yes | No | Proxy mode, you start it, point the embedder at \`http://localhost:<port>/\` |
|
|
84616
|
+
| Claude Desktop / Code MCP preview | Yes | Yes | Proxy mode, write a \`launch.json\` entry, invoke the MCP tool |
|
|
84617
|
+
|
|
84618
|
+
Never start the proxy "just in case" — it adds the localhost hop for no benefit when no embedder needs it.
|
|
84619
|
+
|
|
84620
|
+
## Starting the server yourself
|
|
84621
|
+
|
|
84622
|
+
Use this when no \`launch.json\`-aware runtime is available, regardless of mode.
|
|
84623
|
+
|
|
84624
|
+
For flows / scripts:
|
|
84625
|
+
\`\`\`bash
|
|
84626
|
+
# Direct mode — gives you the remote dev-page URL
|
|
84627
|
+
wmill dev --path <wmill_path> --no-open
|
|
84628
|
+
|
|
84629
|
+
# Proxy mode — gives you a localhost URL that 302s to the remote dev page
|
|
84630
|
+
wmill dev --proxy-port 4000 --path <wmill_path> --no-open
|
|
84631
|
+
\`\`\`
|
|
84632
|
+
|
|
84633
|
+
For apps:
|
|
84634
|
+
\`\`\`bash
|
|
84635
|
+
cd <app_path>__raw_app && wmill app dev --no-open --port 4000
|
|
84636
|
+
\`\`\`
|
|
84637
|
+
|
|
84638
|
+
Each command prints the URL on stdout. Line shapes differ:
|
|
84639
|
+
|
|
84640
|
+
- \`wmill dev --no-open\` (direct) prints \`Go to <url>\` with the full remote URL (workspace, token, path baked in).
|
|
84641
|
+
- \`wmill dev --proxy-port\` prints \`Dev proxy listening on http://localhost:<port>\` — the URL to hand to an embedder is \`http://localhost:<port>/\`.
|
|
84642
|
+
- \`wmill app dev --no-open\` prints \`\uD83D\uDE80 Dev server running at <url>\` — the local app server.
|
|
84643
|
+
|
|
84644
|
+
Capture the URL with a loose match (the first \`https?://…\` token after startup) and either hand it to your embedder or relay it to the user: *"Preview is running — open \`<url>\` in your browser."* Don't construct the URL yourself; you don't have the workspace ID or auth token.
|
|
84645
|
+
|
|
84646
|
+
These commands are long-running — start them in the background, don't block waiting.
|
|
84647
|
+
|
|
84648
|
+
## Letting \`launch.json\` start the server (Claude Desktop / Code MCP only)
|
|
84649
|
+
|
|
84650
|
+
Take this path when **and only when** an \`mcp__Claude_Preview__*\` MCP tool is exposed in your tool list. Skip it otherwise — without an MCP tool reading the file, \`wmill dev\` never starts.
|
|
84651
|
+
|
|
84652
|
+
**Each flow / script / app gets its own named entry** in the user's \`.claude/launch.json\` so multiple previews coexist without colliding — each entry pins a different port + path. Never reuse a generic "windmill" entry for different targets.
|
|
84653
|
+
|
|
84654
|
+
### Step 1 — Reuse or add a per-target entry in \`.claude/launch.json\`
|
|
84655
|
+
|
|
84656
|
+
Convention: name the entry \`windmill: <wmill_path>\` (e.g. \`windmill: f/test/my_flow\`).
|
|
84657
|
+
|
|
84658
|
+
- **Entry already exists** → reuse it; note its \`port\` for the next step.
|
|
84659
|
+
- **Not there** → add one. Pick a port not already taken by another entry (start at 4000 and bump). Shape:
|
|
84660
|
+
|
|
84661
|
+
For flows / scripts:
|
|
84662
|
+
\`\`\`json
|
|
84663
|
+
{
|
|
84664
|
+
"name": "windmill: f/test/my_flow",
|
|
84665
|
+
"runtimeExecutable": "bash",
|
|
84666
|
+
"runtimeArgs": ["-c", "wmill dev --proxy-port \${PORT:-4000} --path f/test/my_flow --no-open"],
|
|
84667
|
+
"port": 4000,
|
|
84668
|
+
"autoPort": true
|
|
84669
|
+
}
|
|
84670
|
+
\`\`\`
|
|
84671
|
+
|
|
84672
|
+
For apps (\`*__raw_app/\`), \`wmill app dev\` is the equivalent — runs from the app folder, no \`--path\`:
|
|
84673
|
+
\`\`\`json
|
|
84674
|
+
{
|
|
84675
|
+
"name": "windmill: f/test/my_app",
|
|
84676
|
+
"runtimeExecutable": "bash",
|
|
84677
|
+
"runtimeArgs": ["-c", "cd f/test/my_app__raw_app && wmill app dev --no-open --port \${PORT:-4001}"],
|
|
84678
|
+
"port": 4001,
|
|
84679
|
+
"autoPort": true
|
|
84680
|
+
}
|
|
84681
|
+
\`\`\`
|
|
84682
|
+
|
|
84683
|
+
If \`.claude/launch.json\` doesn't exist yet, create it with the standard shell \`{ "version": "0.0.1", "configurations": [...] }\`.
|
|
84684
|
+
|
|
84685
|
+
### Step 2 — Invoke the MCP preview tool
|
|
84686
|
+
|
|
84687
|
+
Point it at the entry you just added/found. Use \`http://localhost:<port>/\` as the URL — the proxy's redirect at \`/\` is what appends the workspace ID, the auth token, and the path. Do **NOT** construct a \`/dev?...\` URL yourself.
|
|
84688
|
+
|
|
84689
|
+
The MCP tool launches the configuration on demand, so you don't need to start the \`wmill dev\` process manually.
|
|
84690
|
+
|
|
84691
|
+
## Non-visual alternative
|
|
84692
|
+
|
|
84693
|
+
If the user wants a programmatic test rather than a visual one:
|
|
84694
|
+
- Flow: \`wmill flow preview <path> -d '<args>'\`
|
|
84695
|
+
- Script: \`wmill script preview <path> -d '<args>'\`
|
|
84696
|
+
|
|
84697
|
+
Both print the job result, are safe to run yourself, and don't deploy.
|
|
84698
|
+
|
|
84699
|
+
## Anti-patterns to avoid
|
|
84700
|
+
|
|
84701
|
+
- ❌ Writing a \`.claude/launch.json\` entry when no \`mcp__Claude_Preview__*\` tool is in your tool list. Nothing will read the file; the server never starts. Spawn \`wmill dev\` yourself instead.
|
|
84702
|
+
- ❌ Starting the proxy when no embedder needs a localhost URL. Direct mode is the right choice — the proxy is overhead with no purpose.
|
|
84703
|
+
- ❌ Reusing a single generic \`launch.json\` entry for every preview target. Each flow/script/app gets its own named entry on its own port — that's how multiple sessions coexist without one preview clobbering another.
|
|
84704
|
+
- ❌ Mutating an existing entry's \`--path\` to retarget it. Add a new entry instead.
|
|
84705
|
+
- ❌ Constructing \`http://localhost:<port>/dev?path=<X>\` yourself. The proxy's \`/\` redirect is what appends the workspace ID and auth token; bypassing it gives a broken page. Always use \`http://localhost:<port>/\`.
|
|
84706
|
+
- ❌ Starting \`wmill dev\` in the foreground (you'll hang). Always background.
|
|
84707
|
+
- ❌ Listing both "open in IDE pane" and "open in browser" as a menu — pick one based on context.
|
|
83210
84708
|
`
|
|
83211
84709
|
};
|
|
83212
84710
|
var SCHEMAS = {
|
|
@@ -84234,16 +85732,17 @@ var WMILL_INIT_AI_AGENTS_SOURCE_ENV = "WMILL_INIT_AI_AGENTS_SOURCE";
|
|
|
84234
85732
|
var WMILL_INIT_AI_CLAUDE_SOURCE_ENV = "WMILL_INIT_AI_CLAUDE_SOURCE";
|
|
84235
85733
|
var CLAUDE_MD_DEFAULT = `Instructions are in @AGENTS.md
|
|
84236
85734
|
`;
|
|
85735
|
+
var SKILL_TARGET_ROOTS = [".claude", ".agents"];
|
|
84237
85736
|
async function writeAiGuidanceFiles(options) {
|
|
84238
85737
|
const nonDottedPaths = options.nonDottedPaths ?? true;
|
|
84239
85738
|
const skillMetadata = options.skillsSourcePath ? await readSkillMetadataFromDirectory(options.skillsSourcePath) : getGeneratedSkillMetadata();
|
|
84240
85739
|
const agentsWritten = await writeProjectGuidanceFile({
|
|
84241
|
-
targetPath:
|
|
85740
|
+
targetPath: join18(options.targetDir, "AGENTS.md"),
|
|
84242
85741
|
overwrite: options.overwriteProjectGuidance ?? false,
|
|
84243
85742
|
content: options.agentsSourcePath != null ? await readTextFile(options.agentsSourcePath) : generateAgentsMdContent(buildSkillsReference(skillMetadata))
|
|
84244
85743
|
});
|
|
84245
85744
|
const claudeWritten = await writeProjectGuidanceFile({
|
|
84246
|
-
targetPath:
|
|
85745
|
+
targetPath: join18(options.targetDir, "CLAUDE.md"),
|
|
84247
85746
|
overwrite: options.overwriteProjectGuidance ?? false,
|
|
84248
85747
|
content: options.claudeSourcePath != null ? await readTextFile(options.claudeSourcePath) : CLAUDE_MD_DEFAULT
|
|
84249
85748
|
});
|
|
@@ -84263,17 +85762,17 @@ function buildSkillsReference(skills) {
|
|
|
84263
85762
|
`);
|
|
84264
85763
|
}
|
|
84265
85764
|
async function copySkillsFromSource(targetDir, skillsSourcePath) {
|
|
84266
|
-
const
|
|
84267
|
-
await copyDirectoryContents(skillsSourcePath, skillsDir);
|
|
84268
|
-
return await readSkillMetadataFromDirectory(
|
|
85765
|
+
const skillsDirs = await ensureSkillsDirectories(targetDir);
|
|
85766
|
+
await Promise.all(skillsDirs.map((skillsDir) => copyDirectoryContents(skillsSourcePath, skillsDir)));
|
|
85767
|
+
return await readSkillMetadataFromDirectory(skillsDirs[0]);
|
|
84269
85768
|
}
|
|
84270
85769
|
async function writeGeneratedSkills(targetDir, nonDottedPaths) {
|
|
84271
|
-
const
|
|
84272
|
-
await Promise.all(SKILLS.map(async (skill) => {
|
|
84273
|
-
const skillDir =
|
|
85770
|
+
const skillsDirs = await ensureSkillsDirectories(targetDir);
|
|
85771
|
+
await Promise.all(skillsDirs.flatMap((skillsDir) => SKILLS.map(async (skill) => {
|
|
85772
|
+
const skillDir = join18(skillsDir, skill.name);
|
|
84274
85773
|
await mkdir13(skillDir, { recursive: true });
|
|
84275
|
-
await
|
|
84276
|
-
}));
|
|
85774
|
+
await writeFile20(join18(skillDir, "SKILL.md"), renderGeneratedSkillContent(skill.name, nonDottedPaths), "utf8");
|
|
85775
|
+
})));
|
|
84277
85776
|
return SKILLS.map((skill) => ({
|
|
84278
85777
|
...skill,
|
|
84279
85778
|
directoryName: skill.name
|
|
@@ -84285,15 +85784,15 @@ function getGeneratedSkillMetadata() {
|
|
|
84285
85784
|
directoryName: skill.name
|
|
84286
85785
|
}));
|
|
84287
85786
|
}
|
|
84288
|
-
async function
|
|
84289
|
-
const
|
|
84290
|
-
await mkdir13(skillsDir, { recursive: true });
|
|
84291
|
-
return
|
|
85787
|
+
async function ensureSkillsDirectories(targetDir) {
|
|
85788
|
+
const skillsDirs = SKILL_TARGET_ROOTS.map((root) => join18(targetDir, root, "skills"));
|
|
85789
|
+
await Promise.all(skillsDirs.map((skillsDir) => mkdir13(skillsDir, { recursive: true })));
|
|
85790
|
+
return skillsDirs;
|
|
84292
85791
|
}
|
|
84293
85792
|
async function copyDirectoryContents(sourceDir, targetDir) {
|
|
84294
|
-
const entries = await
|
|
85793
|
+
const entries = await readdir11(sourceDir, { withFileTypes: true });
|
|
84295
85794
|
await Promise.all(entries.map(async (entry) => {
|
|
84296
|
-
await cp(
|
|
85795
|
+
await cp(join18(sourceDir, entry.name), join18(targetDir, entry.name), {
|
|
84297
85796
|
recursive: true,
|
|
84298
85797
|
force: true
|
|
84299
85798
|
});
|
|
@@ -84330,14 +85829,14 @@ ${schemaDocs.join(`
|
|
|
84330
85829
|
`)}`;
|
|
84331
85830
|
}
|
|
84332
85831
|
async function readSkillMetadataFromDirectory(skillsDir) {
|
|
84333
|
-
const entries = await
|
|
85832
|
+
const entries = await readdir11(skillsDir, { withFileTypes: true });
|
|
84334
85833
|
const skills = [];
|
|
84335
85834
|
for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
|
|
84336
85835
|
if (!entry.isDirectory()) {
|
|
84337
85836
|
continue;
|
|
84338
85837
|
}
|
|
84339
|
-
const skillPath =
|
|
84340
|
-
if (!await
|
|
85838
|
+
const skillPath = join18(skillsDir, entry.name, "SKILL.md");
|
|
85839
|
+
if (!await stat18(skillPath).catch(() => null)) {
|
|
84341
85840
|
continue;
|
|
84342
85841
|
}
|
|
84343
85842
|
const content = await readTextFile(skillPath);
|
|
@@ -84373,10 +85872,10 @@ function parseSkillMetadata(content, fallbackName) {
|
|
|
84373
85872
|
return { name, description, directoryName: fallbackName };
|
|
84374
85873
|
}
|
|
84375
85874
|
async function writeProjectGuidanceFile(options) {
|
|
84376
|
-
if (!options.overwrite && await
|
|
85875
|
+
if (!options.overwrite && await stat18(options.targetPath).catch(() => null)) {
|
|
84377
85876
|
return false;
|
|
84378
85877
|
}
|
|
84379
|
-
await
|
|
85878
|
+
await writeFile20(options.targetPath, options.content, "utf8");
|
|
84380
85879
|
return true;
|
|
84381
85880
|
}
|
|
84382
85881
|
function formatSchemaForMarkdown(schemaYaml, schemaName, filePattern) {
|
|
@@ -84860,7 +86359,7 @@ function formatConfigReferenceJson() {
|
|
|
84860
86359
|
async function initAction(opts) {
|
|
84861
86360
|
let didBindWorkspace = false;
|
|
84862
86361
|
let boundProfile;
|
|
84863
|
-
if (await
|
|
86362
|
+
if (await stat19("wmill.yaml").catch(() => null)) {
|
|
84864
86363
|
info("wmill.yaml already exists, skipping config generation");
|
|
84865
86364
|
} else {
|
|
84866
86365
|
const { isGitRepository: isGitRepository2, getCurrentGitBranch: getCurrentGitBranch2 } = await Promise.resolve().then(() => (init_git(), exports_git));
|
|
@@ -84886,13 +86385,16 @@ async function initAction(opts) {
|
|
|
84886
86385
|
selectedProfile = profiles.length > 0 ? await getActiveWorkspace(opts) : undefined;
|
|
84887
86386
|
} else {
|
|
84888
86387
|
const activeProfile = await getActiveWorkspace(opts);
|
|
86388
|
+
const orderedProfiles = activeProfile ? [
|
|
86389
|
+
...profiles.filter((p) => p.name === activeProfile.name),
|
|
86390
|
+
...profiles.filter((p) => p.name !== activeProfile.name)
|
|
86391
|
+
] : profiles;
|
|
84889
86392
|
const selectedName = await Select.prompt({
|
|
84890
86393
|
message: "Select workspace profile",
|
|
84891
|
-
options:
|
|
84892
|
-
name: `${p.name} (${p.workspaceId} on ${p.remote})`,
|
|
86394
|
+
options: orderedProfiles.map((p) => ({
|
|
86395
|
+
name: `${p.name} (${p.workspaceId} on ${p.remote})${activeProfile?.name === p.name ? " — active" : ""}`,
|
|
84893
86396
|
value: p.name
|
|
84894
|
-
}))
|
|
84895
|
-
default: activeProfile?.name
|
|
86397
|
+
}))
|
|
84896
86398
|
});
|
|
84897
86399
|
selectedProfile = profiles.find((p) => p.name === selectedName);
|
|
84898
86400
|
}
|
|
@@ -84932,7 +86434,7 @@ async function initAction(opts) {
|
|
|
84932
86434
|
boundProfile = activeWorkspace;
|
|
84933
86435
|
}
|
|
84934
86436
|
}
|
|
84935
|
-
await
|
|
86437
|
+
await writeFile21("wmill.yaml", generateCommentedTemplate(branchName, undefined, wsBindings), "utf-8");
|
|
84936
86438
|
info(colors.green("wmill.yaml created with default settings"));
|
|
84937
86439
|
if (wsBindings && wsBindings.length > 0) {
|
|
84938
86440
|
didBindWorkspace = true;
|
|
@@ -84967,8 +86469,8 @@ async function initAction(opts) {
|
|
|
84967
86469
|
});
|
|
84968
86470
|
if (choice === "cancel") {
|
|
84969
86471
|
try {
|
|
84970
|
-
await
|
|
84971
|
-
await
|
|
86472
|
+
await rm5("wmill.yaml");
|
|
86473
|
+
await rm5("wmill-lock.yaml");
|
|
84972
86474
|
} catch {}
|
|
84973
86475
|
info("Init cancelled");
|
|
84974
86476
|
process.exit(0);
|
|
@@ -85018,7 +86520,7 @@ async function initAction(opts) {
|
|
|
85018
86520
|
if (guidanceResult.claudeWritten) {
|
|
85019
86521
|
info(colors.green("Created CLAUDE.md"));
|
|
85020
86522
|
}
|
|
85021
|
-
info(colors.green(`Created .claude/skills/ with ${guidanceResult.skillCount} skills`));
|
|
86523
|
+
info(colors.green(`Created .claude/skills/ and .agents/skills/ with ${guidanceResult.skillCount} skills`));
|
|
85022
86524
|
} catch (error2) {
|
|
85023
86525
|
if (error2 instanceof Error) {
|
|
85024
86526
|
warn(`Could not create guidance files: ${error2.message}`);
|
|
@@ -85053,7 +86555,7 @@ await __promiseAll([
|
|
|
85053
86555
|
init_conf(),
|
|
85054
86556
|
init_utils()
|
|
85055
86557
|
]);
|
|
85056
|
-
import * as
|
|
86558
|
+
import * as fs14 from "node:fs/promises";
|
|
85057
86559
|
async function pullJobs(opts, workspace) {
|
|
85058
86560
|
opts = await mergeConfigWithConfigFile(opts);
|
|
85059
86561
|
const ws = await resolveWorkspace({ ...opts, workspace });
|
|
@@ -85097,7 +86599,7 @@ Warning: Found ${workers.length} active worker(s) on the instance.`));
|
|
|
85097
86599
|
page++;
|
|
85098
86600
|
}
|
|
85099
86601
|
const completedPath = opts.completedOutput || "completed_jobs.json";
|
|
85100
|
-
await
|
|
86602
|
+
await fs14.writeFile(completedPath, JSON.stringify(completedJobs, null, 2));
|
|
85101
86603
|
info(colors.green(`Successfully pulled ${completedJobs.length} completed jobs to ${completedPath}`));
|
|
85102
86604
|
let queuedJobs = [];
|
|
85103
86605
|
page = 1;
|
|
@@ -85115,7 +86617,7 @@ Warning: Found ${workers.length} active worker(s) on the instance.`));
|
|
|
85115
86617
|
page++;
|
|
85116
86618
|
}
|
|
85117
86619
|
const queuedPath = opts.queuedOutput || "queued_jobs.json";
|
|
85118
|
-
await
|
|
86620
|
+
await fs14.writeFile(queuedPath, JSON.stringify(queuedJobs, null, 2));
|
|
85119
86621
|
info(colors.green(`Successfully pulled ${queuedJobs.length} queued jobs to ${queuedPath}`));
|
|
85120
86622
|
const allJobs = [...queuedJobs, ...completedJobs];
|
|
85121
86623
|
if (allJobs.length > 0) {
|
|
@@ -85990,8 +87492,8 @@ async function generateMetadata2(opts, folder) {
|
|
|
85990
87492
|
info("");
|
|
85991
87493
|
if (errors.length > 0) {
|
|
85992
87494
|
info(`Done. Updated ${colors.bold(String(succeeded))}/${total} item(s). ${colors.red(String(errors.length) + " failed")}:`);
|
|
85993
|
-
for (const { path:
|
|
85994
|
-
error(` ${
|
|
87495
|
+
for (const { path: path21, error: error2 } of errors) {
|
|
87496
|
+
error(` ${path21}: ${error2}`);
|
|
85995
87497
|
}
|
|
85996
87498
|
process.exitCode = 1;
|
|
85997
87499
|
} else {
|
|
@@ -86078,8 +87580,8 @@ var docs_default = command34;
|
|
|
86078
87580
|
init_mod3();
|
|
86079
87581
|
init_log();
|
|
86080
87582
|
init_colors2();
|
|
86081
|
-
var
|
|
86082
|
-
import { writeFile as
|
|
87583
|
+
var import_yaml41 = __toESM(require_dist(), 1);
|
|
87584
|
+
import { writeFile as writeFile23 } from "node:fs/promises";
|
|
86083
87585
|
await __promiseAll([
|
|
86084
87586
|
init_conf(),
|
|
86085
87587
|
init_yaml()
|
|
@@ -86133,7 +87635,7 @@ async function migrateAction() {
|
|
|
86133
87635
|
} else {
|
|
86134
87636
|
newConf.workspaces = workspaces;
|
|
86135
87637
|
}
|
|
86136
|
-
await
|
|
87638
|
+
await writeFile23(wmillYamlPath, import_yaml41.stringify(newConf), "utf-8");
|
|
86137
87639
|
info(colors.green(`✅ Migrated '${legacyKey}' to 'workspaces' in ${wmillYamlPath}`));
|
|
86138
87640
|
if (wsNames.length > 0) {
|
|
86139
87641
|
info(` Workspace entries: ${wsNames.join(", ")}`);
|
|
@@ -86147,7 +87649,7 @@ var config_default = command35;
|
|
|
86147
87649
|
|
|
86148
87650
|
// src/main.ts
|
|
86149
87651
|
await init_context();
|
|
86150
|
-
var VERSION = "1.
|
|
87652
|
+
var VERSION = "1.692.0";
|
|
86151
87653
|
async function checkVersionSafe(cmd) {
|
|
86152
87654
|
const mainCommand = cmd.getMainCommand();
|
|
86153
87655
|
const upgradeCommand = mainCommand.getCommand("upgrade");
|