orizu 0.5.24 → 0.5.25
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 +23 -3
- package/dist/credentials.d.ts +15 -0
- package/dist/credentials.d.ts.map +1 -1
- package/dist/credentials.js +279 -59
- package/dist/help.d.ts.map +1 -1
- package/dist/help.js +5 -2
- package/dist/http.d.ts +20 -0
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +239 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +153 -213
- package/dist/keyboard-select.d.ts +7 -0
- package/dist/keyboard-select.d.ts.map +1 -0
- package/dist/keyboard-select.js +72 -0
- package/dist/logout-diagnostic.d.ts +4 -0
- package/dist/logout-diagnostic.d.ts.map +1 -0
- package/dist/logout-diagnostic.js +26 -0
- package/dist/setup-account.d.ts +11 -0
- package/dist/setup-account.d.ts.map +1 -0
- package/dist/setup-account.js +106 -0
- package/dist/setup-onboarding.d.ts +27 -1
- package/dist/setup-onboarding.d.ts.map +1 -1
- package/dist/setup-onboarding.js +95 -11
- package/dist/setup-summary.d.ts +12 -0
- package/dist/setup-summary.d.ts.map +1 -0
- package/dist/setup-summary.js +56 -0
- package/package.json +1 -1
- package/src/credentials.ts +326 -57
- package/src/help.ts +7 -2
- package/src/http.ts +325 -20
- package/src/index.ts +193 -279
- package/src/keyboard-select.ts +97 -0
- package/src/logout-diagnostic.ts +39 -0
- package/src/setup-account.ts +129 -0
- package/src/setup-onboarding.ts +133 -10
- package/src/setup-summary.ts +77 -0
- package/vendor/skills/orizu/references/cli-reference.md +2 -2
package/README.md
CHANGED
|
@@ -87,9 +87,29 @@ Install the CLI globally with your package manager:
|
|
|
87
87
|
| Bun | `bun add -g orizu` |
|
|
88
88
|
|
|
89
89
|
Then run the guided setup — it signs you in, asks you to choose or create a
|
|
90
|
-
team and project, initializes the local workspace contract,
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
team and project, initializes the local workspace contract, and optionally
|
|
91
|
+
hands off to Claude, Codex, Pi, OpenCode, and Cursor when their commands are
|
|
92
|
+
installed. Available commands appear in that order, with the first available
|
|
93
|
+
command selected by default. Other is always last. Enter launches the highlighted
|
|
94
|
+
agent; Esc skips agent launch and completes setup. Selecting Other prints the
|
|
95
|
+
complete prompt without launching anything. Explicit
|
|
96
|
+
`--launch claude|codex|pi|opencode|cursor` still requires an interactive terminal
|
|
97
|
+
and asks for confirmation unless `--yes` is supplied; non-interactive setup never
|
|
98
|
+
launches. Cursor uses the `agent` executable, not the Cursor editor `cursor` command.
|
|
99
|
+
The official [Cursor CLI overview](https://cursor.com/docs/cli/overview) and
|
|
100
|
+
[parameter reference](https://cursor.com/docs/cli/reference/parameters), retrieved
|
|
101
|
+
2026-08-30, document direct `agent "prompt"` and `agent -p "prompt"` initial prompts;
|
|
102
|
+
setup uses the direct positional form without a shell.
|
|
103
|
+
|
|
104
|
+
If you accept skill installation, the picker starts with
|
|
105
|
+
`Universal (.agents — Codex and others) — ~/.agents/skills/orizu` and shows each
|
|
106
|
+
detected native target with its `~/.../orizu` destination on the same line before
|
|
107
|
+
any write. All visible choices start selected, and any choice—including Universal—
|
|
108
|
+
can be deselected. In non-interactive setup, `--agent` opts into skill installation.
|
|
109
|
+
Every accepted `--agent` always includes Universal, plus that agent's native
|
|
110
|
+
destination where needed. Duplicate destinations are removed. With no `--agent` flags, setup writes no skills.
|
|
111
|
+
|
|
112
|
+
For example:
|
|
93
113
|
|
|
94
114
|
```bash
|
|
95
115
|
orizu setup
|
package/dist/credentials.d.ts
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
1
|
import { ServerCredentials, StoredCredentialsV2, StoredCredentialsV3 } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Runs a synchronous credentials transaction under the one process-wide and
|
|
4
|
+
* cross-process lock. Exported so real-process fixtures can hold the production
|
|
5
|
+
* lock; CLI credential mutations use this same helper.
|
|
6
|
+
*/
|
|
7
|
+
export declare function withCredentialsTransactionLock<T>(operation: () => T): T;
|
|
8
|
+
/**
|
|
9
|
+
* Holds the credentials lock until an awaited transaction settles. Nested
|
|
10
|
+
* synchronous credential writes are admitted only from this transaction's
|
|
11
|
+
* async execution context; unrelated same-process work must wait or fail.
|
|
12
|
+
*/
|
|
13
|
+
export declare function withCredentialsTransactionLockAsync<T>(operation: () => Promise<T>): Promise<T>;
|
|
2
14
|
export declare function loadCredentialsConfig(): StoredCredentialsV2 | StoredCredentialsV3 | null;
|
|
3
15
|
export declare function getServerCredentials(baseUrl: string): ServerCredentials | null;
|
|
4
16
|
export declare function saveServerCredentials(baseUrl: string, credentials: ServerCredentials): void;
|
|
5
17
|
export declare function updateServerCredentials(baseUrl: string, credentials: ServerCredentials): void;
|
|
18
|
+
export declare function credentialsEqual(left: ServerCredentials, right: ServerCredentials): boolean;
|
|
19
|
+
export declare function updateServerCredentialsIfCurrent(baseUrl: string, expected: ServerCredentials, replacement: ServerCredentials): boolean;
|
|
6
20
|
export declare function getActiveBaseUrl(): string | null;
|
|
7
21
|
/**
|
|
8
22
|
* In-sandbox bearer resolution (ALI-1044). Resolves a bearer supplied out-of-band
|
|
@@ -41,6 +55,7 @@ export declare function resolveAuthTokenForBaseUrl(baseUrl: string): string;
|
|
|
41
55
|
*/
|
|
42
56
|
export declare function hasResolvableAuth(baseUrl: string): boolean;
|
|
43
57
|
export declare function setActiveBaseUrl(baseUrl: string | null): void;
|
|
58
|
+
export declare function clearServerCredentialsIfCurrent(baseUrl: string, expected: ServerCredentials): boolean;
|
|
44
59
|
export declare function clearServerCredentials(baseUrl: string): boolean;
|
|
45
60
|
export declare function clearCredentialsFile(): void;
|
|
46
61
|
//# sourceMappingURL=credentials.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAiBA,OAAO,EACL,iBAAiB,EAEjB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,YAAY,CAAA;AAqInB;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,CAgCvE;AAED;;;;GAIG;AACH,wBAAsB,mCAAmC,CAAC,CAAC,EACzD,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAC1B,OAAO,CAAC,CAAC,CAAC,CAiDZ;AAwGD,wBAAgB,qBAAqB,IAAI,mBAAmB,GAAG,mBAAmB,GAAG,IAAI,CA8BxF;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAW9E;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,iBAAiB,QAepF;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,iBAAiB,QAatF;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAO3F;AAED,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,iBAAiB,EAC3B,WAAW,EAAE,iBAAiB,GAC7B,OAAO,CAUT;AAED,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAGhD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CA0BrD;AAED;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAYlE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAS1D;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,QAMtD;AAED,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,iBAAiB,GAC1B,OAAO,CAWT;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAc/D;AAED,wBAAgB,oBAAoB,SAKnC"}
|
package/dist/credentials.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { chmodSync, closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, writeFileSync, } from 'fs';
|
|
1
|
+
import { chmodSync, closeSync, existsSync, fsyncSync, linkSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, writeFileSync, } from 'fs';
|
|
2
2
|
import { join } from 'path';
|
|
3
|
-
import { homedir } from 'os';
|
|
3
|
+
import { homedir, hostname } from 'os';
|
|
4
4
|
import { randomBytes } from 'crypto';
|
|
5
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
5
6
|
function isNodeError(error) {
|
|
6
7
|
return error instanceof Error;
|
|
7
8
|
}
|
|
@@ -14,6 +15,186 @@ function getConfigDir() {
|
|
|
14
15
|
function getCredentialsPath() {
|
|
15
16
|
return join(getConfigDir(), 'credentials.json');
|
|
16
17
|
}
|
|
18
|
+
const DEFAULT_CREDENTIALS_LOCK_TIMEOUT_MS = 2_000;
|
|
19
|
+
const MAX_CREDENTIALS_LOCK_TIMEOUT_MS = 10_000;
|
|
20
|
+
const CREDENTIALS_LOCK_RETRY_MS = 20;
|
|
21
|
+
let heldCredentialsLock = null;
|
|
22
|
+
const credentialsTransactionOwner = new AsyncLocalStorage();
|
|
23
|
+
function getCredentialsLockPath() {
|
|
24
|
+
return `${getCredentialsPath()}.lock`;
|
|
25
|
+
}
|
|
26
|
+
function readLockDuration(name, fallback, maximum = Number.MAX_SAFE_INTEGER) {
|
|
27
|
+
const raw = process.env[name];
|
|
28
|
+
if (!raw)
|
|
29
|
+
return fallback;
|
|
30
|
+
const parsed = Number(raw);
|
|
31
|
+
return Number.isSafeInteger(parsed) && parsed > 0
|
|
32
|
+
? Math.min(parsed, maximum)
|
|
33
|
+
: fallback;
|
|
34
|
+
}
|
|
35
|
+
function sleepSync(milliseconds) {
|
|
36
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, milliseconds);
|
|
37
|
+
}
|
|
38
|
+
function acquireCredentialsLock() {
|
|
39
|
+
const dir = getConfigDir();
|
|
40
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
41
|
+
chmodSync(dir, 0o700);
|
|
42
|
+
const lockPath = getCredentialsLockPath();
|
|
43
|
+
const timeoutMs = readLockDuration('ORIZU_CREDENTIALS_LOCK_TIMEOUT_MS', DEFAULT_CREDENTIALS_LOCK_TIMEOUT_MS, MAX_CREDENTIALS_LOCK_TIMEOUT_MS);
|
|
44
|
+
const deadline = Date.now() + timeoutMs;
|
|
45
|
+
while (true) {
|
|
46
|
+
const metadata = JSON.stringify({
|
|
47
|
+
version: 1,
|
|
48
|
+
pid: process.pid,
|
|
49
|
+
hostname: hostname(),
|
|
50
|
+
createdAt: Date.now(),
|
|
51
|
+
instanceId: randomBytes(16).toString('hex'),
|
|
52
|
+
});
|
|
53
|
+
const tempPath = join(dir, `.credentials.json.lock.${process.pid}.${randomBytes(8).toString('hex')}.tmp`);
|
|
54
|
+
try {
|
|
55
|
+
const fd = openSync(tempPath, 'wx', 0o600);
|
|
56
|
+
try {
|
|
57
|
+
writeFileSync(fd, metadata, 'utf8');
|
|
58
|
+
fsyncSync(fd);
|
|
59
|
+
chmodSync(tempPath, 0o600);
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
closeSync(fd);
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
// link(2) publishes the already-complete inode without replacing an
|
|
66
|
+
// existing owner. No contender ever unlinks the canonical lock.
|
|
67
|
+
linkSync(tempPath, lockPath);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
if (!(isNodeError(error) && error.code === 'EEXIST'))
|
|
71
|
+
throw error;
|
|
72
|
+
if (Date.now() >= deadline) {
|
|
73
|
+
throw new Error(`ORIZU_CREDENTIALS_LOCK_TIMEOUT: credentials mutation did not acquire the lock within ${timeoutMs}ms. Verify no Orizu process is running, then remove credentials.json.lock manually.`);
|
|
74
|
+
}
|
|
75
|
+
sleepSync(Math.min(CREDENTIALS_LOCK_RETRY_MS, Math.max(1, deadline - Date.now())));
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
let resolveReleased = () => { };
|
|
79
|
+
const released = new Promise(resolve => { resolveReleased = resolve; });
|
|
80
|
+
return { path: lockPath, metadata, depth: 1, released, resolveReleased };
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
// The unique owner-only preparation link is never retained, whether
|
|
84
|
+
// publication succeeds, loses to an owner, or fails unexpectedly.
|
|
85
|
+
rmSync(tempPath, { force: true });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function releaseCredentialsLock(lock) {
|
|
90
|
+
let currentMetadata;
|
|
91
|
+
try {
|
|
92
|
+
currentMetadata = readFileSync(lock.path, 'utf8');
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
if (isNodeError(error) && error.code === 'ENOENT')
|
|
96
|
+
return;
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
// Preserve a changed/replaced lock rather than risking removal of another owner.
|
|
100
|
+
if (currentMetadata !== lock.metadata)
|
|
101
|
+
return;
|
|
102
|
+
rmSync(lock.path);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Runs a synchronous credentials transaction under the one process-wide and
|
|
106
|
+
* cross-process lock. Exported so real-process fixtures can hold the production
|
|
107
|
+
* lock; CLI credential mutations use this same helper.
|
|
108
|
+
*/
|
|
109
|
+
export function withCredentialsTransactionLock(operation) {
|
|
110
|
+
const lockPath = getCredentialsLockPath();
|
|
111
|
+
if (heldCredentialsLock) {
|
|
112
|
+
if (heldCredentialsLock.path !== lockPath) {
|
|
113
|
+
throw new Error('ORIZU_CREDENTIALS_LOCK_NESTED_CONFIG: credentials config changed during a mutation.');
|
|
114
|
+
}
|
|
115
|
+
if (heldCredentialsLock.asyncOwner
|
|
116
|
+
&& credentialsTransactionOwner.getStore() !== heldCredentialsLock.asyncOwner) {
|
|
117
|
+
throw new Error('ORIZU_CREDENTIALS_LOCK_REQUIRED: an asynchronous credentials transaction already owns the lock.');
|
|
118
|
+
}
|
|
119
|
+
heldCredentialsLock.depth += 1;
|
|
120
|
+
try {
|
|
121
|
+
return operation();
|
|
122
|
+
}
|
|
123
|
+
finally {
|
|
124
|
+
heldCredentialsLock.depth -= 1;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const lock = acquireCredentialsLock();
|
|
128
|
+
heldCredentialsLock = lock;
|
|
129
|
+
try {
|
|
130
|
+
return operation();
|
|
131
|
+
}
|
|
132
|
+
finally {
|
|
133
|
+
heldCredentialsLock = null;
|
|
134
|
+
try {
|
|
135
|
+
releaseCredentialsLock(lock);
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
lock.resolveReleased();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Holds the credentials lock until an awaited transaction settles. Nested
|
|
144
|
+
* synchronous credential writes are admitted only from this transaction's
|
|
145
|
+
* async execution context; unrelated same-process work must wait or fail.
|
|
146
|
+
*/
|
|
147
|
+
export async function withCredentialsTransactionLockAsync(operation) {
|
|
148
|
+
const lockPath = getCredentialsLockPath();
|
|
149
|
+
const currentOwner = credentialsTransactionOwner.getStore();
|
|
150
|
+
if (heldCredentialsLock) {
|
|
151
|
+
if (heldCredentialsLock.path !== lockPath) {
|
|
152
|
+
throw new Error('ORIZU_CREDENTIALS_LOCK_NESTED_CONFIG: credentials config changed during a mutation.');
|
|
153
|
+
}
|
|
154
|
+
if (heldCredentialsLock.asyncOwner === currentOwner && currentOwner) {
|
|
155
|
+
heldCredentialsLock.depth += 1;
|
|
156
|
+
try {
|
|
157
|
+
return await operation();
|
|
158
|
+
}
|
|
159
|
+
finally {
|
|
160
|
+
heldCredentialsLock.depth -= 1;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const timeoutMs = readLockDuration('ORIZU_CREDENTIALS_LOCK_TIMEOUT_MS', DEFAULT_CREDENTIALS_LOCK_TIMEOUT_MS, MAX_CREDENTIALS_LOCK_TIMEOUT_MS);
|
|
164
|
+
let timer;
|
|
165
|
+
const didRelease = await Promise.race([
|
|
166
|
+
heldCredentialsLock.released.then(() => true),
|
|
167
|
+
new Promise(resolve => { timer = setTimeout(() => resolve(false), timeoutMs); }),
|
|
168
|
+
]);
|
|
169
|
+
if (timer)
|
|
170
|
+
clearTimeout(timer);
|
|
171
|
+
if (!didRelease) {
|
|
172
|
+
throw new Error(`ORIZU_CREDENTIALS_LOCK_TIMEOUT: credentials mutation did not acquire the lock within ${timeoutMs}ms. Verify no Orizu process is running, then remove credentials.json.lock manually.`);
|
|
173
|
+
}
|
|
174
|
+
return await withCredentialsTransactionLockAsync(operation);
|
|
175
|
+
}
|
|
176
|
+
const lock = acquireCredentialsLock();
|
|
177
|
+
const owner = Symbol('credentials-transaction-owner');
|
|
178
|
+
lock.asyncOwner = owner;
|
|
179
|
+
heldCredentialsLock = lock;
|
|
180
|
+
try {
|
|
181
|
+
return await credentialsTransactionOwner.run(owner, operation);
|
|
182
|
+
}
|
|
183
|
+
finally {
|
|
184
|
+
heldCredentialsLock = null;
|
|
185
|
+
try {
|
|
186
|
+
releaseCredentialsLock(lock);
|
|
187
|
+
}
|
|
188
|
+
finally {
|
|
189
|
+
lock.resolveReleased();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function assertCredentialsLockHeld() {
|
|
194
|
+
if (!heldCredentialsLock || heldCredentialsLock.path !== getCredentialsLockPath()) {
|
|
195
|
+
throw new Error('ORIZU_CREDENTIALS_LOCK_REQUIRED: credentials writes require a transaction lock.');
|
|
196
|
+
}
|
|
197
|
+
}
|
|
17
198
|
function isStoredCredentialsV2(value) {
|
|
18
199
|
if (!value || typeof value !== 'object') {
|
|
19
200
|
return false;
|
|
@@ -52,35 +233,33 @@ function migrateToV2(stored) {
|
|
|
52
233
|
};
|
|
53
234
|
}
|
|
54
235
|
function writeCredentials(config) {
|
|
236
|
+
assertCredentialsLockHeld();
|
|
55
237
|
const dir = getConfigDir();
|
|
56
238
|
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
57
239
|
chmodSync(dir, 0o700);
|
|
58
240
|
const path = getCredentialsPath();
|
|
59
241
|
const tempPath = join(dir, `.credentials.json.${process.pid}.${randomBytes(8).toString('hex')}.tmp`);
|
|
60
242
|
const payload = JSON.stringify(config, null, 2) + '\n';
|
|
61
|
-
const fd = openSync(tempPath, 'wx', 0o600);
|
|
62
243
|
try {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
closeSync(fd);
|
|
68
|
-
}
|
|
69
|
-
chmodSync(tempPath, 0o600);
|
|
70
|
-
try {
|
|
71
|
-
renameSync(tempPath, path);
|
|
72
|
-
}
|
|
73
|
-
catch (error) {
|
|
74
|
-
if (process.platform === 'win32' && isNodeError(error) && error.code === 'EEXIST') {
|
|
75
|
-
rmSync(path, { force: true });
|
|
76
|
-
renameSync(tempPath, path);
|
|
244
|
+
const fd = openSync(tempPath, 'wx', 0o600);
|
|
245
|
+
try {
|
|
246
|
+
writeFileSync(fd, payload, 'utf-8');
|
|
247
|
+
fsyncSync(fd);
|
|
77
248
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
throw error;
|
|
249
|
+
finally {
|
|
250
|
+
closeSync(fd);
|
|
81
251
|
}
|
|
252
|
+
chmodSync(tempPath, 0o600);
|
|
253
|
+
// Never delete the destination to emulate replacement. If this platform
|
|
254
|
+
// cannot atomically replace it, preserve the old file and surface the error.
|
|
255
|
+
renameSync(tempPath, path);
|
|
256
|
+
chmodSync(path, 0o600);
|
|
257
|
+
}
|
|
258
|
+
finally {
|
|
259
|
+
// On success rename has already removed this path; on every error this
|
|
260
|
+
// removes the owner-only temporary file containing credential material.
|
|
261
|
+
rmSync(tempPath, { force: true });
|
|
82
262
|
}
|
|
83
|
-
chmodSync(path, 0o600);
|
|
84
263
|
}
|
|
85
264
|
function createEmptyCredentialsConfig() {
|
|
86
265
|
return {
|
|
@@ -134,29 +313,52 @@ export function getServerCredentials(baseUrl) {
|
|
|
134
313
|
return config.servers[baseUrl] || null;
|
|
135
314
|
}
|
|
136
315
|
export function saveServerCredentials(baseUrl, credentials) {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
316
|
+
return withCredentialsTransactionLock(() => {
|
|
317
|
+
const loaded = loadCredentialsConfigForWrite();
|
|
318
|
+
const config = loaded.version === 3
|
|
319
|
+
? loaded
|
|
320
|
+
: {
|
|
321
|
+
version: 3,
|
|
322
|
+
activeBaseUrl: loaded.activeBaseUrl,
|
|
323
|
+
servers: loaded.servers,
|
|
324
|
+
};
|
|
325
|
+
config.servers[baseUrl] = credentials;
|
|
326
|
+
config.activeBaseUrl = baseUrl;
|
|
327
|
+
writeCredentials(config);
|
|
328
|
+
});
|
|
148
329
|
}
|
|
149
330
|
export function updateServerCredentials(baseUrl, credentials) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
331
|
+
return withCredentialsTransactionLock(() => {
|
|
332
|
+
const loaded = loadCredentialsConfigForWrite();
|
|
333
|
+
const config = loaded.version === 3
|
|
334
|
+
? loaded
|
|
335
|
+
: {
|
|
336
|
+
version: 3,
|
|
337
|
+
activeBaseUrl: loaded.activeBaseUrl,
|
|
338
|
+
servers: loaded.servers,
|
|
339
|
+
};
|
|
340
|
+
config.servers[baseUrl] = credentials;
|
|
341
|
+
writeCredentials(config);
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
export function credentialsEqual(left, right) {
|
|
345
|
+
if ('apiKey' in left || 'apiKey' in right) {
|
|
346
|
+
return 'apiKey' in left && 'apiKey' in right && left.apiKey === right.apiKey;
|
|
347
|
+
}
|
|
348
|
+
return left.accessToken === right.accessToken
|
|
349
|
+
&& left.refreshToken === right.refreshToken
|
|
350
|
+
&& left.expiresAt === right.expiresAt;
|
|
351
|
+
}
|
|
352
|
+
export function updateServerCredentialsIfCurrent(baseUrl, expected, replacement) {
|
|
353
|
+
return withCredentialsTransactionLock(() => {
|
|
354
|
+
const config = loadCredentialsConfig();
|
|
355
|
+
const current = config?.servers[baseUrl];
|
|
356
|
+
if (!config || !current || !credentialsEqual(current, expected))
|
|
357
|
+
return false;
|
|
358
|
+
config.servers[baseUrl] = replacement;
|
|
359
|
+
writeCredentials(config);
|
|
360
|
+
return true;
|
|
361
|
+
});
|
|
160
362
|
}
|
|
161
363
|
export function getActiveBaseUrl() {
|
|
162
364
|
const config = loadCredentialsConfig();
|
|
@@ -244,25 +446,43 @@ export function hasResolvableAuth(baseUrl) {
|
|
|
244
446
|
return getServerCredentials(baseUrl) !== null;
|
|
245
447
|
}
|
|
246
448
|
export function setActiveBaseUrl(baseUrl) {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
449
|
+
return withCredentialsTransactionLock(() => {
|
|
450
|
+
const config = loadCredentialsConfigForWrite();
|
|
451
|
+
config.activeBaseUrl = baseUrl;
|
|
452
|
+
writeCredentials(config);
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
export function clearServerCredentialsIfCurrent(baseUrl, expected) {
|
|
456
|
+
return withCredentialsTransactionLock(() => {
|
|
457
|
+
const config = loadCredentialsConfig();
|
|
458
|
+
const current = config?.servers[baseUrl];
|
|
459
|
+
if (!config || !current || !credentialsEqual(current, expected))
|
|
460
|
+
return false;
|
|
461
|
+
delete config.servers[baseUrl];
|
|
462
|
+
if (config.activeBaseUrl === baseUrl)
|
|
463
|
+
config.activeBaseUrl = null;
|
|
464
|
+
writeCredentials(config);
|
|
465
|
+
return true;
|
|
466
|
+
});
|
|
250
467
|
}
|
|
251
468
|
export function clearServerCredentials(baseUrl) {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
config.activeBaseUrl
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
469
|
+
return withCredentialsTransactionLock(() => {
|
|
470
|
+
const config = loadCredentialsConfig();
|
|
471
|
+
if (!config || !Object.hasOwn(config.servers, baseUrl)) {
|
|
472
|
+
return false;
|
|
473
|
+
}
|
|
474
|
+
delete config.servers[baseUrl];
|
|
475
|
+
if (config.activeBaseUrl === baseUrl) {
|
|
476
|
+
config.activeBaseUrl = null;
|
|
477
|
+
}
|
|
478
|
+
writeCredentials(config);
|
|
479
|
+
return true;
|
|
480
|
+
});
|
|
262
481
|
}
|
|
263
482
|
export function clearCredentialsFile() {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
483
|
+
return withCredentialsTransactionLock(() => {
|
|
484
|
+
const path = getCredentialsPath();
|
|
485
|
+
if (existsSync(path))
|
|
486
|
+
rmSync(path);
|
|
487
|
+
});
|
|
268
488
|
}
|
package/dist/help.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,EAAE,EAAE,CAAA;IACpB,OAAO,CAAC,EAAE,YAAY,EAAE,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CACpB;AAuCD,eAAO,MAAM,YAAY,EAAE,aAAa,EAqoCvC,CAAA;AAUD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,GAAG,SAAS,CAMxE;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,CAWrE;AAOD,wBAAgB,cAAc,IAAI,MAAM,CA0CvC;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAoBtD;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CA4B5D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAgBxD;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;EAoB9C"}
|
package/dist/help.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { AGENT_LAUNCH_SPECS } from './setup-onboarding.js';
|
|
2
|
+
const SETUP_LAUNCH_AGENT_NAMES = Object.keys(AGENT_LAUNCH_SPECS);
|
|
3
|
+
const SETUP_LAUNCH_AGENT_USAGE = SETUP_LAUNCH_AGENT_NAMES.join('|');
|
|
1
4
|
const GLOBAL_OPTIONS = [
|
|
2
5
|
['--json', 'Emit machine-readable JSON instead of human text. Available on every command, as a prefix (orizu --json <command>) or trailing flag.'],
|
|
3
6
|
['--local', 'Use http://localhost:3000.'],
|
|
@@ -219,7 +222,7 @@ export const COMMAND_DOCS = [
|
|
|
219
222
|
},
|
|
220
223
|
{
|
|
221
224
|
path: ['setup'],
|
|
222
|
-
usage:
|
|
225
|
+
usage: `orizu setup [--team <slug>|--create-team <name>] [--project <slug>|--create-project <name>] [--agent <agent>]... [--workspace [path]|--no-workspace] [--validate] [--fix] [--no-symlinks] [--verbose] [--no-install] [--handoff|--no-handoff] [--launch <${SETUP_LAUNCH_AGENT_USAGE}>] [--skip-login] [--dry-run] [--no-input|--non-interactive] [--json]`,
|
|
223
226
|
summary: 'Guided onboarding: sign in, initialize the workbench contract, and install agent skills.',
|
|
224
227
|
group: 'Agent setup',
|
|
225
228
|
options: [
|
|
@@ -239,7 +242,7 @@ export const COMMAND_DOCS = [
|
|
|
239
242
|
{ name: '--no-install', help: 'Skip the coding-agent skill install step.' },
|
|
240
243
|
{ name: '--handoff', help: 'Print the llms.txt and selected-project handoff prompt after setup.' },
|
|
241
244
|
{ name: '--no-handoff', help: 'Compatibility flag; suppresses the final launch picker and explicit handoff/launch.' },
|
|
242
|
-
{ name: '--launch <agent>', help: 'Launch a detected coding agent with the selected project and llms.txt prompt (interactive terminals only).
|
|
245
|
+
{ name: '--launch <agent>', help: 'Launch a detected coding agent with the selected project and llms.txt prompt (interactive terminals only). The cursor selector uses the Cursor Agent `agent` executable, not the editor `cursor` command.', choices: SETUP_LAUNCH_AGENT_NAMES },
|
|
243
246
|
{ name: '--skip-login', help: 'Skip the authentication phase.' },
|
|
244
247
|
{ name: '--dry-run', help: 'Preview every planned change without writing.' },
|
|
245
248
|
{ name: '--no-input', help: 'Never prompt; behave as in a non-interactive terminal.' },
|
package/dist/http.d.ts
CHANGED
|
@@ -5,5 +5,25 @@ export declare function resolveLoginBaseUrl(flags?: GlobalFlags): string;
|
|
|
5
5
|
export declare function getBaseUrl(): string;
|
|
6
6
|
export declare function assertSecureTokenTransport(baseUrl: string): void;
|
|
7
7
|
export declare function credentialRequestRedirectPolicy(): Pick<RequestInit, 'redirect'>;
|
|
8
|
+
export type AuthenticatedRequestSource = 'ORIZU_TOKEN' | 'ORIZU_TOKEN_FILE' | 'stored';
|
|
9
|
+
export interface AuthenticatedRequestContext {
|
|
10
|
+
readonly baseUrl: string;
|
|
11
|
+
readonly source: AuthenticatedRequestSource;
|
|
12
|
+
fetch(path: string, init?: RequestInit): Promise<Response>;
|
|
13
|
+
logout(signal?: AbortSignal | null): Promise<LogoutResult>;
|
|
14
|
+
}
|
|
15
|
+
export interface LogoutResult {
|
|
16
|
+
remoteError: string | null;
|
|
17
|
+
localCredentialCleared: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Captures one authenticated server context for a multi-step operation. The
|
|
21
|
+
* returned interface intentionally exposes no credential material: its closure
|
|
22
|
+
* pins the selected origin and bearer/session so later global config changes
|
|
23
|
+
* cannot move an in-flight operation to another account.
|
|
24
|
+
*/
|
|
25
|
+
export declare function captureAuthenticatedRequestContext(options?: {
|
|
26
|
+
allowRefresh?: boolean;
|
|
27
|
+
}): AuthenticatedRequestContext;
|
|
8
28
|
export declare function authedFetch(path: string, init?: RequestInit): Promise<Response>;
|
|
9
29
|
//# sourceMappingURL=http.d.ts.map
|
package/dist/http.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AASA,OAAO,EAAkB,WAAW,EAAoB,MAAM,mBAAmB,CAAA;AASjF,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,QAEhD;AAED,wBAAgB,cAAc,CAAC,KAAK,GAAE,WAA0B,GAAG,MAAM,CAiBxE;AAED,wBAAgB,mBAAmB,CAAC,KAAK,GAAE,WAA0B,GAAG,MAAM,CAY7E;AAED,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAWD,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,QAmBzD;AAqFD,wBAAgB,+BAA+B,IAAI,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAE/E;AAkGD,MAAM,MAAM,0BAA0B,GAAG,aAAa,GAAG,kBAAkB,GAAG,QAAQ,CAAA;AAEtF,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAA;IAC3C,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC1D,MAAM,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;CAC3D;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,sBAAsB,EAAE,OAAO,CAAA;CAChC;AAED;;;;;GAKG;AACH,wBAAgB,kCAAkC,CAChD,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO,GACvC,2BAA2B,CAgI7B;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB,qBAiErE"}
|