@withone/cli 2.12.0 → 2.14.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 +8 -2
- package/dist/{chunk-EITBMRUB.js → chunk-2OIJGF77.js} +1 -1
- package/dist/{chunk-6IRGRC3G.js → chunk-4H5L3SBY.js} +2 -2
- package/dist/{chunk-J7JWBH45.js → chunk-B5YDLVY5.js} +2 -2
- package/dist/{chunk-7ZBRP3BJ.js → chunk-IM3OA7CU.js} +305 -82
- package/dist/{chunk-WZTPSXHP.js → chunk-LEJKEGB6.js} +2 -2
- package/dist/{chunk-DGQOAFXJ.js → chunk-TSMVFVQ3.js} +2 -2
- package/dist/{chunk-EWHFGWB3.js → chunk-XUAUDMQE.js} +39 -0
- package/dist/{embedding-7Q22D23K.js → embedding-YIXO45HW.js} +2 -2
- package/dist/{flow-runner-6QTY3U2C.js → flow-runner-SRO6YL62.js} +2 -2
- package/dist/index.js +124 -42
- package/dist/{migrate-KKNH3745.js → migrate-RJ7F2LPT.js} +5 -5
- package/dist/{runtime-WB4J6RQK.js → runtime-2OVXKNJS.js} +3 -3
- package/dist/{schema-SDZZ7XZT.js → schema-FIIT33OD.js} +4 -4
- package/dist/sql-KRQUWOPT.js +13 -0
- package/package.json +1 -1
- package/skills/one/references/flows.md +14 -13
- package/dist/sql-BNSA2GZM.js +0 -13
|
@@ -78,6 +78,42 @@ function intersectAllowlists(a, b) {
|
|
|
78
78
|
if (b.includes("*")) return a;
|
|
79
79
|
return a.filter((x) => b.includes(x));
|
|
80
80
|
}
|
|
81
|
+
function checkManagementAccess(settings, op, what) {
|
|
82
|
+
const permissions = settings.permissions ?? "admin";
|
|
83
|
+
if (settings.knowledgeAgent) {
|
|
84
|
+
throw new AccessDeniedError(`${what} is disabled (knowledge-only mode).`);
|
|
85
|
+
}
|
|
86
|
+
const method = op === "delete" ? "DELETE" : "POST";
|
|
87
|
+
if (!isMethodAllowed(method, permissions)) {
|
|
88
|
+
throw new AccessDeniedError(`${what} needs ${op === "delete" ? 'the "admin"' : 'the "write" or "admin"'} permission level (current: "${permissions}").`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function allowlistsUnrestricted(settings) {
|
|
92
|
+
return (settings.actionIds ?? ["*"]).includes("*") && (settings.connectionKeys ?? ["*"]).includes("*");
|
|
93
|
+
}
|
|
94
|
+
async function checkRelayActions(settings, actions, methodOf) {
|
|
95
|
+
if (actions === void 0 || actions === null) return;
|
|
96
|
+
if (!Array.isArray(actions)) throw new AccessDeniedError("--actions must be a JSON array.");
|
|
97
|
+
for (const [i, raw] of actions.entries()) {
|
|
98
|
+
const action = raw ?? {};
|
|
99
|
+
if (action.type === "passthrough") {
|
|
100
|
+
const actionId = String(action.actionId ?? "");
|
|
101
|
+
const connectionKey = String(action.connectionKey ?? "");
|
|
102
|
+
if (!actionId || !connectionKey) {
|
|
103
|
+
throw new AccessDeniedError(`Relay action [${i}] needs an actionId and a connectionKey.`);
|
|
104
|
+
}
|
|
105
|
+
checkPassthroughAccess({ ...settings, permissions: "admin", knowledgeAgent: false }, { actionId, connectionKey, method: "GET" });
|
|
106
|
+
const headers = action.headers && typeof action.headers === "object" ? action.headers : void 0;
|
|
107
|
+
checkPassthroughAccess(settings, { actionId, connectionKey, method: await methodOf(actionId), headers });
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (!allowlistsUnrestricted(settings)) {
|
|
111
|
+
throw new AccessDeniedError(
|
|
112
|
+
`Relay action [${i}] of type "${String(action.type)}" forwards events outside the connection and action allowlists, so it is allowed only when both are "*".`
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
81
117
|
|
|
82
118
|
// src/lib/config.ts
|
|
83
119
|
function configDir() {
|
|
@@ -535,8 +571,11 @@ export {
|
|
|
535
571
|
PERMISSION_METHODS,
|
|
536
572
|
isMethodAllowed,
|
|
537
573
|
isActionAllowed,
|
|
574
|
+
isConnectionAllowed,
|
|
538
575
|
IDENTITY_HEADERS,
|
|
539
576
|
checkPassthroughAccess,
|
|
577
|
+
checkManagementAccess,
|
|
578
|
+
checkRelayActions,
|
|
540
579
|
getProjectRoot,
|
|
541
580
|
getProjectConfigPath,
|
|
542
581
|
getGlobalConfigPath,
|
|
@@ -12,10 +12,10 @@ import {
|
|
|
12
12
|
stripStepsAlias,
|
|
13
13
|
summarizeFlowInputs,
|
|
14
14
|
walkSteps
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-IM3OA7CU.js";
|
|
16
16
|
import "./chunk-44CV5IMX.js";
|
|
17
17
|
import "./chunk-Q6PWTATS.js";
|
|
18
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-XUAUDMQE.js";
|
|
19
19
|
export {
|
|
20
20
|
FlowRunner,
|
|
21
21
|
collectStepTypes,
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
describeInstallContext,
|
|
15
15
|
drainQueue,
|
|
16
16
|
flowRequiresBash,
|
|
17
|
+
flowUsesCodeModules,
|
|
17
18
|
flush,
|
|
18
19
|
flushUsageRollups,
|
|
19
20
|
formatAge,
|
|
@@ -39,10 +40,10 @@ import {
|
|
|
39
40
|
validateActionInput,
|
|
40
41
|
walkSteps,
|
|
41
42
|
writeCache
|
|
42
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-IM3OA7CU.js";
|
|
43
44
|
import {
|
|
44
45
|
memSqlCommand
|
|
45
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-TSMVFVQ3.js";
|
|
46
47
|
import {
|
|
47
48
|
collectIdentityKeys,
|
|
48
49
|
countRecords,
|
|
@@ -73,7 +74,7 @@ import {
|
|
|
73
74
|
writeDraftProfile,
|
|
74
75
|
writePageToMemory,
|
|
75
76
|
writeProfile
|
|
76
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-LEJKEGB6.js";
|
|
77
78
|
import {
|
|
78
79
|
getByDotPath
|
|
79
80
|
} from "./chunk-44CV5IMX.js";
|
|
@@ -87,7 +88,7 @@ import {
|
|
|
87
88
|
requireMemoryInit,
|
|
88
89
|
semanticSearchUpgradeHint,
|
|
89
90
|
semanticSearchUpgradeLine
|
|
90
|
-
} from "./chunk-
|
|
91
|
+
} from "./chunk-B5YDLVY5.js";
|
|
91
92
|
import {
|
|
92
93
|
cancel,
|
|
93
94
|
createSpinner,
|
|
@@ -109,7 +110,7 @@ import {
|
|
|
109
110
|
listBackendPlugins,
|
|
110
111
|
loadBackendFromConfig,
|
|
111
112
|
updateRecord
|
|
112
|
-
} from "./chunk-
|
|
113
|
+
} from "./chunk-4H5L3SBY.js";
|
|
113
114
|
import {
|
|
114
115
|
DEFAULT_MEMORY_CONFIG,
|
|
115
116
|
defaultSearchableText,
|
|
@@ -119,9 +120,11 @@ import {
|
|
|
119
120
|
memoryConfigExists,
|
|
120
121
|
setOpenAiApiKey,
|
|
121
122
|
updateMemoryConfig
|
|
122
|
-
} from "./chunk-
|
|
123
|
+
} from "./chunk-2OIJGF77.js";
|
|
123
124
|
import {
|
|
124
125
|
PERMISSION_METHODS,
|
|
126
|
+
checkManagementAccess,
|
|
127
|
+
checkRelayActions,
|
|
125
128
|
configExists,
|
|
126
129
|
ensureWhoAmI,
|
|
127
130
|
getAccessControl,
|
|
@@ -137,6 +140,7 @@ import {
|
|
|
137
140
|
globalConfigExists,
|
|
138
141
|
homeDir,
|
|
139
142
|
isActionAllowed,
|
|
143
|
+
isConnectionAllowed,
|
|
140
144
|
isMethodAllowed,
|
|
141
145
|
projectConfigExists,
|
|
142
146
|
readConfig,
|
|
@@ -148,7 +152,7 @@ import {
|
|
|
148
152
|
updateApiBase,
|
|
149
153
|
updateWhoAmI,
|
|
150
154
|
writeConfig
|
|
151
|
-
} from "./chunk-
|
|
155
|
+
} from "./chunk-XUAUDMQE.js";
|
|
152
156
|
|
|
153
157
|
// src/cli.ts
|
|
154
158
|
import { createRequire } from "module";
|
|
@@ -2448,6 +2452,11 @@ async function connectionDeleteCommand(connectionKey, options) {
|
|
|
2448
2452
|
if (!apiKey) {
|
|
2449
2453
|
error("Not configured. Run `one init` first.");
|
|
2450
2454
|
}
|
|
2455
|
+
try {
|
|
2456
|
+
checkManagementAccess(getAccessControlFromAllSources(), "delete", "Deleting a connection");
|
|
2457
|
+
} catch (error2) {
|
|
2458
|
+
error(error2 instanceof Error ? error2.message : String(error2));
|
|
2459
|
+
}
|
|
2451
2460
|
const api = new OneApi(apiKey, getApiBase());
|
|
2452
2461
|
const spinner = createSpinner();
|
|
2453
2462
|
spinner.start("Finding connection...");
|
|
@@ -4949,6 +4958,14 @@ ${preflightErrors.map((e) => ` ${e.path}: ${e.message}`).join("\n")}`);
|
|
|
4949
4958
|
}
|
|
4950
4959
|
error(msg);
|
|
4951
4960
|
}
|
|
4961
|
+
if (!options.allowCode && flowUsesCodeModules(flow2)) {
|
|
4962
|
+
const msg = `Workflow "${flow2.key}" contains code.module steps, which run with full Node access. Re-run with --allow-code to permit them.`;
|
|
4963
|
+
if (isAgentMode()) {
|
|
4964
|
+
json({ error: msg, requiresCode: true, flowKey: flow2.key });
|
|
4965
|
+
process.exit(1);
|
|
4966
|
+
}
|
|
4967
|
+
error(msg);
|
|
4968
|
+
}
|
|
4952
4969
|
if (options.stopAfter) {
|
|
4953
4970
|
const ids = /* @__PURE__ */ new Set();
|
|
4954
4971
|
walkSteps(flow2.steps, (s) => {
|
|
@@ -5011,6 +5028,7 @@ ${pc8.yellow("Pausing after current step completes...")} (run ID: ${runId})`);
|
|
|
5011
5028
|
mock: options.mock,
|
|
5012
5029
|
verbose: options.verbose,
|
|
5013
5030
|
allowBash: options.allowBash,
|
|
5031
|
+
allowCode: options.allowCode,
|
|
5014
5032
|
skipValidation: options.skipValidation,
|
|
5015
5033
|
stopAfter: options.stopAfter,
|
|
5016
5034
|
rootDir,
|
|
@@ -5121,7 +5139,7 @@ async function flowListCommand() {
|
|
|
5121
5139
|
layout: f.layout,
|
|
5122
5140
|
inputCount: String(f.inputCount),
|
|
5123
5141
|
stepCount: String(f.stepCount),
|
|
5124
|
-
flags: f.requiresBash ? "--allow-bash" : ""
|
|
5142
|
+
flags: [f.requiresBash ? "--allow-bash" : "", f.usesCodeModules ? "--allow-code" : ""].filter(Boolean).join(" ")
|
|
5125
5143
|
}))
|
|
5126
5144
|
);
|
|
5127
5145
|
console.log();
|
|
@@ -5197,6 +5215,14 @@ async function flowResumeCommand(runId, options = {}) {
|
|
|
5197
5215
|
}
|
|
5198
5216
|
error(msg);
|
|
5199
5217
|
}
|
|
5218
|
+
if (!options.allowCode && flowUsesCodeModules(flow2)) {
|
|
5219
|
+
const msg = `Workflow "${flow2.key}" contains code.module steps, which run with full Node access. Re-run with --allow-code to permit them.`;
|
|
5220
|
+
if (isAgentMode()) {
|
|
5221
|
+
json({ error: msg, requiresCode: true, flowKey: flow2.key, runId });
|
|
5222
|
+
process.exit(1);
|
|
5223
|
+
}
|
|
5224
|
+
error(msg);
|
|
5225
|
+
}
|
|
5200
5226
|
const runner = FlowRunner.fromRunState(state);
|
|
5201
5227
|
const onEvent = (event) => {
|
|
5202
5228
|
if (isAgentMode()) {
|
|
@@ -5209,7 +5235,8 @@ async function flowResumeCommand(runId, options = {}) {
|
|
|
5209
5235
|
const context = await runner.resume(flow2, api, permissions, actionIds, {
|
|
5210
5236
|
onEvent,
|
|
5211
5237
|
rootDir,
|
|
5212
|
-
allowBash: options.allowBash
|
|
5238
|
+
allowBash: options.allowBash,
|
|
5239
|
+
allowCode: options.allowCode
|
|
5213
5240
|
});
|
|
5214
5241
|
spinner.stop("Workflow completed");
|
|
5215
5242
|
if (isAgentMode()) {
|
|
@@ -5525,9 +5552,45 @@ function getConfig3() {
|
|
|
5525
5552
|
if (!apiKey) {
|
|
5526
5553
|
error("Not configured. Run `one init` first.");
|
|
5527
5554
|
}
|
|
5528
|
-
const
|
|
5529
|
-
const connectionKeys =
|
|
5530
|
-
return { apiKey, connectionKeys };
|
|
5555
|
+
const settings = getAccessControlFromAllSources();
|
|
5556
|
+
const connectionKeys = settings.connectionKeys || ["*"];
|
|
5557
|
+
return { apiKey, connectionKeys, settings };
|
|
5558
|
+
}
|
|
5559
|
+
async function connectionIdFilter(api, settings) {
|
|
5560
|
+
const keys = settings.connectionKeys ?? ["*"];
|
|
5561
|
+
if (keys.includes("*")) return () => true;
|
|
5562
|
+
const connections = await api.listConnections();
|
|
5563
|
+
const ids = new Set(connections.filter((c) => isConnectionAllowed(c.key, keys)).map((c) => c.id));
|
|
5564
|
+
return (id) => ids.has(id);
|
|
5565
|
+
}
|
|
5566
|
+
function restricted(settings) {
|
|
5567
|
+
return !(settings.connectionKeys ?? ["*"]).includes("*");
|
|
5568
|
+
}
|
|
5569
|
+
async function allowedEndpoint(api, settings, id) {
|
|
5570
|
+
const allowed = await connectionIdFilter(api, settings);
|
|
5571
|
+
const endpoint = await api.getRelayEndpoint(id);
|
|
5572
|
+
if (!allowed(endpoint.connectionId)) {
|
|
5573
|
+
throw new Error(`Relay endpoint "${id}" is on a connection that is not allowed.`);
|
|
5574
|
+
}
|
|
5575
|
+
return endpoint;
|
|
5576
|
+
}
|
|
5577
|
+
async function allowedEvent(api, settings, id) {
|
|
5578
|
+
const allowed = await connectionIdFilter(api, settings);
|
|
5579
|
+
const event = await api.getRelayEvent(id);
|
|
5580
|
+
if (!allowed(event.connectionId)) {
|
|
5581
|
+
throw new Error(`Relay event "${id}" is on a connection that is not allowed.`);
|
|
5582
|
+
}
|
|
5583
|
+
return event;
|
|
5584
|
+
}
|
|
5585
|
+
function actionMethod(api) {
|
|
5586
|
+
return async (actionId) => (await resolveActionDetails(api, actionId)).details.method;
|
|
5587
|
+
}
|
|
5588
|
+
function guard(check) {
|
|
5589
|
+
try {
|
|
5590
|
+
check();
|
|
5591
|
+
} catch (error2) {
|
|
5592
|
+
error(error2 instanceof Error ? error2.message : String(error2));
|
|
5593
|
+
}
|
|
5531
5594
|
}
|
|
5532
5595
|
function parseJsonArg3(value, argName) {
|
|
5533
5596
|
try {
|
|
@@ -5537,7 +5600,8 @@ function parseJsonArg3(value, argName) {
|
|
|
5537
5600
|
}
|
|
5538
5601
|
}
|
|
5539
5602
|
async function relayCreateCommand(options) {
|
|
5540
|
-
const { apiKey, connectionKeys } = getConfig3();
|
|
5603
|
+
const { apiKey, connectionKeys, settings } = getConfig3();
|
|
5604
|
+
guard(() => checkManagementAccess(settings, "write", "Creating a relay endpoint"));
|
|
5541
5605
|
if (!connectionKeys.includes("*") && !connectionKeys.includes(options.connectionKey)) {
|
|
5542
5606
|
error(`Connection key "${options.connectionKey}" is not allowed.`);
|
|
5543
5607
|
}
|
|
@@ -5577,7 +5641,7 @@ async function relayCreateCommand(options) {
|
|
|
5577
5641
|
}
|
|
5578
5642
|
}
|
|
5579
5643
|
async function relayListCommand(options) {
|
|
5580
|
-
const { apiKey } = getConfig3();
|
|
5644
|
+
const { apiKey, settings } = getConfig3();
|
|
5581
5645
|
const api = new OneApi(apiKey, getApiBase());
|
|
5582
5646
|
const spinner = createSpinner();
|
|
5583
5647
|
spinner.start("Loading relay endpoints...");
|
|
@@ -5586,10 +5650,13 @@ async function relayListCommand(options) {
|
|
|
5586
5650
|
if (options.limit) query.limit = options.limit;
|
|
5587
5651
|
if (options.page) query.page = options.page;
|
|
5588
5652
|
const result = await api.listRelayEndpoints(query);
|
|
5589
|
-
const
|
|
5653
|
+
const allowed = await connectionIdFilter(api, settings);
|
|
5654
|
+
const endpoints = (result.rows || []).filter((e) => allowed(e.connectionId));
|
|
5590
5655
|
if (isAgentMode()) {
|
|
5591
5656
|
json({
|
|
5592
|
-
total
|
|
5657
|
+
// With a connection allowlist the server's total also counts rows
|
|
5658
|
+
// the allowlist hides, so report only what is shown.
|
|
5659
|
+
total: restricted(settings) ? endpoints.length : result.total,
|
|
5593
5660
|
showing: endpoints.length,
|
|
5594
5661
|
endpoints: endpoints.map((e) => ({
|
|
5595
5662
|
id: e.id,
|
|
@@ -5630,12 +5697,12 @@ async function relayListCommand(options) {
|
|
|
5630
5697
|
}
|
|
5631
5698
|
}
|
|
5632
5699
|
async function relayGetCommand(id) {
|
|
5633
|
-
const { apiKey } = getConfig3();
|
|
5700
|
+
const { apiKey, settings } = getConfig3();
|
|
5634
5701
|
const api = new OneApi(apiKey, getApiBase());
|
|
5635
5702
|
const spinner = createSpinner();
|
|
5636
5703
|
spinner.start("Loading relay endpoint...");
|
|
5637
5704
|
try {
|
|
5638
|
-
const result = await api
|
|
5705
|
+
const result = await allowedEndpoint(api, settings, id);
|
|
5639
5706
|
if (isAgentMode()) {
|
|
5640
5707
|
json(result);
|
|
5641
5708
|
return;
|
|
@@ -5661,7 +5728,8 @@ async function relayGetCommand(id) {
|
|
|
5661
5728
|
}
|
|
5662
5729
|
}
|
|
5663
5730
|
async function relayUpdateCommand(id, options) {
|
|
5664
|
-
const { apiKey } = getConfig3();
|
|
5731
|
+
const { apiKey, settings } = getConfig3();
|
|
5732
|
+
guard(() => checkManagementAccess(settings, "write", "Updating a relay endpoint"));
|
|
5665
5733
|
const api = new OneApi(apiKey, getApiBase());
|
|
5666
5734
|
const spinner = createSpinner();
|
|
5667
5735
|
spinner.start("Updating relay endpoint...");
|
|
@@ -5672,6 +5740,9 @@ async function relayUpdateCommand(id, options) {
|
|
|
5672
5740
|
if (options.eventFilters) body.eventFilters = parseJsonArg3(options.eventFilters, "--event-filters");
|
|
5673
5741
|
if (options.tags) body.tags = parseJsonArg3(options.tags, "--tags");
|
|
5674
5742
|
if (options.actions) body.actions = parseJsonArg3(options.actions, "--actions");
|
|
5743
|
+
const existing = await allowedEndpoint(api, settings, id);
|
|
5744
|
+
const effective = body.actions ?? (options.active === true ? existing.actions : void 0);
|
|
5745
|
+
await checkRelayActions(settings, effective, actionMethod(api));
|
|
5675
5746
|
const result = await api.updateRelayEndpoint(id, body);
|
|
5676
5747
|
if (isAgentMode()) {
|
|
5677
5748
|
json(result);
|
|
@@ -5688,11 +5759,13 @@ async function relayUpdateCommand(id, options) {
|
|
|
5688
5759
|
}
|
|
5689
5760
|
}
|
|
5690
5761
|
async function relayDeleteCommand(id) {
|
|
5691
|
-
const { apiKey } = getConfig3();
|
|
5762
|
+
const { apiKey, settings } = getConfig3();
|
|
5763
|
+
guard(() => checkManagementAccess(settings, "delete", "Deleting a relay endpoint"));
|
|
5692
5764
|
const api = new OneApi(apiKey, getApiBase());
|
|
5693
5765
|
const spinner = createSpinner();
|
|
5694
5766
|
spinner.start("Deleting relay endpoint...");
|
|
5695
5767
|
try {
|
|
5768
|
+
await allowedEndpoint(api, settings, id);
|
|
5696
5769
|
const result = await api.deleteRelayEndpoint(id);
|
|
5697
5770
|
if (isAgentMode()) {
|
|
5698
5771
|
json({ deleted: true, id: result.id });
|
|
@@ -5707,12 +5780,15 @@ async function relayDeleteCommand(id) {
|
|
|
5707
5780
|
}
|
|
5708
5781
|
}
|
|
5709
5782
|
async function relayActivateCommand(id, options) {
|
|
5710
|
-
const { apiKey } = getConfig3();
|
|
5783
|
+
const { apiKey, settings } = getConfig3();
|
|
5784
|
+
guard(() => checkManagementAccess(settings, "write", "Activating a relay endpoint"));
|
|
5711
5785
|
const api = new OneApi(apiKey, getApiBase());
|
|
5712
5786
|
const spinner = createSpinner();
|
|
5713
5787
|
spinner.start("Activating relay endpoint...");
|
|
5714
5788
|
try {
|
|
5715
5789
|
const actions2 = parseJsonArg3(options.actions, "--actions");
|
|
5790
|
+
await allowedEndpoint(api, settings, id);
|
|
5791
|
+
await checkRelayActions(settings, actions2, actionMethod(api));
|
|
5716
5792
|
const body = { actions: actions2 };
|
|
5717
5793
|
if (options.webhookSecret) body.webhookSecret = options.webhookSecret;
|
|
5718
5794
|
const result = await api.activateRelayEndpoint(id, body);
|
|
@@ -5731,7 +5807,7 @@ async function relayActivateCommand(id, options) {
|
|
|
5731
5807
|
}
|
|
5732
5808
|
}
|
|
5733
5809
|
async function relayEventsCommand(options) {
|
|
5734
|
-
const { apiKey } = getConfig3();
|
|
5810
|
+
const { apiKey, settings } = getConfig3();
|
|
5735
5811
|
const api = new OneApi(apiKey, getApiBase());
|
|
5736
5812
|
const spinner = createSpinner();
|
|
5737
5813
|
spinner.start("Loading relay events...");
|
|
@@ -5744,10 +5820,13 @@ async function relayEventsCommand(options) {
|
|
|
5744
5820
|
if (options.after) query.after = options.after;
|
|
5745
5821
|
if (options.before) query.before = options.before;
|
|
5746
5822
|
const result = await api.listRelayEvents(query);
|
|
5747
|
-
const
|
|
5823
|
+
const allowed = await connectionIdFilter(api, settings);
|
|
5824
|
+
const events = (result.rows || []).filter((e) => allowed(e.connectionId));
|
|
5748
5825
|
if (isAgentMode()) {
|
|
5749
5826
|
json({
|
|
5750
|
-
total
|
|
5827
|
+
// With a connection allowlist the server's total also counts rows
|
|
5828
|
+
// the allowlist hides, so report only what is shown.
|
|
5829
|
+
total: restricted(settings) ? events.length : result.total,
|
|
5751
5830
|
showing: events.length,
|
|
5752
5831
|
events: events.map((e) => ({
|
|
5753
5832
|
id: e.id,
|
|
@@ -5783,12 +5862,12 @@ async function relayEventsCommand(options) {
|
|
|
5783
5862
|
}
|
|
5784
5863
|
}
|
|
5785
5864
|
async function relayEventGetCommand(id) {
|
|
5786
|
-
const { apiKey } = getConfig3();
|
|
5865
|
+
const { apiKey, settings } = getConfig3();
|
|
5787
5866
|
const api = new OneApi(apiKey, getApiBase());
|
|
5788
5867
|
const spinner = createSpinner();
|
|
5789
5868
|
spinner.start("Loading relay event...");
|
|
5790
5869
|
try {
|
|
5791
|
-
const result = await api
|
|
5870
|
+
const result = await allowedEvent(api, settings, id);
|
|
5792
5871
|
if (isAgentMode()) {
|
|
5793
5872
|
json(result);
|
|
5794
5873
|
return;
|
|
@@ -5811,11 +5890,13 @@ async function relayDeliveriesCommand(options) {
|
|
|
5811
5890
|
if (!options.endpointId && !options.eventId) {
|
|
5812
5891
|
error("Provide either --endpoint-id or --event-id");
|
|
5813
5892
|
}
|
|
5814
|
-
const { apiKey } = getConfig3();
|
|
5893
|
+
const { apiKey, settings } = getConfig3();
|
|
5815
5894
|
const api = new OneApi(apiKey, getApiBase());
|
|
5816
5895
|
const spinner = createSpinner();
|
|
5817
5896
|
spinner.start("Loading deliveries...");
|
|
5818
5897
|
try {
|
|
5898
|
+
if (options.endpointId) await allowedEndpoint(api, settings, options.endpointId);
|
|
5899
|
+
else await allowedEvent(api, settings, options.eventId);
|
|
5819
5900
|
const deliveries = options.endpointId ? await api.listRelayEndpointDeliveries(options.endpointId) : await api.listRelayEventDeliveries(options.eventId);
|
|
5820
5901
|
const items = Array.isArray(deliveries) ? deliveries : deliveries.rows || [];
|
|
5821
5902
|
if (isAgentMode()) {
|
|
@@ -7427,7 +7508,7 @@ async function syncModel(api, profile, options) {
|
|
|
7427
7508
|
updateModelState(platform, model, { status: "failed", pagesProcessed, lastCursor }),
|
|
7428
7509
|
(async () => {
|
|
7429
7510
|
try {
|
|
7430
|
-
const { getBackend: getBackend2 } = await import("./runtime-
|
|
7511
|
+
const { getBackend: getBackend2 } = await import("./runtime-2OVXKNJS.js");
|
|
7431
7512
|
const backend = await getBackend2();
|
|
7432
7513
|
await Promise.race([
|
|
7433
7514
|
backend.close(),
|
|
@@ -7793,7 +7874,7 @@ async function syncModel(api, profile, options) {
|
|
|
7793
7874
|
db.exec(`DROP TABLE IF EXISTS _seen_ids`);
|
|
7794
7875
|
}
|
|
7795
7876
|
if (options.toMemory !== false) {
|
|
7796
|
-
const backend = await (await import("./runtime-
|
|
7877
|
+
const backend = await (await import("./runtime-2OVXKNJS.js")).getBackend();
|
|
7797
7878
|
const type = `${platform}/${model}`;
|
|
7798
7879
|
const existing = await backend.listKeysByType(type);
|
|
7799
7880
|
const sourcePrefix = `${type}:`;
|
|
@@ -7894,7 +7975,7 @@ async function syncModel(api, profile, options) {
|
|
|
7894
7975
|
let statusCounts;
|
|
7895
7976
|
if (options.toMemory !== false) {
|
|
7896
7977
|
try {
|
|
7897
|
-
const backend = await (await import("./runtime-
|
|
7978
|
+
const backend = await (await import("./runtime-2OVXKNJS.js")).getBackend();
|
|
7898
7979
|
const typeName = `${platform}/${model}`;
|
|
7899
7980
|
const [active, archived] = await Promise.all([
|
|
7900
7981
|
backend.count(typeName, { status: "active" }),
|
|
@@ -9616,7 +9697,7 @@ ${result.total} results`);
|
|
|
9616
9697
|
}
|
|
9617
9698
|
}
|
|
9618
9699
|
async function syncSqlCommand(platformModel, sql) {
|
|
9619
|
-
const { syncSqlCommand: runSyncSql } = await import("./sql-
|
|
9700
|
+
const { syncSqlCommand: runSyncSql } = await import("./sql-KRQUWOPT.js");
|
|
9620
9701
|
await runSyncSql(platformModel, sql);
|
|
9621
9702
|
}
|
|
9622
9703
|
async function syncDeleteCommand(platformModel, options) {
|
|
@@ -9694,7 +9775,7 @@ async function syncDeleteCommand(platformModel, options) {
|
|
|
9694
9775
|
async function maybeAutoMigrateLegacy(platform, models) {
|
|
9695
9776
|
const dbSize = getDatabaseSize(platform);
|
|
9696
9777
|
if (!dbSize || dbSize === "0 B") return;
|
|
9697
|
-
const { getBackend: getBackend2 } = await import("./runtime-
|
|
9778
|
+
const { getBackend: getBackend2 } = await import("./runtime-2OVXKNJS.js");
|
|
9698
9779
|
const backend = await getBackend2();
|
|
9699
9780
|
let memoryHasData = false;
|
|
9700
9781
|
for (const model of models) {
|
|
@@ -9710,7 +9791,7 @@ async function maybeAutoMigrateLegacy(platform, models) {
|
|
|
9710
9791
|
` detected legacy .one/sync/data/${platform}.db (${dbSize}) \u2014 auto-migrating into memory before sync.
|
|
9711
9792
|
`
|
|
9712
9793
|
);
|
|
9713
|
-
const { memMigrateCommand: memMigrateCommand3 } = await import("./migrate-
|
|
9794
|
+
const { memMigrateCommand: memMigrateCommand3 } = await import("./migrate-RJ7F2LPT.js");
|
|
9714
9795
|
await memMigrateCommand3({ platform, yes: true });
|
|
9715
9796
|
return;
|
|
9716
9797
|
}
|
|
@@ -9719,7 +9800,7 @@ async function maybeAutoMigrateLegacy(platform, models) {
|
|
|
9719
9800
|
initialValue: true
|
|
9720
9801
|
});
|
|
9721
9802
|
if (p6.isCancel(shouldMigrate) || !shouldMigrate) return;
|
|
9722
|
-
const { memMigrateCommand: memMigrateCommand2 } = await import("./migrate-
|
|
9803
|
+
const { memMigrateCommand: memMigrateCommand2 } = await import("./migrate-RJ7F2LPT.js");
|
|
9723
9804
|
await memMigrateCommand2({ platform, yes: true });
|
|
9724
9805
|
}
|
|
9725
9806
|
async function syncSuggestSearchableCommand(platformModel, options = {}) {
|
|
@@ -9780,7 +9861,7 @@ async function syncSuggestSearchableCommand(platformModel, options = {}) {
|
|
|
9780
9861
|
async function syncListCommand(platform) {
|
|
9781
9862
|
const profiles = listProfiles(platform);
|
|
9782
9863
|
const state = await readSyncState();
|
|
9783
|
-
const { getBackend: getBackend2 } = await import("./runtime-
|
|
9864
|
+
const { getBackend: getBackend2 } = await import("./runtime-2OVXKNJS.js");
|
|
9784
9865
|
const backend = await getBackend2();
|
|
9785
9866
|
const syncs = await Promise.all(profiles.map(async (p9) => {
|
|
9786
9867
|
const modelState = state[p9.platform]?.[p9.model];
|
|
@@ -10056,7 +10137,7 @@ function registerSyncSubcommands(sync) {
|
|
|
10056
10137
|
await syncSqlCommand(platformModel, sql);
|
|
10057
10138
|
});
|
|
10058
10139
|
sync.command("schema <platform/model>").description("Inspect the JSON structure of synced records (field paths, types, examples) \u2014 useful before writing `sync sql` queries").action(async (platformModel) => {
|
|
10059
|
-
const { syncSchemaCommand } = await import("./schema-
|
|
10140
|
+
const { syncSchemaCommand } = await import("./schema-FIIT33OD.js");
|
|
10060
10141
|
await syncSchemaCommand(platformModel);
|
|
10061
10142
|
});
|
|
10062
10143
|
sync.command("delete <platform/model>").description('Delete records from local sync data (e.g. one sync delete notion/pages --id "abc-123")').option("--id <value>", "Delete record by ID").option("--where <conditions>", 'Delete records matching conditions (e.g. "status=archived")').option("--where-sql <predicate>", `Delete using a raw SQL WHERE clause (e.g. "json_extract(data, '$.type') = 'promotion'")`).option("--yes", "Skip confirmation prompt").action(async (platformModel, options) => {
|
|
@@ -10833,7 +10914,7 @@ async function memDoctorCommand() {
|
|
|
10833
10914
|
}
|
|
10834
10915
|
if (cfg.embedding.provider === "openai") {
|
|
10835
10916
|
try {
|
|
10836
|
-
const { embed: embed2 } = await import("./embedding-
|
|
10917
|
+
const { embed: embed2 } = await import("./embedding-YIXO45HW.js");
|
|
10837
10918
|
const result = await embed2("connectivity check");
|
|
10838
10919
|
checks.push({
|
|
10839
10920
|
name: "OpenAI embedding provider reachable",
|
|
@@ -11374,15 +11455,16 @@ one --agent flow list # List all workflows
|
|
|
11374
11455
|
|
|
11375
11456
|
**Key concepts:**
|
|
11376
11457
|
- Workflows live at \`.one/flows/<key>/flow.json\` (folder layout \u2014 REQUIRED for new flows). Flows can be organized into subdirectory groups: \`.one/flows/<group>/<key>/flow.json\`. Reference them as \`group/key\` or just the bare key. The legacy \`.one/flows/<key>.flow.json\` single-file layout is DEPRECATED but still loads for backward compatibility
|
|
11377
|
-
- Code steps can reference an external \`.mjs\` module under the flow's \`lib/\` folder (stdin JSON in, stdout JSON out)
|
|
11458
|
+
- Code steps can reference an external \`.mjs\` module under the flow's \`lib/\` folder (stdin JSON in, stdout JSON out). Modules have full Node access, so flows that use them need \`--allow-code\`
|
|
11459
|
+
- Inline JavaScript (transforms, conditions, \`if\`/\`unless\`, \`code.source\`) runs in a sandbox: no files, programs, network, timers or environment of its own, and no flag needed
|
|
11378
11460
|
- 12 step types: action, transform, code, condition, loop, parallel, file-read, file-write, while, flow, paginate, bash
|
|
11379
11461
|
- Data wiring via selectors: \`$.input.param\`, \`$.steps.stepId.response\`, \`$.loop.item\`
|
|
11380
11462
|
- AI analysis via bash steps: \`claude --print --output-format json\` with \`parseEnvelope: true\` (unwraps the CLI envelope + fences + preamble into clean parsed JSON; use instead of \`parseJson\` for claude steps)
|
|
11381
|
-
- Use \`--allow-bash\` to enable bash steps, \`--mock\` for dry-run with realistic mock responses (uses example data from action schemas)
|
|
11463
|
+
- Use \`--allow-bash\` to enable bash steps, \`--allow-code\` to enable \`code.module\` steps, \`--mock\` for dry-run with realistic mock responses (uses example data from action schemas)
|
|
11382
11464
|
- Use \`--skip-validation\` to bypass input validation on action steps
|
|
11383
11465
|
- Use \`--output-file <path>\` to stream the full result to a file instead of stdout \u2014 for large results that would otherwise be truncated or hit the JSON string-size limit; stdout (and \`--agent\` output) then carries an \`outputFile\` pointer instead of inline \`steps\`
|
|
11384
11466
|
- Step-level \`if\`/\`unless\` (and \`while\`/\`condition\` steps) are null-safe: a condition referencing a skipped or not-yet-run step's output (e.g. \`$.steps.maybeSkipped.output.x\`) evaluates to \`false\` instead of crashing the flow
|
|
11385
|
-
- Debugging: \`--dry-run\` resolves each step's interpolations and shows what they evaluate to without executing (\`$.steps.*\` refs are reported as deferred); \`--stop-after <stepId>\` runs up to a step then stops; \`--dry-run --stop-after <stepId>\` runs earlier steps for real then dry-resolves the target against their output; \`flow inspect <runId>\` shows a past run's per-step outputs (post-mortem, no re-run; \`--full\` for untruncated)
|
|
11467
|
+
- Debugging: \`--dry-run\` resolves each step's interpolations and shows what they evaluate to without executing actions, code, bash or file steps (transform and condition expressions are evaluated, in the sandbox; \`$.steps.*\` refs are reported as deferred); \`--stop-after <stepId>\` runs up to a step then stops; \`--dry-run --stop-after <stepId>\` runs earlier steps for real then dry-resolves the target against their output; \`flow inspect <runId>\` shows a past run's per-step outputs (post-mortem, no re-run; \`--full\` for untruncated)
|
|
11386
11468
|
|
|
11387
11469
|
### 3. Relay \u2014 Webhook event forwarding between platforms
|
|
11388
11470
|
Receive webhooks from platforms (Stripe, GitHub, Airtable, Attio, Google Calendar) and forward event data to any connected platform using passthrough actions with Handlebars templates. No middleware, no code.
|
|
@@ -13822,7 +13904,7 @@ var flow = program.command("flow").alias("f").description("Create, execute, and
|
|
|
13822
13904
|
flow.command("create [key]").description("Create a new workflow from JSON definition").option("--definition <json>", "Workflow definition as JSON string").option("-o, --output <path>", "Custom output path (default .one/flows/<key>/flow.json)").action(async (key, options) => {
|
|
13823
13905
|
await flowCreateCommand(key, options);
|
|
13824
13906
|
});
|
|
13825
|
-
flow.command("execute <keyOrPath>").alias("x").description("Execute a workflow by key or file path").option("-i, --input <name=value>", "Input parameter (repeatable)", collect, []).option("--dry-run", "Resolve each step's interpolations and show what they evaluate to, without
|
|
13907
|
+
flow.command("execute <keyOrPath>").alias("x").description("Execute a workflow by key or file path").option("-i, --input <name=value>", "Input parameter (repeatable)", collect, []).option("--dry-run", "Resolve each step's interpolations and show what they evaluate to, without running actions, code, bash or file steps. Transform and condition expressions are evaluated in the sandbox ($.steps.* refs resolve at runtime)").option("--mock", "With --dry-run: execute transforms/code with realistic mock API responses").option("--stop-after <stepId>", "Execute steps up to and including <stepId>, then stop (later steps are not run). With --dry-run, runs earlier steps for real and dry-resolves <stepId> against their output without executing it. See: one flow inspect").option("--skip-validation", "Skip input validation against action schemas").option("--allow-bash", "Allow bash step execution (disabled by default for security)").option("--allow-code", "Allow code.module steps, which run a .mjs file with full Node access (disabled by default for security). Inline transforms, conditions and code.source run sandboxed and need no flag").option("-v, --verbose", "Show full request/response for each step").option("--output-file <path>", "Write the full result to a file (streamed) instead of stdout \u2014 avoids truncation/string-limit errors for large results; stdout/agent output then carries an outputFile pointer").action(async (keyOrPath, options) => {
|
|
13826
13908
|
await flowExecuteCommand(keyOrPath, options);
|
|
13827
13909
|
});
|
|
13828
13910
|
flow.command("list").alias("ls").description("List all workflows in .one/flows/").action(async () => {
|
|
@@ -13831,7 +13913,7 @@ flow.command("list").alias("ls").description("List all workflows in .one/flows/"
|
|
|
13831
13913
|
flow.command("validate <keyOrPath>").description("Validate a workflow JSON file").action(async (keyOrPath) => {
|
|
13832
13914
|
await flowValidateCommand(keyOrPath);
|
|
13833
13915
|
});
|
|
13834
|
-
flow.command("resume <runId>").description("Resume a paused or failed workflow run").option("--allow-bash", "Allow bash step execution (disabled by default for security) \u2014 required to resume any flow containing bash steps").action(async (runId, options) => {
|
|
13916
|
+
flow.command("resume <runId>").description("Resume a paused or failed workflow run").option("--allow-bash", "Allow bash step execution (disabled by default for security) \u2014 required to resume any flow containing bash steps").option("--allow-code", "Allow code.module steps (full Node access) \u2014 required to resume any flow containing them").action(async (runId, options) => {
|
|
13835
13917
|
await flowResumeCommand(runId, options);
|
|
13836
13918
|
});
|
|
13837
13919
|
flow.command("runs [flowKey]").description("List workflow runs (optionally filtered by flow key)").action(async (flowKey) => {
|
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
dotPathToJsonbExpr,
|
|
4
4
|
memMigrateCommand,
|
|
5
5
|
reviveStringifiedJson
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-LEJKEGB6.js";
|
|
7
7
|
import "./chunk-44CV5IMX.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-B5YDLVY5.js";
|
|
9
9
|
import "./chunk-Q6PWTATS.js";
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
10
|
+
import "./chunk-4H5L3SBY.js";
|
|
11
|
+
import "./chunk-2OIJGF77.js";
|
|
12
|
+
import "./chunk-XUAUDMQE.js";
|
|
13
13
|
export {
|
|
14
14
|
buildIdentityMap,
|
|
15
15
|
dotPathToJsonbExpr,
|
|
@@ -5,9 +5,9 @@ import {
|
|
|
5
5
|
resetBackendSingleton,
|
|
6
6
|
updateRecord,
|
|
7
7
|
upsertRecord
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-4H5L3SBY.js";
|
|
9
|
+
import "./chunk-2OIJGF77.js";
|
|
10
|
+
import "./chunk-XUAUDMQE.js";
|
|
11
11
|
export {
|
|
12
12
|
addRecord,
|
|
13
13
|
closeBackendIfCached,
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
okJson,
|
|
3
3
|
requireMemoryInit
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-B5YDLVY5.js";
|
|
5
5
|
import {
|
|
6
6
|
isAgentMode,
|
|
7
7
|
note
|
|
8
8
|
} from "./chunk-Q6PWTATS.js";
|
|
9
9
|
import {
|
|
10
10
|
getBackend
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-4H5L3SBY.js";
|
|
12
|
+
import "./chunk-2OIJGF77.js";
|
|
13
|
+
import "./chunk-XUAUDMQE.js";
|
|
14
14
|
|
|
15
15
|
// src/lib/memory/sync/schema.ts
|
|
16
16
|
import pc from "picocolors";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
memSqlCommand,
|
|
3
|
+
syncSqlCommand
|
|
4
|
+
} from "./chunk-TSMVFVQ3.js";
|
|
5
|
+
import "./chunk-B5YDLVY5.js";
|
|
6
|
+
import "./chunk-Q6PWTATS.js";
|
|
7
|
+
import "./chunk-4H5L3SBY.js";
|
|
8
|
+
import "./chunk-2OIJGF77.js";
|
|
9
|
+
import "./chunk-XUAUDMQE.js";
|
|
10
|
+
export {
|
|
11
|
+
memSqlCommand,
|
|
12
|
+
syncSqlCommand
|
|
13
|
+
};
|