overlord-cli 4.19.0 → 4.21.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/bin/_cli/credentials.mjs
CHANGED
|
@@ -22,8 +22,7 @@ const LOCAL_SECRET_HEADER = 'X-Overlord-Local-Secret';
|
|
|
22
22
|
* refresh_token?: string,
|
|
23
23
|
* organization_id?: number | null,
|
|
24
24
|
* platform_url: string,
|
|
25
|
-
* user_email?: string
|
|
26
|
-
* legacy_agent_token?: string
|
|
25
|
+
* user_email?: string
|
|
27
26
|
* }} Credentials
|
|
28
27
|
*/
|
|
29
28
|
|
|
@@ -80,10 +79,9 @@ function parseStoredCredentialsData(parsed, { requireAuthData = false } = {}) {
|
|
|
80
79
|
typeof parsed.organization_id === 'number' && Number.isFinite(parsed.organization_id)
|
|
81
80
|
? parsed.organization_id
|
|
82
81
|
: null;
|
|
83
|
-
const legacyAgentToken = accessToken && !refreshToken ? accessToken : '';
|
|
84
82
|
|
|
85
83
|
if (!platformUrl) return null;
|
|
86
|
-
if (requireAuthData && !refreshToken
|
|
84
|
+
if (requireAuthData && !refreshToken) return null;
|
|
87
85
|
|
|
88
86
|
return {
|
|
89
87
|
platform_url: platformUrl,
|
|
@@ -93,8 +91,7 @@ function parseStoredCredentialsData(parsed, { requireAuthData = false } = {}) {
|
|
|
93
91
|
...(organizationId ? { organization_id: organizationId } : {}),
|
|
94
92
|
...(typeof parsed.user_email === 'string' && parsed.user_email.trim()
|
|
95
93
|
? { user_email: parsed.user_email.trim() }
|
|
96
|
-
: {})
|
|
97
|
-
...(legacyAgentToken ? { legacy_agent_token: legacyAgentToken } : {})
|
|
94
|
+
: {})
|
|
98
95
|
};
|
|
99
96
|
}
|
|
100
97
|
|
|
@@ -151,7 +148,6 @@ export function saveCredentials(data) {
|
|
|
151
148
|
}
|
|
152
149
|
if (credentials.organization_id) electronPayload.organization_id = credentials.organization_id;
|
|
153
150
|
if (credentials.user_email) electronPayload.user_email = credentials.user_email;
|
|
154
|
-
delete electronPayload.legacy_agent_token;
|
|
155
151
|
delete electronPayload.supabase_refresh_token;
|
|
156
152
|
writeJsonFileAtomic(ELECTRON_CREDENTIALS_FILE, electronPayload);
|
|
157
153
|
}
|
|
@@ -465,17 +461,23 @@ export async function resolveAuth() {
|
|
|
465
461
|
? runtime.local_secret
|
|
466
462
|
: '';
|
|
467
463
|
|
|
468
|
-
const
|
|
469
|
-
if (
|
|
464
|
+
const envAccessToken = normalizeAccessToken(process.env.OVERLORD_ACCESS_TOKEN);
|
|
465
|
+
if (envAccessToken) {
|
|
466
|
+
const envOrganizationId =
|
|
467
|
+
typeof process.env.OVERLORD_ORGANIZATION_ID === 'string'
|
|
468
|
+
? Number.parseInt(process.env.OVERLORD_ORGANIZATION_ID, 10)
|
|
469
|
+
: null;
|
|
470
|
+
if (!Number.isFinite(envOrganizationId)) {
|
|
471
|
+
throw new Error(
|
|
472
|
+
'OVERLORD_ACCESS_TOKEN requires OVERLORD_ORGANIZATION_ID so protocol requests stay scoped.'
|
|
473
|
+
);
|
|
474
|
+
}
|
|
470
475
|
return {
|
|
471
476
|
platformUrl,
|
|
472
|
-
bearerToken:
|
|
477
|
+
bearerToken: envAccessToken,
|
|
473
478
|
localSecret,
|
|
474
|
-
organizationId:
|
|
475
|
-
|
|
476
|
-
? Number.parseInt(process.env.OVERLORD_ORGANIZATION_ID, 10)
|
|
477
|
-
: null,
|
|
478
|
-
authMode: 'legacy_agent_token'
|
|
479
|
+
organizationId: envOrganizationId,
|
|
480
|
+
authMode: 'oauth_env'
|
|
479
481
|
};
|
|
480
482
|
}
|
|
481
483
|
|
|
@@ -525,16 +527,6 @@ export async function resolveAuth() {
|
|
|
525
527
|
};
|
|
526
528
|
}
|
|
527
529
|
|
|
528
|
-
if (creds.legacy_agent_token) {
|
|
529
|
-
return {
|
|
530
|
-
platformUrl,
|
|
531
|
-
bearerToken: creds.legacy_agent_token,
|
|
532
|
-
localSecret,
|
|
533
|
-
organizationId: creds.organization_id ?? null,
|
|
534
|
-
authMode: 'legacy_agent_token'
|
|
535
|
-
};
|
|
536
|
-
}
|
|
537
|
-
|
|
538
530
|
return {
|
|
539
531
|
platformUrl,
|
|
540
532
|
bearerToken: 'overlord-local-dev-token',
|
|
@@ -564,12 +556,10 @@ export async function getAuthStatus() {
|
|
|
564
556
|
}
|
|
565
557
|
|
|
566
558
|
let tokenSource = 'fallback';
|
|
567
|
-
if (
|
|
568
|
-
tokenSource = '
|
|
559
|
+
if (normalizeAccessToken(process.env.OVERLORD_ACCESS_TOKEN)) {
|
|
560
|
+
tokenSource = 'OVERLORD_ACCESS_TOKEN';
|
|
569
561
|
} else if (creds?.refresh_token) {
|
|
570
562
|
tokenSource = getCredentialFileSource();
|
|
571
|
-
} else if (creds?.legacy_agent_token) {
|
|
572
|
-
tokenSource = `${getCredentialFileSource()} (legacy)`;
|
|
573
563
|
}
|
|
574
564
|
|
|
575
565
|
let platformUrlSource = 'default';
|
|
@@ -613,7 +603,7 @@ export function repairCredentials() {
|
|
|
613
603
|
};
|
|
614
604
|
}
|
|
615
605
|
|
|
616
|
-
function
|
|
606
|
+
function normalizeAccessToken(value) {
|
|
617
607
|
if (typeof value !== 'string') return '';
|
|
618
608
|
return value.trim();
|
|
619
609
|
}
|
package/bin/_cli/launcher.mjs
CHANGED
|
@@ -173,8 +173,31 @@ async function runAgent(agent, mode = 'run') {
|
|
|
173
173
|
} else {
|
|
174
174
|
execFileSync('opencode', ['--prompt', context], { stdio: 'inherit', env: childEnv });
|
|
175
175
|
}
|
|
176
|
-
} else {
|
|
177
|
-
|
|
176
|
+
} else if (agent === 'gemini') {
|
|
177
|
+
// Write context to a temp file. Passing inline content as a positional arg
|
|
178
|
+
// causes Gemini's @-reference parser to lstat(cwd + content) when it encounters
|
|
179
|
+
// @ symbols in the markdown (e.g. "@@ -10,6 +10,14 @@" in JSON hunk examples),
|
|
180
|
+
// producing an ENAMETOOLONG crash. Using @file keeps the path short.
|
|
181
|
+
const tag = `overlord-${ticketId.slice(-8)}-${Date.now()}`;
|
|
182
|
+
const contextFile = path.join(os.tmpdir(), `${tag}-ctx.md`);
|
|
183
|
+
fs.writeFileSync(contextFile, context, 'utf-8');
|
|
184
|
+
setTimeout(() => { try { fs.unlinkSync(contextFile); } catch { /* already gone */ } }, 30 * 60_000).unref();
|
|
185
|
+
|
|
186
|
+
if (mode === 'resume') {
|
|
187
|
+
const geminiSessionId = process.env.GEMINI_SESSION_ID?.trim();
|
|
188
|
+
const resumeTarget = geminiSessionId ?? 'latest';
|
|
189
|
+
execFileSync(
|
|
190
|
+
'gemini',
|
|
191
|
+
['--resume', resumeTarget, '--include-directories', os.tmpdir(), `@${contextFile}`],
|
|
192
|
+
{ stdio: 'inherit', env: childEnv }
|
|
193
|
+
);
|
|
194
|
+
} else {
|
|
195
|
+
execFileSync(
|
|
196
|
+
'gemini',
|
|
197
|
+
['--include-directories', os.tmpdir(), `@${contextFile}`],
|
|
198
|
+
{ stdio: 'inherit', env: childEnv }
|
|
199
|
+
);
|
|
200
|
+
}
|
|
178
201
|
}
|
|
179
202
|
} catch (error) {
|
|
180
203
|
const isResume = mode === 'resume';
|
package/bin/_cli/protocol.mjs
CHANGED
|
@@ -1280,7 +1280,7 @@ Subcommands:
|
|
|
1280
1280
|
Environment fallback:
|
|
1281
1281
|
--session-key <- SESSION_KEY
|
|
1282
1282
|
--ticket-id <- TICKET_ID
|
|
1283
|
-
auth/host <- OVERLORD_URL, optional
|
|
1283
|
+
auth/host <- OVERLORD_URL, optional OVERLORD_ACCESS_TOKEN + OVERLORD_ORGANIZATION_ID, or shared OAuth credentials from ovld auth/Desktop login
|
|
1284
1284
|
--timeout <- OVERLORD_TIMEOUT
|
|
1285
1285
|
|
|
1286
1286
|
Common flags:
|
package/package.json
CHANGED
package/plugins/claude/README.md
CHANGED
|
@@ -7,7 +7,7 @@ Claude Code plugin that exposes the Overlord local ticket workflow to any Claude
|
|
|
7
7
|
- `skills/overlord-ticket/SKILL.md` — durable attach → update → ask → deliver workflow.
|
|
8
8
|
- `commands/{connect,load,create,spawn}.md` — slash commands for session routing and ticket creation.
|
|
9
9
|
- `hooks/hooks.json` + `scripts/permission-hook.sh` — PermissionRequest notifier that calls `ovld protocol permission-request`.
|
|
10
|
-
- `userConfig` for
|
|
10
|
+
- `userConfig` for `overlord_url`. Current installs should authenticate with `ovld auth login` or Overlord Desktop; env vars remain optional overrides for remote shells, CI, and explicit OAuth token injection.
|
|
11
11
|
|
|
12
12
|
## Requirements
|
|
13
13
|
|
|
@@ -29,7 +29,7 @@ claude plugin marketplace add cooperativ/overlord-marketplace
|
|
|
29
29
|
claude plugin install overlord@cooperativ
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
Older plugin versions prompted for `overlord_url` and
|
|
32
|
+
Older plugin versions prompted for `overlord_url` and a legacy token at install time. The current hook goes through `ovld protocol`, so the CLI resolves auth from env vars or the shared `~/.ovld` credentials written by CLI/Desktop login.
|
|
33
33
|
|
|
34
34
|
## Namespaced components
|
|
35
35
|
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
# Overlord PermissionRequest notification hook (plugin-managed).
|
|
3
3
|
#
|
|
4
4
|
# Prefers plugin userConfig values (CLAUDE_PLUGIN_OPTION_*) when set, and falls
|
|
5
|
-
# back to the raw OVERLORD_URL /
|
|
6
|
-
# already export. Silently no-ops if we can't authenticate — the hook must
|
|
5
|
+
# back to the raw OVERLORD_URL / OVERLORD_ACCESS_TOKEN env vars Overlord-launched
|
|
6
|
+
# shells already export. Silently no-ops if we can't authenticate — the hook must
|
|
7
7
|
# never block the user or leak errors into the Claude session.
|
|
8
8
|
BODY=$(cat -)
|
|
9
9
|
OVERLORD_BASE_URL="${CLAUDE_PLUGIN_OPTION_OVERLORD_URL:-$OVERLORD_URL}"
|
|
10
|
-
OVERLORD_TOKEN="${
|
|
10
|
+
OVERLORD_TOKEN="${CLAUDE_PLUGIN_OPTION_OVERLORD_ACCESS_TOKEN:-$OVERLORD_ACCESS_TOKEN}"
|
|
11
11
|
if [ -n "$OVERLORD_BASE_URL" ] && [ -n "$OVERLORD_TOKEN" ] && [ -n "$TICKET_ID" ]; then
|
|
12
12
|
curl -sf -m 5 \
|
|
13
13
|
-X POST "$OVERLORD_BASE_URL/api/protocol/permission-request?ticketId=$TICKET_ID" \
|
|
@@ -14,7 +14,7 @@ personal marketplace entry at `~/.agents/plugins/marketplace.json`.
|
|
|
14
14
|
## Requirements
|
|
15
15
|
|
|
16
16
|
- Install the Overlord CLI so `ovld` is available on `PATH`.
|
|
17
|
-
- Authenticate with `ovld auth login` or Overlord Desktop. `OVERLORD_URL`
|
|
17
|
+
- Authenticate with `ovld auth login` or Overlord Desktop. `OVERLORD_URL` can be used to point the CLI at a non-default host.
|
|
18
18
|
- Optionally set `OVLD_BIN` if the CLI lives at a non-standard path.
|
|
19
19
|
|
|
20
20
|
## Tool coverage
|