@bridge4dev/runner 0.65.1 → 0.67.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/account-commands.d.ts +43 -0
- package/dist/account-commands.js +142 -0
- package/dist/adapters/claude-usage.d.ts +79 -15
- package/dist/adapters/claude-usage.js +143 -67
- package/dist/adapters/claude.d.ts +30 -1
- package/dist/adapters/claude.js +171 -11
- package/dist/adapters/codex-home.d.ts +143 -21
- package/dist/adapters/codex-home.js +623 -77
- package/dist/adapters/codex.d.ts +25 -3
- package/dist/adapters/codex.js +149 -11
- package/dist/adapters/types.d.ts +22 -0
- package/dist/agent-auth.d.ts +100 -0
- package/dist/agent-auth.js +273 -15
- package/dist/auth-relay.d.ts +114 -26
- package/dist/auth-relay.js +464 -278
- package/dist/claude-homes.d.ts +433 -0
- package/dist/claude-homes.js +1550 -0
- package/dist/codex-accounts.d.ts +79 -0
- package/dist/codex-accounts.js +386 -0
- package/dist/commit-message.js +4 -1
- package/dist/config.d.ts +16 -16
- package/dist/config.js +4 -1
- package/dist/index.js +78 -10
- package/dist/login-marks.d.ts +42 -0
- package/dist/login-marks.js +70 -0
- package/dist/protocol.d.ts +38 -38
- package/dist/protocol.js +3 -1
- package/dist/supervisor.js +17 -4
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7,14 +7,17 @@ import path from 'node:path';
|
|
|
7
7
|
import { promisify } from 'node:util';
|
|
8
8
|
import { ClaudeAdapter } from './adapters/claude.js';
|
|
9
9
|
import { CodexAdapter } from './adapters/codex.js';
|
|
10
|
-
import { ensureCodexHome } from './adapters/codex-home.js';
|
|
10
|
+
import { configureCodexAuth, discardAbandonedCodexStagingHomes, ensureCodexHome, } from './adapters/codex-home.js';
|
|
11
11
|
import { sessionClaudePath } from './agent-binary.js';
|
|
12
12
|
import { claimCageAuthority, runSystemctl } from './cage-authority.js';
|
|
13
13
|
import { acquireDaemonLock, isHeldByAnother } from './daemon-lock.js';
|
|
14
|
-
import { loadConfig, mergeIntoPairedConfig, requireConfig, saveConfig
|
|
14
|
+
import { loadConfig, mergeIntoPairedConfig, requireConfig, saveConfig } from './config.js';
|
|
15
15
|
import { log } from './log.js';
|
|
16
16
|
import { installIsWritable, installPrefixFor, isSupervisedProcess, restartCapability, manualUpdateCommand, resolveInstalledPackageDir, } from './self-update.js';
|
|
17
17
|
import { applyStoredClaudeToken } from './agent-auth.js';
|
|
18
|
+
import { discardAbandonedStagingHomes, recoverInterruptedSwaps, refreshAccountIdentity, } from './claude-homes.js';
|
|
19
|
+
import { ACCOUNT_AGENTS, ACCOUNT_COMMANDS } from './account-commands.js';
|
|
20
|
+
import { MACHINE_ACCOUNT_ID } from './login-marks.js';
|
|
18
21
|
import { Supervisor } from './supervisor.js';
|
|
19
22
|
import { readStatusFile, isPidAlive, writeStatusFile, STATUS_FRESH_MS } from './status-file.js';
|
|
20
23
|
import { RunnerWsClient } from './ws-client.js';
|
|
@@ -515,6 +518,13 @@ function runnerCapabilities(apiUrlOverride) {
|
|
|
515
518
|
* `kind: 'oom'` is inferred from the cgroup counter — see `crash-note.ts`.
|
|
516
519
|
*/
|
|
517
520
|
...(LAST_EXIT ? { lastExit: LAST_EXIT } : {}),
|
|
521
|
+
/**
|
|
522
|
+
* #422 (R11): the agents this runner keeps several logins for. Static per
|
|
523
|
+
* version – the LIST of accounts is always asked with `agent_accounts`,
|
|
524
|
+
* never read from here (a snapshot taken at start, #395). The dashboard
|
|
525
|
+
* shows the account window only to an agent named here.
|
|
526
|
+
*/
|
|
527
|
+
accounts: [...ACCOUNT_AGENTS],
|
|
518
528
|
/** Commands beyond the stage-A/B set. */
|
|
519
529
|
commands: [
|
|
520
530
|
'purge_session',
|
|
@@ -578,6 +588,10 @@ function runnerCapabilities(apiUrlOverride) {
|
|
|
578
588
|
// ANSWERS the command, with a sentence saying why — which is a better
|
|
579
589
|
// outcome than a frame nobody replies to.
|
|
580
590
|
'runner_restart',
|
|
591
|
+
// #422: list, sign in to, switch and forget agent logins (plan §8).
|
|
592
|
+
// Unconditional: they read and write only the runner's own state, and an
|
|
593
|
+
// agent they do not serve yet is answered with a sentence.
|
|
594
|
+
...ACCOUNT_COMMANDS,
|
|
581
595
|
],
|
|
582
596
|
};
|
|
583
597
|
}
|
|
@@ -633,15 +647,19 @@ async function cmdPair(args) {
|
|
|
633
647
|
* per-session: a fresh home clones ~90 MB of plugin marketplace on first use.
|
|
634
648
|
* A failure here disables Codex rather than the whole daemon.
|
|
635
649
|
*/
|
|
636
|
-
function bootstrapCodex(
|
|
650
|
+
function bootstrapCodex() {
|
|
637
651
|
try {
|
|
638
|
-
const home = ensureCodexHome(
|
|
639
|
-
log.info('codex: isolated home ready', {
|
|
652
|
+
const home = ensureCodexHome();
|
|
653
|
+
log.info('codex: isolated home ready', {
|
|
654
|
+
path: home.path,
|
|
655
|
+
auth: home.auth,
|
|
656
|
+
...(home.accountId ? { account: home.accountId } : {}),
|
|
657
|
+
});
|
|
640
658
|
// Deliberately NOT passing `codexHome`: the adapter re-asserts the home on
|
|
641
659
|
// every session. Freezing this snapshot is how a credential that went
|
|
642
660
|
// missing mid-day kept being reported as present while sessions failed.
|
|
643
|
-
//
|
|
644
|
-
return new CodexAdapter(
|
|
661
|
+
// Nor the mode: those repairs read it from `configureCodexAuth`.
|
|
662
|
+
return new CodexAdapter();
|
|
645
663
|
}
|
|
646
664
|
catch (error) {
|
|
647
665
|
log.error('codex: could not prepare an isolated home — Codex disabled', {
|
|
@@ -955,9 +973,43 @@ async function cmdDaemon() {
|
|
|
955
973
|
if (applyStoredClaudeToken()) {
|
|
956
974
|
log.info('daemon: using the Claude token stored on this server');
|
|
957
975
|
}
|
|
976
|
+
/**
|
|
977
|
+
* #422: a swap of Claude homes the previous daemon died inside is finished or
|
|
978
|
+
* undone before anything can run under an account; and who the machine login
|
|
979
|
+
* is gets asked once, in the background (R14 c) – the verdict and the list read
|
|
980
|
+
* the answer, the minute poll never asks.
|
|
981
|
+
*/
|
|
982
|
+
try {
|
|
983
|
+
recoverInterruptedSwaps();
|
|
984
|
+
}
|
|
985
|
+
catch (error) {
|
|
986
|
+
log.warn('daemon: could not finish an interrupted swap of Claude homes', {
|
|
987
|
+
error: String(error),
|
|
988
|
+
});
|
|
989
|
+
}
|
|
990
|
+
try {
|
|
991
|
+
// A sign-in the previous daemon accepted but never adopted (S2): nothing can
|
|
992
|
+
// be adopting before the supervisor exists. Codex sign-ins too (S4) – and
|
|
993
|
+
// the fixed-path staging home runners before S4 never removed.
|
|
994
|
+
discardAbandonedStagingHomes();
|
|
995
|
+
discardAbandonedCodexStagingHomes();
|
|
996
|
+
}
|
|
997
|
+
catch (error) {
|
|
998
|
+
log.warn('daemon: could not remove sign-in homes a previous daemon left', {
|
|
999
|
+
error: String(error),
|
|
1000
|
+
});
|
|
1001
|
+
}
|
|
1002
|
+
void refreshAccountIdentity(MACHINE_ACCOUNT_ID).catch(() => undefined);
|
|
1003
|
+
// Only a mode the owner WROTE is ever forced, and never over a saved login
|
|
1004
|
+
// (#422 S4 item 2): the defaults that used to be passed around re-linked the
|
|
1005
|
+
// host login at every start, session and probe. Recorded whatever is on PATH:
|
|
1006
|
+
// Codex may be installed from the dashboard later, and the account commands and
|
|
1007
|
+
// the minute probe read this from the first moment (found by the independent
|
|
1008
|
+
// check of S4).
|
|
1009
|
+
configureCodexAuth(config.codex?.auth);
|
|
958
1010
|
const agents = installedAgents();
|
|
959
1011
|
const ws = new RunnerWsClient(config.api.ws_url, config.server.token, runnerCapabilities());
|
|
960
|
-
const codex = agents.includes('codex') ? bootstrapCodex(
|
|
1012
|
+
const codex = agents.includes('codex') ? bootstrapCodex() : null;
|
|
961
1013
|
const supervisor = new Supervisor(ws, {
|
|
962
1014
|
adapters: {
|
|
963
1015
|
CLAUDE: new ClaudeAdapter(),
|
|
@@ -976,7 +1028,7 @@ async function cmdDaemon() {
|
|
|
976
1028
|
* `hasExecutable` is asked HERE, at the moment of the question, which is
|
|
977
1029
|
* the whole point.
|
|
978
1030
|
*/
|
|
979
|
-
makeAdapter: (agent) => agent === 'CODEX' && hasExecutable('codex') ? bootstrapCodex(
|
|
1031
|
+
makeAdapter: (agent) => (agent === 'CODEX' && hasExecutable('codex') ? bootstrapCodex() : null),
|
|
980
1032
|
...(config.mcp ? { mcp: { url: config.mcp.url, token: config.mcp.token } } : {}),
|
|
981
1033
|
...(config.limits?.max_sessions ? { maxSessionsLimit: config.limits.max_sessions } : {}),
|
|
982
1034
|
/**
|
|
@@ -1379,6 +1431,15 @@ async function runnerChecks() {
|
|
|
1379
1431
|
});
|
|
1380
1432
|
return checks;
|
|
1381
1433
|
}
|
|
1434
|
+
/** « · account <email> (saved)» – nothing for the machine login nobody named. */
|
|
1435
|
+
function accountLine(account) {
|
|
1436
|
+
if (!account)
|
|
1437
|
+
return '';
|
|
1438
|
+
if (account.id === MACHINE_ACCOUNT_ID) {
|
|
1439
|
+
return account.email ? ` · machine login ${account.email}` : '';
|
|
1440
|
+
}
|
|
1441
|
+
return ` · saved account ${account.email ?? account.id}`;
|
|
1442
|
+
}
|
|
1382
1443
|
async function agentChecks() {
|
|
1383
1444
|
const me = runnerIdentity();
|
|
1384
1445
|
// The probes log a verdict line each, which belongs in the journal, not in
|
|
@@ -1440,8 +1501,12 @@ async function agentChecks() {
|
|
|
1440
1501
|
checks.push({
|
|
1441
1502
|
ok: signedIn,
|
|
1442
1503
|
name: `${agent} login`,
|
|
1504
|
+
// Which account the verdict is about (#422): the same rule as the panel,
|
|
1505
|
+
// read from the same file, so doctor and the dashboard cannot answer about
|
|
1506
|
+
// two different logins on one machine.
|
|
1443
1507
|
detail: (info.detail ?? info.status) +
|
|
1444
|
-
(info.expiresAt ? ` · until ${formatLocalDay(info.expiresAt)}` : '')
|
|
1508
|
+
(info.expiresAt ? ` · until ${formatLocalDay(info.expiresAt)}` : '') +
|
|
1509
|
+
accountLine(info.activeAccount),
|
|
1445
1510
|
...(signedIn
|
|
1446
1511
|
? {}
|
|
1447
1512
|
: {
|
|
@@ -1621,6 +1686,9 @@ async function cmdDoctor(args) {
|
|
|
1621
1686
|
// reloads systemd, which is the `install` grade and nothing above it (#403).
|
|
1622
1687
|
claimCageAuthority(fix ? 'install' : 'probe');
|
|
1623
1688
|
const config = loadConfig();
|
|
1689
|
+
// The same Codex mode the daemon honours, or doctor's verdict would repair the
|
|
1690
|
+
// home by a rule the daemon does not follow (#422 S4 item 2).
|
|
1691
|
+
configureCodexAuth(config?.codex?.auth);
|
|
1624
1692
|
print(`devbridge-runner ${RUNNER_VERSION}`);
|
|
1625
1693
|
print(config ? `Paired with: ${config.server.name} (${config.api.url})` : 'Not paired');
|
|
1626
1694
|
// Paths given on the command line win; otherwise check what this runner has
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { RelayAgentName } from './agent-registry.js';
|
|
2
|
+
/**
|
|
3
|
+
* What the agent actually experienced with a sign-in — per agent AND per account.
|
|
4
|
+
*
|
|
5
|
+
* The credentials file cannot tell us the provider revoked a login: the refresh
|
|
6
|
+
* token still sits there, dated. The one authority on that is a real refusal
|
|
7
|
+
* from a real run — so a session that failed to authenticate demotes the file's
|
|
8
|
+
* verdict for a while, and any successful turn clears it again.
|
|
9
|
+
*
|
|
10
|
+
* Moved out of `auth-relay.ts` for #422 and keyed by account as well as agent.
|
|
11
|
+
* With several Claude logins on one machine «Claude was refused» stopped being
|
|
12
|
+
* a statement about anything: the session that was refused ran under ONE
|
|
13
|
+
* account, and the machine may have been switched to another since. The mark
|
|
14
|
+
* belongs to the account the session started under (R14) – which is why both
|
|
15
|
+
* the account list (`claude-homes.ts`) and the panel verdict (`auth-relay.ts`)
|
|
16
|
+
* read it from here rather than each keeping a copy.
|
|
17
|
+
*
|
|
18
|
+
* Process memory on purpose: no protocol, no disk. The consequence is worth
|
|
19
|
+
* naming — restarting the daemon forgets the refusal and the panel goes back
|
|
20
|
+
* to trusting the file until the next session tries. (A saved account also
|
|
21
|
+
* carries a mark on disk, D2 – see `markLoginExpired` in `claude-homes.ts`.)
|
|
22
|
+
*/
|
|
23
|
+
/** The machine's own login – the one row every agent has. */
|
|
24
|
+
export declare const MACHINE_ACCOUNT_ID = "machine";
|
|
25
|
+
/**
|
|
26
|
+
* A saved account's id – twelve lowercase letters and digits, never `machine`.
|
|
27
|
+
* One format for both agents (#422 S4): the wire, the refusal marks and the
|
|
28
|
+
* dashboard read the same alphabet whichever agent a row belongs to.
|
|
29
|
+
*/
|
|
30
|
+
export declare function isAccountId(id: unknown): id is string;
|
|
31
|
+
/** A refusal meant for a person: the wire (S2) sends its message as it is, and it names no path. */
|
|
32
|
+
export declare class AccountError extends Error {
|
|
33
|
+
constructor(message: string);
|
|
34
|
+
}
|
|
35
|
+
export declare function newAccountId(): string;
|
|
36
|
+
/** A session under this agent and account was just refused. */
|
|
37
|
+
export declare function noteRefusal(agent: RelayAgentName, accountId?: string): void;
|
|
38
|
+
/** The sign-in worked again. Answers whether a refusal was being held. */
|
|
39
|
+
export declare function clearRefusal(agent: RelayAgentName, accountId?: string): boolean;
|
|
40
|
+
/** Is a refusal still being held against this agent and account? */
|
|
41
|
+
export declare function refusalActive(agent: RelayAgentName, accountId?: string): boolean;
|
|
42
|
+
//# sourceMappingURL=login-marks.d.ts.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
/**
|
|
3
|
+
* What the agent actually experienced with a sign-in — per agent AND per account.
|
|
4
|
+
*
|
|
5
|
+
* The credentials file cannot tell us the provider revoked a login: the refresh
|
|
6
|
+
* token still sits there, dated. The one authority on that is a real refusal
|
|
7
|
+
* from a real run — so a session that failed to authenticate demotes the file's
|
|
8
|
+
* verdict for a while, and any successful turn clears it again.
|
|
9
|
+
*
|
|
10
|
+
* Moved out of `auth-relay.ts` for #422 and keyed by account as well as agent.
|
|
11
|
+
* With several Claude logins on one machine «Claude was refused» stopped being
|
|
12
|
+
* a statement about anything: the session that was refused ran under ONE
|
|
13
|
+
* account, and the machine may have been switched to another since. The mark
|
|
14
|
+
* belongs to the account the session started under (R14) – which is why both
|
|
15
|
+
* the account list (`claude-homes.ts`) and the panel verdict (`auth-relay.ts`)
|
|
16
|
+
* read it from here rather than each keeping a copy.
|
|
17
|
+
*
|
|
18
|
+
* Process memory on purpose: no protocol, no disk. The consequence is worth
|
|
19
|
+
* naming — restarting the daemon forgets the refusal and the panel goes back
|
|
20
|
+
* to trusting the file until the next session tries. (A saved account also
|
|
21
|
+
* carries a mark on disk, D2 – see `markLoginExpired` in `claude-homes.ts`.)
|
|
22
|
+
*/
|
|
23
|
+
/** The machine's own login – the one row every agent has. */
|
|
24
|
+
export const MACHINE_ACCOUNT_ID = 'machine';
|
|
25
|
+
const ACCOUNT_ID = /^[a-z0-9]{12}$/;
|
|
26
|
+
/**
|
|
27
|
+
* A saved account's id – twelve lowercase letters and digits, never `machine`.
|
|
28
|
+
* One format for both agents (#422 S4): the wire, the refusal marks and the
|
|
29
|
+
* dashboard read the same alphabet whichever agent a row belongs to.
|
|
30
|
+
*/
|
|
31
|
+
export function isAccountId(id) {
|
|
32
|
+
return typeof id === 'string' && ACCOUNT_ID.test(id);
|
|
33
|
+
}
|
|
34
|
+
/** A refusal meant for a person: the wire (S2) sends its message as it is, and it names no path. */
|
|
35
|
+
export class AccountError extends Error {
|
|
36
|
+
constructor(message) {
|
|
37
|
+
super(message);
|
|
38
|
+
this.name = 'AccountError';
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export function newAccountId() {
|
|
42
|
+
// base32-ish from random bytes: 12 characters of [a-z0-9].
|
|
43
|
+
const alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
|
44
|
+
const bytes = crypto.randomBytes(12);
|
|
45
|
+
return Array.from(bytes, (byte) => alphabet[byte % alphabet.length]).join('');
|
|
46
|
+
}
|
|
47
|
+
const AUTH_FAILURE_TTL_MS = 15 * 60_000;
|
|
48
|
+
const refusals = new Map();
|
|
49
|
+
const keyOf = (agent, accountId) => `${agent}:${accountId}`;
|
|
50
|
+
/** A session under this agent and account was just refused. */
|
|
51
|
+
export function noteRefusal(agent, accountId = MACHINE_ACCOUNT_ID) {
|
|
52
|
+
refusals.set(keyOf(agent, accountId), Date.now());
|
|
53
|
+
}
|
|
54
|
+
/** The sign-in worked again. Answers whether a refusal was being held. */
|
|
55
|
+
export function clearRefusal(agent, accountId = MACHINE_ACCOUNT_ID) {
|
|
56
|
+
return refusals.delete(keyOf(agent, accountId));
|
|
57
|
+
}
|
|
58
|
+
/** Is a refusal still being held against this agent and account? */
|
|
59
|
+
export function refusalActive(agent, accountId = MACHINE_ACCOUNT_ID) {
|
|
60
|
+
const key = keyOf(agent, accountId);
|
|
61
|
+
const at = refusals.get(key);
|
|
62
|
+
if (at === undefined)
|
|
63
|
+
return false;
|
|
64
|
+
if (Date.now() - at > AUTH_FAILURE_TTL_MS) {
|
|
65
|
+
refusals.delete(key);
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=login-marks.js.map
|
package/dist/protocol.d.ts
CHANGED
|
@@ -235,11 +235,11 @@ export declare const SessionDescriptorSchema: z.ZodObject<{
|
|
|
235
235
|
token: string;
|
|
236
236
|
}>>;
|
|
237
237
|
}, "strip", z.ZodTypeAny, {
|
|
238
|
-
mode: "
|
|
239
|
-
agent: "CLAUDE" | "CODEX";
|
|
240
|
-
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
238
|
+
mode: "plan" | "ask" | "auto" | "full";
|
|
241
239
|
id: string;
|
|
240
|
+
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
242
241
|
kind: "TICKET" | "CHAT";
|
|
242
|
+
agent: "CLAUDE" | "CODEX";
|
|
243
243
|
model: string | null;
|
|
244
244
|
effort: string | null;
|
|
245
245
|
prompt: string;
|
|
@@ -286,10 +286,10 @@ export declare const SessionDescriptorSchema: z.ZodObject<{
|
|
|
286
286
|
baseSha?: string | undefined;
|
|
287
287
|
} | undefined;
|
|
288
288
|
}, {
|
|
289
|
-
agent: "CLAUDE" | "CODEX";
|
|
290
|
-
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
291
289
|
id: string;
|
|
290
|
+
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
292
291
|
kind: "TICKET" | "CHAT";
|
|
292
|
+
agent: "CLAUDE" | "CODEX";
|
|
293
293
|
prompt: string;
|
|
294
294
|
providerSessionId: string | null;
|
|
295
295
|
workspace: {
|
|
@@ -316,7 +316,7 @@ export declare const SessionDescriptorSchema: z.ZodObject<{
|
|
|
316
316
|
url: string;
|
|
317
317
|
token: string;
|
|
318
318
|
} | undefined;
|
|
319
|
-
mode?: "
|
|
319
|
+
mode?: "plan" | "ask" | "auto" | "full" | undefined;
|
|
320
320
|
workMode?: unknown;
|
|
321
321
|
model?: string | null | undefined;
|
|
322
322
|
effort?: string | null | undefined;
|
|
@@ -385,8 +385,8 @@ export declare const QuestionAnswerArgsSchema: z.ZodObject<{
|
|
|
385
385
|
}>, "many">>;
|
|
386
386
|
readonly text: z.ZodOptional<z.ZodString>;
|
|
387
387
|
}, "strip", z.ZodTypeAny, {
|
|
388
|
-
askId: string;
|
|
389
388
|
action: "answer" | "discuss";
|
|
389
|
+
askId: string;
|
|
390
390
|
text?: string | undefined;
|
|
391
391
|
answers?: {
|
|
392
392
|
values: string[];
|
|
@@ -395,8 +395,8 @@ export declare const QuestionAnswerArgsSchema: z.ZodObject<{
|
|
|
395
395
|
notes?: string | undefined;
|
|
396
396
|
}[] | undefined;
|
|
397
397
|
}, {
|
|
398
|
-
askId: string;
|
|
399
398
|
action: "answer" | "discuss";
|
|
399
|
+
askId: string;
|
|
400
400
|
text?: string | undefined;
|
|
401
401
|
answers?: {
|
|
402
402
|
values: string[];
|
|
@@ -685,11 +685,11 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
685
685
|
token: string;
|
|
686
686
|
}>>;
|
|
687
687
|
}, "strip", z.ZodTypeAny, {
|
|
688
|
-
mode: "
|
|
689
|
-
agent: "CLAUDE" | "CODEX";
|
|
690
|
-
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
688
|
+
mode: "plan" | "ask" | "auto" | "full";
|
|
691
689
|
id: string;
|
|
690
|
+
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
692
691
|
kind: "TICKET" | "CHAT";
|
|
692
|
+
agent: "CLAUDE" | "CODEX";
|
|
693
693
|
model: string | null;
|
|
694
694
|
effort: string | null;
|
|
695
695
|
prompt: string;
|
|
@@ -736,10 +736,10 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
736
736
|
baseSha?: string | undefined;
|
|
737
737
|
} | undefined;
|
|
738
738
|
}, {
|
|
739
|
-
agent: "CLAUDE" | "CODEX";
|
|
740
|
-
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
741
739
|
id: string;
|
|
740
|
+
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
742
741
|
kind: "TICKET" | "CHAT";
|
|
742
|
+
agent: "CLAUDE" | "CODEX";
|
|
743
743
|
prompt: string;
|
|
744
744
|
providerSessionId: string | null;
|
|
745
745
|
workspace: {
|
|
@@ -766,7 +766,7 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
766
766
|
url: string;
|
|
767
767
|
token: string;
|
|
768
768
|
} | undefined;
|
|
769
|
-
mode?: "
|
|
769
|
+
mode?: "plan" | "ask" | "auto" | "full" | undefined;
|
|
770
770
|
workMode?: unknown;
|
|
771
771
|
model?: string | null | undefined;
|
|
772
772
|
effort?: string | null | undefined;
|
|
@@ -785,11 +785,11 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
785
785
|
}, "strip", z.ZodTypeAny, {
|
|
786
786
|
type: "hello_ack";
|
|
787
787
|
sessions: {
|
|
788
|
-
mode: "
|
|
789
|
-
agent: "CLAUDE" | "CODEX";
|
|
790
|
-
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
788
|
+
mode: "plan" | "ask" | "auto" | "full";
|
|
791
789
|
id: string;
|
|
790
|
+
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
792
791
|
kind: "TICKET" | "CHAT";
|
|
792
|
+
agent: "CLAUDE" | "CODEX";
|
|
793
793
|
model: string | null;
|
|
794
794
|
effort: string | null;
|
|
795
795
|
prompt: string;
|
|
@@ -842,10 +842,10 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
842
842
|
}, {
|
|
843
843
|
type: "hello_ack";
|
|
844
844
|
sessions: {
|
|
845
|
-
agent: "CLAUDE" | "CODEX";
|
|
846
|
-
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
847
845
|
id: string;
|
|
846
|
+
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
848
847
|
kind: "TICKET" | "CHAT";
|
|
848
|
+
agent: "CLAUDE" | "CODEX";
|
|
849
849
|
prompt: string;
|
|
850
850
|
providerSessionId: string | null;
|
|
851
851
|
workspace: {
|
|
@@ -872,7 +872,7 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
872
872
|
url: string;
|
|
873
873
|
token: string;
|
|
874
874
|
} | undefined;
|
|
875
|
-
mode?: "
|
|
875
|
+
mode?: "plan" | "ask" | "auto" | "full" | undefined;
|
|
876
876
|
workMode?: unknown;
|
|
877
877
|
model?: string | null | undefined;
|
|
878
878
|
effort?: string | null | undefined;
|
|
@@ -1154,11 +1154,11 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
1154
1154
|
token: string;
|
|
1155
1155
|
}>>;
|
|
1156
1156
|
}, "strip", z.ZodTypeAny, {
|
|
1157
|
-
mode: "
|
|
1158
|
-
agent: "CLAUDE" | "CODEX";
|
|
1159
|
-
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
1157
|
+
mode: "plan" | "ask" | "auto" | "full";
|
|
1160
1158
|
id: string;
|
|
1159
|
+
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
1161
1160
|
kind: "TICKET" | "CHAT";
|
|
1161
|
+
agent: "CLAUDE" | "CODEX";
|
|
1162
1162
|
model: string | null;
|
|
1163
1163
|
effort: string | null;
|
|
1164
1164
|
prompt: string;
|
|
@@ -1205,10 +1205,10 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
1205
1205
|
baseSha?: string | undefined;
|
|
1206
1206
|
} | undefined;
|
|
1207
1207
|
}, {
|
|
1208
|
-
agent: "CLAUDE" | "CODEX";
|
|
1209
|
-
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
1210
1208
|
id: string;
|
|
1209
|
+
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
1211
1210
|
kind: "TICKET" | "CHAT";
|
|
1211
|
+
agent: "CLAUDE" | "CODEX";
|
|
1212
1212
|
prompt: string;
|
|
1213
1213
|
providerSessionId: string | null;
|
|
1214
1214
|
workspace: {
|
|
@@ -1235,7 +1235,7 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
1235
1235
|
url: string;
|
|
1236
1236
|
token: string;
|
|
1237
1237
|
} | undefined;
|
|
1238
|
-
mode?: "
|
|
1238
|
+
mode?: "plan" | "ask" | "auto" | "full" | undefined;
|
|
1239
1239
|
workMode?: unknown;
|
|
1240
1240
|
model?: string | null | undefined;
|
|
1241
1241
|
effort?: string | null | undefined;
|
|
@@ -1253,11 +1253,11 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
1253
1253
|
}>;
|
|
1254
1254
|
}, "strip", z.ZodTypeAny, {
|
|
1255
1255
|
session: {
|
|
1256
|
-
mode: "
|
|
1257
|
-
agent: "CLAUDE" | "CODEX";
|
|
1258
|
-
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
1256
|
+
mode: "plan" | "ask" | "auto" | "full";
|
|
1259
1257
|
id: string;
|
|
1258
|
+
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
1260
1259
|
kind: "TICKET" | "CHAT";
|
|
1260
|
+
agent: "CLAUDE" | "CODEX";
|
|
1261
1261
|
model: string | null;
|
|
1262
1262
|
effort: string | null;
|
|
1263
1263
|
prompt: string;
|
|
@@ -1307,10 +1307,10 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
1307
1307
|
type: "session_start";
|
|
1308
1308
|
}, {
|
|
1309
1309
|
session: {
|
|
1310
|
-
agent: "CLAUDE" | "CODEX";
|
|
1311
|
-
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
1312
1310
|
id: string;
|
|
1311
|
+
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
1313
1312
|
kind: "TICKET" | "CHAT";
|
|
1313
|
+
agent: "CLAUDE" | "CODEX";
|
|
1314
1314
|
prompt: string;
|
|
1315
1315
|
providerSessionId: string | null;
|
|
1316
1316
|
workspace: {
|
|
@@ -1337,7 +1337,7 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
1337
1337
|
url: string;
|
|
1338
1338
|
token: string;
|
|
1339
1339
|
} | undefined;
|
|
1340
|
-
mode?: "
|
|
1340
|
+
mode?: "plan" | "ask" | "auto" | "full" | undefined;
|
|
1341
1341
|
workMode?: unknown;
|
|
1342
1342
|
model?: string | null | undefined;
|
|
1343
1343
|
effort?: string | null | undefined;
|
|
@@ -1440,8 +1440,8 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
1440
1440
|
}, "strip", z.ZodTypeAny, {
|
|
1441
1441
|
sessionId: string;
|
|
1442
1442
|
type: "question_answer";
|
|
1443
|
-
askId: string;
|
|
1444
1443
|
action: "answer" | "discuss";
|
|
1444
|
+
askId: string;
|
|
1445
1445
|
text?: string | undefined;
|
|
1446
1446
|
answers?: {
|
|
1447
1447
|
values: string[];
|
|
@@ -1452,8 +1452,8 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
1452
1452
|
}, {
|
|
1453
1453
|
sessionId: string;
|
|
1454
1454
|
type: "question_answer";
|
|
1455
|
-
askId: string;
|
|
1456
1455
|
action: "answer" | "discuss";
|
|
1456
|
+
askId: string;
|
|
1457
1457
|
text?: string | undefined;
|
|
1458
1458
|
answers?: {
|
|
1459
1459
|
values: string[];
|
|
@@ -1513,8 +1513,8 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
1513
1513
|
}, "strip", z.ZodTypeAny, {
|
|
1514
1514
|
type: "workspace_settings";
|
|
1515
1515
|
workspaceId: string;
|
|
1516
|
-
agentAutoCommit?: boolean | undefined;
|
|
1517
1516
|
trustMode?: "STRICT" | "NORMAL" | "AUTO" | undefined;
|
|
1517
|
+
agentAutoCommit?: boolean | undefined;
|
|
1518
1518
|
agentPushBan?: boolean | undefined;
|
|
1519
1519
|
agentProtectedBranches?: string[] | undefined;
|
|
1520
1520
|
agentAllowForcePush?: boolean | undefined;
|
|
@@ -1523,8 +1523,8 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
1523
1523
|
}, {
|
|
1524
1524
|
type: "workspace_settings";
|
|
1525
1525
|
workspaceId: string;
|
|
1526
|
-
agentAutoCommit?: boolean | undefined;
|
|
1527
1526
|
trustMode?: "STRICT" | "NORMAL" | "AUTO" | undefined;
|
|
1527
|
+
agentAutoCommit?: boolean | undefined;
|
|
1528
1528
|
agentPushBan?: boolean | undefined;
|
|
1529
1529
|
agentProtectedBranches?: string[] | undefined;
|
|
1530
1530
|
agentAllowForcePush?: boolean | undefined;
|
|
@@ -1539,13 +1539,13 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
1539
1539
|
}, "strip", z.ZodTypeAny, {
|
|
1540
1540
|
sessionId: string;
|
|
1541
1541
|
type: "session_settings";
|
|
1542
|
-
mode?: "
|
|
1542
|
+
mode?: "plan" | "ask" | "auto" | "full" | undefined;
|
|
1543
1543
|
model?: string | undefined;
|
|
1544
1544
|
effort?: string | null | undefined;
|
|
1545
1545
|
}, {
|
|
1546
1546
|
sessionId: string;
|
|
1547
1547
|
type: "session_settings";
|
|
1548
|
-
mode?: "
|
|
1548
|
+
mode?: "plan" | "ask" | "auto" | "full" | undefined;
|
|
1549
1549
|
model?: string | undefined;
|
|
1550
1550
|
effort?: string | null | undefined;
|
|
1551
1551
|
}>, z.ZodObject<{
|
package/dist/protocol.js
CHANGED
|
@@ -430,7 +430,9 @@ export const GatewayFrameSchema = z.discriminatedUnion('type', [
|
|
|
430
430
|
// git_branches, update_from_base, git_push, git_refs, workspace_state,
|
|
431
431
|
// recipe_state, verify_start, verify_status, verify_cancel,
|
|
432
432
|
// preview_checkout, preview_stop, propose_commit_message, git_stage,
|
|
433
|
-
// git_unstage, git_discard, git_pull, git_merge_abort, fs_publish
|
|
433
|
+
// git_unstage, git_discard, git_pull, git_merge_abort, fs_publish,
|
|
434
|
+
// agent_accounts, agent_account_login_start, agent_account_login_code,
|
|
435
|
+
// agent_account_activate, agent_account_forget (#422).
|
|
434
436
|
name: z.string().min(1).max(64),
|
|
435
437
|
workspaceId: z.string().optional(),
|
|
436
438
|
sessionId: z.string().optional(),
|
package/dist/supervisor.js
CHANGED
|
@@ -19,6 +19,7 @@ import { applySession, gitBranches, gitCommit, gitDiff, gitLog, gitPush, gitRefs
|
|
|
19
19
|
import { fsView } from './fsview.js';
|
|
20
20
|
import { publishFile } from './file-publish.js';
|
|
21
21
|
import { agentAuthStatuses, AuthRelay, clearAgentAuthFailure, noteAgentAuthFailure, } from './auth-relay.js';
|
|
22
|
+
import { isAccountCommand, runAccountCommand } from './account-commands.js';
|
|
22
23
|
import { isSupervisedProcess, selfUpdate } from './self-update.js';
|
|
23
24
|
import { installAgent } from './agent-install.js';
|
|
24
25
|
import { autoUpdateRefusal, claimAgentAutoUpdate } from './agent-auto-update.js';
|
|
@@ -2702,7 +2703,7 @@ export class Supervisor {
|
|
|
2702
2703
|
const { descriptor } = running;
|
|
2703
2704
|
try {
|
|
2704
2705
|
for await (const event of session.events) {
|
|
2705
|
-
this.forwardEvent(running, event);
|
|
2706
|
+
this.forwardEvent(running, event, session);
|
|
2706
2707
|
}
|
|
2707
2708
|
}
|
|
2708
2709
|
catch (error) {
|
|
@@ -3618,7 +3619,14 @@ export class Supervisor {
|
|
|
3618
3619
|
this.syncBudgetClock(running);
|
|
3619
3620
|
this.reportStatus(running.descriptor.id, 'RUNNING', {});
|
|
3620
3621
|
}
|
|
3621
|
-
forwardEvent(running, event
|
|
3622
|
+
forwardEvent(running, event,
|
|
3623
|
+
/**
|
|
3624
|
+
* The process this event came from (#422). A refusal and a working turn are
|
|
3625
|
+
* attributed to the account THAT process started under – read off the
|
|
3626
|
+
* session that produced the event, not off whatever holds the slot by the
|
|
3627
|
+
* time the event is handled.
|
|
3628
|
+
*/
|
|
3629
|
+
source = running.session) {
|
|
3622
3630
|
const { descriptor } = running;
|
|
3623
3631
|
// Ticket #225: ANY event is the process proving it came up — its own
|
|
3624
3632
|
// capabilities probe answers within about two seconds of a healthy launch,
|
|
@@ -3812,7 +3820,7 @@ export class Supervisor {
|
|
|
3812
3820
|
if (event.code === 'auth_expired') {
|
|
3813
3821
|
const refused = relayAgent(String(descriptor.agent).toLowerCase());
|
|
3814
3822
|
if (refused)
|
|
3815
|
-
noteAgentAuthFailure(refused);
|
|
3823
|
+
noteAgentAuthFailure(refused, source?.accountId);
|
|
3816
3824
|
}
|
|
3817
3825
|
// Only `auth_missing` is worth a relaunch, and the distinction is the
|
|
3818
3826
|
// adapter's own (`probeAuth`), not a guess from prose.
|
|
@@ -3917,7 +3925,7 @@ export class Supervisor {
|
|
|
3917
3925
|
if (event.role === 'assistant') {
|
|
3918
3926
|
const working = relayAgent(String(descriptor.agent).toLowerCase());
|
|
3919
3927
|
if (working)
|
|
3920
|
-
clearAgentAuthFailure(working);
|
|
3928
|
+
clearAgentAuthFailure(working, source?.accountId);
|
|
3921
3929
|
}
|
|
3922
3930
|
this.sendEvent(running, 'message', { role: event.role, text: event.text });
|
|
3923
3931
|
return;
|
|
@@ -7483,6 +7491,11 @@ export class Supervisor {
|
|
|
7483
7491
|
});
|
|
7484
7492
|
}
|
|
7485
7493
|
default:
|
|
7494
|
+
// #422: the five account commands – their own module, one door each
|
|
7495
|
+
// over `claude-homes.ts` (plan §8).
|
|
7496
|
+
if (isAccountCommand(frame.name)) {
|
|
7497
|
+
return void reply(await runAccountCommand(frame.name, frame.args ?? {}, this.authRelay));
|
|
7498
|
+
}
|
|
7486
7499
|
return void reply({ ok: false, error: `Unknown command` });
|
|
7487
7500
|
}
|
|
7488
7501
|
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const RUNNER_VERSION = "0.
|
|
1
|
+
export declare const RUNNER_VERSION = "0.67.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
package/package.json
CHANGED