@withone/cli 2.5.0 → 2.6.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 +2 -0
- package/dist/{chunk-MRQ47KSZ.js → chunk-4KX5ZERS.js} +783 -116
- package/dist/{chunk-7FPQOAQ4.js → chunk-O3HDWHHS.js} +5 -3
- package/dist/{chunk-XKUTG7JD.js → chunk-PUQKTRYC.js} +5 -3
- package/dist/chunk-Q6PWTATS.js +79 -0
- package/dist/{chunk-NOFJ4NYD.js → chunk-VMFWA43Q.js} +5 -77
- package/dist/{flow-runner-4A5ANCTT.js → flow-runner-FME4AVVN.js} +2 -1
- package/dist/index.js +692 -1316
- package/dist/{migrate-3LSEIPRF.js → migrate-KWEEEQ3E.js} +3 -2
- package/dist/{schema-FICQRMZ7.js → schema-YJ7JTGFL.js} +5 -3
- package/dist/{sql-AKQSXRV2.js → sql-NDMMFQP6.js} +3 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7,12 +7,21 @@ import {
|
|
|
7
7
|
TimeoutError,
|
|
8
8
|
clearAll,
|
|
9
9
|
clearEntry,
|
|
10
|
+
cliVersion,
|
|
11
|
+
collectInstallContext,
|
|
12
|
+
describeInstallContext,
|
|
13
|
+
drainQueue,
|
|
10
14
|
flowRequiresBash,
|
|
15
|
+
flush,
|
|
16
|
+
flushUsageRollups,
|
|
11
17
|
formatAge,
|
|
12
18
|
generateFlowGuide,
|
|
13
19
|
getAge,
|
|
20
|
+
getAgentStatuses,
|
|
14
21
|
getNestedStepsKeys,
|
|
15
22
|
getStepTypeDescriptor,
|
|
23
|
+
installContextToParams,
|
|
24
|
+
installMcpConfig,
|
|
16
25
|
isActionAllowed,
|
|
17
26
|
isFresh,
|
|
18
27
|
isMethodAllowed,
|
|
@@ -21,17 +30,19 @@ import {
|
|
|
21
30
|
listFlows,
|
|
22
31
|
loadFlowWithMeta,
|
|
23
32
|
makeCacheEntry,
|
|
33
|
+
maybeShowTelemetryNotice,
|
|
24
34
|
readCache,
|
|
35
|
+
recordCommand,
|
|
25
36
|
resolveActionDetails,
|
|
26
37
|
resolveFlowPath,
|
|
27
38
|
saveFlow,
|
|
28
39
|
validateActionInput,
|
|
29
40
|
walkSteps,
|
|
30
41
|
writeCache
|
|
31
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-4KX5ZERS.js";
|
|
32
43
|
import {
|
|
33
44
|
memSqlCommand
|
|
34
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-O3HDWHHS.js";
|
|
35
46
|
import {
|
|
36
47
|
collectIdentityKeys,
|
|
37
48
|
countRecords,
|
|
@@ -62,20 +73,12 @@ import {
|
|
|
62
73
|
writeDraftProfile,
|
|
63
74
|
writePageToMemory,
|
|
64
75
|
writeProfile
|
|
65
|
-
} from "./chunk-
|
|
76
|
+
} from "./chunk-PUQKTRYC.js";
|
|
66
77
|
import {
|
|
67
78
|
getByDotPath
|
|
68
79
|
} from "./chunk-44CV5IMX.js";
|
|
69
80
|
import {
|
|
70
|
-
cancel,
|
|
71
|
-
createSpinner,
|
|
72
|
-
error,
|
|
73
|
-
intro,
|
|
74
|
-
isAgentMode,
|
|
75
|
-
json,
|
|
76
|
-
note,
|
|
77
81
|
okJson,
|
|
78
|
-
outro,
|
|
79
82
|
parseCsv,
|
|
80
83
|
parseJsonArg,
|
|
81
84
|
parsePositiveInt,
|
|
@@ -83,10 +86,20 @@ import {
|
|
|
83
86
|
printRecord,
|
|
84
87
|
requireMemoryInit,
|
|
85
88
|
semanticSearchUpgradeHint,
|
|
86
|
-
semanticSearchUpgradeLine
|
|
89
|
+
semanticSearchUpgradeLine
|
|
90
|
+
} from "./chunk-VMFWA43Q.js";
|
|
91
|
+
import {
|
|
92
|
+
cancel,
|
|
93
|
+
createSpinner,
|
|
94
|
+
error,
|
|
95
|
+
intro,
|
|
96
|
+
isAgentMode,
|
|
97
|
+
json,
|
|
98
|
+
note,
|
|
99
|
+
outro,
|
|
87
100
|
setAgentMode,
|
|
88
101
|
silenceWarningsInAgentMode
|
|
89
|
-
} from "./chunk-
|
|
102
|
+
} from "./chunk-Q6PWTATS.js";
|
|
90
103
|
import {
|
|
91
104
|
SCHEMA_VERSION,
|
|
92
105
|
addRecord,
|
|
@@ -108,16 +121,12 @@ import {
|
|
|
108
121
|
updateMemoryConfig
|
|
109
122
|
} from "./chunk-3HRC3IPE.js";
|
|
110
123
|
import {
|
|
111
|
-
appendAnalyticsQueue,
|
|
112
|
-
appendUsageLog,
|
|
113
|
-
claimUsageLog,
|
|
114
124
|
configExists,
|
|
115
125
|
ensureWhoAmI,
|
|
116
126
|
getAccessControl,
|
|
117
127
|
getAccessControlFromAllSources,
|
|
118
128
|
getApiBase,
|
|
119
129
|
getApiKey,
|
|
120
|
-
getDeviceId,
|
|
121
130
|
getEnvFromApiKey,
|
|
122
131
|
getGlobalConfigPath,
|
|
123
132
|
getOpenAiApiKey,
|
|
@@ -126,665 +135,32 @@ import {
|
|
|
126
135
|
getWhoAmI,
|
|
127
136
|
globalConfigExists,
|
|
128
137
|
homeDir,
|
|
129
|
-
markTelemetryNoticeShown,
|
|
130
138
|
projectConfigExists,
|
|
131
|
-
readAnalyticsQueue,
|
|
132
139
|
readConfig,
|
|
133
140
|
readGlobalConfig,
|
|
134
141
|
readProjectConfig,
|
|
135
|
-
readUsageState,
|
|
136
142
|
resolveConfig,
|
|
137
143
|
saveCredentials,
|
|
138
|
-
telemetryNoticeShown,
|
|
139
144
|
updateAccessControl,
|
|
140
145
|
updateApiBase,
|
|
141
146
|
updateWhoAmI,
|
|
142
|
-
|
|
143
|
-
writeConfig,
|
|
144
|
-
writeUsageLog,
|
|
145
|
-
writeUsageState
|
|
147
|
+
writeConfig
|
|
146
148
|
} from "./chunk-HTXZZQ6U.js";
|
|
147
149
|
|
|
148
150
|
// src/cli.ts
|
|
149
|
-
import { createRequire
|
|
150
|
-
import
|
|
151
|
+
import { createRequire } from "module";
|
|
152
|
+
import path12 from "path";
|
|
151
153
|
import { Command } from "commander";
|
|
152
154
|
|
|
153
155
|
// src/commands/init.ts
|
|
154
156
|
import * as p3 from "@clack/prompts";
|
|
155
|
-
import
|
|
156
|
-
import fs4 from "fs";
|
|
157
|
-
import path5 from "path";
|
|
158
|
-
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
159
|
-
|
|
160
|
-
// src/lib/agents.ts
|
|
161
|
-
import fs from "fs";
|
|
162
|
-
import path from "path";
|
|
163
|
-
import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
|
|
164
|
-
function expandPath(p9) {
|
|
165
|
-
if (p9.startsWith("~/")) {
|
|
166
|
-
return path.join(homeDir(), p9.slice(2));
|
|
167
|
-
}
|
|
168
|
-
return p9;
|
|
169
|
-
}
|
|
170
|
-
function getClaudeDesktopConfigPath() {
|
|
171
|
-
switch (process.platform) {
|
|
172
|
-
case "darwin":
|
|
173
|
-
return "~/Library/Application Support/Claude/claude_desktop_config.json";
|
|
174
|
-
case "win32":
|
|
175
|
-
return path.join(process.env.APPDATA || "", "Claude", "claude_desktop_config.json");
|
|
176
|
-
default:
|
|
177
|
-
return "~/.config/Claude/claude_desktop_config.json";
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
function getClaudeDesktopDetectDir() {
|
|
181
|
-
switch (process.platform) {
|
|
182
|
-
case "darwin":
|
|
183
|
-
return "~/Library/Application Support/Claude";
|
|
184
|
-
case "win32":
|
|
185
|
-
return path.join(process.env.APPDATA || "", "Claude");
|
|
186
|
-
default:
|
|
187
|
-
return "~/.config/Claude";
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
function getWindsurfConfigPath() {
|
|
191
|
-
if (process.platform === "win32") {
|
|
192
|
-
return path.join(homeDir(), ".codeium", "windsurf", "mcp_config.json");
|
|
193
|
-
}
|
|
194
|
-
return "~/.codeium/windsurf/mcp_config.json";
|
|
195
|
-
}
|
|
196
|
-
function getWindsurfDetectDir() {
|
|
197
|
-
if (process.platform === "win32") {
|
|
198
|
-
return path.join(homeDir(), ".codeium", "windsurf");
|
|
199
|
-
}
|
|
200
|
-
return "~/.codeium/windsurf";
|
|
201
|
-
}
|
|
202
|
-
function getCursorConfigPath() {
|
|
203
|
-
if (process.platform === "win32") {
|
|
204
|
-
return path.join(homeDir(), ".cursor", "mcp.json");
|
|
205
|
-
}
|
|
206
|
-
return "~/.cursor/mcp.json";
|
|
207
|
-
}
|
|
208
|
-
function getAgents() {
|
|
209
|
-
return [
|
|
210
|
-
{
|
|
211
|
-
id: "claude-code",
|
|
212
|
-
name: "Claude Code",
|
|
213
|
-
configPath: "~/.claude.json",
|
|
214
|
-
configKey: "mcpServers",
|
|
215
|
-
detectDir: "~/.claude",
|
|
216
|
-
projectConfigPath: ".mcp.json"
|
|
217
|
-
},
|
|
218
|
-
{
|
|
219
|
-
id: "claude-desktop",
|
|
220
|
-
name: "Claude Desktop",
|
|
221
|
-
configPath: getClaudeDesktopConfigPath(),
|
|
222
|
-
configKey: "mcpServers",
|
|
223
|
-
detectDir: getClaudeDesktopDetectDir()
|
|
224
|
-
},
|
|
225
|
-
{
|
|
226
|
-
id: "cursor",
|
|
227
|
-
name: "Cursor",
|
|
228
|
-
configPath: getCursorConfigPath(),
|
|
229
|
-
configKey: "mcpServers",
|
|
230
|
-
detectDir: "~/.cursor",
|
|
231
|
-
projectConfigPath: ".cursor/mcp.json"
|
|
232
|
-
},
|
|
233
|
-
{
|
|
234
|
-
id: "windsurf",
|
|
235
|
-
name: "Windsurf",
|
|
236
|
-
configPath: getWindsurfConfigPath(),
|
|
237
|
-
configKey: "mcpServers",
|
|
238
|
-
detectDir: getWindsurfDetectDir()
|
|
239
|
-
},
|
|
240
|
-
{
|
|
241
|
-
id: "codex",
|
|
242
|
-
name: "Codex",
|
|
243
|
-
configPath: "~/.codex/config.toml",
|
|
244
|
-
configKey: "mcp_servers",
|
|
245
|
-
detectDir: "~/.codex",
|
|
246
|
-
projectConfigPath: ".codex/config.toml",
|
|
247
|
-
configFormat: "toml"
|
|
248
|
-
},
|
|
249
|
-
{
|
|
250
|
-
id: "kiro",
|
|
251
|
-
name: "Kiro",
|
|
252
|
-
configPath: "~/.kiro/settings/mcp.json",
|
|
253
|
-
configKey: "mcpServers",
|
|
254
|
-
detectDir: "~/.kiro",
|
|
255
|
-
projectConfigPath: ".kiro/settings/mcp.json"
|
|
256
|
-
}
|
|
257
|
-
];
|
|
258
|
-
}
|
|
259
|
-
function detectInstalledAgents() {
|
|
260
|
-
return getAgents().filter((agent) => {
|
|
261
|
-
const detectDir = expandPath(agent.detectDir);
|
|
262
|
-
return fs.existsSync(detectDir);
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
function getAgentConfigPath(agent, scope = "global") {
|
|
266
|
-
if (scope === "project" && agent.projectConfigPath) {
|
|
267
|
-
return path.join(process.cwd(), agent.projectConfigPath);
|
|
268
|
-
}
|
|
269
|
-
return expandPath(agent.configPath);
|
|
270
|
-
}
|
|
271
|
-
function readAgentConfig(agent, scope = "global") {
|
|
272
|
-
const configPath = getAgentConfigPath(agent, scope);
|
|
273
|
-
if (!fs.existsSync(configPath)) {
|
|
274
|
-
return {};
|
|
275
|
-
}
|
|
276
|
-
try {
|
|
277
|
-
const content = fs.readFileSync(configPath, "utf-8");
|
|
278
|
-
if (agent.configFormat === "toml") {
|
|
279
|
-
return parseToml(content);
|
|
280
|
-
}
|
|
281
|
-
return JSON.parse(content);
|
|
282
|
-
} catch {
|
|
283
|
-
return {};
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
function writeAgentConfig(agent, config2, scope = "global") {
|
|
287
|
-
const configPath = getAgentConfigPath(agent, scope);
|
|
288
|
-
const configDir = path.dirname(configPath);
|
|
289
|
-
if (!fs.existsSync(configDir)) {
|
|
290
|
-
fs.mkdirSync(configDir, { recursive: true });
|
|
291
|
-
}
|
|
292
|
-
if (agent.configFormat === "toml") {
|
|
293
|
-
fs.writeFileSync(configPath, stringifyToml(config2));
|
|
294
|
-
} else {
|
|
295
|
-
fs.writeFileSync(configPath, JSON.stringify(config2, null, 2));
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
function getMcpServerConfig(apiKey, accessControl) {
|
|
299
|
-
const env = {
|
|
300
|
-
ONE_SECRET: apiKey
|
|
301
|
-
};
|
|
302
|
-
if (accessControl) {
|
|
303
|
-
if (accessControl.permissions && accessControl.permissions !== "admin") {
|
|
304
|
-
env.ONE_PERMISSIONS = accessControl.permissions;
|
|
305
|
-
}
|
|
306
|
-
if (accessControl.connectionKeys && !(accessControl.connectionKeys.length === 1 && accessControl.connectionKeys[0] === "*")) {
|
|
307
|
-
env.ONE_CONNECTION_KEYS = accessControl.connectionKeys.join(",");
|
|
308
|
-
}
|
|
309
|
-
if (accessControl.actionIds && !(accessControl.actionIds.length === 1 && accessControl.actionIds[0] === "*")) {
|
|
310
|
-
env.ONE_ACTION_IDS = accessControl.actionIds.join(",");
|
|
311
|
-
}
|
|
312
|
-
if (accessControl.knowledgeAgent) {
|
|
313
|
-
env.ONE_KNOWLEDGE_AGENT = "true";
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
return {
|
|
317
|
-
command: "npx",
|
|
318
|
-
args: ["-y", "@withone/mcp"],
|
|
319
|
-
env
|
|
320
|
-
};
|
|
321
|
-
}
|
|
322
|
-
function installMcpConfig(agent, apiKey, scope = "global", accessControl) {
|
|
323
|
-
const config2 = readAgentConfig(agent, scope);
|
|
324
|
-
const configKey = agent.configKey;
|
|
325
|
-
const mcpServers = config2[configKey] || {};
|
|
326
|
-
mcpServers["one"] = getMcpServerConfig(apiKey, accessControl);
|
|
327
|
-
config2[configKey] = mcpServers;
|
|
328
|
-
writeAgentConfig(agent, config2, scope);
|
|
329
|
-
}
|
|
330
|
-
function isMcpInstalled(agent, scope = "global") {
|
|
331
|
-
const config2 = readAgentConfig(agent, scope);
|
|
332
|
-
const configKey = agent.configKey;
|
|
333
|
-
const mcpServers = config2[configKey];
|
|
334
|
-
return mcpServers?.["one"] !== void 0;
|
|
335
|
-
}
|
|
336
|
-
function getAgentStatuses() {
|
|
337
|
-
return getAgents().map((agent) => {
|
|
338
|
-
const detected = fs.existsSync(expandPath(agent.detectDir));
|
|
339
|
-
const globalMcp = detected && isMcpInstalled(agent, "global");
|
|
340
|
-
const projectMcp = agent.projectConfigPath ? isMcpInstalled(agent, "project") : null;
|
|
341
|
-
return { agent, detected, globalMcp, projectMcp };
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// src/lib/browser.ts
|
|
346
|
-
import open from "open";
|
|
347
|
-
|
|
348
|
-
// src/lib/install-context.ts
|
|
157
|
+
import pc3 from "picocolors";
|
|
349
158
|
import fs2 from "fs";
|
|
350
|
-
import os from "os";
|
|
351
|
-
import path3 from "path";
|
|
352
|
-
|
|
353
|
-
// src/lib/analytics.ts
|
|
354
|
-
import { createRequire as createRequire2 } from "module";
|
|
355
|
-
import { randomUUID, createHash } from "crypto";
|
|
356
|
-
import pc from "picocolors";
|
|
357
|
-
|
|
358
|
-
// src/lib/version.ts
|
|
359
|
-
import { createRequire } from "module";
|
|
360
|
-
import { existsSync } from "fs";
|
|
361
159
|
import path2 from "path";
|
|
362
|
-
import { fileURLToPath } from "url";
|
|
363
|
-
var require2 = createRequire(import.meta.url);
|
|
364
|
-
var cached = null;
|
|
365
|
-
function cliVersion() {
|
|
366
|
-
if (cached !== null) return cached;
|
|
367
|
-
const dir = path2.dirname(fileURLToPath(import.meta.url));
|
|
368
|
-
for (let i = 1; i <= 4; i++) {
|
|
369
|
-
const candidate = path2.resolve(dir, ...Array(i).fill(".."), "package.json");
|
|
370
|
-
if (!existsSync(candidate)) continue;
|
|
371
|
-
try {
|
|
372
|
-
const version2 = require2(candidate).version;
|
|
373
|
-
if (version2) {
|
|
374
|
-
cached = version2;
|
|
375
|
-
return cached;
|
|
376
|
-
}
|
|
377
|
-
} catch {
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
cached = "unknown";
|
|
381
|
-
return cached;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
// src/lib/analytics.ts
|
|
385
|
-
var require3 = createRequire2(import.meta.url);
|
|
386
|
-
var DEFAULT_POSTHOG_HOST = "https://us.i.posthog.com";
|
|
387
|
-
var DEFAULT_POSTHOG_KEY = "phc_a9ok4w0uxiZcVoSWOISIlin85lHMXQD3vWPaYnuRlRV";
|
|
388
|
-
var SEND_MAX_ATTEMPTS = 3;
|
|
389
|
-
var QUEUE_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
390
|
-
var EXIT_GRACE_MS = 300;
|
|
391
|
-
var inFlight = /* @__PURE__ */ new Set();
|
|
392
|
-
var pending = /* @__PURE__ */ new Set();
|
|
393
|
-
var dispatched = /* @__PURE__ */ new Set();
|
|
394
|
-
var delivered = /* @__PURE__ */ new Set();
|
|
395
|
-
var UUID_SHAPE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
396
|
-
function uuidFromInsertId(insertId) {
|
|
397
|
-
if (UUID_SHAPE.test(insertId)) return insertId.toLowerCase();
|
|
398
|
-
const h = createHash("sha1").update(`one-cli-event:${insertId}`).digest("hex");
|
|
399
|
-
const variant = (parseInt(h[16], 16) & 3 | 8).toString(16);
|
|
400
|
-
return `${h.slice(0, 8)}-${h.slice(8, 12)}-5${h.slice(13, 16)}-${variant}${h.slice(17, 20)}-${h.slice(20, 32)}`;
|
|
401
|
-
}
|
|
402
|
-
function posthogHost() {
|
|
403
|
-
return process.env.ONE_POSTHOG_HOST || DEFAULT_POSTHOG_HOST;
|
|
404
|
-
}
|
|
405
|
-
function posthogKey() {
|
|
406
|
-
return process.env.ONE_POSTHOG_KEY || DEFAULT_POSTHOG_KEY;
|
|
407
|
-
}
|
|
408
|
-
function envName() {
|
|
409
|
-
const key = getApiKey();
|
|
410
|
-
return key ? getEnvFromApiKey(key) : "live";
|
|
411
|
-
}
|
|
412
|
-
function isOn(value) {
|
|
413
|
-
return value === "1" || value === "true";
|
|
414
|
-
}
|
|
415
|
-
function debugLog(message) {
|
|
416
|
-
if (isOn(process.env.ONE_ANALYTICS_DEBUG)) {
|
|
417
|
-
process.stderr.write(`[analytics] ${message}
|
|
418
|
-
`);
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
function isTelemetryDisabled() {
|
|
422
|
-
if (isOn(process.env.ONE_NO_TELEMETRY) || isOn(process.env.ONE_DISABLE_TELEMETRY)) return true;
|
|
423
|
-
if (isOn(process.env.DO_NOT_TRACK)) return true;
|
|
424
|
-
if (isOn(process.env.CI)) return true;
|
|
425
|
-
if (readConfig()?.telemetry === "off") return true;
|
|
426
|
-
return false;
|
|
427
|
-
}
|
|
428
|
-
function distinctId() {
|
|
429
|
-
return getWhoAmI()?.user?.id ?? getDeviceId();
|
|
430
|
-
}
|
|
431
|
-
function isAuthenticated() {
|
|
432
|
-
return !!getWhoAmI()?.user || !!getApiKey();
|
|
433
|
-
}
|
|
434
|
-
function baseProperties() {
|
|
435
|
-
return {
|
|
436
|
-
$lib: "one-cli",
|
|
437
|
-
cli_version: cliVersion(),
|
|
438
|
-
agent_mode: isAgentMode(),
|
|
439
|
-
env: envName(),
|
|
440
|
-
os: process.platform,
|
|
441
|
-
arch: process.arch,
|
|
442
|
-
node_version: process.versions.node,
|
|
443
|
-
authenticated: isAuthenticated()
|
|
444
|
-
};
|
|
445
|
-
}
|
|
446
|
-
function personSet() {
|
|
447
|
-
const whoami = getWhoAmI();
|
|
448
|
-
if (!whoami?.user) return void 0;
|
|
449
|
-
const set = {};
|
|
450
|
-
if (whoami.user.email) set.email = whoami.user.email;
|
|
451
|
-
if (whoami.user.name) set.name = whoami.user.name;
|
|
452
|
-
if (whoami.organization?.id) set.organization_id = whoami.organization.id;
|
|
453
|
-
return Object.keys(set).length ? set : void 0;
|
|
454
|
-
}
|
|
455
|
-
function send(item) {
|
|
456
|
-
const insertId = item.properties.$insert_id;
|
|
457
|
-
if (insertId) dispatched.add(insertId);
|
|
458
|
-
const controller = new AbortController();
|
|
459
|
-
inFlight.add(controller);
|
|
460
|
-
const run = (async () => {
|
|
461
|
-
try {
|
|
462
|
-
const res = await fetch(`${posthogHost()}/i/v0/e/`, {
|
|
463
|
-
method: "POST",
|
|
464
|
-
headers: { "Content-Type": "application/json" },
|
|
465
|
-
body: JSON.stringify({
|
|
466
|
-
api_key: posthogKey(),
|
|
467
|
-
event: item.event,
|
|
468
|
-
distinct_id: item.distinct_id,
|
|
469
|
-
// PostHog's dedupe key — a re-sent copy is dropped on ingest.
|
|
470
|
-
uuid: item.uuid ?? (insertId ? uuidFromInsertId(insertId) : void 0),
|
|
471
|
-
properties: item.properties,
|
|
472
|
-
timestamp: item.timestamp
|
|
473
|
-
}),
|
|
474
|
-
signal: controller.signal
|
|
475
|
-
});
|
|
476
|
-
if (res.ok && insertId) delivered.add(insertId);
|
|
477
|
-
debugLog(`"${item.event}" -> HTTP ${res.status}${res.ok ? "" : " (retry next run)"}`);
|
|
478
|
-
} catch (err) {
|
|
479
|
-
debugLog(`"${item.event}" not sent: ${err instanceof Error ? err.message : String(err)} (retry next run)`);
|
|
480
|
-
} finally {
|
|
481
|
-
inFlight.delete(controller);
|
|
482
|
-
}
|
|
483
|
-
})();
|
|
484
|
-
pending.add(run);
|
|
485
|
-
void run.finally(() => pending.delete(run));
|
|
486
|
-
}
|
|
487
|
-
function capture(event, properties = {}, opts = {}) {
|
|
488
|
-
if (isTelemetryDisabled()) {
|
|
489
|
-
debugLog(`disabled \u2014 skipping "${event}"`);
|
|
490
|
-
return;
|
|
491
|
-
}
|
|
492
|
-
const did = opts.distinctId ?? distinctId();
|
|
493
|
-
const props = { ...baseProperties(), ...properties };
|
|
494
|
-
if (props.$insert_id === void 0) props.$insert_id = randomUUID();
|
|
495
|
-
const insertId = props.$insert_id;
|
|
496
|
-
if (opts.personProfile === false) {
|
|
497
|
-
props.$process_person_profile = false;
|
|
498
|
-
} else if (did === distinctId()) {
|
|
499
|
-
const set = personSet();
|
|
500
|
-
if (set) props.$set = set;
|
|
501
|
-
}
|
|
502
|
-
const item = {
|
|
503
|
-
event,
|
|
504
|
-
distinct_id: did,
|
|
505
|
-
properties: props,
|
|
506
|
-
timestamp: opts.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
507
|
-
uuid: uuidFromInsertId(insertId)
|
|
508
|
-
};
|
|
509
|
-
appendAnalyticsQueue(JSON.stringify(item));
|
|
510
|
-
}
|
|
511
|
-
var ROLLUP_WINDOW_MS = 5 * 60 * 1e3;
|
|
512
|
-
var ROLLUP_MAX_BATCH = 500;
|
|
513
|
-
function utcDay(ts) {
|
|
514
|
-
return new Date(ts).toISOString().slice(0, 10);
|
|
515
|
-
}
|
|
516
|
-
var PRE_AUTH_COMMANDS = /* @__PURE__ */ new Set([
|
|
517
|
-
"init",
|
|
518
|
-
"login",
|
|
519
|
-
"logout",
|
|
520
|
-
"guide",
|
|
521
|
-
"platforms",
|
|
522
|
-
"onboard",
|
|
523
|
-
"config",
|
|
524
|
-
"update",
|
|
525
|
-
"help"
|
|
526
|
-
]);
|
|
527
|
-
function shouldRecord(commandPath2) {
|
|
528
|
-
if (isAuthenticated()) return true;
|
|
529
|
-
return PRE_AUTH_COMMANDS.has(commandPath2.split(" ")[0]);
|
|
530
|
-
}
|
|
531
|
-
function recordCommand(command) {
|
|
532
|
-
if (isTelemetryDisabled()) {
|
|
533
|
-
writeUsageLog([]);
|
|
534
|
-
return;
|
|
535
|
-
}
|
|
536
|
-
const cmdPath = commandPath(command);
|
|
537
|
-
if (!shouldRecord(cmdPath)) return;
|
|
538
|
-
const did = distinctId();
|
|
539
|
-
const entry = { ts: Date.now(), command: cmdPath, agent: isAgentMode(), did };
|
|
540
|
-
appendUsageLog(JSON.stringify(entry));
|
|
541
|
-
const today = utcDay(entry.ts);
|
|
542
|
-
const state = readUsageState();
|
|
543
|
-
const firstTouch = state.lastDay !== today || state.distinctId !== did;
|
|
544
|
-
flushUsageRollups({ force: firstTouch });
|
|
545
|
-
if (firstTouch) writeUsageState({ lastDay: today, distinctId: did });
|
|
546
|
-
}
|
|
547
|
-
function flushUsageRollups(opts = {}) {
|
|
548
|
-
if (isTelemetryDisabled()) {
|
|
549
|
-
writeUsageLog([]);
|
|
550
|
-
return;
|
|
551
|
-
}
|
|
552
|
-
const lines = claimUsageLog();
|
|
553
|
-
if (!lines || lines.length === 0) return;
|
|
554
|
-
const entries = [];
|
|
555
|
-
for (const line of lines) {
|
|
556
|
-
try {
|
|
557
|
-
const e = JSON.parse(line);
|
|
558
|
-
if (e && typeof e.ts === "number" && typeof e.command === "string" && typeof e.did === "string") {
|
|
559
|
-
entries.push(e);
|
|
560
|
-
}
|
|
561
|
-
} catch {
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
if (entries.length === 0) return;
|
|
565
|
-
const currentDid = entries[entries.length - 1].did;
|
|
566
|
-
const now = Date.now();
|
|
567
|
-
const groups = /* @__PURE__ */ new Map();
|
|
568
|
-
for (const e of entries) {
|
|
569
|
-
const g = groups.get(e.did);
|
|
570
|
-
if (g) g.push(e);
|
|
571
|
-
else groups.set(e.did, [e]);
|
|
572
|
-
}
|
|
573
|
-
const kept = [];
|
|
574
|
-
for (const [did, group] of groups) {
|
|
575
|
-
const due = opts.force === true || did !== currentDid || // a superseded login's batch — flush it now
|
|
576
|
-
group.length >= ROLLUP_MAX_BATCH || now - group[0].ts >= ROLLUP_WINDOW_MS;
|
|
577
|
-
if (due) emitRollup(did, group);
|
|
578
|
-
else kept.push(...group);
|
|
579
|
-
}
|
|
580
|
-
for (const e of kept) appendUsageLog(JSON.stringify(e));
|
|
581
|
-
}
|
|
582
|
-
function emitRollup(did, group) {
|
|
583
|
-
const byCommand = {};
|
|
584
|
-
let agentCount = 0;
|
|
585
|
-
for (const e of group) {
|
|
586
|
-
byCommand[e.command] = (byCommand[e.command] ?? 0) + 1;
|
|
587
|
-
if (e.agent) agentCount += 1;
|
|
588
|
-
}
|
|
589
|
-
const insertId = createHash("sha1").update(`${did}|${group.map((e) => `${e.ts}:${e.command}:${e.agent ? 1 : 0}`).join("|")}`).digest("hex");
|
|
590
|
-
capture(
|
|
591
|
-
"CLI Usage Rollup",
|
|
592
|
-
{
|
|
593
|
-
command_count: group.length,
|
|
594
|
-
by_command: byCommand,
|
|
595
|
-
agent_count: agentCount,
|
|
596
|
-
human_count: group.length - agentCount,
|
|
597
|
-
window_start: new Date(group[0].ts).toISOString(),
|
|
598
|
-
window_end: new Date(group[group.length - 1].ts).toISOString(),
|
|
599
|
-
$insert_id: insertId
|
|
600
|
-
},
|
|
601
|
-
{
|
|
602
|
-
distinctId: did,
|
|
603
|
-
timestamp: new Date(group[group.length - 1].ts).toISOString(),
|
|
604
|
-
// Rollups bill at the anonymous rate; the person already exists.
|
|
605
|
-
personProfile: false
|
|
606
|
-
}
|
|
607
|
-
);
|
|
608
|
-
debugLog(`rollup \u2014 ${group.length} command(s) for ${did}`);
|
|
609
|
-
}
|
|
610
|
-
function commandPath(command) {
|
|
611
|
-
const parts = [];
|
|
612
|
-
let current = command;
|
|
613
|
-
while (current && current.name() && current.name() !== "one") {
|
|
614
|
-
parts.unshift(current.name());
|
|
615
|
-
current = current.parent;
|
|
616
|
-
}
|
|
617
|
-
return parts.join(" ") || command.name();
|
|
618
|
-
}
|
|
619
|
-
function drainQueue() {
|
|
620
|
-
if (isTelemetryDisabled()) {
|
|
621
|
-
writeAnalyticsQueue([]);
|
|
622
|
-
return;
|
|
623
|
-
}
|
|
624
|
-
const now = Date.now();
|
|
625
|
-
const kept = [];
|
|
626
|
-
let changed = false;
|
|
627
|
-
for (const line of readAnalyticsQueue()) {
|
|
628
|
-
let item;
|
|
629
|
-
try {
|
|
630
|
-
item = JSON.parse(line);
|
|
631
|
-
} catch {
|
|
632
|
-
changed = true;
|
|
633
|
-
continue;
|
|
634
|
-
}
|
|
635
|
-
const insertId = item?.properties?.$insert_id;
|
|
636
|
-
if (!insertId) {
|
|
637
|
-
changed = true;
|
|
638
|
-
continue;
|
|
639
|
-
}
|
|
640
|
-
const age = now - Date.parse(item.timestamp);
|
|
641
|
-
const attempts = item.attempts ?? 0;
|
|
642
|
-
if (!(age < QUEUE_MAX_AGE_MS) || attempts >= SEND_MAX_ATTEMPTS) {
|
|
643
|
-
debugLog(`"${item.event}" dropped (${attempts} attempts, ${Math.round(age / 6e4)} min old)`);
|
|
644
|
-
changed = true;
|
|
645
|
-
continue;
|
|
646
|
-
}
|
|
647
|
-
if (dispatched.has(insertId)) {
|
|
648
|
-
kept.push(line);
|
|
649
|
-
continue;
|
|
650
|
-
}
|
|
651
|
-
item.attempts = attempts + 1;
|
|
652
|
-
if (!item.uuid) item.uuid = uuidFromInsertId(insertId);
|
|
653
|
-
kept.push(JSON.stringify(item));
|
|
654
|
-
changed = true;
|
|
655
|
-
send(item);
|
|
656
|
-
}
|
|
657
|
-
if (changed) writeAnalyticsQueue(kept);
|
|
658
|
-
}
|
|
659
|
-
async function flush() {
|
|
660
|
-
if (pending.size > 0) {
|
|
661
|
-
await Promise.race([
|
|
662
|
-
Promise.allSettled([...pending]),
|
|
663
|
-
new Promise((resolve) => setTimeout(resolve, EXIT_GRACE_MS))
|
|
664
|
-
]);
|
|
665
|
-
}
|
|
666
|
-
for (const controller of inFlight) controller.abort();
|
|
667
|
-
const remaining = readAnalyticsQueue().filter((line) => {
|
|
668
|
-
try {
|
|
669
|
-
const item = JSON.parse(line);
|
|
670
|
-
const id = item.properties?.$insert_id;
|
|
671
|
-
if (!id || delivered.has(id)) return false;
|
|
672
|
-
return (item.attempts ?? 0) < SEND_MAX_ATTEMPTS;
|
|
673
|
-
} catch {
|
|
674
|
-
return false;
|
|
675
|
-
}
|
|
676
|
-
});
|
|
677
|
-
writeAnalyticsQueue(remaining);
|
|
678
|
-
dispatched.clear();
|
|
679
|
-
delivered.clear();
|
|
680
|
-
}
|
|
681
|
-
function maybeShowTelemetryNotice() {
|
|
682
|
-
if (isTelemetryDisabled() || isAgentMode()) return;
|
|
683
|
-
if (telemetryNoticeShown()) return;
|
|
684
|
-
markTelemetryNoticeShown();
|
|
685
|
-
process.stderr.write(
|
|
686
|
-
pc.dim(
|
|
687
|
-
"One CLI collects usage analytics (which commands run, linked to your One account) to improve the product.\nNo arguments, inputs, or secrets are ever collected. Opt out anytime with ONE_NO_TELEMETRY=1.\n"
|
|
688
|
-
)
|
|
689
|
-
);
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
// src/lib/install-context.ts
|
|
693
|
-
var EXTRA_HARNESS_DIRS = [
|
|
694
|
-
{ id: "gemini-cli", dir: ".gemini" },
|
|
695
|
-
{ id: "openclaw", dir: ".openclaw" },
|
|
696
|
-
{ id: "hermes", dir: ".hermes" },
|
|
697
|
-
{ id: "devin", dir: ".devin" }
|
|
698
|
-
];
|
|
699
|
-
var LAUNCHER_ENV = [
|
|
700
|
-
{ id: "claude-code", vars: ["CLAUDECODE", "CLAUDE_CODE_ENTRYPOINT"] },
|
|
701
|
-
{ id: "codex", vars: ["CODEX_SANDBOX", "CODEX_CI", "CODEX_THREAD_ID"] },
|
|
702
|
-
{ id: "gemini-cli", vars: ["GEMINI_CLI"] },
|
|
703
|
-
// CURSOR_TRACE_ID is deliberately absent: Cursor exports it into every
|
|
704
|
-
// integrated-terminal shell, so it marks the editor, not an agent.
|
|
705
|
-
{ id: "cursor", vars: ["CURSOR_AGENT"] },
|
|
706
|
-
{ id: "windsurf", vars: ["WINDSURF_AGENT"] },
|
|
707
|
-
{ id: "kiro", vars: ["KIRO_AGENT"] },
|
|
708
|
-
{ id: "openclaw", vars: ["OPENCLAW_AGENT", "OPENCLAW_SESSION"] },
|
|
709
|
-
{ id: "hermes", vars: ["HERMES_AGENT", "HERMES_SESSION"] },
|
|
710
|
-
{ id: "devin", vars: ["DEVIN_SESSION_ID"] }
|
|
711
|
-
];
|
|
712
|
-
function detectLauncher(env = process.env) {
|
|
713
|
-
for (const entry of LAUNCHER_ENV) {
|
|
714
|
-
if (entry.vars.some((v) => env[v] !== void 0 && env[v] !== "")) return entry.id;
|
|
715
|
-
}
|
|
716
|
-
return void 0;
|
|
717
|
-
}
|
|
718
|
-
function detectInstalledHarnesses() {
|
|
719
|
-
const ids = new Set(detectInstalledAgents().map((a) => a.id));
|
|
720
|
-
for (const { id, dir } of EXTRA_HARNESS_DIRS) {
|
|
721
|
-
if (fs2.existsSync(path3.join(homeDir(), dir))) ids.add(id);
|
|
722
|
-
}
|
|
723
|
-
return [...ids].sort();
|
|
724
|
-
}
|
|
725
|
-
function tryRead(read) {
|
|
726
|
-
try {
|
|
727
|
-
const value = read();
|
|
728
|
-
return value === null || value === "" ? void 0 : value;
|
|
729
|
-
} catch {
|
|
730
|
-
return void 0;
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
function collectInstallContext(opts) {
|
|
734
|
-
const env = opts.env ?? process.env;
|
|
735
|
-
const ctx = {
|
|
736
|
-
scope: opts.scope,
|
|
737
|
-
harnesses: tryRead(() => detectInstalledHarnesses()) ?? []
|
|
738
|
-
};
|
|
739
|
-
if (opts.scope === "project") {
|
|
740
|
-
ctx.path = opts.projectRoot ?? tryRead(() => getProjectRoot());
|
|
741
|
-
}
|
|
742
|
-
ctx.host = tryRead(() => os.hostname());
|
|
743
|
-
ctx.os = process.platform;
|
|
744
|
-
ctx.osVersion = tryRead(() => os.release());
|
|
745
|
-
ctx.arch = process.arch;
|
|
746
|
-
ctx.user = tryRead(() => os.userInfo().username);
|
|
747
|
-
if (!isTelemetryDisabled()) ctx.device = tryRead(() => getDeviceId());
|
|
748
|
-
const cli = tryRead(() => cliVersion());
|
|
749
|
-
ctx.cli = cli === "unknown" ? void 0 : cli;
|
|
750
|
-
ctx.launcher = detectLauncher(env);
|
|
751
|
-
return ctx;
|
|
752
|
-
}
|
|
753
|
-
function installContextToParams(ctx) {
|
|
754
|
-
const params = new URLSearchParams();
|
|
755
|
-
const set = (key, value) => {
|
|
756
|
-
if (value !== void 0 && value !== "") params.set(key, value);
|
|
757
|
-
};
|
|
758
|
-
set("scope", ctx.scope);
|
|
759
|
-
set("path", ctx.path);
|
|
760
|
-
set("host", ctx.host);
|
|
761
|
-
set("os", ctx.os);
|
|
762
|
-
set("osv", ctx.osVersion);
|
|
763
|
-
set("arch", ctx.arch);
|
|
764
|
-
set("user", ctx.user);
|
|
765
|
-
set("device", ctx.device);
|
|
766
|
-
set("cli", ctx.cli);
|
|
767
|
-
if (ctx.harnesses.length > 0) params.set("harnesses", ctx.harnesses.join(","));
|
|
768
|
-
set("launcher", ctx.launcher);
|
|
769
|
-
return params;
|
|
770
|
-
}
|
|
771
|
-
function describeInstallContext(ctx) {
|
|
772
|
-
const lines = [`scope: ${ctx.scope}`];
|
|
773
|
-
if (ctx.path) lines.push(`path: ${ctx.path}`);
|
|
774
|
-
if (ctx.host || ctx.os) {
|
|
775
|
-
const osPart = [ctx.os, ctx.osVersion].filter(Boolean).join(" ");
|
|
776
|
-
const detail = [osPart, ctx.arch].filter(Boolean).join(", ");
|
|
777
|
-
lines.push(`machine: ${ctx.host ?? "unknown"}${detail ? ` (${detail})` : ""}`);
|
|
778
|
-
}
|
|
779
|
-
if (ctx.user) lines.push(`user: ${ctx.user}`);
|
|
780
|
-
if (ctx.device) lines.push(`device: ${ctx.device}`);
|
|
781
|
-
if (ctx.harnesses.length > 0) lines.push(`harnesses: ${ctx.harnesses.join(", ")}`);
|
|
782
|
-
if (ctx.launcher) lines.push(`launched by: ${ctx.launcher}`);
|
|
783
|
-
if (ctx.cli) lines.push(`cli: ${ctx.cli}`);
|
|
784
|
-
return lines.join("\n");
|
|
785
|
-
}
|
|
160
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
786
161
|
|
|
787
162
|
// src/lib/browser.ts
|
|
163
|
+
import open from "open";
|
|
788
164
|
var DEFAULT_APP_URL = "https://app.withone.ai";
|
|
789
165
|
function oneAppUrl() {
|
|
790
166
|
const override = process.env.ONE_APP_URL?.trim();
|
|
@@ -818,25 +194,25 @@ function getCliAuthUrl(port, state, context) {
|
|
|
818
194
|
|
|
819
195
|
// src/commands/config.ts
|
|
820
196
|
import * as p from "@clack/prompts";
|
|
821
|
-
import
|
|
197
|
+
import pc from "picocolors";
|
|
822
198
|
async function configCommand() {
|
|
823
199
|
if (isAgentMode()) {
|
|
824
200
|
error("This command requires interactive input. Run without --agent.");
|
|
825
201
|
}
|
|
826
202
|
const config2 = readConfig();
|
|
827
203
|
if (!config2) {
|
|
828
|
-
p.log.error(`No One config found. Run ${
|
|
204
|
+
p.log.error(`No One config found. Run ${pc.cyan("one init")} first.`);
|
|
829
205
|
return;
|
|
830
206
|
}
|
|
831
|
-
p.intro(
|
|
207
|
+
p.intro(pc.bgCyan(pc.black(" One Access Control ")));
|
|
832
208
|
const current = getAccessControl();
|
|
833
209
|
console.log();
|
|
834
|
-
console.log(` ${
|
|
835
|
-
console.log(` ${
|
|
836
|
-
console.log(` ${
|
|
837
|
-
console.log(` ${
|
|
838
|
-
console.log(` ${
|
|
839
|
-
console.log(` ${
|
|
210
|
+
console.log(` ${pc.bold("Current Access Control")}`);
|
|
211
|
+
console.log(` ${pc.dim("\u2500".repeat(42))}`);
|
|
212
|
+
console.log(` ${pc.dim("Permissions:")} ${current.permissions ?? "admin"}`);
|
|
213
|
+
console.log(` ${pc.dim("Connections:")} ${formatList(current.connectionKeys)}`);
|
|
214
|
+
console.log(` ${pc.dim("Action IDs:")} ${formatList(current.actionIds)}`);
|
|
215
|
+
console.log(` ${pc.dim("Knowledge only:")} ${current.knowledgeAgent ? "yes" : "no"}`);
|
|
840
216
|
console.log();
|
|
841
217
|
const permissions = await p.select({
|
|
842
218
|
message: "Permission level",
|
|
@@ -871,7 +247,7 @@ async function configCommand() {
|
|
|
871
247
|
return;
|
|
872
248
|
}
|
|
873
249
|
if (connectionKeys.length === 0) {
|
|
874
|
-
p.log.info(`No connections found. Defaulting to all. Use ${
|
|
250
|
+
p.log.info(`No connections found. Defaulting to all. Use ${pc.cyan("one add")} to connect platforms.`);
|
|
875
251
|
connectionKeys = void 0;
|
|
876
252
|
}
|
|
877
253
|
}
|
|
@@ -948,7 +324,7 @@ async function configCommand() {
|
|
|
948
324
|
}
|
|
949
325
|
const normalized = customUrl.replace(/\/+$/, "").replace(/\/v1$/, "");
|
|
950
326
|
const apiKey = await p.text({
|
|
951
|
-
message: `Enter your API key for ${
|
|
327
|
+
message: `Enter your API key for ${pc.cyan(normalized)}:`,
|
|
952
328
|
placeholder: "sk_live_...",
|
|
953
329
|
validate: (value) => {
|
|
954
330
|
if (!value) return "API key is required";
|
|
@@ -971,12 +347,12 @@ async function configCommand() {
|
|
|
971
347
|
} catch (err) {
|
|
972
348
|
spinner.stop("Connection failed");
|
|
973
349
|
const msg = err instanceof Error ? err.message : String(err);
|
|
974
|
-
p.log.error(`Could not reach ${
|
|
350
|
+
p.log.error(`Could not reach ${pc.cyan(normalized)}: ${msg}`);
|
|
975
351
|
return;
|
|
976
352
|
}
|
|
977
353
|
if (!isValid) {
|
|
978
354
|
spinner.stop("Invalid API key");
|
|
979
|
-
p.log.error(`Invalid API key for ${
|
|
355
|
+
p.log.error(`Invalid API key for ${pc.cyan(normalized)}.`);
|
|
980
356
|
return;
|
|
981
357
|
}
|
|
982
358
|
spinner.stop("API key validated");
|
|
@@ -984,7 +360,7 @@ async function configCommand() {
|
|
|
984
360
|
newApiKey = apiKey;
|
|
985
361
|
} else if (isCustomBase) {
|
|
986
362
|
const apiKey = await p.text({
|
|
987
|
-
message: `Enter your API key for ${
|
|
363
|
+
message: `Enter your API key for ${pc.cyan("https://api.withone.ai")}:`,
|
|
988
364
|
placeholder: "sk_live_...",
|
|
989
365
|
validate: (value) => {
|
|
990
366
|
if (!value) return "API key is required";
|
|
@@ -1007,7 +383,7 @@ async function configCommand() {
|
|
|
1007
383
|
} catch (err) {
|
|
1008
384
|
spinner.stop("Connection failed");
|
|
1009
385
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1010
|
-
p.log.error(`Could not reach ${
|
|
386
|
+
p.log.error(`Could not reach ${pc.cyan("https://api.withone.ai")}: ${msg}`);
|
|
1011
387
|
return;
|
|
1012
388
|
}
|
|
1013
389
|
if (!isValid) {
|
|
@@ -1098,15 +474,15 @@ function formatList(list) {
|
|
|
1098
474
|
import open3 from "open";
|
|
1099
475
|
|
|
1100
476
|
// src/lib/skill-sync.ts
|
|
1101
|
-
import
|
|
1102
|
-
import
|
|
1103
|
-
import { fileURLToPath
|
|
477
|
+
import fs from "fs";
|
|
478
|
+
import path from "path";
|
|
479
|
+
import { fileURLToPath } from "url";
|
|
1104
480
|
|
|
1105
481
|
// src/commands/update.ts
|
|
1106
482
|
import { spawn } from "child_process";
|
|
1107
|
-
import { existsSync
|
|
483
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync, openSync, closeSync } from "fs";
|
|
1108
484
|
import { delimiter, dirname, join } from "path";
|
|
1109
|
-
import
|
|
485
|
+
import pc2 from "picocolors";
|
|
1110
486
|
var currentVersion = cliVersion();
|
|
1111
487
|
var ONE_DIR = () => join(homeDir(), ".one");
|
|
1112
488
|
var CACHE_PATH = () => join(ONE_DIR(), "update-check.json");
|
|
@@ -1165,7 +541,7 @@ function resolveNpmBin(nodeExecPath = process.execPath) {
|
|
|
1165
541
|
const name = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
1166
542
|
try {
|
|
1167
543
|
const sibling = join(dirname(nodeExecPath), name);
|
|
1168
|
-
if (
|
|
544
|
+
if (existsSync(sibling)) return sibling;
|
|
1169
545
|
} catch {
|
|
1170
546
|
}
|
|
1171
547
|
return name;
|
|
@@ -1282,10 +658,10 @@ function maybeWarnAboutFailedUpdates(targetVersion) {
|
|
|
1282
658
|
if (!shouldWarnAboutFailedUpdates(state)) return;
|
|
1283
659
|
writeAutoUpdateState({ ...state, lastNoticeAt: Date.now() });
|
|
1284
660
|
process.stderr.write(
|
|
1285
|
-
|
|
661
|
+
pc2.yellow(
|
|
1286
662
|
`One CLI could not auto-update (v${currentVersion} \u2192 v${targetVersion}) after ${state.failures} attempts.
|
|
1287
663
|
`
|
|
1288
|
-
) +
|
|
664
|
+
) + pc2.dim(
|
|
1289
665
|
`Update manually with: npm install -g @withone/cli@latest
|
|
1290
666
|
Details: ${LOG_PATH()}. Silence this with ONE_NO_AUTO_UPDATE=1.
|
|
1291
667
|
`
|
|
@@ -1382,42 +758,42 @@ function autoUpdate(targetVersion, publishedAt) {
|
|
|
1382
758
|
var CANONICAL_SKILL_DIR = ".agents/skills";
|
|
1383
759
|
var VERSION_MARKER = ".one-cli-version";
|
|
1384
760
|
function getPackagedSkillDir() {
|
|
1385
|
-
const here =
|
|
1386
|
-
return
|
|
761
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
762
|
+
return path.resolve(here, "..", "skills", "one");
|
|
1387
763
|
}
|
|
1388
764
|
function getCanonicalSkillPath() {
|
|
1389
|
-
return
|
|
765
|
+
return path.join(homeDir(), CANONICAL_SKILL_DIR, "one");
|
|
1390
766
|
}
|
|
1391
767
|
function getVersionMarkerPath() {
|
|
1392
|
-
return
|
|
768
|
+
return path.join(getCanonicalSkillPath(), VERSION_MARKER);
|
|
1393
769
|
}
|
|
1394
770
|
function isSkillInstalled() {
|
|
1395
|
-
return
|
|
771
|
+
return fs.existsSync(path.join(getCanonicalSkillPath(), "SKILL.md"));
|
|
1396
772
|
}
|
|
1397
773
|
function readInstalledSkillVersion() {
|
|
1398
774
|
try {
|
|
1399
|
-
return
|
|
775
|
+
return fs.readFileSync(getVersionMarkerPath(), "utf-8").trim() || null;
|
|
1400
776
|
} catch {
|
|
1401
777
|
return null;
|
|
1402
778
|
}
|
|
1403
779
|
}
|
|
1404
780
|
function writeInstalledSkillVersion(version2) {
|
|
1405
781
|
try {
|
|
1406
|
-
|
|
1407
|
-
|
|
782
|
+
fs.mkdirSync(getCanonicalSkillPath(), { recursive: true });
|
|
783
|
+
fs.writeFileSync(getVersionMarkerPath(), `${version2}
|
|
1408
784
|
`);
|
|
1409
785
|
} catch {
|
|
1410
786
|
}
|
|
1411
787
|
}
|
|
1412
788
|
function copyDirSync(src, dest) {
|
|
1413
|
-
|
|
1414
|
-
for (const entry of
|
|
1415
|
-
const srcPath =
|
|
1416
|
-
const destPath =
|
|
789
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
790
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
791
|
+
const srcPath = path.join(src, entry.name);
|
|
792
|
+
const destPath = path.join(dest, entry.name);
|
|
1417
793
|
if (entry.isDirectory()) {
|
|
1418
794
|
copyDirSync(srcPath, destPath);
|
|
1419
795
|
} else {
|
|
1420
|
-
|
|
796
|
+
fs.copyFileSync(srcPath, destPath);
|
|
1421
797
|
}
|
|
1422
798
|
}
|
|
1423
799
|
}
|
|
@@ -1440,7 +816,7 @@ function forceSyncSkills() {
|
|
|
1440
816
|
}
|
|
1441
817
|
function performSync(current, reason) {
|
|
1442
818
|
const source = getPackagedSkillDir();
|
|
1443
|
-
if (!
|
|
819
|
+
if (!fs.existsSync(path.join(source, "SKILL.md"))) {
|
|
1444
820
|
return { synced: false, reason: "source-missing" };
|
|
1445
821
|
}
|
|
1446
822
|
const canonical = getCanonicalSkillPath();
|
|
@@ -1686,25 +1062,25 @@ async function loginCommand() {
|
|
|
1686
1062
|
let targetScope = "global";
|
|
1687
1063
|
const existingKey = getApiKey();
|
|
1688
1064
|
if (existingKey) {
|
|
1689
|
-
const
|
|
1065
|
+
const pc17 = (await import("picocolors")).default;
|
|
1690
1066
|
const resolved = resolveConfig();
|
|
1691
1067
|
const whoami2 = resolved.config?.whoami;
|
|
1692
1068
|
const env2 = getEnvFromApiKey(existingKey);
|
|
1693
|
-
const envLabel2 = env2 === "test" ?
|
|
1694
|
-
const currentScope = resolved.scope === "project" ?
|
|
1069
|
+
const envLabel2 = env2 === "test" ? pc17.yellow("test") : pc17.green("live");
|
|
1070
|
+
const currentScope = resolved.scope === "project" ? pc17.cyan("local config") : pc17.magenta("global config");
|
|
1695
1071
|
const lines = ["You are already logged in.", ""];
|
|
1696
1072
|
if (whoami2) {
|
|
1697
1073
|
const contextParts2 = [];
|
|
1698
1074
|
if (whoami2.organization) contextParts2.push(whoami2.organization.name);
|
|
1699
1075
|
if (whoami2.project) contextParts2.push(whoami2.project.name);
|
|
1700
1076
|
const scopeDisplay2 = contextParts2.length > 0 ? contextParts2.join(" / ") : "Personal";
|
|
1701
|
-
lines.push(`${
|
|
1702
|
-
lines.push(`${whoami2.user.name} ${
|
|
1703
|
-
if (whoami2.organization) lines.push(`${
|
|
1704
|
-
if (whoami2.project) lines.push(`${
|
|
1077
|
+
lines.push(`${pc17.bold(scopeDisplay2)} ${pc17.dim("\xB7")} ${envLabel2}`);
|
|
1078
|
+
lines.push(`${whoami2.user.name} ${pc17.dim(`(${whoami2.user.email})`)}`);
|
|
1079
|
+
if (whoami2.organization) lines.push(`${pc17.dim("Org:")} ${whoami2.organization.name}`);
|
|
1080
|
+
if (whoami2.project) lines.push(`${pc17.dim("Project:")} ${whoami2.project.name}`);
|
|
1705
1081
|
}
|
|
1706
1082
|
lines.push("");
|
|
1707
|
-
lines.push(`${
|
|
1083
|
+
lines.push(`${pc17.dim("Stored in")} ${currentScope}`);
|
|
1708
1084
|
p2.note(lines.join("\n"));
|
|
1709
1085
|
const scopeChoice = await p2.select({
|
|
1710
1086
|
message: "Where would you like to log in?",
|
|
@@ -1723,42 +1099,42 @@ async function loginCommand() {
|
|
|
1723
1099
|
if (!result) return;
|
|
1724
1100
|
const { apiKey, whoami, keyName, grant, knowledgeOnly } = result;
|
|
1725
1101
|
saveCredentials(apiKey, targetScope, { keyName, whoami, knowledgeOnly });
|
|
1726
|
-
const
|
|
1102
|
+
const pc16 = (await import("picocolors")).default;
|
|
1727
1103
|
const env = getEnvFromApiKey(apiKey);
|
|
1728
1104
|
const contextParts = [];
|
|
1729
1105
|
if (whoami.organization) contextParts.push(whoami.organization.name);
|
|
1730
1106
|
if (whoami.project) contextParts.push(whoami.project.name);
|
|
1731
1107
|
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
1732
|
-
const envLabel = env === "test" ?
|
|
1733
|
-
const configLabel = targetScope === "project" ?
|
|
1108
|
+
const envLabel = env === "test" ? pc16.yellow("test") : pc16.green("live");
|
|
1109
|
+
const configLabel = targetScope === "project" ? pc16.cyan("local config") : pc16.magenta("global config");
|
|
1734
1110
|
const infoLines = [
|
|
1735
|
-
`${
|
|
1736
|
-
`${whoami.user.name} ${
|
|
1111
|
+
`${pc16.bold(scopeDisplay)} ${pc16.dim("\xB7")} ${envLabel}`,
|
|
1112
|
+
`${whoami.user.name} ${pc16.dim(`(${whoami.user.email})`)}`
|
|
1737
1113
|
];
|
|
1738
|
-
if (keyName) infoLines.push(`${
|
|
1739
|
-
infoLines.push(...grantNoteLines(grant,
|
|
1740
|
-
if (whoami.organization) infoLines.push(`${
|
|
1741
|
-
if (whoami.project) infoLines.push(`${
|
|
1114
|
+
if (keyName) infoLines.push(`${pc16.dim("Key:")} ${keyName}`);
|
|
1115
|
+
infoLines.push(...grantNoteLines(grant, pc16.dim("Access:")));
|
|
1116
|
+
if (whoami.organization) infoLines.push(`${pc16.dim("Org:")} ${whoami.organization.name}`);
|
|
1117
|
+
if (whoami.project) infoLines.push(`${pc16.dim("Project:")} ${whoami.project.name}`);
|
|
1742
1118
|
infoLines.push("");
|
|
1743
|
-
infoLines.push(`${
|
|
1119
|
+
infoLines.push(`${pc16.dim("Stored in")} ${configLabel}`);
|
|
1744
1120
|
p2.note(infoLines.join("\n"), "Logged in");
|
|
1745
1121
|
console.log();
|
|
1746
|
-
console.log(` ${
|
|
1747
|
-
console.log(` ${
|
|
1122
|
+
console.log(` ${pc16.dim("Next steps:")}`);
|
|
1123
|
+
console.log(` ${pc16.cyan("one add <platform>")} ${pc16.dim("\u2014")} Connect a platform (e.g. gmail, slack, stripe)`);
|
|
1748
1124
|
console.log();
|
|
1749
|
-
console.log(
|
|
1125
|
+
console.log(pc16.bold(" Copy-paste this to your AI agent:"));
|
|
1750
1126
|
console.log();
|
|
1751
|
-
console.log(
|
|
1752
|
-
console.log(
|
|
1753
|
-
console.log(
|
|
1754
|
-
console.log(
|
|
1755
|
-
console.log(
|
|
1756
|
-
console.log(
|
|
1757
|
-
console.log(
|
|
1758
|
-
console.log(
|
|
1759
|
-
console.log(
|
|
1760
|
-
console.log(
|
|
1761
|
-
console.log(
|
|
1127
|
+
console.log(pc16.cyan(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
1128
|
+
console.log(pc16.cyan(" \u2502"));
|
|
1129
|
+
console.log(pc16.cyan(" \u2502 The One CLI (`one`) is now installed on this machine. It"));
|
|
1130
|
+
console.log(pc16.cyan(" \u2502 lets you interact with 750+ third-party platforms (Gmail,"));
|
|
1131
|
+
console.log(pc16.cyan(" \u2502 Slack, Shopify, HubSpot, Stripe, GitHub, etc.) through"));
|
|
1132
|
+
console.log(pc16.cyan(" \u2502 their APIs. Whenever you need to interact with any"));
|
|
1133
|
+
console.log(pc16.cyan(" \u2502 third-party platform or external service, use the `one`"));
|
|
1134
|
+
console.log(pc16.cyan(" \u2502 skill. Please save this to your project instructions or"));
|
|
1135
|
+
console.log(pc16.cyan(" \u2502 memory so you remember it in future conversations."));
|
|
1136
|
+
console.log(pc16.cyan(" \u2502"));
|
|
1137
|
+
console.log(pc16.cyan(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
1762
1138
|
console.log();
|
|
1763
1139
|
p2.outro("Happy building!");
|
|
1764
1140
|
}
|
|
@@ -1862,20 +1238,20 @@ async function nonInteractiveInit(options) {
|
|
|
1862
1238
|
if (whoami.organization) contextParts.push(whoami.organization.name);
|
|
1863
1239
|
if (whoami.project) contextParts.push(whoami.project.name);
|
|
1864
1240
|
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
1865
|
-
const envLabel = env === "test" ?
|
|
1241
|
+
const envLabel = env === "test" ? pc3.yellow("test") : pc3.green("live");
|
|
1866
1242
|
console.log();
|
|
1867
|
-
console.log(` ${
|
|
1868
|
-
console.log(` ${
|
|
1869
|
-
console.log(` ${
|
|
1870
|
-
console.log(` ${
|
|
1871
|
-
if (keyName) console.log(` ${
|
|
1872
|
-
if (grant) console.log(` ${
|
|
1873
|
-
console.log(` ${
|
|
1243
|
+
console.log(` ${pc3.bold("Setup complete")} ${scopeLabel(scope)}`);
|
|
1244
|
+
console.log(` ${pc3.dim("\u2500".repeat(42))}`);
|
|
1245
|
+
console.log(` ${pc3.dim("Account:")} ${scopeDisplay} ${pc3.dim("\xB7")} ${envLabel}`);
|
|
1246
|
+
console.log(` ${pc3.dim("User:")} ${whoami.user.name} ${pc3.dim(`(${whoami.user.email})`)}`);
|
|
1247
|
+
if (keyName) console.log(` ${pc3.dim("Key:")} ${keyName}`);
|
|
1248
|
+
if (grant) console.log(` ${pc3.dim("Access:")} ${grant}`);
|
|
1249
|
+
console.log(` ${pc3.dim("Config:")} ${tildify(configPath)}`);
|
|
1874
1250
|
if (installed.length > 0) {
|
|
1875
|
-
console.log(` ${
|
|
1251
|
+
console.log(` ${pc3.dim("Skill:")} ${pc3.green("installed")} ${pc3.dim("\xB7 " + installed.join(", "))}`);
|
|
1876
1252
|
}
|
|
1877
1253
|
console.log();
|
|
1878
|
-
console.log(` ${
|
|
1254
|
+
console.log(` ${pc3.dim("Connect a platform later with")} ${pc3.cyan("one add <platform>")}`);
|
|
1879
1255
|
printOnboardingPrompt();
|
|
1880
1256
|
}
|
|
1881
1257
|
async function chooseConfigScope(options) {
|
|
@@ -1885,13 +1261,13 @@ async function chooseConfigScope(options) {
|
|
|
1885
1261
|
const hasGlobal = globalConfigExists();
|
|
1886
1262
|
const hasProject = projectConfigExists();
|
|
1887
1263
|
const projectRoot = resolved.projectRoot;
|
|
1888
|
-
const projectName =
|
|
1264
|
+
const projectName = path2.basename(projectRoot);
|
|
1889
1265
|
const homeGlobal = tildify(getGlobalConfigPath());
|
|
1890
1266
|
const homeProject = tildify(getProjectConfigPath(projectRoot));
|
|
1891
1267
|
if (hasProject) {
|
|
1892
1268
|
console.log();
|
|
1893
|
-
console.log(` ${
|
|
1894
|
-
console.log(` ${
|
|
1269
|
+
console.log(` ${pc3.dim("Project:")} ${projectName} ${pc3.dim(projectRoot)}`);
|
|
1270
|
+
console.log(` ${pc3.bold("Active config:")} ${pc3.cyan("project")} ${pc3.dim("\xB7 " + homeProject)}`);
|
|
1895
1271
|
console.log();
|
|
1896
1272
|
if (hasGlobal) {
|
|
1897
1273
|
const which2 = await p3.select({
|
|
@@ -1908,11 +1284,11 @@ async function chooseConfigScope(options) {
|
|
|
1908
1284
|
return "project";
|
|
1909
1285
|
}
|
|
1910
1286
|
console.log();
|
|
1911
|
-
console.log(` ${
|
|
1912
|
-
console.log(` ${
|
|
1913
|
-
console.log(` ${
|
|
1914
|
-
console.log(` ${
|
|
1915
|
-
console.log(` ${
|
|
1287
|
+
console.log(` ${pc3.bold("Initializing One")}`);
|
|
1288
|
+
console.log(` ${pc3.dim("\u2500".repeat(42))}`);
|
|
1289
|
+
console.log(` ${pc3.dim("Project:")} ${projectName} ${pc3.dim(projectRoot)}`);
|
|
1290
|
+
console.log(` ${pc3.dim("Global:")} ${hasGlobal ? pc3.green("\u2713 configured") : pc3.yellow("\u2014 not set up")} ${pc3.dim(homeGlobal)}`);
|
|
1291
|
+
console.log(` ${pc3.dim("Project:")} ${pc3.yellow("\u2014 not set up")} ${pc3.dim(homeProject)}`);
|
|
1916
1292
|
console.log();
|
|
1917
1293
|
const defaultScope = hasGlobal ? "project" : "global";
|
|
1918
1294
|
const hint = hasGlobal ? "Your global config stays as-is. This folder gets its own setup." : "No global config yet \u2014 this becomes your default for every folder.";
|
|
@@ -1941,7 +1317,7 @@ function tildify(filePath) {
|
|
|
1941
1317
|
return filePath.startsWith(home) ? "~" + filePath.slice(home.length) : filePath;
|
|
1942
1318
|
}
|
|
1943
1319
|
function scopeLabel(scope) {
|
|
1944
|
-
return scope === "project" ?
|
|
1320
|
+
return scope === "project" ? pc3.cyan("[project]") : pc3.magenta("[global]");
|
|
1945
1321
|
}
|
|
1946
1322
|
function scopedMessage(scope, message) {
|
|
1947
1323
|
return `${scopeLabel(scope)} ${message}`;
|
|
@@ -1952,20 +1328,20 @@ async function handleExistingConfig(apiKey, scope, options) {
|
|
|
1952
1328
|
const skillInstalled = isSkillInstalled2();
|
|
1953
1329
|
const activeConfigPath = scope === "project" ? getProjectConfigPath() : getGlobalConfigPath();
|
|
1954
1330
|
console.log();
|
|
1955
|
-
console.log(` ${
|
|
1956
|
-
console.log(` ${
|
|
1957
|
-
console.log(` ${
|
|
1958
|
-
console.log(` ${
|
|
1959
|
-
console.log(` ${
|
|
1331
|
+
console.log(` ${pc3.bold("Current Setup")} ${scopeLabel(scope)}`);
|
|
1332
|
+
console.log(` ${pc3.dim("\u2500".repeat(42))}`);
|
|
1333
|
+
console.log(` ${pc3.dim("API Key:")} ${masked}`);
|
|
1334
|
+
console.log(` ${pc3.dim("Skill:")} ${skillInstalled ? pc3.green("installed") : pc3.yellow("not installed")}`);
|
|
1335
|
+
console.log(` ${pc3.dim("Config:")} ${tildify(activeConfigPath)}`);
|
|
1960
1336
|
const ac = getAccessControl();
|
|
1961
1337
|
if (Object.keys(ac).length > 0) {
|
|
1962
1338
|
console.log();
|
|
1963
|
-
console.log(` ${
|
|
1964
|
-
console.log(` ${
|
|
1965
|
-
if (ac.permissions) console.log(` ${
|
|
1966
|
-
if (ac.connectionKeys) console.log(` ${
|
|
1967
|
-
if (ac.actionIds) console.log(` ${
|
|
1968
|
-
if (ac.knowledgeAgent) console.log(` ${
|
|
1339
|
+
console.log(` ${pc3.bold("Access Control")}`);
|
|
1340
|
+
console.log(` ${pc3.dim("\u2500".repeat(42))}`);
|
|
1341
|
+
if (ac.permissions) console.log(` ${pc3.dim("Permissions:")} ${ac.permissions}`);
|
|
1342
|
+
if (ac.connectionKeys) console.log(` ${pc3.dim("Connections:")} ${ac.connectionKeys.join(", ")}`);
|
|
1343
|
+
if (ac.actionIds) console.log(` ${pc3.dim("Action IDs:")} ${ac.actionIds.join(", ")}`);
|
|
1344
|
+
if (ac.knowledgeAgent) console.log(` ${pc3.dim("Knowledge only:")} yes`);
|
|
1969
1345
|
}
|
|
1970
1346
|
console.log();
|
|
1971
1347
|
const actionOptions = [];
|
|
@@ -2081,7 +1457,7 @@ async function handleUpdateKey(statuses, scope) {
|
|
|
2081
1457
|
whoamiResult = result.whoami;
|
|
2082
1458
|
} else {
|
|
2083
1459
|
p3.note(`Get your API key at:
|
|
2084
|
-
${
|
|
1460
|
+
${pc3.cyan(getApiKeyUrl())}`, `API Key ${scopeLabel(scope)}`);
|
|
2085
1461
|
const openBrowser = await p3.confirm({
|
|
2086
1462
|
message: scopedMessage(scope, "Open browser to get API key?"),
|
|
2087
1463
|
initialValue: true
|
|
@@ -2126,13 +1502,13 @@ ${pc4.cyan(getApiKeyUrl())}`, `API Key ${scopeLabel(scope)}`);
|
|
|
2126
1502
|
if (whoamiResult.organization) contextParts.push(whoamiResult.organization.name);
|
|
2127
1503
|
if (whoamiResult.project) contextParts.push(whoamiResult.project.name);
|
|
2128
1504
|
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
2129
|
-
const envLabel = env === "test" ?
|
|
1505
|
+
const envLabel = env === "test" ? pc3.yellow("test") : pc3.green("live");
|
|
2130
1506
|
p3.note(
|
|
2131
1507
|
[
|
|
2132
|
-
`${scopeDisplay} ${
|
|
2133
|
-
`${whoamiResult.user.name} ${
|
|
2134
|
-
...keyName ? [`${
|
|
2135
|
-
...grantNoteLines(grant,
|
|
1508
|
+
`${scopeDisplay} ${pc3.dim("\xB7")} ${envLabel}`,
|
|
1509
|
+
`${whoamiResult.user.name} ${pc3.dim(`(${whoamiResult.user.email})`)}`,
|
|
1510
|
+
...keyName ? [`${pc3.dim("Key:")} ${keyName}`] : [],
|
|
1511
|
+
...grantNoteLines(grant, pc3.dim("Access:"))
|
|
2136
1512
|
].join("\n"),
|
|
2137
1513
|
"Account"
|
|
2138
1514
|
);
|
|
@@ -2168,30 +1544,30 @@ var SKILL_AGENTS = [
|
|
|
2168
1544
|
];
|
|
2169
1545
|
var CANONICAL_SKILL_DIR2 = ".agents/skills";
|
|
2170
1546
|
function getSkillSourceDir() {
|
|
2171
|
-
const __dirname2 =
|
|
2172
|
-
return
|
|
1547
|
+
const __dirname2 = path2.dirname(fileURLToPath2(import.meta.url));
|
|
1548
|
+
return path2.resolve(__dirname2, "..", "skills", "one");
|
|
2173
1549
|
}
|
|
2174
1550
|
function getCanonicalSkillPath2() {
|
|
2175
|
-
return
|
|
1551
|
+
return path2.join(homeDir(), CANONICAL_SKILL_DIR2, "one");
|
|
2176
1552
|
}
|
|
2177
1553
|
function getAgentSkillPath(agent) {
|
|
2178
|
-
return
|
|
1554
|
+
return path2.join(homeDir(), agent.skillDir, "one");
|
|
2179
1555
|
}
|
|
2180
1556
|
function isSkillInstalled2() {
|
|
2181
|
-
return
|
|
1557
|
+
return fs2.existsSync(path2.join(getCanonicalSkillPath2(), "SKILL.md"));
|
|
2182
1558
|
}
|
|
2183
1559
|
function isSkillInstalledForAgent(agent) {
|
|
2184
|
-
return
|
|
1560
|
+
return fs2.existsSync(path2.join(getAgentSkillPath(agent), "SKILL.md"));
|
|
2185
1561
|
}
|
|
2186
1562
|
function copyDirSync2(src, dest) {
|
|
2187
|
-
|
|
2188
|
-
for (const entry of
|
|
2189
|
-
const srcPath =
|
|
2190
|
-
const destPath =
|
|
1563
|
+
fs2.mkdirSync(dest, { recursive: true });
|
|
1564
|
+
for (const entry of fs2.readdirSync(src, { withFileTypes: true })) {
|
|
1565
|
+
const srcPath = path2.join(src, entry.name);
|
|
1566
|
+
const destPath = path2.join(dest, entry.name);
|
|
2191
1567
|
if (entry.isDirectory()) {
|
|
2192
1568
|
copyDirSync2(srcPath, destPath);
|
|
2193
1569
|
} else {
|
|
2194
|
-
|
|
1570
|
+
fs2.copyFileSync(srcPath, destPath);
|
|
2195
1571
|
}
|
|
2196
1572
|
}
|
|
2197
1573
|
}
|
|
@@ -2200,12 +1576,12 @@ function installSkillForAgents(agentIds) {
|
|
|
2200
1576
|
const canonical = getCanonicalSkillPath2();
|
|
2201
1577
|
const installed = [];
|
|
2202
1578
|
const failed = [];
|
|
2203
|
-
if (!
|
|
1579
|
+
if (!fs2.existsSync(path2.join(source, "SKILL.md"))) {
|
|
2204
1580
|
return { installed: [], failed: ["skill source not found"] };
|
|
2205
1581
|
}
|
|
2206
1582
|
try {
|
|
2207
|
-
if (
|
|
2208
|
-
|
|
1583
|
+
if (fs2.existsSync(canonical)) {
|
|
1584
|
+
fs2.rmSync(canonical, { recursive: true });
|
|
2209
1585
|
}
|
|
2210
1586
|
copyDirSync2(source, canonical);
|
|
2211
1587
|
writeInstalledSkillVersion(getCurrentVersion());
|
|
@@ -2222,15 +1598,15 @@ function installSkillForAgents(agentIds) {
|
|
|
2222
1598
|
continue;
|
|
2223
1599
|
}
|
|
2224
1600
|
try {
|
|
2225
|
-
const agentSkillsDir =
|
|
2226
|
-
|
|
1601
|
+
const agentSkillsDir = path2.dirname(agentPath);
|
|
1602
|
+
fs2.mkdirSync(agentSkillsDir, { recursive: true });
|
|
2227
1603
|
try {
|
|
2228
|
-
|
|
2229
|
-
|
|
1604
|
+
fs2.lstatSync(agentPath);
|
|
1605
|
+
fs2.rmSync(agentPath, { recursive: true });
|
|
2230
1606
|
} catch {
|
|
2231
1607
|
}
|
|
2232
|
-
const relative =
|
|
2233
|
-
|
|
1608
|
+
const relative = path2.relative(agentSkillsDir, canonical);
|
|
1609
|
+
fs2.symlinkSync(relative, agentPath);
|
|
2234
1610
|
installed.push(agent.name);
|
|
2235
1611
|
seen.set(agentPath, true);
|
|
2236
1612
|
} catch {
|
|
@@ -2245,7 +1621,7 @@ async function promptOpenAiKey(scope) {
|
|
|
2245
1621
|
const entered = await p3.password({
|
|
2246
1622
|
message: scopedMessage(
|
|
2247
1623
|
scope,
|
|
2248
|
-
`OpenAI API key ${
|
|
1624
|
+
`OpenAI API key ${pc3.dim("(optional \u2014 enables semantic search in `one mem`)")}`
|
|
2249
1625
|
),
|
|
2250
1626
|
mask: "\u2022",
|
|
2251
1627
|
// Validator accepts empty → treated as "skip".
|
|
@@ -2300,7 +1676,7 @@ async function promptSkillInstall() {
|
|
|
2300
1676
|
...primaryAgents.map((a) => ({
|
|
2301
1677
|
value: a.id,
|
|
2302
1678
|
label: a.name,
|
|
2303
|
-
hint: isSkillInstalledForAgent(a) ?
|
|
1679
|
+
hint: isSkillInstalledForAgent(a) ? pc3.green("installed") : void 0
|
|
2304
1680
|
})),
|
|
2305
1681
|
{
|
|
2306
1682
|
value: "_other",
|
|
@@ -2324,7 +1700,7 @@ async function promptSkillInstall() {
|
|
|
2324
1700
|
options: otherAgents.map((a) => ({
|
|
2325
1701
|
value: a.id,
|
|
2326
1702
|
label: a.name,
|
|
2327
|
-
hint: isSkillInstalledForAgent(a) ?
|
|
1703
|
+
hint: isSkillInstalledForAgent(a) ? pc3.green("installed") : void 0
|
|
2328
1704
|
}))
|
|
2329
1705
|
});
|
|
2330
1706
|
if (!p3.isCancel(otherChoice)) {
|
|
@@ -2340,7 +1716,7 @@ async function promptSkillInstall() {
|
|
|
2340
1716
|
const { installed, failed } = installSkillForAgents(selectedIds);
|
|
2341
1717
|
spinner.stop(installed.length > 0 ? "Skill installed" : "Installation failed");
|
|
2342
1718
|
for (const name of installed) {
|
|
2343
|
-
p3.log.success(`${name}: ${
|
|
1719
|
+
p3.log.success(`${name}: ${pc3.green("\u2713")} skill installed`);
|
|
2344
1720
|
}
|
|
2345
1721
|
for (const name of failed) {
|
|
2346
1722
|
p3.log.warn(`${name}: failed to install`);
|
|
@@ -2349,19 +1725,19 @@ async function promptSkillInstall() {
|
|
|
2349
1725
|
}
|
|
2350
1726
|
function printOnboardingPrompt() {
|
|
2351
1727
|
console.log();
|
|
2352
|
-
console.log(
|
|
1728
|
+
console.log(pc3.bold(" Copy-paste this to your AI agent:"));
|
|
2353
1729
|
console.log();
|
|
2354
|
-
console.log(
|
|
2355
|
-
console.log(
|
|
2356
|
-
console.log(
|
|
2357
|
-
console.log(
|
|
2358
|
-
console.log(
|
|
2359
|
-
console.log(
|
|
2360
|
-
console.log(
|
|
2361
|
-
console.log(
|
|
2362
|
-
console.log(
|
|
2363
|
-
console.log(
|
|
2364
|
-
console.log(
|
|
1730
|
+
console.log(pc3.cyan(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
1731
|
+
console.log(pc3.cyan(" \u2502"));
|
|
1732
|
+
console.log(pc3.cyan(" \u2502 The One CLI (`one`) is now installed on this machine. It"));
|
|
1733
|
+
console.log(pc3.cyan(" \u2502 lets you interact with 750+ third-party platforms (Gmail,"));
|
|
1734
|
+
console.log(pc3.cyan(" \u2502 Slack, Shopify, HubSpot, Stripe, GitHub, etc.) through"));
|
|
1735
|
+
console.log(pc3.cyan(" \u2502 their APIs. Whenever you need to interact with any"));
|
|
1736
|
+
console.log(pc3.cyan(" \u2502 third-party platform or external service, use the `one`"));
|
|
1737
|
+
console.log(pc3.cyan(" \u2502 skill. Please save this to your project instructions or"));
|
|
1738
|
+
console.log(pc3.cyan(" \u2502 memory so you remember it in future conversations."));
|
|
1739
|
+
console.log(pc3.cyan(" \u2502"));
|
|
1740
|
+
console.log(pc3.cyan(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
2365
1741
|
console.log();
|
|
2366
1742
|
}
|
|
2367
1743
|
async function freshSetup(scope, options) {
|
|
@@ -2389,13 +1765,13 @@ async function freshSetup(scope, options) {
|
|
|
2389
1765
|
if (result.whoami.organization) contextParts.push(result.whoami.organization.name);
|
|
2390
1766
|
if (result.whoami.project) contextParts.push(result.whoami.project.name);
|
|
2391
1767
|
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
2392
|
-
const envLabel = env2 === "test" ?
|
|
1768
|
+
const envLabel = env2 === "test" ? pc3.yellow("test") : pc3.green("live");
|
|
2393
1769
|
p3.note(
|
|
2394
1770
|
[
|
|
2395
|
-
`${scopeDisplay} ${
|
|
2396
|
-
`${result.whoami.user.name} ${
|
|
2397
|
-
...result.keyName ? [`${
|
|
2398
|
-
...grantNoteLines(result.grant,
|
|
1771
|
+
`${scopeDisplay} ${pc3.dim("\xB7")} ${envLabel}`,
|
|
1772
|
+
`${result.whoami.user.name} ${pc3.dim(`(${result.whoami.user.email})`)}`,
|
|
1773
|
+
...result.keyName ? [`${pc3.dim("Key:")} ${result.keyName}`] : [],
|
|
1774
|
+
...grantNoteLines(result.grant, pc3.dim("Access:"))
|
|
2399
1775
|
].join("\n"),
|
|
2400
1776
|
"Account"
|
|
2401
1777
|
);
|
|
@@ -2406,7 +1782,7 @@ async function freshSetup(scope, options) {
|
|
|
2406
1782
|
});
|
|
2407
1783
|
} else {
|
|
2408
1784
|
p3.note(`Get your API key at:
|
|
2409
|
-
${
|
|
1785
|
+
${pc3.cyan(getApiKeyUrl())}`, `API Key ${scopeLabel(scope)}`);
|
|
2410
1786
|
const openBrowser = await p3.confirm({
|
|
2411
1787
|
message: scopedMessage(scope, "Open browser to get API key?"),
|
|
2412
1788
|
initialValue: true
|
|
@@ -2449,10 +1825,10 @@ ${pc4.cyan(getApiKeyUrl())}`, `API Key ${scopeLabel(scope)}`);
|
|
|
2449
1825
|
if (whoami.organization) contextParts.push(whoami.organization.name);
|
|
2450
1826
|
if (whoami.project) contextParts.push(whoami.project.name);
|
|
2451
1827
|
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
2452
|
-
const envLabel = env2 === "test" ?
|
|
1828
|
+
const envLabel = env2 === "test" ? pc3.yellow("test") : pc3.green("live");
|
|
2453
1829
|
p3.note(
|
|
2454
|
-
`${scopeDisplay} ${
|
|
2455
|
-
${whoami.user.name} ${
|
|
1830
|
+
`${scopeDisplay} ${pc3.dim("\xB7")} ${envLabel}
|
|
1831
|
+
${whoami.user.name} ${pc3.dim(`(${whoami.user.email})`)}`,
|
|
2456
1832
|
"Account"
|
|
2457
1833
|
);
|
|
2458
1834
|
saveCredentials(apiKey, scope, { whoami });
|
|
@@ -2468,11 +1844,11 @@ ${whoami.user.name} ${pc4.dim(`(${whoami.user.email})`)}`,
|
|
|
2468
1844
|
};
|
|
2469
1845
|
await promptConnectIntegrations(apiKey, connParams);
|
|
2470
1846
|
const savedPath = scope === "project" ? getProjectConfigPath() : getGlobalConfigPath();
|
|
2471
|
-
const resolutionHint = scope === "project" ? `When you run ${
|
|
1847
|
+
const resolutionHint = scope === "project" ? `When you run ${pc3.cyan("one")} from ${pc3.bold(path2.basename(getProjectRoot()))}, it uses this project config.
|
|
2472
1848
|
From anywhere else, it falls back to your global config.` : `This config applies to every folder unless a project config is set.`;
|
|
2473
1849
|
p3.note(
|
|
2474
1850
|
`${scopeLabel(scope)} Config saved to:
|
|
2475
|
-
${
|
|
1851
|
+
${pc3.dim(tildify(savedPath))}
|
|
2476
1852
|
|
|
2477
1853
|
${resolutionHint}`,
|
|
2478
1854
|
"Setup Complete"
|
|
@@ -2481,9 +1857,9 @@ ${resolutionHint}`,
|
|
|
2481
1857
|
p3.outro("Done! Paste the prompt above to your AI agent.");
|
|
2482
1858
|
}
|
|
2483
1859
|
function lime(text5) {
|
|
2484
|
-
if (!
|
|
1860
|
+
if (!pc3.isColorSupported) return text5;
|
|
2485
1861
|
const truecolor = process.env.COLORTERM === "truecolor" || process.env.COLORTERM === "24bit";
|
|
2486
|
-
return truecolor ? `\x1B[38;2;204;255;0m${text5}\x1B[39m` :
|
|
1862
|
+
return truecolor ? `\x1B[38;2;204;255;0m${text5}\x1B[39m` : pc3.green(text5);
|
|
2487
1863
|
}
|
|
2488
1864
|
function printBanner() {
|
|
2489
1865
|
console.log();
|
|
@@ -2498,7 +1874,7 @@ function printBanner() {
|
|
|
2498
1874
|
console.log(lime(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
|
|
2499
1875
|
console.log(lime(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
|
|
2500
1876
|
console.log();
|
|
2501
|
-
console.log(
|
|
1877
|
+
console.log(pc3.dim(" I N F R A S T R U C T U R E F O R A G E N T S"));
|
|
2502
1878
|
console.log();
|
|
2503
1879
|
}
|
|
2504
1880
|
var TOP_INTEGRATIONS = [
|
|
@@ -2544,13 +1920,13 @@ async function promptConnectIntegrations(apiKey, connParams) {
|
|
|
2544
1920
|
} catch {
|
|
2545
1921
|
p3.note(connectionsUrl, "Open in browser");
|
|
2546
1922
|
}
|
|
2547
|
-
p3.log.info(`Connect from the dashboard, or use ${
|
|
1923
|
+
p3.log.info(`Connect from the dashboard, or use ${pc3.cyan("one add <platform>")}`);
|
|
2548
1924
|
break;
|
|
2549
1925
|
}
|
|
2550
1926
|
const platform = choice;
|
|
2551
1927
|
const integration = TOP_INTEGRATIONS.find((i) => i.value === platform);
|
|
2552
1928
|
const label = integration?.label ?? platform;
|
|
2553
|
-
p3.log.info(`Opening browser to connect ${
|
|
1929
|
+
p3.log.info(`Opening browser to connect ${pc3.cyan(label)}...`);
|
|
2554
1930
|
try {
|
|
2555
1931
|
await openConnectionPage(platform, connParams);
|
|
2556
1932
|
} catch {
|
|
@@ -2563,13 +1939,13 @@ async function promptConnectIntegrations(apiKey, connParams) {
|
|
|
2563
1939
|
try {
|
|
2564
1940
|
await api.waitForConnection(platform, 5 * 60 * 1e3, 5e3);
|
|
2565
1941
|
spinner.stop(`${label} connected!`);
|
|
2566
|
-
p3.log.success(`${
|
|
1942
|
+
p3.log.success(`${pc3.green("\u2713")} ${label} is now available to your AI agents`);
|
|
2567
1943
|
connected.push(platform);
|
|
2568
1944
|
first = false;
|
|
2569
1945
|
} catch (error2) {
|
|
2570
1946
|
spinner.stop("Connection timed out");
|
|
2571
1947
|
if (error2 instanceof TimeoutError) {
|
|
2572
|
-
p3.log.warn(`No worries. Connect later with: ${
|
|
1948
|
+
p3.log.warn(`No worries. Connect later with: ${pc3.cyan(`one add ${platform}`)}`);
|
|
2573
1949
|
}
|
|
2574
1950
|
first = false;
|
|
2575
1951
|
}
|
|
@@ -2586,7 +1962,7 @@ function maskApiKey(key) {
|
|
|
2586
1962
|
|
|
2587
1963
|
// src/commands/connection.ts
|
|
2588
1964
|
import * as p4 from "@clack/prompts";
|
|
2589
|
-
import
|
|
1965
|
+
import pc5 from "picocolors";
|
|
2590
1966
|
|
|
2591
1967
|
// src/lib/access.ts
|
|
2592
1968
|
async function resolveAllowedActions(api, actionIds) {
|
|
@@ -2742,7 +2118,7 @@ function countMatchingChars(a, b) {
|
|
|
2742
2118
|
}
|
|
2743
2119
|
|
|
2744
2120
|
// src/lib/table.ts
|
|
2745
|
-
import
|
|
2121
|
+
import pc4 from "picocolors";
|
|
2746
2122
|
function printTable(columns, rows) {
|
|
2747
2123
|
if (rows.length === 0) return;
|
|
2748
2124
|
const gap = " ";
|
|
@@ -2754,10 +2130,10 @@ function printTable(columns, rows) {
|
|
|
2754
2130
|
});
|
|
2755
2131
|
const header = columns.map((col, i) => {
|
|
2756
2132
|
const padded = col.align === "right" ? col.label.padStart(widths[i]) : col.label.padEnd(widths[i]);
|
|
2757
|
-
return
|
|
2133
|
+
return pc4.dim(padded);
|
|
2758
2134
|
}).join(gap);
|
|
2759
2135
|
console.log(`${indent}${header}`);
|
|
2760
|
-
const separator = columns.map((_, i) =>
|
|
2136
|
+
const separator = columns.map((_, i) => pc4.dim("\u2500".repeat(widths[i]))).join(gap);
|
|
2761
2137
|
console.log(`${indent}${separator}`);
|
|
2762
2138
|
for (const row of rows) {
|
|
2763
2139
|
const line = columns.map((col, i) => {
|
|
@@ -2782,7 +2158,7 @@ async function connectionAddCommand(platformArg, options) {
|
|
|
2782
2158
|
if (isAgentMode()) {
|
|
2783
2159
|
error("This command requires interactive input. Run without --agent.");
|
|
2784
2160
|
}
|
|
2785
|
-
p4.intro(
|
|
2161
|
+
p4.intro(pc5.bgCyan(pc5.black(" One ")));
|
|
2786
2162
|
const apiKey = getApiKey();
|
|
2787
2163
|
if (!apiKey) {
|
|
2788
2164
|
p4.cancel("Not configured. Run `one init` first.");
|
|
@@ -2817,7 +2193,7 @@ async function connectionAddCommand(platformArg, options) {
|
|
|
2817
2193
|
]
|
|
2818
2194
|
});
|
|
2819
2195
|
if (p4.isCancel(suggestion) || suggestion === "__other__") {
|
|
2820
|
-
p4.note(`Run ${
|
|
2196
|
+
p4.note(`Run ${pc5.cyan("one platforms")} to see all available platforms.`);
|
|
2821
2197
|
p4.cancel("Connection cancelled.");
|
|
2822
2198
|
process.exit(0);
|
|
2823
2199
|
}
|
|
@@ -2825,7 +2201,7 @@ async function connectionAddCommand(platformArg, options) {
|
|
|
2825
2201
|
} else {
|
|
2826
2202
|
p4.cancel(`Unknown platform: ${platformArg}
|
|
2827
2203
|
|
|
2828
|
-
Run ${
|
|
2204
|
+
Run ${pc5.cyan("one platforms")} to see available platforms.`);
|
|
2829
2205
|
process.exit(1);
|
|
2830
2206
|
}
|
|
2831
2207
|
}
|
|
@@ -2848,7 +2224,7 @@ Run ${pc6.cyan("one platforms")} to see available platforms.`);
|
|
|
2848
2224
|
} else {
|
|
2849
2225
|
p4.cancel(`Unknown platform: ${platformInput}
|
|
2850
2226
|
|
|
2851
|
-
Run ${
|
|
2227
|
+
Run ${pc5.cyan("one platforms")} to see available platforms.`);
|
|
2852
2228
|
process.exit(1);
|
|
2853
2229
|
}
|
|
2854
2230
|
}
|
|
@@ -2859,8 +2235,8 @@ Run ${pc6.cyan("one platforms")} to see available platforms.`);
|
|
|
2859
2235
|
...whoami?.project && { projectId: whoami.project.id }
|
|
2860
2236
|
};
|
|
2861
2237
|
const url = getConnectionUrl(platform, connParams);
|
|
2862
|
-
p4.log.info(`Opening browser to connect ${
|
|
2863
|
-
p4.note(
|
|
2238
|
+
p4.log.info(`Opening browser to connect ${pc5.cyan(platform)}...`);
|
|
2239
|
+
p4.note(pc5.dim(url), "URL");
|
|
2864
2240
|
try {
|
|
2865
2241
|
await openConnectionPage(platform, connParams);
|
|
2866
2242
|
} catch {
|
|
@@ -2888,7 +2264,7 @@ The connection is usable; set the tag later in the dashboard or retry.`
|
|
|
2888
2264
|
);
|
|
2889
2265
|
}
|
|
2890
2266
|
}
|
|
2891
|
-
p4.log.success(`${
|
|
2267
|
+
p4.log.success(`${pc5.green("\u2713")} ${connection2.platform} is now available to your AI agents.${tag ? ` (tag: ${tag})` : ""}`);
|
|
2892
2268
|
p4.outro("Connection complete!");
|
|
2893
2269
|
} catch (error2) {
|
|
2894
2270
|
pollSpinner.stop("Connection timed out");
|
|
@@ -2899,7 +2275,7 @@ The connection is usable; set the tag later in the dashboard or retry.`
|
|
|
2899
2275
|
- Browser popup was blocked
|
|
2900
2276
|
- Wrong account selected
|
|
2901
2277
|
|
|
2902
|
-
Try again with: ${
|
|
2278
|
+
Try again with: ${pc5.cyan(`one connection add ${platform}`)}`,
|
|
2903
2279
|
"Timed Out"
|
|
2904
2280
|
);
|
|
2905
2281
|
} else {
|
|
@@ -2976,7 +2352,7 @@ async function connectionListCommand(options) {
|
|
|
2976
2352
|
p4.note(
|
|
2977
2353
|
`No connections matching "${searchQuery}".
|
|
2978
2354
|
|
|
2979
|
-
Try: ${
|
|
2355
|
+
Try: ${pc5.cyan("one connection list")} to see all connections.`,
|
|
2980
2356
|
"No Results"
|
|
2981
2357
|
);
|
|
2982
2358
|
} else if (serverAccess.doc?.rules && allConnections.length === 0) {
|
|
@@ -2990,7 +2366,7 @@ Change it in the dashboard under API keys.`,
|
|
|
2990
2366
|
p4.note(
|
|
2991
2367
|
`No connections yet.
|
|
2992
2368
|
|
|
2993
|
-
Add one with: ${
|
|
2369
|
+
Add one with: ${pc5.cyan("one connection add gmail")}`,
|
|
2994
2370
|
"No Connections"
|
|
2995
2371
|
);
|
|
2996
2372
|
}
|
|
@@ -3011,9 +2387,9 @@ Add one with: ${pc6.cyan("one connection add gmail")}`,
|
|
|
3011
2387
|
{ key: "status", label: "" },
|
|
3012
2388
|
{ key: "platform", label: "Platform" },
|
|
3013
2389
|
{ key: "state", label: "Status" },
|
|
3014
|
-
{ key: "key", label: "Connection Key", color:
|
|
3015
|
-
...hasTags ? [{ key: "tags", label: "Tags", color:
|
|
3016
|
-
{ key: "access", label: serverAccess.ok ? "Access" : "Access (CLI settings only)", color:
|
|
2390
|
+
{ key: "key", label: "Connection Key", color: pc5.dim },
|
|
2391
|
+
...hasTags ? [{ key: "tags", label: "Tags", color: pc5.dim }] : [],
|
|
2392
|
+
{ key: "access", label: serverAccess.ok ? "Access" : "Access (CLI settings only)", color: pc5.yellow }
|
|
3017
2393
|
],
|
|
3018
2394
|
rows
|
|
3019
2395
|
);
|
|
@@ -3026,7 +2402,7 @@ Add one with: ${pc6.cyan("one connection add gmail")}`,
|
|
|
3026
2402
|
p4.note(
|
|
3027
2403
|
`${wrapText(lines.join("\n"))}
|
|
3028
2404
|
|
|
3029
|
-
This key's access: dashboard \u2192 API keys. This CLI's own limits: ${
|
|
2405
|
+
This key's access: dashboard \u2192 API keys. This CLI's own limits: ${pc5.cyan("one config")}`,
|
|
3030
2406
|
"Access"
|
|
3031
2407
|
);
|
|
3032
2408
|
}
|
|
@@ -3036,7 +2412,7 @@ This key's access: dashboard \u2192 API keys. This CLI's own limits: ${pc6.cyan(
|
|
|
3036
2412
|
"Limited"
|
|
3037
2413
|
);
|
|
3038
2414
|
} else {
|
|
3039
|
-
p4.note(`Add more with: ${
|
|
2415
|
+
p4.note(`Add more with: ${pc5.cyan("one connection add <platform>")}`, "Tip");
|
|
3040
2416
|
}
|
|
3041
2417
|
} catch (error2) {
|
|
3042
2418
|
spinner.stop("Failed to load connections");
|
|
@@ -3072,7 +2448,7 @@ async function connectionDeleteCommand(connectionKey, options) {
|
|
|
3072
2448
|
spinner.stop(`Found ${connection2.platform} (${connection2.state})`);
|
|
3073
2449
|
if (!isAgentMode() && !options?.force) {
|
|
3074
2450
|
console.log();
|
|
3075
|
-
console.log(` ${getStatusIndicator(connection2.state)} ${connection2.platform} ${
|
|
2451
|
+
console.log(` ${getStatusIndicator(connection2.state)} ${connection2.platform} ${pc5.dim(connection2.key)}`);
|
|
3076
2452
|
console.log();
|
|
3077
2453
|
const confirmed = await p4.confirm({
|
|
3078
2454
|
message: "Are you sure you want to delete this connection?",
|
|
@@ -3096,7 +2472,7 @@ async function connectionDeleteCommand(connectionKey, options) {
|
|
|
3096
2472
|
});
|
|
3097
2473
|
return;
|
|
3098
2474
|
}
|
|
3099
|
-
p4.log.success(`${
|
|
2475
|
+
p4.log.success(`${pc5.green("\u2713")} ${connection2.platform} connection removed.`);
|
|
3100
2476
|
} catch (error2) {
|
|
3101
2477
|
deleteSpinner.stop("Failed to delete connection");
|
|
3102
2478
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
@@ -3150,19 +2526,19 @@ function wrapText(text5, width = 72) {
|
|
|
3150
2526
|
function getStatusIndicator(state) {
|
|
3151
2527
|
switch (state) {
|
|
3152
2528
|
case "operational":
|
|
3153
|
-
return
|
|
2529
|
+
return pc5.green("\u25CF");
|
|
3154
2530
|
case "degraded":
|
|
3155
|
-
return
|
|
2531
|
+
return pc5.yellow("\u25CF");
|
|
3156
2532
|
case "failed":
|
|
3157
|
-
return
|
|
2533
|
+
return pc5.red("\u25CF");
|
|
3158
2534
|
default:
|
|
3159
|
-
return
|
|
2535
|
+
return pc5.dim("\u25CB");
|
|
3160
2536
|
}
|
|
3161
2537
|
}
|
|
3162
2538
|
|
|
3163
2539
|
// src/commands/platforms.ts
|
|
3164
2540
|
import * as p5 from "@clack/prompts";
|
|
3165
|
-
import
|
|
2541
|
+
import pc6 from "picocolors";
|
|
3166
2542
|
async function platformsCommand(options) {
|
|
3167
2543
|
const apiKey = getApiKey();
|
|
3168
2544
|
if (!apiKey) {
|
|
@@ -3228,7 +2604,7 @@ async function platformsCommand(options) {
|
|
|
3228
2604
|
);
|
|
3229
2605
|
}
|
|
3230
2606
|
console.log();
|
|
3231
|
-
p5.note(`Connect with: ${
|
|
2607
|
+
p5.note(`Connect with: ${pc6.cyan("one connection add <platform>")}`, "Tip");
|
|
3232
2608
|
} catch (error2) {
|
|
3233
2609
|
spinner.stop("Failed to load platforms");
|
|
3234
2610
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
@@ -3236,7 +2612,7 @@ async function platformsCommand(options) {
|
|
|
3236
2612
|
}
|
|
3237
2613
|
|
|
3238
2614
|
// src/commands/actions.ts
|
|
3239
|
-
import
|
|
2615
|
+
import pc7 from "picocolors";
|
|
3240
2616
|
|
|
3241
2617
|
// src/lib/knowledge-sections.ts
|
|
3242
2618
|
var DEFAULT_WHOLE_DOC_THRESHOLD = 8e3;
|
|
@@ -3893,7 +3269,7 @@ var CUSTOM_ACTION_NOTE = '\n\nThis is a custom action: ALSO include "connectionK
|
|
|
3893
3269
|
function codeGuideAction(action, knowledge, platform, tags, apiBase) {
|
|
3894
3270
|
const base = apiBase.replace(/\/$/, "");
|
|
3895
3271
|
const method = action.method.toUpperCase();
|
|
3896
|
-
const
|
|
3272
|
+
const path13 = action.path.startsWith("/") ? action.path : `/${action.path}`;
|
|
3897
3273
|
const connEnv = `ONE_${platformEnvSegment(platform)}_CONNECTION_KEY`;
|
|
3898
3274
|
const customNote = tags.includes("custom") ? CUSTOM_ACTION_NOTE : "";
|
|
3899
3275
|
return `### ${actionHeading(action)}
|
|
@@ -3902,7 +3278,7 @@ function codeGuideAction(action, knowledge, platform, tags, apiBase) {
|
|
|
3902
3278
|
${knowledge ?? NO_KNOWLEDGE}
|
|
3903
3279
|
|
|
3904
3280
|
## Calling this action from code
|
|
3905
|
-
URL: ${base}/passthrough${
|
|
3281
|
+
URL: ${base}/passthrough${path13}
|
|
3906
3282
|
Method: ${method}
|
|
3907
3283
|
Headers:
|
|
3908
3284
|
- x-one-secret: the value of the ONE_SECRET env var
|
|
@@ -3913,7 +3289,7 @@ Headers:
|
|
|
3913
3289
|
Environment variables: ONE_SECRET (their One API key) and ${connEnv} (the key of their ${platform} connection), both from the One dashboard.
|
|
3914
3290
|
|
|
3915
3291
|
\`\`\`typescript
|
|
3916
|
-
const response = await fetch("${base}/passthrough${
|
|
3292
|
+
const response = await fetch("${base}/passthrough${path13}", {
|
|
3917
3293
|
method: "${method}",
|
|
3918
3294
|
headers: {
|
|
3919
3295
|
"x-one-secret": process.env.ONE_SECRET,
|
|
@@ -4044,7 +3420,7 @@ function failure(error2) {
|
|
|
4044
3420
|
return error2 instanceof Error ? error2.message : "Unknown error";
|
|
4045
3421
|
}
|
|
4046
3422
|
async function actionsFindCommand(pairs, options) {
|
|
4047
|
-
intro(
|
|
3423
|
+
intro(pc7.bgCyan(pc7.black(" One ")));
|
|
4048
3424
|
if (options.type !== void 0 && options.type !== "execute" && options.type !== "knowledge") {
|
|
4049
3425
|
error("--type must be execute or knowledge.");
|
|
4050
3426
|
}
|
|
@@ -4102,7 +3478,7 @@ async function actionsLoadCommand(actionIds, options) {
|
|
|
4102
3478
|
);
|
|
4103
3479
|
return;
|
|
4104
3480
|
}
|
|
4105
|
-
intro(
|
|
3481
|
+
intro(pc7.bgCyan(pc7.black(" One ")));
|
|
4106
3482
|
const { apiKey, permissions, connectionKeys, actionIds: allowed, knowledgeAgent } = getConfig();
|
|
4107
3483
|
const api = new OneApi(apiKey, getApiBase());
|
|
4108
3484
|
const settings = { knowledgeAgent, permissions, actionIds: allowed, connectionKeys, apiBase: getApiBase() };
|
|
@@ -4124,7 +3500,7 @@ async function actionsLoadCommand(actionIds, options) {
|
|
|
4124
3500
|
}
|
|
4125
3501
|
}
|
|
4126
3502
|
async function actionsExecuteCommand(platform, actionId, connectionKey, options) {
|
|
4127
|
-
intro(
|
|
3503
|
+
intro(pc7.bgCyan(pc7.black(" One ")));
|
|
4128
3504
|
const { apiKey, permissions, actionIds, connectionKeys, knowledgeAgent } = getConfig();
|
|
4129
3505
|
if (knowledgeAgent) {
|
|
4130
3506
|
error(
|
|
@@ -4149,7 +3525,7 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
|
|
|
4149
3525
|
);
|
|
4150
3526
|
}
|
|
4151
3527
|
spinner.stop(
|
|
4152
|
-
`Action: ${actionDetails.title} [${actionDetails.method}]` + (preflightCacheHit ?
|
|
3528
|
+
`Action: ${actionDetails.title} [${actionDetails.method}]` + (preflightCacheHit ? pc7.dim(" (cached)") : "")
|
|
4153
3529
|
);
|
|
4154
3530
|
const data = options.data ? parseJsonArg2(options.data, "--data") : void 0;
|
|
4155
3531
|
const pathVariables = options.pathVars ? parseJsonArg2(options.pathVars, "--path-vars") : void 0;
|
|
@@ -4169,9 +3545,9 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
|
|
|
4169
3545
|
}
|
|
4170
3546
|
console.log();
|
|
4171
3547
|
for (const m of validation.missing) {
|
|
4172
|
-
console.log(
|
|
3548
|
+
console.log(pc7.red(` ${m.flag} is missing "${m.param}"`));
|
|
4173
3549
|
if (m.description) {
|
|
4174
|
-
console.log(
|
|
3550
|
+
console.log(pc7.dim(` ${m.description}`));
|
|
4175
3551
|
}
|
|
4176
3552
|
}
|
|
4177
3553
|
console.log();
|
|
@@ -4196,7 +3572,7 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
|
|
|
4196
3572
|
}
|
|
4197
3573
|
console.log();
|
|
4198
3574
|
if (mockResponse) {
|
|
4199
|
-
console.log(
|
|
3575
|
+
console.log(pc7.bold("Mock Response:"));
|
|
4200
3576
|
console.log(JSON.stringify(mockResponse, null, 2));
|
|
4201
3577
|
} else {
|
|
4202
3578
|
note("No example output available for this action", "Mock");
|
|
@@ -4237,26 +3613,26 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
|
|
|
4237
3613
|
return;
|
|
4238
3614
|
}
|
|
4239
3615
|
console.log();
|
|
4240
|
-
console.log(
|
|
3616
|
+
console.log(pc7.dim("Request:"));
|
|
4241
3617
|
console.log(
|
|
4242
|
-
|
|
3618
|
+
pc7.dim(
|
|
4243
3619
|
` ${result.requestConfig.method} ${result.requestConfig.url}`
|
|
4244
3620
|
)
|
|
4245
3621
|
);
|
|
4246
3622
|
if (options.dryRun) {
|
|
4247
3623
|
if (result.requestConfig.data) {
|
|
4248
3624
|
console.log();
|
|
4249
|
-
console.log(
|
|
4250
|
-
console.log(
|
|
3625
|
+
console.log(pc7.dim("Body:"));
|
|
3626
|
+
console.log(pc7.dim(JSON.stringify(result.requestConfig.data, null, 2)));
|
|
4251
3627
|
}
|
|
4252
3628
|
console.log();
|
|
4253
3629
|
note("Dry run \u2014 request was not sent", "Dry Run");
|
|
4254
3630
|
} else {
|
|
4255
3631
|
console.log();
|
|
4256
|
-
console.log(
|
|
3632
|
+
console.log(pc7.bold("Response:"));
|
|
4257
3633
|
const rd = result.responseData;
|
|
4258
3634
|
if (rd && typeof rd === "object" && typeof rd.text === "string" && "contentType" in rd) {
|
|
4259
|
-
if (rd.contentType) console.log(
|
|
3635
|
+
if (rd.contentType) console.log(pc7.dim(`(${rd.contentType})`));
|
|
4260
3636
|
console.log(rd.text);
|
|
4261
3637
|
} else {
|
|
4262
3638
|
console.log(JSON.stringify(result.responseData, null, 2));
|
|
@@ -4460,7 +3836,7 @@ async function actionsExecuteParallelCommand() {
|
|
|
4460
3836
|
}
|
|
4461
3837
|
console.log();
|
|
4462
3838
|
for (const e of errors) {
|
|
4463
|
-
console.log(` ${
|
|
3839
|
+
console.log(` ${pc7.red("\u2717")} Segment ${e.segment} (${e.label}):`);
|
|
4464
3840
|
for (const msg of e.messages) {
|
|
4465
3841
|
console.log(` ${msg}`);
|
|
4466
3842
|
}
|
|
@@ -4555,17 +3931,17 @@ async function actionsExecuteParallelCommand() {
|
|
|
4555
3931
|
console.log();
|
|
4556
3932
|
for (const r of results) {
|
|
4557
3933
|
const label = `${r.platform}/${r.actionId}`;
|
|
4558
|
-
const time =
|
|
3934
|
+
const time = pc7.dim(`(${(r.durationMs / 1e3).toFixed(2)}s)`);
|
|
4559
3935
|
if (r.mock) {
|
|
4560
|
-
console.log(` [${r.segment}/${total}] ${label} ${
|
|
4561
|
-
if (r.response) console.log(` ${
|
|
3936
|
+
console.log(` [${r.segment}/${total}] ${label} ${pc7.cyan("\u25C7 mock")} ${time}`);
|
|
3937
|
+
if (r.response) console.log(` ${pc7.dim(JSON.stringify(r.response, null, 2).split("\n").join("\n "))}`);
|
|
4562
3938
|
} else if (r.dryRun) {
|
|
4563
|
-
console.log(` [${r.segment}/${total}] ${label} ${
|
|
3939
|
+
console.log(` [${r.segment}/${total}] ${label} ${pc7.yellow("\u2298 dry-run")} ${time}`);
|
|
4564
3940
|
} else if (r.status === "success") {
|
|
4565
|
-
console.log(` [${r.segment}/${total}] ${label} ${
|
|
4566
|
-
if (r.response) console.log(` ${
|
|
3941
|
+
console.log(` [${r.segment}/${total}] ${label} ${pc7.green("\u2713")} ${time}`);
|
|
3942
|
+
if (r.response) console.log(` ${pc7.dim(JSON.stringify(r.response, null, 2).split("\n").join("\n "))}`);
|
|
4567
3943
|
} else {
|
|
4568
|
-
console.log(` [${r.segment}/${total}] ${label} ${
|
|
3944
|
+
console.log(` [${r.segment}/${total}] ${label} ${pc7.red("\u2717")} ${time} \u2014 ${r.error}`);
|
|
4569
3945
|
}
|
|
4570
3946
|
}
|
|
4571
3947
|
console.log();
|
|
@@ -4579,11 +3955,11 @@ async function actionsExecuteParallelCommand() {
|
|
|
4579
3955
|
}
|
|
4580
3956
|
|
|
4581
3957
|
// src/commands/flow.ts
|
|
4582
|
-
import
|
|
3958
|
+
import pc8 from "picocolors";
|
|
4583
3959
|
|
|
4584
3960
|
// src/lib/flow-validator.ts
|
|
4585
|
-
import
|
|
4586
|
-
import
|
|
3961
|
+
import fs3 from "fs";
|
|
3962
|
+
import path3 from "path";
|
|
4587
3963
|
import { spawnSync } from "child_process";
|
|
4588
3964
|
function validateFlowSchema(flow2) {
|
|
4589
3965
|
const errors = [];
|
|
@@ -4658,32 +4034,32 @@ function validateStepsArray(steps, pathPrefix, errors) {
|
|
|
4658
4034
|
const validTypes = FLOW_SCHEMA.stepTypes.map((st) => st.type);
|
|
4659
4035
|
for (let i = 0; i < steps.length; i++) {
|
|
4660
4036
|
const step = steps[i];
|
|
4661
|
-
const
|
|
4037
|
+
const path13 = `${pathPrefix}[${i}]`;
|
|
4662
4038
|
if (!step || typeof step !== "object" || Array.isArray(step)) {
|
|
4663
|
-
errors.push({ path:
|
|
4039
|
+
errors.push({ path: path13, message: "Step must be an object" });
|
|
4664
4040
|
continue;
|
|
4665
4041
|
}
|
|
4666
4042
|
const s = step;
|
|
4667
4043
|
if (!s.id || typeof s.id !== "string") {
|
|
4668
|
-
errors.push({ path: `${
|
|
4044
|
+
errors.push({ path: `${path13}.id`, message: 'Step must have a string "id"' });
|
|
4669
4045
|
}
|
|
4670
4046
|
if (!s.name || typeof s.name !== "string") {
|
|
4671
|
-
errors.push({ path: `${
|
|
4047
|
+
errors.push({ path: `${path13}.name`, message: 'Step must have a string "name"' });
|
|
4672
4048
|
}
|
|
4673
4049
|
if (!s.type || !validTypes.includes(s.type)) {
|
|
4674
|
-
errors.push({ path: `${
|
|
4050
|
+
errors.push({ path: `${path13}.type`, message: `Step type must be one of: ${validTypes.join(", ")}` });
|
|
4675
4051
|
continue;
|
|
4676
4052
|
}
|
|
4677
4053
|
if (s.requires !== void 0) {
|
|
4678
4054
|
if (!Array.isArray(s.requires)) {
|
|
4679
|
-
errors.push({ path: `${
|
|
4055
|
+
errors.push({ path: `${path13}.requires`, message: '"requires" must be an array of selector strings (e.g. ["$.steps.foo.output.bar"])' });
|
|
4680
4056
|
} else {
|
|
4681
4057
|
for (let r = 0; r < s.requires.length; r++) {
|
|
4682
4058
|
const sel = s.requires[r];
|
|
4683
4059
|
if (typeof sel !== "string") {
|
|
4684
|
-
errors.push({ path: `${
|
|
4060
|
+
errors.push({ path: `${path13}.requires[${r}]`, message: '"requires" entry must be a selector string' });
|
|
4685
4061
|
} else if (!sel.startsWith("$.")) {
|
|
4686
|
-
errors.push({ path: `${
|
|
4062
|
+
errors.push({ path: `${path13}.requires[${r}]`, message: `"requires" entry "${sel}" must be a selector starting with "$." (e.g. "$.steps.foo.output.bar")` });
|
|
4687
4063
|
}
|
|
4688
4064
|
}
|
|
4689
4065
|
}
|
|
@@ -4691,7 +4067,7 @@ function validateStepsArray(steps, pathPrefix, errors) {
|
|
|
4691
4067
|
if (s.onError && typeof s.onError === "object") {
|
|
4692
4068
|
const oe = s.onError;
|
|
4693
4069
|
if (!FLOW_SCHEMA.errorStrategies.includes(oe.strategy)) {
|
|
4694
|
-
errors.push({ path: `${
|
|
4070
|
+
errors.push({ path: `${path13}.onError.strategy`, message: `Error strategy must be one of: ${FLOW_SCHEMA.errorStrategies.join(", ")}` });
|
|
4695
4071
|
}
|
|
4696
4072
|
}
|
|
4697
4073
|
const descriptor = getStepTypeDescriptor(s.type);
|
|
@@ -4701,14 +4077,14 @@ function validateStepsArray(steps, pathPrefix, errors) {
|
|
|
4701
4077
|
if (!configObj || typeof configObj !== "object") {
|
|
4702
4078
|
const hint = detectFlatConfigHint(s, descriptor);
|
|
4703
4079
|
errors.push({
|
|
4704
|
-
path: `${
|
|
4080
|
+
path: `${path13}.${configKey}`,
|
|
4705
4081
|
message: `${capitalize(descriptor.type)} step must have a "${configKey}" config object${hint}`
|
|
4706
4082
|
});
|
|
4707
4083
|
continue;
|
|
4708
4084
|
}
|
|
4709
4085
|
const config2 = configObj;
|
|
4710
4086
|
for (const [fieldName, fd] of Object.entries(descriptor.fields)) {
|
|
4711
|
-
const fieldPath = `${
|
|
4087
|
+
const fieldPath = `${path13}.${configKey}.${fieldName}`;
|
|
4712
4088
|
const value = config2[fieldName];
|
|
4713
4089
|
if (fd.required && (value === void 0 || value === null || value === "")) {
|
|
4714
4090
|
errors.push({ path: fieldPath, message: `${capitalize(descriptor.type)} must have ${fd.type === "string" ? "a string" : fd.type === "array" ? "a" : "a"} "${fieldName}"` });
|
|
@@ -4741,30 +4117,30 @@ function validateStepsArray(steps, pathPrefix, errors) {
|
|
|
4741
4117
|
}
|
|
4742
4118
|
}
|
|
4743
4119
|
if (descriptor.type === "action") {
|
|
4744
|
-
validateConnectionForm(config2, `${
|
|
4120
|
+
validateConnectionForm(config2, `${path13}.${configKey}`, errors);
|
|
4745
4121
|
}
|
|
4746
4122
|
if (descriptor.type === "code") {
|
|
4747
4123
|
const hasSource = typeof config2.source === "string" && config2.source.length > 0;
|
|
4748
4124
|
const hasModule = typeof config2.module === "string" && config2.module.length > 0;
|
|
4749
4125
|
if (!hasSource && !hasModule) {
|
|
4750
|
-
errors.push({ path: `${
|
|
4126
|
+
errors.push({ path: `${path13}.${configKey}`, message: 'Code step must define either "source" (inline JS) or "module" (path to .mjs file)' });
|
|
4751
4127
|
} else if (hasSource && hasModule) {
|
|
4752
|
-
errors.push({ path: `${
|
|
4128
|
+
errors.push({ path: `${path13}.${configKey}`, message: 'Code step cannot define both "source" and "module" \u2014 pick one' });
|
|
4753
4129
|
}
|
|
4754
4130
|
if (hasModule) {
|
|
4755
4131
|
const m = config2.module;
|
|
4756
4132
|
if (m.startsWith("/") || /^[a-zA-Z]:[\\/]/.test(m)) {
|
|
4757
|
-
errors.push({ path: `${
|
|
4133
|
+
errors.push({ path: `${path13}.${configKey}.module`, message: "Code module path must be relative to the flow folder (no absolute paths)" });
|
|
4758
4134
|
} else if (m.split(/[\\/]/).includes("..")) {
|
|
4759
|
-
errors.push({ path: `${
|
|
4135
|
+
errors.push({ path: `${path13}.${configKey}.module`, message: 'Code module path must not escape the flow folder ("..")' });
|
|
4760
4136
|
} else if (!m.endsWith(".mjs")) {
|
|
4761
|
-
errors.push({ path: `${
|
|
4137
|
+
errors.push({ path: `${path13}.${configKey}.module`, message: "Code module must be a .mjs file" });
|
|
4762
4138
|
}
|
|
4763
4139
|
}
|
|
4764
4140
|
if (hasSource) {
|
|
4765
4141
|
const syntaxError = checkCodeSourceSyntax(config2.source);
|
|
4766
4142
|
if (syntaxError) {
|
|
4767
|
-
errors.push({ path: `${
|
|
4143
|
+
errors.push({ path: `${path13}.${configKey}.source`, message: `Syntax error in code step: ${syntaxError}` });
|
|
4768
4144
|
}
|
|
4769
4145
|
}
|
|
4770
4146
|
}
|
|
@@ -4836,16 +4212,16 @@ function validateStepIds(flow2) {
|
|
|
4836
4212
|
function collectIds(steps, pathPrefix) {
|
|
4837
4213
|
for (let i = 0; i < steps.length; i++) {
|
|
4838
4214
|
const step = steps[i];
|
|
4839
|
-
const
|
|
4215
|
+
const path13 = `${pathPrefix}[${i}]`;
|
|
4840
4216
|
if (seen.has(step.id)) {
|
|
4841
|
-
errors.push({ path: `${
|
|
4217
|
+
errors.push({ path: `${path13}.id`, message: `Duplicate step ID: "${step.id}"` });
|
|
4842
4218
|
} else {
|
|
4843
4219
|
seen.add(step.id);
|
|
4844
4220
|
}
|
|
4845
4221
|
for (const { configKey, fieldName } of nestedKeys) {
|
|
4846
4222
|
const config2 = step[configKey];
|
|
4847
4223
|
if (config2 && Array.isArray(config2[fieldName])) {
|
|
4848
|
-
collectIds(config2[fieldName], `${
|
|
4224
|
+
collectIds(config2[fieldName], `${path13}.${configKey}.${fieldName}`);
|
|
4849
4225
|
}
|
|
4850
4226
|
}
|
|
4851
4227
|
}
|
|
@@ -4893,7 +4269,7 @@ function validateSelectorReferences(flow2, rootDir) {
|
|
|
4893
4269
|
}
|
|
4894
4270
|
return selectors;
|
|
4895
4271
|
}
|
|
4896
|
-
function checkSelectors(selectors,
|
|
4272
|
+
function checkSelectors(selectors, path13, precedingStepIds) {
|
|
4897
4273
|
for (const selector of selectors) {
|
|
4898
4274
|
const parts = selector.split(".");
|
|
4899
4275
|
if (parts.length < 3) continue;
|
|
@@ -4901,15 +4277,15 @@ function validateSelectorReferences(flow2, rootDir) {
|
|
|
4901
4277
|
if (root === "input") {
|
|
4902
4278
|
const inputName = parts[2];
|
|
4903
4279
|
if (!inputNames.has(inputName)) {
|
|
4904
|
-
errors.push({ path:
|
|
4280
|
+
errors.push({ path: path13, message: `Selector "${selector}" references undefined input "${inputName}"` });
|
|
4905
4281
|
}
|
|
4906
4282
|
} else if (root === "steps") {
|
|
4907
4283
|
const stepId = parts[2].replace(/[\[\]]/g, "").split(/[\[\]]/)[0];
|
|
4908
4284
|
if (!allStepIds.has(stepId)) {
|
|
4909
|
-
errors.push({ path:
|
|
4285
|
+
errors.push({ path: path13, message: `Selector "${selector}" references undefined step "${stepId}"` });
|
|
4910
4286
|
} else if (precedingStepIds && !precedingStepIds.has(stepId)) {
|
|
4911
4287
|
errors.push({
|
|
4912
|
-
path:
|
|
4288
|
+
path: path13,
|
|
4913
4289
|
message: `Selector "${selector}" references step "${stepId}" which is declared after the current step. Steps execute in declaration order, so this will always resolve to undefined at runtime \u2014 move the dependency earlier in the steps array.`
|
|
4914
4290
|
});
|
|
4915
4291
|
}
|
|
@@ -4917,20 +4293,20 @@ function validateSelectorReferences(flow2, rootDir) {
|
|
|
4917
4293
|
}
|
|
4918
4294
|
}
|
|
4919
4295
|
const EXPRESSION_FIELDS = /* @__PURE__ */ new Set(["condition.expression", "while.condition"]);
|
|
4920
|
-
function checkOperatorsInSelectorField(value,
|
|
4296
|
+
function checkOperatorsInSelectorField(value, path13) {
|
|
4921
4297
|
if (typeof value === "string" && value.startsWith("$.")) {
|
|
4922
4298
|
if (value.includes("||")) {
|
|
4923
|
-
errors.push({ path:
|
|
4299
|
+
errors.push({ path: path13, message: `Selector "${value}" contains unsupported operator "||". Selectors in data fields use dot-path resolution, not JS evaluation. Use the "default" field on the input definition instead, or use a "code" step for complex expressions.` });
|
|
4924
4300
|
} else if (value.includes("&&")) {
|
|
4925
|
-
errors.push({ path:
|
|
4301
|
+
errors.push({ path: path13, message: `Selector "${value}" contains unsupported operator "&&". Selectors in data fields use dot-path resolution, not JS evaluation. Use a "condition" step or "code" step for complex expressions.` });
|
|
4926
4302
|
}
|
|
4927
4303
|
} else if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
4928
4304
|
for (const [k, v] of Object.entries(value)) {
|
|
4929
|
-
checkOperatorsInSelectorField(v, `${
|
|
4305
|
+
checkOperatorsInSelectorField(v, `${path13}.${k}`);
|
|
4930
4306
|
}
|
|
4931
4307
|
} else if (Array.isArray(value)) {
|
|
4932
4308
|
for (let i = 0; i < value.length; i++) {
|
|
4933
|
-
checkOperatorsInSelectorField(value[i], `${
|
|
4309
|
+
checkOperatorsInSelectorField(value[i], `${path13}[${i}]`);
|
|
4934
4310
|
}
|
|
4935
4311
|
}
|
|
4936
4312
|
}
|
|
@@ -4974,10 +4350,10 @@ function validateSelectorReferences(flow2, rootDir) {
|
|
|
4974
4350
|
}
|
|
4975
4351
|
const modulePath = step.type === "code" ? c.module : void 0;
|
|
4976
4352
|
if (rootDir && typeof modulePath === "string" && modulePath.length > 0) {
|
|
4977
|
-
const abs =
|
|
4978
|
-
if (
|
|
4353
|
+
const abs = path3.resolve(rootDir, modulePath);
|
|
4354
|
+
if (fs3.existsSync(abs)) {
|
|
4979
4355
|
try {
|
|
4980
|
-
const moduleText =
|
|
4356
|
+
const moduleText = fs3.readFileSync(abs, "utf-8");
|
|
4981
4357
|
checkSelectors(extractSelectors(moduleText), `${pathPrefix}.${descriptor.configKey}.module`, preceding2);
|
|
4982
4358
|
} catch {
|
|
4983
4359
|
}
|
|
@@ -5015,10 +4391,10 @@ var VALID_OUTPUT_SCHEMA_TYPES = /* @__PURE__ */ new Set(["string", "number", "bo
|
|
|
5015
4391
|
function isOutputSchemaObject(v) {
|
|
5016
4392
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
5017
4393
|
}
|
|
5018
|
-
function walkOutputSchema(schema,
|
|
4394
|
+
function walkOutputSchema(schema, path13) {
|
|
5019
4395
|
let current = schema;
|
|
5020
|
-
for (let i = 0; i <
|
|
5021
|
-
const seg =
|
|
4396
|
+
for (let i = 0; i < path13.length; i++) {
|
|
4397
|
+
const seg = path13[i];
|
|
5022
4398
|
if (typeof current === "string") {
|
|
5023
4399
|
return current === "unknown" || current === "object" || current === "array" ? "opaque" : "opaque";
|
|
5024
4400
|
}
|
|
@@ -5170,8 +4546,8 @@ function validateCodeModules(flow2, rootDir) {
|
|
|
5170
4546
|
const stepPath = `${pathPrefix}[${i}]`;
|
|
5171
4547
|
if (step.type === "code" && step.code?.module) {
|
|
5172
4548
|
const m = step.code.module;
|
|
5173
|
-
const abs =
|
|
5174
|
-
if (!
|
|
4549
|
+
const abs = path3.resolve(rootDir, m);
|
|
4550
|
+
if (!fs3.existsSync(abs)) {
|
|
5175
4551
|
errors.push({
|
|
5176
4552
|
path: `${stepPath}.code.module`,
|
|
5177
4553
|
message: `Code module "${m}" not found at ${abs}`
|
|
@@ -5302,11 +4678,11 @@ function validateFileReadSchemas(flow2) {
|
|
|
5302
4678
|
}
|
|
5303
4679
|
|
|
5304
4680
|
// src/commands/flow.ts
|
|
5305
|
-
import
|
|
5306
|
-
import
|
|
4681
|
+
import fs4 from "fs";
|
|
4682
|
+
import path4 from "path";
|
|
5307
4683
|
async function writeFlowResultFile(filePath, meta, steps) {
|
|
5308
|
-
const abs =
|
|
5309
|
-
const ws =
|
|
4684
|
+
const abs = path4.resolve(filePath);
|
|
4685
|
+
const ws = fs4.createWriteStream(abs);
|
|
5310
4686
|
const done = new Promise((resolve, reject) => {
|
|
5311
4687
|
ws.on("finish", () => resolve());
|
|
5312
4688
|
ws.on("error", reject);
|
|
@@ -5337,25 +4713,25 @@ function previewValue(value, max = 120) {
|
|
|
5337
4713
|
}
|
|
5338
4714
|
function renderDryRef(ref2) {
|
|
5339
4715
|
if (ref2.status === "resolved") {
|
|
5340
|
-
return `${
|
|
4716
|
+
return `${pc8.green("\u2713")} ${ref2.selector} ${pc8.dim("\u2192")} ${previewValue(ref2.value)}`;
|
|
5341
4717
|
}
|
|
5342
4718
|
if (ref2.status === "deferred") {
|
|
5343
|
-
return `${
|
|
4719
|
+
return `${pc8.dim("\u25CB")} ${ref2.selector} ${pc8.dim("\u2192 pending (produced by a later step)")}`;
|
|
5344
4720
|
}
|
|
5345
|
-
return `${
|
|
4721
|
+
return `${pc8.yellow("!")} ${ref2.selector} ${pc8.yellow("\u2192 unresolved \u2014 check the input/env name")}`;
|
|
5346
4722
|
}
|
|
5347
4723
|
function renderDryResolution(steps) {
|
|
5348
4724
|
const isExpr = (t) => t === "transform" || t === "condition" || t === "while";
|
|
5349
4725
|
for (const s of steps) {
|
|
5350
|
-
const label = s.name ? `${s.stepId} ${
|
|
5351
|
-
console.log(` ${
|
|
4726
|
+
const label = s.name ? `${s.stepId} ${pc8.dim(`"${s.name}"`)}` : s.stepId;
|
|
4727
|
+
console.log(` ${pc8.cyan("\u25B8")} ${label} ${pc8.dim(`(${s.type})`)}`);
|
|
5352
4728
|
if (s.error !== void 0) {
|
|
5353
|
-
console.log(` ${
|
|
4729
|
+
console.log(` ${pc8.red("error")} ${s.error}`);
|
|
5354
4730
|
} else if (isExpr(s.type) && s.deferred) {
|
|
5355
4731
|
const deps = s.references.map((r) => r.selector).join(", ");
|
|
5356
|
-
console.log(` ${
|
|
4732
|
+
console.log(` ${pc8.dim("\u25CB pending \u2014 depends on")} ${deps} ${pc8.dim("(produced by a later step)")}`);
|
|
5357
4733
|
} else if (isExpr(s.type)) {
|
|
5358
|
-
console.log(` ${
|
|
4734
|
+
console.log(` ${pc8.dim("=")} ${previewValue(s.resolved)}`);
|
|
5359
4735
|
}
|
|
5360
4736
|
if (!(isExpr(s.type) && s.deferred)) {
|
|
5361
4737
|
for (const ref2 of s.references) {
|
|
@@ -5363,7 +4739,7 @@ function renderDryResolution(steps) {
|
|
|
5363
4739
|
}
|
|
5364
4740
|
}
|
|
5365
4741
|
if (!isExpr(s.type) && s.references.length === 0 && s.error === void 0) {
|
|
5366
|
-
console.log(` ${
|
|
4742
|
+
console.log(` ${pc8.dim("(no interpolations)")}`);
|
|
5367
4743
|
}
|
|
5368
4744
|
}
|
|
5369
4745
|
}
|
|
@@ -5417,14 +4793,14 @@ async function autoResolveConnectionInputs(flow2, inputs, api) {
|
|
|
5417
4793
|
return resolved;
|
|
5418
4794
|
}
|
|
5419
4795
|
async function flowCreateCommand(key, options) {
|
|
5420
|
-
intro(
|
|
4796
|
+
intro(pc8.bgCyan(pc8.black(" One Workflow ")));
|
|
5421
4797
|
let flow2;
|
|
5422
4798
|
if (options.definition) {
|
|
5423
4799
|
let raw = options.definition;
|
|
5424
4800
|
if (raw.startsWith("@")) {
|
|
5425
4801
|
const filePath = raw.slice(1);
|
|
5426
4802
|
try {
|
|
5427
|
-
raw =
|
|
4803
|
+
raw = fs4.readFileSync(filePath, "utf-8");
|
|
5428
4804
|
} catch (err) {
|
|
5429
4805
|
error(`Cannot read file "${filePath}": ${err.message}`);
|
|
5430
4806
|
}
|
|
@@ -5473,11 +4849,11 @@ ${errors.map((e) => ` ${e.path}: ${e.message}`).join("\n")}`);
|
|
|
5473
4849
|
return;
|
|
5474
4850
|
}
|
|
5475
4851
|
note(`Workflow "${flow2.name}" saved to ${flowPath}`, "Created");
|
|
5476
|
-
outro(`Validate: ${
|
|
5477
|
-
Execute: ${
|
|
4852
|
+
outro(`Validate: ${pc8.cyan(`one flow validate ${flow2.key}`)}
|
|
4853
|
+
Execute: ${pc8.cyan(`one flow execute ${flow2.key}`)}`);
|
|
5478
4854
|
}
|
|
5479
4855
|
async function flowExecuteCommand(keyOrPath, options) {
|
|
5480
|
-
intro(
|
|
4856
|
+
intro(pc8.bgCyan(pc8.black(" One Workflow ")));
|
|
5481
4857
|
const { apiKey, permissions, actionIds } = getConfig2();
|
|
5482
4858
|
const api = new OneApi(apiKey, getApiBase());
|
|
5483
4859
|
const spinner = createSpinner();
|
|
@@ -5510,7 +4886,7 @@ ${preflightErrors.map((e) => ` ${e.path}: ${e.message}`).join("\n")}`);
|
|
|
5510
4886
|
if (isAgentMode()) {
|
|
5511
4887
|
json({ event: "flow:deprecation", flowKey: flow2.key, warning: msg });
|
|
5512
4888
|
} else {
|
|
5513
|
-
console.error(
|
|
4889
|
+
console.error(pc8.yellow(`\u26A0 ${msg}`));
|
|
5514
4890
|
}
|
|
5515
4891
|
}
|
|
5516
4892
|
if (!options.allowBash && flowRequiresBash(flow2)) {
|
|
@@ -5544,7 +4920,7 @@ ${preflightErrors.map((e) => ` ${e.path}: ${e.message}`).join("\n")}`);
|
|
|
5544
4920
|
runner.requestPause();
|
|
5545
4921
|
if (!isAgentMode()) {
|
|
5546
4922
|
console.log(`
|
|
5547
|
-
${
|
|
4923
|
+
${pc8.yellow("Pausing after current step completes...")} (run ID: ${runId})`);
|
|
5548
4924
|
}
|
|
5549
4925
|
};
|
|
5550
4926
|
process.on("SIGINT", sigintHandler);
|
|
@@ -5564,12 +4940,12 @@ ${pc9.yellow("Pausing after current step completes...")} (run ID: ${runId})`);
|
|
|
5564
4940
|
} else if (options.verbose) {
|
|
5565
4941
|
const ts = (/* @__PURE__ */ new Date()).toISOString().split("T")[1].slice(0, 8);
|
|
5566
4942
|
if (event.event === "step:start") {
|
|
5567
|
-
console.log(` ${
|
|
4943
|
+
console.log(` ${pc8.dim(ts)} ${pc8.cyan("\u25B6")} ${event.stepName} ${pc8.dim(`(${event.type})`)}`);
|
|
5568
4944
|
} else if (event.event === "step:complete") {
|
|
5569
|
-
const status2 = event.status === "success" ?
|
|
5570
|
-
console.log(` ${
|
|
4945
|
+
const status2 = event.status === "success" ? pc8.green("\u2713") : event.status === "skipped" ? pc8.dim("\u25CB") : pc8.red("\u2717");
|
|
4946
|
+
console.log(` ${pc8.dim(ts)} ${status2} ${event.stepId} ${pc8.dim(`${event.durationMs}ms`)}`);
|
|
5571
4947
|
} else if (event.event === "step:error") {
|
|
5572
|
-
console.log(` ${
|
|
4948
|
+
console.log(` ${pc8.dim(ts)} ${pc8.red("\u2717")} ${event.stepId}: ${event.error}`);
|
|
5573
4949
|
}
|
|
5574
4950
|
}
|
|
5575
4951
|
};
|
|
@@ -5618,8 +4994,8 @@ ${pc9.yellow("Pausing after current step completes...")} (run ID: ${runId})`);
|
|
|
5618
4994
|
console.log();
|
|
5619
4995
|
const missing = dryRunSteps.reduce((n, s) => n + s.references.filter((r) => r.status === "missing").length, 0);
|
|
5620
4996
|
note(
|
|
5621
|
-
`Dry run \u2014 no steps executed. Resolved ${dryRunSteps.length} step(s)` + (missing > 0 ? `; ${
|
|
5622
|
-
${
|
|
4997
|
+
`Dry run \u2014 no steps executed. Resolved ${dryRunSteps.length} step(s)` + (missing > 0 ? `; ${pc8.yellow(`${missing} unresolved input/env reference(s)`)}` : "") + `.
|
|
4998
|
+
${pc8.dim("$.steps.* refs resolve at runtime \u2014 re-run with --stop-after=<stepId> to resolve them against real output.")}`,
|
|
5623
4999
|
"Dry Run"
|
|
5624
5000
|
);
|
|
5625
5001
|
return;
|
|
@@ -5629,17 +5005,17 @@ ${pc9.dim("$.steps.* refs resolve at runtime \u2014 re-run with --stop-after=<st
|
|
|
5629
5005
|
const failed = stepEntries.filter(([, r]) => r.status === "failed").length;
|
|
5630
5006
|
const skipped = stepEntries.filter(([, r]) => r.status === "skipped").length;
|
|
5631
5007
|
console.log();
|
|
5632
|
-
console.log(` ${
|
|
5633
|
-
console.log(` ${
|
|
5634
|
-
console.log(` ${
|
|
5008
|
+
console.log(` ${pc8.green("\u2713")} ${succeeded} succeeded ${failed > 0 ? pc8.red(`\u2717 ${failed} failed`) : ""} ${skipped > 0 ? pc8.dim(`\u25CB ${skipped} skipped`) : ""}`);
|
|
5009
|
+
console.log(` ${pc8.dim(`Run ID: ${runId}`)}`);
|
|
5010
|
+
console.log(` ${pc8.dim(`Log: ${logPath}`)}`);
|
|
5635
5011
|
if (dryResolveTarget) {
|
|
5636
5012
|
console.log();
|
|
5637
|
-
console.log(` ${
|
|
5013
|
+
console.log(` ${pc8.dim(`Resolved (not executed) "${dryResolveTarget.stepId}":`)}`);
|
|
5638
5014
|
renderDryResolution([dryResolveTarget]);
|
|
5639
5015
|
}
|
|
5640
5016
|
if (stoppedAfter) {
|
|
5641
5017
|
note(
|
|
5642
|
-
`Stopped after step "${stoppedAfter}". Inspect step outputs with: ${
|
|
5018
|
+
`Stopped after step "${stoppedAfter}". Inspect step outputs with: ${pc8.cyan(`one flow inspect ${runId}`)}`,
|
|
5643
5019
|
"Stopped"
|
|
5644
5020
|
);
|
|
5645
5021
|
} else if (options.dryRun) {
|
|
@@ -5661,13 +5037,13 @@ ${pc9.dim("$.steps.* refs resolve at runtime \u2014 re-run with --stop-after=<st
|
|
|
5661
5037
|
});
|
|
5662
5038
|
process.exit(1);
|
|
5663
5039
|
}
|
|
5664
|
-
console.log(` ${
|
|
5665
|
-
console.log(` ${
|
|
5040
|
+
console.log(` ${pc8.dim(`Run ID: ${runId}`)}`);
|
|
5041
|
+
console.log(` ${pc8.dim(`Log: ${logPath}`)}`);
|
|
5666
5042
|
error(`Workflow failed: ${errorMsg}`);
|
|
5667
5043
|
}
|
|
5668
5044
|
}
|
|
5669
5045
|
async function flowListCommand() {
|
|
5670
|
-
intro(
|
|
5046
|
+
intro(pc8.bgCyan(pc8.black(" One Workflow ")));
|
|
5671
5047
|
const flows = listFlows();
|
|
5672
5048
|
if (isAgentMode()) {
|
|
5673
5049
|
json({ workflows: flows });
|
|
@@ -5699,7 +5075,7 @@ async function flowListCommand() {
|
|
|
5699
5075
|
console.log();
|
|
5700
5076
|
}
|
|
5701
5077
|
async function flowValidateCommand(keyOrPath) {
|
|
5702
|
-
intro(
|
|
5078
|
+
intro(pc8.bgCyan(pc8.black(" One Workflow ")));
|
|
5703
5079
|
const spinner = createSpinner();
|
|
5704
5080
|
spinner.start(`Validating "${keyOrPath}"...`);
|
|
5705
5081
|
let flowData;
|
|
@@ -5711,9 +5087,9 @@ async function flowValidateCommand(keyOrPath) {
|
|
|
5711
5087
|
rootDir = loaded.rootDir;
|
|
5712
5088
|
} catch {
|
|
5713
5089
|
const flowPath = resolveFlowPath(keyOrPath);
|
|
5714
|
-
const content =
|
|
5090
|
+
const content = fs4.readFileSync(flowPath, "utf-8");
|
|
5715
5091
|
flowData = JSON.parse(content);
|
|
5716
|
-
rootDir =
|
|
5092
|
+
rootDir = path4.dirname(flowPath);
|
|
5717
5093
|
}
|
|
5718
5094
|
} catch (err) {
|
|
5719
5095
|
spinner.stop("Validation failed");
|
|
@@ -5728,7 +5104,7 @@ async function flowValidateCommand(keyOrPath) {
|
|
|
5728
5104
|
}
|
|
5729
5105
|
console.log();
|
|
5730
5106
|
for (const e of errors) {
|
|
5731
|
-
console.log(` ${
|
|
5107
|
+
console.log(` ${pc8.red("\u2717")} ${pc8.dim(e.path)}: ${e.message}`);
|
|
5732
5108
|
}
|
|
5733
5109
|
console.log();
|
|
5734
5110
|
error(`${errors.length} validation error(s) found`);
|
|
@@ -5741,7 +5117,7 @@ async function flowValidateCommand(keyOrPath) {
|
|
|
5741
5117
|
note(`Workflow "${flowData.key}" passed all validation checks`, "Valid");
|
|
5742
5118
|
}
|
|
5743
5119
|
async function flowResumeCommand(runId, options = {}) {
|
|
5744
|
-
intro(
|
|
5120
|
+
intro(pc8.bgCyan(pc8.black(" One Workflow ")));
|
|
5745
5121
|
const state = FlowRunner.loadRunState(runId);
|
|
5746
5122
|
if (!state) {
|
|
5747
5123
|
error(`Run "${runId}" not found`);
|
|
@@ -5794,8 +5170,8 @@ async function flowResumeCommand(runId, options = {}) {
|
|
|
5794
5170
|
});
|
|
5795
5171
|
return;
|
|
5796
5172
|
}
|
|
5797
|
-
console.log(` ${
|
|
5798
|
-
console.log(` ${
|
|
5173
|
+
console.log(` ${pc8.green("\u2713")} Resumed and completed successfully`);
|
|
5174
|
+
console.log(` ${pc8.dim(`Log: ${runner.getLogPath()}`)}`);
|
|
5799
5175
|
} catch (error2) {
|
|
5800
5176
|
spinner.stop("Resume failed");
|
|
5801
5177
|
const errorMsg = error2 instanceof Error ? error2.message : String(error2);
|
|
@@ -5807,7 +5183,7 @@ async function flowResumeCommand(runId, options = {}) {
|
|
|
5807
5183
|
}
|
|
5808
5184
|
}
|
|
5809
5185
|
async function flowRunsCommand(flowKey) {
|
|
5810
|
-
intro(
|
|
5186
|
+
intro(pc8.bgCyan(pc8.black(" One Workflow ")));
|
|
5811
5187
|
const runs = FlowRunner.listRuns(flowKey);
|
|
5812
5188
|
if (isAgentMode()) {
|
|
5813
5189
|
json({
|
|
@@ -5847,7 +5223,7 @@ async function flowRunsCommand(flowKey) {
|
|
|
5847
5223
|
console.log();
|
|
5848
5224
|
}
|
|
5849
5225
|
async function flowInspectCommand(runId, options = {}) {
|
|
5850
|
-
intro(
|
|
5226
|
+
intro(pc8.bgCyan(pc8.black(" One Workflow ")));
|
|
5851
5227
|
const state = FlowRunner.loadRunState(runId);
|
|
5852
5228
|
if (!state) {
|
|
5853
5229
|
const msg = `No run found for id "${runId}". List runs with: one flow runs`;
|
|
@@ -5876,44 +5252,44 @@ async function flowInspectCommand(runId, options = {}) {
|
|
|
5876
5252
|
return;
|
|
5877
5253
|
}
|
|
5878
5254
|
console.log();
|
|
5879
|
-
console.log(` ${
|
|
5880
|
-
console.log(` ${
|
|
5881
|
-
if (state.currentStepId) console.log(` ${
|
|
5255
|
+
console.log(` ${pc8.bold(state.flowKey)} ${pc8.dim(`run ${state.runId}`)} ${colorStatus(state.status)}`);
|
|
5256
|
+
console.log(` ${pc8.dim(`Started: ${state.startedAt}${state.completedAt ? ` \xB7 Ended: ${state.completedAt}` : ""}`)}`);
|
|
5257
|
+
if (state.currentStepId) console.log(` ${pc8.dim(`Current step: ${state.currentStepId}`)}`);
|
|
5882
5258
|
console.log();
|
|
5883
5259
|
if (stepEntries.length === 0) {
|
|
5884
5260
|
note("No step outputs recorded yet for this run.", "Steps");
|
|
5885
5261
|
} else {
|
|
5886
5262
|
for (const [id, result] of stepEntries) {
|
|
5887
|
-
const icon = result.status === "success" ?
|
|
5888
|
-
const dur = result.durationMs !== void 0 ?
|
|
5889
|
-
const retries = result.retries ?
|
|
5890
|
-
console.log(` ${icon} ${id} ${
|
|
5263
|
+
const icon = result.status === "success" ? pc8.green("\u2713") : result.status === "skipped" ? pc8.dim("\u25CB") : result.status === "timeout" ? pc8.yellow("\u29D6") : pc8.red("\u2717");
|
|
5264
|
+
const dur = result.durationMs !== void 0 ? pc8.dim(` ${result.durationMs}ms`) : "";
|
|
5265
|
+
const retries = result.retries ? pc8.dim(` (${result.retries} retr${result.retries === 1 ? "y" : "ies"})`) : "";
|
|
5266
|
+
console.log(` ${icon} ${id} ${pc8.dim(`[${result.status}]`)}${dur}${retries}`);
|
|
5891
5267
|
if (result.error) {
|
|
5892
|
-
console.log(` ${
|
|
5268
|
+
console.log(` ${pc8.red("error")} ${result.error}${result.errorCode ? pc8.dim(` (${result.errorCode})`) : ""}`);
|
|
5893
5269
|
}
|
|
5894
5270
|
if (result.output !== void 0) {
|
|
5895
5271
|
const json2 = JSON.stringify(result.output, null, options.full ? 2 : 0) ?? String(result.output);
|
|
5896
|
-
const shown = options.full || json2.length <= 240 ? json2 : `${json2.slice(0, 239)}\u2026 ${
|
|
5897
|
-
const indented = options.full ? shown.split("\n").map((l) => ` ${l}`).join("\n") : ` ${
|
|
5272
|
+
const shown = options.full || json2.length <= 240 ? json2 : `${json2.slice(0, 239)}\u2026 ${pc8.dim("(--full for all)")}`;
|
|
5273
|
+
const indented = options.full ? shown.split("\n").map((l) => ` ${l}`).join("\n") : ` ${pc8.dim("output")} ${shown}`;
|
|
5898
5274
|
console.log(indented);
|
|
5899
5275
|
}
|
|
5900
5276
|
}
|
|
5901
5277
|
}
|
|
5902
5278
|
console.log();
|
|
5903
|
-
console.log(` ${
|
|
5904
|
-
console.log(` ${
|
|
5279
|
+
console.log(` ${pc8.dim(`State: ${statePath}`)}`);
|
|
5280
|
+
console.log(` ${pc8.dim(`Log: ${path4.join(".one/flows/.logs", `${state.flowKey}-${state.runId}.log`)}`)}`);
|
|
5905
5281
|
console.log();
|
|
5906
5282
|
}
|
|
5907
5283
|
function colorStatus(status2) {
|
|
5908
5284
|
switch (status2) {
|
|
5909
5285
|
case "completed":
|
|
5910
|
-
return
|
|
5286
|
+
return pc8.green(status2);
|
|
5911
5287
|
case "running":
|
|
5912
|
-
return
|
|
5288
|
+
return pc8.cyan(status2);
|
|
5913
5289
|
case "paused":
|
|
5914
|
-
return
|
|
5290
|
+
return pc8.yellow(status2);
|
|
5915
5291
|
case "failed":
|
|
5916
|
-
return
|
|
5292
|
+
return pc8.red(status2);
|
|
5917
5293
|
default:
|
|
5918
5294
|
return status2;
|
|
5919
5295
|
}
|
|
@@ -6091,7 +5467,7 @@ async function flowScaffoldCommand(template) {
|
|
|
6091
5467
|
}
|
|
6092
5468
|
|
|
6093
5469
|
// src/commands/relay.ts
|
|
6094
|
-
import
|
|
5470
|
+
import pc9 from "picocolors";
|
|
6095
5471
|
function getConfig3() {
|
|
6096
5472
|
const apiKey = getApiKey();
|
|
6097
5473
|
if (!apiKey) {
|
|
@@ -6132,15 +5508,15 @@ async function relayCreateCommand(options) {
|
|
|
6132
5508
|
}
|
|
6133
5509
|
spinner.stop("Relay endpoint created");
|
|
6134
5510
|
console.log();
|
|
6135
|
-
console.log(` ${
|
|
6136
|
-
console.log(` ${
|
|
6137
|
-
console.log(` ${
|
|
6138
|
-
if (result.description) console.log(` ${
|
|
6139
|
-
if (result.eventFilters?.length) console.log(` ${
|
|
6140
|
-
if (result.webhookPayload?.id) console.log(` ${
|
|
5511
|
+
console.log(` ${pc9.dim("ID:")} ${result.id}`);
|
|
5512
|
+
console.log(` ${pc9.dim("URL:")} ${result.url}`);
|
|
5513
|
+
console.log(` ${pc9.dim("Active:")} ${result.active}`);
|
|
5514
|
+
if (result.description) console.log(` ${pc9.dim("Description:")} ${result.description}`);
|
|
5515
|
+
if (result.eventFilters?.length) console.log(` ${pc9.dim("Events:")} ${result.eventFilters.join(", ")}`);
|
|
5516
|
+
if (result.webhookPayload?.id) console.log(` ${pc9.dim("Webhook ID:")} ${result.webhookPayload.id}`);
|
|
6141
5517
|
if (result.warning) {
|
|
6142
5518
|
console.log();
|
|
6143
|
-
console.log(` ${
|
|
5519
|
+
console.log(` ${pc9.yellow("\u26A0 Warning:")} ${result.warning}`);
|
|
6144
5520
|
}
|
|
6145
5521
|
console.log();
|
|
6146
5522
|
} catch (error2) {
|
|
@@ -6186,12 +5562,12 @@ async function relayListCommand(options) {
|
|
|
6186
5562
|
{ key: "description", label: "Description" },
|
|
6187
5563
|
{ key: "events", label: "Events" },
|
|
6188
5564
|
{ key: "actions", label: "Actions" },
|
|
6189
|
-
{ key: "id", label: "ID", color:
|
|
5565
|
+
{ key: "id", label: "ID", color: pc9.dim }
|
|
6190
5566
|
],
|
|
6191
5567
|
endpoints.map((e) => ({
|
|
6192
|
-
status: e.active ?
|
|
6193
|
-
description: e.description ||
|
|
6194
|
-
events: e.eventFilters?.join(", ") ||
|
|
5568
|
+
status: e.active ? pc9.green("\u25CF") : pc9.dim("\u25CB"),
|
|
5569
|
+
description: e.description || pc9.dim("(none)"),
|
|
5570
|
+
events: e.eventFilters?.join(", ") || pc9.dim("all"),
|
|
6195
5571
|
actions: String(e.actions?.length || 0),
|
|
6196
5572
|
id: e.id.slice(0, 8)
|
|
6197
5573
|
}))
|
|
@@ -6214,18 +5590,18 @@ async function relayGetCommand(id) {
|
|
|
6214
5590
|
}
|
|
6215
5591
|
spinner.stop("Relay endpoint loaded");
|
|
6216
5592
|
console.log();
|
|
6217
|
-
console.log(` ${
|
|
6218
|
-
console.log(` ${
|
|
6219
|
-
console.log(` ${
|
|
6220
|
-
if (result.description) console.log(` ${
|
|
6221
|
-
if (result.eventFilters?.length) console.log(` ${
|
|
6222
|
-
console.log(` ${
|
|
5593
|
+
console.log(` ${pc9.dim("ID:")} ${result.id}`);
|
|
5594
|
+
console.log(` ${pc9.dim("URL:")} ${result.url}`);
|
|
5595
|
+
console.log(` ${pc9.dim("Active:")} ${result.active}`);
|
|
5596
|
+
if (result.description) console.log(` ${pc9.dim("Description:")} ${result.description}`);
|
|
5597
|
+
if (result.eventFilters?.length) console.log(` ${pc9.dim("Events:")} ${result.eventFilters.join(", ")}`);
|
|
5598
|
+
console.log(` ${pc9.dim("Actions:")} ${result.actions?.length || 0}`);
|
|
6223
5599
|
if (result.actions?.length) {
|
|
6224
5600
|
for (const [i, action] of result.actions.entries()) {
|
|
6225
|
-
console.log(` ${
|
|
5601
|
+
console.log(` ${pc9.dim(`[${i}]`)} type=${action.type}${action.actionId ? ` actionId=${action.actionId}` : ""}${action.url ? ` url=${action.url}` : ""}`);
|
|
6226
5602
|
}
|
|
6227
5603
|
}
|
|
6228
|
-
console.log(` ${
|
|
5604
|
+
console.log(` ${pc9.dim("Created:")} ${result.createdAt}`);
|
|
6229
5605
|
console.log();
|
|
6230
5606
|
} catch (error2) {
|
|
6231
5607
|
spinner.stop("Failed to load relay endpoint");
|
|
@@ -6250,9 +5626,9 @@ async function relayUpdateCommand(id, options) {
|
|
|
6250
5626
|
return;
|
|
6251
5627
|
}
|
|
6252
5628
|
spinner.stop("Relay endpoint updated");
|
|
6253
|
-
console.log(` ${
|
|
6254
|
-
console.log(` ${
|
|
6255
|
-
console.log(` ${
|
|
5629
|
+
console.log(` ${pc9.dim("ID:")} ${result.id}`);
|
|
5630
|
+
console.log(` ${pc9.dim("Active:")} ${result.active}`);
|
|
5631
|
+
console.log(` ${pc9.dim("Actions:")} ${result.actions?.length || 0}`);
|
|
6256
5632
|
console.log();
|
|
6257
5633
|
} catch (error2) {
|
|
6258
5634
|
spinner.stop("Failed to update relay endpoint");
|
|
@@ -6293,9 +5669,9 @@ async function relayActivateCommand(id, options) {
|
|
|
6293
5669
|
return;
|
|
6294
5670
|
}
|
|
6295
5671
|
spinner.stop("Relay endpoint activated");
|
|
6296
|
-
console.log(` ${
|
|
6297
|
-
console.log(` ${
|
|
6298
|
-
console.log(` ${
|
|
5672
|
+
console.log(` ${pc9.dim("ID:")} ${result.id}`);
|
|
5673
|
+
console.log(` ${pc9.dim("Active:")} ${result.active}`);
|
|
5674
|
+
console.log(` ${pc9.dim("Actions:")} ${result.actions?.length || 0}`);
|
|
6299
5675
|
console.log();
|
|
6300
5676
|
} catch (error2) {
|
|
6301
5677
|
spinner.stop("Failed to activate relay endpoint");
|
|
@@ -6340,11 +5716,11 @@ async function relayEventsCommand(options) {
|
|
|
6340
5716
|
{ key: "platform", label: "Platform" },
|
|
6341
5717
|
{ key: "eventType", label: "Event Type" },
|
|
6342
5718
|
{ key: "timestamp", label: "Timestamp" },
|
|
6343
|
-
{ key: "id", label: "ID", color:
|
|
5719
|
+
{ key: "id", label: "ID", color: pc9.dim }
|
|
6344
5720
|
],
|
|
6345
5721
|
events.map((e) => ({
|
|
6346
5722
|
platform: e.platform,
|
|
6347
|
-
eventType: e.eventType ||
|
|
5723
|
+
eventType: e.eventType || pc9.dim("unknown"),
|
|
6348
5724
|
timestamp: e.timestamp || e.createdAt,
|
|
6349
5725
|
id: e.id.slice(0, 8)
|
|
6350
5726
|
}))
|
|
@@ -6367,11 +5743,11 @@ async function relayEventGetCommand(id) {
|
|
|
6367
5743
|
}
|
|
6368
5744
|
spinner.stop("Relay event loaded");
|
|
6369
5745
|
console.log();
|
|
6370
|
-
console.log(` ${
|
|
6371
|
-
console.log(` ${
|
|
6372
|
-
console.log(` ${
|
|
6373
|
-
console.log(` ${
|
|
6374
|
-
console.log(` ${
|
|
5746
|
+
console.log(` ${pc9.dim("ID:")} ${result.id}`);
|
|
5747
|
+
console.log(` ${pc9.dim("Platform:")} ${result.platform}`);
|
|
5748
|
+
console.log(` ${pc9.dim("Event:")} ${result.eventType}`);
|
|
5749
|
+
console.log(` ${pc9.dim("Timestamp:")} ${result.timestamp || result.createdAt}`);
|
|
5750
|
+
console.log(` ${pc9.dim("Payload:")}`);
|
|
6375
5751
|
console.log(JSON.stringify(result.payload, null, 2));
|
|
6376
5752
|
console.log();
|
|
6377
5753
|
} catch (error2) {
|
|
@@ -6408,11 +5784,11 @@ async function relayDeliveriesCommand(options) {
|
|
|
6408
5784
|
{ key: "error", label: "Error" }
|
|
6409
5785
|
],
|
|
6410
5786
|
items.map((d) => ({
|
|
6411
|
-
status: d.status === "success" ?
|
|
6412
|
-
code: d.statusCode != null ? String(d.statusCode) :
|
|
5787
|
+
status: d.status === "success" ? pc9.green(d.status) : pc9.red(d.status),
|
|
5788
|
+
code: d.statusCode != null ? String(d.statusCode) : pc9.dim("-"),
|
|
6413
5789
|
attempt: String(d.attempt),
|
|
6414
|
-
deliveredAt: d.deliveredAt ||
|
|
6415
|
-
error: d.error ?
|
|
5790
|
+
deliveredAt: d.deliveredAt || pc9.dim("-"),
|
|
5791
|
+
error: d.error ? pc9.red(d.error.slice(0, 50)) : pc9.dim("-")
|
|
6416
5792
|
}))
|
|
6417
5793
|
);
|
|
6418
5794
|
} catch (error2) {
|
|
@@ -6440,14 +5816,14 @@ async function relayPlatformsCommand() {
|
|
|
6440
5816
|
printTable(
|
|
6441
5817
|
[
|
|
6442
5818
|
{ key: "platform", label: "Platform" },
|
|
6443
|
-
{ key: "eventTypeCount", label: "Event types", color:
|
|
5819
|
+
{ key: "eventTypeCount", label: "Event types", color: pc9.dim }
|
|
6444
5820
|
],
|
|
6445
5821
|
platforms.map((p9) => ({ platform: p9.platform, eventTypeCount: String(p9.eventTypeCount) }))
|
|
6446
5822
|
);
|
|
6447
5823
|
console.log();
|
|
6448
5824
|
console.log(
|
|
6449
|
-
|
|
6450
|
-
` Run ${
|
|
5825
|
+
pc9.dim(
|
|
5826
|
+
` Run ${pc9.cyan("one relay event-types <platform>")} to see the full event list for a platform.
|
|
6451
5827
|
`
|
|
6452
5828
|
)
|
|
6453
5829
|
);
|
|
@@ -6460,7 +5836,7 @@ async function relayEventTypesCommand(platform) {
|
|
|
6460
5836
|
const { apiKey } = getConfig3();
|
|
6461
5837
|
const api = new OneApi(apiKey, getApiBase());
|
|
6462
5838
|
const spinner = createSpinner();
|
|
6463
|
-
spinner.start(`Loading event types for ${
|
|
5839
|
+
spinner.start(`Loading event types for ${pc9.cyan(platform)}...`);
|
|
6464
5840
|
try {
|
|
6465
5841
|
const eventTypes = await api.listRelayEventTypes(platform);
|
|
6466
5842
|
if (isAgentMode()) {
|
|
@@ -6606,11 +5982,11 @@ function handleId(response, config2, records) {
|
|
|
6606
5982
|
}
|
|
6607
5983
|
|
|
6608
5984
|
// src/lib/memory/sync/state.ts
|
|
6609
|
-
import
|
|
6610
|
-
import
|
|
6611
|
-
var SYNC_DIR =
|
|
6612
|
-
var STATE_DIR =
|
|
6613
|
-
var LEGACY_SINGLE_FILE =
|
|
5985
|
+
import fs5 from "fs";
|
|
5986
|
+
import path5 from "path";
|
|
5987
|
+
var SYNC_DIR = path5.join(".one", "sync");
|
|
5988
|
+
var STATE_DIR = path5.join(SYNC_DIR, "state");
|
|
5989
|
+
var LEGACY_SINGLE_FILE = path5.join(SYNC_DIR, "sync_state.json");
|
|
6614
5990
|
var legacyMigrationDone = false;
|
|
6615
5991
|
function rowToState(row) {
|
|
6616
5992
|
return {
|
|
@@ -6638,9 +6014,9 @@ function stateToRow(platform, model, state, lastError) {
|
|
|
6638
6014
|
async function migrateLegacyOnce() {
|
|
6639
6015
|
if (legacyMigrationDone) return;
|
|
6640
6016
|
legacyMigrationDone = true;
|
|
6641
|
-
if (
|
|
6017
|
+
if (fs5.existsSync(LEGACY_SINGLE_FILE)) {
|
|
6642
6018
|
try {
|
|
6643
|
-
const raw =
|
|
6019
|
+
const raw = fs5.readFileSync(LEGACY_SINGLE_FILE, "utf-8");
|
|
6644
6020
|
const legacy = JSON.parse(raw);
|
|
6645
6021
|
const backend = await getBackend();
|
|
6646
6022
|
for (const [platform, models] of Object.entries(legacy)) {
|
|
@@ -6650,32 +6026,32 @@ async function migrateLegacyOnce() {
|
|
|
6650
6026
|
await backend.setSyncState(stateToRow(platform, model, modelState));
|
|
6651
6027
|
}
|
|
6652
6028
|
}
|
|
6653
|
-
|
|
6029
|
+
fs5.unlinkSync(LEGACY_SINGLE_FILE);
|
|
6654
6030
|
} catch {
|
|
6655
6031
|
try {
|
|
6656
|
-
|
|
6032
|
+
fs5.unlinkSync(LEGACY_SINGLE_FILE);
|
|
6657
6033
|
} catch {
|
|
6658
6034
|
}
|
|
6659
6035
|
}
|
|
6660
6036
|
}
|
|
6661
|
-
if (
|
|
6037
|
+
if (fs5.existsSync(STATE_DIR)) {
|
|
6662
6038
|
try {
|
|
6663
6039
|
const backend = await getBackend();
|
|
6664
|
-
const platforms =
|
|
6040
|
+
const platforms = fs5.readdirSync(STATE_DIR);
|
|
6665
6041
|
for (const platform of platforms) {
|
|
6666
|
-
const platformDir =
|
|
6042
|
+
const platformDir = path5.join(STATE_DIR, platform);
|
|
6667
6043
|
let entries;
|
|
6668
6044
|
try {
|
|
6669
|
-
entries =
|
|
6045
|
+
entries = fs5.readdirSync(platformDir);
|
|
6670
6046
|
} catch {
|
|
6671
6047
|
continue;
|
|
6672
6048
|
}
|
|
6673
6049
|
for (const entry of entries) {
|
|
6674
6050
|
if (!entry.endsWith(".json")) continue;
|
|
6675
6051
|
const model = entry.slice(0, -".json".length);
|
|
6676
|
-
const filePath =
|
|
6052
|
+
const filePath = path5.join(platformDir, entry);
|
|
6677
6053
|
try {
|
|
6678
|
-
const raw =
|
|
6054
|
+
const raw = fs5.readFileSync(filePath, "utf-8");
|
|
6679
6055
|
const modelState = JSON.parse(raw);
|
|
6680
6056
|
const existing = await backend.getSyncState(platform, model);
|
|
6681
6057
|
if (!existing) {
|
|
@@ -6685,7 +6061,7 @@ async function migrateLegacyOnce() {
|
|
|
6685
6061
|
}
|
|
6686
6062
|
}
|
|
6687
6063
|
}
|
|
6688
|
-
|
|
6064
|
+
fs5.rmSync(STATE_DIR, { recursive: true, force: true });
|
|
6689
6065
|
} catch {
|
|
6690
6066
|
}
|
|
6691
6067
|
}
|
|
@@ -6729,12 +6105,12 @@ async function removeModelState(platform, model) {
|
|
|
6729
6105
|
}
|
|
6730
6106
|
|
|
6731
6107
|
// src/lib/memory/sync/lock.ts
|
|
6732
|
-
import
|
|
6733
|
-
import
|
|
6734
|
-
var LOCK_DIR_REL =
|
|
6108
|
+
import fs6 from "fs";
|
|
6109
|
+
import path6 from "path";
|
|
6110
|
+
var LOCK_DIR_REL = path6.join(".one", "sync", "locks");
|
|
6735
6111
|
var STALE_MS = 30 * 60 * 1e3;
|
|
6736
6112
|
function lockPath(platform, model) {
|
|
6737
|
-
return
|
|
6113
|
+
return path6.join(LOCK_DIR_REL, `${platform}_${model}`);
|
|
6738
6114
|
}
|
|
6739
6115
|
function isProcessAlive(pid) {
|
|
6740
6116
|
try {
|
|
@@ -6751,15 +6127,15 @@ var SyncLockError = class extends Error {
|
|
|
6751
6127
|
}
|
|
6752
6128
|
};
|
|
6753
6129
|
function acquireSyncLock(platform, model) {
|
|
6754
|
-
|
|
6130
|
+
fs6.mkdirSync(LOCK_DIR_REL, { recursive: true });
|
|
6755
6131
|
const dir = lockPath(platform, model);
|
|
6756
|
-
const pidFile =
|
|
6132
|
+
const pidFile = path6.join(dir, "pid");
|
|
6757
6133
|
try {
|
|
6758
|
-
|
|
6134
|
+
fs6.mkdirSync(dir);
|
|
6759
6135
|
} catch (err) {
|
|
6760
6136
|
const stat = (() => {
|
|
6761
6137
|
try {
|
|
6762
|
-
return
|
|
6138
|
+
return fs6.statSync(dir);
|
|
6763
6139
|
} catch {
|
|
6764
6140
|
return null;
|
|
6765
6141
|
}
|
|
@@ -6768,7 +6144,7 @@ function acquireSyncLock(platform, model) {
|
|
|
6768
6144
|
const age = Date.now() - stat.mtimeMs;
|
|
6769
6145
|
let ownerPid = null;
|
|
6770
6146
|
try {
|
|
6771
|
-
const raw =
|
|
6147
|
+
const raw = fs6.readFileSync(pidFile, "utf-8");
|
|
6772
6148
|
const parsed = parseInt(raw.trim(), 10);
|
|
6773
6149
|
if (!isNaN(parsed)) ownerPid = parsed;
|
|
6774
6150
|
} catch {
|
|
@@ -6777,8 +6153,8 @@ function acquireSyncLock(platform, model) {
|
|
|
6777
6153
|
const veryOld = age > STALE_MS;
|
|
6778
6154
|
if (ownerDead || veryOld) {
|
|
6779
6155
|
try {
|
|
6780
|
-
|
|
6781
|
-
|
|
6156
|
+
fs6.rmSync(dir, { recursive: true, force: true });
|
|
6157
|
+
fs6.mkdirSync(dir);
|
|
6782
6158
|
} catch {
|
|
6783
6159
|
throw new SyncLockError(
|
|
6784
6160
|
`Could not take over stale lock at ${dir}. Remove it manually if no sync is running.`
|
|
@@ -6795,13 +6171,13 @@ function acquireSyncLock(platform, model) {
|
|
|
6795
6171
|
}
|
|
6796
6172
|
}
|
|
6797
6173
|
try {
|
|
6798
|
-
|
|
6174
|
+
fs6.writeFileSync(pidFile, String(process.pid));
|
|
6799
6175
|
} catch {
|
|
6800
6176
|
}
|
|
6801
6177
|
return {
|
|
6802
6178
|
release() {
|
|
6803
6179
|
try {
|
|
6804
|
-
|
|
6180
|
+
fs6.rmSync(dir, { recursive: true, force: true });
|
|
6805
6181
|
} catch {
|
|
6806
6182
|
}
|
|
6807
6183
|
}
|
|
@@ -6810,9 +6186,9 @@ function acquireSyncLock(platform, model) {
|
|
|
6810
6186
|
|
|
6811
6187
|
// src/lib/memory/sync/hooks.ts
|
|
6812
6188
|
import { spawn as spawn2 } from "child_process";
|
|
6813
|
-
import
|
|
6814
|
-
import
|
|
6815
|
-
var EVENTS_DIR =
|
|
6189
|
+
import fs7 from "fs";
|
|
6190
|
+
import path7 from "path";
|
|
6191
|
+
var EVENTS_DIR = path7.join(".one", "sync", "events");
|
|
6816
6192
|
function classifyRecords(db, model, records, idField, tableExists2) {
|
|
6817
6193
|
if (!tableExists2 || records.length === 0) {
|
|
6818
6194
|
return { inserts: records, updates: [] };
|
|
@@ -6858,10 +6234,10 @@ async function fireHooks(hookCommand, events) {
|
|
|
6858
6234
|
function appendEventLog(events) {
|
|
6859
6235
|
if (events.length === 0) return;
|
|
6860
6236
|
const { platform, model } = events[0];
|
|
6861
|
-
|
|
6862
|
-
const logPath =
|
|
6237
|
+
fs7.mkdirSync(EVENTS_DIR, { recursive: true });
|
|
6238
|
+
const logPath = path7.join(EVENTS_DIR, `${platform}_${model}.jsonl`);
|
|
6863
6239
|
const lines = events.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
6864
|
-
|
|
6240
|
+
fs7.appendFileSync(logPath, lines);
|
|
6865
6241
|
}
|
|
6866
6242
|
function runShellHook(command, events) {
|
|
6867
6243
|
return new Promise((resolve) => {
|
|
@@ -6965,8 +6341,8 @@ function sleep(ms) {
|
|
|
6965
6341
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
6966
6342
|
}
|
|
6967
6343
|
function interpolate(template, record) {
|
|
6968
|
-
return template.replace(/\{?\{(\w+(?:\.\w+)*)\}\}?/g, (_,
|
|
6969
|
-
const parts =
|
|
6344
|
+
return template.replace(/\{?\{(\w+(?:\.\w+)*)\}\}?/g, (_, path13) => {
|
|
6345
|
+
const parts = path13.split(".");
|
|
6970
6346
|
let value = record;
|
|
6971
6347
|
for (const part2 of parts) {
|
|
6972
6348
|
if (typeof value !== "object" || value === null) return "";
|
|
@@ -6994,8 +6370,8 @@ function deepMerge(target, source) {
|
|
|
6994
6370
|
}
|
|
6995
6371
|
return result;
|
|
6996
6372
|
}
|
|
6997
|
-
function getByDotPath2(obj,
|
|
6998
|
-
const parts =
|
|
6373
|
+
function getByDotPath2(obj, path13) {
|
|
6374
|
+
const parts = path13.split(".");
|
|
6999
6375
|
let current = obj;
|
|
7000
6376
|
for (const part2 of parts) {
|
|
7001
6377
|
if (current === null || current === void 0 || typeof current !== "object") return void 0;
|
|
@@ -7004,8 +6380,8 @@ function getByDotPath2(obj, path16) {
|
|
|
7004
6380
|
return current;
|
|
7005
6381
|
}
|
|
7006
6382
|
function stripExcludedFields(obj, paths) {
|
|
7007
|
-
for (const
|
|
7008
|
-
stripOnePath(obj,
|
|
6383
|
+
for (const path13 of paths) {
|
|
6384
|
+
stripOnePath(obj, path13.replace(/\[\]/g, ".*").split("."));
|
|
7009
6385
|
}
|
|
7010
6386
|
}
|
|
7011
6387
|
function stripOnePath(obj, parts) {
|
|
@@ -7171,7 +6547,7 @@ async function enrichPhase(api, db, config2, model, idField, connectionKey, plat
|
|
|
7171
6547
|
);
|
|
7172
6548
|
let batchHitRateLimit = false;
|
|
7173
6549
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
7174
|
-
const
|
|
6550
|
+
const pending = [];
|
|
7175
6551
|
for (let j = 0; j < results.length; j++) {
|
|
7176
6552
|
const result = results[j];
|
|
7177
6553
|
const row = batch[j];
|
|
@@ -7190,7 +6566,7 @@ async function enrichPhase(api, db, config2, model, idField, connectionKey, plat
|
|
|
7190
6566
|
const fp = merged[config2.invalidateOn] ?? row[config2.invalidateOn];
|
|
7191
6567
|
merged[ENRICH_FINGERPRINT_COLUMN] = fp == null ? null : String(fp);
|
|
7192
6568
|
}
|
|
7193
|
-
|
|
6569
|
+
pending.push({ merged, id });
|
|
7194
6570
|
} else if (result.status === "fulfilled" && result.value === null) {
|
|
7195
6571
|
rateLimited++;
|
|
7196
6572
|
skipped++;
|
|
@@ -7199,14 +6575,14 @@ async function enrichPhase(api, db, config2, model, idField, connectionKey, plat
|
|
|
7199
6575
|
skipped++;
|
|
7200
6576
|
}
|
|
7201
6577
|
}
|
|
7202
|
-
let writes =
|
|
7203
|
-
if (ctx.transform &&
|
|
7204
|
-
const transformed = await transformRecords(ctx.transform,
|
|
6578
|
+
let writes = pending;
|
|
6579
|
+
if (ctx.transform && pending.length > 0) {
|
|
6580
|
+
const transformed = await transformRecords(ctx.transform, pending.map((p9) => p9.merged));
|
|
7205
6581
|
if (transformed) {
|
|
7206
6582
|
const byId = /* @__PURE__ */ new Map();
|
|
7207
6583
|
for (const r of transformed) byId.set(r[idField], r);
|
|
7208
6584
|
writes = [];
|
|
7209
|
-
for (const p9 of
|
|
6585
|
+
for (const p9 of pending) {
|
|
7210
6586
|
const t = byId.get(p9.id);
|
|
7211
6587
|
if (!t) continue;
|
|
7212
6588
|
if (!t[tsField]) t[tsField] = now;
|
|
@@ -7426,8 +6802,8 @@ function sleep2(ms) {
|
|
|
7426
6802
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
7427
6803
|
}
|
|
7428
6804
|
function stripFields(record, paths) {
|
|
7429
|
-
for (const
|
|
7430
|
-
stripOnePath2(record,
|
|
6805
|
+
for (const path13 of paths) {
|
|
6806
|
+
stripOnePath2(record, path13.split("."));
|
|
7431
6807
|
}
|
|
7432
6808
|
}
|
|
7433
6809
|
function stripOnePath2(obj, parts) {
|
|
@@ -8520,19 +7896,19 @@ function inferProfileFromKnowledge(knowledge, modelName, platform) {
|
|
|
8520
7896
|
|
|
8521
7897
|
// src/lib/memory/sync/schedule.ts
|
|
8522
7898
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
8523
|
-
import
|
|
8524
|
-
import
|
|
8525
|
-
import
|
|
7899
|
+
import fs9 from "fs";
|
|
7900
|
+
import os from "os";
|
|
7901
|
+
import path9 from "path";
|
|
8526
7902
|
|
|
8527
7903
|
// src/lib/memory/sync/schedule-registry.ts
|
|
8528
|
-
import
|
|
8529
|
-
import
|
|
8530
|
-
var REGISTRY_DIR = () =>
|
|
8531
|
-
var REGISTRY_FILE = () =>
|
|
7904
|
+
import fs8 from "fs";
|
|
7905
|
+
import path8 from "path";
|
|
7906
|
+
var REGISTRY_DIR = () => path8.join(homeDir(), ".one", "sync");
|
|
7907
|
+
var REGISTRY_FILE = () => path8.join(REGISTRY_DIR(), "schedules.json");
|
|
8532
7908
|
function readRaw() {
|
|
8533
7909
|
try {
|
|
8534
|
-
if (!
|
|
8535
|
-
const raw =
|
|
7910
|
+
if (!fs8.existsSync(REGISTRY_FILE())) return { schedules: [] };
|
|
7911
|
+
const raw = fs8.readFileSync(REGISTRY_FILE(), "utf-8");
|
|
8536
7912
|
const parsed = JSON.parse(raw);
|
|
8537
7913
|
if (!parsed || !Array.isArray(parsed.schedules)) return { schedules: [] };
|
|
8538
7914
|
return parsed;
|
|
@@ -8541,13 +7917,13 @@ function readRaw() {
|
|
|
8541
7917
|
}
|
|
8542
7918
|
}
|
|
8543
7919
|
function writeRaw(file) {
|
|
8544
|
-
|
|
7920
|
+
fs8.mkdirSync(REGISTRY_DIR(), { recursive: true });
|
|
8545
7921
|
const tmp = REGISTRY_FILE() + ".tmp";
|
|
8546
|
-
|
|
8547
|
-
|
|
7922
|
+
fs8.writeFileSync(tmp, JSON.stringify(file, null, 2));
|
|
7923
|
+
fs8.renameSync(tmp, REGISTRY_FILE());
|
|
8548
7924
|
}
|
|
8549
7925
|
function makeScheduleId(platform, cwd) {
|
|
8550
|
-
const slug =
|
|
7926
|
+
const slug = path8.basename(cwd).replace(/[^a-zA-Z0-9_-]/g, "-").toLowerCase();
|
|
8551
7927
|
return `${platform}-${slug}`;
|
|
8552
7928
|
}
|
|
8553
7929
|
function listRegistered() {
|
|
@@ -8581,7 +7957,7 @@ function removeRegistered(id) {
|
|
|
8581
7957
|
|
|
8582
7958
|
// src/lib/memory/sync/schedule.ts
|
|
8583
7959
|
var MARKER = "# one-sync";
|
|
8584
|
-
var LOG_DIR_REL =
|
|
7960
|
+
var LOG_DIR_REL = path9.join(".one", "sync", "logs");
|
|
8585
7961
|
function durationToCron(every) {
|
|
8586
7962
|
const match = every.match(/^(\d+)([mhd])$/);
|
|
8587
7963
|
if (!match) return null;
|
|
@@ -8614,13 +7990,13 @@ function cronExprToDuration(expr) {
|
|
|
8614
7990
|
return null;
|
|
8615
7991
|
}
|
|
8616
7992
|
function isWindows() {
|
|
8617
|
-
return
|
|
7993
|
+
return os.platform() === "win32";
|
|
8618
7994
|
}
|
|
8619
7995
|
function resolveOneBinary() {
|
|
8620
7996
|
try {
|
|
8621
7997
|
const entry = process.argv[1];
|
|
8622
|
-
if (entry &&
|
|
8623
|
-
return
|
|
7998
|
+
if (entry && fs9.existsSync(entry)) {
|
|
7999
|
+
return fs9.realpathSync(entry);
|
|
8624
8000
|
}
|
|
8625
8001
|
} catch {
|
|
8626
8002
|
}
|
|
@@ -8698,7 +8074,7 @@ function migrateLegacyCronEntries() {
|
|
|
8698
8074
|
const modelsMatch = command.match(/--models\s+(\S+)/);
|
|
8699
8075
|
const models = modelsMatch ? modelsMatch[1].split(",") : void 0;
|
|
8700
8076
|
const logMatch = command.match(/>>\s+"([^"]+)"/);
|
|
8701
|
-
const logFile = logMatch ? logMatch[1] :
|
|
8077
|
+
const logFile = logMatch ? logMatch[1] : path9.resolve(cwd, LOG_DIR_REL, `${platform}.log`);
|
|
8702
8078
|
const id = makeScheduleId(platform, cwd);
|
|
8703
8079
|
if (registeredIds.has(id)) continue;
|
|
8704
8080
|
upsertRegistered({
|
|
@@ -8732,9 +8108,9 @@ function addSchedule(opts) {
|
|
|
8732
8108
|
const cwd = process.cwd();
|
|
8733
8109
|
const id = makeScheduleId(opts.platform, cwd);
|
|
8734
8110
|
const replaced = getRegistered(id) !== void 0;
|
|
8735
|
-
const logDir =
|
|
8736
|
-
|
|
8737
|
-
const logFile =
|
|
8111
|
+
const logDir = path9.join(cwd, LOG_DIR_REL);
|
|
8112
|
+
fs9.mkdirSync(logDir, { recursive: true });
|
|
8113
|
+
const logFile = path9.join(logDir, `${opts.platform}.log`);
|
|
8738
8114
|
const entry = {
|
|
8739
8115
|
id,
|
|
8740
8116
|
platform: opts.platform,
|
|
@@ -8788,15 +8164,15 @@ function removeSchedule(idOrPlatform, options) {
|
|
|
8788
8164
|
function scheduleStatus() {
|
|
8789
8165
|
const entries = listSchedules();
|
|
8790
8166
|
return entries.map((entry) => {
|
|
8791
|
-
const logExists =
|
|
8792
|
-
const logSize = logExists ?
|
|
8167
|
+
const logExists = fs9.existsSync(entry.logFile);
|
|
8168
|
+
const logSize = logExists ? fs9.statSync(entry.logFile).size : 0;
|
|
8793
8169
|
let logTail = [];
|
|
8794
8170
|
let lastRunAt = null;
|
|
8795
8171
|
if (logExists) {
|
|
8796
8172
|
try {
|
|
8797
|
-
lastRunAt =
|
|
8173
|
+
lastRunAt = fs9.statSync(entry.logFile).mtime.toISOString();
|
|
8798
8174
|
if (logSize > 0) {
|
|
8799
|
-
const content =
|
|
8175
|
+
const content = fs9.readFileSync(entry.logFile, "utf-8");
|
|
8800
8176
|
logTail = content.trim().split("\n").slice(-10);
|
|
8801
8177
|
}
|
|
8802
8178
|
} catch {
|
|
@@ -8804,8 +8180,8 @@ function scheduleStatus() {
|
|
|
8804
8180
|
}
|
|
8805
8181
|
let drift = "ok";
|
|
8806
8182
|
if (!entry.cronInstalled) drift = "missing-cron";
|
|
8807
|
-
else if (!
|
|
8808
|
-
else if (!
|
|
8183
|
+
else if (!fs9.existsSync(entry.nodeBin)) drift = "stale-node-bin";
|
|
8184
|
+
else if (!fs9.existsSync(entry.cliBin)) drift = "stale-cli-bin";
|
|
8809
8185
|
return { entry, logExists, logSize, logTail, lastRunAt, drift };
|
|
8810
8186
|
});
|
|
8811
8187
|
}
|
|
@@ -9078,11 +8454,11 @@ function isNoise(s) {
|
|
|
9078
8454
|
if (/^-?\d+(\.\d+)?([eE][-+]?\d+)?$/.test(s)) return true;
|
|
9079
8455
|
return false;
|
|
9080
8456
|
}
|
|
9081
|
-
function recordSample(stats,
|
|
9082
|
-
let s = stats.get(
|
|
8457
|
+
function recordSample(stats, path13, value, jsType, recordIndex, totalSamples) {
|
|
8458
|
+
let s = stats.get(path13);
|
|
9083
8459
|
if (!s) {
|
|
9084
8460
|
s = {
|
|
9085
|
-
path:
|
|
8461
|
+
path: path13,
|
|
9086
8462
|
total: totalSamples,
|
|
9087
8463
|
recordIndices: /* @__PURE__ */ new Set(),
|
|
9088
8464
|
lenSum: 0,
|
|
@@ -9091,7 +8467,7 @@ function recordSample(stats, path16, value, jsType, recordIndex, totalSamples) {
|
|
|
9091
8467
|
primaryType: jsType,
|
|
9092
8468
|
examples: []
|
|
9093
8469
|
};
|
|
9094
|
-
stats.set(
|
|
8470
|
+
stats.set(path13, s);
|
|
9095
8471
|
}
|
|
9096
8472
|
s.recordIndices.add(recordIndex);
|
|
9097
8473
|
s.lenSum += value.length;
|
|
@@ -9100,28 +8476,28 @@ function recordSample(stats, path16, value, jsType, recordIndex, totalSamples) {
|
|
|
9100
8476
|
if (s.primaryType !== jsType) s.primaryType = "mixed";
|
|
9101
8477
|
if (s.examples.length < 3 && value.length < 200) s.examples.push(value);
|
|
9102
8478
|
}
|
|
9103
|
-
function walkRecord(record,
|
|
8479
|
+
function walkRecord(record, path13, stats, recordIndex, totalSamples) {
|
|
9104
8480
|
if (record === null || record === void 0) return;
|
|
9105
8481
|
if (typeof record === "string") {
|
|
9106
8482
|
const trimmed = record.trim();
|
|
9107
|
-
if (trimmed) recordSample(stats,
|
|
8483
|
+
if (trimmed) recordSample(stats, path13, trimmed, "string", recordIndex, totalSamples);
|
|
9108
8484
|
return;
|
|
9109
8485
|
}
|
|
9110
8486
|
if (typeof record === "number" || typeof record === "boolean") {
|
|
9111
8487
|
const str = String(record);
|
|
9112
8488
|
const kind = typeof record === "number" ? "number" : "boolean";
|
|
9113
|
-
if (str) recordSample(stats,
|
|
8489
|
+
if (str) recordSample(stats, path13, str, kind, recordIndex, totalSamples);
|
|
9114
8490
|
return;
|
|
9115
8491
|
}
|
|
9116
8492
|
if (Array.isArray(record)) {
|
|
9117
|
-
const childPath =
|
|
8493
|
+
const childPath = path13 ? `${path13}[]` : "[]";
|
|
9118
8494
|
for (const item of record) walkRecord(item, childPath, stats, recordIndex, totalSamples);
|
|
9119
8495
|
return;
|
|
9120
8496
|
}
|
|
9121
8497
|
if (typeof record === "object") {
|
|
9122
8498
|
for (const [key, value] of Object.entries(record)) {
|
|
9123
8499
|
if (key.startsWith("_")) continue;
|
|
9124
|
-
const childPath =
|
|
8500
|
+
const childPath = path13 ? `${path13}.${key}` : key;
|
|
9125
8501
|
walkRecord(value, childPath, stats, recordIndex, totalSamples);
|
|
9126
8502
|
}
|
|
9127
8503
|
}
|
|
@@ -9159,7 +8535,7 @@ function suggestSearchablePaths(records, limit = 15) {
|
|
|
9159
8535
|
// src/lib/memory/sync/index.ts
|
|
9160
8536
|
import { spawn as spawn4 } from "child_process";
|
|
9161
8537
|
import * as p6 from "@clack/prompts";
|
|
9162
|
-
import
|
|
8538
|
+
import pc10 from "picocolors";
|
|
9163
8539
|
async function syncInstallCommand() {
|
|
9164
8540
|
if (await isSqliteAvailable()) {
|
|
9165
8541
|
if (isAgentMode()) {
|
|
@@ -9224,15 +8600,15 @@ async function syncDoctorCommand() {
|
|
|
9224
8600
|
return;
|
|
9225
8601
|
}
|
|
9226
8602
|
for (const c of checks) {
|
|
9227
|
-
const mark = c.ok ?
|
|
9228
|
-
console.log(` ${mark} ${c.name}${c.detail ?
|
|
8603
|
+
const mark = c.ok ? pc10.green("\u2713") : pc10.red("\u2717");
|
|
8604
|
+
console.log(` ${mark} ${c.name}${c.detail ? pc10.dim(` \u2014 ${c.detail}`) : ""}`);
|
|
9229
8605
|
}
|
|
9230
8606
|
if (!allOk) {
|
|
9231
8607
|
console.log(`
|
|
9232
|
-
${
|
|
8608
|
+
${pc10.yellow("Sync is not ready.")} Try: ${pc10.bold("one sync install")}`);
|
|
9233
8609
|
} else {
|
|
9234
8610
|
console.log(`
|
|
9235
|
-
${
|
|
8611
|
+
${pc10.green("Sync is ready.")}`);
|
|
9236
8612
|
}
|
|
9237
8613
|
}
|
|
9238
8614
|
function getApi() {
|
|
@@ -9275,11 +8651,11 @@ async function syncProfilesCommand(platform) {
|
|
|
9275
8651
|
if (p9.enrich) extras.push("enrich");
|
|
9276
8652
|
if (p9.identityKey || p9.identityKeys) extras.push("identity");
|
|
9277
8653
|
if (p9.dateFilter) extras.push("incremental");
|
|
9278
|
-
const tags = extras.length > 0 ? ` ${
|
|
9279
|
-
console.log(` ${
|
|
8654
|
+
const tags = extras.length > 0 ? ` ${pc10.dim(`[${extras.join(", ")}]`)}` : "";
|
|
8655
|
+
console.log(` ${pc10.bold(`${p9.platform}/${p9.model}`.padEnd(35))} ${p9.description}${tags}`);
|
|
9280
8656
|
}
|
|
9281
8657
|
console.log(`
|
|
9282
|
-
${profiles.length} built-in profile(s). Run ${
|
|
8658
|
+
${profiles.length} built-in profile(s). Run ${pc10.bold("one sync init <platform> <model>")} to use one.`);
|
|
9283
8659
|
}
|
|
9284
8660
|
async function syncModelsCommand(platform) {
|
|
9285
8661
|
const api = getApi();
|
|
@@ -9297,7 +8673,7 @@ async function syncModelsCommand(platform) {
|
|
|
9297
8673
|
return;
|
|
9298
8674
|
}
|
|
9299
8675
|
const lines = models.map(
|
|
9300
|
-
(m) => ` ${
|
|
8676
|
+
(m) => ` ${pc10.bold(m.name.padEnd(30))} ${pc10.dim(m.listAction.method)} ${pc10.dim(m.listAction.path)}`
|
|
9301
8677
|
);
|
|
9302
8678
|
note(lines.join("\n"), `${platform} \u2014 ${models.length} models`);
|
|
9303
8679
|
} catch (err) {
|
|
@@ -9401,15 +8777,15 @@ async function syncInitCommand(platform, model, options) {
|
|
|
9401
8777
|
note(JSON.stringify(template, null, 2), "Sync profile template");
|
|
9402
8778
|
if (inferred && inferred.reasoning.length > 0) {
|
|
9403
8779
|
console.log(`
|
|
9404
|
-
${
|
|
9405
|
-
for (const r of inferred.reasoning) console.log(` ${
|
|
8780
|
+
${pc10.bold("Inferred from knowledge:")}`);
|
|
8781
|
+
for (const r of inferred.reasoning) console.log(` ${pc10.dim("\u2022")} ${r}`);
|
|
9406
8782
|
}
|
|
9407
8783
|
if (testReport) {
|
|
9408
8784
|
console.log(`
|
|
9409
|
-
${
|
|
8785
|
+
${pc10.bold("Test results:")}`);
|
|
9410
8786
|
for (const c of testReport.checks) {
|
|
9411
|
-
const mark = c.ok ?
|
|
9412
|
-
console.log(` ${mark} ${c.name}${c.detail ?
|
|
8787
|
+
const mark = c.ok ? pc10.green("\u2713") : pc10.red("\u2717");
|
|
8788
|
+
console.log(` ${mark} ${c.name}${c.detail ? pc10.dim(` \u2014 ${c.detail}`) : ""}`);
|
|
9413
8789
|
}
|
|
9414
8790
|
}
|
|
9415
8791
|
console.log(`
|
|
@@ -9492,17 +8868,17 @@ async function syncTestCommand(platformModel, options = {}) {
|
|
|
9492
8868
|
return;
|
|
9493
8869
|
}
|
|
9494
8870
|
for (const c of report2.checks) {
|
|
9495
|
-
const mark = c.ok ?
|
|
9496
|
-
console.log(` ${mark} ${c.name}${c.detail ?
|
|
8871
|
+
const mark = c.ok ? pc10.green("\u2713") : pc10.red("\u2717");
|
|
8872
|
+
console.log(` ${mark} ${c.name}${c.detail ? pc10.dim(` \u2014 ${c.detail}`) : ""}`);
|
|
9497
8873
|
}
|
|
9498
8874
|
if (report2.detectedColumns && report2.detectedColumns.length > 0) {
|
|
9499
8875
|
console.log(`
|
|
9500
|
-
${
|
|
8876
|
+
${pc10.bold("Detected columns:")}`);
|
|
9501
8877
|
for (const col of report2.detectedColumns.slice(0, 20)) {
|
|
9502
|
-
console.log(` ${col.name.padEnd(30)} ${
|
|
8878
|
+
console.log(` ${col.name.padEnd(30)} ${pc10.dim(col.type)}`);
|
|
9503
8879
|
}
|
|
9504
8880
|
if (report2.detectedColumns.length > 20) {
|
|
9505
|
-
console.log(
|
|
8881
|
+
console.log(pc10.dim(` ... and ${report2.detectedColumns.length - 20} more`));
|
|
9506
8882
|
}
|
|
9507
8883
|
}
|
|
9508
8884
|
if (report2.identityKeysPreview) {
|
|
@@ -9510,45 +8886,45 @@ async function syncTestCommand(platformModel, options = {}) {
|
|
|
9510
8886
|
const total = perRecord.reduce((a, b) => a + b, 0);
|
|
9511
8887
|
const min = perRecord.length ? Math.min(...perRecord) : 0;
|
|
9512
8888
|
const max = perRecord.length ? Math.max(...perRecord) : 0;
|
|
9513
|
-
const mark = total === 0 ?
|
|
8889
|
+
const mark = total === 0 ? pc10.yellow("~") : pc10.green("\u2713");
|
|
9514
8890
|
console.log(`
|
|
9515
|
-
${
|
|
8891
|
+
${pc10.bold("Merge + identity keys")} ${pc10.dim(`(cross-platform \u2014 #128)`)}`);
|
|
9516
8892
|
console.log(` ${mark} ${perRecord.length} sample${perRecord.length === 1 ? "" : "s"}, ${min}\u2013${max} key${max === 1 ? "" : "s"} per record`);
|
|
9517
8893
|
if (sampleKeys.length > 0) {
|
|
9518
|
-
console.log(` ${
|
|
8894
|
+
console.log(` ${pc10.dim("e.g.")} ${sampleKeys.slice(0, 8).map((k) => pc10.cyan(k)).join(", ")}`);
|
|
9519
8895
|
} else if (resolvesAfterEnrich) {
|
|
9520
|
-
console.log(` ${
|
|
8896
|
+
console.log(` ${pc10.dim("note:")} 0 on these list-shape samples \u2014 this profile enriches, and its identityKeys paths resolve in the enrich phase.`);
|
|
9521
8897
|
} else {
|
|
9522
|
-
console.log(` ${
|
|
8898
|
+
console.log(` ${pc10.yellow("note:")} no identity keys resolved on these samples \u2014 check the identityKey/identityKeys paths.`);
|
|
9523
8899
|
}
|
|
9524
8900
|
if (entityFanOut) {
|
|
9525
|
-
console.log(` ${
|
|
9526
|
-
console.log(` ${
|
|
9527
|
-
console.log(` ${
|
|
9528
|
-
console.log(` ${
|
|
8901
|
+
console.log(` ${pc10.yellow("warn:")} identityKey resolved to MULTIPLE values on ${entityFanOut.count} of ${perRecord.length} samples \u2014 those records get NO merge key.`);
|
|
8902
|
+
console.log(` ${pc10.dim("saw:")} ${entityFanOut.sampleValues.map((v) => pc10.cyan(v)).join(", ")}`);
|
|
8903
|
+
console.log(` ${pc10.dim('A singular identityKey means "this record IS this entity", so a fan-out has no safe answer.')}`);
|
|
8904
|
+
console.log(` ${pc10.dim("Point it at a single-valued path, or move it to identityKeys[] for participant associations.")}`);
|
|
9529
8905
|
}
|
|
9530
8906
|
}
|
|
9531
8907
|
if (searchablePreview) {
|
|
9532
8908
|
console.log(`
|
|
9533
|
-
${
|
|
9534
|
-
console.log(` ${
|
|
9535
|
-
console.log(` ${
|
|
8909
|
+
${pc10.bold("Searchable preview")} ${pc10.dim(`(${searchablePreview.mode}, ${searchablePreview.sampledRecords} sample${searchablePreview.sampledRecords === 1 ? "" : "s"})`)}`);
|
|
8910
|
+
console.log(` ${pc10.dim("length:")} ${searchablePreview.length} chars (first sample)`);
|
|
8911
|
+
console.log(` ${pc10.dim("text:")} ${searchablePreview.text.slice(0, 300)}${searchablePreview.length > 300 ? pc10.dim(" \u2026") : ""}`);
|
|
9536
8912
|
if (searchablePreview.paths) {
|
|
9537
|
-
console.log(` ${
|
|
8913
|
+
console.log(` ${pc10.dim("paths:")} ${pc10.dim('(hit rate across all samples \u2014 differentiates "wrong path" from "field sometimes missing")')}`);
|
|
9538
8914
|
for (const p9 of searchablePreview.paths) {
|
|
9539
8915
|
const rate = `${p9.hits}/${p9.total}`;
|
|
9540
|
-
const mark = p9.hits === p9.total ?
|
|
9541
|
-
const trailer = p9.sample ?
|
|
8916
|
+
const mark = p9.hits === p9.total ? pc10.green("\u2713") : p9.hits === 0 ? pc10.red("\u2717") : pc10.yellow("~");
|
|
8917
|
+
const trailer = p9.sample ? pc10.dim(` \u2192 "${p9.sample}"`) : p9.hits === 0 ? pc10.dim(" (no sample matched \u2014 typo, or field never populated in this page)") : "";
|
|
9542
8918
|
console.log(` ${mark} ${rate.padStart(5)} ${p9.path}${trailer}`);
|
|
9543
8919
|
}
|
|
9544
8920
|
} else {
|
|
9545
|
-
console.log(` ${
|
|
9546
|
-
console.log(` ${
|
|
8921
|
+
console.log(` ${pc10.yellow("note:")} no memory.searchable declared \u2014 using the default walker (walks every field, often noisy).`);
|
|
8922
|
+
console.log(` ${pc10.dim("tip:")} run \`one sync suggest-searchable ${platform}/${model}\` for an auto-ranked starter list, or pick paths by hand and add them to profile.memory.searchable.`);
|
|
9547
8923
|
}
|
|
9548
8924
|
}
|
|
9549
8925
|
console.log(
|
|
9550
8926
|
`
|
|
9551
|
-
${report2.ok ?
|
|
8927
|
+
${report2.ok ? pc10.green("Profile looks good.") : pc10.red("Profile has issues.")} ` + (report2.ok ? `Run: ${pc10.bold(`one sync run ${platform} --models ${model}`)}` : "Fix the issues above and test again.")
|
|
9552
8928
|
);
|
|
9553
8929
|
}
|
|
9554
8930
|
function buildSearchablePreview(profile, samples) {
|
|
@@ -9556,7 +8932,7 @@ function buildSearchablePreview(profile, samples) {
|
|
|
9556
8932
|
const first = samples[0];
|
|
9557
8933
|
const paths = getSearchablePaths(profile);
|
|
9558
8934
|
if (paths) {
|
|
9559
|
-
const perPathAgg = paths.map((
|
|
8935
|
+
const perPathAgg = paths.map((path13) => ({ path: path13, hits: 0, total: samples.length, sample: "" }));
|
|
9560
8936
|
for (const record of samples) {
|
|
9561
8937
|
const { paths: perPath } = extractSearchableFromPaths(record, paths);
|
|
9562
8938
|
perPath.forEach((p9, i) => {
|
|
@@ -9589,8 +8965,8 @@ async function syncRunCommand(platform, options) {
|
|
|
9589
8965
|
if (profileDrift.length > 0 && !isAgentMode()) {
|
|
9590
8966
|
for (const d of profileDrift) {
|
|
9591
8967
|
console.log(
|
|
9592
|
-
` ${
|
|
9593
|
-
Run ${
|
|
8968
|
+
` ${pc10.yellow("!")} ${platform}/${d.model} is missing ${d.missing.map((f) => pc10.bold(f)).join(", ")} from the current built-in profile.
|
|
8969
|
+
Run ${pc10.bold(`one sync init ${platform} ${d.model}`)} to pick ${d.missing.length > 1 ? "them" : "it"} up.`
|
|
9594
8970
|
);
|
|
9595
8971
|
}
|
|
9596
8972
|
}
|
|
@@ -9633,21 +9009,21 @@ async function syncRunCommand(platform, options) {
|
|
|
9633
9009
|
return;
|
|
9634
9010
|
}
|
|
9635
9011
|
for (const r of results) {
|
|
9636
|
-
const status2 = r.status === "complete" ?
|
|
9637
|
-
console.log(` ${
|
|
9012
|
+
const status2 = r.status === "complete" ? pc10.green("complete") : r.status === "dry-run" ? pc10.yellow("dry-run") : pc10.red("failed");
|
|
9013
|
+
console.log(` ${pc10.bold(r.model)} \u2014 ${r.recordsSynced} records, ${r.pagesProcessed} pages, ${r.duration} [${status2}]`);
|
|
9638
9014
|
if (r.reconcileSkipped) {
|
|
9639
|
-
console.log(` ${
|
|
9015
|
+
console.log(` ${pc10.yellow("--full-refresh reconcile skipped \u2014 pagination truncated (e.g. --max-pages). Re-run without the cap to prune stale rows.")}`);
|
|
9640
9016
|
}
|
|
9641
9017
|
const sc = r.statusCounts;
|
|
9642
9018
|
if (sc && (sc.archived > 0 || sc.active > 0)) {
|
|
9643
|
-
const archivedColor = sc.archived > sc.active ?
|
|
9644
|
-
console.log(` memory: ${
|
|
9019
|
+
const archivedColor = sc.archived > sc.active ? pc10.red : pc10.dim;
|
|
9020
|
+
console.log(` memory: ${pc10.green(String(sc.active))} active, ${archivedColor(String(sc.archived))} archived`);
|
|
9645
9021
|
}
|
|
9646
9022
|
if (r.error) {
|
|
9647
9023
|
const errParts = [r.error.message];
|
|
9648
9024
|
if (r.error.httpStatus) errParts.push(`HTTP ${r.error.httpStatus}`);
|
|
9649
9025
|
if (r.error.retryAfter) errParts.push(`retry after ${r.error.retryAfter}s`);
|
|
9650
|
-
console.log(` ${
|
|
9026
|
+
console.log(` ${pc10.red(errParts.join(" \u2014 "))}`);
|
|
9651
9027
|
}
|
|
9652
9028
|
}
|
|
9653
9029
|
}
|
|
@@ -9673,8 +9049,8 @@ async function syncQueryCommand(platformModel, options) {
|
|
|
9673
9049
|
json(result);
|
|
9674
9050
|
return;
|
|
9675
9051
|
}
|
|
9676
|
-
console.log(
|
|
9677
|
-
console.log(
|
|
9052
|
+
console.log(pc10.dim(`Query: ${result.query}`));
|
|
9053
|
+
console.log(pc10.dim(`Source: local | Last sync: ${result.lastSync ?? "never"} | Age: ${result.syncAge ?? "n/a"}`));
|
|
9678
9054
|
console.log(JSON.stringify(result.results, null, 2));
|
|
9679
9055
|
console.log(`
|
|
9680
9056
|
${result.total} results`);
|
|
@@ -9696,7 +9072,7 @@ async function syncSearchCommand(query, options) {
|
|
|
9696
9072
|
return;
|
|
9697
9073
|
}
|
|
9698
9074
|
for (const r of result.results) {
|
|
9699
|
-
console.log(` ${
|
|
9075
|
+
console.log(` ${pc10.bold(`${r.platform}/${r.model}`)} ${pc10.dim(`(rank: ${r.rank.toFixed(2)})`)}`);
|
|
9700
9076
|
console.log(` ${JSON.stringify(r.record)}`);
|
|
9701
9077
|
}
|
|
9702
9078
|
console.log(`
|
|
@@ -9706,7 +9082,7 @@ ${result.total} results`);
|
|
|
9706
9082
|
}
|
|
9707
9083
|
}
|
|
9708
9084
|
async function syncSqlCommand(platformModel, sql) {
|
|
9709
|
-
const { syncSqlCommand: runSyncSql } = await import("./sql-
|
|
9085
|
+
const { syncSqlCommand: runSyncSql } = await import("./sql-NDMMFQP6.js");
|
|
9710
9086
|
await runSyncSql(platformModel, sql);
|
|
9711
9087
|
}
|
|
9712
9088
|
async function syncDeleteCommand(platformModel, options) {
|
|
@@ -9800,7 +9176,7 @@ async function maybeAutoMigrateLegacy(platform, models) {
|
|
|
9800
9176
|
` detected legacy .one/sync/data/${platform}.db (${dbSize}) \u2014 auto-migrating into memory before sync.
|
|
9801
9177
|
`
|
|
9802
9178
|
);
|
|
9803
|
-
const { memMigrateCommand: memMigrateCommand3 } = await import("./migrate-
|
|
9179
|
+
const { memMigrateCommand: memMigrateCommand3 } = await import("./migrate-KWEEEQ3E.js");
|
|
9804
9180
|
await memMigrateCommand3({ platform, yes: true });
|
|
9805
9181
|
return;
|
|
9806
9182
|
}
|
|
@@ -9809,7 +9185,7 @@ async function maybeAutoMigrateLegacy(platform, models) {
|
|
|
9809
9185
|
initialValue: true
|
|
9810
9186
|
});
|
|
9811
9187
|
if (p6.isCancel(shouldMigrate) || !shouldMigrate) return;
|
|
9812
|
-
const { memMigrateCommand: memMigrateCommand2 } = await import("./migrate-
|
|
9188
|
+
const { memMigrateCommand: memMigrateCommand2 } = await import("./migrate-KWEEEQ3E.js");
|
|
9813
9189
|
await memMigrateCommand2({ platform, yes: true });
|
|
9814
9190
|
}
|
|
9815
9191
|
async function syncSuggestSearchableCommand(platformModel, options = {}) {
|
|
@@ -9847,25 +9223,25 @@ async function syncSuggestSearchableCommand(platformModel, options = {}) {
|
|
|
9847
9223
|
return;
|
|
9848
9224
|
}
|
|
9849
9225
|
console.log(`
|
|
9850
|
-
${
|
|
9226
|
+
${pc10.bold("memory.searchable \u2014 ranked suggestions")} ${pc10.dim(`(${samples.length} samples)`)}`);
|
|
9851
9227
|
if (suggestions.length === 0) {
|
|
9852
|
-
console.log(` ${
|
|
9228
|
+
console.log(` ${pc10.yellow("no high-signal leaves found")} \u2014 page may be all UUIDs / timestamps / enum markers. Inspect the sample with \`sync test\` and pick paths manually.`);
|
|
9853
9229
|
return;
|
|
9854
9230
|
}
|
|
9855
9231
|
for (const s of suggestions) {
|
|
9856
9232
|
const hitPct = Math.round(s.hitRate * 100);
|
|
9857
9233
|
const noisePct = Math.round(s.noiseFraction * 100);
|
|
9858
|
-
const noiseBadge = noisePct > 0 ?
|
|
9234
|
+
const noiseBadge = noisePct > 0 ? pc10.dim(` noise=${noisePct}%`) : "";
|
|
9859
9235
|
console.log(
|
|
9860
|
-
` ${
|
|
9236
|
+
` ${pc10.green(String(s.score).padStart(5))} ${pc10.cyan(s.path.padEnd(52))}` + pc10.dim(` ${hitPct}% hit`) + pc10.dim(` avg=${s.avgLength}ch`) + noiseBadge + (s.sampleValue ? pc10.dim(`
|
|
9861
9237
|
\u2192 "${s.sampleValue.slice(0, 140)}"`) : "")
|
|
9862
9238
|
);
|
|
9863
9239
|
}
|
|
9864
9240
|
console.log(`
|
|
9865
|
-
${
|
|
9866
|
-
console.log(" " +
|
|
9241
|
+
${pc10.bold("Paste-ready:")}`);
|
|
9242
|
+
console.log(" " + pc10.cyan(`one sync init ${platform} ${model} --config '${JSON.stringify(configPatch)}'`));
|
|
9867
9243
|
console.log(`
|
|
9868
|
-
${
|
|
9244
|
+
${pc10.dim("then preview: ")}${pc10.cyan(`one sync test ${platform}/${model} --show-searchable`)}`);
|
|
9869
9245
|
}
|
|
9870
9246
|
async function syncListCommand(platform) {
|
|
9871
9247
|
const profiles = listProfiles(platform);
|
|
@@ -9899,10 +9275,10 @@ async function syncListCommand(platform) {
|
|
|
9899
9275
|
return;
|
|
9900
9276
|
}
|
|
9901
9277
|
for (const s of syncs) {
|
|
9902
|
-
const status2 = s.status === "idle" ?
|
|
9903
|
-
const legacy = s.legacyDbSize && s.legacyDbSize !== "0 B" ?
|
|
9278
|
+
const status2 = s.status === "idle" ? pc10.green("idle") : s.status === "syncing" ? pc10.yellow(`syncing \u2014 page ${s.pagesProcessed}`) : pc10.red("failed");
|
|
9279
|
+
const legacy = s.legacyDbSize && s.legacyDbSize !== "0 B" ? pc10.yellow(` legacy .db ${s.legacyDbSize}`) : "";
|
|
9904
9280
|
console.log(
|
|
9905
|
-
` ${
|
|
9281
|
+
` ${pc10.bold(`${s.platform}/${s.model}`.padEnd(35))} ${String(s.totalRecords).padStart(8)} records ${status2} ${pc10.dim(s.lastSync ? `last: ${s.lastSync}` : "never synced")}` + legacy
|
|
9906
9282
|
);
|
|
9907
9283
|
}
|
|
9908
9284
|
}
|
|
@@ -9981,8 +9357,8 @@ async function syncScheduleAddCommand(platform, options) {
|
|
|
9981
9357
|
}
|
|
9982
9358
|
const verb = replaced ? "Replaced existing schedule" : "Scheduled sync";
|
|
9983
9359
|
outro(
|
|
9984
|
-
`${verb} ${
|
|
9985
|
-
Logs: ${
|
|
9360
|
+
`${verb} ${pc10.bold(entry.id)} \u2014 every ${pc10.bold(entry.every)} (cron: ${pc10.dim(entry.cronExpr)})
|
|
9361
|
+
Logs: ${pc10.dim(entry.logFile)}`
|
|
9986
9362
|
);
|
|
9987
9363
|
} catch (err) {
|
|
9988
9364
|
error(err instanceof Error ? err.message : String(err));
|
|
@@ -10001,14 +9377,14 @@ async function syncScheduleListCommand() {
|
|
|
10001
9377
|
}
|
|
10002
9378
|
for (const e of entries) {
|
|
10003
9379
|
const modelsStr = e.models ? ` [${e.models.join(",")}]` : "";
|
|
10004
|
-
const installed = e.cronInstalled ?
|
|
9380
|
+
const installed = e.cronInstalled ? pc10.green("\u25CF") : pc10.red("\u2717");
|
|
10005
9381
|
console.log(
|
|
10006
|
-
` ${installed} ${
|
|
9382
|
+
` ${installed} ${pc10.bold(e.id.padEnd(32))} every ${pc10.bold(e.every.padEnd(5))} ${pc10.dim(e.cronExpr.padEnd(13))}${modelsStr}`
|
|
10007
9383
|
);
|
|
10008
|
-
console.log(` ${
|
|
9384
|
+
console.log(` ${pc10.dim("cwd:")} ${e.cwd}`);
|
|
10009
9385
|
}
|
|
10010
9386
|
console.log(`
|
|
10011
|
-
${
|
|
9387
|
+
${pc10.dim("\u25CF = cron line installed \u2717 = registry drift, run `sync schedule repair <id>`")}`);
|
|
10012
9388
|
} catch (err) {
|
|
10013
9389
|
error(err instanceof Error ? err.message : String(err));
|
|
10014
9390
|
}
|
|
@@ -10032,7 +9408,7 @@ async function syncScheduleRemoveCommand(idOrPlatform, options) {
|
|
|
10032
9408
|
return;
|
|
10033
9409
|
}
|
|
10034
9410
|
for (const r of result.removed) {
|
|
10035
|
-
console.log(` ${
|
|
9411
|
+
console.log(` ${pc10.green("\u2713")} removed ${pc10.bold(r.id)} ${pc10.dim(`(${r.cwd})`)}`);
|
|
10036
9412
|
}
|
|
10037
9413
|
} catch (err) {
|
|
10038
9414
|
error(err instanceof Error ? err.message : String(err));
|
|
@@ -10050,21 +9426,21 @@ async function syncScheduleStatusCommand() {
|
|
|
10050
9426
|
return;
|
|
10051
9427
|
}
|
|
10052
9428
|
for (const s of statuses) {
|
|
10053
|
-
const driftMarker = s.drift === "ok" ?
|
|
10054
|
-
console.log(` ${driftMarker} ${
|
|
10055
|
-
console.log(` ${
|
|
10056
|
-
console.log(` ${
|
|
10057
|
-
console.log(` ${
|
|
9429
|
+
const driftMarker = s.drift === "ok" ? pc10.green("\u25CF") : s.drift === "missing-cron" ? pc10.red("\u2717 missing cron line") : pc10.yellow(`\u26A0 ${s.drift}`);
|
|
9430
|
+
console.log(` ${driftMarker} ${pc10.bold(s.entry.id)} \u2014 every ${s.entry.every} (${pc10.dim(s.entry.cronExpr)})`);
|
|
9431
|
+
console.log(` ${pc10.dim("cwd:")} ${s.entry.cwd}`);
|
|
9432
|
+
console.log(` ${pc10.dim("last run:")} ${s.lastRunAt ?? pc10.yellow("never")}`);
|
|
9433
|
+
console.log(` ${pc10.dim("log:")} ${s.entry.logFile} ${s.logExists ? pc10.dim(`(${s.logSize} bytes)`) : pc10.yellow("(empty)")}`);
|
|
10058
9434
|
if (s.logTail.length > 0) {
|
|
10059
|
-
console.log(
|
|
9435
|
+
console.log(pc10.dim(" last lines:"));
|
|
10060
9436
|
for (const line of s.logTail.slice(-3)) {
|
|
10061
|
-
console.log(
|
|
9437
|
+
console.log(pc10.dim(` ${line}`));
|
|
10062
9438
|
}
|
|
10063
9439
|
}
|
|
10064
9440
|
}
|
|
10065
9441
|
if (statuses.some((s) => s.drift !== "ok")) {
|
|
10066
9442
|
console.log(`
|
|
10067
|
-
${
|
|
9443
|
+
${pc10.yellow("Drift detected.")} Run ${pc10.bold("one sync schedule repair <id>")} to heal.`);
|
|
10068
9444
|
}
|
|
10069
9445
|
} catch (err) {
|
|
10070
9446
|
error(err instanceof Error ? err.message : String(err));
|
|
@@ -10077,7 +9453,7 @@ async function syncScheduleRepairCommand(id) {
|
|
|
10077
9453
|
json({ status: "repaired", ...healed });
|
|
10078
9454
|
return;
|
|
10079
9455
|
}
|
|
10080
|
-
outro(`Repaired ${
|
|
9456
|
+
outro(`Repaired ${pc10.bold(healed.id)}: re-installed cron line with current node/cli paths.`);
|
|
10081
9457
|
} catch (err) {
|
|
10082
9458
|
error(err instanceof Error ? err.message : String(err));
|
|
10083
9459
|
}
|
|
@@ -10146,7 +9522,7 @@ function registerSyncSubcommands(sync) {
|
|
|
10146
9522
|
await syncSqlCommand(platformModel, sql);
|
|
10147
9523
|
});
|
|
10148
9524
|
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) => {
|
|
10149
|
-
const { syncSchemaCommand } = await import("./schema-
|
|
9525
|
+
const { syncSchemaCommand } = await import("./schema-YJ7JTGFL.js");
|
|
10150
9526
|
await syncSchemaCommand(platformModel);
|
|
10151
9527
|
});
|
|
10152
9528
|
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) => {
|
|
@@ -10513,16 +9889,16 @@ function projectEmbeddingApiKey(cfg) {
|
|
|
10513
9889
|
}
|
|
10514
9890
|
function redactSecrets(cfg) {
|
|
10515
9891
|
const copy = JSON.parse(JSON.stringify(cfg));
|
|
10516
|
-
for (const
|
|
10517
|
-
const val = getPath(copy,
|
|
9892
|
+
for (const path13 of SECRET_PATHS) {
|
|
9893
|
+
const val = getPath(copy, path13);
|
|
10518
9894
|
if (typeof val === "string" && val.length > 0) {
|
|
10519
|
-
setPath(copy,
|
|
9895
|
+
setPath(copy, path13, `${val.slice(0, 6)}\u2026(redacted, use --show-secrets)`);
|
|
10520
9896
|
}
|
|
10521
9897
|
}
|
|
10522
9898
|
return copy;
|
|
10523
9899
|
}
|
|
10524
|
-
function getPath(obj,
|
|
10525
|
-
const parts =
|
|
9900
|
+
function getPath(obj, path13) {
|
|
9901
|
+
const parts = path13.split(".");
|
|
10526
9902
|
let cur = obj;
|
|
10527
9903
|
for (const part2 of parts) {
|
|
10528
9904
|
if (cur == null || typeof cur !== "object") return void 0;
|
|
@@ -10530,8 +9906,8 @@ function getPath(obj, path16) {
|
|
|
10530
9906
|
}
|
|
10531
9907
|
return cur;
|
|
10532
9908
|
}
|
|
10533
|
-
function setPath(obj,
|
|
10534
|
-
const parts =
|
|
9909
|
+
function setPath(obj, path13, value) {
|
|
9910
|
+
const parts = path13.split(".");
|
|
10535
9911
|
let cur = obj;
|
|
10536
9912
|
for (let i = 0; i < parts.length - 1; i++) {
|
|
10537
9913
|
const part2 = parts[i];
|
|
@@ -10541,8 +9917,8 @@ function setPath(obj, path16, value) {
|
|
|
10541
9917
|
cur[parts[parts.length - 1]] = value;
|
|
10542
9918
|
return obj;
|
|
10543
9919
|
}
|
|
10544
|
-
function unsetPath(obj,
|
|
10545
|
-
const parts =
|
|
9920
|
+
function unsetPath(obj, path13) {
|
|
9921
|
+
const parts = path13.split(".");
|
|
10546
9922
|
let cur = obj;
|
|
10547
9923
|
for (let i = 0; i < parts.length - 1; i++) {
|
|
10548
9924
|
const part2 = parts[i];
|
|
@@ -10568,7 +9944,7 @@ function parseValue(raw) {
|
|
|
10568
9944
|
}
|
|
10569
9945
|
|
|
10570
9946
|
// src/commands/mem/records.ts
|
|
10571
|
-
import
|
|
9947
|
+
import pc11 from "picocolors";
|
|
10572
9948
|
async function memAddCommand(type, dataRaw, flags) {
|
|
10573
9949
|
requireMemoryInit();
|
|
10574
9950
|
const data = parseJsonArg(dataRaw, "data");
|
|
@@ -10767,7 +10143,7 @@ function summarizeRecord(r) {
|
|
|
10767
10143
|
const v = d[field];
|
|
10768
10144
|
if (typeof v === "string" && v.trim()) return v.trim().slice(0, 80);
|
|
10769
10145
|
}
|
|
10770
|
-
return
|
|
10146
|
+
return pc11.dim("(untitled)");
|
|
10771
10147
|
}
|
|
10772
10148
|
function relativeTime(iso) {
|
|
10773
10149
|
if (!iso) return "";
|
|
@@ -10830,7 +10206,7 @@ async function memFindByKeyCommand(key, secondKey, flags) {
|
|
|
10830
10206
|
});
|
|
10831
10207
|
return;
|
|
10832
10208
|
}
|
|
10833
|
-
const label = matchedKeys.map((k) =>
|
|
10209
|
+
const label = matchedKeys.map((k) => pc11.cyan(k)).join(pc11.dim(" + "));
|
|
10834
10210
|
if (records.length === 0) {
|
|
10835
10211
|
console.log(`
|
|
10836
10212
|
No records linked to ${label}.
|
|
@@ -10838,27 +10214,27 @@ async function memFindByKeyCommand(key, secondKey, flags) {
|
|
|
10838
10214
|
return;
|
|
10839
10215
|
}
|
|
10840
10216
|
console.log();
|
|
10841
|
-
console.log(` ${label} ${
|
|
10217
|
+
console.log(` ${label} ${pc11.dim("\u2014")} ${records.length}${truncated ? "+" : ""} record${records.length === 1 ? "" : "s"} across ${byType.size} type${byType.size === 1 ? "" : "s"}`);
|
|
10842
10218
|
console.log();
|
|
10843
10219
|
const typeWidth = Math.min(30, Math.max(...[...byType.keys()].map((t) => t.length)));
|
|
10844
10220
|
for (const [type, list] of byType) {
|
|
10845
|
-
console.log(` ${
|
|
10221
|
+
console.log(` ${pc11.bold(type.padEnd(typeWidth))} ${pc11.dim(`${list.length} record${list.length === 1 ? "" : "s"}`)}`);
|
|
10846
10222
|
for (const r of list.slice(0, perType)) {
|
|
10847
|
-
console.log(` ${
|
|
10223
|
+
console.log(` ${pc11.dim("\xB7")} ${summarizeRecord(r)} ${pc11.dim(relativeTime(r.updated_at))} ${pc11.dim(r.id)}`);
|
|
10848
10224
|
}
|
|
10849
10225
|
if (list.length > perType) {
|
|
10850
|
-
console.log(` ${
|
|
10226
|
+
console.log(` ${pc11.dim(`\u2026 and ${list.length - perType} more (raise --limit)`)}`);
|
|
10851
10227
|
}
|
|
10852
10228
|
}
|
|
10853
10229
|
if (truncated) {
|
|
10854
10230
|
console.log();
|
|
10855
|
-
console.log(` ${
|
|
10231
|
+
console.log(` ${pc11.yellow("\u26A0")} Stopped at ${FIND_BY_KEY_FETCH_CAP} matches \u2014 there are more, and types sorting after the last one shown are missing entirely. Re-run with --type <type> to see them.`);
|
|
10856
10232
|
}
|
|
10857
10233
|
console.log();
|
|
10858
10234
|
}
|
|
10859
10235
|
|
|
10860
10236
|
// src/commands/mem/doctor.ts
|
|
10861
|
-
import
|
|
10237
|
+
import pc12 from "picocolors";
|
|
10862
10238
|
async function memDoctorCommand() {
|
|
10863
10239
|
const checks = [];
|
|
10864
10240
|
const cfg = getMemoryConfig();
|
|
@@ -10965,23 +10341,23 @@ function emit(checks, capInfo) {
|
|
|
10965
10341
|
return;
|
|
10966
10342
|
}
|
|
10967
10343
|
for (const c of checks) {
|
|
10968
|
-
const mark = c.ok ?
|
|
10969
|
-
const detail = c.detail ?
|
|
10344
|
+
const mark = c.ok ? pc12.green("\u2713") : pc12.red("\u2717");
|
|
10345
|
+
const detail = c.detail ? pc12.dim(` \u2014 ${c.detail}`) : "";
|
|
10970
10346
|
console.log(` ${mark} ${c.name}${detail}`);
|
|
10971
10347
|
}
|
|
10972
10348
|
if (!allOk) {
|
|
10973
|
-
console.log("\n" +
|
|
10349
|
+
console.log("\n" + pc12.yellow("Memory is not fully healthy."));
|
|
10974
10350
|
process.exitCode = 1;
|
|
10975
10351
|
} else {
|
|
10976
|
-
console.log("\n" +
|
|
10352
|
+
console.log("\n" + pc12.green("Memory is healthy."));
|
|
10977
10353
|
}
|
|
10978
10354
|
const line = semanticSearchUpgradeLine({ vectorSearchAvailable: capInfo.vectorSearchAvailable });
|
|
10979
10355
|
if (line) console.log(`
|
|
10980
|
-
${
|
|
10356
|
+
${pc12.dim(line)}`);
|
|
10981
10357
|
}
|
|
10982
10358
|
|
|
10983
10359
|
// src/commands/mem/export.ts
|
|
10984
|
-
import
|
|
10360
|
+
import fs10 from "fs";
|
|
10985
10361
|
import { once } from "events";
|
|
10986
10362
|
async function writeLine(stream, line) {
|
|
10987
10363
|
if (!stream.write(line)) {
|
|
@@ -10993,7 +10369,7 @@ async function memExportCommand(outfile) {
|
|
|
10993
10369
|
const backend = await getBackend();
|
|
10994
10370
|
const stats = await backend.stats();
|
|
10995
10371
|
const toFile = !!outfile && outfile !== "-";
|
|
10996
|
-
const stream = toFile ?
|
|
10372
|
+
const stream = toFile ? fs10.createWriteStream(outfile, "utf-8") : process.stdout;
|
|
10997
10373
|
const all = await listAllTypes(backend);
|
|
10998
10374
|
const pageSize = 500;
|
|
10999
10375
|
let written = 0;
|
|
@@ -11024,9 +10400,9 @@ async function memExportCommand(outfile) {
|
|
|
11024
10400
|
}
|
|
11025
10401
|
async function memImportCommand(file) {
|
|
11026
10402
|
requireMemoryInit();
|
|
11027
|
-
if (!
|
|
10403
|
+
if (!fs10.existsSync(file)) error(`File not found: ${file}`);
|
|
11028
10404
|
const backend = await getBackend();
|
|
11029
|
-
const raw =
|
|
10405
|
+
const raw = fs10.readFileSync(file, "utf-8");
|
|
11030
10406
|
const lines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
11031
10407
|
let inserted = 0;
|
|
11032
10408
|
let updated = 0;
|
|
@@ -11272,7 +10648,7 @@ function registerMemoryCommands(program2) {
|
|
|
11272
10648
|
}
|
|
11273
10649
|
|
|
11274
10650
|
// src/commands/cache.ts
|
|
11275
|
-
import
|
|
10651
|
+
import pc13 from "picocolors";
|
|
11276
10652
|
async function cacheClearCommand(actionId) {
|
|
11277
10653
|
if (actionId) {
|
|
11278
10654
|
const deleted = clearEntry(actionId);
|
|
@@ -11281,9 +10657,9 @@ async function cacheClearCommand(actionId) {
|
|
|
11281
10657
|
return;
|
|
11282
10658
|
}
|
|
11283
10659
|
if (deleted) {
|
|
11284
|
-
console.log(`Cleared cache for ${
|
|
10660
|
+
console.log(`Cleared cache for ${pc13.cyan(actionId)}`);
|
|
11285
10661
|
} else {
|
|
11286
|
-
console.log(`No cache entry found for ${
|
|
10662
|
+
console.log(`No cache entry found for ${pc13.dim(actionId)}`);
|
|
11287
10663
|
}
|
|
11288
10664
|
} else {
|
|
11289
10665
|
const count = clearAll();
|
|
@@ -11320,7 +10696,7 @@ async function cacheListCommand(options) {
|
|
|
11320
10696
|
type: e.type,
|
|
11321
10697
|
key: e.entry.key,
|
|
11322
10698
|
age: formatAge(getAge(e.entry)),
|
|
11323
|
-
status: isFresh(e.entry) ?
|
|
10699
|
+
status: isFresh(e.entry) ? pc13.green("fresh") : pc13.yellow("expired")
|
|
11324
10700
|
}));
|
|
11325
10701
|
printTable(
|
|
11326
10702
|
[
|
|
@@ -11373,13 +10749,13 @@ async function cacheUpdateAllCommand() {
|
|
|
11373
10749
|
if (errors.length > 0) {
|
|
11374
10750
|
console.log();
|
|
11375
10751
|
for (const e of errors) {
|
|
11376
|
-
console.log(` ${
|
|
10752
|
+
console.log(` ${pc13.red("\u2717")} ${e.key}: ${pc13.dim(e.error)}`);
|
|
11377
10753
|
}
|
|
11378
10754
|
}
|
|
11379
10755
|
}
|
|
11380
10756
|
|
|
11381
10757
|
// src/commands/guide.ts
|
|
11382
|
-
import
|
|
10758
|
+
import pc14 from "picocolors";
|
|
11383
10759
|
|
|
11384
10760
|
// src/lib/guide-content.ts
|
|
11385
10761
|
var GUIDE_OVERVIEW = `# One CLI \u2014 Agent Guide
|
|
@@ -12582,14 +11958,14 @@ async function guideCommand(topic = "all") {
|
|
|
12582
11958
|
json({ topic, title, content, availableTopics });
|
|
12583
11959
|
return;
|
|
12584
11960
|
}
|
|
12585
|
-
intro(
|
|
11961
|
+
intro(pc14.bgCyan(pc14.black(" One Guide ")));
|
|
12586
11962
|
console.log();
|
|
12587
11963
|
console.log(content);
|
|
12588
|
-
console.log(
|
|
11964
|
+
console.log(pc14.dim("\u2500".repeat(60)));
|
|
12589
11965
|
console.log(
|
|
12590
|
-
|
|
11966
|
+
pc14.dim("Available topics: ") + availableTopics.map((t) => pc14.cyan(t.topic)).join(", ")
|
|
12591
11967
|
);
|
|
12592
|
-
console.log(
|
|
11968
|
+
console.log(pc14.dim(`Run ${pc14.cyan("one guide <topic>")} for a specific section.`));
|
|
12593
11969
|
}
|
|
12594
11970
|
|
|
12595
11971
|
// src/lib/platform-meta.ts
|
|
@@ -12909,24 +12285,24 @@ function buildWorkflowIdeas(connections) {
|
|
|
12909
12285
|
}
|
|
12910
12286
|
|
|
12911
12287
|
// src/commands/logout.ts
|
|
12912
|
-
import
|
|
12288
|
+
import fs11 from "fs";
|
|
12913
12289
|
import * as p8 from "@clack/prompts";
|
|
12914
|
-
function formatWhoami(config2, apiKey,
|
|
12290
|
+
function formatWhoami(config2, apiKey, pc16) {
|
|
12915
12291
|
const whoami = config2.whoami;
|
|
12916
12292
|
const env = getEnvFromApiKey(apiKey);
|
|
12917
|
-
const envLabel = env === "test" ?
|
|
12293
|
+
const envLabel = env === "test" ? pc16.yellow("test") : pc16.green("live");
|
|
12918
12294
|
const lines = [];
|
|
12919
12295
|
if (whoami) {
|
|
12920
12296
|
const contextParts = [];
|
|
12921
12297
|
if (whoami.organization) contextParts.push(whoami.organization.name);
|
|
12922
12298
|
if (whoami.project) contextParts.push(whoami.project.name);
|
|
12923
12299
|
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
12924
|
-
lines.push(`${
|
|
12925
|
-
lines.push(`${whoami.user.name} ${
|
|
12926
|
-
if (config2.apiKeyName) lines.push(`${
|
|
12300
|
+
lines.push(`${pc16.bold(scopeDisplay)} ${pc16.dim("\xB7")} ${envLabel}`);
|
|
12301
|
+
lines.push(`${whoami.user.name} ${pc16.dim(`(${whoami.user.email})`)}`);
|
|
12302
|
+
if (config2.apiKeyName) lines.push(`${pc16.dim("Key:")} ${config2.apiKeyName}`);
|
|
12927
12303
|
} else {
|
|
12928
12304
|
const keyLabel = config2.apiKeyName ?? `${apiKey.slice(0, 8)}...`;
|
|
12929
|
-
lines.push(`${
|
|
12305
|
+
lines.push(`${pc16.dim("Key:")} ${keyLabel} ${pc16.dim("\xB7")} ${envLabel}`);
|
|
12930
12306
|
}
|
|
12931
12307
|
return lines;
|
|
12932
12308
|
}
|
|
@@ -12944,18 +12320,18 @@ async function logoutCommand() {
|
|
|
12944
12320
|
const globalPath = getGlobalConfigPath();
|
|
12945
12321
|
const projectPath = getProjectConfigPath();
|
|
12946
12322
|
let cleared = false;
|
|
12947
|
-
if (
|
|
12948
|
-
|
|
12323
|
+
if (fs11.existsSync(projectPath)) {
|
|
12324
|
+
fs11.unlinkSync(projectPath);
|
|
12949
12325
|
cleared = true;
|
|
12950
12326
|
}
|
|
12951
|
-
if (
|
|
12952
|
-
|
|
12327
|
+
if (fs11.existsSync(globalPath)) {
|
|
12328
|
+
fs11.unlinkSync(globalPath);
|
|
12953
12329
|
cleared = true;
|
|
12954
12330
|
}
|
|
12955
12331
|
json({ status: cleared ? "logged_out" : "not_logged_in", message: cleared ? "Credentials cleared." : "No config found." });
|
|
12956
12332
|
return;
|
|
12957
12333
|
}
|
|
12958
|
-
const
|
|
12334
|
+
const pc16 = (await import("picocolors")).default;
|
|
12959
12335
|
const globalConfig = readGlobalConfig();
|
|
12960
12336
|
const projectConfig = readProjectConfig();
|
|
12961
12337
|
const hasGlobal = globalConfig?.apiKey != null;
|
|
@@ -12964,13 +12340,13 @@ async function logoutCommand() {
|
|
|
12964
12340
|
if (hasGlobal && hasProject) {
|
|
12965
12341
|
const infoLines = ["You are logged in with multiple configs.", ""];
|
|
12966
12342
|
if (projectConfig) {
|
|
12967
|
-
infoLines.push(`${
|
|
12968
|
-
infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey,
|
|
12343
|
+
infoLines.push(`${pc16.cyan("Local config:")}`);
|
|
12344
|
+
infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey, pc16));
|
|
12969
12345
|
infoLines.push("");
|
|
12970
12346
|
}
|
|
12971
12347
|
if (globalConfig) {
|
|
12972
|
-
infoLines.push(`${
|
|
12973
|
-
infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey,
|
|
12348
|
+
infoLines.push(`${pc16.magenta("Global config:")}`);
|
|
12349
|
+
infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey, pc16));
|
|
12974
12350
|
}
|
|
12975
12351
|
p8.note(infoLines.join("\n"));
|
|
12976
12352
|
const choice = await p8.select({
|
|
@@ -12988,14 +12364,14 @@ async function logoutCommand() {
|
|
|
12988
12364
|
targetScope = choice;
|
|
12989
12365
|
} else if (hasProject) {
|
|
12990
12366
|
const infoLines = ["You are logged in.", ""];
|
|
12991
|
-
infoLines.push(`${
|
|
12992
|
-
infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey,
|
|
12367
|
+
infoLines.push(`${pc16.dim("Stored in")} ${pc16.cyan("local config")}`);
|
|
12368
|
+
infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey, pc16));
|
|
12993
12369
|
p8.note(infoLines.join("\n"));
|
|
12994
12370
|
targetScope = "project";
|
|
12995
12371
|
} else if (hasGlobal) {
|
|
12996
12372
|
const infoLines = ["You are logged in.", ""];
|
|
12997
|
-
infoLines.push(`${
|
|
12998
|
-
infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey,
|
|
12373
|
+
infoLines.push(`${pc16.dim("Stored in")} ${pc16.magenta("global config")}`);
|
|
12374
|
+
infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey, pc16));
|
|
12999
12375
|
p8.note(infoLines.join("\n"));
|
|
13000
12376
|
targetScope = "global";
|
|
13001
12377
|
} else {
|
|
@@ -13018,11 +12394,11 @@ async function logoutCommand() {
|
|
|
13018
12394
|
}
|
|
13019
12395
|
if (targetScope === "project" || targetScope === "both") {
|
|
13020
12396
|
const projectPath = getProjectConfigPath();
|
|
13021
|
-
if (
|
|
12397
|
+
if (fs11.existsSync(projectPath)) fs11.unlinkSync(projectPath);
|
|
13022
12398
|
}
|
|
13023
12399
|
if (targetScope === "global" || targetScope === "both") {
|
|
13024
12400
|
const globalPath = getGlobalConfigPath();
|
|
13025
|
-
if (
|
|
12401
|
+
if (fs11.existsSync(globalPath)) fs11.unlinkSync(globalPath);
|
|
13026
12402
|
}
|
|
13027
12403
|
p8.log.success("Credentials cleared.");
|
|
13028
12404
|
p8.log.info("Your API key is still active. Manage keys at app.withone.ai/settings");
|
|
@@ -13031,9 +12407,9 @@ async function logoutCommand() {
|
|
|
13031
12407
|
|
|
13032
12408
|
// src/lib/project-skills.ts
|
|
13033
12409
|
import crypto2 from "crypto";
|
|
13034
|
-
import
|
|
13035
|
-
import
|
|
13036
|
-
import
|
|
12410
|
+
import fs12 from "fs";
|
|
12411
|
+
import os2 from "os";
|
|
12412
|
+
import path10 from "path";
|
|
13037
12413
|
import zlib from "zlib";
|
|
13038
12414
|
var OPTIONAL_SKILLS = [
|
|
13039
12415
|
{
|
|
@@ -13065,27 +12441,27 @@ function findAgentTarget(id) {
|
|
|
13065
12441
|
return SKILL_AGENT_TARGETS.find((a) => a.id === id.trim().toLowerCase());
|
|
13066
12442
|
}
|
|
13067
12443
|
function findProjectRoot(start) {
|
|
13068
|
-
let dir =
|
|
12444
|
+
let dir = path10.resolve(start);
|
|
13069
12445
|
for (; ; ) {
|
|
13070
|
-
if (
|
|
13071
|
-
const parent =
|
|
12446
|
+
if (fs12.existsSync(path10.join(dir, "package.json")) || fs12.existsSync(path10.join(dir, ".git"))) return dir;
|
|
12447
|
+
const parent = path10.dirname(dir);
|
|
13072
12448
|
if (parent === dir) return null;
|
|
13073
12449
|
dir = parent;
|
|
13074
12450
|
}
|
|
13075
12451
|
}
|
|
13076
12452
|
function findInstalledPackage(start, packageName) {
|
|
13077
|
-
let dir =
|
|
12453
|
+
let dir = path10.resolve(start);
|
|
13078
12454
|
for (; ; ) {
|
|
13079
|
-
const pkgDir =
|
|
13080
|
-
const manifest =
|
|
13081
|
-
if (
|
|
12455
|
+
const pkgDir = path10.join(dir, "node_modules", ...packageName.split("/"));
|
|
12456
|
+
const manifest = path10.join(pkgDir, "package.json");
|
|
12457
|
+
if (fs12.existsSync(manifest)) {
|
|
13082
12458
|
try {
|
|
13083
|
-
const { version: version2 } = JSON.parse(
|
|
12459
|
+
const { version: version2 } = JSON.parse(fs12.readFileSync(manifest, "utf-8"));
|
|
13084
12460
|
if (version2) return { dir: pkgDir, version: version2 };
|
|
13085
12461
|
} catch {
|
|
13086
12462
|
}
|
|
13087
12463
|
}
|
|
13088
|
-
const parent =
|
|
12464
|
+
const parent = path10.dirname(dir);
|
|
13089
12465
|
if (parent === dir) return null;
|
|
13090
12466
|
dir = parent;
|
|
13091
12467
|
}
|
|
@@ -13099,8 +12475,8 @@ var SkillSourceError = class extends Error {
|
|
|
13099
12475
|
function projectSkillSource(skill, projectDir) {
|
|
13100
12476
|
const installed = findInstalledPackage(projectDir, skill.packageName);
|
|
13101
12477
|
if (!installed) return null;
|
|
13102
|
-
const dir =
|
|
13103
|
-
if (!
|
|
12478
|
+
const dir = path10.join(installed.dir, ...skill.packagePath.split("/"));
|
|
12479
|
+
if (!fs12.existsSync(path10.join(dir, "SKILL.md"))) {
|
|
13104
12480
|
throw new SkillSourceError(
|
|
13105
12481
|
`${skill.packageName} ${installed.version} does not include the ${skill.title} skill. Upgrade it: npm install ${skill.packageName}@latest`,
|
|
13106
12482
|
"skill-missing"
|
|
@@ -13143,11 +12519,11 @@ async function registrySkillSource(skill, fetchImpl = fetch) {
|
|
|
13143
12519
|
if (!files.some((f) => f.path === "SKILL.md")) {
|
|
13144
12520
|
throw new SkillSourceError(`${skill.packageName}@${version2} does not include the ${skill.title} skill.`, "not-in-package");
|
|
13145
12521
|
}
|
|
13146
|
-
const tmp =
|
|
12522
|
+
const tmp = fs12.mkdtempSync(path10.join(os2.tmpdir(), "one-skill-"));
|
|
13147
12523
|
for (const file of files) {
|
|
13148
|
-
const dest =
|
|
13149
|
-
|
|
13150
|
-
|
|
12524
|
+
const dest = path10.join(tmp, ...file.path.split("/"));
|
|
12525
|
+
fs12.mkdirSync(path10.dirname(dest), { recursive: true });
|
|
12526
|
+
fs12.writeFileSync(dest, file.data);
|
|
13151
12527
|
}
|
|
13152
12528
|
return {
|
|
13153
12529
|
kind: "registry",
|
|
@@ -13156,7 +12532,7 @@ async function registrySkillSource(skill, fetchImpl = fetch) {
|
|
|
13156
12532
|
origin: tarball,
|
|
13157
12533
|
cleanup: () => {
|
|
13158
12534
|
try {
|
|
13159
|
-
|
|
12535
|
+
fs12.rmSync(tmp, { recursive: true, force: true });
|
|
13160
12536
|
} catch {
|
|
13161
12537
|
}
|
|
13162
12538
|
}
|
|
@@ -13200,7 +12576,7 @@ function readTarEntries(tar, prefix) {
|
|
|
13200
12576
|
if ((type === "0" || type === "\0") && full.startsWith(prefix)) {
|
|
13201
12577
|
const rel = full.slice(prefix.length);
|
|
13202
12578
|
const parts = rel.split("/");
|
|
13203
|
-
if (rel && !
|
|
12579
|
+
if (rel && !path10.isAbsolute(rel) && !parts.includes("..") && !parts.includes("")) {
|
|
13204
12580
|
out.push({ path: rel, data: Buffer.from(body) });
|
|
13205
12581
|
}
|
|
13206
12582
|
}
|
|
@@ -13211,11 +12587,11 @@ function readTarEntries(tar, prefix) {
|
|
|
13211
12587
|
}
|
|
13212
12588
|
var SKILL_STAMP = ".one-skill.json";
|
|
13213
12589
|
function canonicalSkillDir(skill, plan) {
|
|
13214
|
-
return
|
|
12590
|
+
return path10.join(plan.root, ...UNIVERSAL_PROJECT_DIR.split("/"), skill.dirName);
|
|
13215
12591
|
}
|
|
13216
12592
|
function readStamp(dir) {
|
|
13217
12593
|
try {
|
|
13218
|
-
return JSON.parse(
|
|
12594
|
+
return JSON.parse(fs12.readFileSync(path10.join(dir, SKILL_STAMP), "utf-8"));
|
|
13219
12595
|
} catch {
|
|
13220
12596
|
return null;
|
|
13221
12597
|
}
|
|
@@ -13225,9 +12601,9 @@ function resolveAgentFolders(plan) {
|
|
|
13225
12601
|
const chosen = SKILL_AGENT_TARGETS.filter((agent) => {
|
|
13226
12602
|
if (explicit) return plan.agents.includes(agent.id);
|
|
13227
12603
|
if (plan.scope === "global") {
|
|
13228
|
-
return
|
|
12604
|
+
return fs12.existsSync(path10.join(plan.root, path10.dirname(agent.homeDir)));
|
|
13229
12605
|
}
|
|
13230
|
-
return agent.projectMarker === null ||
|
|
12606
|
+
return agent.projectMarker === null || fs12.existsSync(path10.join(plan.root, agent.projectMarker));
|
|
13231
12607
|
});
|
|
13232
12608
|
const readers = [];
|
|
13233
12609
|
const byDir = /* @__PURE__ */ new Map();
|
|
@@ -13242,33 +12618,33 @@ function resolveAgentFolders(plan) {
|
|
|
13242
12618
|
return { readers, folders: [...byDir].map(([dir, agents]) => ({ dir, agents })) };
|
|
13243
12619
|
}
|
|
13244
12620
|
function copyDir(src, dest) {
|
|
13245
|
-
|
|
13246
|
-
for (const entry of
|
|
12621
|
+
fs12.mkdirSync(dest, { recursive: true });
|
|
12622
|
+
for (const entry of fs12.readdirSync(src, { withFileTypes: true })) {
|
|
13247
12623
|
if (entry.name === SKILL_STAMP) continue;
|
|
13248
|
-
const from =
|
|
13249
|
-
const to =
|
|
12624
|
+
const from = path10.join(src, entry.name);
|
|
12625
|
+
const to = path10.join(dest, entry.name);
|
|
13250
12626
|
if (entry.isDirectory()) copyDir(from, to);
|
|
13251
|
-
else
|
|
12627
|
+
else fs12.copyFileSync(from, to);
|
|
13252
12628
|
}
|
|
13253
12629
|
}
|
|
13254
12630
|
function removePath(target) {
|
|
13255
12631
|
try {
|
|
13256
|
-
const stat =
|
|
13257
|
-
if (stat.isSymbolicLink())
|
|
13258
|
-
else
|
|
12632
|
+
const stat = fs12.lstatSync(target);
|
|
12633
|
+
if (stat.isSymbolicLink()) fs12.unlinkSync(target);
|
|
12634
|
+
else fs12.rmSync(target, { recursive: true, force: true });
|
|
13259
12635
|
} catch {
|
|
13260
12636
|
}
|
|
13261
12637
|
}
|
|
13262
12638
|
function linkDir(target, linkPath) {
|
|
13263
12639
|
removePath(linkPath);
|
|
13264
|
-
|
|
12640
|
+
fs12.mkdirSync(path10.dirname(linkPath), { recursive: true });
|
|
13265
12641
|
try {
|
|
13266
|
-
|
|
12642
|
+
fs12.symlinkSync(path10.relative(path10.dirname(linkPath), target), linkPath, "dir");
|
|
13267
12643
|
return "symlink";
|
|
13268
12644
|
} catch {
|
|
13269
12645
|
}
|
|
13270
12646
|
try {
|
|
13271
|
-
|
|
12647
|
+
fs12.symlinkSync(target, linkPath, "junction");
|
|
13272
12648
|
return "junction";
|
|
13273
12649
|
} catch {
|
|
13274
12650
|
}
|
|
@@ -13299,17 +12675,17 @@ function installSkill(skill, source, plan, cliVersion2) {
|
|
|
13299
12675
|
installedBy: `@withone/cli@${cliVersion2}`,
|
|
13300
12676
|
installedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
13301
12677
|
};
|
|
13302
|
-
|
|
12678
|
+
fs12.writeFileSync(path10.join(canonical, SKILL_STAMP), JSON.stringify(stamp, null, 2) + "\n");
|
|
13303
12679
|
return { skill, version: source.version, source: source.kind, origin: source.origin, scope: plan.scope, root: plan.root, canonical, readers, links };
|
|
13304
12680
|
}
|
|
13305
12681
|
function removeSkill(skill, plan) {
|
|
13306
12682
|
const canonical = canonicalSkillDir(skill, plan);
|
|
13307
12683
|
const stamp = readStamp(canonical);
|
|
13308
|
-
if (!stamp && !
|
|
12684
|
+
if (!stamp && !fs12.existsSync(path10.join(canonical, "SKILL.md"))) return { removed: false, paths: [] };
|
|
13309
12685
|
const paths = [];
|
|
13310
12686
|
for (const link of stamp?.links ?? []) {
|
|
13311
12687
|
const full = fromStamp(plan.root, link.path);
|
|
13312
|
-
if (
|
|
12688
|
+
if (fs12.existsSync(full) || isDanglingLink(full)) {
|
|
13313
12689
|
removePath(full);
|
|
13314
12690
|
paths.push(full);
|
|
13315
12691
|
}
|
|
@@ -13322,18 +12698,18 @@ function toPosix(p9) {
|
|
|
13322
12698
|
return p9.split("\\").join("/");
|
|
13323
12699
|
}
|
|
13324
12700
|
function fromStamp(root, rel) {
|
|
13325
|
-
return
|
|
12701
|
+
return path10.join(root, ...toPosix(rel).split("/"));
|
|
13326
12702
|
}
|
|
13327
12703
|
function isDanglingLink(p9) {
|
|
13328
12704
|
try {
|
|
13329
|
-
return
|
|
12705
|
+
return fs12.lstatSync(p9).isSymbolicLink();
|
|
13330
12706
|
} catch {
|
|
13331
12707
|
return false;
|
|
13332
12708
|
}
|
|
13333
12709
|
}
|
|
13334
12710
|
function installedSkill(skill, plan) {
|
|
13335
12711
|
const canonical = canonicalSkillDir(skill, plan);
|
|
13336
|
-
if (!
|
|
12712
|
+
if (!fs12.existsSync(path10.join(canonical, "SKILL.md"))) return null;
|
|
13337
12713
|
const stamp = readStamp(canonical);
|
|
13338
12714
|
return { scope: plan.scope, root: plan.root, canonical, version: stamp?.version ?? null, source: stamp?.source ?? null, links: stamp?.links ?? [] };
|
|
13339
12715
|
}
|
|
@@ -13342,7 +12718,7 @@ function globalRoot() {
|
|
|
13342
12718
|
}
|
|
13343
12719
|
function refreshProjectSkills(cwd, cliVersion2) {
|
|
13344
12720
|
const root = findProjectRoot(cwd);
|
|
13345
|
-
if (!root ||
|
|
12721
|
+
if (!root || path10.resolve(root) === path10.resolve(homeDir())) return [];
|
|
13346
12722
|
const results = [];
|
|
13347
12723
|
for (const skill of OPTIONAL_SKILLS) {
|
|
13348
12724
|
const canonical = canonicalSkillDir(skill, { scope: "project", root });
|
|
@@ -13365,8 +12741,8 @@ function refreshProjectSkills(cwd, cliVersion2) {
|
|
|
13365
12741
|
}
|
|
13366
12742
|
|
|
13367
12743
|
// src/commands/skills.ts
|
|
13368
|
-
import
|
|
13369
|
-
import
|
|
12744
|
+
import path11 from "path";
|
|
12745
|
+
import pc15 from "picocolors";
|
|
13370
12746
|
function requireSkill(name) {
|
|
13371
12747
|
const skill = findOptionalSkill(name);
|
|
13372
12748
|
if (!skill) {
|
|
@@ -13389,7 +12765,7 @@ function resolvePlan(options) {
|
|
|
13389
12765
|
const agents = parseAgents(options.agents);
|
|
13390
12766
|
if (options.global) return { scope: "global", root: globalRoot(), agents };
|
|
13391
12767
|
const root = findProjectRoot(process.cwd());
|
|
13392
|
-
if (!root ||
|
|
12768
|
+
if (!root || path11.resolve(root) === path11.resolve(homeDir())) {
|
|
13393
12769
|
error("No project here: run this inside your app (a folder with package.json or .git), or pass --global.");
|
|
13394
12770
|
}
|
|
13395
12771
|
return { scope: "project", root, agents };
|
|
@@ -13405,7 +12781,7 @@ async function resolveSource(skill, plan) {
|
|
|
13405
12781
|
}
|
|
13406
12782
|
}
|
|
13407
12783
|
function display(p9, root) {
|
|
13408
|
-
const rel =
|
|
12784
|
+
const rel = path11.relative(root, p9);
|
|
13409
12785
|
return rel && !rel.startsWith("..") ? rel : p9;
|
|
13410
12786
|
}
|
|
13411
12787
|
function report(command, result, packageInProject) {
|
|
@@ -13421,7 +12797,7 @@ function report(command, result, packageInProject) {
|
|
|
13421
12797
|
root: result.root,
|
|
13422
12798
|
installedTo: [
|
|
13423
12799
|
{ path: result.canonical, kind: "folder", agents: result.readers },
|
|
13424
|
-
...result.links.map((l) => ({ path:
|
|
12800
|
+
...result.links.map((l) => ({ path: path11.join(result.root, ...l.path.split("/")), kind: l.kind, agents: l.agents }))
|
|
13425
12801
|
],
|
|
13426
12802
|
next: nextSteps(result, packageInProject)
|
|
13427
12803
|
});
|
|
@@ -13429,20 +12805,20 @@ function report(command, result, packageInProject) {
|
|
|
13429
12805
|
}
|
|
13430
12806
|
const scopeLabel2 = result.scope === "project" ? "this project" : "every project on this machine";
|
|
13431
12807
|
console.log();
|
|
13432
|
-
console.log(` ${
|
|
12808
|
+
console.log(` ${pc15.green("\u2713")} ${pc15.bold(`${result.skill.title} skill ${result.version}`)} installed for ${scopeLabel2}`);
|
|
13433
12809
|
console.log();
|
|
13434
|
-
const from = result.source === "project" ? `${where(result.origin)} ${
|
|
13435
|
-
console.log(` ${
|
|
12810
|
+
const from = result.source === "project" ? `${where(result.origin)} ${pc15.dim("(the version your code uses)")}` : `npm ${pc15.dim(result.scope === "project" ? `(latest ${result.skill.packageName}; not installed in this project yet)` : `(latest ${result.skill.packageName})`)}`;
|
|
12811
|
+
console.log(` ${pc15.dim("From")} ${from}`);
|
|
13436
12812
|
const rows = [
|
|
13437
12813
|
{ path: where(result.canonical), agents: result.readers },
|
|
13438
|
-
...result.links.map((l) => ({ path: `${l.path}${l.kind === "copy" ?
|
|
12814
|
+
...result.links.map((l) => ({ path: `${l.path}${l.kind === "copy" ? pc15.dim(" (copy)") : ""}`, agents: l.agents }))
|
|
13439
12815
|
];
|
|
13440
12816
|
rows.forEach((row, i) => {
|
|
13441
|
-
const agents = row.agents.length ?
|
|
13442
|
-
console.log(` ${
|
|
12817
|
+
const agents = row.agents.length ? pc15.dim(row.agents.join(", ")) : pc15.dim("shared copy the links point to");
|
|
12818
|
+
console.log(` ${pc15.dim(i === 0 ? "To " : " ")} ${row.path} ${agents}`);
|
|
13443
12819
|
});
|
|
13444
12820
|
console.log();
|
|
13445
|
-
console.log(` ${
|
|
12821
|
+
console.log(` ${pc15.bold("Next")}`);
|
|
13446
12822
|
nextSteps(result, packageInProject).forEach((step, i) => console.log(` ${i + 1}. ${step}`));
|
|
13447
12823
|
console.log();
|
|
13448
12824
|
}
|
|
@@ -13505,7 +12881,7 @@ async function skillsUpdateCommand(name, options) {
|
|
|
13505
12881
|
console.log("No optional skills are installed here. See: one skills list");
|
|
13506
12882
|
return;
|
|
13507
12883
|
}
|
|
13508
|
-
for (const r of updated) console.log(` ${
|
|
12884
|
+
for (const r of updated) console.log(` ${pc15.green("\u2713")} ${r.skill.title} skill ${r.version} ${pc15.dim(display(r.canonical, r.root))}`);
|
|
13509
12885
|
}
|
|
13510
12886
|
async function skillsRemoveCommand(name, options) {
|
|
13511
12887
|
const skill = requireSkill(name);
|
|
@@ -13519,12 +12895,12 @@ async function skillsRemoveCommand(name, options) {
|
|
|
13519
12895
|
console.log(`${skill.title} skill is not installed ${plan.scope === "global" ? "globally" : "in this project"}.`);
|
|
13520
12896
|
return;
|
|
13521
12897
|
}
|
|
13522
|
-
console.log(` ${
|
|
13523
|
-
for (const p9 of result.paths) console.log(` ${
|
|
12898
|
+
console.log(` ${pc15.green("\u2713")} Removed the ${skill.title} skill`);
|
|
12899
|
+
for (const p9 of result.paths) console.log(` ${pc15.dim(display(p9, plan.root))}`);
|
|
13524
12900
|
}
|
|
13525
12901
|
async function skillsListCommand() {
|
|
13526
12902
|
const projectRoot = findProjectRoot(process.cwd());
|
|
13527
|
-
const inProject = projectRoot &&
|
|
12903
|
+
const inProject = projectRoot && path11.resolve(projectRoot) !== path11.resolve(homeDir()) ? projectRoot : null;
|
|
13528
12904
|
const optional = OPTIONAL_SKILLS.map((skill) => {
|
|
13529
12905
|
const project = inProject ? installedSkill(skill, { scope: "project", root: inProject }) : null;
|
|
13530
12906
|
const global = installedSkill(skill, { scope: "global", root: globalRoot() });
|
|
@@ -13552,19 +12928,19 @@ async function skillsListCommand() {
|
|
|
13552
12928
|
return;
|
|
13553
12929
|
}
|
|
13554
12930
|
console.log();
|
|
13555
|
-
console.log(` ${
|
|
12931
|
+
console.log(` ${pc15.bold("one")} ${oneSkill.installed ? pc15.green(`installed ${oneSkill.version ?? ""}`.trim()) : pc15.yellow("not installed")} ${pc15.dim("managed by one init")}`);
|
|
13556
12932
|
for (const s of optional) {
|
|
13557
|
-
const state = s.project ?
|
|
13558
|
-
console.log(` ${
|
|
13559
|
-
console.log(` ${" ".repeat(8)} ${
|
|
12933
|
+
const state = s.project ? pc15.green(`project ${s.project.version ?? ""}`.trim()) + (s.project.upToDate ? "" : pc15.yellow(` (package is ${s.packageInProject}: run one skills update ${s.skill})`)) : s.global ? pc15.green(`global ${s.global.version ?? ""}`.trim()) : pc15.dim(`not installed \u2014 one skills add ${s.skill}`);
|
|
12934
|
+
console.log(` ${pc15.bold(s.skill.padEnd(8))} ${state}`);
|
|
12935
|
+
console.log(` ${" ".repeat(8)} ${pc15.dim(s.description)}`);
|
|
13560
12936
|
}
|
|
13561
12937
|
console.log();
|
|
13562
12938
|
}
|
|
13563
12939
|
|
|
13564
12940
|
// src/cli.ts
|
|
13565
12941
|
silenceWarningsInAgentMode();
|
|
13566
|
-
var
|
|
13567
|
-
var { version } =
|
|
12942
|
+
var require2 = createRequire(import.meta.url);
|
|
12943
|
+
var { version } = require2("../package.json");
|
|
13568
12944
|
var program = new Command();
|
|
13569
12945
|
program.name("one").option("--agent", "Machine-readable JSON output (no colors, spinners, or prompts)").description(`One CLI \u2014 Connect AI agents to 750+ platforms through one interface.
|
|
13570
12946
|
|
|
@@ -13802,8 +13178,8 @@ config.command("reset").description("Remove the project config for the current d
|
|
|
13802
13178
|
return;
|
|
13803
13179
|
}
|
|
13804
13180
|
}
|
|
13805
|
-
const
|
|
13806
|
-
|
|
13181
|
+
const fs14 = await import("fs");
|
|
13182
|
+
fs14.unlinkSync(globalPath);
|
|
13807
13183
|
if (isAgentMode()) {
|
|
13808
13184
|
json({ deleted: true, scope: "global" });
|
|
13809
13185
|
} else {
|
|
@@ -13820,15 +13196,15 @@ config.command("reset").description("Remove the project config for the current d
|
|
|
13820
13196
|
}
|
|
13821
13197
|
return;
|
|
13822
13198
|
}
|
|
13823
|
-
const
|
|
13824
|
-
const configContent =
|
|
13825
|
-
|
|
13199
|
+
const fs13 = await import("fs");
|
|
13200
|
+
const configContent = fs13.readFileSync(resolved.path, "utf-8");
|
|
13201
|
+
fs13.unlinkSync(resolved.path);
|
|
13826
13202
|
const next = resolveConfig();
|
|
13827
|
-
|
|
13828
|
-
|
|
13203
|
+
fs13.mkdirSync(path12.dirname(resolved.path), { recursive: true });
|
|
13204
|
+
fs13.writeFileSync(resolved.path, configContent);
|
|
13829
13205
|
let fallbackLabel;
|
|
13830
13206
|
if (next.scope === "project") {
|
|
13831
|
-
fallbackLabel = `parent project config (${
|
|
13207
|
+
fallbackLabel = `parent project config (${path12.basename(next.projectRoot)})`;
|
|
13832
13208
|
} else if (next.scope === "global") {
|
|
13833
13209
|
fallbackLabel = "global config";
|
|
13834
13210
|
} else {
|
|
@@ -13837,7 +13213,7 @@ config.command("reset").description("Remove the project config for the current d
|
|
|
13837
13213
|
if (!isAgentMode()) {
|
|
13838
13214
|
const p9 = await import("@clack/prompts");
|
|
13839
13215
|
const confirmed = await p9.confirm({
|
|
13840
|
-
message: `Delete project config for ${
|
|
13216
|
+
message: `Delete project config for ${path12.basename(resolved.projectRoot)}? Will fall back to ${fallbackLabel}.`,
|
|
13841
13217
|
initialValue: false
|
|
13842
13218
|
});
|
|
13843
13219
|
if (p9.isCancel(confirmed) || !confirmed) {
|
|
@@ -13845,9 +13221,9 @@ config.command("reset").description("Remove the project config for the current d
|
|
|
13845
13221
|
return;
|
|
13846
13222
|
}
|
|
13847
13223
|
}
|
|
13848
|
-
|
|
13224
|
+
fs13.unlinkSync(resolved.path);
|
|
13849
13225
|
try {
|
|
13850
|
-
|
|
13226
|
+
fs13.rmdirSync(path12.dirname(resolved.path));
|
|
13851
13227
|
} catch {
|
|
13852
13228
|
}
|
|
13853
13229
|
if (isAgentMode()) {
|
|
@@ -14010,22 +13386,22 @@ program.command("whoami").description("Show the user, organization, and project
|
|
|
14010
13386
|
});
|
|
14011
13387
|
return;
|
|
14012
13388
|
}
|
|
14013
|
-
const
|
|
13389
|
+
const pc16 = (await import("picocolors")).default;
|
|
14014
13390
|
const contextParts = [];
|
|
14015
13391
|
if (whoami.organization) contextParts.push(whoami.organization.name);
|
|
14016
13392
|
if (whoami.project) contextParts.push(whoami.project.name);
|
|
14017
13393
|
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
14018
|
-
const envLabel = env === "test" ?
|
|
14019
|
-
const configLabel = configScope === "project" ?
|
|
13394
|
+
const envLabel = env === "test" ? pc16.yellow("test") : pc16.green("live");
|
|
13395
|
+
const configLabel = configScope === "project" ? pc16.cyan("project config") : pc16.magenta("global config");
|
|
14020
13396
|
console.log();
|
|
14021
|
-
console.log(` ${
|
|
14022
|
-
console.log(` ${whoami.user.name} ${
|
|
14023
|
-
if (keyName) console.log(` ${
|
|
14024
|
-
if (whoami.organization) console.log(` ${
|
|
14025
|
-
if (whoami.project) console.log(` ${
|
|
13397
|
+
console.log(` ${pc16.bold(scopeDisplay)} ${pc16.dim("\xB7")} ${envLabel}`);
|
|
13398
|
+
console.log(` ${whoami.user.name} ${pc16.dim(`(${whoami.user.email})`)}`);
|
|
13399
|
+
if (keyName) console.log(` ${pc16.dim("Key:")} ${keyName}`);
|
|
13400
|
+
if (whoami.organization) console.log(` ${pc16.dim("Org:")} ${whoami.organization.name} ${pc16.dim(`(${whoami.organization.id})`)}`);
|
|
13401
|
+
if (whoami.project) console.log(` ${pc16.dim("Project:")} ${whoami.project.name} ${pc16.dim(`(${whoami.project.id})`)}`);
|
|
14026
13402
|
console.log();
|
|
14027
|
-
console.log(` ${
|
|
14028
|
-
console.log(` ${
|
|
13403
|
+
console.log(` ${pc16.dim("Using")} ${configLabel}`);
|
|
13404
|
+
console.log(` ${pc16.dim("API:")} ${apiBase}`);
|
|
14029
13405
|
console.log();
|
|
14030
13406
|
});
|
|
14031
13407
|
program.command("add [platform]").description("Shortcut for: connection add").option("--tag <name>", "Tag the new connection (disambiguates multiple connections per platform in sync/flow profiles)").action(async (platform, options) => {
|