@runtypelabs/cli 2.59.0 → 2.59.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-0-T9NWjH.js +3899 -0
- package/dist/chunk-0x7UKC1U.js +17 -0
- package/dist/chunk-2ySxXtcg.js +418 -0
- package/dist/chunk-3An_BRHv.js +501 -0
- package/dist/chunk-6uTxgdiY.js +16218 -0
- package/dist/chunk-87nRnNRG.js +1363 -0
- package/dist/chunk-B3wo8uRx.js +322 -0
- package/dist/chunk-BGp3ZdBy.js +560 -0
- package/dist/chunk-BJQv9Elp.js +107 -0
- package/dist/chunk-BOpO6xE-.js +6053 -0
- package/dist/chunk-BQXXCL8B.js +102 -0
- package/dist/chunk-BV-8isOd.js +34 -0
- package/dist/chunk-BVMhjGVe.js +826 -0
- package/dist/chunk-BW2fg46T.js +141 -0
- package/dist/chunk-BWJdY5Ag.js +36 -0
- package/dist/chunk-BYJOrLhh.js +302 -0
- package/dist/chunk-BYab8EVL.js +127 -0
- package/dist/chunk-BfEKvp7h.js +82 -0
- package/dist/chunk-BhgLSfH6.js +1123 -0
- package/dist/chunk-BirUxTtH.js +296 -0
- package/dist/chunk-BmB6UVZ9.js +1559 -0
- package/dist/chunk-BnWhIqW1.js +109 -0
- package/dist/chunk-Bpfnfk0t.js +123 -0
- package/dist/chunk-BrhgdnM3.js +108 -0
- package/dist/chunk-Bt0XAgX5.js +327 -0
- package/dist/chunk-Bu0FJr6S.js +84 -0
- package/dist/chunk-BvEoKpN3.js +255 -0
- package/dist/chunk-BxNJgYbE.js +28 -0
- package/dist/chunk-C1OFhd7F.js +6131 -0
- package/dist/chunk-C7e7WwbU.js +331 -0
- package/dist/chunk-CDTYP6bN.js +558 -0
- package/dist/chunk-CGDQoqDC.js +24 -0
- package/dist/chunk-CJraEBVd.js +127 -0
- package/dist/chunk-CQrNhOtv.js +40 -0
- package/dist/chunk-CW6AzBH6.js +128 -0
- package/dist/chunk-CXgL4w-9.js +317 -0
- package/dist/chunk-CZrqoPyf.js +233 -0
- package/dist/chunk-CcFCyqbB.js +83 -0
- package/dist/chunk-CdaIvO-y.js +485 -0
- package/dist/chunk-CehSXtgK.js +624 -0
- package/dist/chunk-Ciqkop65.js +218 -0
- package/dist/chunk-CoAWdSiE.js +43 -0
- package/dist/chunk-Crb4y7t4.js +830 -0
- package/dist/chunk-CrlqIfmb.js +337 -0
- package/dist/chunk-Cs4pwCQ-.js +324 -0
- package/dist/chunk-CwM_9y01.js +519 -0
- package/dist/chunk-CyRbIJg8.js +440 -0
- package/dist/chunk-D0OHsyMy.js +212 -0
- package/dist/chunk-D3y2bURs.js +1347 -0
- package/dist/chunk-D4_mJk03.js +2338 -0
- package/dist/chunk-D6C8rned.js +578 -0
- package/dist/chunk-D9ZbUnks.js +11 -0
- package/dist/chunk-DEPmLshX.js +834 -0
- package/dist/chunk-DFj1UPB2.js +330 -0
- package/dist/chunk-DGdFdZVf.js +197 -0
- package/dist/chunk-DGv7X9S_.js +63 -0
- package/dist/chunk-DJQ47WYZ.js +664 -0
- package/dist/chunk-DJw3O61j.js +1974 -0
- package/dist/chunk-DK4FbWVK.js +100 -0
- package/dist/chunk-DSRYhUus.js +993 -0
- package/dist/chunk-DajZ9Eg4.js +299 -0
- package/dist/chunk-Df4dunvU.js +195 -0
- package/dist/chunk-DjNTPhfO.js +481 -0
- package/dist/chunk-Dn8eaJuu.js +1042 -0
- package/dist/chunk-DwDWqSxM.js +637 -0
- package/dist/chunk-Dz7cEtxl.js +84 -0
- package/dist/chunk-E_0bgjrS.js +359 -0
- package/dist/chunk-KPYN2vUp.js +776 -0
- package/dist/chunk-KcqPQJBi.js +86 -0
- package/dist/chunk-N9H0JnoG.js +349 -0
- package/dist/chunk-NONFcXkn.js +728 -0
- package/dist/chunk-PrFjcpmH.js +256 -0
- package/dist/chunk-QSfNYiw9.js +11 -0
- package/dist/chunk-R265bzj9.js +226 -0
- package/dist/chunk-X9V_r6jM.js +166 -0
- package/dist/chunk-ZBtPUtyA.js +55 -0
- package/dist/chunk-ZCTfmOs7.js +4939 -0
- package/dist/chunk-h6oavj0t.js +97 -0
- package/dist/chunk-i7DwkvvD.js +42 -0
- package/dist/chunk-mG-4eZ6S.js +203 -0
- package/dist/chunk-o0ygUbCf.js +313 -0
- package/dist/chunk-ucu5lrDZ.js +5715 -0
- package/dist/index.js +11367 -73764
- package/package.json +6 -6
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { t as redactPiiText } from "./chunk-mG-4eZ6S.js";
|
|
3
|
+
// src/lib/local-harness/delivery/redaction.ts
|
|
4
|
+
const SENSITIVE_KEY = /^(?:authorization|password|secret|token|access[_-]?token|refresh[_-]?token|client[_-]?secret|credentials?|api[_-]?key|cookie|private[_-]?key|environment|env)$/i;
|
|
5
|
+
const MARKER = "[redacted]";
|
|
6
|
+
function redactHarnessValue(value, policy, secrets = []) {
|
|
7
|
+
let changed = false;
|
|
8
|
+
const text = (input) => {
|
|
9
|
+
let output = input;
|
|
10
|
+
for (const secret of secrets) if (secret.length >= 4) output = output.split(secret).join(MARKER);
|
|
11
|
+
output = output.replace(/\b(?:Bearer\s+\S+|(?:sk-|rt_|sst_)[A-Za-z0-9_-]{8,})/gi, MARKER);
|
|
12
|
+
output = output.replace(/(https?:\/\/)[^\s/@]+:[^\s/@]+@/gi, "$1[redacted]@");
|
|
13
|
+
output = output.replace(/([?&](?:key|token|secret|password|api_key|client[_-]?secret)=)[^&#\s]+/gi, "$1[redacted]");
|
|
14
|
+
if (policy === "redacted") output = redactPiiText(output, { mode: "redact" }).text;
|
|
15
|
+
if (output !== input) changed = true;
|
|
16
|
+
return output;
|
|
17
|
+
};
|
|
18
|
+
const walk = (input, depth) => {
|
|
19
|
+
if (depth > 24) {
|
|
20
|
+
changed = true;
|
|
21
|
+
return "[depth limit]";
|
|
22
|
+
}
|
|
23
|
+
if (typeof input === "string") {
|
|
24
|
+
if (/^\s*[[{]/.test(input)) try {
|
|
25
|
+
const parsed = JSON.parse(input);
|
|
26
|
+
return JSON.stringify(walk(parsed, depth + 1));
|
|
27
|
+
} catch {
|
|
28
|
+
return text(input);
|
|
29
|
+
}
|
|
30
|
+
return text(input);
|
|
31
|
+
}
|
|
32
|
+
if (input === null || typeof input === "boolean" || typeof input === "number") return input;
|
|
33
|
+
if (Array.isArray(input)) return input.map((entry) => walk(entry, depth + 1));
|
|
34
|
+
if (typeof input !== "object") return void 0;
|
|
35
|
+
return Object.fromEntries(Object.entries(input).map(([key, entry]) => {
|
|
36
|
+
if (SENSITIVE_KEY.test(key)) {
|
|
37
|
+
changed = true;
|
|
38
|
+
return [key, MARKER];
|
|
39
|
+
}
|
|
40
|
+
return [text(key), walk(entry, depth + 1)];
|
|
41
|
+
}));
|
|
42
|
+
};
|
|
43
|
+
return {
|
|
44
|
+
value: walk(value, 0),
|
|
45
|
+
changed
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function redactObservation(observation, policy, secrets) {
|
|
49
|
+
if (policy === "metrics") {
|
|
50
|
+
const tool = observation.tool;
|
|
51
|
+
const removedContent = observation.native !== void 0 || observation.message !== void 0 || tool?.input !== void 0 || tool?.output !== void 0;
|
|
52
|
+
const result = redactHarnessValue({
|
|
53
|
+
kind: observation.kind,
|
|
54
|
+
nativeId: observation.nativeId,
|
|
55
|
+
nativeSessionId: observation.nativeSessionId,
|
|
56
|
+
nativeTurnId: observation.nativeTurnId,
|
|
57
|
+
parentId: observation.parentId,
|
|
58
|
+
nativeTime: observation.nativeTime,
|
|
59
|
+
...tool ? { tool: {
|
|
60
|
+
id: tool.id,
|
|
61
|
+
name: tool.name,
|
|
62
|
+
nativeName: tool.nativeName,
|
|
63
|
+
mcpServer: tool.mcpServer,
|
|
64
|
+
mcpTool: tool.mcpTool,
|
|
65
|
+
status: tool.status,
|
|
66
|
+
startedAt: tool.startedAt,
|
|
67
|
+
endedAt: tool.endedAt,
|
|
68
|
+
durationMs: tool.durationMs
|
|
69
|
+
} } : {},
|
|
70
|
+
...observation.usage ? { usage: observation.usage } : {},
|
|
71
|
+
...observation.permission ? { permission: observation.permission } : {},
|
|
72
|
+
...observation.lifecycle ? { lifecycle: { state: observation.lifecycle.state } } : {}
|
|
73
|
+
}, policy, secrets);
|
|
74
|
+
return {
|
|
75
|
+
observation: result.value,
|
|
76
|
+
changed: removedContent || result.changed
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const result = redactHarnessValue(observation, policy, secrets);
|
|
80
|
+
return {
|
|
81
|
+
observation: result.value,
|
|
82
|
+
changed: result.changed
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
export { redactObservation as n, redactHarnessValue as t };
|
|
86
|
+
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { t as isTTY } from "./index.js";
|
|
3
|
+
import { ConfirmPrompt, DataList, EntityCard, MutationResult, React, render, useEffect, useState } from "./chunk-CoAWdSiE.js";
|
|
4
|
+
import { r as createCliClient } from "./chunk-BW2fg46T.js";
|
|
5
|
+
import { n as ensureAuth } from "./chunk-CJraEBVd.js";
|
|
6
|
+
import { a as printJson, i as printDetail, o as printList, r as getTotalCount, s as printNextCursorHint } from "./chunk-CcFCyqbB.js";
|
|
7
|
+
import { t as readJsonFile } from "./chunk-DGv7X9S_.js";
|
|
8
|
+
import { n as addExecutionInputOptions, r as resolveExecutionInput, t as runExecution } from "./chunk-Cs4pwCQ-.js";
|
|
9
|
+
import { c as buildEntityPullCommand, n as FLOW_ENSURE_SPEC, s as buildEntityEnsureCommand } from "./chunk-BirUxTtH.js";
|
|
10
|
+
import { Command } from "commander";
|
|
11
|
+
import chalk from "chalk";
|
|
12
|
+
// src/commands/flows.ts
|
|
13
|
+
/** Build the typed list params the SDK endpoint expects from the CLI's string flags. */
|
|
14
|
+
function flowsListParams(options) {
|
|
15
|
+
return {
|
|
16
|
+
limit: options.limit ? Number(options.limit) : void 0,
|
|
17
|
+
cursor: options.cursor
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
const flowsCommand = new Command("flows").description("Manage flows");
|
|
21
|
+
flowsCommand.addCommand(buildEntityEnsureCommand(FLOW_ENSURE_SPEC));
|
|
22
|
+
flowsCommand.addCommand(buildEntityPullCommand(FLOW_ENSURE_SPEC));
|
|
23
|
+
flowsCommand.command("list").description("List all flows").option("--limit <n>", "Limit results (defaults to the API page size)").option("--cursor <cursor>", "Pagination cursor for the next page").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (options) => {
|
|
24
|
+
const apiKey = await ensureAuth();
|
|
25
|
+
if (!apiKey) return;
|
|
26
|
+
const client = createCliClient(apiKey);
|
|
27
|
+
const listParams = flowsListParams(options);
|
|
28
|
+
if (!isTTY(options) || options.json) {
|
|
29
|
+
try {
|
|
30
|
+
const data = await client.flows.list(listParams);
|
|
31
|
+
if (options.json) {
|
|
32
|
+
printJson(data);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
printList(data.data, {
|
|
36
|
+
title: "Your Flows",
|
|
37
|
+
columns: [{
|
|
38
|
+
key: "id",
|
|
39
|
+
color: "green"
|
|
40
|
+
}, { key: "name" }],
|
|
41
|
+
emptyMessage: "No flows found",
|
|
42
|
+
total: getTotalCount(data.pagination)
|
|
43
|
+
});
|
|
44
|
+
printNextCursorHint("runtype flows list", data.pagination);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
47
|
+
console.error(chalk.red(`Failed to fetch flows: ${message}`));
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const App = () => {
|
|
53
|
+
const [items, setItems] = useState(null);
|
|
54
|
+
const [error, setError] = useState(null);
|
|
55
|
+
const [total, setTotal] = useState();
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
client.flows.list(listParams).then((res) => {
|
|
58
|
+
setItems(res.data);
|
|
59
|
+
setTotal(getTotalCount(res.pagination));
|
|
60
|
+
}).catch((err) => setError(err instanceof Error ? err : new Error(String(err))));
|
|
61
|
+
}, []);
|
|
62
|
+
return React.createElement(DataList, {
|
|
63
|
+
title: "Your Flows",
|
|
64
|
+
items,
|
|
65
|
+
error,
|
|
66
|
+
loading: items === null && error === null,
|
|
67
|
+
total,
|
|
68
|
+
renderCard: (item) => {
|
|
69
|
+
const flow = item;
|
|
70
|
+
return React.createElement(EntityCard, { fields: [{
|
|
71
|
+
label: "ID",
|
|
72
|
+
value: flow.id,
|
|
73
|
+
color: "green"
|
|
74
|
+
}, {
|
|
75
|
+
label: "Name",
|
|
76
|
+
value: flow.name
|
|
77
|
+
}] });
|
|
78
|
+
},
|
|
79
|
+
emptyMessage: "No flows found"
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
const { waitUntilExit } = render(React.createElement(App));
|
|
83
|
+
await waitUntilExit();
|
|
84
|
+
});
|
|
85
|
+
flowsCommand.command("get <id>").description("Get flow details").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (id, options) => {
|
|
86
|
+
const apiKey = await ensureAuth();
|
|
87
|
+
if (!apiKey) return;
|
|
88
|
+
const client = createCliClient(apiKey);
|
|
89
|
+
if (!isTTY(options) || options.json) {
|
|
90
|
+
try {
|
|
91
|
+
const data = await client.flows.get(id);
|
|
92
|
+
if (options.json) {
|
|
93
|
+
printJson(data);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
printDetail("Flow", [
|
|
97
|
+
{
|
|
98
|
+
label: "ID",
|
|
99
|
+
value: data.id
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
label: "Name",
|
|
103
|
+
value: data.name
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
label: "Steps",
|
|
107
|
+
value: data.stepCount ?? data.flowSteps?.length
|
|
108
|
+
}
|
|
109
|
+
]);
|
|
110
|
+
} catch (error) {
|
|
111
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
112
|
+
console.error(chalk.red(`Failed to fetch flow: ${message}`));
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const App = () => {
|
|
118
|
+
const [items, setItems] = useState(null);
|
|
119
|
+
const [error, setError] = useState(null);
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
client.flows.get(id).then((res) => setItems([res])).catch((err) => setError(err instanceof Error ? err : new Error(String(err))));
|
|
122
|
+
}, []);
|
|
123
|
+
return React.createElement(DataList, {
|
|
124
|
+
title: "Flow",
|
|
125
|
+
items,
|
|
126
|
+
error,
|
|
127
|
+
loading: items === null && error === null,
|
|
128
|
+
renderCard: (item) => {
|
|
129
|
+
const flow = item;
|
|
130
|
+
return React.createElement(EntityCard, { fields: [
|
|
131
|
+
{
|
|
132
|
+
label: "ID",
|
|
133
|
+
value: flow.id,
|
|
134
|
+
color: "green"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
label: "Name",
|
|
138
|
+
value: flow.name
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
label: "Steps",
|
|
142
|
+
value: flow.stepCount ?? flow.flowSteps?.length
|
|
143
|
+
}
|
|
144
|
+
] });
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
};
|
|
148
|
+
const { waitUntilExit } = render(React.createElement(App));
|
|
149
|
+
await waitUntilExit();
|
|
150
|
+
});
|
|
151
|
+
addExecutionInputOptions(flowsCommand.command("run <id>").description("Execute a flow via dispatch").option("-r, --record <id>", "Record ID to run with").option("-m, --message <text>", "Message to send").option("--stream", "Stream the response (default)", true).option("--no-stream", "Wait for complete response").option("--json", "Output one final JSON result").option("--jsonl", "Output stream events and a terminal execution_summary as JSON lines")).action(async (flowId, options) => {
|
|
152
|
+
await runExecution(options, () => ({
|
|
153
|
+
...resolveExecutionInput(options),
|
|
154
|
+
flow: { id: flowId },
|
|
155
|
+
options: { streamResponse: options.stream }
|
|
156
|
+
}), (client, payload) => options.stream ? client.dispatch.executeStream(payload) : client.dispatch.execute(payload), "flow");
|
|
157
|
+
});
|
|
158
|
+
flowsCommand.command("create").description("Create a new flow").requiredOption("-n, --name <name>", "Flow name").option("-d, --description <desc>", "Flow description").option("--from-file <file>", "Import flow from JSON file").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (options) => {
|
|
159
|
+
const apiKey = await ensureAuth();
|
|
160
|
+
if (!apiKey) return;
|
|
161
|
+
const client = createCliClient(apiKey);
|
|
162
|
+
let body = {
|
|
163
|
+
name: options.name,
|
|
164
|
+
description: options.description
|
|
165
|
+
};
|
|
166
|
+
if (options.fromFile) {
|
|
167
|
+
body = { ...readJsonFile(options.fromFile, {
|
|
168
|
+
label: "flow file",
|
|
169
|
+
unwrapKey: "flow"
|
|
170
|
+
}) };
|
|
171
|
+
if (options.name !== void 0) body.name = options.name;
|
|
172
|
+
if (options.description !== void 0) body.description = options.description;
|
|
173
|
+
}
|
|
174
|
+
if (!isTTY(options) || options.json) {
|
|
175
|
+
try {
|
|
176
|
+
const data = await client.post("/flows", body);
|
|
177
|
+
if (options.json) {
|
|
178
|
+
printJson(data);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
console.log(` ID: ${chalk.green(data.id)}`);
|
|
182
|
+
console.log(` Name: ${data.name}`);
|
|
183
|
+
} catch (error) {
|
|
184
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
185
|
+
console.error(chalk.red(`Failed to create flow: ${message}`));
|
|
186
|
+
process.exit(1);
|
|
187
|
+
}
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
const App = () => {
|
|
191
|
+
const [loading, setLoading] = useState(true);
|
|
192
|
+
const [success, setSuccess] = useState(null);
|
|
193
|
+
const [error, setError] = useState(null);
|
|
194
|
+
const [result, setResult] = useState(null);
|
|
195
|
+
useEffect(() => {
|
|
196
|
+
client.post("/flows", body).then((data) => {
|
|
197
|
+
setResult(data);
|
|
198
|
+
setSuccess(true);
|
|
199
|
+
setLoading(false);
|
|
200
|
+
}).catch((err) => {
|
|
201
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
202
|
+
setSuccess(false);
|
|
203
|
+
setLoading(false);
|
|
204
|
+
});
|
|
205
|
+
}, []);
|
|
206
|
+
return React.createElement(MutationResult, {
|
|
207
|
+
loading,
|
|
208
|
+
loadingLabel: "Creating flow...",
|
|
209
|
+
success,
|
|
210
|
+
successMessage: "Flow created",
|
|
211
|
+
error,
|
|
212
|
+
result: result ? React.createElement(EntityCard, { fields: [{
|
|
213
|
+
label: "ID",
|
|
214
|
+
value: result.id,
|
|
215
|
+
color: "green"
|
|
216
|
+
}, {
|
|
217
|
+
label: "Name",
|
|
218
|
+
value: result.name
|
|
219
|
+
}] }) : void 0
|
|
220
|
+
});
|
|
221
|
+
};
|
|
222
|
+
const { waitUntilExit } = render(React.createElement(App));
|
|
223
|
+
await waitUntilExit();
|
|
224
|
+
});
|
|
225
|
+
flowsCommand.command("update <id>").description("Update a flow").option("-n, --name <name>", "New flow name").option("-d, --description <desc>", "New flow description").option("--from-file <file>", "Update flow from JSON file (full body)").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (id, options) => {
|
|
226
|
+
const apiKey = await ensureAuth();
|
|
227
|
+
if (!apiKey) return;
|
|
228
|
+
const client = createCliClient(apiKey);
|
|
229
|
+
let body = {};
|
|
230
|
+
if (options.fromFile) body = readJsonFile(options.fromFile, {
|
|
231
|
+
label: "flow file",
|
|
232
|
+
unwrapKey: "flow"
|
|
233
|
+
});
|
|
234
|
+
if (options.name !== void 0) body.name = options.name;
|
|
235
|
+
if (options.description !== void 0) body.description = options.description;
|
|
236
|
+
if (Object.keys(body).length === 0) {
|
|
237
|
+
console.error(chalk.red("Error: provide at least one of --name, --description, or --from-file"));
|
|
238
|
+
process.exit(1);
|
|
239
|
+
}
|
|
240
|
+
if (!isTTY(options) || options.json) {
|
|
241
|
+
try {
|
|
242
|
+
const data = await client.put(`/flows/${id}`, body);
|
|
243
|
+
if (options.json) {
|
|
244
|
+
printJson(data);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
console.log(chalk.green("Flow updated"));
|
|
248
|
+
console.log(` ID: ${chalk.green(data.id)}`);
|
|
249
|
+
console.log(` Name: ${data.name}`);
|
|
250
|
+
} catch (error) {
|
|
251
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
252
|
+
console.error(chalk.red(`Failed to update flow: ${message}`));
|
|
253
|
+
process.exit(1);
|
|
254
|
+
}
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const App = () => {
|
|
258
|
+
const [loading, setLoading] = useState(true);
|
|
259
|
+
const [success, setSuccess] = useState(null);
|
|
260
|
+
const [error, setError] = useState(null);
|
|
261
|
+
const [result, setResult] = useState(null);
|
|
262
|
+
useEffect(() => {
|
|
263
|
+
client.put(`/flows/${id}`, body).then((data) => {
|
|
264
|
+
setResult(data);
|
|
265
|
+
setSuccess(true);
|
|
266
|
+
setLoading(false);
|
|
267
|
+
}).catch((err) => {
|
|
268
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
269
|
+
setSuccess(false);
|
|
270
|
+
setLoading(false);
|
|
271
|
+
});
|
|
272
|
+
}, []);
|
|
273
|
+
return React.createElement(MutationResult, {
|
|
274
|
+
loading,
|
|
275
|
+
loadingLabel: "Updating flow...",
|
|
276
|
+
success,
|
|
277
|
+
successMessage: "Flow updated",
|
|
278
|
+
error,
|
|
279
|
+
result: result ? React.createElement(EntityCard, { fields: [{
|
|
280
|
+
label: "ID",
|
|
281
|
+
value: result.id,
|
|
282
|
+
color: "green"
|
|
283
|
+
}, {
|
|
284
|
+
label: "Name",
|
|
285
|
+
value: result.name
|
|
286
|
+
}] }) : void 0
|
|
287
|
+
});
|
|
288
|
+
};
|
|
289
|
+
const { waitUntilExit } = render(React.createElement(App));
|
|
290
|
+
await waitUntilExit();
|
|
291
|
+
});
|
|
292
|
+
flowsCommand.command("delete <id>").description("Delete a flow").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (id, options) => {
|
|
293
|
+
const apiKey = await ensureAuth();
|
|
294
|
+
if (!apiKey) return;
|
|
295
|
+
const client = createCliClient(apiKey);
|
|
296
|
+
if (!isTTY(options)) {
|
|
297
|
+
try {
|
|
298
|
+
await client.flows.delete(id);
|
|
299
|
+
console.log(JSON.stringify({
|
|
300
|
+
status: "deleted",
|
|
301
|
+
id
|
|
302
|
+
}, null, 2));
|
|
303
|
+
} catch (error) {
|
|
304
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
305
|
+
console.error(chalk.red(`Failed to delete flow: ${message}`));
|
|
306
|
+
process.exit(1);
|
|
307
|
+
}
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
const App = () => {
|
|
311
|
+
const [confirmed, setConfirmed] = useState(null);
|
|
312
|
+
const [loading, setLoading] = useState(false);
|
|
313
|
+
const [success, setSuccess] = useState(null);
|
|
314
|
+
const [error, setError] = useState(null);
|
|
315
|
+
useEffect(() => {
|
|
316
|
+
if (confirmed !== true) return void 0;
|
|
317
|
+
setLoading(true);
|
|
318
|
+
client.flows.delete(id).then(() => {
|
|
319
|
+
setSuccess(true);
|
|
320
|
+
setLoading(false);
|
|
321
|
+
}).catch((err) => {
|
|
322
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
323
|
+
setSuccess(false);
|
|
324
|
+
setLoading(false);
|
|
325
|
+
});
|
|
326
|
+
}, [confirmed]);
|
|
327
|
+
if (confirmed === null) return React.createElement(ConfirmPrompt, {
|
|
328
|
+
message: `Delete flow ${id}?`,
|
|
329
|
+
onConfirm: (val) => setConfirmed(val)
|
|
330
|
+
});
|
|
331
|
+
if (confirmed === false) return React.createElement(MutationResult, {
|
|
332
|
+
loading: false,
|
|
333
|
+
success: true,
|
|
334
|
+
successMessage: "Cancelled",
|
|
335
|
+
error: null
|
|
336
|
+
});
|
|
337
|
+
return React.createElement(MutationResult, {
|
|
338
|
+
loading,
|
|
339
|
+
loadingLabel: "Deleting flow...",
|
|
340
|
+
success,
|
|
341
|
+
successMessage: "Flow deleted",
|
|
342
|
+
error
|
|
343
|
+
});
|
|
344
|
+
};
|
|
345
|
+
const { waitUntilExit } = render(React.createElement(App));
|
|
346
|
+
await waitUntilExit();
|
|
347
|
+
});
|
|
348
|
+
export { flowsCommand };
|
|
349
|
+
|