@withone/cli 1.43.9 → 1.44.1
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 +10 -0
- package/dist/index.js +130 -6
- package/package.json +1 -1
- package/skills/one/SKILL.md +3 -1
package/README.md
CHANGED
|
@@ -144,11 +144,21 @@ In a monorepo, the project root is the nearest ancestor with `.one/`, `.git`, or
|
|
|
144
144
|
|
|
145
145
|
If you've already set up, `one init` shows your current status for the active scope and lets you update your key, install to more agents, or reconfigure.
|
|
146
146
|
|
|
147
|
+
**Agent-driven setup (no prompts).** Pass `--auth` and `one init` runs end-to-end without any terminal interaction — handy when an AI agent is onboarding you. It saves the key, auto-installs the One skill, and skips the connect step (`one add` later).
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
one init --auth browser # opens a login window; you authenticate, the window closes — done
|
|
151
|
+
one init --auth manual --api-key sk_live_... # headless / CI, no browser
|
|
152
|
+
```
|
|
153
|
+
|
|
147
154
|
| Flag | What it does |
|
|
148
155
|
|------|-------------|
|
|
149
156
|
| `-y` | Skip confirmations |
|
|
150
157
|
| `-g` | Non-interactive: write the One config globally (`~/.one/config.json`) |
|
|
151
158
|
| `-p` | Non-interactive: write the One config for this project (`~/.one/projects/<slug>/config.json`) |
|
|
159
|
+
| `--auth <browser\|manual>` | Run setup with **no prompts**. `browser` opens a login window; `manual` uses `--api-key`. Scope from `-g`/`-p` (default global). |
|
|
160
|
+
| `--api-key <key>` | API key for `--auth manual` (`sk_live_…` / `sk_test_…`) |
|
|
161
|
+
| `--openai-key <key>` | Optional OpenAI key for `one mem` semantic search |
|
|
152
162
|
|
|
153
163
|
### `one add <platform>`
|
|
154
164
|
|
package/dist/index.js
CHANGED
|
@@ -1046,8 +1046,12 @@ async function loginCommand() {
|
|
|
1046
1046
|
|
|
1047
1047
|
// src/commands/init.ts
|
|
1048
1048
|
async function initCommand(options) {
|
|
1049
|
+
if (options.auth) {
|
|
1050
|
+
await nonInteractiveInit(options);
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1049
1053
|
if (isAgentMode()) {
|
|
1050
|
-
error("This command
|
|
1054
|
+
error("This command is interactive. Run without --agent, or pass --auth <browser|manual> for a non-interactive setup.");
|
|
1051
1055
|
}
|
|
1052
1056
|
printBanner();
|
|
1053
1057
|
const scope = await chooseConfigScope(options);
|
|
@@ -1062,6 +1066,101 @@ async function initCommand(options) {
|
|
|
1062
1066
|
}
|
|
1063
1067
|
await freshSetup(scope, options);
|
|
1064
1068
|
}
|
|
1069
|
+
async function nonInteractiveInit(options) {
|
|
1070
|
+
const auth = options.auth;
|
|
1071
|
+
if (auth !== "browser" && auth !== "manual") {
|
|
1072
|
+
error(`Invalid --auth value '${auth}'. Use 'browser' or 'manual'.`);
|
|
1073
|
+
}
|
|
1074
|
+
const scope = options.global ? "global" : options.project ? "project" : "global";
|
|
1075
|
+
let apiKey;
|
|
1076
|
+
let whoami;
|
|
1077
|
+
if (auth === "browser") {
|
|
1078
|
+
const result = await browserLogin();
|
|
1079
|
+
if (!result) {
|
|
1080
|
+
error("Browser login did not complete. Try again: one init --auth browser");
|
|
1081
|
+
}
|
|
1082
|
+
apiKey = result.apiKey;
|
|
1083
|
+
whoami = result.whoami;
|
|
1084
|
+
} else {
|
|
1085
|
+
const key = options.apiKey?.trim();
|
|
1086
|
+
if (!key) {
|
|
1087
|
+
error("--auth manual requires --api-key <sk_live_\u2026 | sk_test_\u2026>.");
|
|
1088
|
+
}
|
|
1089
|
+
if (!key.startsWith("sk_live_") && !key.startsWith("sk_test_")) {
|
|
1090
|
+
error("API key should start with sk_live_ or sk_test_.");
|
|
1091
|
+
}
|
|
1092
|
+
const api = new OneApi(key, getApiBase());
|
|
1093
|
+
let validated;
|
|
1094
|
+
try {
|
|
1095
|
+
validated = await api.validateApiKey();
|
|
1096
|
+
} catch (err) {
|
|
1097
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1098
|
+
error(`Could not validate API key: ${msg}`);
|
|
1099
|
+
}
|
|
1100
|
+
if (!validated) {
|
|
1101
|
+
error(`Invalid API key. Get a valid key at ${getApiKeyUrl()}`);
|
|
1102
|
+
}
|
|
1103
|
+
apiKey = key;
|
|
1104
|
+
whoami = validated;
|
|
1105
|
+
}
|
|
1106
|
+
const existing = scope === "project" ? readProjectConfig() : readGlobalConfig();
|
|
1107
|
+
writeConfig(
|
|
1108
|
+
{
|
|
1109
|
+
apiKey,
|
|
1110
|
+
installedAgents: existing?.installedAgents ?? [],
|
|
1111
|
+
createdAt: existing?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
1112
|
+
accessControl: existing?.accessControl,
|
|
1113
|
+
apiBase: existing?.apiBase,
|
|
1114
|
+
cacheTtl: existing?.cacheTtl,
|
|
1115
|
+
whoami
|
|
1116
|
+
},
|
|
1117
|
+
scope
|
|
1118
|
+
);
|
|
1119
|
+
if (options.openaiKey?.trim()) {
|
|
1120
|
+
try {
|
|
1121
|
+
setOpenAiApiKey(options.openaiKey.trim());
|
|
1122
|
+
} catch {
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
const primaryIds = SKILL_AGENTS.filter((a) => a.primary).map((a) => a.id);
|
|
1126
|
+
const { installed, failed } = installSkillForAgents(primaryIds);
|
|
1127
|
+
const configPath = scope === "project" ? getProjectConfigPath() : getGlobalConfigPath();
|
|
1128
|
+
if (isAgentMode()) {
|
|
1129
|
+
json({
|
|
1130
|
+
success: true,
|
|
1131
|
+
scope,
|
|
1132
|
+
configPath,
|
|
1133
|
+
auth,
|
|
1134
|
+
account: {
|
|
1135
|
+
user: whoami.user,
|
|
1136
|
+
organization: whoami.organization,
|
|
1137
|
+
project: whoami.project,
|
|
1138
|
+
env: getEnvFromApiKey(apiKey)
|
|
1139
|
+
},
|
|
1140
|
+
skillInstalled: installed,
|
|
1141
|
+
skillFailed: failed
|
|
1142
|
+
});
|
|
1143
|
+
return;
|
|
1144
|
+
}
|
|
1145
|
+
const env = getEnvFromApiKey(apiKey);
|
|
1146
|
+
const contextParts = [];
|
|
1147
|
+
if (whoami.organization) contextParts.push(whoami.organization.name);
|
|
1148
|
+
if (whoami.project) contextParts.push(whoami.project.name);
|
|
1149
|
+
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
1150
|
+
const envLabel = env === "test" ? pc2.yellow("test") : pc2.green("live");
|
|
1151
|
+
console.log();
|
|
1152
|
+
console.log(` ${pc2.bold("Setup complete")} ${scopeLabel(scope)}`);
|
|
1153
|
+
console.log(` ${pc2.dim("\u2500".repeat(42))}`);
|
|
1154
|
+
console.log(` ${pc2.dim("Account:")} ${scopeDisplay} ${pc2.dim("\xB7")} ${envLabel}`);
|
|
1155
|
+
console.log(` ${pc2.dim("User:")} ${whoami.user.name} ${pc2.dim(`(${whoami.user.email})`)}`);
|
|
1156
|
+
console.log(` ${pc2.dim("Config:")} ${tildify(configPath)}`);
|
|
1157
|
+
if (installed.length > 0) {
|
|
1158
|
+
console.log(` ${pc2.dim("Skill:")} ${pc2.green("installed")} ${pc2.dim("\xB7 " + installed.join(", "))}`);
|
|
1159
|
+
}
|
|
1160
|
+
console.log();
|
|
1161
|
+
console.log(` ${pc2.dim("Connect a platform later with")} ${pc2.cyan("one add <platform>")}`);
|
|
1162
|
+
printOnboardingPrompt();
|
|
1163
|
+
}
|
|
1065
1164
|
async function chooseConfigScope(options) {
|
|
1066
1165
|
if (options.global) return "global";
|
|
1067
1166
|
if (options.project) return "project";
|
|
@@ -6174,17 +6273,23 @@ async function syncModel(api, profile, options) {
|
|
|
6174
6273
|
if (lock) lock.release();
|
|
6175
6274
|
const rawMsg = err instanceof Error ? err.message : String(err);
|
|
6176
6275
|
const shortMsg = truncate(rawMsg, 500);
|
|
6276
|
+
const httpStatus = err instanceof ApiError ? err.status : void 0;
|
|
6277
|
+
const retryAfter = err instanceof ApiError ? err.retryAfterSeconds : void 0;
|
|
6177
6278
|
if (pagesProcessed > 0) {
|
|
6178
6279
|
const resumeErr = new Error(
|
|
6179
6280
|
`Sync interrupted after page ${pagesProcessed} (${totalRecords} records). Run again to resume. Error: ${shortMsg}`
|
|
6180
6281
|
);
|
|
6181
6282
|
resumeErr._recordsSynced = totalRecords;
|
|
6182
6283
|
resumeErr._pagesProcessed = pagesProcessed;
|
|
6284
|
+
resumeErr._httpStatus = httpStatus;
|
|
6285
|
+
resumeErr._retryAfter = retryAfter;
|
|
6183
6286
|
throw resumeErr;
|
|
6184
6287
|
}
|
|
6185
6288
|
const wrapped = new Error(shortMsg);
|
|
6186
6289
|
wrapped._recordsSynced = totalRecords;
|
|
6187
6290
|
wrapped._pagesProcessed = pagesProcessed;
|
|
6291
|
+
wrapped._httpStatus = httpStatus;
|
|
6292
|
+
wrapped._retryAfter = retryAfter;
|
|
6188
6293
|
throw wrapped;
|
|
6189
6294
|
} finally {
|
|
6190
6295
|
process.off("SIGINT", onSigint);
|
|
@@ -7663,13 +7768,18 @@ async function syncRunCommand(platform, options) {
|
|
|
7663
7768
|
results.push(result);
|
|
7664
7769
|
} catch (err) {
|
|
7665
7770
|
const errObj = err;
|
|
7771
|
+
const errorContext = {
|
|
7772
|
+
message: err instanceof Error ? err.message : String(err),
|
|
7773
|
+
...errObj?._httpStatus !== void 0 ? { httpStatus: errObj._httpStatus } : {},
|
|
7774
|
+
...errObj?._retryAfter !== void 0 ? { retryAfter: errObj._retryAfter } : {}
|
|
7775
|
+
};
|
|
7666
7776
|
results.push({
|
|
7667
7777
|
model: profile.model,
|
|
7668
7778
|
recordsSynced: errObj?._recordsSynced ?? 0,
|
|
7669
7779
|
pagesProcessed: errObj?._pagesProcessed ?? 0,
|
|
7670
7780
|
duration: "0s",
|
|
7671
7781
|
status: "failed",
|
|
7672
|
-
error:
|
|
7782
|
+
error: errorContext
|
|
7673
7783
|
});
|
|
7674
7784
|
}
|
|
7675
7785
|
}
|
|
@@ -7688,8 +7798,11 @@ async function syncRunCommand(platform, options) {
|
|
|
7688
7798
|
const archivedColor = sc.archived > sc.active ? pc9.red : pc9.dim;
|
|
7689
7799
|
console.log(` memory: ${pc9.green(String(sc.active))} active, ${archivedColor(String(sc.archived))} archived`);
|
|
7690
7800
|
}
|
|
7691
|
-
if (
|
|
7692
|
-
|
|
7801
|
+
if (r.error) {
|
|
7802
|
+
const errParts = [r.error.message];
|
|
7803
|
+
if (r.error.httpStatus) errParts.push(`HTTP ${r.error.httpStatus}`);
|
|
7804
|
+
if (r.error.retryAfter) errParts.push(`retry after ${r.error.retryAfter}s`);
|
|
7805
|
+
console.log(` ${pc9.red(errParts.join(" \u2014 "))}`);
|
|
7693
7806
|
}
|
|
7694
7807
|
}
|
|
7695
7808
|
}
|
|
@@ -9236,6 +9349,17 @@ var GUIDE_OVERVIEW = `# One CLI \u2014 Agent Guide
|
|
|
9236
9349
|
|
|
9237
9350
|
You can also use \`one login\` / \`one logout\` to manage authentication separately (global or per-directory).
|
|
9238
9351
|
|
|
9352
|
+
### Agent-driven setup (no prompts)
|
|
9353
|
+
To onboard a user without any terminal interaction, pass \`--auth\` to \`one init\`. This disables every prompt, auto-installs the One skill, and skips the connect-a-platform step (run \`one add <platform>\` afterwards).
|
|
9354
|
+
|
|
9355
|
+
\`\`\`bash
|
|
9356
|
+
one init --auth browser # opens a login window; the user authenticates, the CLI saves the key
|
|
9357
|
+
one init --auth browser --project # same, but scoped to this folder (default scope is global)
|
|
9358
|
+
one init --auth manual --api-key sk_live_... # headless / CI \u2014 no browser
|
|
9359
|
+
\`\`\`
|
|
9360
|
+
|
|
9361
|
+
With \`--auth browser\` the user sees a browser window, picks how to authenticate, and the window closes when done \u2014 the agent never blocks on stdin. Add \`--openai-key sk-...\` to enable semantic search in \`one mem\` during setup.
|
|
9362
|
+
|
|
9239
9363
|
## The --agent Flag
|
|
9240
9364
|
|
|
9241
9365
|
Always use \`--agent\` for machine-readable JSON output. It disables colors, spinners, and interactive prompts.
|
|
@@ -10640,7 +10764,7 @@ program.name("one").option("--agent", "Machine-readable JSON output (no colors,
|
|
|
10640
10764
|
Setup:
|
|
10641
10765
|
one login Authenticate via browser (opens app.withone.ai)
|
|
10642
10766
|
one logout Clear local credentials
|
|
10643
|
-
one init Set up API key
|
|
10767
|
+
one init Set up API key + skill (add --auth browser for no-prompt agent setup)
|
|
10644
10768
|
one add <platform> Connect a platform via OAuth (e.g. gmail, slack, shopify)
|
|
10645
10769
|
one connection delete <key> Remove a connection (alias: one connection rm)
|
|
10646
10770
|
one config Configure access control (permissions, scoping)
|
|
@@ -10734,7 +10858,7 @@ program.hook("postAction", async () => {
|
|
|
10734
10858
|
if (!isNewerVersion(info.version, current)) return;
|
|
10735
10859
|
autoUpdate(info.version, info.publishedAt);
|
|
10736
10860
|
});
|
|
10737
|
-
program.command("init").description("Set up One and install
|
|
10861
|
+
program.command("init").description("Set up One and install the skill to your AI agents (interactive; pass --auth for a no-prompt setup)").option("-y, --yes", "Skip confirmations").option("-g, --global", "Write the One config globally (~/.one/config.json) \u2014 skips the scope picker").option("-p, --project", "Write the One config for this project only (~/.one/projects/<slug>/) \u2014 skips the scope picker").option("--auth <method>", 'Non-interactive setup (no prompts): "browser" opens a login window, "manual" uses --api-key').option("--api-key <key>", "API key for --auth manual (sk_live_\u2026 or sk_test_\u2026)").option("--openai-key <key>", "Optional OpenAI key for `one mem` semantic search (non-interactive setup)").action(async (options) => {
|
|
10738
10862
|
await initCommand(options);
|
|
10739
10863
|
});
|
|
10740
10864
|
program.command("login").description("Authenticate with One via browser").action(async () => {
|
package/package.json
CHANGED
package/skills/one/SKILL.md
CHANGED
|
@@ -31,7 +31,9 @@ one login # Browser-based login (opens app.withone.ai)
|
|
|
31
31
|
one logout # Clear local credentials
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
`one login` opens the browser for OAuth authentication and automatically creates and stores an API key. If already logged in, the user can choose to log in globally or for the current directory. `one logout` shows current session info and confirms before clearing credentials.
|
|
34
|
+
`one login` opens the browser for OAuth authentication and automatically creates and stores an API key. If already logged in, the user can choose to log in globally or for the current directory. `one logout` shows current session info and confirms before clearing credentials.
|
|
35
|
+
|
|
36
|
+
**Onboarding a user with no prompts:** run `one init --auth browser` — it opens a login window (the user authenticates there), saves the key, and auto-installs this skill, all without blocking on stdin. Add `-g`/`-p` for scope (default global). For CI/CD or headless environments, use `one init --auth manual --api-key sk_live_...`.
|
|
35
37
|
|
|
36
38
|
## Core Workflow: search -> knowledge -> execute
|
|
37
39
|
|