instar 1.3.1286 → 1.3.1288
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/dashboard/index.html +14 -0
- package/dashboard/subscriptions.js +24 -5
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +55 -18
- package/dist/commands/server.js.map +1 -1
- package/dist/core/CliLoginStatus.d.ts +38 -0
- package/dist/core/CliLoginStatus.d.ts.map +1 -0
- package/dist/core/CliLoginStatus.js +116 -0
- package/dist/core/CliLoginStatus.js.map +1 -0
- package/dist/core/PostUpdateMigrator.d.ts +8 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +45 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/QuotaPoller.d.ts +42 -0
- package/dist/core/QuotaPoller.d.ts.map +1 -1
- package/dist/core/QuotaPoller.js +110 -11
- package/dist/core/QuotaPoller.js.map +1 -1
- package/dist/core/SessionManager.d.ts +13 -0
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +22 -6
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/SubscriptionLoginLedger.d.ts +1 -1
- package/dist/core/SubscriptionLoginLedger.d.ts.map +1 -1
- package/dist/core/SubscriptionLoginLedger.js +3 -0
- package/dist/core/SubscriptionLoginLedger.js.map +1 -1
- package/dist/core/SubscriptionReloginHelper.d.ts +119 -0
- package/dist/core/SubscriptionReloginHelper.d.ts.map +1 -0
- package/dist/core/SubscriptionReloginHelper.js +329 -0
- package/dist/core/SubscriptionReloginHelper.js.map +1 -0
- package/dist/core/SubscriptionReloginOrchestrator.d.ts +25 -2
- package/dist/core/SubscriptionReloginOrchestrator.d.ts.map +1 -1
- package/dist/core/SubscriptionReloginOrchestrator.js +58 -3
- package/dist/core/SubscriptionReloginOrchestrator.js.map +1 -1
- package/dist/core/SubscriptionReloginPolicy.d.ts +1 -1
- package/dist/core/SubscriptionReloginPolicy.d.ts.map +1 -1
- package/dist/core/SubscriptionReloginPolicy.js +1 -0
- package/dist/core/SubscriptionReloginPolicy.js.map +1 -1
- package/dist/core/SubscriptionReloginRuntime.d.ts +74 -4
- package/dist/core/SubscriptionReloginRuntime.d.ts.map +1 -1
- package/dist/core/SubscriptionReloginRuntime.js +163 -7
- package/dist/core/SubscriptionReloginRuntime.js.map +1 -1
- package/dist/core/SubscriptionReloginService.d.ts +17 -0
- package/dist/core/SubscriptionReloginService.d.ts.map +1 -1
- package/dist/core/SubscriptionReloginService.js +54 -4
- package/dist/core/SubscriptionReloginService.js.map +1 -1
- package/dist/core/SubscriptionReloginStore.d.ts +22 -2
- package/dist/core/SubscriptionReloginStore.d.ts.map +1 -1
- package/dist/core/SubscriptionReloginStore.js +82 -2
- package/dist/core/SubscriptionReloginStore.js.map +1 -1
- package/dist/core/types.d.ts +6 -3
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/data/builtinSkillContent.d.ts +1 -1
- package/dist/data/builtinSkillContent.d.ts.map +1 -1
- package/dist/data/builtinSkillContent.js +11 -0
- package/dist/data/builtinSkillContent.js.map +1 -1
- package/dist/data/standards-guard-index.json +1 -1
- package/dist/data/standards-guard-index.meta.json +2 -2
- package/dist/data/standards-registry.meta.json +1 -1
- package/dist/providers/adapters/openai-codex/observability/codexLiveRateLimitReader.d.ts +29 -0
- package/dist/providers/adapters/openai-codex/observability/codexLiveRateLimitReader.d.ts.map +1 -1
- package/dist/providers/adapters/openai-codex/observability/codexLiveRateLimitReader.js +37 -9
- package/dist/providers/adapters/openai-codex/observability/codexLiveRateLimitReader.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +1 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +3 -1
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/middleware.d.ts +2 -0
- package/dist/server/middleware.d.ts.map +1 -1
- package/dist/server/middleware.js +18 -0
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/routes.d.ts +5 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +58 -1
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +64 -64
- package/src/data/builtinSkillContent.ts +11 -0
- package/src/data/standards-guard-index.json +1 -1
- package/src/data/standards-guard-index.meta.json +2 -2
- package/src/data/standards-registry.meta.json +1 -1
- package/src/scaffold/templates.ts +1 -0
- package/upgrades/1.3.1288.md +58 -0
- package/upgrades/side-effects/skill-driven-signin-repair.md +197 -0
- package/upgrades/side-effects/subscriptions-provider-colors.md +44 -0
- package/upgrades/subscriptions-provider-colors.eli16.md +9 -0
package/dashboard/index.html
CHANGED
|
@@ -3720,6 +3720,20 @@
|
|
|
3720
3720
|
.sub-provider-heading { font-size:12px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
|
|
3721
3721
|
opacity:.6; margin:14px 0 8px; padding-bottom:6px; border-bottom:1px solid var(--border,#2a2a2a); }
|
|
3722
3722
|
.sub-provider-heading:first-child { margin-top:0; }
|
|
3723
|
+
/* Provider colors (operator request 2026-09-25): Claude and Codex are told apart
|
|
3724
|
+
at a glance — a colored band on each group heading and a colored edge on every
|
|
3725
|
+
account card and grid row. Claude = clay orange, Codex = blue. */
|
|
3726
|
+
.sub-prov-claude { --prov:#e07a4f; --prov-tint:rgba(224,122,79,.12); }
|
|
3727
|
+
.sub-prov-codex { --prov:#4f8ff0; --prov-tint:rgba(79,143,240,.12); }
|
|
3728
|
+
.sub-prov-other { --prov:#9ca3af; --prov-tint:rgba(156,163,175,.10); }
|
|
3729
|
+
.sub-provider-heading.sub-prov-claude, .sub-provider-heading.sub-prov-codex, .sub-provider-heading.sub-prov-other {
|
|
3730
|
+
opacity:1; color:var(--prov); font-size:15px; background:var(--prov-tint); border-bottom:none;
|
|
3731
|
+
border-left:6px solid var(--prov); border-radius:6px; padding:8px 12px; margin:20px 0 10px; }
|
|
3732
|
+
.sub-account.sub-prov-claude, .sub-account.sub-prov-codex, .sub-account.sub-prov-other { border-left:6px solid var(--prov); }
|
|
3733
|
+
.sub-matrix-group.sub-prov-claude, .sub-matrix-group.sub-prov-codex, .sub-matrix-group.sub-prov-other {
|
|
3734
|
+
color:var(--prov); background:var(--prov-tint); font-size:14px; opacity:1; border-left:6px solid var(--prov); padding:10px 12px; }
|
|
3735
|
+
.sub-matrix tr.sub-prov-claude > .sub-matrix-acct, .sub-matrix tr.sub-prov-codex > .sub-matrix-acct, .sub-matrix tr.sub-prov-other > .sub-matrix-acct {
|
|
3736
|
+
border-left:6px solid var(--prov); background:var(--prov-tint); }
|
|
3723
3737
|
.sub-account { border:1px solid var(--border,#2a2a2a); border-radius:10px; padding:14px 16px; margin-bottom:12px; }
|
|
3724
3738
|
.sub-account-inuse { border-color:#16a34a; box-shadow:0 0 0 1px #16a34a44; }
|
|
3725
3739
|
.sub-account-inuse-badge { font-size:11px; font-weight:600; color:#22c55e; margin-right:auto; }
|
|
@@ -282,6 +282,15 @@ export function quotaBar(doc, label, pct, resetIso, now = Date.now()) {
|
|
|
282
282
|
* pinned by a test, because "we grouped everything" would quietly add a redundant
|
|
283
283
|
* heading to the common case.
|
|
284
284
|
*/
|
|
285
|
+
/** CSS class that colors a provider's group at a glance (operator request 2026-09-25:
|
|
286
|
+
* Claude and Codex must be distinguishable without reading). Closed mapping, so a
|
|
287
|
+
* provider string never reaches a class name raw. */
|
|
288
|
+
export function providerClass(provider) {
|
|
289
|
+
if (provider === 'anthropic') return 'sub-prov-claude';
|
|
290
|
+
if (provider === 'openai') return 'sub-prov-codex';
|
|
291
|
+
return 'sub-prov-other';
|
|
292
|
+
}
|
|
293
|
+
|
|
285
294
|
export function groupAccountsByProvider(accounts) {
|
|
286
295
|
if (!Array.isArray(accounts)) return [];
|
|
287
296
|
const groups = new Map(); // provider key (raw) → accounts, in first-appearance order
|
|
@@ -298,7 +307,7 @@ export function groupAccountsByProvider(accounts) {
|
|
|
298
307
|
// else, so an unrecognised or hostile provider string cannot reach the DOM raw.
|
|
299
308
|
// An absent provider has no honest name, so say so rather than invent one.
|
|
300
309
|
const label = friendlyProvider(key) || 'Other';
|
|
301
|
-
out.push({ __providerHeading: label });
|
|
310
|
+
out.push({ __providerHeading: label, __providerKey: key });
|
|
302
311
|
}
|
|
303
312
|
for (const m of members) out.push(m);
|
|
304
313
|
}
|
|
@@ -322,11 +331,11 @@ export function renderAccounts(doc, target, accounts, now = Date.now(), inUseAcc
|
|
|
322
331
|
// accounts mixed together with only a small per-card meta line to tell them
|
|
323
332
|
// apart. The heading is what makes the split scannable.)
|
|
324
333
|
if (a && a.__providerHeading) {
|
|
325
|
-
target.appendChild(el(doc, 'div',
|
|
334
|
+
target.appendChild(el(doc, 'div', `sub-provider-heading ${providerClass(a.__providerKey)}`, a.__providerHeading));
|
|
326
335
|
continue;
|
|
327
336
|
}
|
|
328
337
|
const inUse = !!(inUseAccountId && a && a.id === inUseAccountId);
|
|
329
|
-
const card = el(doc, 'div', inUse ? 'sub-account sub-account-inuse' : 'sub-account');
|
|
338
|
+
const card = el(doc, 'div', `${inUse ? 'sub-account sub-account-inuse' : 'sub-account'} ${providerClass(a && a.provider)}`);
|
|
330
339
|
const head = el(doc, 'div', 'sub-account-head');
|
|
331
340
|
head.appendChild(el(doc, 'span', 'sub-account-nick', sanitizeForDisplay(a && a.nickname, 'label')));
|
|
332
341
|
if (inUse) head.appendChild(el(doc, 'span', 'sub-account-inuse-badge', '● In use now'));
|
|
@@ -924,7 +933,7 @@ export function renderAccountMatrix(doc, target, poolScope, pendingScope, transi
|
|
|
924
933
|
for (const entry of groupMatrixRowsByProvider(model.rows)) {
|
|
925
934
|
if (entry && entry.__providerHeading) {
|
|
926
935
|
const gtr = doc.createElement('tr');
|
|
927
|
-
const gth = el(doc, 'th',
|
|
936
|
+
const gth = el(doc, 'th', `sub-matrix-group ${providerClass(entry.__providerKey)}`, entry.__providerHeading);
|
|
928
937
|
// Span the account column + every machine column so the heading reads as a band
|
|
929
938
|
// across the grid rather than a stray cell.
|
|
930
939
|
gth.setAttribute('colspan', String(model.machines.length + 1));
|
|
@@ -934,7 +943,7 @@ export function renderAccountMatrix(doc, target, poolScope, pendingScope, transi
|
|
|
934
943
|
continue;
|
|
935
944
|
}
|
|
936
945
|
const row = entry.__row;
|
|
937
|
-
const tr = doc
|
|
946
|
+
const tr = el(doc, 'tr', providerClass(row && row.account && row.account.provider));
|
|
938
947
|
tr.appendChild(el(doc, 'th', 'sub-matrix-acct', sanitizeForDisplay(row.account.email, 'label')));
|
|
939
948
|
for (const c of row.cells) {
|
|
940
949
|
const repairCandidate = Array.isArray(reloginEpisodes)
|
|
@@ -971,6 +980,16 @@ export function renderAccountMatrix(doc, target, poolScope, pendingScope, transi
|
|
|
971
980
|
button.setAttribute('data-episode-id', sanitizeForDisplay(repair.id, 'label'));
|
|
972
981
|
td.appendChild(button);
|
|
973
982
|
}
|
|
983
|
+
// While a repair waits on the operator (a phone tap, a macOS Allow, no helper account), the
|
|
984
|
+
// operator can also finish the sign-in themselves from here — the same one-tap Sign in flow
|
|
985
|
+
// as a needs-reauth cell (spec skill-driven-signin-repair, operator contact).
|
|
986
|
+
if (repair.state === 'waiting-operator-only') {
|
|
987
|
+
const signIn = el(doc, 'button', 'sub-matrix-setup', 'Sign in');
|
|
988
|
+
signIn.setAttribute('data-matrix-setup', '1');
|
|
989
|
+
signIn.setAttribute('data-account-id', sanitizeForDisplay(c.accountId, 'label'));
|
|
990
|
+
signIn.setAttribute('data-machine-id', sanitizeForDisplay(c.machineId, 'label'));
|
|
991
|
+
td.appendChild(signIn);
|
|
992
|
+
}
|
|
974
993
|
} else if (c.state === 'empty' || c.state === 'needs-reauth' || c.state === 'held' || c.state === 'cant-resolve' || c.state === 'email-missing' || c.state === 'expired' || c.state === 'broken') {
|
|
975
994
|
// An actionable cell → a button that runs the SAME in-dashboard sign-in flow (PIN → link →
|
|
976
995
|
// paste code). empty → "Set up"; needs-reauth (an existing account whose login expired) →
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAsGA,OAAO,EAAE,cAAc,EAAwD,MAAM,2BAA2B,CAAC;AAUjH,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AA4BjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAmI7D,OAAO,KAAK,EAAW,oBAAoB,EAAe,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACjG,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAkFtD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC1C,OAAO,CAUT;AA0ID,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAoDD,+EAA+E;AAC/E,wBAAgB,qCAAqC,CACnD,SAAS,EAAE,IAAI,CAAC,OAAO,2BAA2B,EAAE,cAAc,EAAE,QAAQ,CAAC,GAAG,IAAI,EACpF,OAAO,EAAE,MAAM,GACd,IAAI,CAEN;AAsrDD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,YAAY,EACpB,YAAY,EAAE,oBAAoB,GAAG,IAAI,GACxC;IACD,YAAY,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB,CAqBA;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,eAAe,EACzB,cAAc,EAAE,cAAc,EAC9B,YAAY,CAAC,EAAE,YAAY,EAC3B,WAAW,CAAC,EAAE,WAAW,EACzB,WAAW,CAAC,EAAE,WAAW,EACzB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EAGvE,UAAU,CAAC,EAAE,MAAM,OAAO,8BAA8B,EAAE,WAAW,GAAG,IAAI,EAK5E,qBAAqB,CAAC,EAAE,MAAM,OAAO,gCAAgC,EAAE,kBAAkB,GAAG,IAAI,EAKhG,mBAAmB,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,EAQrD,oBAAoB,CAAC,EAAE,MAAM;IAC3B,YAAY,EAAE,OAAO,kBAAkB,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACrE,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,IAAI,GACP,IAAI,CA8yBN;AAgmBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/server.js
CHANGED
|
@@ -13442,12 +13442,21 @@ export async function startServer(options) {
|
|
|
13442
13442
|
// pool is non-empty (started below); on-demand polling is always available
|
|
13443
13443
|
// via POST /subscription-pool/poll.
|
|
13444
13444
|
const { QuotaPoller } = await import('../core/QuotaPoller.js');
|
|
13445
|
-
const { buildCodexLiveUsageReader } = await import('../providers/adapters/openai-codex/observability/codexLiveRateLimitReader.js');
|
|
13445
|
+
const { buildCodexLiveUsageReader, buildCodexLiveUsageReaderDetailed } = await import('../providers/adapters/openai-codex/observability/codexLiveRateLimitReader.js');
|
|
13446
|
+
// The Codex CLI's own login check (spec skill-driven-signin-repair), proven able to fail by
|
|
13447
|
+
// its canary before any "signed in" answer is trusted. Shared by the poller and the sign-in
|
|
13448
|
+
// repair's helper-seat pick.
|
|
13449
|
+
const { CodexLoginStatusChecker } = await import('../core/CliLoginStatus.js');
|
|
13450
|
+
const codexLoginStatusChecker = new CodexLoginStatusChecker();
|
|
13446
13451
|
const quotaPoller = new QuotaPoller({
|
|
13447
13452
|
pool: subscriptionPool,
|
|
13448
13453
|
// Zero-spend live codex quota (app-server account/rateLimits/read). ON by
|
|
13449
13454
|
// default; `subscriptionPool.codexLiveQuota: false` forces rollout-only.
|
|
13450
13455
|
codexLiveUsageReader: buildCodexLiveUsageReader(config.subscriptionPool),
|
|
13456
|
+
// The same live read with its failure KIND kept: an app-server "authentication required"
|
|
13457
|
+
// refusal is told apart from a transport failure, and only a live read proves login.
|
|
13458
|
+
codexLiveUsageReaderDetailed: buildCodexLiveUsageReaderDetailed(config.subscriptionPool),
|
|
13459
|
+
codexLoginStatus: (codexHome) => codexLoginStatusChecker.check(codexHome),
|
|
13451
13460
|
loginObservationSink: subscriptionLoginLedger
|
|
13452
13461
|
? (input) => subscriptionLoginLedger.recordObservation(input)
|
|
13453
13462
|
: undefined,
|
|
@@ -13857,7 +13866,7 @@ export async function startServer(options) {
|
|
|
13857
13866
|
const reloginCfg = config.subscriptionPool?.assistedRelogin;
|
|
13858
13867
|
if (reloginCfg?.enabled === true && subscriptionLoginLedger && subscriptionPoolMachineId && sharedIntelligence) {
|
|
13859
13868
|
try {
|
|
13860
|
-
const [{ createSubscriptionReloginRuntime, resolveReloginNavigation, takeFirstBackupCode }, { PlaywrightProfileRegistry }, { SecretStore }, { secretKeyPaths }, { ClaudePasteBackController }, { createReloginBrowser }] = await Promise.all([
|
|
13869
|
+
const [{ createSubscriptionReloginRuntime, resolveReloginNavigation, takeFirstBackupCode, buildReloginHelperSessionPorts }, { PlaywrightProfileRegistry }, { SecretStore }, { secretKeyPaths }, { ClaudePasteBackController }, { createReloginBrowser }] = await Promise.all([
|
|
13861
13870
|
import('../core/SubscriptionReloginRuntime.js'), import('../core/PlaywrightProfileRegistry.js'),
|
|
13862
13871
|
import('../core/SecretStore.js'), import('../core/SecretSync.js'),
|
|
13863
13872
|
import('../core/ClaudePasteBackController.js'), import('../core/PlainChromeReloginBrowser.js'),
|
|
@@ -13890,18 +13899,42 @@ export async function startServer(options) {
|
|
|
13890
13899
|
});
|
|
13891
13900
|
const notify = telegram ? async (episode, deliveryKey, kind) => {
|
|
13892
13901
|
const doorway = episode.framework === 'codex-cli' ? 'Codex' : 'Claude Code';
|
|
13902
|
+
// The dashboard's Subscriptions tab, where the operator can finish from a phone.
|
|
13903
|
+
let subscriptionsLink = `http://localhost:${config.port}/dashboard?tab=subscriptions`;
|
|
13904
|
+
try {
|
|
13905
|
+
if (tunnel?.url)
|
|
13906
|
+
subscriptionsLink = `${tunnel.url}/dashboard?tab=subscriptions`;
|
|
13907
|
+
}
|
|
13908
|
+
catch { /* @silent-fallback-ok — tunnel URL is best-effort; the local link still names the tab */ }
|
|
13909
|
+
// A helper-reported macOS permission rides the reason token `agent-permission-<name>`.
|
|
13910
|
+
const permissionReason = episode.failureClass === 'automation-permission'
|
|
13911
|
+
? (subscriptionReloginRuntime?.store.listEvents(episode.id, 5)
|
|
13912
|
+
.map((event) => event.reason ?? '').find((reason) => reason.startsWith('agent-permission-')) ?? null)
|
|
13913
|
+
: null;
|
|
13914
|
+
const permissionName = permissionReason === 'agent-permission-screen-recording' ? 'Screen Recording'
|
|
13915
|
+
: permissionReason === 'agent-permission-accessibility' ? 'Accessibility'
|
|
13916
|
+
: permissionReason === 'agent-permission-automation' ? 'Automation (control Google Chrome)' : null;
|
|
13893
13917
|
const summary = kind === 'approval'
|
|
13894
|
-
? `A ${doorway} subscription sign-in needs repair. Open Subscriptions and tap Repair sign-in once
|
|
13895
|
-
: kind === '
|
|
13896
|
-
?
|
|
13897
|
-
|
|
13898
|
-
|
|
13899
|
-
|
|
13900
|
-
|
|
13901
|
-
|
|
13918
|
+
? `A ${doorway} subscription sign-in needs repair. Open Subscriptions and tap Repair sign-in once: ${subscriptionsLink}`
|
|
13919
|
+
: kind === 'phone-tap'
|
|
13920
|
+
? `${doorway} sign-in repair is waiting on your phone: tap "Yes, it's me" on the Google prompt now. The helper continues on its own after that.`
|
|
13921
|
+
: kind === 'operator-only'
|
|
13922
|
+
? (episode.failureClass === 'no-healthy-seat'
|
|
13923
|
+
? `${doorway} sign-in repair has no other healthy account on this machine to run its helper. Finish the sign-in from your phone: open ${subscriptionsLink} and tap Sign in on that account.`
|
|
13924
|
+
: episode.failureClass === 'automation-permission' && permissionName
|
|
13925
|
+
? `${doorway} sign-in repair needs a one-time macOS permission on this machine: ${permissionName}. On that machine, click Allow if the prompt is showing, or turn it on in System Settings, Privacy & Security. Then open ${subscriptionsLink} and tap Try repair again, or tap Sign in to finish it yourself.`
|
|
13926
|
+
: episode.failureClass === 'automation-permission'
|
|
13927
|
+
? `${doorway} sign-in repair needs a one-time permission on this machine: allow the agent to control Google Chrome. On that machine, signed in as the Mac user the agent runs as, click Allow on the "control Google Chrome" prompt if one is showing, or turn it on in System Settings, Privacy & Security, Automation. Then open Subscriptions and tap Try repair again: ${subscriptionsLink}`
|
|
13928
|
+
: `Automated sign-in paused and needs you. Open ${subscriptionsLink} to continue, or tap Sign in to finish it from your phone.`)
|
|
13929
|
+
: episode.failureClass === 'resolved-elsewhere'
|
|
13930
|
+
? `${doorway} subscription is signed in again (verified), so its open sign-in repair was closed. Nothing to do.`
|
|
13931
|
+
: episode.state === 'succeeded'
|
|
13932
|
+
? `${doorway} subscription sign-in was repaired and verified.`
|
|
13933
|
+
: `${doorway} subscription repair ended in ${episode.state}. Open ${subscriptionsLink} for the redacted audit, or tap Sign in to finish it from your phone.`;
|
|
13902
13934
|
await telegram.createAttentionItem({ id: deliveryKey.replace(/:/g, '-'), title: `${doorway} sign-in repair`,
|
|
13903
13935
|
summary, description: summary, category: 'subscription-relogin',
|
|
13904
|
-
priority: kind === '
|
|
13936
|
+
priority: kind === 'phone-tap' ? 'URGENT'
|
|
13937
|
+
: kind === 'terminal' && (episode.state === 'succeeded' || episode.failureClass === 'resolved-elsewhere') ? 'NORMAL' : 'HIGH',
|
|
13905
13938
|
sourceContext: 'assisted-subscription-relogin' });
|
|
13906
13939
|
} : undefined;
|
|
13907
13940
|
subscriptionReloginRuntime = createSubscriptionReloginRuntime({ stateDir: config.stateDir,
|
|
@@ -13940,7 +13973,13 @@ export async function startServer(options) {
|
|
|
13940
13973
|
return action;
|
|
13941
13974
|
},
|
|
13942
13975
|
// Agent navigation (spec agent-driven-relogin): omitted ⇒ the development-agent gate.
|
|
13976
|
+
// `agent-session` (spec skill-driven-signin-repair) is macOS-only; omitted ⇒ agent-session
|
|
13977
|
+
// on a macOS development agent.
|
|
13943
13978
|
navigation: resolveReloginNavigation(reloginCfg.navigation, config),
|
|
13979
|
+
// A Codex repair can only be proven by a LIVE app-server read (spec skill-driven-signin-repair).
|
|
13980
|
+
codexLiveReadAvailable: config.subscriptionPool?.codexLiveQuota !== false,
|
|
13981
|
+
helperSession: buildReloginHelperSessionPorts({ sessionManager, maxSessions: config.sessions.maxSessions,
|
|
13982
|
+
serverPort: config.port, codexLoginStatus: (codexHome) => codexLoginStatusChecker.check(codexHome) }),
|
|
13944
13983
|
navigate: async (input) => {
|
|
13945
13984
|
const prompt = [
|
|
13946
13985
|
'You are signing an expired subscription account back in, in that account\'s own browser, the way a careful person would.',
|
|
@@ -13969,6 +14008,7 @@ export async function startServer(options) {
|
|
|
13969
14008
|
onSuggested: notify ? (episode, key) => notify(episode, key, 'approval') : undefined,
|
|
13970
14009
|
onOperatorOnly: notify ? (episode, key) => notify(episode, key, 'operator-only') : undefined,
|
|
13971
14010
|
onTerminal: notify ? (episode, key) => notify(episode, key, 'terminal') : undefined,
|
|
14011
|
+
onPhoneTap: notify ? (episode, key) => notify(episode, key, 'phone-tap') : undefined,
|
|
13972
14012
|
allowedScopes: reloginCfg.allowedScopes ?? [], tickMs: reloginCfg.tickMs,
|
|
13973
14013
|
maxAttempts: reloginCfg.maxAttempts, retryBaseMs: reloginCfg.retryBaseMs,
|
|
13974
14014
|
unattendedPolicy: reloginCfg.unattendedPolicy, });
|
|
@@ -26543,13 +26583,10 @@ export async function startServer(options) {
|
|
|
26543
26583
|
});
|
|
26544
26584
|
}
|
|
26545
26585
|
server.setSubscriptionLoginLedger(subscriptionLoginLedger);
|
|
26546
|
-
|
|
26547
|
-
|
|
26548
|
-
|
|
26549
|
-
|
|
26550
|
-
retry: (episodeId) => subscriptionReloginRuntime.service.retry(episodeId),
|
|
26551
|
-
close: () => subscriptionReloginRuntime.close(),
|
|
26552
|
-
} : null);
|
|
26586
|
+
{
|
|
26587
|
+
const { subscriptionReloginRouteContext } = await import('../core/SubscriptionReloginRuntime.js');
|
|
26588
|
+
server.setSubscriptionRelogin(subscriptionReloginRuntime ? subscriptionReloginRouteContext(subscriptionReloginRuntime) : null);
|
|
26589
|
+
}
|
|
26553
26590
|
server.setWorkQueue(workQueue);
|
|
26554
26591
|
if (_stateSyncStoresResolved?.classReview?.enabled && replicatedPeerStreamReader) {
|
|
26555
26592
|
const { CLASS_REVIEW_STORE_KEY, classReviewFromOriginRecord } = await import('../core/ClassReviewReplicatedStore.js');
|