@withone/cli 2.10.0 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -529,14 +529,14 @@ Commit `.agents/skills/one-connect` and the agent links so your team's agents sh
529
529
 
530
530
  ### `one connect`
531
531
 
532
- Create and update a [One Connect](https://www.npmjs.com/package/@withone/connect) app from `one.connect.ts`, typed by `defineConnectApp` from `@withone/connect/config` (0.19.0 or later).
532
+ Create and update a [One Connect](https://www.npmjs.com/package/@withone/connect) app from `one.connect.ts`, typed by `defineConnectApp` from `@withone/connect/config` (0.20.0 or later).
533
533
 
534
534
  ```bash
535
535
  one connect types # writes one-connect-env.d.ts: tool slugs and action names autocomplete
536
536
  one connect create # approve the app in the browser; re-run to review and apply changes
537
537
  ```
538
538
 
539
- `one connect create` opens a setup page in your signed-in browser, where you review the app (or, on a re-run, its new version) and approve it; nothing is created or changed with your API key. A new app's client secret and connect key are made there and shown once, so they never pass through the terminal. Once you approve, the CLI writes `ONE_CLIENT_ID`, `ONE_PERMISSION_SET` and `ONE_REDIRECT_URI` to `.env.local` (or `.env`). Each tool in `ask` takes `access`: `read-only`, `read-write`, `full-access`, or `custom` with `actions`, named as `one connect types` wrote them or by id from `one actions find <platform> "<what it does>" --no-knowledge`. Options: `--config <file>`, `--env-file <file>`, `--no-open`. Install `@withone/connect` (0.19.0 or later) in the project first. A `.ts` config needs Node 22.18 or later; on older Node use `one.connect.mjs`.
539
+ `one connect create` opens a setup page in your signed-in browser, where you review the app (or, on a re-run, its new version) and approve it; nothing is created or changed with your API key. A new app's client secret and connect key are made there and shown once, so they never pass through the terminal. Once you approve, the CLI writes `ONE_CLIENT_ID`, `ONE_REDIRECT_URI` and, for a list of tools, `ONE_PERMISSION_SET` to `.env.local` (or `.env`). `ask` is required: either the tools, where each takes `access` (`read-only`, `read-write`, `full-access`, or `custom` with `actions`, named as `one connect types` wrote them or by id from `one actions find <platform> "<what it does>" --no-knowledge`), or `"everything"`, where users see every connection they have and can connect any other app. An app switched to `"everything"` loses its ask, and the CLI removes `ONE_PERMISSION_SET` from the env file. Options: `--config <file>`, `--env-file <file>`, `--no-open`. Install `@withone/connect` (0.20.0 or later) in the project first. A `.ts` config needs Node 22.18 or later; on older Node use `one.connect.mjs`.
540
540
 
541
541
  ### `one guide [topic]`
542
542
 
package/dist/index.js CHANGED
@@ -6015,6 +6015,9 @@ import zlib from "zlib";
6015
6015
  import { pathToFileURL } from "url";
6016
6016
  var CONFIG_FILES = ["one.connect.ts", "one.connect.mts", "one.connect.mjs", "one.connect.js"];
6017
6017
  var TYPES_FILE = "one-connect-env.d.ts";
6018
+ function askedTools(config2) {
6019
+ return config2.ask === "everything" ? [] : Object.entries(config2.ask ?? {});
6020
+ }
6018
6021
  var ACCESS_METHODS = {
6019
6022
  "read-only": ["GET"],
6020
6023
  "read-write": ["GET", "POST", "PUT", "PATCH"],
@@ -6077,7 +6080,18 @@ function validateConfig(value) {
6077
6080
  if (!HEX_COLOR.test(String(v.branding[key] ?? ""))) errors.push(`\`branding.${key}\` must be a #RRGGBB colour.`);
6078
6081
  }
6079
6082
  }
6080
- for (const [tool, ask] of Object.entries(v.ask ?? {})) {
6083
+ const asked = v.ask;
6084
+ if (asked === void 0) {
6085
+ errors.push('`ask` is required: name the tools the app asks for, or write `ask: "everything"`.');
6086
+ } else if (typeof asked === "string") {
6087
+ if (asked !== "everything") errors.push(`\`ask\` is "${asked}"; it must be a map of tools or "everything".`);
6088
+ } else if (!asked || typeof asked !== "object" || Array.isArray(asked)) {
6089
+ errors.push('`ask` must be a map of tools or "everything".');
6090
+ } else if (Object.keys(asked).length === 0) {
6091
+ errors.push('`ask` names no tools. Name at least one, or write `ask: "everything"`.');
6092
+ }
6093
+ const tools = asked && typeof asked === "object" && !Array.isArray(asked) ? Object.entries(asked) : [];
6094
+ for (const [tool, ask] of tools) {
6081
6095
  const access = ask?.access;
6082
6096
  if (access === "custom") {
6083
6097
  const actions2 = ask.actions;
@@ -6134,7 +6148,11 @@ function clientFields(config2) {
6134
6148
  return fields;
6135
6149
  }
6136
6150
  function buildHandoff(config2, rules) {
6137
- return { v: 1, app: clientFields(config2), ask: rules.length > 0 ? rules : null };
6151
+ return {
6152
+ v: 2,
6153
+ app: clientFields(config2),
6154
+ ask: config2.ask === "everything" ? { kind: "everything" } : { kind: "tools", rules }
6155
+ };
6138
6156
  }
6139
6157
  function encodeHandoff(handoff) {
6140
6158
  return zlib.deflateRawSync(Buffer.from(JSON.stringify(handoff), "utf8"), { level: 9 }).toString("base64url");
@@ -6165,6 +6183,10 @@ function upsertEnv(text5, values) {
6165
6183
  return `${next}${separator}${appended.join("\n")}
6166
6184
  `;
6167
6185
  }
6186
+ function removeEnvKeys(text5, keys) {
6187
+ return keys.reduce((next, key) => next.replace(new RegExp(`^${key}=.*(?:\r?
6188
+ |$)`, "m"), ""), text5);
6189
+ }
6168
6190
  function renderTypes(tools, actionsByTool) {
6169
6191
  const literal = (value) => JSON.stringify(value);
6170
6192
  const union = (values) => values.length > 0 ? values.map(literal).join(" | ") : "never";
@@ -6214,7 +6236,7 @@ function message(error2) {
6214
6236
  return error2 instanceof Error ? error2.message : String(error2);
6215
6237
  }
6216
6238
  async function buildRules(api, config2) {
6217
- const asked = Object.entries(config2.ask ?? {});
6239
+ const asked = askedTools(config2);
6218
6240
  if (asked.length === 0) return [];
6219
6241
  const platforms = await api.listPlatforms();
6220
6242
  const idBySlug = new Map(platforms.map((p9) => [p9.platform, p9.id]));
@@ -6302,19 +6324,21 @@ async function connectCreateCommand(options) {
6302
6324
  if (outcome.kind === "cancelled") error("Cancelled in the browser. Nothing was changed.");
6303
6325
  if (outcome.kind === "failed") error(`The setup page reported: ${outcome.reason}`);
6304
6326
  const created = outcome.outcome === "created";
6327
+ const asksForEverything = config2.ask === "everything";
6305
6328
  fs6.writeFileSync(
6306
6329
  envFile,
6307
- upsertEnv(envText, {
6330
+ upsertEnv(asksForEverything ? removeEnvKeys(envText, ["ONE_PERMISSION_SET"]) : envText, {
6308
6331
  ONE_CLIENT_ID: outcome.clientId,
6309
6332
  ONE_REDIRECT_URI: config2.redirectUris[0],
6310
- ...outcome.permissionSetId ? { ONE_PERMISSION_SET: outcome.permissionSetId } : {},
6333
+ ...!asksForEverything && outcome.permissionSetId ? { ONE_PERMISSION_SET: outcome.permissionSetId } : {},
6311
6334
  ...created ? { ONE_CLIENT_SECRET: null, ONE_CONNECT_KEY: null } : {}
6312
6335
  })
6313
6336
  );
6314
6337
  const result = {
6315
6338
  outcome: outcome.outcome,
6316
6339
  clientId: outcome.clientId,
6317
- permissionSetId: outcome.permissionSetId,
6340
+ permissionSetId: asksForEverything ? null : outcome.permissionSetId,
6341
+ asksForEverything,
6318
6342
  redirectUris: config2.redirectUris,
6319
6343
  envFile: path6.relative(cwd, envFile) || envFile
6320
6344
  };
@@ -6327,7 +6351,8 @@ async function connectCreateCommand(options) {
6327
6351
  );
6328
6352
  console.log();
6329
6353
  console.log(` ${pc10.dim("Client ID:")} ${outcome.clientId}`);
6330
- if (outcome.permissionSetId) console.log(` ${pc10.dim("Permission set:")} ${outcome.permissionSetId}`);
6354
+ if (asksForEverything) console.log(` ${pc10.dim("Asks for:")} everything the user has connected`);
6355
+ else if (outcome.permissionSetId) console.log(` ${pc10.dim("Permission set:")} ${outcome.permissionSetId}`);
6331
6356
  console.log(` ${pc10.dim("Wrote")} ${result.envFile}`);
6332
6357
  if (created) {
6333
6358
  console.log(` ${pc10.dim("The two secrets came from the browser page, never through here.")}`);
@@ -6349,7 +6374,7 @@ async function connectTypesCommand(options) {
6349
6374
  try {
6350
6375
  const file = findConfigFile(cwd, options.config);
6351
6376
  const config2 = file ? validateConfig(await loadConfigFile(file)) : null;
6352
- const tools = Object.keys(config2 && "config" in config2 ? config2.config.ask ?? {} : {});
6377
+ const tools = config2 && "config" in config2 ? askedTools(config2.config).map(([slug]) => slug) : [];
6353
6378
  const platforms = await api.listPlatforms();
6354
6379
  const known = new Set(platforms.map((p9) => p9.platform));
6355
6380
  const actionsByTool = {};
@@ -11380,7 +11405,7 @@ one --agent relay deliveries --endpoint-id <id> # Check delivery
11380
11405
  - Use \`actions find\` (and \`actions load\` for more) to learn both the incoming payload shape AND the destination API shape before building templates
11381
11406
 
11382
11407
  ### 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\`).
11408
+ \`one connect create\` reads \`one.connect.ts\`, typed by \`defineConnectApp\` from \`@withone/connect/config\` (install \`@withone/connect\` 0.20.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_REDIRECT_URI\` and, for a list of tools, \`ONE_PERMISSION_SET\` to the env file. \`one connect types\` writes \`one-connect-env.d.ts\` so tool slugs and action names autocomplete. \`ask\` is required: the tools, each with \`access\` \`read-only\`, \`read-write\`, \`full-access\`, or \`custom\` with \`actions\` (names, or ids from \`actions find\`), or \`"everything"\`, which asks for every connection the user has and removes \`ONE_PERMISSION_SET\` from the env file.
11384
11409
 
11385
11410
  ### 4. Memory + Sync \u2014 Unified store with hybrid FTS + semantic search
11386
11411
  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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@withone/cli",
3
- "version": "2.10.0",
3
+ "version": "2.11.0",
4
4
  "description": "CLI for managing One",
5
5
  "type": "module",
6
6
  "files": [
@@ -377,10 +377,10 @@ To create the Connect app itself without the dashboard, install `@withone/connec
377
377
 
378
378
  ```bash
379
379
  one --agent connect types # tool slugs and action names autocomplete in one.connect.ts
380
- one --agent connect create # the human approves it in the browser; then writes ONE_CLIENT_ID, ONE_PERMISSION_SET, ONE_REDIRECT_URI to .env
380
+ one --agent connect create # the human approves it in the browser; then writes ONE_CLIENT_ID, ONE_REDIRECT_URI and (for a list of tools) ONE_PERMISSION_SET to .env
381
381
  ```
382
382
 
383
- It opens a setup page in the human's browser and waits up to 10 minutes, so run it in the background or with a long timeout; the link is printed to stderr at once, so pass it on if no browser opened. The human reviews the app (or, on a re-run, its new version) and approves it with their dashboard session: an API key never creates or changes a Connect app. For a new app the page also makes `ONE_CLIENT_SECRET` and `ONE_CONNECT_KEY` and shows them once; tell the human to copy them into the env file the result names. The CLI never receives either secret. Run `connect create` again after editing the file to update the same app.
383
+ It opens a setup page in the human's browser and waits up to 10 minutes, so run it in the background or with a long timeout; the link is printed to stderr at once, so pass it on if no browser opened. The human reviews the app (or, on a re-run, its new version) and approves it with their dashboard session: an API key never creates or changes a Connect app. For a new app the page also makes `ONE_CLIENT_SECRET` and `ONE_CONNECT_KEY` and shows them once; tell the human to copy them into the env file the result names. The CLI never receives either secret. Run `connect create` again after editing the file to update the same app. `ask` is required: the tools the app asks for, or `"everything"` (users see every connection they have and can connect any other app; the CLI then removes `ONE_PERMISSION_SET` from the env file).
384
384
 
385
385
  ## Adding New Connections
386
386