@withone/cli 1.44.2 → 1.45.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 +5 -3
- package/dist/chunk-77564KWS.js +211 -0
- package/dist/{chunk-MNNKOQ6V.js → chunk-KH4ERRJ5.js} +4 -2
- package/dist/{chunk-YBEVCY4D.js → chunk-TGWQUBKA.js} +4 -2
- package/dist/{chunk-7ZILTQQO.js → chunk-TLRJMJGU.js} +2 -2
- package/dist/{chunk-ZD5S4IWT.js → chunk-TVIZC7AC.js} +2 -203
- package/dist/{chunk-YGOS6KEC.js → chunk-UXKF6AEG.js} +254 -85
- package/dist/{chunk-VQPV5XET.js → chunk-Z4HKASJT.js} +2 -2
- package/dist/{embedding-GZGDGIUA.js → embedding-C3E4EAQ7.js} +2 -1
- package/dist/{flow-runner-EXZ77YLF.js → flow-runner-FQVTF36N.js} +2 -1
- package/dist/index.js +261 -372
- package/dist/{migrate-J2ZRDEFB.js → migrate-VV3VOXWJ.js} +5 -4
- package/dist/{runtime-RVXAPQAZ.js → runtime-3NDWRLXL.js} +3 -2
- package/dist/sql-ZABEXIXW.js +12 -0
- package/package.json +2 -2
- package/skills/one/SKILL.md +6 -5
- package/dist/sql-V44IVBHX.js +0 -11
|
@@ -2,16 +2,19 @@ import {
|
|
|
2
2
|
getByDotPath,
|
|
3
3
|
setByDotPath
|
|
4
4
|
} from "./chunk-44CV5IMX.js";
|
|
5
|
+
import {
|
|
6
|
+
getCacheTtl
|
|
7
|
+
} from "./chunk-TVIZC7AC.js";
|
|
5
8
|
|
|
6
9
|
// src/lib/flow-runner.ts
|
|
7
|
-
import
|
|
8
|
-
import
|
|
10
|
+
import fs3 from "fs";
|
|
11
|
+
import path3 from "path";
|
|
9
12
|
import crypto from "crypto";
|
|
10
13
|
|
|
11
14
|
// src/lib/flow-engine.ts
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
+
import fs2 from "fs";
|
|
16
|
+
import os2 from "os";
|
|
17
|
+
import path2 from "path";
|
|
15
18
|
import { exec, spawn } from "child_process";
|
|
16
19
|
import { promisify } from "util";
|
|
17
20
|
|
|
@@ -45,8 +48,8 @@ var OneApi = class {
|
|
|
45
48
|
this.apiBase = apiBase ?? "https://api.withone.ai/v1";
|
|
46
49
|
}
|
|
47
50
|
apiBase;
|
|
48
|
-
async request(
|
|
49
|
-
return this.requestFull({ path:
|
|
51
|
+
async request(path4) {
|
|
52
|
+
return this.requestFull({ path: path4 });
|
|
50
53
|
}
|
|
51
54
|
async requestFull(opts) {
|
|
52
55
|
let url = `${this.apiBase}${opts.path}`;
|
|
@@ -231,7 +234,12 @@ var OneApi = class {
|
|
|
231
234
|
const data = text ? JSON.parse(text) : {};
|
|
232
235
|
return { data, etag, status: response.status };
|
|
233
236
|
}
|
|
234
|
-
|
|
237
|
+
/**
|
|
238
|
+
* Full action details (method, path, tags, ioSchema, knowledge) with ETag
|
|
239
|
+
* support. This is what the knowledge cache stores: caching the complete
|
|
240
|
+
* object lets `actions execute` reuse it and skip its preflight round trip.
|
|
241
|
+
*/
|
|
242
|
+
async getActionDetailsWithMeta(actionId, ifNoneMatch) {
|
|
235
243
|
const result = await this.requestWithMeta({
|
|
236
244
|
path: "/knowledge",
|
|
237
245
|
queryParams: { _id: actionId },
|
|
@@ -244,12 +252,7 @@ var OneApi = class {
|
|
|
244
252
|
if (actions.length === 0) {
|
|
245
253
|
throw new ApiError(404, `Action with ID ${actionId} not found`);
|
|
246
254
|
}
|
|
247
|
-
|
|
248
|
-
const knowledge = {
|
|
249
|
-
knowledge: action.knowledge || "No knowledge was found",
|
|
250
|
-
method: action.method || "No method was found"
|
|
251
|
-
};
|
|
252
|
-
return { data: knowledge, etag: result.etag, status: result.status };
|
|
255
|
+
return { data: actions[0], etag: result.etag, status: result.status };
|
|
253
256
|
}
|
|
254
257
|
async searchActionsWithMeta(platform, query, agentType, ifNoneMatch) {
|
|
255
258
|
const isKnowledgeAgent = agentType === "knowledge";
|
|
@@ -478,9 +481,9 @@ var TimeoutError = class extends Error {
|
|
|
478
481
|
function sleep(ms) {
|
|
479
482
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
480
483
|
}
|
|
481
|
-
function replacePathVariables(
|
|
482
|
-
if (!
|
|
483
|
-
let result =
|
|
484
|
+
function replacePathVariables(path4, variables) {
|
|
485
|
+
if (!path4) return path4;
|
|
486
|
+
let result = path4;
|
|
484
487
|
result = result.replace(/\{\{([^}]+)\}\}/g, (_match, variable) => {
|
|
485
488
|
const trimmedVariable = variable.trim();
|
|
486
489
|
const value = variables[trimmedVariable];
|
|
@@ -544,6 +547,159 @@ Read the API documentation below to identify which parameters are path variables
|
|
|
544
547
|
${knowledge}`;
|
|
545
548
|
}
|
|
546
549
|
|
|
550
|
+
// src/lib/cache.ts
|
|
551
|
+
import fs from "fs";
|
|
552
|
+
import path from "path";
|
|
553
|
+
import os from "os";
|
|
554
|
+
function knowledgeDir() {
|
|
555
|
+
return path.join(os.homedir(), ".one", "cache", "knowledge");
|
|
556
|
+
}
|
|
557
|
+
function searchDir() {
|
|
558
|
+
return path.join(os.homedir(), ".one", "cache", "search");
|
|
559
|
+
}
|
|
560
|
+
function sanitizeFilename(input) {
|
|
561
|
+
return input.replace(/[^a-zA-Z0-9_\-\.]/g, "_");
|
|
562
|
+
}
|
|
563
|
+
function knowledgeCachePath(actionId) {
|
|
564
|
+
return path.join(knowledgeDir(), `${sanitizeFilename(actionId)}.json`);
|
|
565
|
+
}
|
|
566
|
+
function searchCachePath(platform, query, type) {
|
|
567
|
+
const key = `${platform}_${sanitizeFilename(query)}_${type || "knowledge"}`;
|
|
568
|
+
return path.join(searchDir(), `${key}.json`);
|
|
569
|
+
}
|
|
570
|
+
function readCache(filePath) {
|
|
571
|
+
try {
|
|
572
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
573
|
+
return JSON.parse(content);
|
|
574
|
+
} catch {
|
|
575
|
+
return null;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
function writeCache(filePath, entry) {
|
|
579
|
+
try {
|
|
580
|
+
const dir = path.dirname(filePath);
|
|
581
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
582
|
+
fs.writeFileSync(filePath, JSON.stringify(entry, null, 2));
|
|
583
|
+
} catch {
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
function isFresh(entry) {
|
|
587
|
+
const cachedTime = new Date(entry.cachedAt).getTime();
|
|
588
|
+
const now = Date.now();
|
|
589
|
+
return now - cachedTime < entry.ttl * 1e3;
|
|
590
|
+
}
|
|
591
|
+
function getAge(entry) {
|
|
592
|
+
return Math.floor((Date.now() - new Date(entry.cachedAt).getTime()) / 1e3);
|
|
593
|
+
}
|
|
594
|
+
function buildCacheMeta(entry, hit) {
|
|
595
|
+
if (!entry) {
|
|
596
|
+
return { hit: false, age: 0, fresh: false };
|
|
597
|
+
}
|
|
598
|
+
return {
|
|
599
|
+
hit,
|
|
600
|
+
age: getAge(entry),
|
|
601
|
+
fresh: isFresh(entry)
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
function formatAge(seconds) {
|
|
605
|
+
if (seconds < 60) return `${seconds}s`;
|
|
606
|
+
if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
|
|
607
|
+
if (seconds < 86400) {
|
|
608
|
+
const h2 = Math.floor(seconds / 3600);
|
|
609
|
+
const m = Math.floor(seconds % 3600 / 60);
|
|
610
|
+
return m > 0 ? `${h2}h ${m}m` : `${h2}h`;
|
|
611
|
+
}
|
|
612
|
+
const d = Math.floor(seconds / 86400);
|
|
613
|
+
const h = Math.floor(seconds % 86400 / 3600);
|
|
614
|
+
return h > 0 ? `${d}d ${h}h` : `${d}d`;
|
|
615
|
+
}
|
|
616
|
+
function listCacheEntries() {
|
|
617
|
+
const entries = [];
|
|
618
|
+
for (const [dir, type] of [[knowledgeDir(), "knowledge"], [searchDir(), "search"]]) {
|
|
619
|
+
try {
|
|
620
|
+
const files = fs.readdirSync(dir);
|
|
621
|
+
for (const file of files) {
|
|
622
|
+
if (!file.endsWith(".json")) continue;
|
|
623
|
+
const filePath = path.join(dir, file);
|
|
624
|
+
const entry = readCache(filePath);
|
|
625
|
+
if (entry) {
|
|
626
|
+
entries.push({ type, filePath, entry });
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
} catch {
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
return entries;
|
|
633
|
+
}
|
|
634
|
+
function clearAll() {
|
|
635
|
+
let count = 0;
|
|
636
|
+
for (const dir of [knowledgeDir(), searchDir()]) {
|
|
637
|
+
try {
|
|
638
|
+
const files = fs.readdirSync(dir);
|
|
639
|
+
for (const file of files) {
|
|
640
|
+
fs.unlinkSync(path.join(dir, file));
|
|
641
|
+
count++;
|
|
642
|
+
}
|
|
643
|
+
fs.rmdirSync(dir);
|
|
644
|
+
} catch {
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
return count;
|
|
648
|
+
}
|
|
649
|
+
function clearEntry(actionId) {
|
|
650
|
+
const filePath = knowledgeCachePath(actionId);
|
|
651
|
+
try {
|
|
652
|
+
fs.unlinkSync(filePath);
|
|
653
|
+
return true;
|
|
654
|
+
} catch {
|
|
655
|
+
return false;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
function makeCacheEntry(key, data, etag) {
|
|
659
|
+
return {
|
|
660
|
+
key,
|
|
661
|
+
etag,
|
|
662
|
+
cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
663
|
+
ttl: getCacheTtl(),
|
|
664
|
+
data
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// src/lib/action-details.ts
|
|
669
|
+
function isActionDetailsEntry(entry) {
|
|
670
|
+
const data = entry?.data;
|
|
671
|
+
return !!data && typeof data._id === "string" && typeof data.path === "string" && typeof data.method === "string";
|
|
672
|
+
}
|
|
673
|
+
async function resolveActionDetails(api, actionId, opts = {}) {
|
|
674
|
+
const useCache = opts.useCache !== false;
|
|
675
|
+
const cachePath = knowledgeCachePath(actionId);
|
|
676
|
+
const raw = useCache ? readCache(cachePath) : null;
|
|
677
|
+
const cached = isActionDetailsEntry(raw) ? raw : null;
|
|
678
|
+
if (cached && isFresh(cached)) {
|
|
679
|
+
return { details: cached.data, cacheHit: true, entry: cached };
|
|
680
|
+
}
|
|
681
|
+
try {
|
|
682
|
+
const result = await api.getActionDetailsWithMeta(actionId, cached?.etag ?? void 0);
|
|
683
|
+
if (result.status === 304 && cached) {
|
|
684
|
+
cached.cachedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
685
|
+
writeCache(cachePath, cached);
|
|
686
|
+
return { details: cached.data, cacheHit: true, entry: cached };
|
|
687
|
+
}
|
|
688
|
+
const entry = makeCacheEntry(actionId, result.data, result.etag);
|
|
689
|
+
writeCache(cachePath, entry);
|
|
690
|
+
return { details: result.data, cacheHit: false, entry };
|
|
691
|
+
} catch (fetchError) {
|
|
692
|
+
if (cached) {
|
|
693
|
+
process.stderr.write(
|
|
694
|
+
`Warning: serving cached action details (network unavailable, cached ${formatAge(getAge(cached))} ago)
|
|
695
|
+
`
|
|
696
|
+
);
|
|
697
|
+
return { details: cached.data, cacheHit: true, entry: cached };
|
|
698
|
+
}
|
|
699
|
+
throw fetchError;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
|
|
547
703
|
// src/lib/validate.ts
|
|
548
704
|
var SCHEMA_GROUP_TO_FLAG = {
|
|
549
705
|
path: "--path-vars",
|
|
@@ -816,7 +972,7 @@ async function executeActionStep(step, context, api, permissions, allowedActionI
|
|
|
816
972
|
if (!isActionAllowed(actionId, allowedActionIds)) {
|
|
817
973
|
throw new Error(`Action "${actionId}" is not in the allowed action list`);
|
|
818
974
|
}
|
|
819
|
-
const actionDetails = await api
|
|
975
|
+
const { details: actionDetails } = await resolveActionDetails(api, actionId);
|
|
820
976
|
if (!isMethodAllowed(actionDetails.method, permissions)) {
|
|
821
977
|
throw new Error(`Method "${actionDetails.method}" is not allowed under "${permissions}" permission level`);
|
|
822
978
|
}
|
|
@@ -899,15 +1055,15 @@ async function executeCodeModule(stepId, modulePath, context, options) {
|
|
|
899
1055
|
if (!rootDir) {
|
|
900
1056
|
throw new Error(`Code step "${stepId}" uses module "${modulePath}" but no flow rootDir is available. Flows that use code modules must be loaded via loadFlowWithMeta.`);
|
|
901
1057
|
}
|
|
902
|
-
if (
|
|
1058
|
+
if (path2.isAbsolute(modulePath)) {
|
|
903
1059
|
throw new Error(`Code module path must be relative to the flow root, got absolute: "${modulePath}"`);
|
|
904
1060
|
}
|
|
905
|
-
const absPath =
|
|
906
|
-
const relFromRoot =
|
|
907
|
-
if (relFromRoot.startsWith("..") ||
|
|
1061
|
+
const absPath = path2.resolve(rootDir, modulePath);
|
|
1062
|
+
const relFromRoot = path2.relative(rootDir, absPath);
|
|
1063
|
+
if (relFromRoot.startsWith("..") || path2.isAbsolute(relFromRoot)) {
|
|
908
1064
|
throw new Error(`Code module "${modulePath}" resolves outside the flow directory`);
|
|
909
1065
|
}
|
|
910
|
-
if (!
|
|
1066
|
+
if (!fs2.existsSync(absPath)) {
|
|
911
1067
|
throw new Error(`Code module not found: ${absPath}`);
|
|
912
1068
|
}
|
|
913
1069
|
const { env: _omitEnv, ...safeContext } = context;
|
|
@@ -1055,8 +1211,8 @@ async function executeParallelStep(step, context, api, permissions, allowedActio
|
|
|
1055
1211
|
function executeFileReadStep(step, context) {
|
|
1056
1212
|
const config = step.fileRead;
|
|
1057
1213
|
const filePath = resolveValue(config.path, context);
|
|
1058
|
-
const resolvedPath =
|
|
1059
|
-
const content =
|
|
1214
|
+
const resolvedPath = path2.resolve(filePath);
|
|
1215
|
+
const content = fs2.readFileSync(resolvedPath, "utf-8");
|
|
1060
1216
|
const output = config.parseJson ? JSON.parse(stripCodeFences(content)) : content;
|
|
1061
1217
|
return { status: "success", output, response: output };
|
|
1062
1218
|
}
|
|
@@ -1064,16 +1220,16 @@ function executeFileWriteStep(step, context) {
|
|
|
1064
1220
|
const config = step.fileWrite;
|
|
1065
1221
|
const filePath = resolveValue(config.path, context);
|
|
1066
1222
|
const content = resolveValue(config.content, context);
|
|
1067
|
-
const resolvedPath =
|
|
1068
|
-
const dir =
|
|
1069
|
-
if (!
|
|
1070
|
-
|
|
1223
|
+
const resolvedPath = path2.resolve(filePath);
|
|
1224
|
+
const dir = path2.dirname(resolvedPath);
|
|
1225
|
+
if (!fs2.existsSync(dir)) {
|
|
1226
|
+
fs2.mkdirSync(dir, { recursive: true });
|
|
1071
1227
|
}
|
|
1072
1228
|
const stringContent = typeof content === "string" ? content : JSON.stringify(content, null, 2);
|
|
1073
1229
|
if (config.append) {
|
|
1074
|
-
|
|
1230
|
+
fs2.appendFileSync(resolvedPath, stringContent);
|
|
1075
1231
|
} else {
|
|
1076
|
-
|
|
1232
|
+
fs2.writeFileSync(resolvedPath, stringContent);
|
|
1077
1233
|
}
|
|
1078
1234
|
return { status: "success", output: { path: resolvedPath, bytesWritten: stringContent.length }, response: { path: resolvedPath } };
|
|
1079
1235
|
}
|
|
@@ -1112,7 +1268,7 @@ async function executeSubflowStep(step, context, api, permissions, allowedAction
|
|
|
1112
1268
|
if (flowStack.includes(resolvedKey)) {
|
|
1113
1269
|
throw new Error(`Circular flow detected: ${[...flowStack, resolvedKey].join(" \u2192 ")}`);
|
|
1114
1270
|
}
|
|
1115
|
-
const { loadFlowWithMeta: loadFlowWithMeta2 } = await import("./flow-runner-
|
|
1271
|
+
const { loadFlowWithMeta: loadFlowWithMeta2 } = await import("./flow-runner-FQVTF36N.js");
|
|
1116
1272
|
const { flow: subFlow, rootDir: subRootDir } = loadFlowWithMeta2(resolvedKey);
|
|
1117
1273
|
const subContext = await executeFlow(
|
|
1118
1274
|
subFlow,
|
|
@@ -1215,11 +1371,11 @@ function resolveBashEnv(envConfig, context, stepId) {
|
|
|
1215
1371
|
if ("json" in obj) {
|
|
1216
1372
|
const resolved2 = resolveValue(obj.json, context);
|
|
1217
1373
|
const json = JSON.stringify(resolved2 ?? null);
|
|
1218
|
-
const tmp =
|
|
1219
|
-
|
|
1374
|
+
const tmp = path2.join(
|
|
1375
|
+
os2.tmpdir(),
|
|
1220
1376
|
`one-flow-${stepId}-${key}-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.json`
|
|
1221
1377
|
);
|
|
1222
|
-
|
|
1378
|
+
fs2.writeFileSync(tmp, json, { encoding: "utf-8" });
|
|
1223
1379
|
tempFiles.push(tmp);
|
|
1224
1380
|
out[key] = tmp;
|
|
1225
1381
|
continue;
|
|
@@ -1266,7 +1422,7 @@ async function executeBashStep(step, context, options) {
|
|
|
1266
1422
|
} finally {
|
|
1267
1423
|
for (const tmp of tempFiles) {
|
|
1268
1424
|
try {
|
|
1269
|
-
|
|
1425
|
+
fs2.unlinkSync(tmp);
|
|
1270
1426
|
} catch {
|
|
1271
1427
|
}
|
|
1272
1428
|
}
|
|
@@ -1347,7 +1503,7 @@ async function executeSingleStep(step, context, api, permissions, allowedActionI
|
|
|
1347
1503
|
if (step.type === "action" && step.action) {
|
|
1348
1504
|
const actionId = resolveValue(step.action.actionId, context);
|
|
1349
1505
|
try {
|
|
1350
|
-
const actionDetails = await api
|
|
1506
|
+
const { details: actionDetails } = await resolveActionDetails(api, actionId);
|
|
1351
1507
|
if (!options.skipValidation) {
|
|
1352
1508
|
const data = step.action.data ? resolveValue(step.action.data, context) : void 0;
|
|
1353
1509
|
const pathVars = step.action.pathVars ? resolveValue(step.action.pathVars, context) : void 0;
|
|
@@ -2389,8 +2545,8 @@ var FLOWS_DIR = ".one/flows";
|
|
|
2389
2545
|
var RUNS_DIR = ".one/flows/.runs";
|
|
2390
2546
|
var LOGS_DIR = ".one/flows/.logs";
|
|
2391
2547
|
function ensureDir(dir) {
|
|
2392
|
-
if (!
|
|
2393
|
-
|
|
2548
|
+
if (!fs3.existsSync(dir)) {
|
|
2549
|
+
fs3.mkdirSync(dir, { recursive: true });
|
|
2394
2550
|
}
|
|
2395
2551
|
}
|
|
2396
2552
|
function generateRunId() {
|
|
@@ -2408,8 +2564,8 @@ var FlowRunner = class _FlowRunner {
|
|
|
2408
2564
|
this.flowKey = flow.key;
|
|
2409
2565
|
ensureDir(RUNS_DIR);
|
|
2410
2566
|
ensureDir(LOGS_DIR);
|
|
2411
|
-
this.statePath =
|
|
2412
|
-
this.logPath =
|
|
2567
|
+
this.statePath = path3.join(RUNS_DIR, `${flow.key}-${this.runId}.state.json`);
|
|
2568
|
+
this.logPath = path3.join(LOGS_DIR, `${flow.key}-${this.runId}.log`);
|
|
2413
2569
|
const resolvedInputs = { ...inputs };
|
|
2414
2570
|
for (const [name, decl] of Object.entries(flow.inputs)) {
|
|
2415
2571
|
if (resolvedInputs[name] === void 0 && decl.default !== void 0) {
|
|
@@ -2450,10 +2606,10 @@ var FlowRunner = class _FlowRunner {
|
|
|
2450
2606
|
msg,
|
|
2451
2607
|
...data
|
|
2452
2608
|
};
|
|
2453
|
-
|
|
2609
|
+
fs3.appendFileSync(this.logPath, JSON.stringify(entry) + "\n");
|
|
2454
2610
|
}
|
|
2455
2611
|
saveState() {
|
|
2456
|
-
|
|
2612
|
+
fs3.writeFileSync(this.statePath, JSON.stringify(this.state, null, 2));
|
|
2457
2613
|
}
|
|
2458
2614
|
createEventHandler(externalHandler) {
|
|
2459
2615
|
return (event) => {
|
|
@@ -2551,10 +2707,10 @@ var FlowRunner = class _FlowRunner {
|
|
|
2551
2707
|
}
|
|
2552
2708
|
static loadRunState(runId) {
|
|
2553
2709
|
ensureDir(RUNS_DIR);
|
|
2554
|
-
const files =
|
|
2710
|
+
const files = fs3.readdirSync(RUNS_DIR).filter((f) => f.includes(runId) && f.endsWith(".state.json"));
|
|
2555
2711
|
if (files.length === 0) return null;
|
|
2556
2712
|
try {
|
|
2557
|
-
const content =
|
|
2713
|
+
const content = fs3.readFileSync(path3.join(RUNS_DIR, files[0]), "utf-8");
|
|
2558
2714
|
return JSON.parse(content);
|
|
2559
2715
|
} catch {
|
|
2560
2716
|
return null;
|
|
@@ -2566,17 +2722,17 @@ var FlowRunner = class _FlowRunner {
|
|
|
2566
2722
|
runner.flowKey = state.flowKey;
|
|
2567
2723
|
runner.state = state;
|
|
2568
2724
|
runner.paused = false;
|
|
2569
|
-
runner.statePath =
|
|
2570
|
-
runner.logPath =
|
|
2725
|
+
runner.statePath = path3.join(RUNS_DIR, `${state.flowKey}-${state.runId}.state.json`);
|
|
2726
|
+
runner.logPath = path3.join(LOGS_DIR, `${state.flowKey}-${state.runId}.log`);
|
|
2571
2727
|
return runner;
|
|
2572
2728
|
}
|
|
2573
2729
|
static listRuns(flowKey) {
|
|
2574
2730
|
ensureDir(RUNS_DIR);
|
|
2575
|
-
const files =
|
|
2731
|
+
const files = fs3.readdirSync(RUNS_DIR).filter((f) => f.endsWith(".state.json"));
|
|
2576
2732
|
const runs = [];
|
|
2577
2733
|
for (const file of files) {
|
|
2578
2734
|
try {
|
|
2579
|
-
const content =
|
|
2735
|
+
const content = fs3.readFileSync(path3.join(RUNS_DIR, file), "utf-8");
|
|
2580
2736
|
const state = JSON.parse(content);
|
|
2581
2737
|
if (!flowKey || state.flowKey === flowKey) {
|
|
2582
2738
|
runs.push(state);
|
|
@@ -2589,44 +2745,44 @@ var FlowRunner = class _FlowRunner {
|
|
|
2589
2745
|
};
|
|
2590
2746
|
function resolveFlowPath(keyOrPath) {
|
|
2591
2747
|
if (keyOrPath.endsWith(".json")) {
|
|
2592
|
-
return
|
|
2748
|
+
return path3.resolve(keyOrPath);
|
|
2593
2749
|
}
|
|
2594
2750
|
if (keyOrPath.includes("\\")) {
|
|
2595
|
-
return
|
|
2751
|
+
return path3.resolve(keyOrPath);
|
|
2596
2752
|
}
|
|
2597
2753
|
if (keyOrPath.includes("/")) {
|
|
2598
|
-
const nestedFolder =
|
|
2599
|
-
if (
|
|
2600
|
-
const literal =
|
|
2601
|
-
if (
|
|
2754
|
+
const nestedFolder = path3.resolve(FLOWS_DIR, keyOrPath, "flow.json");
|
|
2755
|
+
if (fs3.existsSync(nestedFolder)) return nestedFolder;
|
|
2756
|
+
const literal = path3.resolve(keyOrPath);
|
|
2757
|
+
if (fs3.existsSync(literal)) return literal;
|
|
2602
2758
|
return nestedFolder;
|
|
2603
2759
|
}
|
|
2604
|
-
const folderPath =
|
|
2605
|
-
if (
|
|
2606
|
-
const legacyPath =
|
|
2607
|
-
if (
|
|
2608
|
-
const flowsDir =
|
|
2609
|
-
if (
|
|
2610
|
-
for (const entry of
|
|
2760
|
+
const folderPath = path3.resolve(FLOWS_DIR, keyOrPath, "flow.json");
|
|
2761
|
+
if (fs3.existsSync(folderPath)) return folderPath;
|
|
2762
|
+
const legacyPath = path3.resolve(FLOWS_DIR, `${keyOrPath}.flow.json`);
|
|
2763
|
+
if (fs3.existsSync(legacyPath)) return legacyPath;
|
|
2764
|
+
const flowsDir = path3.resolve(FLOWS_DIR);
|
|
2765
|
+
if (fs3.existsSync(flowsDir)) {
|
|
2766
|
+
for (const entry of fs3.readdirSync(flowsDir, { withFileTypes: true })) {
|
|
2611
2767
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
2612
|
-
const nested =
|
|
2613
|
-
if (
|
|
2768
|
+
const nested = path3.join(flowsDir, entry.name, keyOrPath, "flow.json");
|
|
2769
|
+
if (fs3.existsSync(nested)) return nested;
|
|
2614
2770
|
}
|
|
2615
2771
|
}
|
|
2616
2772
|
return folderPath;
|
|
2617
2773
|
}
|
|
2618
2774
|
function getFlowRootDir(flowFilePath) {
|
|
2619
|
-
const dir =
|
|
2620
|
-
const base =
|
|
2775
|
+
const dir = path3.dirname(flowFilePath);
|
|
2776
|
+
const base = path3.basename(flowFilePath);
|
|
2621
2777
|
if (base === "flow.json") return dir;
|
|
2622
2778
|
return dir;
|
|
2623
2779
|
}
|
|
2624
2780
|
function loadFlowWithMeta(keyOrPath) {
|
|
2625
2781
|
const filePath = resolveFlowPath(keyOrPath);
|
|
2626
|
-
if (!
|
|
2782
|
+
if (!fs3.existsSync(filePath)) {
|
|
2627
2783
|
throw new Error(`Flow not found: ${filePath}`);
|
|
2628
2784
|
}
|
|
2629
|
-
const content =
|
|
2785
|
+
const content = fs3.readFileSync(filePath, "utf-8");
|
|
2630
2786
|
const flow = JSON.parse(content);
|
|
2631
2787
|
return { flow, filePath, rootDir: getFlowRootDir(filePath) };
|
|
2632
2788
|
}
|
|
@@ -2673,13 +2829,13 @@ function summarizeFlowInputs(flow) {
|
|
|
2673
2829
|
}));
|
|
2674
2830
|
}
|
|
2675
2831
|
function listFlows() {
|
|
2676
|
-
const flowsDir =
|
|
2677
|
-
if (!
|
|
2832
|
+
const flowsDir = path3.resolve(FLOWS_DIR);
|
|
2833
|
+
if (!fs3.existsSync(flowsDir)) return [];
|
|
2678
2834
|
const flows = [];
|
|
2679
2835
|
const seenKeys = /* @__PURE__ */ new Set();
|
|
2680
2836
|
const readFlowFile = (filePath, group) => {
|
|
2681
2837
|
try {
|
|
2682
|
-
const content =
|
|
2838
|
+
const content = fs3.readFileSync(filePath, "utf-8");
|
|
2683
2839
|
const flow = JSON.parse(content);
|
|
2684
2840
|
const nsKey = group ? `${group}/${flow.key}` : flow.key;
|
|
2685
2841
|
if (seenKeys.has(nsKey)) return;
|
|
@@ -2691,7 +2847,7 @@ function listFlows() {
|
|
|
2691
2847
|
inputCount: Object.keys(flow.inputs).length,
|
|
2692
2848
|
stepCount: flow.steps.length,
|
|
2693
2849
|
path: filePath,
|
|
2694
|
-
layout:
|
|
2850
|
+
layout: path3.basename(filePath) === "flow.json" ? "folder" : "legacy",
|
|
2695
2851
|
group,
|
|
2696
2852
|
stepTypes: collectStepTypes(flow),
|
|
2697
2853
|
requiresBash: flowRequiresBash(flow),
|
|
@@ -2702,12 +2858,12 @@ function listFlows() {
|
|
|
2702
2858
|
}
|
|
2703
2859
|
};
|
|
2704
2860
|
const scanDir = (dir, group) => {
|
|
2705
|
-
for (const entry of
|
|
2861
|
+
for (const entry of fs3.readdirSync(dir, { withFileTypes: true })) {
|
|
2706
2862
|
if (entry.name.startsWith(".")) continue;
|
|
2707
|
-
const full =
|
|
2863
|
+
const full = path3.join(dir, entry.name);
|
|
2708
2864
|
if (entry.isDirectory()) {
|
|
2709
|
-
const flowJson =
|
|
2710
|
-
if (
|
|
2865
|
+
const flowJson = path3.join(full, "flow.json");
|
|
2866
|
+
if (fs3.existsSync(flowJson)) {
|
|
2711
2867
|
readFlowFile(flowJson, group);
|
|
2712
2868
|
} else {
|
|
2713
2869
|
if (!group) {
|
|
@@ -2725,7 +2881,7 @@ function listFlows() {
|
|
|
2725
2881
|
function saveFlow(flow, outputPath, group) {
|
|
2726
2882
|
let flowPath;
|
|
2727
2883
|
if (outputPath) {
|
|
2728
|
-
flowPath =
|
|
2884
|
+
flowPath = path3.resolve(outputPath);
|
|
2729
2885
|
} else {
|
|
2730
2886
|
let bareKey = flow.key;
|
|
2731
2887
|
let resolvedGroup = group;
|
|
@@ -2735,21 +2891,21 @@ function saveFlow(flow, outputPath, group) {
|
|
|
2735
2891
|
resolvedGroup = resolvedGroup || parts.join("/");
|
|
2736
2892
|
flow.key = bareKey;
|
|
2737
2893
|
}
|
|
2738
|
-
const basePath = resolvedGroup ?
|
|
2739
|
-
const legacyPath =
|
|
2740
|
-
const folderPath =
|
|
2741
|
-
if (!resolvedGroup &&
|
|
2894
|
+
const basePath = resolvedGroup ? path3.resolve(FLOWS_DIR, resolvedGroup, bareKey) : path3.resolve(FLOWS_DIR, bareKey);
|
|
2895
|
+
const legacyPath = path3.resolve(FLOWS_DIR, `${bareKey}.flow.json`);
|
|
2896
|
+
const folderPath = path3.join(basePath, "flow.json");
|
|
2897
|
+
if (!resolvedGroup && fs3.existsSync(legacyPath) && !fs3.existsSync(folderPath)) {
|
|
2742
2898
|
flowPath = legacyPath;
|
|
2743
2899
|
} else {
|
|
2744
2900
|
flowPath = folderPath;
|
|
2745
2901
|
}
|
|
2746
2902
|
}
|
|
2747
|
-
const dir =
|
|
2903
|
+
const dir = path3.dirname(flowPath);
|
|
2748
2904
|
ensureDir(dir);
|
|
2749
|
-
if (
|
|
2750
|
-
ensureDir(
|
|
2905
|
+
if (path3.basename(flowPath) === "flow.json") {
|
|
2906
|
+
ensureDir(path3.join(dir, "lib"));
|
|
2751
2907
|
}
|
|
2752
|
-
|
|
2908
|
+
fs3.writeFileSync(flowPath, JSON.stringify(flow, null, 2) + "\n");
|
|
2753
2909
|
return flowPath;
|
|
2754
2910
|
}
|
|
2755
2911
|
|
|
@@ -2762,6 +2918,19 @@ export {
|
|
|
2762
2918
|
isActionAllowed,
|
|
2763
2919
|
buildActionKnowledgeWithGuidance,
|
|
2764
2920
|
validateActionInput,
|
|
2921
|
+
knowledgeCachePath,
|
|
2922
|
+
searchCachePath,
|
|
2923
|
+
readCache,
|
|
2924
|
+
writeCache,
|
|
2925
|
+
isFresh,
|
|
2926
|
+
getAge,
|
|
2927
|
+
buildCacheMeta,
|
|
2928
|
+
formatAge,
|
|
2929
|
+
listCacheEntries,
|
|
2930
|
+
clearAll,
|
|
2931
|
+
clearEntry,
|
|
2932
|
+
makeCacheEntry,
|
|
2933
|
+
resolveActionDetails,
|
|
2765
2934
|
FLOW_SCHEMA,
|
|
2766
2935
|
getStepTypeDescriptor,
|
|
2767
2936
|
getNestedStepsKeys,
|
|
@@ -6,11 +6,11 @@ import {
|
|
|
6
6
|
note,
|
|
7
7
|
okJson,
|
|
8
8
|
requireMemoryInit
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-KH4ERRJ5.js";
|
|
10
10
|
import {
|
|
11
11
|
getBackend,
|
|
12
12
|
upsertRecord
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-TGWQUBKA.js";
|
|
14
14
|
|
|
15
15
|
// src/commands/mem/migrate.ts
|
|
16
16
|
import fs4 from "fs";
|