@withone/cli 2.9.2 → 2.10.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/dist/index.js CHANGED
@@ -42,7 +42,7 @@ import {
42
42
  validateActionInput,
43
43
  walkSteps,
44
44
  writeCache
45
- } from "./chunk-UP2L4XJH.js";
45
+ } from "./chunk-5CPQHXTO.js";
46
46
  import {
47
47
  memSqlCommand
48
48
  } from "./chunk-O3HDWHHS.js";
@@ -152,7 +152,7 @@ import {
152
152
 
153
153
  // src/cli.ts
154
154
  import { createRequire } from "module";
155
- import path12 from "path";
155
+ import path14 from "path";
156
156
  import { Command } from "commander";
157
157
 
158
158
  // src/commands/init.ts
@@ -180,6 +180,27 @@ function getConnectionUrl(platform, params) {
180
180
  function getApiKeyUrl() {
181
181
  return `${oneAppUrl()}/settings/api-keys`;
182
182
  }
183
+ function connectSetupParams(scope, extra) {
184
+ const params = new URLSearchParams();
185
+ if (scope.orgId) params.set("orgId", scope.orgId);
186
+ if (scope.projectId) params.set("projectId", scope.projectId);
187
+ if (scope.envFile) params.set("env", scope.envFile);
188
+ for (const [key, value] of extra) if (value) params.set(key, value);
189
+ const qs = params.toString();
190
+ return qs ? `?${qs}` : "";
191
+ }
192
+ function getConnectSetupUrl(opts) {
193
+ const target = opts.clientId ? encodeURIComponent(opts.clientId) : "new";
194
+ const qs = connectSetupParams(opts, [
195
+ ["set", opts.permissionSetId],
196
+ ["port", String(opts.port)],
197
+ ["state", opts.state]
198
+ ]);
199
+ return `${oneAppUrl()}/cli/connect/${target}${qs}#z=${opts.handoff}`;
200
+ }
201
+ function getConnectDoneUrl(clientId, outcome, scope) {
202
+ return `${oneAppUrl()}/cli/connect/${encodeURIComponent(clientId)}${connectSetupParams(scope, [["outcome", outcome]])}`;
203
+ }
183
204
  async function openConnectionPage(platform, params) {
184
205
  await open(getConnectionUrl(platform, params));
185
206
  }
@@ -1065,25 +1086,25 @@ async function loginCommand() {
1065
1086
  let targetScope = "global";
1066
1087
  const existingKey = getApiKey();
1067
1088
  if (existingKey) {
1068
- const pc17 = (await import("picocolors")).default;
1089
+ const pc18 = (await import("picocolors")).default;
1069
1090
  const resolved = resolveConfig();
1070
1091
  const whoami2 = resolved.config?.whoami;
1071
1092
  const env2 = getEnvFromApiKey(existingKey);
1072
- const envLabel2 = env2 === "test" ? pc17.yellow("test") : pc17.green("live");
1073
- const currentScope = resolved.scope === "project" ? pc17.cyan("local config") : pc17.magenta("global config");
1093
+ const envLabel2 = env2 === "test" ? pc18.yellow("test") : pc18.green("live");
1094
+ const currentScope = resolved.scope === "project" ? pc18.cyan("local config") : pc18.magenta("global config");
1074
1095
  const lines = ["You are already logged in.", ""];
1075
1096
  if (whoami2) {
1076
1097
  const contextParts2 = [];
1077
1098
  if (whoami2.organization) contextParts2.push(whoami2.organization.name);
1078
1099
  if (whoami2.project) contextParts2.push(whoami2.project.name);
1079
1100
  const scopeDisplay2 = contextParts2.length > 0 ? contextParts2.join(" / ") : "Personal";
1080
- lines.push(`${pc17.bold(scopeDisplay2)} ${pc17.dim("\xB7")} ${envLabel2}`);
1081
- lines.push(`${whoami2.user.name} ${pc17.dim(`(${whoami2.user.email})`)}`);
1082
- if (whoami2.organization) lines.push(`${pc17.dim("Org:")} ${whoami2.organization.name}`);
1083
- if (whoami2.project) lines.push(`${pc17.dim("Project:")} ${whoami2.project.name}`);
1101
+ lines.push(`${pc18.bold(scopeDisplay2)} ${pc18.dim("\xB7")} ${envLabel2}`);
1102
+ lines.push(`${whoami2.user.name} ${pc18.dim(`(${whoami2.user.email})`)}`);
1103
+ if (whoami2.organization) lines.push(`${pc18.dim("Org:")} ${whoami2.organization.name}`);
1104
+ if (whoami2.project) lines.push(`${pc18.dim("Project:")} ${whoami2.project.name}`);
1084
1105
  }
1085
1106
  lines.push("");
1086
- lines.push(`${pc17.dim("Stored in")} ${currentScope}`);
1107
+ lines.push(`${pc18.dim("Stored in")} ${currentScope}`);
1087
1108
  p2.note(lines.join("\n"));
1088
1109
  const scopeChoice = await p2.select({
1089
1110
  message: "Where would you like to log in?",
@@ -1102,42 +1123,42 @@ async function loginCommand() {
1102
1123
  if (!result) return;
1103
1124
  const { apiKey, whoami, keyName, grant, knowledgeOnly } = result;
1104
1125
  saveCredentials(apiKey, targetScope, { keyName, whoami, knowledgeOnly });
1105
- const pc16 = (await import("picocolors")).default;
1126
+ const pc17 = (await import("picocolors")).default;
1106
1127
  const env = getEnvFromApiKey(apiKey);
1107
1128
  const contextParts = [];
1108
1129
  if (whoami.organization) contextParts.push(whoami.organization.name);
1109
1130
  if (whoami.project) contextParts.push(whoami.project.name);
1110
1131
  const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
1111
- const envLabel = env === "test" ? pc16.yellow("test") : pc16.green("live");
1112
- const configLabel = targetScope === "project" ? pc16.cyan("local config") : pc16.magenta("global config");
1132
+ const envLabel = env === "test" ? pc17.yellow("test") : pc17.green("live");
1133
+ const configLabel = targetScope === "project" ? pc17.cyan("local config") : pc17.magenta("global config");
1113
1134
  const infoLines = [
1114
- `${pc16.bold(scopeDisplay)} ${pc16.dim("\xB7")} ${envLabel}`,
1115
- `${whoami.user.name} ${pc16.dim(`(${whoami.user.email})`)}`
1135
+ `${pc17.bold(scopeDisplay)} ${pc17.dim("\xB7")} ${envLabel}`,
1136
+ `${whoami.user.name} ${pc17.dim(`(${whoami.user.email})`)}`
1116
1137
  ];
1117
- if (keyName) infoLines.push(`${pc16.dim("Key:")} ${keyName}`);
1118
- infoLines.push(...grantNoteLines(grant, pc16.dim("Access:")));
1119
- if (whoami.organization) infoLines.push(`${pc16.dim("Org:")} ${whoami.organization.name}`);
1120
- if (whoami.project) infoLines.push(`${pc16.dim("Project:")} ${whoami.project.name}`);
1138
+ if (keyName) infoLines.push(`${pc17.dim("Key:")} ${keyName}`);
1139
+ infoLines.push(...grantNoteLines(grant, pc17.dim("Access:")));
1140
+ if (whoami.organization) infoLines.push(`${pc17.dim("Org:")} ${whoami.organization.name}`);
1141
+ if (whoami.project) infoLines.push(`${pc17.dim("Project:")} ${whoami.project.name}`);
1121
1142
  infoLines.push("");
1122
- infoLines.push(`${pc16.dim("Stored in")} ${configLabel}`);
1143
+ infoLines.push(`${pc17.dim("Stored in")} ${configLabel}`);
1123
1144
  p2.note(infoLines.join("\n"), "Logged in");
1124
1145
  console.log();
1125
- console.log(` ${pc16.dim("Next steps:")}`);
1126
- console.log(` ${pc16.cyan("one add <platform>")} ${pc16.dim("\u2014")} Connect a platform (e.g. gmail, slack, stripe)`);
1146
+ console.log(` ${pc17.dim("Next steps:")}`);
1147
+ console.log(` ${pc17.cyan("one add <platform>")} ${pc17.dim("\u2014")} Connect a platform (e.g. gmail, slack, stripe)`);
1127
1148
  console.log();
1128
- console.log(pc16.bold(" Copy-paste this to your AI agent:"));
1149
+ console.log(pc17.bold(" Copy-paste this to your AI agent:"));
1129
1150
  console.log();
1130
- 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"));
1131
- console.log(pc16.cyan(" \u2502"));
1132
- console.log(pc16.cyan(" \u2502 The One CLI (`one`) is now installed on this machine. It"));
1133
- console.log(pc16.cyan(" \u2502 lets you interact with 1000+ third-party platforms (Gmail,"));
1134
- console.log(pc16.cyan(" \u2502 Slack, Shopify, HubSpot, Stripe, GitHub, etc.) through"));
1135
- console.log(pc16.cyan(" \u2502 their APIs. Whenever you need to interact with any"));
1136
- console.log(pc16.cyan(" \u2502 third-party platform or external service, use the `one`"));
1137
- console.log(pc16.cyan(" \u2502 skill. Please save this to your project instructions or"));
1138
- console.log(pc16.cyan(" \u2502 memory so you remember it in future conversations."));
1139
- console.log(pc16.cyan(" \u2502"));
1140
- 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"));
1151
+ console.log(pc17.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"));
1152
+ console.log(pc17.cyan(" \u2502"));
1153
+ console.log(pc17.cyan(" \u2502 The One CLI (`one`) is now installed on this machine. It"));
1154
+ console.log(pc17.cyan(" \u2502 lets you interact with 1000+ third-party platforms (Gmail,"));
1155
+ console.log(pc17.cyan(" \u2502 Slack, Shopify, HubSpot, Stripe, GitHub, etc.) through"));
1156
+ console.log(pc17.cyan(" \u2502 their APIs. Whenever you need to interact with any"));
1157
+ console.log(pc17.cyan(" \u2502 third-party platform or external service, use the `one`"));
1158
+ console.log(pc17.cyan(" \u2502 skill. Please save this to your project instructions or"));
1159
+ console.log(pc17.cyan(" \u2502 memory so you remember it in future conversations."));
1160
+ console.log(pc17.cyan(" \u2502"));
1161
+ console.log(pc17.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"));
1141
1162
  console.log();
1142
1163
  p2.outro("Happy building!");
1143
1164
  }
@@ -1322,8 +1343,8 @@ function tildify(filePath) {
1322
1343
  function scopeLabel(scope) {
1323
1344
  return scope === "project" ? pc3.cyan("[project]") : pc3.magenta("[global]");
1324
1345
  }
1325
- function scopedMessage(scope, message) {
1326
- return `${scopeLabel(scope)} ${message}`;
1346
+ function scopedMessage(scope, message2) {
1347
+ return `${scopeLabel(scope)} ${message2}`;
1327
1348
  }
1328
1349
  async function handleExistingConfig(apiKey, scope, options) {
1329
1350
  const statuses = getAgentStatuses();
@@ -1910,8 +1931,8 @@ async function promptConnectIntegrations(apiKey, connParams) {
1910
1931
  { value: "more", label: "Browse all 1000+ platforms" },
1911
1932
  { value: "skip", label: "Skip for now", hint: "you can always run one add later" }
1912
1933
  ];
1913
- const message = first ? "Connect your first integration?" : "Connect another?";
1914
- const choice = await p3.select({ message, options });
1934
+ const message2 = first ? "Connect your first integration?" : "Connect another?";
1935
+ const choice = await p3.select({ message: message2, options });
1915
1936
  if (p3.isCancel(choice) || choice === "skip") {
1916
1937
  break;
1917
1938
  }
@@ -3295,7 +3316,7 @@ var CUSTOM_ACTION_NOTE = '\n\nThis is a custom action: ALSO include "connectionK
3295
3316
  function codeGuideAction(action, knowledge, platform, tags, apiBase) {
3296
3317
  const base = apiBase.replace(/\/$/, "");
3297
3318
  const method = action.method.toUpperCase();
3298
- const path13 = action.path.startsWith("/") ? action.path : `/${action.path}`;
3319
+ const path15 = action.path.startsWith("/") ? action.path : `/${action.path}`;
3299
3320
  const connEnv = `ONE_${platformEnvSegment(platform)}_CONNECTION_KEY`;
3300
3321
  const customNote = tags.includes("custom") ? CUSTOM_ACTION_NOTE : "";
3301
3322
  return `### ${actionHeading(action)}
@@ -3304,7 +3325,7 @@ function codeGuideAction(action, knowledge, platform, tags, apiBase) {
3304
3325
  ${knowledge ?? NO_KNOWLEDGE}
3305
3326
 
3306
3327
  ## Calling this action from code
3307
- URL: ${base}/passthrough${path13}
3328
+ URL: ${base}/passthrough${path15}
3308
3329
  Method: ${method}
3309
3330
  Headers:
3310
3331
  - x-one-secret: the value of the ONE_SECRET env var
@@ -3315,7 +3336,7 @@ Headers:
3315
3336
  Environment variables: ONE_SECRET (their One API key) and ${connEnv} (the key of their ${platform} connection), both from the One dashboard.
3316
3337
 
3317
3338
  \`\`\`typescript
3318
- const response = await fetch("${base}/passthrough${path13}", {
3339
+ const response = await fetch("${base}/passthrough${path15}", {
3319
3340
  method: "${method}",
3320
3341
  headers: {
3321
3342
  "x-one-secret": process.env.ONE_SECRET,
@@ -4065,32 +4086,32 @@ function validateStepsArray(steps, pathPrefix, errors) {
4065
4086
  const validTypes = FLOW_SCHEMA.stepTypes.map((st) => st.type);
4066
4087
  for (let i = 0; i < steps.length; i++) {
4067
4088
  const step = steps[i];
4068
- const path13 = `${pathPrefix}[${i}]`;
4089
+ const path15 = `${pathPrefix}[${i}]`;
4069
4090
  if (!step || typeof step !== "object" || Array.isArray(step)) {
4070
- errors.push({ path: path13, message: "Step must be an object" });
4091
+ errors.push({ path: path15, message: "Step must be an object" });
4071
4092
  continue;
4072
4093
  }
4073
4094
  const s = step;
4074
4095
  if (!s.id || typeof s.id !== "string") {
4075
- errors.push({ path: `${path13}.id`, message: 'Step must have a string "id"' });
4096
+ errors.push({ path: `${path15}.id`, message: 'Step must have a string "id"' });
4076
4097
  }
4077
4098
  if (!s.name || typeof s.name !== "string") {
4078
- errors.push({ path: `${path13}.name`, message: 'Step must have a string "name"' });
4099
+ errors.push({ path: `${path15}.name`, message: 'Step must have a string "name"' });
4079
4100
  }
4080
4101
  if (!s.type || !validTypes.includes(s.type)) {
4081
- errors.push({ path: `${path13}.type`, message: `Step type must be one of: ${validTypes.join(", ")}` });
4102
+ errors.push({ path: `${path15}.type`, message: `Step type must be one of: ${validTypes.join(", ")}` });
4082
4103
  continue;
4083
4104
  }
4084
4105
  if (s.requires !== void 0) {
4085
4106
  if (!Array.isArray(s.requires)) {
4086
- errors.push({ path: `${path13}.requires`, message: '"requires" must be an array of selector strings (e.g. ["$.steps.foo.output.bar"])' });
4107
+ errors.push({ path: `${path15}.requires`, message: '"requires" must be an array of selector strings (e.g. ["$.steps.foo.output.bar"])' });
4087
4108
  } else {
4088
4109
  for (let r = 0; r < s.requires.length; r++) {
4089
4110
  const sel = s.requires[r];
4090
4111
  if (typeof sel !== "string") {
4091
- errors.push({ path: `${path13}.requires[${r}]`, message: '"requires" entry must be a selector string' });
4112
+ errors.push({ path: `${path15}.requires[${r}]`, message: '"requires" entry must be a selector string' });
4092
4113
  } else if (!sel.startsWith("$.")) {
4093
- errors.push({ path: `${path13}.requires[${r}]`, message: `"requires" entry "${sel}" must be a selector starting with "$." (e.g. "$.steps.foo.output.bar")` });
4114
+ errors.push({ path: `${path15}.requires[${r}]`, message: `"requires" entry "${sel}" must be a selector starting with "$." (e.g. "$.steps.foo.output.bar")` });
4094
4115
  }
4095
4116
  }
4096
4117
  }
@@ -4098,7 +4119,7 @@ function validateStepsArray(steps, pathPrefix, errors) {
4098
4119
  if (s.onError && typeof s.onError === "object") {
4099
4120
  const oe = s.onError;
4100
4121
  if (!FLOW_SCHEMA.errorStrategies.includes(oe.strategy)) {
4101
- errors.push({ path: `${path13}.onError.strategy`, message: `Error strategy must be one of: ${FLOW_SCHEMA.errorStrategies.join(", ")}` });
4122
+ errors.push({ path: `${path15}.onError.strategy`, message: `Error strategy must be one of: ${FLOW_SCHEMA.errorStrategies.join(", ")}` });
4102
4123
  }
4103
4124
  }
4104
4125
  const descriptor = getStepTypeDescriptor(s.type);
@@ -4108,14 +4129,14 @@ function validateStepsArray(steps, pathPrefix, errors) {
4108
4129
  if (!configObj || typeof configObj !== "object") {
4109
4130
  const hint = detectFlatConfigHint(s, descriptor);
4110
4131
  errors.push({
4111
- path: `${path13}.${configKey}`,
4132
+ path: `${path15}.${configKey}`,
4112
4133
  message: `${capitalize(descriptor.type)} step must have a "${configKey}" config object${hint}`
4113
4134
  });
4114
4135
  continue;
4115
4136
  }
4116
4137
  const config2 = configObj;
4117
4138
  for (const [fieldName, fd] of Object.entries(descriptor.fields)) {
4118
- const fieldPath = `${path13}.${configKey}.${fieldName}`;
4139
+ const fieldPath = `${path15}.${configKey}.${fieldName}`;
4119
4140
  const value = config2[fieldName];
4120
4141
  if (fd.required && (value === void 0 || value === null || value === "")) {
4121
4142
  errors.push({ path: fieldPath, message: `${capitalize(descriptor.type)} must have ${fd.type === "string" ? "a string" : fd.type === "array" ? "a" : "a"} "${fieldName}"` });
@@ -4148,30 +4169,30 @@ function validateStepsArray(steps, pathPrefix, errors) {
4148
4169
  }
4149
4170
  }
4150
4171
  if (descriptor.type === "action") {
4151
- validateConnectionForm(config2, `${path13}.${configKey}`, errors);
4172
+ validateConnectionForm(config2, `${path15}.${configKey}`, errors);
4152
4173
  }
4153
4174
  if (descriptor.type === "code") {
4154
4175
  const hasSource = typeof config2.source === "string" && config2.source.length > 0;
4155
4176
  const hasModule = typeof config2.module === "string" && config2.module.length > 0;
4156
4177
  if (!hasSource && !hasModule) {
4157
- errors.push({ path: `${path13}.${configKey}`, message: 'Code step must define either "source" (inline JS) or "module" (path to .mjs file)' });
4178
+ errors.push({ path: `${path15}.${configKey}`, message: 'Code step must define either "source" (inline JS) or "module" (path to .mjs file)' });
4158
4179
  } else if (hasSource && hasModule) {
4159
- errors.push({ path: `${path13}.${configKey}`, message: 'Code step cannot define both "source" and "module" \u2014 pick one' });
4180
+ errors.push({ path: `${path15}.${configKey}`, message: 'Code step cannot define both "source" and "module" \u2014 pick one' });
4160
4181
  }
4161
4182
  if (hasModule) {
4162
4183
  const m = config2.module;
4163
4184
  if (m.startsWith("/") || /^[a-zA-Z]:[\\/]/.test(m)) {
4164
- errors.push({ path: `${path13}.${configKey}.module`, message: "Code module path must be relative to the flow folder (no absolute paths)" });
4185
+ errors.push({ path: `${path15}.${configKey}.module`, message: "Code module path must be relative to the flow folder (no absolute paths)" });
4165
4186
  } else if (m.split(/[\\/]/).includes("..")) {
4166
- errors.push({ path: `${path13}.${configKey}.module`, message: 'Code module path must not escape the flow folder ("..")' });
4187
+ errors.push({ path: `${path15}.${configKey}.module`, message: 'Code module path must not escape the flow folder ("..")' });
4167
4188
  } else if (!m.endsWith(".mjs")) {
4168
- errors.push({ path: `${path13}.${configKey}.module`, message: "Code module must be a .mjs file" });
4189
+ errors.push({ path: `${path15}.${configKey}.module`, message: "Code module must be a .mjs file" });
4169
4190
  }
4170
4191
  }
4171
4192
  if (hasSource) {
4172
4193
  const syntaxError = checkCodeSourceSyntax(config2.source);
4173
4194
  if (syntaxError) {
4174
- errors.push({ path: `${path13}.${configKey}.source`, message: `Syntax error in code step: ${syntaxError}` });
4195
+ errors.push({ path: `${path15}.${configKey}.source`, message: `Syntax error in code step: ${syntaxError}` });
4175
4196
  }
4176
4197
  }
4177
4198
  }
@@ -4243,16 +4264,16 @@ function validateStepIds(flow2) {
4243
4264
  function collectIds(steps, pathPrefix) {
4244
4265
  for (let i = 0; i < steps.length; i++) {
4245
4266
  const step = steps[i];
4246
- const path13 = `${pathPrefix}[${i}]`;
4267
+ const path15 = `${pathPrefix}[${i}]`;
4247
4268
  if (seen.has(step.id)) {
4248
- errors.push({ path: `${path13}.id`, message: `Duplicate step ID: "${step.id}"` });
4269
+ errors.push({ path: `${path15}.id`, message: `Duplicate step ID: "${step.id}"` });
4249
4270
  } else {
4250
4271
  seen.add(step.id);
4251
4272
  }
4252
4273
  for (const { configKey, fieldName } of nestedKeys) {
4253
4274
  const config2 = step[configKey];
4254
4275
  if (config2 && Array.isArray(config2[fieldName])) {
4255
- collectIds(config2[fieldName], `${path13}.${configKey}.${fieldName}`);
4276
+ collectIds(config2[fieldName], `${path15}.${configKey}.${fieldName}`);
4256
4277
  }
4257
4278
  }
4258
4279
  }
@@ -4300,7 +4321,7 @@ function validateSelectorReferences(flow2, rootDir) {
4300
4321
  }
4301
4322
  return selectors;
4302
4323
  }
4303
- function checkSelectors(selectors, path13, precedingStepIds) {
4324
+ function checkSelectors(selectors, path15, precedingStepIds) {
4304
4325
  for (const selector of selectors) {
4305
4326
  const parts = selector.split(".");
4306
4327
  if (parts.length < 3) continue;
@@ -4308,15 +4329,15 @@ function validateSelectorReferences(flow2, rootDir) {
4308
4329
  if (root === "input") {
4309
4330
  const inputName = parts[2];
4310
4331
  if (!inputNames.has(inputName)) {
4311
- errors.push({ path: path13, message: `Selector "${selector}" references undefined input "${inputName}"` });
4332
+ errors.push({ path: path15, message: `Selector "${selector}" references undefined input "${inputName}"` });
4312
4333
  }
4313
4334
  } else if (root === "steps") {
4314
4335
  const stepId = parts[2].replace(/[\[\]]/g, "").split(/[\[\]]/)[0];
4315
4336
  if (!allStepIds.has(stepId)) {
4316
- errors.push({ path: path13, message: `Selector "${selector}" references undefined step "${stepId}"` });
4337
+ errors.push({ path: path15, message: `Selector "${selector}" references undefined step "${stepId}"` });
4317
4338
  } else if (precedingStepIds && !precedingStepIds.has(stepId)) {
4318
4339
  errors.push({
4319
- path: path13,
4340
+ path: path15,
4320
4341
  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.`
4321
4342
  });
4322
4343
  }
@@ -4324,20 +4345,20 @@ function validateSelectorReferences(flow2, rootDir) {
4324
4345
  }
4325
4346
  }
4326
4347
  const EXPRESSION_FIELDS = /* @__PURE__ */ new Set(["condition.expression", "while.condition"]);
4327
- function checkOperatorsInSelectorField(value, path13) {
4348
+ function checkOperatorsInSelectorField(value, path15) {
4328
4349
  if (typeof value === "string" && value.startsWith("$.")) {
4329
4350
  if (value.includes("||")) {
4330
- 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.` });
4351
+ errors.push({ path: path15, 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.` });
4331
4352
  } else if (value.includes("&&")) {
4332
- 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.` });
4353
+ errors.push({ path: path15, 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.` });
4333
4354
  }
4334
4355
  } else if (value && typeof value === "object" && !Array.isArray(value)) {
4335
4356
  for (const [k, v] of Object.entries(value)) {
4336
- checkOperatorsInSelectorField(v, `${path13}.${k}`);
4357
+ checkOperatorsInSelectorField(v, `${path15}.${k}`);
4337
4358
  }
4338
4359
  } else if (Array.isArray(value)) {
4339
4360
  for (let i = 0; i < value.length; i++) {
4340
- checkOperatorsInSelectorField(value[i], `${path13}[${i}]`);
4361
+ checkOperatorsInSelectorField(value[i], `${path15}[${i}]`);
4341
4362
  }
4342
4363
  }
4343
4364
  }
@@ -4422,10 +4443,10 @@ var VALID_OUTPUT_SCHEMA_TYPES = /* @__PURE__ */ new Set(["string", "number", "bo
4422
4443
  function isOutputSchemaObject(v) {
4423
4444
  return !!v && typeof v === "object" && !Array.isArray(v);
4424
4445
  }
4425
- function walkOutputSchema(schema, path13) {
4446
+ function walkOutputSchema(schema, path15) {
4426
4447
  let current = schema;
4427
- for (let i = 0; i < path13.length; i++) {
4428
- const seg = path13[i];
4448
+ for (let i = 0; i < path15.length; i++) {
4449
+ const seg = path15[i];
4429
4450
  if (typeof current === "string") {
4430
4451
  return current === "unknown" || current === "object" || current === "array" ? "opaque" : "opaque";
4431
4452
  }
@@ -5892,6 +5913,463 @@ async function relayEventTypesCommand(platform) {
5892
5913
  }
5893
5914
  }
5894
5915
 
5916
+ // src/commands/connect.ts
5917
+ import crypto2 from "crypto";
5918
+ import fs6 from "fs";
5919
+ import path6 from "path";
5920
+ import open4 from "open";
5921
+ import pc10 from "picocolors";
5922
+
5923
+ // src/lib/connect-callback.ts
5924
+ import http2 from "http";
5925
+ var PORT_RANGE_START2 = 49152;
5926
+ var PORT_RANGE_END2 = 65535;
5927
+ var MAX_PORT_ATTEMPTS2 = 5;
5928
+ var MAX_ID_LENGTH = 200;
5929
+ var MAX_ERROR_LENGTH2 = 200;
5930
+ var ID_PATTERN = /^[A-Za-z0-9_:.-]+$/;
5931
+ function statusPage2(title, body) {
5932
+ return `<!DOCTYPE html>
5933
+ <html><head><title>One CLI</title></head>
5934
+ <body style="font-family:system-ui;display:flex;justify-content:center;align-items:center;height:100vh;margin:0;background:#0a0a0a;color:#fafafa">
5935
+ <div style="text-align:center">
5936
+ <h1 style="font-size:20px;margin:0 0 8px">${title}</h1>
5937
+ <p style="color:#a1a1aa;font-size:14px">${body}</p>
5938
+ </div></body></html>`;
5939
+ }
5940
+ var CANCELLED_HTML2 = statusPage2("Nothing was changed", "You can close this tab and run <code>one connect create</code> again.");
5941
+ var FAILED_HTML2 = statusPage2("The app wasn't set up", "Return to your terminal for details.");
5942
+ function cleanId(value) {
5943
+ if (!value) return void 0;
5944
+ const trimmed = value.trim();
5945
+ return trimmed.length <= MAX_ID_LENGTH && ID_PATTERN.test(trimmed) ? trimmed : void 0;
5946
+ }
5947
+ function cleanText(value) {
5948
+ if (value === null) return void 0;
5949
+ const cleaned = value.replace(/[\u0000-\u001f\u007f-\u009f]/g, "").trim();
5950
+ return cleaned ? Array.from(cleaned).slice(0, MAX_ERROR_LENGTH2).join("") : void 0;
5951
+ }
5952
+ function parseConnectCallback(url, expectedState) {
5953
+ if (url.pathname !== "/callback") return { status: 404 };
5954
+ const state = url.searchParams.get("state");
5955
+ if (!state) return { status: 400 };
5956
+ if (state !== expectedState) return { status: 403 };
5957
+ const error2 = cleanText(url.searchParams.get("error"));
5958
+ if (error2 === "cancelled") return { status: 200, outcome: { kind: "cancelled" } };
5959
+ if (error2) return { status: 200, outcome: { kind: "failed", reason: error2 } };
5960
+ const outcome = url.searchParams.get("outcome");
5961
+ const clientId = cleanId(url.searchParams.get("clientId"));
5962
+ const rawSet = url.searchParams.get("permissionSetId");
5963
+ const permissionSetId = rawSet ? cleanId(rawSet) : null;
5964
+ if (outcome !== "created" && outcome !== "updated" && outcome !== "unchanged" || !clientId || permissionSetId === void 0) {
5965
+ return { status: 400 };
5966
+ }
5967
+ return { status: 200, outcome: { kind: "done", outcome, clientId, permissionSetId } };
5968
+ }
5969
+ function randomPort2() {
5970
+ return PORT_RANGE_START2 + Math.floor(Math.random() * (PORT_RANGE_END2 - PORT_RANGE_START2));
5971
+ }
5972
+ function startConnectCallbackServer(expectedState, doneUrl) {
5973
+ return new Promise((resolveSetup, rejectSetup) => {
5974
+ let attempts = 0;
5975
+ let resolveResult;
5976
+ const result = new Promise((res) => {
5977
+ resolveResult = res;
5978
+ });
5979
+ function tryListen() {
5980
+ const port = randomPort2();
5981
+ attempts++;
5982
+ const server = http2.createServer((req, res) => {
5983
+ const { status: status2, outcome } = parseConnectCallback(new URL(req.url || "/", `http://localhost:${port}`), expectedState);
5984
+ if (!outcome) {
5985
+ res.writeHead(status2, { "Content-Type": "text/plain" });
5986
+ res.end(status2 === 403 ? "State mismatch" : status2 === 404 ? "Not found" : "Missing required parameters");
5987
+ return;
5988
+ }
5989
+ if (outcome.kind === "done") {
5990
+ res.writeHead(302, { Location: doneUrl(outcome) });
5991
+ res.end();
5992
+ } else {
5993
+ res.writeHead(200, { "Content-Type": "text/html" });
5994
+ res.end(outcome.kind === "cancelled" ? CANCELLED_HTML2 : FAILED_HTML2);
5995
+ }
5996
+ resolveResult(outcome);
5997
+ });
5998
+ server.on("error", (err) => {
5999
+ if ((err.code === "EADDRINUSE" || err.code === "EACCES") && attempts < MAX_PORT_ATTEMPTS2) {
6000
+ tryListen();
6001
+ return;
6002
+ }
6003
+ rejectSetup(err);
6004
+ });
6005
+ server.listen(port, "127.0.0.1", () => resolveSetup({ server, port, result }));
6006
+ }
6007
+ tryListen();
6008
+ });
6009
+ }
6010
+
6011
+ // src/lib/connect-app.ts
6012
+ import fs5 from "fs";
6013
+ import path5 from "path";
6014
+ import zlib from "zlib";
6015
+ import { pathToFileURL } from "url";
6016
+ var CONFIG_FILES = ["one.connect.ts", "one.connect.mts", "one.connect.mjs", "one.connect.js"];
6017
+ var TYPES_FILE = "one-connect-env.d.ts";
6018
+ var ACCESS_METHODS = {
6019
+ "read-only": ["GET"],
6020
+ "read-write": ["GET", "POST", "PUT", "PATCH"],
6021
+ "full-access": null
6022
+ };
6023
+ var HEX_COLOR = /^#[0-9a-fA-F]{6}$/;
6024
+ var ACTION_ID_PREFIX = "conn_mod_def::";
6025
+ function findConfigFile(cwd, explicit) {
6026
+ if (explicit) {
6027
+ const resolved = path5.resolve(cwd, explicit);
6028
+ return fs5.existsSync(resolved) ? resolved : null;
6029
+ }
6030
+ for (const name of CONFIG_FILES) {
6031
+ const candidate = path5.join(cwd, name);
6032
+ if (fs5.existsSync(candidate)) return candidate;
6033
+ }
6034
+ return null;
6035
+ }
6036
+ async function loadConfigFile(file) {
6037
+ try {
6038
+ const mod = await import(pathToFileURL(file).href);
6039
+ return mod.default ?? mod;
6040
+ } catch (error2) {
6041
+ const { code, message: message2 = "" } = error2;
6042
+ if (code === "ERR_MODULE_NOT_FOUND" && message2.includes("'@withone/connect'")) {
6043
+ throw new Error(
6044
+ `it imports @withone/connect, which isn't installed in this project. Run \`npm i @withone/connect\` first.`
6045
+ );
6046
+ }
6047
+ if (code === "ERR_PACKAGE_PATH_NOT_EXPORTED" && /@withone[\\/]connect/.test(message2)) {
6048
+ throw new Error(
6049
+ `this project's @withone/connect is older than 0.19.0, which added @withone/connect/config. Run \`npm i @withone/connect@latest\` first.`
6050
+ );
6051
+ }
6052
+ if (code === "ERR_UNKNOWN_FILE_EXTENSION" && /\.m?ts$/.test(file)) {
6053
+ throw new Error(
6054
+ `Node ${process.versions.node} can't load ${path5.basename(file)}. Use Node 22.18 or later, or rename it to one.connect.mjs and type it with /** @type {import("@withone/connect/config").ConnectAppConfig} */.`
6055
+ );
6056
+ }
6057
+ throw error2;
6058
+ }
6059
+ }
6060
+ function validateConfig(value) {
6061
+ const errors = [];
6062
+ const v = value;
6063
+ if (!v || typeof v !== "object") return { errors: ["The config must export an object (use defineConnectApp)."] };
6064
+ if (typeof v.name !== "string" || !v.name.trim()) errors.push("`name` is required.");
6065
+ if (!Array.isArray(v.redirectUris) || v.redirectUris.length === 0) {
6066
+ errors.push("`redirectUris` needs at least one callback URL.");
6067
+ } else {
6068
+ for (const uri of v.redirectUris) {
6069
+ if (typeof uri !== "string" || !/^https?:\/\//.test(uri)) errors.push(`Redirect URI "${uri}" must be an http(s) URL.`);
6070
+ }
6071
+ }
6072
+ if (v.reason !== void 0 && (typeof v.reason !== "string" || v.reason.trim().length === 0 || v.reason.length > 200)) {
6073
+ errors.push("`reason` must be one sentence of at most 200 characters.");
6074
+ }
6075
+ if (v.branding) {
6076
+ for (const key of ["panelColor", "buttonColor"]) {
6077
+ if (!HEX_COLOR.test(String(v.branding[key] ?? ""))) errors.push(`\`branding.${key}\` must be a #RRGGBB colour.`);
6078
+ }
6079
+ }
6080
+ for (const [tool, ask] of Object.entries(v.ask ?? {})) {
6081
+ const access = ask?.access;
6082
+ if (access === "custom") {
6083
+ const actions2 = ask.actions;
6084
+ if (!Array.isArray(actions2) || actions2.length === 0) errors.push(`\`ask.${tool}\` is custom, so it needs at least one action.`);
6085
+ } else if (typeof access !== "string" || !(access in ACCESS_METHODS)) {
6086
+ errors.push(`\`ask.${tool}.access\` must be read-only, read-write, full-access or custom.`);
6087
+ }
6088
+ }
6089
+ return errors.length > 0 ? { errors } : { config: v };
6090
+ }
6091
+ function actionName(title) {
6092
+ const words = title.split(/[^A-Za-z0-9]+/).filter(Boolean);
6093
+ return words.map((word, i) => i === 0 ? word.toLowerCase() : word[0].toUpperCase() + word.slice(1).toLowerCase()).join("");
6094
+ }
6095
+ function actionNames(actions2) {
6096
+ const byName = /* @__PURE__ */ new Map();
6097
+ const shared = /* @__PURE__ */ new Set();
6098
+ for (const action of actions2) {
6099
+ const name = actionName(action.title);
6100
+ if (!name) continue;
6101
+ if (byName.has(name)) shared.add(name);
6102
+ else byName.set(name, action.systemId);
6103
+ }
6104
+ for (const name of shared) byName.delete(name);
6105
+ return byName;
6106
+ }
6107
+ function resolveActions(refs, names, ids) {
6108
+ const resolved = [];
6109
+ const unknown = [];
6110
+ for (const ref2 of refs) {
6111
+ const id = ref2.startsWith(ACTION_ID_PREFIX) ? ids.has(ref2) ? ref2 : void 0 : names.get(ref2);
6112
+ if (id) resolved.push(id);
6113
+ else unknown.push(ref2);
6114
+ }
6115
+ return unknown.length > 0 ? { unknown } : { ids: [...new Set(resolved)] };
6116
+ }
6117
+ function connectorRule(connectionDefinitionId, ask, actionIds = []) {
6118
+ if (ask.access === "custom") return { type: "connectionDefinition", connectionDefinitionId, methods: null, actionIds };
6119
+ return { type: "connectionDefinition", connectionDefinitionId, methods: ACCESS_METHODS[ask.access], actionIds: null };
6120
+ }
6121
+ function clientFields(config2) {
6122
+ const fields = { name: config2.name.trim(), redirectUris: config2.redirectUris };
6123
+ if (config2.description) fields.description = config2.description;
6124
+ if (config2.logoUrl) fields.logoUrl = config2.logoUrl;
6125
+ if (config2.homepageUrl) fields.homepageUrl = config2.homepageUrl;
6126
+ if (config2.reason) fields.consentReason = config2.reason.trim();
6127
+ if (config2.branding) {
6128
+ fields.frontend = {
6129
+ panelColor: config2.branding.panelColor,
6130
+ buttonColor: config2.branding.buttonColor,
6131
+ cobrandEmail: config2.branding.cobrandEmail ?? false
6132
+ };
6133
+ }
6134
+ return fields;
6135
+ }
6136
+ function buildHandoff(config2, rules) {
6137
+ return { v: 1, app: clientFields(config2), ask: rules.length > 0 ? rules : null };
6138
+ }
6139
+ function encodeHandoff(handoff) {
6140
+ return zlib.deflateRawSync(Buffer.from(JSON.stringify(handoff), "utf8"), { level: 9 }).toString("base64url");
6141
+ }
6142
+ var MAX_HANDOFF_LENGTH = 32e3;
6143
+ var MAX_WINDOWS_OPEN_LENGTH = 11e3;
6144
+ function defaultEnvFile(cwd) {
6145
+ const local = path5.join(cwd, ".env.local");
6146
+ return fs5.existsSync(local) ? local : path5.join(cwd, ".env");
6147
+ }
6148
+ function readEnvValue(text5, key) {
6149
+ const match = text5.match(new RegExp(`^${key}=(.*)$`, "m"));
6150
+ return match ? match[1].trim().replace(/^["']|["']$/g, "") : void 0;
6151
+ }
6152
+ function upsertEnv(text5, values) {
6153
+ let next = text5;
6154
+ const appended = [];
6155
+ for (const [key, value] of Object.entries(values)) {
6156
+ const line = new RegExp(`^${key}=.*$`, "m");
6157
+ if (line.test(next)) {
6158
+ if (value !== null) next = next.replace(line, `${key}=${value}`);
6159
+ } else {
6160
+ appended.push(`${key}=${value ?? ""}`);
6161
+ }
6162
+ }
6163
+ if (appended.length === 0) return next;
6164
+ const separator = next.length === 0 || next.endsWith("\n") ? "" : "\n";
6165
+ return `${next}${separator}${appended.join("\n")}
6166
+ `;
6167
+ }
6168
+ function renderTypes(tools, actionsByTool) {
6169
+ const literal = (value) => JSON.stringify(value);
6170
+ const union = (values) => values.length > 0 ? values.map(literal).join(" | ") : "never";
6171
+ const actionLines = Object.entries(actionsByTool).sort(([a], [b]) => a.localeCompare(b)).map(([tool, names]) => ` ${literal(tool)}: ${union([...names].sort())};`);
6172
+ return [
6173
+ "// Generated by `one connect types`. Run it again after changing the tools in one.connect.ts.",
6174
+ 'import "@withone/connect/config";',
6175
+ "",
6176
+ 'declare module "@withone/connect/config" {',
6177
+ " interface ConnectRegistry {",
6178
+ ` tools: ${union([...tools].sort())};`,
6179
+ " actions: {",
6180
+ ...actionLines,
6181
+ " };",
6182
+ " }",
6183
+ "}",
6184
+ ""
6185
+ ].join("\n");
6186
+ }
6187
+
6188
+ // src/commands/connect.ts
6189
+ var SETUP_TIMEOUT_MS = 10 * 60 * 1e3;
6190
+ function requireApi() {
6191
+ const apiKey = getApiKey();
6192
+ if (!apiKey) error("Not configured. Run `one init` first.");
6193
+ return new OneApi(apiKey, getApiBase());
6194
+ }
6195
+ async function readConfig2(cwd, explicit) {
6196
+ const file = findConfigFile(cwd, explicit);
6197
+ if (!file) {
6198
+ error(
6199
+ explicit ? `No config at ${explicit}.` : "No one.connect.ts here. Create one with defineConnectApp from @withone/connect/config."
6200
+ );
6201
+ }
6202
+ let loaded;
6203
+ try {
6204
+ loaded = await loadConfigFile(file);
6205
+ } catch (error2) {
6206
+ error(`Couldn't load ${path6.basename(file)}: ${error2 instanceof Error ? error2.message : String(error2)}`);
6207
+ }
6208
+ const checked = validateConfig(loaded);
6209
+ if ("errors" in checked) error(`${path6.basename(file)} has problems:
6210
+ ${checked.errors.join("\n ")}`);
6211
+ return { file, config: checked.config };
6212
+ }
6213
+ function message(error2) {
6214
+ return error2 instanceof Error ? error2.message : String(error2);
6215
+ }
6216
+ async function buildRules(api, config2) {
6217
+ const asked = Object.entries(config2.ask ?? {});
6218
+ if (asked.length === 0) return [];
6219
+ const platforms = await api.listPlatforms();
6220
+ const idBySlug = new Map(platforms.map((p9) => [p9.platform, p9.id]));
6221
+ const unknownTools = asked.map(([slug]) => slug).filter((slug) => !idBySlug.has(slug));
6222
+ if (unknownTools.length > 0) {
6223
+ error(`Not in One's catalog: ${unknownTools.join(", ")}. Run \`one platforms\` for the slugs.`);
6224
+ }
6225
+ const rules = [];
6226
+ for (const [slug, ask] of asked) {
6227
+ const definitionId = idBySlug.get(slug);
6228
+ if (ask.access !== "custom") {
6229
+ rules.push(connectorRule(definitionId, ask));
6230
+ continue;
6231
+ }
6232
+ const actions2 = await api.listAllAvailableActions(slug);
6233
+ const resolved = resolveActions(ask.actions, actionNames(actions2), new Set(actions2.map((a) => a.systemId)));
6234
+ if ("unknown" in resolved) {
6235
+ error(
6236
+ `${slug} has no action named ${resolved.unknown.join(", ")}. Run \`one connect types\` for the names, or \`one actions find ${slug} "<what it does>" --no-knowledge\` for an id.`
6237
+ );
6238
+ }
6239
+ rules.push(connectorRule(definitionId, ask, resolved.ids));
6240
+ }
6241
+ return rules;
6242
+ }
6243
+ async function connectCreateCommand(options) {
6244
+ const cwd = process.cwd();
6245
+ const api = requireApi();
6246
+ const { file, config: config2 } = await readConfig2(cwd, options.config);
6247
+ const envFile = options.envFile ? path6.resolve(cwd, options.envFile) : defaultEnvFile(cwd);
6248
+ const envText = fs6.existsSync(envFile) ? fs6.readFileSync(envFile, "utf8") : "";
6249
+ const existingId = readEnvValue(envText, "ONE_CLIENT_ID") || void 0;
6250
+ const spinner = createSpinner();
6251
+ spinner.start(`Reading ${path6.basename(file)}...`);
6252
+ let server;
6253
+ let timer;
6254
+ try {
6255
+ const rules = await buildRules(api, config2);
6256
+ const whoami = await ensureWhoAmI(api);
6257
+ const scope = {
6258
+ orgId: whoami?.organization?.id,
6259
+ projectId: whoami?.project?.id,
6260
+ envFile: path6.basename(envFile)
6261
+ };
6262
+ const handoff = encodeHandoff(buildHandoff(config2, rules));
6263
+ if (handoff.length > MAX_HANDOFF_LENGTH) {
6264
+ error(
6265
+ `${path6.basename(file)} is too big to hand to the browser (${Math.ceil(handoff.length / 1024)} KB compressed, limit ${Math.floor(MAX_HANDOFF_LENGTH / 1024)} KB). Give tools with long custom lists an access level instead.`
6266
+ );
6267
+ }
6268
+ const state = crypto2.randomBytes(16).toString("hex");
6269
+ const started = await startConnectCallbackServer(
6270
+ state,
6271
+ (done) => getConnectDoneUrl(done.clientId, done.outcome, scope)
6272
+ );
6273
+ server = started.server;
6274
+ const url = getConnectSetupUrl({
6275
+ ...scope,
6276
+ clientId: existingId,
6277
+ permissionSetId: readEnvValue(envText, "ONE_PERMISSION_SET") || void 0,
6278
+ port: started.port,
6279
+ state,
6280
+ handoff
6281
+ });
6282
+ const tooLongToOpen = process.platform === "win32" && url.length > MAX_WINDOWS_OPEN_LENGTH;
6283
+ const opening = options.open !== false && !tooLongToOpen;
6284
+ if (opening) await open4(url).catch(() => void 0);
6285
+ const verb = existingId ? "Approve the update" : "Create the app";
6286
+ if (isAgentMode()) {
6287
+ process.stderr.write(`${verb} in the browser: ${url}
6288
+ `);
6289
+ } else {
6290
+ spinner.stop(opening ? `${verb} in your browser` : `${verb}: open this link in your browser`);
6291
+ console.log(` ${pc10.underline(url)}`);
6292
+ console.log();
6293
+ spinner.start("Waiting for you to approve it...");
6294
+ }
6295
+ const outcome = await Promise.race([
6296
+ started.result,
6297
+ new Promise((resolve) => {
6298
+ timer = setTimeout(() => resolve(null), SETUP_TIMEOUT_MS);
6299
+ })
6300
+ ]);
6301
+ if (!outcome) error("Timed out waiting for the browser. Run `one connect create` again.");
6302
+ if (outcome.kind === "cancelled") error("Cancelled in the browser. Nothing was changed.");
6303
+ if (outcome.kind === "failed") error(`The setup page reported: ${outcome.reason}`);
6304
+ const created = outcome.outcome === "created";
6305
+ fs6.writeFileSync(
6306
+ envFile,
6307
+ upsertEnv(envText, {
6308
+ ONE_CLIENT_ID: outcome.clientId,
6309
+ ONE_REDIRECT_URI: config2.redirectUris[0],
6310
+ ...outcome.permissionSetId ? { ONE_PERMISSION_SET: outcome.permissionSetId } : {},
6311
+ ...created ? { ONE_CLIENT_SECRET: null, ONE_CONNECT_KEY: null } : {}
6312
+ })
6313
+ );
6314
+ const result = {
6315
+ outcome: outcome.outcome,
6316
+ clientId: outcome.clientId,
6317
+ permissionSetId: outcome.permissionSetId,
6318
+ redirectUris: config2.redirectUris,
6319
+ envFile: path6.relative(cwd, envFile) || envFile
6320
+ };
6321
+ if (isAgentMode()) {
6322
+ json(result);
6323
+ return;
6324
+ }
6325
+ spinner.stop(
6326
+ created ? `Created ${config2.name}` : outcome.outcome === "updated" ? `Updated ${config2.name}` : `${config2.name} is up to date`
6327
+ );
6328
+ console.log();
6329
+ console.log(` ${pc10.dim("Client ID:")} ${outcome.clientId}`);
6330
+ if (outcome.permissionSetId) console.log(` ${pc10.dim("Permission set:")} ${outcome.permissionSetId}`);
6331
+ console.log(` ${pc10.dim("Wrote")} ${result.envFile}`);
6332
+ if (created) {
6333
+ console.log(` ${pc10.dim("The two secrets came from the browser page, never through here.")}`);
6334
+ }
6335
+ console.log();
6336
+ } catch (error2) {
6337
+ spinner.stop("Failed");
6338
+ error(`Error: ${message(error2)}`);
6339
+ } finally {
6340
+ if (timer) clearTimeout(timer);
6341
+ server?.close();
6342
+ }
6343
+ }
6344
+ async function connectTypesCommand(options) {
6345
+ const cwd = process.cwd();
6346
+ const api = requireApi();
6347
+ const spinner = createSpinner();
6348
+ spinner.start("Reading One's catalog...");
6349
+ try {
6350
+ const file = findConfigFile(cwd, options.config);
6351
+ const config2 = file ? validateConfig(await loadConfigFile(file)) : null;
6352
+ const tools = Object.keys(config2 && "config" in config2 ? config2.config.ask ?? {} : {});
6353
+ const platforms = await api.listPlatforms();
6354
+ const known = new Set(platforms.map((p9) => p9.platform));
6355
+ const actionsByTool = {};
6356
+ for (const tool of tools.filter((t) => known.has(t))) {
6357
+ actionsByTool[tool] = [...actionNames(await api.listAllAvailableActions(tool)).keys()];
6358
+ }
6359
+ const target = path6.join(file ? path6.dirname(file) : cwd, TYPES_FILE);
6360
+ fs6.writeFileSync(target, renderTypes([...known], actionsByTool));
6361
+ if (isAgentMode()) {
6362
+ json({ file: target, tools: known.size, actions: actionsByTool });
6363
+ return;
6364
+ }
6365
+ spinner.stop(`Wrote ${path6.relative(cwd, target) || target}`);
6366
+ console.log(` ${pc10.dim(`${known.size} tools; action names for ${Object.keys(actionsByTool).join(", ") || "none yet (add tools to ask, then run it again)"}`)}`);
6367
+ } catch (error2) {
6368
+ spinner.stop("Failed");
6369
+ error(`Error: ${message(error2)}`);
6370
+ }
6371
+ }
6372
+
5895
6373
  // src/lib/memory/sync/models.ts
5896
6374
  function parseActionType(actionKey) {
5897
6375
  const parts = actionKey.split("::");
@@ -6013,11 +6491,11 @@ function handleId(response, config2, records) {
6013
6491
  }
6014
6492
 
6015
6493
  // src/lib/memory/sync/state.ts
6016
- import fs5 from "fs";
6017
- import path5 from "path";
6018
- var SYNC_DIR = path5.join(".one", "sync");
6019
- var STATE_DIR = path5.join(SYNC_DIR, "state");
6020
- var LEGACY_SINGLE_FILE = path5.join(SYNC_DIR, "sync_state.json");
6494
+ import fs7 from "fs";
6495
+ import path7 from "path";
6496
+ var SYNC_DIR = path7.join(".one", "sync");
6497
+ var STATE_DIR = path7.join(SYNC_DIR, "state");
6498
+ var LEGACY_SINGLE_FILE = path7.join(SYNC_DIR, "sync_state.json");
6021
6499
  var legacyMigrationDone = false;
6022
6500
  function rowToState(row) {
6023
6501
  return {
@@ -6045,9 +6523,9 @@ function stateToRow(platform, model, state, lastError) {
6045
6523
  async function migrateLegacyOnce() {
6046
6524
  if (legacyMigrationDone) return;
6047
6525
  legacyMigrationDone = true;
6048
- if (fs5.existsSync(LEGACY_SINGLE_FILE)) {
6526
+ if (fs7.existsSync(LEGACY_SINGLE_FILE)) {
6049
6527
  try {
6050
- const raw = fs5.readFileSync(LEGACY_SINGLE_FILE, "utf-8");
6528
+ const raw = fs7.readFileSync(LEGACY_SINGLE_FILE, "utf-8");
6051
6529
  const legacy = JSON.parse(raw);
6052
6530
  const backend = await getBackend();
6053
6531
  for (const [platform, models] of Object.entries(legacy)) {
@@ -6057,32 +6535,32 @@ async function migrateLegacyOnce() {
6057
6535
  await backend.setSyncState(stateToRow(platform, model, modelState));
6058
6536
  }
6059
6537
  }
6060
- fs5.unlinkSync(LEGACY_SINGLE_FILE);
6538
+ fs7.unlinkSync(LEGACY_SINGLE_FILE);
6061
6539
  } catch {
6062
6540
  try {
6063
- fs5.unlinkSync(LEGACY_SINGLE_FILE);
6541
+ fs7.unlinkSync(LEGACY_SINGLE_FILE);
6064
6542
  } catch {
6065
6543
  }
6066
6544
  }
6067
6545
  }
6068
- if (fs5.existsSync(STATE_DIR)) {
6546
+ if (fs7.existsSync(STATE_DIR)) {
6069
6547
  try {
6070
6548
  const backend = await getBackend();
6071
- const platforms = fs5.readdirSync(STATE_DIR);
6549
+ const platforms = fs7.readdirSync(STATE_DIR);
6072
6550
  for (const platform of platforms) {
6073
- const platformDir = path5.join(STATE_DIR, platform);
6551
+ const platformDir = path7.join(STATE_DIR, platform);
6074
6552
  let entries;
6075
6553
  try {
6076
- entries = fs5.readdirSync(platformDir);
6554
+ entries = fs7.readdirSync(platformDir);
6077
6555
  } catch {
6078
6556
  continue;
6079
6557
  }
6080
6558
  for (const entry of entries) {
6081
6559
  if (!entry.endsWith(".json")) continue;
6082
6560
  const model = entry.slice(0, -".json".length);
6083
- const filePath = path5.join(platformDir, entry);
6561
+ const filePath = path7.join(platformDir, entry);
6084
6562
  try {
6085
- const raw = fs5.readFileSync(filePath, "utf-8");
6563
+ const raw = fs7.readFileSync(filePath, "utf-8");
6086
6564
  const modelState = JSON.parse(raw);
6087
6565
  const existing = await backend.getSyncState(platform, model);
6088
6566
  if (!existing) {
@@ -6092,7 +6570,7 @@ async function migrateLegacyOnce() {
6092
6570
  }
6093
6571
  }
6094
6572
  }
6095
- fs5.rmSync(STATE_DIR, { recursive: true, force: true });
6573
+ fs7.rmSync(STATE_DIR, { recursive: true, force: true });
6096
6574
  } catch {
6097
6575
  }
6098
6576
  }
@@ -6136,12 +6614,12 @@ async function removeModelState(platform, model) {
6136
6614
  }
6137
6615
 
6138
6616
  // src/lib/memory/sync/lock.ts
6139
- import fs6 from "fs";
6140
- import path6 from "path";
6141
- var LOCK_DIR_REL = path6.join(".one", "sync", "locks");
6617
+ import fs8 from "fs";
6618
+ import path8 from "path";
6619
+ var LOCK_DIR_REL = path8.join(".one", "sync", "locks");
6142
6620
  var STALE_MS = 30 * 60 * 1e3;
6143
6621
  function lockPath(platform, model) {
6144
- return path6.join(LOCK_DIR_REL, `${platform}_${model}`);
6622
+ return path8.join(LOCK_DIR_REL, `${platform}_${model}`);
6145
6623
  }
6146
6624
  function isProcessAlive(pid) {
6147
6625
  try {
@@ -6152,21 +6630,21 @@ function isProcessAlive(pid) {
6152
6630
  }
6153
6631
  }
6154
6632
  var SyncLockError = class extends Error {
6155
- constructor(message) {
6156
- super(message);
6633
+ constructor(message2) {
6634
+ super(message2);
6157
6635
  this.name = "SyncLockError";
6158
6636
  }
6159
6637
  };
6160
6638
  function acquireSyncLock(platform, model) {
6161
- fs6.mkdirSync(LOCK_DIR_REL, { recursive: true });
6639
+ fs8.mkdirSync(LOCK_DIR_REL, { recursive: true });
6162
6640
  const dir = lockPath(platform, model);
6163
- const pidFile = path6.join(dir, "pid");
6641
+ const pidFile = path8.join(dir, "pid");
6164
6642
  try {
6165
- fs6.mkdirSync(dir);
6643
+ fs8.mkdirSync(dir);
6166
6644
  } catch (err) {
6167
6645
  const stat = (() => {
6168
6646
  try {
6169
- return fs6.statSync(dir);
6647
+ return fs8.statSync(dir);
6170
6648
  } catch {
6171
6649
  return null;
6172
6650
  }
@@ -6175,7 +6653,7 @@ function acquireSyncLock(platform, model) {
6175
6653
  const age = Date.now() - stat.mtimeMs;
6176
6654
  let ownerPid = null;
6177
6655
  try {
6178
- const raw = fs6.readFileSync(pidFile, "utf-8");
6656
+ const raw = fs8.readFileSync(pidFile, "utf-8");
6179
6657
  const parsed = parseInt(raw.trim(), 10);
6180
6658
  if (!isNaN(parsed)) ownerPid = parsed;
6181
6659
  } catch {
@@ -6184,8 +6662,8 @@ function acquireSyncLock(platform, model) {
6184
6662
  const veryOld = age > STALE_MS;
6185
6663
  if (ownerDead || veryOld) {
6186
6664
  try {
6187
- fs6.rmSync(dir, { recursive: true, force: true });
6188
- fs6.mkdirSync(dir);
6665
+ fs8.rmSync(dir, { recursive: true, force: true });
6666
+ fs8.mkdirSync(dir);
6189
6667
  } catch {
6190
6668
  throw new SyncLockError(
6191
6669
  `Could not take over stale lock at ${dir}. Remove it manually if no sync is running.`
@@ -6202,13 +6680,13 @@ function acquireSyncLock(platform, model) {
6202
6680
  }
6203
6681
  }
6204
6682
  try {
6205
- fs6.writeFileSync(pidFile, String(process.pid));
6683
+ fs8.writeFileSync(pidFile, String(process.pid));
6206
6684
  } catch {
6207
6685
  }
6208
6686
  return {
6209
6687
  release() {
6210
6688
  try {
6211
- fs6.rmSync(dir, { recursive: true, force: true });
6689
+ fs8.rmSync(dir, { recursive: true, force: true });
6212
6690
  } catch {
6213
6691
  }
6214
6692
  }
@@ -6217,9 +6695,9 @@ function acquireSyncLock(platform, model) {
6217
6695
 
6218
6696
  // src/lib/memory/sync/hooks.ts
6219
6697
  import { spawn as spawn2 } from "child_process";
6220
- import fs7 from "fs";
6221
- import path7 from "path";
6222
- var EVENTS_DIR = path7.join(".one", "sync", "events");
6698
+ import fs9 from "fs";
6699
+ import path9 from "path";
6700
+ var EVENTS_DIR = path9.join(".one", "sync", "events");
6223
6701
  function classifyRecords(db, model, records, idField, tableExists2) {
6224
6702
  if (!tableExists2 || records.length === 0) {
6225
6703
  return { inserts: records, updates: [] };
@@ -6265,10 +6743,10 @@ async function fireHooks(hookCommand, events) {
6265
6743
  function appendEventLog(events) {
6266
6744
  if (events.length === 0) return;
6267
6745
  const { platform, model } = events[0];
6268
- fs7.mkdirSync(EVENTS_DIR, { recursive: true });
6269
- const logPath = path7.join(EVENTS_DIR, `${platform}_${model}.jsonl`);
6746
+ fs9.mkdirSync(EVENTS_DIR, { recursive: true });
6747
+ const logPath = path9.join(EVENTS_DIR, `${platform}_${model}.jsonl`);
6270
6748
  const lines = events.map((e) => JSON.stringify(e)).join("\n") + "\n";
6271
- fs7.appendFileSync(logPath, lines);
6749
+ fs9.appendFileSync(logPath, lines);
6272
6750
  }
6273
6751
  function runShellHook(command, events) {
6274
6752
  return new Promise((resolve) => {
@@ -6372,8 +6850,8 @@ function sleep(ms) {
6372
6850
  return new Promise((resolve) => setTimeout(resolve, ms));
6373
6851
  }
6374
6852
  function interpolate(template, record) {
6375
- return template.replace(/\{?\{(\w+(?:\.\w+)*)\}\}?/g, (_, path13) => {
6376
- const parts = path13.split(".");
6853
+ return template.replace(/\{?\{(\w+(?:\.\w+)*)\}\}?/g, (_, path15) => {
6854
+ const parts = path15.split(".");
6377
6855
  let value = record;
6378
6856
  for (const part2 of parts) {
6379
6857
  if (typeof value !== "object" || value === null) return "";
@@ -6401,8 +6879,8 @@ function deepMerge(target, source) {
6401
6879
  }
6402
6880
  return result;
6403
6881
  }
6404
- function getByDotPath2(obj, path13) {
6405
- const parts = path13.split(".");
6882
+ function getByDotPath2(obj, path15) {
6883
+ const parts = path15.split(".");
6406
6884
  let current = obj;
6407
6885
  for (const part2 of parts) {
6408
6886
  if (current === null || current === void 0 || typeof current !== "object") return void 0;
@@ -6411,8 +6889,8 @@ function getByDotPath2(obj, path13) {
6411
6889
  return current;
6412
6890
  }
6413
6891
  function stripExcludedFields(obj, paths) {
6414
- for (const path13 of paths) {
6415
- stripOnePath(obj, path13.replace(/\[\]/g, ".*").split("."));
6892
+ for (const path15 of paths) {
6893
+ stripOnePath(obj, path15.replace(/\[\]/g, ".*").split("."));
6416
6894
  }
6417
6895
  }
6418
6896
  function stripOnePath(obj, parts) {
@@ -6833,8 +7311,8 @@ function sleep2(ms) {
6833
7311
  return new Promise((resolve) => setTimeout(resolve, ms));
6834
7312
  }
6835
7313
  function stripFields(record, paths) {
6836
- for (const path13 of paths) {
6837
- stripOnePath2(record, path13.split("."));
7314
+ for (const path15 of paths) {
7315
+ stripOnePath2(record, path15.split("."));
6838
7316
  }
6839
7317
  }
6840
7318
  function stripOnePath2(obj, parts) {
@@ -7927,19 +8405,19 @@ function inferProfileFromKnowledge(knowledge, modelName, platform) {
7927
8405
 
7928
8406
  // src/lib/memory/sync/schedule.ts
7929
8407
  import { spawnSync as spawnSync2 } from "child_process";
7930
- import fs9 from "fs";
8408
+ import fs11 from "fs";
7931
8409
  import os from "os";
7932
- import path9 from "path";
8410
+ import path11 from "path";
7933
8411
 
7934
8412
  // src/lib/memory/sync/schedule-registry.ts
7935
- import fs8 from "fs";
7936
- import path8 from "path";
7937
- var REGISTRY_DIR = () => path8.join(homeDir(), ".one", "sync");
7938
- var REGISTRY_FILE = () => path8.join(REGISTRY_DIR(), "schedules.json");
8413
+ import fs10 from "fs";
8414
+ import path10 from "path";
8415
+ var REGISTRY_DIR = () => path10.join(homeDir(), ".one", "sync");
8416
+ var REGISTRY_FILE = () => path10.join(REGISTRY_DIR(), "schedules.json");
7939
8417
  function readRaw() {
7940
8418
  try {
7941
- if (!fs8.existsSync(REGISTRY_FILE())) return { schedules: [] };
7942
- const raw = fs8.readFileSync(REGISTRY_FILE(), "utf-8");
8419
+ if (!fs10.existsSync(REGISTRY_FILE())) return { schedules: [] };
8420
+ const raw = fs10.readFileSync(REGISTRY_FILE(), "utf-8");
7943
8421
  const parsed = JSON.parse(raw);
7944
8422
  if (!parsed || !Array.isArray(parsed.schedules)) return { schedules: [] };
7945
8423
  return parsed;
@@ -7948,13 +8426,13 @@ function readRaw() {
7948
8426
  }
7949
8427
  }
7950
8428
  function writeRaw(file) {
7951
- fs8.mkdirSync(REGISTRY_DIR(), { recursive: true });
8429
+ fs10.mkdirSync(REGISTRY_DIR(), { recursive: true });
7952
8430
  const tmp = REGISTRY_FILE() + ".tmp";
7953
- fs8.writeFileSync(tmp, JSON.stringify(file, null, 2));
7954
- fs8.renameSync(tmp, REGISTRY_FILE());
8431
+ fs10.writeFileSync(tmp, JSON.stringify(file, null, 2));
8432
+ fs10.renameSync(tmp, REGISTRY_FILE());
7955
8433
  }
7956
8434
  function makeScheduleId(platform, cwd) {
7957
- const slug = path8.basename(cwd).replace(/[^a-zA-Z0-9_-]/g, "-").toLowerCase();
8435
+ const slug = path10.basename(cwd).replace(/[^a-zA-Z0-9_-]/g, "-").toLowerCase();
7958
8436
  return `${platform}-${slug}`;
7959
8437
  }
7960
8438
  function listRegistered() {
@@ -7988,7 +8466,7 @@ function removeRegistered(id) {
7988
8466
 
7989
8467
  // src/lib/memory/sync/schedule.ts
7990
8468
  var MARKER = "# one-sync";
7991
- var LOG_DIR_REL = path9.join(".one", "sync", "logs");
8469
+ var LOG_DIR_REL = path11.join(".one", "sync", "logs");
7992
8470
  function durationToCron(every) {
7993
8471
  const match = every.match(/^(\d+)([mhd])$/);
7994
8472
  if (!match) return null;
@@ -8026,8 +8504,8 @@ function isWindows() {
8026
8504
  function resolveOneBinary() {
8027
8505
  try {
8028
8506
  const entry = process.argv[1];
8029
- if (entry && fs9.existsSync(entry)) {
8030
- return fs9.realpathSync(entry);
8507
+ if (entry && fs11.existsSync(entry)) {
8508
+ return fs11.realpathSync(entry);
8031
8509
  }
8032
8510
  } catch {
8033
8511
  }
@@ -8105,7 +8583,7 @@ function migrateLegacyCronEntries() {
8105
8583
  const modelsMatch = command.match(/--models\s+(\S+)/);
8106
8584
  const models = modelsMatch ? modelsMatch[1].split(",") : void 0;
8107
8585
  const logMatch = command.match(/>>\s+"([^"]+)"/);
8108
- const logFile = logMatch ? logMatch[1] : path9.resolve(cwd, LOG_DIR_REL, `${platform}.log`);
8586
+ const logFile = logMatch ? logMatch[1] : path11.resolve(cwd, LOG_DIR_REL, `${platform}.log`);
8109
8587
  const id = makeScheduleId(platform, cwd);
8110
8588
  if (registeredIds.has(id)) continue;
8111
8589
  upsertRegistered({
@@ -8139,9 +8617,9 @@ function addSchedule(opts) {
8139
8617
  const cwd = process.cwd();
8140
8618
  const id = makeScheduleId(opts.platform, cwd);
8141
8619
  const replaced = getRegistered(id) !== void 0;
8142
- const logDir = path9.join(cwd, LOG_DIR_REL);
8143
- fs9.mkdirSync(logDir, { recursive: true });
8144
- const logFile = path9.join(logDir, `${opts.platform}.log`);
8620
+ const logDir = path11.join(cwd, LOG_DIR_REL);
8621
+ fs11.mkdirSync(logDir, { recursive: true });
8622
+ const logFile = path11.join(logDir, `${opts.platform}.log`);
8145
8623
  const entry = {
8146
8624
  id,
8147
8625
  platform: opts.platform,
@@ -8195,15 +8673,15 @@ function removeSchedule(idOrPlatform, options) {
8195
8673
  function scheduleStatus() {
8196
8674
  const entries = listSchedules();
8197
8675
  return entries.map((entry) => {
8198
- const logExists = fs9.existsSync(entry.logFile);
8199
- const logSize = logExists ? fs9.statSync(entry.logFile).size : 0;
8676
+ const logExists = fs11.existsSync(entry.logFile);
8677
+ const logSize = logExists ? fs11.statSync(entry.logFile).size : 0;
8200
8678
  let logTail = [];
8201
8679
  let lastRunAt = null;
8202
8680
  if (logExists) {
8203
8681
  try {
8204
- lastRunAt = fs9.statSync(entry.logFile).mtime.toISOString();
8682
+ lastRunAt = fs11.statSync(entry.logFile).mtime.toISOString();
8205
8683
  if (logSize > 0) {
8206
- const content = fs9.readFileSync(entry.logFile, "utf-8");
8684
+ const content = fs11.readFileSync(entry.logFile, "utf-8");
8207
8685
  logTail = content.trim().split("\n").slice(-10);
8208
8686
  }
8209
8687
  } catch {
@@ -8211,8 +8689,8 @@ function scheduleStatus() {
8211
8689
  }
8212
8690
  let drift = "ok";
8213
8691
  if (!entry.cronInstalled) drift = "missing-cron";
8214
- else if (!fs9.existsSync(entry.nodeBin)) drift = "stale-node-bin";
8215
- else if (!fs9.existsSync(entry.cliBin)) drift = "stale-cli-bin";
8692
+ else if (!fs11.existsSync(entry.nodeBin)) drift = "stale-node-bin";
8693
+ else if (!fs11.existsSync(entry.cliBin)) drift = "stale-cli-bin";
8216
8694
  return { entry, logExists, logSize, logTail, lastRunAt, drift };
8217
8695
  });
8218
8696
  }
@@ -8485,11 +8963,11 @@ function isNoise(s) {
8485
8963
  if (/^-?\d+(\.\d+)?([eE][-+]?\d+)?$/.test(s)) return true;
8486
8964
  return false;
8487
8965
  }
8488
- function recordSample(stats, path13, value, jsType, recordIndex, totalSamples) {
8489
- let s = stats.get(path13);
8966
+ function recordSample(stats, path15, value, jsType, recordIndex, totalSamples) {
8967
+ let s = stats.get(path15);
8490
8968
  if (!s) {
8491
8969
  s = {
8492
- path: path13,
8970
+ path: path15,
8493
8971
  total: totalSamples,
8494
8972
  recordIndices: /* @__PURE__ */ new Set(),
8495
8973
  lenSum: 0,
@@ -8498,7 +8976,7 @@ function recordSample(stats, path13, value, jsType, recordIndex, totalSamples) {
8498
8976
  primaryType: jsType,
8499
8977
  examples: []
8500
8978
  };
8501
- stats.set(path13, s);
8979
+ stats.set(path15, s);
8502
8980
  }
8503
8981
  s.recordIndices.add(recordIndex);
8504
8982
  s.lenSum += value.length;
@@ -8507,28 +8985,28 @@ function recordSample(stats, path13, value, jsType, recordIndex, totalSamples) {
8507
8985
  if (s.primaryType !== jsType) s.primaryType = "mixed";
8508
8986
  if (s.examples.length < 3 && value.length < 200) s.examples.push(value);
8509
8987
  }
8510
- function walkRecord(record, path13, stats, recordIndex, totalSamples) {
8988
+ function walkRecord(record, path15, stats, recordIndex, totalSamples) {
8511
8989
  if (record === null || record === void 0) return;
8512
8990
  if (typeof record === "string") {
8513
8991
  const trimmed = record.trim();
8514
- if (trimmed) recordSample(stats, path13, trimmed, "string", recordIndex, totalSamples);
8992
+ if (trimmed) recordSample(stats, path15, trimmed, "string", recordIndex, totalSamples);
8515
8993
  return;
8516
8994
  }
8517
8995
  if (typeof record === "number" || typeof record === "boolean") {
8518
8996
  const str = String(record);
8519
8997
  const kind = typeof record === "number" ? "number" : "boolean";
8520
- if (str) recordSample(stats, path13, str, kind, recordIndex, totalSamples);
8998
+ if (str) recordSample(stats, path15, str, kind, recordIndex, totalSamples);
8521
8999
  return;
8522
9000
  }
8523
9001
  if (Array.isArray(record)) {
8524
- const childPath = path13 ? `${path13}[]` : "[]";
9002
+ const childPath = path15 ? `${path15}[]` : "[]";
8525
9003
  for (const item of record) walkRecord(item, childPath, stats, recordIndex, totalSamples);
8526
9004
  return;
8527
9005
  }
8528
9006
  if (typeof record === "object") {
8529
9007
  for (const [key, value] of Object.entries(record)) {
8530
9008
  if (key.startsWith("_")) continue;
8531
- const childPath = path13 ? `${path13}.${key}` : key;
9009
+ const childPath = path15 ? `${path15}.${key}` : key;
8532
9010
  walkRecord(value, childPath, stats, recordIndex, totalSamples);
8533
9011
  }
8534
9012
  }
@@ -8566,7 +9044,7 @@ function suggestSearchablePaths(records, limit = 15) {
8566
9044
  // src/lib/memory/sync/index.ts
8567
9045
  import { spawn as spawn4 } from "child_process";
8568
9046
  import * as p6 from "@clack/prompts";
8569
- import pc10 from "picocolors";
9047
+ import pc11 from "picocolors";
8570
9048
  async function syncInstallCommand() {
8571
9049
  if (await isSqliteAvailable()) {
8572
9050
  if (isAgentMode()) {
@@ -8631,15 +9109,15 @@ async function syncDoctorCommand() {
8631
9109
  return;
8632
9110
  }
8633
9111
  for (const c of checks) {
8634
- const mark = c.ok ? pc10.green("\u2713") : pc10.red("\u2717");
8635
- console.log(` ${mark} ${c.name}${c.detail ? pc10.dim(` \u2014 ${c.detail}`) : ""}`);
9112
+ const mark = c.ok ? pc11.green("\u2713") : pc11.red("\u2717");
9113
+ console.log(` ${mark} ${c.name}${c.detail ? pc11.dim(` \u2014 ${c.detail}`) : ""}`);
8636
9114
  }
8637
9115
  if (!allOk) {
8638
9116
  console.log(`
8639
- ${pc10.yellow("Sync is not ready.")} Try: ${pc10.bold("one sync install")}`);
9117
+ ${pc11.yellow("Sync is not ready.")} Try: ${pc11.bold("one sync install")}`);
8640
9118
  } else {
8641
9119
  console.log(`
8642
- ${pc10.green("Sync is ready.")}`);
9120
+ ${pc11.green("Sync is ready.")}`);
8643
9121
  }
8644
9122
  }
8645
9123
  function getApi() {
@@ -8682,11 +9160,11 @@ async function syncProfilesCommand(platform) {
8682
9160
  if (p9.enrich) extras.push("enrich");
8683
9161
  if (p9.identityKey || p9.identityKeys) extras.push("identity");
8684
9162
  if (p9.dateFilter) extras.push("incremental");
8685
- const tags = extras.length > 0 ? ` ${pc10.dim(`[${extras.join(", ")}]`)}` : "";
8686
- console.log(` ${pc10.bold(`${p9.platform}/${p9.model}`.padEnd(35))} ${p9.description}${tags}`);
9163
+ const tags = extras.length > 0 ? ` ${pc11.dim(`[${extras.join(", ")}]`)}` : "";
9164
+ console.log(` ${pc11.bold(`${p9.platform}/${p9.model}`.padEnd(35))} ${p9.description}${tags}`);
8687
9165
  }
8688
9166
  console.log(`
8689
- ${profiles.length} built-in profile(s). Run ${pc10.bold("one sync init <platform> <model>")} to use one.`);
9167
+ ${profiles.length} built-in profile(s). Run ${pc11.bold("one sync init <platform> <model>")} to use one.`);
8690
9168
  }
8691
9169
  async function syncModelsCommand(platform) {
8692
9170
  const api = getApi();
@@ -8704,7 +9182,7 @@ async function syncModelsCommand(platform) {
8704
9182
  return;
8705
9183
  }
8706
9184
  const lines = models.map(
8707
- (m) => ` ${pc10.bold(m.name.padEnd(30))} ${pc10.dim(m.listAction.method)} ${pc10.dim(m.listAction.path)}`
9185
+ (m) => ` ${pc11.bold(m.name.padEnd(30))} ${pc11.dim(m.listAction.method)} ${pc11.dim(m.listAction.path)}`
8708
9186
  );
8709
9187
  note(lines.join("\n"), `${platform} \u2014 ${models.length} models`);
8710
9188
  } catch (err) {
@@ -8808,15 +9286,15 @@ async function syncInitCommand(platform, model, options) {
8808
9286
  note(JSON.stringify(template, null, 2), "Sync profile template");
8809
9287
  if (inferred && inferred.reasoning.length > 0) {
8810
9288
  console.log(`
8811
- ${pc10.bold("Inferred from knowledge:")}`);
8812
- for (const r of inferred.reasoning) console.log(` ${pc10.dim("\u2022")} ${r}`);
9289
+ ${pc11.bold("Inferred from knowledge:")}`);
9290
+ for (const r of inferred.reasoning) console.log(` ${pc11.dim("\u2022")} ${r}`);
8813
9291
  }
8814
9292
  if (testReport) {
8815
9293
  console.log(`
8816
- ${pc10.bold("Test results:")}`);
9294
+ ${pc11.bold("Test results:")}`);
8817
9295
  for (const c of testReport.checks) {
8818
- const mark = c.ok ? pc10.green("\u2713") : pc10.red("\u2717");
8819
- console.log(` ${mark} ${c.name}${c.detail ? pc10.dim(` \u2014 ${c.detail}`) : ""}`);
9296
+ const mark = c.ok ? pc11.green("\u2713") : pc11.red("\u2717");
9297
+ console.log(` ${mark} ${c.name}${c.detail ? pc11.dim(` \u2014 ${c.detail}`) : ""}`);
8820
9298
  }
8821
9299
  }
8822
9300
  console.log(`
@@ -8899,17 +9377,17 @@ async function syncTestCommand(platformModel, options = {}) {
8899
9377
  return;
8900
9378
  }
8901
9379
  for (const c of report2.checks) {
8902
- const mark = c.ok ? pc10.green("\u2713") : pc10.red("\u2717");
8903
- console.log(` ${mark} ${c.name}${c.detail ? pc10.dim(` \u2014 ${c.detail}`) : ""}`);
9380
+ const mark = c.ok ? pc11.green("\u2713") : pc11.red("\u2717");
9381
+ console.log(` ${mark} ${c.name}${c.detail ? pc11.dim(` \u2014 ${c.detail}`) : ""}`);
8904
9382
  }
8905
9383
  if (report2.detectedColumns && report2.detectedColumns.length > 0) {
8906
9384
  console.log(`
8907
- ${pc10.bold("Detected columns:")}`);
9385
+ ${pc11.bold("Detected columns:")}`);
8908
9386
  for (const col of report2.detectedColumns.slice(0, 20)) {
8909
- console.log(` ${col.name.padEnd(30)} ${pc10.dim(col.type)}`);
9387
+ console.log(` ${col.name.padEnd(30)} ${pc11.dim(col.type)}`);
8910
9388
  }
8911
9389
  if (report2.detectedColumns.length > 20) {
8912
- console.log(pc10.dim(` ... and ${report2.detectedColumns.length - 20} more`));
9390
+ console.log(pc11.dim(` ... and ${report2.detectedColumns.length - 20} more`));
8913
9391
  }
8914
9392
  }
8915
9393
  if (report2.identityKeysPreview) {
@@ -8917,45 +9395,45 @@ async function syncTestCommand(platformModel, options = {}) {
8917
9395
  const total = perRecord.reduce((a, b) => a + b, 0);
8918
9396
  const min = perRecord.length ? Math.min(...perRecord) : 0;
8919
9397
  const max = perRecord.length ? Math.max(...perRecord) : 0;
8920
- const mark = total === 0 ? pc10.yellow("~") : pc10.green("\u2713");
9398
+ const mark = total === 0 ? pc11.yellow("~") : pc11.green("\u2713");
8921
9399
  console.log(`
8922
- ${pc10.bold("Merge + identity keys")} ${pc10.dim(`(cross-platform \u2014 #128)`)}`);
9400
+ ${pc11.bold("Merge + identity keys")} ${pc11.dim(`(cross-platform \u2014 #128)`)}`);
8923
9401
  console.log(` ${mark} ${perRecord.length} sample${perRecord.length === 1 ? "" : "s"}, ${min}\u2013${max} key${max === 1 ? "" : "s"} per record`);
8924
9402
  if (sampleKeys.length > 0) {
8925
- console.log(` ${pc10.dim("e.g.")} ${sampleKeys.slice(0, 8).map((k) => pc10.cyan(k)).join(", ")}`);
9403
+ console.log(` ${pc11.dim("e.g.")} ${sampleKeys.slice(0, 8).map((k) => pc11.cyan(k)).join(", ")}`);
8926
9404
  } else if (resolvesAfterEnrich) {
8927
- console.log(` ${pc10.dim("note:")} 0 on these list-shape samples \u2014 this profile enriches, and its identityKeys paths resolve in the enrich phase.`);
9405
+ console.log(` ${pc11.dim("note:")} 0 on these list-shape samples \u2014 this profile enriches, and its identityKeys paths resolve in the enrich phase.`);
8928
9406
  } else {
8929
- console.log(` ${pc10.yellow("note:")} no identity keys resolved on these samples \u2014 check the identityKey/identityKeys paths.`);
9407
+ console.log(` ${pc11.yellow("note:")} no identity keys resolved on these samples \u2014 check the identityKey/identityKeys paths.`);
8930
9408
  }
8931
9409
  if (entityFanOut) {
8932
- console.log(` ${pc10.yellow("warn:")} identityKey resolved to MULTIPLE values on ${entityFanOut.count} of ${perRecord.length} samples \u2014 those records get NO merge key.`);
8933
- console.log(` ${pc10.dim("saw:")} ${entityFanOut.sampleValues.map((v) => pc10.cyan(v)).join(", ")}`);
8934
- console.log(` ${pc10.dim('A singular identityKey means "this record IS this entity", so a fan-out has no safe answer.')}`);
8935
- console.log(` ${pc10.dim("Point it at a single-valued path, or move it to identityKeys[] for participant associations.")}`);
9410
+ console.log(` ${pc11.yellow("warn:")} identityKey resolved to MULTIPLE values on ${entityFanOut.count} of ${perRecord.length} samples \u2014 those records get NO merge key.`);
9411
+ console.log(` ${pc11.dim("saw:")} ${entityFanOut.sampleValues.map((v) => pc11.cyan(v)).join(", ")}`);
9412
+ console.log(` ${pc11.dim('A singular identityKey means "this record IS this entity", so a fan-out has no safe answer.')}`);
9413
+ console.log(` ${pc11.dim("Point it at a single-valued path, or move it to identityKeys[] for participant associations.")}`);
8936
9414
  }
8937
9415
  }
8938
9416
  if (searchablePreview) {
8939
9417
  console.log(`
8940
- ${pc10.bold("Searchable preview")} ${pc10.dim(`(${searchablePreview.mode}, ${searchablePreview.sampledRecords} sample${searchablePreview.sampledRecords === 1 ? "" : "s"})`)}`);
8941
- console.log(` ${pc10.dim("length:")} ${searchablePreview.length} chars (first sample)`);
8942
- console.log(` ${pc10.dim("text:")} ${searchablePreview.text.slice(0, 300)}${searchablePreview.length > 300 ? pc10.dim(" \u2026") : ""}`);
9418
+ ${pc11.bold("Searchable preview")} ${pc11.dim(`(${searchablePreview.mode}, ${searchablePreview.sampledRecords} sample${searchablePreview.sampledRecords === 1 ? "" : "s"})`)}`);
9419
+ console.log(` ${pc11.dim("length:")} ${searchablePreview.length} chars (first sample)`);
9420
+ console.log(` ${pc11.dim("text:")} ${searchablePreview.text.slice(0, 300)}${searchablePreview.length > 300 ? pc11.dim(" \u2026") : ""}`);
8943
9421
  if (searchablePreview.paths) {
8944
- console.log(` ${pc10.dim("paths:")} ${pc10.dim('(hit rate across all samples \u2014 differentiates "wrong path" from "field sometimes missing")')}`);
9422
+ console.log(` ${pc11.dim("paths:")} ${pc11.dim('(hit rate across all samples \u2014 differentiates "wrong path" from "field sometimes missing")')}`);
8945
9423
  for (const p9 of searchablePreview.paths) {
8946
9424
  const rate = `${p9.hits}/${p9.total}`;
8947
- const mark = p9.hits === p9.total ? pc10.green("\u2713") : p9.hits === 0 ? pc10.red("\u2717") : pc10.yellow("~");
8948
- 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)") : "";
9425
+ const mark = p9.hits === p9.total ? pc11.green("\u2713") : p9.hits === 0 ? pc11.red("\u2717") : pc11.yellow("~");
9426
+ const trailer = p9.sample ? pc11.dim(` \u2192 "${p9.sample}"`) : p9.hits === 0 ? pc11.dim(" (no sample matched \u2014 typo, or field never populated in this page)") : "";
8949
9427
  console.log(` ${mark} ${rate.padStart(5)} ${p9.path}${trailer}`);
8950
9428
  }
8951
9429
  } else {
8952
- console.log(` ${pc10.yellow("note:")} no memory.searchable declared \u2014 using the default walker (walks every field, often noisy).`);
8953
- 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.`);
9430
+ console.log(` ${pc11.yellow("note:")} no memory.searchable declared \u2014 using the default walker (walks every field, often noisy).`);
9431
+ console.log(` ${pc11.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.`);
8954
9432
  }
8955
9433
  }
8956
9434
  console.log(
8957
9435
  `
8958
- ${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.")
9436
+ ${report2.ok ? pc11.green("Profile looks good.") : pc11.red("Profile has issues.")} ` + (report2.ok ? `Run: ${pc11.bold(`one sync run ${platform} --models ${model}`)}` : "Fix the issues above and test again.")
8959
9437
  );
8960
9438
  }
8961
9439
  function buildSearchablePreview(profile, samples) {
@@ -8963,7 +9441,7 @@ function buildSearchablePreview(profile, samples) {
8963
9441
  const first = samples[0];
8964
9442
  const paths = getSearchablePaths(profile);
8965
9443
  if (paths) {
8966
- const perPathAgg = paths.map((path13) => ({ path: path13, hits: 0, total: samples.length, sample: "" }));
9444
+ const perPathAgg = paths.map((path15) => ({ path: path15, hits: 0, total: samples.length, sample: "" }));
8967
9445
  for (const record of samples) {
8968
9446
  const { paths: perPath } = extractSearchableFromPaths(record, paths);
8969
9447
  perPath.forEach((p9, i) => {
@@ -8996,8 +9474,8 @@ async function syncRunCommand(platform, options) {
8996
9474
  if (profileDrift.length > 0 && !isAgentMode()) {
8997
9475
  for (const d of profileDrift) {
8998
9476
  console.log(
8999
- ` ${pc10.yellow("!")} ${platform}/${d.model} is missing ${d.missing.map((f) => pc10.bold(f)).join(", ")} from the current built-in profile.
9000
- Run ${pc10.bold(`one sync init ${platform} ${d.model}`)} to pick ${d.missing.length > 1 ? "them" : "it"} up.`
9477
+ ` ${pc11.yellow("!")} ${platform}/${d.model} is missing ${d.missing.map((f) => pc11.bold(f)).join(", ")} from the current built-in profile.
9478
+ Run ${pc11.bold(`one sync init ${platform} ${d.model}`)} to pick ${d.missing.length > 1 ? "them" : "it"} up.`
9001
9479
  );
9002
9480
  }
9003
9481
  }
@@ -9040,21 +9518,21 @@ async function syncRunCommand(platform, options) {
9040
9518
  return;
9041
9519
  }
9042
9520
  for (const r of results) {
9043
- const status2 = r.status === "complete" ? pc10.green("complete") : r.status === "dry-run" ? pc10.yellow("dry-run") : pc10.red("failed");
9044
- console.log(` ${pc10.bold(r.model)} \u2014 ${r.recordsSynced} records, ${r.pagesProcessed} pages, ${r.duration} [${status2}]`);
9521
+ const status2 = r.status === "complete" ? pc11.green("complete") : r.status === "dry-run" ? pc11.yellow("dry-run") : pc11.red("failed");
9522
+ console.log(` ${pc11.bold(r.model)} \u2014 ${r.recordsSynced} records, ${r.pagesProcessed} pages, ${r.duration} [${status2}]`);
9045
9523
  if (r.reconcileSkipped) {
9046
- console.log(` ${pc10.yellow("--full-refresh reconcile skipped \u2014 pagination truncated (e.g. --max-pages). Re-run without the cap to prune stale rows.")}`);
9524
+ console.log(` ${pc11.yellow("--full-refresh reconcile skipped \u2014 pagination truncated (e.g. --max-pages). Re-run without the cap to prune stale rows.")}`);
9047
9525
  }
9048
9526
  const sc = r.statusCounts;
9049
9527
  if (sc && (sc.archived > 0 || sc.active > 0)) {
9050
- const archivedColor = sc.archived > sc.active ? pc10.red : pc10.dim;
9051
- console.log(` memory: ${pc10.green(String(sc.active))} active, ${archivedColor(String(sc.archived))} archived`);
9528
+ const archivedColor = sc.archived > sc.active ? pc11.red : pc11.dim;
9529
+ console.log(` memory: ${pc11.green(String(sc.active))} active, ${archivedColor(String(sc.archived))} archived`);
9052
9530
  }
9053
9531
  if (r.error) {
9054
9532
  const errParts = [r.error.message];
9055
9533
  if (r.error.httpStatus) errParts.push(`HTTP ${r.error.httpStatus}`);
9056
9534
  if (r.error.retryAfter) errParts.push(`retry after ${r.error.retryAfter}s`);
9057
- console.log(` ${pc10.red(errParts.join(" \u2014 "))}`);
9535
+ console.log(` ${pc11.red(errParts.join(" \u2014 "))}`);
9058
9536
  }
9059
9537
  }
9060
9538
  }
@@ -9080,8 +9558,8 @@ async function syncQueryCommand(platformModel, options) {
9080
9558
  json(result);
9081
9559
  return;
9082
9560
  }
9083
- console.log(pc10.dim(`Query: ${result.query}`));
9084
- console.log(pc10.dim(`Source: local | Last sync: ${result.lastSync ?? "never"} | Age: ${result.syncAge ?? "n/a"}`));
9561
+ console.log(pc11.dim(`Query: ${result.query}`));
9562
+ console.log(pc11.dim(`Source: local | Last sync: ${result.lastSync ?? "never"} | Age: ${result.syncAge ?? "n/a"}`));
9085
9563
  console.log(JSON.stringify(result.results, null, 2));
9086
9564
  console.log(`
9087
9565
  ${result.total} results`);
@@ -9103,7 +9581,7 @@ async function syncSearchCommand(query, options) {
9103
9581
  return;
9104
9582
  }
9105
9583
  for (const r of result.results) {
9106
- console.log(` ${pc10.bold(`${r.platform}/${r.model}`)} ${pc10.dim(`(rank: ${r.rank.toFixed(2)})`)}`);
9584
+ console.log(` ${pc11.bold(`${r.platform}/${r.model}`)} ${pc11.dim(`(rank: ${r.rank.toFixed(2)})`)}`);
9107
9585
  console.log(` ${JSON.stringify(r.record)}`);
9108
9586
  }
9109
9587
  console.log(`
@@ -9254,25 +9732,25 @@ async function syncSuggestSearchableCommand(platformModel, options = {}) {
9254
9732
  return;
9255
9733
  }
9256
9734
  console.log(`
9257
- ${pc10.bold("memory.searchable \u2014 ranked suggestions")} ${pc10.dim(`(${samples.length} samples)`)}`);
9735
+ ${pc11.bold("memory.searchable \u2014 ranked suggestions")} ${pc11.dim(`(${samples.length} samples)`)}`);
9258
9736
  if (suggestions.length === 0) {
9259
- 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.`);
9737
+ console.log(` ${pc11.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.`);
9260
9738
  return;
9261
9739
  }
9262
9740
  for (const s of suggestions) {
9263
9741
  const hitPct = Math.round(s.hitRate * 100);
9264
9742
  const noisePct = Math.round(s.noiseFraction * 100);
9265
- const noiseBadge = noisePct > 0 ? pc10.dim(` noise=${noisePct}%`) : "";
9743
+ const noiseBadge = noisePct > 0 ? pc11.dim(` noise=${noisePct}%`) : "";
9266
9744
  console.log(
9267
- ` ${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(`
9745
+ ` ${pc11.green(String(s.score).padStart(5))} ${pc11.cyan(s.path.padEnd(52))}` + pc11.dim(` ${hitPct}% hit`) + pc11.dim(` avg=${s.avgLength}ch`) + noiseBadge + (s.sampleValue ? pc11.dim(`
9268
9746
  \u2192 "${s.sampleValue.slice(0, 140)}"`) : "")
9269
9747
  );
9270
9748
  }
9271
9749
  console.log(`
9272
- ${pc10.bold("Paste-ready:")}`);
9273
- console.log(" " + pc10.cyan(`one sync init ${platform} ${model} --config '${JSON.stringify(configPatch)}'`));
9750
+ ${pc11.bold("Paste-ready:")}`);
9751
+ console.log(" " + pc11.cyan(`one sync init ${platform} ${model} --config '${JSON.stringify(configPatch)}'`));
9274
9752
  console.log(`
9275
- ${pc10.dim("then preview: ")}${pc10.cyan(`one sync test ${platform}/${model} --show-searchable`)}`);
9753
+ ${pc11.dim("then preview: ")}${pc11.cyan(`one sync test ${platform}/${model} --show-searchable`)}`);
9276
9754
  }
9277
9755
  async function syncListCommand(platform) {
9278
9756
  const profiles = listProfiles(platform);
@@ -9306,10 +9784,10 @@ async function syncListCommand(platform) {
9306
9784
  return;
9307
9785
  }
9308
9786
  for (const s of syncs) {
9309
- const status2 = s.status === "idle" ? pc10.green("idle") : s.status === "syncing" ? pc10.yellow(`syncing \u2014 page ${s.pagesProcessed}`) : pc10.red("failed");
9310
- const legacy = s.legacyDbSize && s.legacyDbSize !== "0 B" ? pc10.yellow(` legacy .db ${s.legacyDbSize}`) : "";
9787
+ const status2 = s.status === "idle" ? pc11.green("idle") : s.status === "syncing" ? pc11.yellow(`syncing \u2014 page ${s.pagesProcessed}`) : pc11.red("failed");
9788
+ const legacy = s.legacyDbSize && s.legacyDbSize !== "0 B" ? pc11.yellow(` legacy .db ${s.legacyDbSize}`) : "";
9311
9789
  console.log(
9312
- ` ${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
9790
+ ` ${pc11.bold(`${s.platform}/${s.model}`.padEnd(35))} ${String(s.totalRecords).padStart(8)} records ${status2} ${pc11.dim(s.lastSync ? `last: ${s.lastSync}` : "never synced")}` + legacy
9313
9791
  );
9314
9792
  }
9315
9793
  }
@@ -9388,8 +9866,8 @@ async function syncScheduleAddCommand(platform, options) {
9388
9866
  }
9389
9867
  const verb = replaced ? "Replaced existing schedule" : "Scheduled sync";
9390
9868
  outro(
9391
- `${verb} ${pc10.bold(entry.id)} \u2014 every ${pc10.bold(entry.every)} (cron: ${pc10.dim(entry.cronExpr)})
9392
- Logs: ${pc10.dim(entry.logFile)}`
9869
+ `${verb} ${pc11.bold(entry.id)} \u2014 every ${pc11.bold(entry.every)} (cron: ${pc11.dim(entry.cronExpr)})
9870
+ Logs: ${pc11.dim(entry.logFile)}`
9393
9871
  );
9394
9872
  } catch (err) {
9395
9873
  error(err instanceof Error ? err.message : String(err));
@@ -9408,14 +9886,14 @@ async function syncScheduleListCommand() {
9408
9886
  }
9409
9887
  for (const e of entries) {
9410
9888
  const modelsStr = e.models ? ` [${e.models.join(",")}]` : "";
9411
- const installed = e.cronInstalled ? pc10.green("\u25CF") : pc10.red("\u2717");
9889
+ const installed = e.cronInstalled ? pc11.green("\u25CF") : pc11.red("\u2717");
9412
9890
  console.log(
9413
- ` ${installed} ${pc10.bold(e.id.padEnd(32))} every ${pc10.bold(e.every.padEnd(5))} ${pc10.dim(e.cronExpr.padEnd(13))}${modelsStr}`
9891
+ ` ${installed} ${pc11.bold(e.id.padEnd(32))} every ${pc11.bold(e.every.padEnd(5))} ${pc11.dim(e.cronExpr.padEnd(13))}${modelsStr}`
9414
9892
  );
9415
- console.log(` ${pc10.dim("cwd:")} ${e.cwd}`);
9893
+ console.log(` ${pc11.dim("cwd:")} ${e.cwd}`);
9416
9894
  }
9417
9895
  console.log(`
9418
- ${pc10.dim("\u25CF = cron line installed \u2717 = registry drift, run `sync schedule repair <id>`")}`);
9896
+ ${pc11.dim("\u25CF = cron line installed \u2717 = registry drift, run `sync schedule repair <id>`")}`);
9419
9897
  } catch (err) {
9420
9898
  error(err instanceof Error ? err.message : String(err));
9421
9899
  }
@@ -9439,7 +9917,7 @@ async function syncScheduleRemoveCommand(idOrPlatform, options) {
9439
9917
  return;
9440
9918
  }
9441
9919
  for (const r of result.removed) {
9442
- console.log(` ${pc10.green("\u2713")} removed ${pc10.bold(r.id)} ${pc10.dim(`(${r.cwd})`)}`);
9920
+ console.log(` ${pc11.green("\u2713")} removed ${pc11.bold(r.id)} ${pc11.dim(`(${r.cwd})`)}`);
9443
9921
  }
9444
9922
  } catch (err) {
9445
9923
  error(err instanceof Error ? err.message : String(err));
@@ -9457,21 +9935,21 @@ async function syncScheduleStatusCommand() {
9457
9935
  return;
9458
9936
  }
9459
9937
  for (const s of statuses) {
9460
- const driftMarker = s.drift === "ok" ? pc10.green("\u25CF") : s.drift === "missing-cron" ? pc10.red("\u2717 missing cron line") : pc10.yellow(`\u26A0 ${s.drift}`);
9461
- console.log(` ${driftMarker} ${pc10.bold(s.entry.id)} \u2014 every ${s.entry.every} (${pc10.dim(s.entry.cronExpr)})`);
9462
- console.log(` ${pc10.dim("cwd:")} ${s.entry.cwd}`);
9463
- console.log(` ${pc10.dim("last run:")} ${s.lastRunAt ?? pc10.yellow("never")}`);
9464
- console.log(` ${pc10.dim("log:")} ${s.entry.logFile} ${s.logExists ? pc10.dim(`(${s.logSize} bytes)`) : pc10.yellow("(empty)")}`);
9938
+ const driftMarker = s.drift === "ok" ? pc11.green("\u25CF") : s.drift === "missing-cron" ? pc11.red("\u2717 missing cron line") : pc11.yellow(`\u26A0 ${s.drift}`);
9939
+ console.log(` ${driftMarker} ${pc11.bold(s.entry.id)} \u2014 every ${s.entry.every} (${pc11.dim(s.entry.cronExpr)})`);
9940
+ console.log(` ${pc11.dim("cwd:")} ${s.entry.cwd}`);
9941
+ console.log(` ${pc11.dim("last run:")} ${s.lastRunAt ?? pc11.yellow("never")}`);
9942
+ console.log(` ${pc11.dim("log:")} ${s.entry.logFile} ${s.logExists ? pc11.dim(`(${s.logSize} bytes)`) : pc11.yellow("(empty)")}`);
9465
9943
  if (s.logTail.length > 0) {
9466
- console.log(pc10.dim(" last lines:"));
9944
+ console.log(pc11.dim(" last lines:"));
9467
9945
  for (const line of s.logTail.slice(-3)) {
9468
- console.log(pc10.dim(` ${line}`));
9946
+ console.log(pc11.dim(` ${line}`));
9469
9947
  }
9470
9948
  }
9471
9949
  }
9472
9950
  if (statuses.some((s) => s.drift !== "ok")) {
9473
9951
  console.log(`
9474
- ${pc10.yellow("Drift detected.")} Run ${pc10.bold("one sync schedule repair <id>")} to heal.`);
9952
+ ${pc11.yellow("Drift detected.")} Run ${pc11.bold("one sync schedule repair <id>")} to heal.`);
9475
9953
  }
9476
9954
  } catch (err) {
9477
9955
  error(err instanceof Error ? err.message : String(err));
@@ -9484,7 +9962,7 @@ async function syncScheduleRepairCommand(id) {
9484
9962
  json({ status: "repaired", ...healed });
9485
9963
  return;
9486
9964
  }
9487
- outro(`Repaired ${pc10.bold(healed.id)}: re-installed cron line with current node/cli paths.`);
9965
+ outro(`Repaired ${pc11.bold(healed.id)}: re-installed cron line with current node/cli paths.`);
9488
9966
  } catch (err) {
9489
9967
  error(err instanceof Error ? err.message : String(err));
9490
9968
  }
@@ -9920,16 +10398,16 @@ function projectEmbeddingApiKey(cfg) {
9920
10398
  }
9921
10399
  function redactSecrets(cfg) {
9922
10400
  const copy = JSON.parse(JSON.stringify(cfg));
9923
- for (const path13 of SECRET_PATHS) {
9924
- const val = getPath(copy, path13);
10401
+ for (const path15 of SECRET_PATHS) {
10402
+ const val = getPath(copy, path15);
9925
10403
  if (typeof val === "string" && val.length > 0) {
9926
- setPath(copy, path13, `${val.slice(0, 6)}\u2026(redacted, use --show-secrets)`);
10404
+ setPath(copy, path15, `${val.slice(0, 6)}\u2026(redacted, use --show-secrets)`);
9927
10405
  }
9928
10406
  }
9929
10407
  return copy;
9930
10408
  }
9931
- function getPath(obj, path13) {
9932
- const parts = path13.split(".");
10409
+ function getPath(obj, path15) {
10410
+ const parts = path15.split(".");
9933
10411
  let cur = obj;
9934
10412
  for (const part2 of parts) {
9935
10413
  if (cur == null || typeof cur !== "object") return void 0;
@@ -9937,8 +10415,8 @@ function getPath(obj, path13) {
9937
10415
  }
9938
10416
  return cur;
9939
10417
  }
9940
- function setPath(obj, path13, value) {
9941
- const parts = path13.split(".");
10418
+ function setPath(obj, path15, value) {
10419
+ const parts = path15.split(".");
9942
10420
  let cur = obj;
9943
10421
  for (let i = 0; i < parts.length - 1; i++) {
9944
10422
  const part2 = parts[i];
@@ -9948,8 +10426,8 @@ function setPath(obj, path13, value) {
9948
10426
  cur[parts[parts.length - 1]] = value;
9949
10427
  return obj;
9950
10428
  }
9951
- function unsetPath(obj, path13) {
9952
- const parts = path13.split(".");
10429
+ function unsetPath(obj, path15) {
10430
+ const parts = path15.split(".");
9953
10431
  let cur = obj;
9954
10432
  for (let i = 0; i < parts.length - 1; i++) {
9955
10433
  const part2 = parts[i];
@@ -9975,7 +10453,7 @@ function parseValue(raw) {
9975
10453
  }
9976
10454
 
9977
10455
  // src/commands/mem/records.ts
9978
- import pc11 from "picocolors";
10456
+ import pc12 from "picocolors";
9979
10457
  async function memAddCommand(type, dataRaw, flags) {
9980
10458
  requireMemoryInit();
9981
10459
  const data = parseJsonArg(dataRaw, "data");
@@ -10174,7 +10652,7 @@ function summarizeRecord(r) {
10174
10652
  const v = d[field];
10175
10653
  if (typeof v === "string" && v.trim()) return v.trim().slice(0, 80);
10176
10654
  }
10177
- return pc11.dim("(untitled)");
10655
+ return pc12.dim("(untitled)");
10178
10656
  }
10179
10657
  function relativeTime(iso) {
10180
10658
  if (!iso) return "";
@@ -10237,7 +10715,7 @@ async function memFindByKeyCommand(key, secondKey, flags) {
10237
10715
  });
10238
10716
  return;
10239
10717
  }
10240
- const label = matchedKeys.map((k) => pc11.cyan(k)).join(pc11.dim(" + "));
10718
+ const label = matchedKeys.map((k) => pc12.cyan(k)).join(pc12.dim(" + "));
10241
10719
  if (records.length === 0) {
10242
10720
  console.log(`
10243
10721
  No records linked to ${label}.
@@ -10245,27 +10723,27 @@ async function memFindByKeyCommand(key, secondKey, flags) {
10245
10723
  return;
10246
10724
  }
10247
10725
  console.log();
10248
- console.log(` ${label} ${pc11.dim("\u2014")} ${records.length}${truncated ? "+" : ""} record${records.length === 1 ? "" : "s"} across ${byType.size} type${byType.size === 1 ? "" : "s"}`);
10726
+ console.log(` ${label} ${pc12.dim("\u2014")} ${records.length}${truncated ? "+" : ""} record${records.length === 1 ? "" : "s"} across ${byType.size} type${byType.size === 1 ? "" : "s"}`);
10249
10727
  console.log();
10250
10728
  const typeWidth = Math.min(30, Math.max(...[...byType.keys()].map((t) => t.length)));
10251
10729
  for (const [type, list] of byType) {
10252
- console.log(` ${pc11.bold(type.padEnd(typeWidth))} ${pc11.dim(`${list.length} record${list.length === 1 ? "" : "s"}`)}`);
10730
+ console.log(` ${pc12.bold(type.padEnd(typeWidth))} ${pc12.dim(`${list.length} record${list.length === 1 ? "" : "s"}`)}`);
10253
10731
  for (const r of list.slice(0, perType)) {
10254
- console.log(` ${pc11.dim("\xB7")} ${summarizeRecord(r)} ${pc11.dim(relativeTime(r.updated_at))} ${pc11.dim(r.id)}`);
10732
+ console.log(` ${pc12.dim("\xB7")} ${summarizeRecord(r)} ${pc12.dim(relativeTime(r.updated_at))} ${pc12.dim(r.id)}`);
10255
10733
  }
10256
10734
  if (list.length > perType) {
10257
- console.log(` ${pc11.dim(`\u2026 and ${list.length - perType} more (raise --limit)`)}`);
10735
+ console.log(` ${pc12.dim(`\u2026 and ${list.length - perType} more (raise --limit)`)}`);
10258
10736
  }
10259
10737
  }
10260
10738
  if (truncated) {
10261
10739
  console.log();
10262
- 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.`);
10740
+ console.log(` ${pc12.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.`);
10263
10741
  }
10264
10742
  console.log();
10265
10743
  }
10266
10744
 
10267
10745
  // src/commands/mem/doctor.ts
10268
- import pc12 from "picocolors";
10746
+ import pc13 from "picocolors";
10269
10747
  async function memDoctorCommand() {
10270
10748
  const checks = [];
10271
10749
  const cfg = getMemoryConfig();
@@ -10372,23 +10850,23 @@ function emit(checks, capInfo) {
10372
10850
  return;
10373
10851
  }
10374
10852
  for (const c of checks) {
10375
- const mark = c.ok ? pc12.green("\u2713") : pc12.red("\u2717");
10376
- const detail = c.detail ? pc12.dim(` \u2014 ${c.detail}`) : "";
10853
+ const mark = c.ok ? pc13.green("\u2713") : pc13.red("\u2717");
10854
+ const detail = c.detail ? pc13.dim(` \u2014 ${c.detail}`) : "";
10377
10855
  console.log(` ${mark} ${c.name}${detail}`);
10378
10856
  }
10379
10857
  if (!allOk) {
10380
- console.log("\n" + pc12.yellow("Memory is not fully healthy."));
10858
+ console.log("\n" + pc13.yellow("Memory is not fully healthy."));
10381
10859
  process.exitCode = 1;
10382
10860
  } else {
10383
- console.log("\n" + pc12.green("Memory is healthy."));
10861
+ console.log("\n" + pc13.green("Memory is healthy."));
10384
10862
  }
10385
10863
  const line = semanticSearchUpgradeLine({ vectorSearchAvailable: capInfo.vectorSearchAvailable });
10386
10864
  if (line) console.log(`
10387
- ${pc12.dim(line)}`);
10865
+ ${pc13.dim(line)}`);
10388
10866
  }
10389
10867
 
10390
10868
  // src/commands/mem/export.ts
10391
- import fs10 from "fs";
10869
+ import fs12 from "fs";
10392
10870
  import { once } from "events";
10393
10871
  async function writeLine(stream, line) {
10394
10872
  if (!stream.write(line)) {
@@ -10400,7 +10878,7 @@ async function memExportCommand(outfile) {
10400
10878
  const backend = await getBackend();
10401
10879
  const stats = await backend.stats();
10402
10880
  const toFile = !!outfile && outfile !== "-";
10403
- const stream = toFile ? fs10.createWriteStream(outfile, "utf-8") : process.stdout;
10881
+ const stream = toFile ? fs12.createWriteStream(outfile, "utf-8") : process.stdout;
10404
10882
  const all = await listAllTypes(backend);
10405
10883
  const pageSize = 500;
10406
10884
  let written = 0;
@@ -10431,9 +10909,9 @@ async function memExportCommand(outfile) {
10431
10909
  }
10432
10910
  async function memImportCommand(file) {
10433
10911
  requireMemoryInit();
10434
- if (!fs10.existsSync(file)) error(`File not found: ${file}`);
10912
+ if (!fs12.existsSync(file)) error(`File not found: ${file}`);
10435
10913
  const backend = await getBackend();
10436
- const raw = fs10.readFileSync(file, "utf-8");
10914
+ const raw = fs12.readFileSync(file, "utf-8");
10437
10915
  const lines = raw.split("\n").filter((l) => l.trim().length > 0);
10438
10916
  let inserted = 0;
10439
10917
  let updated = 0;
@@ -10679,7 +11157,7 @@ function registerMemoryCommands(program2) {
10679
11157
  }
10680
11158
 
10681
11159
  // src/commands/cache.ts
10682
- import pc13 from "picocolors";
11160
+ import pc14 from "picocolors";
10683
11161
  async function cacheClearCommand(actionId) {
10684
11162
  if (actionId) {
10685
11163
  const deleted = clearEntry(actionId);
@@ -10688,9 +11166,9 @@ async function cacheClearCommand(actionId) {
10688
11166
  return;
10689
11167
  }
10690
11168
  if (deleted) {
10691
- console.log(`Cleared cache for ${pc13.cyan(actionId)}`);
11169
+ console.log(`Cleared cache for ${pc14.cyan(actionId)}`);
10692
11170
  } else {
10693
- console.log(`No cache entry found for ${pc13.dim(actionId)}`);
11171
+ console.log(`No cache entry found for ${pc14.dim(actionId)}`);
10694
11172
  }
10695
11173
  } else {
10696
11174
  const count = clearAll();
@@ -10727,7 +11205,7 @@ async function cacheListCommand(options) {
10727
11205
  type: e.type,
10728
11206
  key: e.entry.key,
10729
11207
  age: formatAge(getAge(e.entry)),
10730
- status: isFresh(e.entry) ? pc13.green("fresh") : pc13.yellow("expired")
11208
+ status: isFresh(e.entry) ? pc14.green("fresh") : pc14.yellow("expired")
10731
11209
  }));
10732
11210
  printTable(
10733
11211
  [
@@ -10780,13 +11258,13 @@ async function cacheUpdateAllCommand() {
10780
11258
  if (errors.length > 0) {
10781
11259
  console.log();
10782
11260
  for (const e of errors) {
10783
- console.log(` ${pc13.red("\u2717")} ${e.key}: ${pc13.dim(e.error)}`);
11261
+ console.log(` ${pc14.red("\u2717")} ${e.key}: ${pc14.dim(e.error)}`);
10784
11262
  }
10785
11263
  }
10786
11264
  }
10787
11265
 
10788
11266
  // src/commands/guide.ts
10789
- import pc14 from "picocolors";
11267
+ import pc15 from "picocolors";
10790
11268
 
10791
11269
  // src/lib/guide-content.ts
10792
11270
  var GUIDE_OVERVIEW = `# One CLI \u2014 Agent Guide
@@ -10901,6 +11379,9 @@ one --agent relay deliveries --endpoint-id <id> # Check delivery
10901
11379
  - \`--create-webhook\` auto-registers the webhook URL with the source platform
10902
11380
  - Use \`actions find\` (and \`actions load\` for more) to learn both the incoming payload shape AND the destination API shape before building templates
10903
11381
 
11382
+ ### One Connect apps \u2014 created from \`one.connect.ts\`
11383
+ \`one connect create\` reads \`one.connect.ts\`, typed by \`defineConnectApp\` from \`@withone/connect/config\` (install \`@withone/connect\` 0.19.0 or later in the project first), and opens a setup page where the human reviews the app (or, once .env holds its \`ONE_CLIENT_ID\`, its new version) and approves it with their dashboard session; an API key never creates or changes a Connect app. A new app's client secret and connect key are made and shown there once; the CLI never receives them. It waits up to 10 minutes, then writes \`ONE_CLIENT_ID\`, \`ONE_PERMISSION_SET\` and \`ONE_REDIRECT_URI\` to the env file. \`one connect types\` writes \`one-connect-env.d.ts\` so tool slugs and action names autocomplete. Each tool's \`access\` is \`read-only\`, \`read-write\`, \`full-access\`, or \`custom\` with \`actions\` (names, or ids from \`actions find\`).
11384
+
10904
11385
  ### 4. Memory + Sync \u2014 Unified store with hybrid FTS + semantic search
10905
11386
  One ships a local memory store (a real Postgres process bootstrapped on demand via the bundled \`embedded-postgres\` plugin, with a \`postgres\` plugin for remote/self-hosted) that backs both user-authored notes (\`one mem add\`) and synced platform data (\`one sync run\`). Auto-initializes on first use \u2014 no separate install step. Run \`one guide memory\` and \`one guide sync\` for the full references.
10906
11387
 
@@ -11992,14 +12473,14 @@ async function guideCommand(topic = "all") {
11992
12473
  json({ topic, title, content, availableTopics });
11993
12474
  return;
11994
12475
  }
11995
- intro(pc14.bgCyan(pc14.black(" One Guide ")));
12476
+ intro(pc15.bgCyan(pc15.black(" One Guide ")));
11996
12477
  console.log();
11997
12478
  console.log(content);
11998
- console.log(pc14.dim("\u2500".repeat(60)));
12479
+ console.log(pc15.dim("\u2500".repeat(60)));
11999
12480
  console.log(
12000
- pc14.dim("Available topics: ") + availableTopics.map((t) => pc14.cyan(t.topic)).join(", ")
12481
+ pc15.dim("Available topics: ") + availableTopics.map((t) => pc15.cyan(t.topic)).join(", ")
12001
12482
  );
12002
- console.log(pc14.dim(`Run ${pc14.cyan("one guide <topic>")} for a specific section.`));
12483
+ console.log(pc15.dim(`Run ${pc15.cyan("one guide <topic>")} for a specific section.`));
12003
12484
  }
12004
12485
 
12005
12486
  // src/lib/platform-meta.ts
@@ -12319,24 +12800,24 @@ function buildWorkflowIdeas(connections) {
12319
12800
  }
12320
12801
 
12321
12802
  // src/commands/logout.ts
12322
- import fs11 from "fs";
12803
+ import fs13 from "fs";
12323
12804
  import * as p8 from "@clack/prompts";
12324
- function formatWhoami(config2, apiKey, pc16) {
12805
+ function formatWhoami(config2, apiKey, pc17) {
12325
12806
  const whoami = config2.whoami;
12326
12807
  const env = getEnvFromApiKey(apiKey);
12327
- const envLabel = env === "test" ? pc16.yellow("test") : pc16.green("live");
12808
+ const envLabel = env === "test" ? pc17.yellow("test") : pc17.green("live");
12328
12809
  const lines = [];
12329
12810
  if (whoami) {
12330
12811
  const contextParts = [];
12331
12812
  if (whoami.organization) contextParts.push(whoami.organization.name);
12332
12813
  if (whoami.project) contextParts.push(whoami.project.name);
12333
12814
  const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
12334
- lines.push(`${pc16.bold(scopeDisplay)} ${pc16.dim("\xB7")} ${envLabel}`);
12335
- lines.push(`${whoami.user.name} ${pc16.dim(`(${whoami.user.email})`)}`);
12336
- if (config2.apiKeyName) lines.push(`${pc16.dim("Key:")} ${config2.apiKeyName}`);
12815
+ lines.push(`${pc17.bold(scopeDisplay)} ${pc17.dim("\xB7")} ${envLabel}`);
12816
+ lines.push(`${whoami.user.name} ${pc17.dim(`(${whoami.user.email})`)}`);
12817
+ if (config2.apiKeyName) lines.push(`${pc17.dim("Key:")} ${config2.apiKeyName}`);
12337
12818
  } else {
12338
12819
  const keyLabel = config2.apiKeyName ?? `${apiKey.slice(0, 8)}...`;
12339
- lines.push(`${pc16.dim("Key:")} ${keyLabel} ${pc16.dim("\xB7")} ${envLabel}`);
12820
+ lines.push(`${pc17.dim("Key:")} ${keyLabel} ${pc17.dim("\xB7")} ${envLabel}`);
12340
12821
  }
12341
12822
  return lines;
12342
12823
  }
@@ -12354,18 +12835,18 @@ async function logoutCommand() {
12354
12835
  const globalPath = getGlobalConfigPath();
12355
12836
  const projectPath = getProjectConfigPath();
12356
12837
  let cleared = false;
12357
- if (fs11.existsSync(projectPath)) {
12358
- fs11.unlinkSync(projectPath);
12838
+ if (fs13.existsSync(projectPath)) {
12839
+ fs13.unlinkSync(projectPath);
12359
12840
  cleared = true;
12360
12841
  }
12361
- if (fs11.existsSync(globalPath)) {
12362
- fs11.unlinkSync(globalPath);
12842
+ if (fs13.existsSync(globalPath)) {
12843
+ fs13.unlinkSync(globalPath);
12363
12844
  cleared = true;
12364
12845
  }
12365
12846
  json({ status: cleared ? "logged_out" : "not_logged_in", message: cleared ? "Credentials cleared." : "No config found." });
12366
12847
  return;
12367
12848
  }
12368
- const pc16 = (await import("picocolors")).default;
12849
+ const pc17 = (await import("picocolors")).default;
12369
12850
  const globalConfig = readGlobalConfig();
12370
12851
  const projectConfig = readProjectConfig();
12371
12852
  const hasGlobal = globalConfig?.apiKey != null;
@@ -12374,13 +12855,13 @@ async function logoutCommand() {
12374
12855
  if (hasGlobal && hasProject) {
12375
12856
  const infoLines = ["You are logged in with multiple configs.", ""];
12376
12857
  if (projectConfig) {
12377
- infoLines.push(`${pc16.cyan("Local config:")}`);
12378
- infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey, pc16));
12858
+ infoLines.push(`${pc17.cyan("Local config:")}`);
12859
+ infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey, pc17));
12379
12860
  infoLines.push("");
12380
12861
  }
12381
12862
  if (globalConfig) {
12382
- infoLines.push(`${pc16.magenta("Global config:")}`);
12383
- infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey, pc16));
12863
+ infoLines.push(`${pc17.magenta("Global config:")}`);
12864
+ infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey, pc17));
12384
12865
  }
12385
12866
  p8.note(infoLines.join("\n"));
12386
12867
  const choice = await p8.select({
@@ -12398,14 +12879,14 @@ async function logoutCommand() {
12398
12879
  targetScope = choice;
12399
12880
  } else if (hasProject) {
12400
12881
  const infoLines = ["You are logged in.", ""];
12401
- infoLines.push(`${pc16.dim("Stored in")} ${pc16.cyan("local config")}`);
12402
- infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey, pc16));
12882
+ infoLines.push(`${pc17.dim("Stored in")} ${pc17.cyan("local config")}`);
12883
+ infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey, pc17));
12403
12884
  p8.note(infoLines.join("\n"));
12404
12885
  targetScope = "project";
12405
12886
  } else if (hasGlobal) {
12406
12887
  const infoLines = ["You are logged in.", ""];
12407
- infoLines.push(`${pc16.dim("Stored in")} ${pc16.magenta("global config")}`);
12408
- infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey, pc16));
12888
+ infoLines.push(`${pc17.dim("Stored in")} ${pc17.magenta("global config")}`);
12889
+ infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey, pc17));
12409
12890
  p8.note(infoLines.join("\n"));
12410
12891
  targetScope = "global";
12411
12892
  } else {
@@ -12428,11 +12909,11 @@ async function logoutCommand() {
12428
12909
  }
12429
12910
  if (targetScope === "project" || targetScope === "both") {
12430
12911
  const projectPath = getProjectConfigPath();
12431
- if (fs11.existsSync(projectPath)) fs11.unlinkSync(projectPath);
12912
+ if (fs13.existsSync(projectPath)) fs13.unlinkSync(projectPath);
12432
12913
  }
12433
12914
  if (targetScope === "global" || targetScope === "both") {
12434
12915
  const globalPath = getGlobalConfigPath();
12435
- if (fs11.existsSync(globalPath)) fs11.unlinkSync(globalPath);
12916
+ if (fs13.existsSync(globalPath)) fs13.unlinkSync(globalPath);
12436
12917
  }
12437
12918
  p8.log.success("Credentials cleared.");
12438
12919
  p8.log.info("Your API key is still active. Manage keys at app.withone.ai/settings");
@@ -12440,11 +12921,11 @@ async function logoutCommand() {
12440
12921
  }
12441
12922
 
12442
12923
  // src/lib/project-skills.ts
12443
- import crypto2 from "crypto";
12444
- import fs12 from "fs";
12924
+ import crypto3 from "crypto";
12925
+ import fs14 from "fs";
12445
12926
  import os2 from "os";
12446
- import path10 from "path";
12447
- import zlib from "zlib";
12927
+ import path12 from "path";
12928
+ import zlib2 from "zlib";
12448
12929
  var OPTIONAL_SKILLS = [
12449
12930
  {
12450
12931
  name: "connect",
@@ -12475,42 +12956,42 @@ function findAgentTarget(id) {
12475
12956
  return SKILL_AGENT_TARGETS.find((a) => a.id === id.trim().toLowerCase());
12476
12957
  }
12477
12958
  function findProjectRoot(start) {
12478
- let dir = path10.resolve(start);
12959
+ let dir = path12.resolve(start);
12479
12960
  for (; ; ) {
12480
- if (fs12.existsSync(path10.join(dir, "package.json")) || fs12.existsSync(path10.join(dir, ".git"))) return dir;
12481
- const parent = path10.dirname(dir);
12961
+ if (fs14.existsSync(path12.join(dir, "package.json")) || fs14.existsSync(path12.join(dir, ".git"))) return dir;
12962
+ const parent = path12.dirname(dir);
12482
12963
  if (parent === dir) return null;
12483
12964
  dir = parent;
12484
12965
  }
12485
12966
  }
12486
12967
  function findInstalledPackage(start, packageName) {
12487
- let dir = path10.resolve(start);
12968
+ let dir = path12.resolve(start);
12488
12969
  for (; ; ) {
12489
- const pkgDir = path10.join(dir, "node_modules", ...packageName.split("/"));
12490
- const manifest = path10.join(pkgDir, "package.json");
12491
- if (fs12.existsSync(manifest)) {
12970
+ const pkgDir = path12.join(dir, "node_modules", ...packageName.split("/"));
12971
+ const manifest = path12.join(pkgDir, "package.json");
12972
+ if (fs14.existsSync(manifest)) {
12492
12973
  try {
12493
- const { version: version2 } = JSON.parse(fs12.readFileSync(manifest, "utf-8"));
12974
+ const { version: version2 } = JSON.parse(fs14.readFileSync(manifest, "utf-8"));
12494
12975
  if (version2) return { dir: pkgDir, version: version2 };
12495
12976
  } catch {
12496
12977
  }
12497
12978
  }
12498
- const parent = path10.dirname(dir);
12979
+ const parent = path12.dirname(dir);
12499
12980
  if (parent === dir) return null;
12500
12981
  dir = parent;
12501
12982
  }
12502
12983
  }
12503
12984
  var SkillSourceError = class extends Error {
12504
- constructor(message, code) {
12505
- super(message);
12985
+ constructor(message2, code) {
12986
+ super(message2);
12506
12987
  this.code = code;
12507
12988
  }
12508
12989
  };
12509
12990
  function projectSkillSource(skill, projectDir) {
12510
12991
  const installed = findInstalledPackage(projectDir, skill.packageName);
12511
12992
  if (!installed) return null;
12512
- const dir = path10.join(installed.dir, ...skill.packagePath.split("/"));
12513
- if (!fs12.existsSync(path10.join(dir, "SKILL.md"))) {
12993
+ const dir = path12.join(installed.dir, ...skill.packagePath.split("/"));
12994
+ if (!fs14.existsSync(path12.join(dir, "SKILL.md"))) {
12514
12995
  throw new SkillSourceError(
12515
12996
  `${skill.packageName} ${installed.version} does not include the ${skill.title} skill. Upgrade it: npm install ${skill.packageName}@latest`,
12516
12997
  "skill-missing"
@@ -12549,15 +13030,15 @@ async function registrySkillSource(skill, fetchImpl = fetch) {
12549
13030
  if (!matchesIntegrity(bytes, integrity)) {
12550
13031
  throw new SkillSourceError(`${skill.packageName}@${version2} failed its integrity check; nothing was installed.`, "integrity");
12551
13032
  }
12552
- const files = readTarEntries(zlib.gunzipSync(bytes), `package/${skill.packagePath}/`);
13033
+ const files = readTarEntries(zlib2.gunzipSync(bytes), `package/${skill.packagePath}/`);
12553
13034
  if (!files.some((f) => f.path === "SKILL.md")) {
12554
13035
  throw new SkillSourceError(`${skill.packageName}@${version2} does not include the ${skill.title} skill.`, "not-in-package");
12555
13036
  }
12556
- const tmp = fs12.mkdtempSync(path10.join(os2.tmpdir(), "one-skill-"));
13037
+ const tmp = fs14.mkdtempSync(path12.join(os2.tmpdir(), "one-skill-"));
12557
13038
  for (const file of files) {
12558
- const dest = path10.join(tmp, ...file.path.split("/"));
12559
- fs12.mkdirSync(path10.dirname(dest), { recursive: true });
12560
- fs12.writeFileSync(dest, file.data);
13039
+ const dest = path12.join(tmp, ...file.path.split("/"));
13040
+ fs14.mkdirSync(path12.dirname(dest), { recursive: true });
13041
+ fs14.writeFileSync(dest, file.data);
12561
13042
  }
12562
13043
  return {
12563
13044
  kind: "registry",
@@ -12566,7 +13047,7 @@ async function registrySkillSource(skill, fetchImpl = fetch) {
12566
13047
  origin: tarball,
12567
13048
  cleanup: () => {
12568
13049
  try {
12569
- fs12.rmSync(tmp, { recursive: true, force: true });
13050
+ fs14.rmSync(tmp, { recursive: true, force: true });
12570
13051
  } catch {
12571
13052
  }
12572
13053
  }
@@ -12578,7 +13059,7 @@ function matchesIntegrity(bytes, integrity) {
12578
13059
  if (dash < 0) return false;
12579
13060
  const algorithm = entry.slice(0, dash);
12580
13061
  if (!["sha512", "sha384", "sha256"].includes(algorithm)) return false;
12581
- return crypto2.createHash(algorithm).update(bytes).digest("base64") === entry.slice(dash + 1);
13062
+ return crypto3.createHash(algorithm).update(bytes).digest("base64") === entry.slice(dash + 1);
12582
13063
  });
12583
13064
  }
12584
13065
  function readTarEntries(tar, prefix) {
@@ -12610,7 +13091,7 @@ function readTarEntries(tar, prefix) {
12610
13091
  if ((type === "0" || type === "\0") && full.startsWith(prefix)) {
12611
13092
  const rel = full.slice(prefix.length);
12612
13093
  const parts = rel.split("/");
12613
- if (rel && !path10.isAbsolute(rel) && !parts.includes("..") && !parts.includes("")) {
13094
+ if (rel && !path12.isAbsolute(rel) && !parts.includes("..") && !parts.includes("")) {
12614
13095
  out.push({ path: rel, data: Buffer.from(body) });
12615
13096
  }
12616
13097
  }
@@ -12621,11 +13102,11 @@ function readTarEntries(tar, prefix) {
12621
13102
  }
12622
13103
  var SKILL_STAMP = ".one-skill.json";
12623
13104
  function canonicalSkillDir(skill, plan) {
12624
- return path10.join(plan.root, ...UNIVERSAL_PROJECT_DIR.split("/"), skill.dirName);
13105
+ return path12.join(plan.root, ...UNIVERSAL_PROJECT_DIR.split("/"), skill.dirName);
12625
13106
  }
12626
13107
  function readStamp(dir) {
12627
13108
  try {
12628
- return JSON.parse(fs12.readFileSync(path10.join(dir, SKILL_STAMP), "utf-8"));
13109
+ return JSON.parse(fs14.readFileSync(path12.join(dir, SKILL_STAMP), "utf-8"));
12629
13110
  } catch {
12630
13111
  return null;
12631
13112
  }
@@ -12635,9 +13116,9 @@ function resolveAgentFolders(plan) {
12635
13116
  const chosen = SKILL_AGENT_TARGETS.filter((agent) => {
12636
13117
  if (explicit) return plan.agents.includes(agent.id);
12637
13118
  if (plan.scope === "global") {
12638
- return fs12.existsSync(path10.join(plan.root, path10.dirname(agent.homeDir)));
13119
+ return fs14.existsSync(path12.join(plan.root, path12.dirname(agent.homeDir)));
12639
13120
  }
12640
- return agent.projectMarker === null || fs12.existsSync(path10.join(plan.root, agent.projectMarker));
13121
+ return agent.projectMarker === null || fs14.existsSync(path12.join(plan.root, agent.projectMarker));
12641
13122
  });
12642
13123
  const readers = [];
12643
13124
  const byDir = /* @__PURE__ */ new Map();
@@ -12652,33 +13133,33 @@ function resolveAgentFolders(plan) {
12652
13133
  return { readers, folders: [...byDir].map(([dir, agents]) => ({ dir, agents })) };
12653
13134
  }
12654
13135
  function copyDir(src, dest) {
12655
- fs12.mkdirSync(dest, { recursive: true });
12656
- for (const entry of fs12.readdirSync(src, { withFileTypes: true })) {
13136
+ fs14.mkdirSync(dest, { recursive: true });
13137
+ for (const entry of fs14.readdirSync(src, { withFileTypes: true })) {
12657
13138
  if (entry.name === SKILL_STAMP) continue;
12658
- const from = path10.join(src, entry.name);
12659
- const to = path10.join(dest, entry.name);
13139
+ const from = path12.join(src, entry.name);
13140
+ const to = path12.join(dest, entry.name);
12660
13141
  if (entry.isDirectory()) copyDir(from, to);
12661
- else fs12.copyFileSync(from, to);
13142
+ else fs14.copyFileSync(from, to);
12662
13143
  }
12663
13144
  }
12664
13145
  function removePath(target) {
12665
13146
  try {
12666
- const stat = fs12.lstatSync(target);
12667
- if (stat.isSymbolicLink()) fs12.unlinkSync(target);
12668
- else fs12.rmSync(target, { recursive: true, force: true });
13147
+ const stat = fs14.lstatSync(target);
13148
+ if (stat.isSymbolicLink()) fs14.unlinkSync(target);
13149
+ else fs14.rmSync(target, { recursive: true, force: true });
12669
13150
  } catch {
12670
13151
  }
12671
13152
  }
12672
13153
  function linkDir(target, linkPath) {
12673
13154
  removePath(linkPath);
12674
- fs12.mkdirSync(path10.dirname(linkPath), { recursive: true });
13155
+ fs14.mkdirSync(path12.dirname(linkPath), { recursive: true });
12675
13156
  try {
12676
- fs12.symlinkSync(path10.relative(path10.dirname(linkPath), target), linkPath, "dir");
13157
+ fs14.symlinkSync(path12.relative(path12.dirname(linkPath), target), linkPath, "dir");
12677
13158
  return "symlink";
12678
13159
  } catch {
12679
13160
  }
12680
13161
  try {
12681
- fs12.symlinkSync(target, linkPath, "junction");
13162
+ fs14.symlinkSync(target, linkPath, "junction");
12682
13163
  return "junction";
12683
13164
  } catch {
12684
13165
  }
@@ -12709,17 +13190,17 @@ function installSkill(skill, source, plan, cliVersion2) {
12709
13190
  installedBy: `@withone/cli@${cliVersion2}`,
12710
13191
  installedAt: (/* @__PURE__ */ new Date()).toISOString()
12711
13192
  };
12712
- fs12.writeFileSync(path10.join(canonical, SKILL_STAMP), JSON.stringify(stamp, null, 2) + "\n");
13193
+ fs14.writeFileSync(path12.join(canonical, SKILL_STAMP), JSON.stringify(stamp, null, 2) + "\n");
12713
13194
  return { skill, version: source.version, source: source.kind, origin: source.origin, scope: plan.scope, root: plan.root, canonical, readers, links };
12714
13195
  }
12715
13196
  function removeSkill(skill, plan) {
12716
13197
  const canonical = canonicalSkillDir(skill, plan);
12717
13198
  const stamp = readStamp(canonical);
12718
- if (!stamp && !fs12.existsSync(path10.join(canonical, "SKILL.md"))) return { removed: false, paths: [] };
13199
+ if (!stamp && !fs14.existsSync(path12.join(canonical, "SKILL.md"))) return { removed: false, paths: [] };
12719
13200
  const paths = [];
12720
13201
  for (const link of stamp?.links ?? []) {
12721
13202
  const full = fromStamp(plan.root, link.path);
12722
- if (fs12.existsSync(full) || isDanglingLink(full)) {
13203
+ if (fs14.existsSync(full) || isDanglingLink(full)) {
12723
13204
  removePath(full);
12724
13205
  paths.push(full);
12725
13206
  }
@@ -12732,18 +13213,18 @@ function toPosix(p9) {
12732
13213
  return p9.split("\\").join("/");
12733
13214
  }
12734
13215
  function fromStamp(root, rel) {
12735
- return path10.join(root, ...toPosix(rel).split("/"));
13216
+ return path12.join(root, ...toPosix(rel).split("/"));
12736
13217
  }
12737
13218
  function isDanglingLink(p9) {
12738
13219
  try {
12739
- return fs12.lstatSync(p9).isSymbolicLink();
13220
+ return fs14.lstatSync(p9).isSymbolicLink();
12740
13221
  } catch {
12741
13222
  return false;
12742
13223
  }
12743
13224
  }
12744
13225
  function installedSkill(skill, plan) {
12745
13226
  const canonical = canonicalSkillDir(skill, plan);
12746
- if (!fs12.existsSync(path10.join(canonical, "SKILL.md"))) return null;
13227
+ if (!fs14.existsSync(path12.join(canonical, "SKILL.md"))) return null;
12747
13228
  const stamp = readStamp(canonical);
12748
13229
  return { scope: plan.scope, root: plan.root, canonical, version: stamp?.version ?? null, source: stamp?.source ?? null, links: stamp?.links ?? [] };
12749
13230
  }
@@ -12752,7 +13233,7 @@ function globalRoot() {
12752
13233
  }
12753
13234
  function refreshProjectSkills(cwd, cliVersion2) {
12754
13235
  const root = findProjectRoot(cwd);
12755
- if (!root || path10.resolve(root) === path10.resolve(homeDir())) return [];
13236
+ if (!root || path12.resolve(root) === path12.resolve(homeDir())) return [];
12756
13237
  const results = [];
12757
13238
  for (const skill of OPTIONAL_SKILLS) {
12758
13239
  const canonical = canonicalSkillDir(skill, { scope: "project", root });
@@ -12775,8 +13256,8 @@ function refreshProjectSkills(cwd, cliVersion2) {
12775
13256
  }
12776
13257
 
12777
13258
  // src/commands/skills.ts
12778
- import path11 from "path";
12779
- import pc15 from "picocolors";
13259
+ import path13 from "path";
13260
+ import pc16 from "picocolors";
12780
13261
  function requireSkill(name) {
12781
13262
  const skill = findOptionalSkill(name);
12782
13263
  if (!skill) {
@@ -12799,7 +13280,7 @@ function resolvePlan(options) {
12799
13280
  const agents = parseAgents(options.agents);
12800
13281
  if (options.global) return { scope: "global", root: globalRoot(), agents };
12801
13282
  const root = findProjectRoot(process.cwd());
12802
- if (!root || path11.resolve(root) === path11.resolve(homeDir())) {
13283
+ if (!root || path13.resolve(root) === path13.resolve(homeDir())) {
12803
13284
  error("No project here: run this inside your app (a folder with package.json or .git), or pass --global.");
12804
13285
  }
12805
13286
  return { scope: "project", root, agents };
@@ -12815,7 +13296,7 @@ async function resolveSource(skill, plan) {
12815
13296
  }
12816
13297
  }
12817
13298
  function display(p9, root) {
12818
- const rel = path11.relative(root, p9);
13299
+ const rel = path13.relative(root, p9);
12819
13300
  return rel && !rel.startsWith("..") ? rel : p9;
12820
13301
  }
12821
13302
  function report(command, result, packageInProject) {
@@ -12831,7 +13312,7 @@ function report(command, result, packageInProject) {
12831
13312
  root: result.root,
12832
13313
  installedTo: [
12833
13314
  { path: result.canonical, kind: "folder", agents: result.readers },
12834
- ...result.links.map((l) => ({ path: path11.join(result.root, ...l.path.split("/")), kind: l.kind, agents: l.agents }))
13315
+ ...result.links.map((l) => ({ path: path13.join(result.root, ...l.path.split("/")), kind: l.kind, agents: l.agents }))
12835
13316
  ],
12836
13317
  next: nextSteps(result, packageInProject)
12837
13318
  });
@@ -12839,20 +13320,20 @@ function report(command, result, packageInProject) {
12839
13320
  }
12840
13321
  const scopeLabel2 = result.scope === "project" ? "this project" : "every project on this machine";
12841
13322
  console.log();
12842
- console.log(` ${pc15.green("\u2713")} ${pc15.bold(`${result.skill.title} skill ${result.version}`)} installed for ${scopeLabel2}`);
13323
+ console.log(` ${pc16.green("\u2713")} ${pc16.bold(`${result.skill.title} skill ${result.version}`)} installed for ${scopeLabel2}`);
12843
13324
  console.log();
12844
- 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})`)}`;
12845
- console.log(` ${pc15.dim("From")} ${from}`);
13325
+ const from = result.source === "project" ? `${where(result.origin)} ${pc16.dim("(the version your code uses)")}` : `npm ${pc16.dim(result.scope === "project" ? `(latest ${result.skill.packageName}; not installed in this project yet)` : `(latest ${result.skill.packageName})`)}`;
13326
+ console.log(` ${pc16.dim("From")} ${from}`);
12846
13327
  const rows = [
12847
13328
  { path: where(result.canonical), agents: result.readers },
12848
- ...result.links.map((l) => ({ path: `${l.path}${l.kind === "copy" ? pc15.dim(" (copy)") : ""}`, agents: l.agents }))
13329
+ ...result.links.map((l) => ({ path: `${l.path}${l.kind === "copy" ? pc16.dim(" (copy)") : ""}`, agents: l.agents }))
12849
13330
  ];
12850
13331
  rows.forEach((row, i) => {
12851
- const agents = row.agents.length ? pc15.dim(row.agents.join(", ")) : pc15.dim("shared copy the links point to");
12852
- console.log(` ${pc15.dim(i === 0 ? "To " : " ")} ${row.path} ${agents}`);
13332
+ const agents = row.agents.length ? pc16.dim(row.agents.join(", ")) : pc16.dim("shared copy the links point to");
13333
+ console.log(` ${pc16.dim(i === 0 ? "To " : " ")} ${row.path} ${agents}`);
12853
13334
  });
12854
13335
  console.log();
12855
- console.log(` ${pc15.bold("Next")}`);
13336
+ console.log(` ${pc16.bold("Next")}`);
12856
13337
  nextSteps(result, packageInProject).forEach((step, i) => console.log(` ${i + 1}. ${step}`));
12857
13338
  console.log();
12858
13339
  }
@@ -12915,7 +13396,7 @@ async function skillsUpdateCommand(name, options) {
12915
13396
  console.log("No optional skills are installed here. See: one skills list");
12916
13397
  return;
12917
13398
  }
12918
- for (const r of updated) console.log(` ${pc15.green("\u2713")} ${r.skill.title} skill ${r.version} ${pc15.dim(display(r.canonical, r.root))}`);
13399
+ for (const r of updated) console.log(` ${pc16.green("\u2713")} ${r.skill.title} skill ${r.version} ${pc16.dim(display(r.canonical, r.root))}`);
12919
13400
  }
12920
13401
  async function skillsRemoveCommand(name, options) {
12921
13402
  const skill = requireSkill(name);
@@ -12929,12 +13410,12 @@ async function skillsRemoveCommand(name, options) {
12929
13410
  console.log(`${skill.title} skill is not installed ${plan.scope === "global" ? "globally" : "in this project"}.`);
12930
13411
  return;
12931
13412
  }
12932
- console.log(` ${pc15.green("\u2713")} Removed the ${skill.title} skill`);
12933
- for (const p9 of result.paths) console.log(` ${pc15.dim(display(p9, plan.root))}`);
13413
+ console.log(` ${pc16.green("\u2713")} Removed the ${skill.title} skill`);
13414
+ for (const p9 of result.paths) console.log(` ${pc16.dim(display(p9, plan.root))}`);
12934
13415
  }
12935
13416
  async function skillsListCommand() {
12936
13417
  const projectRoot = findProjectRoot(process.cwd());
12937
- const inProject = projectRoot && path11.resolve(projectRoot) !== path11.resolve(homeDir()) ? projectRoot : null;
13418
+ const inProject = projectRoot && path13.resolve(projectRoot) !== path13.resolve(homeDir()) ? projectRoot : null;
12938
13419
  const optional = OPTIONAL_SKILLS.map((skill) => {
12939
13420
  const project = inProject ? installedSkill(skill, { scope: "project", root: inProject }) : null;
12940
13421
  const global = installedSkill(skill, { scope: "global", root: globalRoot() });
@@ -12962,11 +13443,11 @@ async function skillsListCommand() {
12962
13443
  return;
12963
13444
  }
12964
13445
  console.log();
12965
- console.log(` ${pc15.bold("one")} ${oneSkill.installed ? pc15.green(`installed ${oneSkill.version ?? ""}`.trim()) : pc15.yellow("not installed")} ${pc15.dim("managed by one init")}`);
13446
+ console.log(` ${pc16.bold("one")} ${oneSkill.installed ? pc16.green(`installed ${oneSkill.version ?? ""}`.trim()) : pc16.yellow("not installed")} ${pc16.dim("managed by one init")}`);
12966
13447
  for (const s of optional) {
12967
- 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}`);
12968
- console.log(` ${pc15.bold(s.skill.padEnd(8))} ${state}`);
12969
- console.log(` ${" ".repeat(8)} ${pc15.dim(s.description)}`);
13448
+ const state = s.project ? pc16.green(`project ${s.project.version ?? ""}`.trim()) + (s.project.upToDate ? "" : pc16.yellow(` (package is ${s.packageInProject}: run one skills update ${s.skill})`)) : s.global ? pc16.green(`global ${s.global.version ?? ""}`.trim()) : pc16.dim(`not installed \u2014 one skills add ${s.skill}`);
13449
+ console.log(` ${pc16.bold(s.skill.padEnd(8))} ${state}`);
13450
+ console.log(` ${" ".repeat(8)} ${pc16.dim(s.description)}`);
12970
13451
  }
12971
13452
  console.log();
12972
13453
  }
@@ -12999,6 +13480,10 @@ program.name("one").option("--agent", "Machine-readable JSON output (no colors,
12999
13480
  one skills update [connect] Re-copy from the installed @withone/connect after an upgrade
13000
13481
  one skills remove connect Remove it
13001
13482
 
13483
+ Connect apps (one.connect.ts, typed by @withone/connect/config):
13484
+ one connect create Approve the app (or its new version) in the browser, then write .env
13485
+ one connect types Write one-connect-env.d.ts so tool slugs and action names autocomplete
13486
+
13002
13487
  Guide:
13003
13488
  one guide [topic] Full CLI guide (topics: overview, actions, workflows, memory, sync, all)
13004
13489
 
@@ -13212,8 +13697,8 @@ config.command("reset").description("Remove the project config for the current d
13212
13697
  return;
13213
13698
  }
13214
13699
  }
13215
- const fs14 = await import("fs");
13216
- fs14.unlinkSync(globalPath);
13700
+ const fs16 = await import("fs");
13701
+ fs16.unlinkSync(globalPath);
13217
13702
  if (isAgentMode()) {
13218
13703
  json({ deleted: true, scope: "global" });
13219
13704
  } else {
@@ -13230,15 +13715,15 @@ config.command("reset").description("Remove the project config for the current d
13230
13715
  }
13231
13716
  return;
13232
13717
  }
13233
- const fs13 = await import("fs");
13234
- const configContent = fs13.readFileSync(resolved.path, "utf-8");
13235
- fs13.unlinkSync(resolved.path);
13718
+ const fs15 = await import("fs");
13719
+ const configContent = fs15.readFileSync(resolved.path, "utf-8");
13720
+ fs15.unlinkSync(resolved.path);
13236
13721
  const next = resolveConfig();
13237
- fs13.mkdirSync(path12.dirname(resolved.path), { recursive: true });
13238
- fs13.writeFileSync(resolved.path, configContent);
13722
+ fs15.mkdirSync(path14.dirname(resolved.path), { recursive: true });
13723
+ fs15.writeFileSync(resolved.path, configContent);
13239
13724
  let fallbackLabel;
13240
13725
  if (next.scope === "project") {
13241
- fallbackLabel = `parent project config (${path12.basename(next.projectRoot)})`;
13726
+ fallbackLabel = `parent project config (${path14.basename(next.projectRoot)})`;
13242
13727
  } else if (next.scope === "global") {
13243
13728
  fallbackLabel = "global config";
13244
13729
  } else {
@@ -13247,7 +13732,7 @@ config.command("reset").description("Remove the project config for the current d
13247
13732
  if (!isAgentMode()) {
13248
13733
  const p9 = await import("@clack/prompts");
13249
13734
  const confirmed = await p9.confirm({
13250
- message: `Delete project config for ${path12.basename(resolved.projectRoot)}? Will fall back to ${fallbackLabel}.`,
13735
+ message: `Delete project config for ${path14.basename(resolved.projectRoot)}? Will fall back to ${fallbackLabel}.`,
13251
13736
  initialValue: false
13252
13737
  });
13253
13738
  if (p9.isCancel(confirmed) || !confirmed) {
@@ -13255,9 +13740,9 @@ config.command("reset").description("Remove the project config for the current d
13255
13740
  return;
13256
13741
  }
13257
13742
  }
13258
- fs13.unlinkSync(resolved.path);
13743
+ fs15.unlinkSync(resolved.path);
13259
13744
  try {
13260
- fs13.rmdirSync(path12.dirname(resolved.path));
13745
+ fs15.rmdirSync(path14.dirname(resolved.path));
13261
13746
  } catch {
13262
13747
  }
13263
13748
  if (isAgentMode()) {
@@ -13333,6 +13818,13 @@ flow.command("inspect <runId>").description("Inspect a past run's per-step outpu
13333
13818
  flow.command("scaffold [template]").description("Generate a workflow scaffold (templates: basic, conditional, loop, ai)").action(async (template) => {
13334
13819
  await flowScaffoldCommand(template);
13335
13820
  });
13821
+ var connectApp = program.command("connect").description("Create and update a One Connect app from one.connect.ts");
13822
+ connectApp.command("create").description("Open the setup page to approve the app (or, once .env holds its ONE_CLIENT_ID, its new version); a new app gets its two secrets there. Then write .env").option("--config <file>", "Config file (default: one.connect.ts, .mts, .mjs or .js in this directory)").option("--env-file <file>", "Env file to write (default: .env.local if it exists, else .env)").option("--no-open", "Print the setup page link instead of opening it").action(async (options) => {
13823
+ await connectCreateCommand(options);
13824
+ });
13825
+ connectApp.command("types").description("Write one-connect-env.d.ts: every tool slug, and action names for the tools the config asks for").option("--config <file>", "Config file (default: one.connect.ts, .mts, .mjs or .js in this directory)").action(async (options) => {
13826
+ await connectTypesCommand(options);
13827
+ });
13336
13828
  var relay = program.command("relay").alias("r").description("Receive webhooks from platforms and relay them via passthrough actions");
13337
13829
  relay.command("create").description("Create a new relay endpoint for a connection").requiredOption("--connection-key <key>", "Connection key for the source platform").option("--description <desc>", "Description of the relay endpoint").option("--event-filters <json>", `JSON array of event types to filter (e.g. '["customer.created"]')`).option("--tags <json>", "JSON array of tags").option("--metadata <json>", `JSON object of platform-specific metadata required to register the webhook (e.g. GitHub: '{"GITHUB_OWNER":"org","GITHUB_REPOSITORY":"repo"}', Typeform: '{"TYPEFORM_FORM_ID":"abc"}')`).option("--create-webhook", "Automatically register the webhook with the source platform").action(async (options) => {
13338
13830
  await relayCreateCommand(options);
@@ -13420,22 +13912,22 @@ program.command("whoami").description("Show the user, organization, and project
13420
13912
  });
13421
13913
  return;
13422
13914
  }
13423
- const pc16 = (await import("picocolors")).default;
13915
+ const pc17 = (await import("picocolors")).default;
13424
13916
  const contextParts = [];
13425
13917
  if (whoami.organization) contextParts.push(whoami.organization.name);
13426
13918
  if (whoami.project) contextParts.push(whoami.project.name);
13427
13919
  const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
13428
- const envLabel = env === "test" ? pc16.yellow("test") : pc16.green("live");
13429
- const configLabel = configScope === "project" ? pc16.cyan("project config") : pc16.magenta("global config");
13920
+ const envLabel = env === "test" ? pc17.yellow("test") : pc17.green("live");
13921
+ const configLabel = configScope === "project" ? pc17.cyan("project config") : pc17.magenta("global config");
13430
13922
  console.log();
13431
- console.log(` ${pc16.bold(scopeDisplay)} ${pc16.dim("\xB7")} ${envLabel}`);
13432
- console.log(` ${whoami.user.name} ${pc16.dim(`(${whoami.user.email})`)}`);
13433
- if (keyName) console.log(` ${pc16.dim("Key:")} ${keyName}`);
13434
- if (whoami.organization) console.log(` ${pc16.dim("Org:")} ${whoami.organization.name} ${pc16.dim(`(${whoami.organization.id})`)}`);
13435
- if (whoami.project) console.log(` ${pc16.dim("Project:")} ${whoami.project.name} ${pc16.dim(`(${whoami.project.id})`)}`);
13923
+ console.log(` ${pc17.bold(scopeDisplay)} ${pc17.dim("\xB7")} ${envLabel}`);
13924
+ console.log(` ${whoami.user.name} ${pc17.dim(`(${whoami.user.email})`)}`);
13925
+ if (keyName) console.log(` ${pc17.dim("Key:")} ${keyName}`);
13926
+ if (whoami.organization) console.log(` ${pc17.dim("Org:")} ${whoami.organization.name} ${pc17.dim(`(${whoami.organization.id})`)}`);
13927
+ if (whoami.project) console.log(` ${pc17.dim("Project:")} ${whoami.project.name} ${pc17.dim(`(${whoami.project.id})`)}`);
13436
13928
  console.log();
13437
- console.log(` ${pc16.dim("Using")} ${configLabel}`);
13438
- console.log(` ${pc16.dim("API:")} ${apiBase}`);
13929
+ console.log(` ${pc17.dim("Using")} ${configLabel}`);
13930
+ console.log(` ${pc17.dim("API:")} ${apiBase}`);
13439
13931
  console.log();
13440
13932
  });
13441
13933
  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) => {