flavor-code 1.2.15 → 1.2.16
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/{app-3KW2FTVJ.js → app-7ZCJ3UOI.js} +1 -1
- package/dist/auth/store.d.ts +7 -0
- package/dist/{chunk-5TG3E2EJ.js → chunk-5SRARNAC.js} +79 -5
- package/dist/{chunk-BKARQJQZ.js → chunk-PGS3M32Y.js} +1 -1
- package/dist/cli.js +3 -3
- package/dist/desktop/main.js +90 -6
- package/dist/desktop/preload.cjs +2 -0
- package/dist/desktop-renderer/assets/index-BmXr_vX3.js +151 -0
- package/dist/desktop-renderer/assets/{index-CPxt3vFY.css → index-DEL8gXBO.css} +1 -1
- package/dist/desktop-renderer/index.html +2 -2
- package/dist/sdk/index.js +2 -2
- package/dist/tools/shell.d.ts +11 -0
- package/dist/ui/commands.d.ts +1 -1
- package/dist/ui/session.d.ts +1 -0
- package/package.json +1 -1
- package/dist/desktop-renderer/assets/index-BCJjMvbX.js +0 -151
package/dist/auth/store.d.ts
CHANGED
|
@@ -12,4 +12,11 @@ export interface OAuthTokenStore {
|
|
|
12
12
|
load(): Promise<Record<string, StoredToken>>;
|
|
13
13
|
save(tokens: Record<string, StoredToken>): Promise<void>;
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Reduce the token store to a single credential. `/login` is a switch-to
|
|
17
|
+
* operation: keeping tokens from earlier services made the runtime pick the
|
|
18
|
+
* active provider by registration order, so the welcome card could show a
|
|
19
|
+
* stale service (e.g. a previous "Token Plan") instead of the one just logged in.
|
|
20
|
+
*/
|
|
21
|
+
export declare function retainOnlyCredentials(store: OAuthTokenStore, keepCredentialId: string): Promise<void>;
|
|
15
22
|
export declare function createFileTokenStore(filePath: string): OAuthTokenStore;
|
|
@@ -2900,6 +2900,7 @@ var MVP_COMMANDS = [
|
|
|
2900
2900
|
"init",
|
|
2901
2901
|
"config",
|
|
2902
2902
|
"login",
|
|
2903
|
+
"logout",
|
|
2903
2904
|
"permissions",
|
|
2904
2905
|
"skills",
|
|
2905
2906
|
"plugins",
|
|
@@ -2937,6 +2938,7 @@ var COMMAND_DESCRIPTIONS = {
|
|
|
2937
2938
|
init: "Initialize Flavor project files",
|
|
2938
2939
|
config: "Show the resolved configuration",
|
|
2939
2940
|
login: "Authenticate via OAuth PKCE",
|
|
2941
|
+
logout: "Clear stored OAuth credentials and restore configured models",
|
|
2940
2942
|
permissions: "Change the tool permission mode",
|
|
2941
2943
|
skills: "List discovered skills",
|
|
2942
2944
|
plugins: "List loaded plugins",
|
|
@@ -3214,6 +3216,7 @@ var HELP = [
|
|
|
3214
3216
|
"/model <main|subagent> <provider:model> switch any configured model",
|
|
3215
3217
|
"/permissions <default|acceptEdits|plan|bypassPermissions|auto|bubble>",
|
|
3216
3218
|
"/login authenticate via OAuth PKCE",
|
|
3219
|
+
"/logout clear stored OAuth credentials",
|
|
3217
3220
|
"/init /config /skills /plugins /hooks /tasks",
|
|
3218
3221
|
"/memory /remember [type] <text> /forget <text-or-id> /forget-cold /finish",
|
|
3219
3222
|
"/checkpoint [label] /tree /rewind <node> /unrevert /fork <node>",
|
|
@@ -3628,6 +3631,8 @@ var FlavorSession = class {
|
|
|
3628
3631
|
} else if (command.name === "login") {
|
|
3629
3632
|
this.#notice("Opening browser for authentication...");
|
|
3630
3633
|
this.#notice(await this.#services.login());
|
|
3634
|
+
} else if (command.name === "logout") {
|
|
3635
|
+
this.#notice(await this.#services.logout());
|
|
3631
3636
|
} else if (command.name === "help") this.#notice(HELP);
|
|
3632
3637
|
else if (command.name === "exit") this.#services.output({ type: "exit" });
|
|
3633
3638
|
}
|
|
@@ -10646,7 +10651,7 @@ import { readFile as readFile11 } from "fs/promises";
|
|
|
10646
10651
|
import { join as join16 } from "path";
|
|
10647
10652
|
|
|
10648
10653
|
// src/tools/shell.ts
|
|
10649
|
-
import { spawn as spawn6 } from "child_process";
|
|
10654
|
+
import { spawn as spawn6, spawnSync } from "child_process";
|
|
10650
10655
|
import { isAbsolute as isAbsolute6, relative as relative11, resolve as resolve13, sep as sep10 } from "path";
|
|
10651
10656
|
import { z as z16 } from "zod";
|
|
10652
10657
|
|
|
@@ -10776,6 +10781,29 @@ function tokenizeCommandLine(command) {
|
|
|
10776
10781
|
function unquoteToken(token) {
|
|
10777
10782
|
return token.length >= 2 && token.startsWith('"') && token.endsWith('"') ? token.slice(1, -1) : token;
|
|
10778
10783
|
}
|
|
10784
|
+
var cachedWindowsShell;
|
|
10785
|
+
function hasExecutable(name) {
|
|
10786
|
+
try {
|
|
10787
|
+
return spawnSync("where", [name], { stdio: "ignore", windowsHide: true }).status === 0;
|
|
10788
|
+
} catch {
|
|
10789
|
+
return false;
|
|
10790
|
+
}
|
|
10791
|
+
}
|
|
10792
|
+
function detectWindowsShell() {
|
|
10793
|
+
if (cachedWindowsShell !== void 0) return cachedWindowsShell;
|
|
10794
|
+
cachedWindowsShell = hasExecutable("pwsh") ? "pwsh" : hasExecutable("powershell") ? "powershell" : "cmd";
|
|
10795
|
+
return cachedWindowsShell;
|
|
10796
|
+
}
|
|
10797
|
+
function psQuote(token) {
|
|
10798
|
+
return `'${token.replace(/'/g, "''")}'`;
|
|
10799
|
+
}
|
|
10800
|
+
function buildWindowsCommandLine(kind, commandLine, command, args) {
|
|
10801
|
+
if (kind === "cmd") return `chcp 65001>nul & ${commandLine}`;
|
|
10802
|
+
const executable = kind === "pwsh" ? "pwsh" : "powershell";
|
|
10803
|
+
const script = `& ${psQuote(command)}${args.length > 0 ? ` ${args.map(psQuote).join(" ")}` : ""}; exit $LASTEXITCODE`;
|
|
10804
|
+
const encoded = Buffer.from(script, "utf16le").toString("base64");
|
|
10805
|
+
return `chcp 65001>nul & ${executable} -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -EncodedCommand ${encoded}`;
|
|
10806
|
+
}
|
|
10779
10807
|
function createShellTool(workspace, options = {}) {
|
|
10780
10808
|
const root = resolve13(workspace);
|
|
10781
10809
|
const maxBytes = options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES2;
|
|
@@ -10896,7 +10924,7 @@ async function executeShell(root, input, cancellation, maxBytes, onOutput) {
|
|
|
10896
10924
|
const quoteArg = (s) => s.includes(" ") ? `"${s.replace(/"/g, '""')}"` : s;
|
|
10897
10925
|
const quoted = input.args.map(quoteArg).join(" ");
|
|
10898
10926
|
const commandLine = quoted.length > 0 ? `${quoteArg(input.command)} ${quoted}` : quoteArg(input.command);
|
|
10899
|
-
const shellCommandLine = process.platform === "win32" ?
|
|
10927
|
+
const shellCommandLine = process.platform === "win32" ? buildWindowsCommandLine(detectWindowsShell(), commandLine, input.command, input.args) : commandLine;
|
|
10900
10928
|
const child = spawn6(shellCommandLine, {
|
|
10901
10929
|
cwd,
|
|
10902
10930
|
shell: true,
|
|
@@ -12435,6 +12463,11 @@ function escapeHtml(text) {
|
|
|
12435
12463
|
|
|
12436
12464
|
// src/auth/store.ts
|
|
12437
12465
|
import { dirname as dirname13 } from "path";
|
|
12466
|
+
async function retainOnlyCredentials(store, keepCredentialId) {
|
|
12467
|
+
const tokens = await store.load();
|
|
12468
|
+
const retained = Object.fromEntries(Object.entries(tokens).filter(([id]) => id === keepCredentialId));
|
|
12469
|
+
await store.save(retained);
|
|
12470
|
+
}
|
|
12438
12471
|
function createFileTokenStore(filePath) {
|
|
12439
12472
|
let baseline = {};
|
|
12440
12473
|
const store = {
|
|
@@ -19464,7 +19497,10 @@ async function createProductionRuntime(options) {
|
|
|
19464
19497
|
states: { ...taskStates },
|
|
19465
19498
|
results: { ...taskResults }
|
|
19466
19499
|
},
|
|
19467
|
-
|
|
19500
|
+
// Persist the resolved decision, not the harness snapshot: after logout the
|
|
19501
|
+
// harness may still hold the old login model, and resuming from that stale
|
|
19502
|
+
// value is what made the welcome card show a previous service.
|
|
19503
|
+
models: { main: mainModel, subagent: childModel },
|
|
19468
19504
|
permissionMode: harness.permissionMode,
|
|
19469
19505
|
memory: memoryLifecycle,
|
|
19470
19506
|
timeline: { version: 1, state: timelineState }
|
|
@@ -20105,8 +20141,8 @@ async function createProductionRuntime(options) {
|
|
|
20105
20141
|
const services = {
|
|
20106
20142
|
hooks,
|
|
20107
20143
|
workspace,
|
|
20108
|
-
mainModel: () =>
|
|
20109
|
-
subagentModel: () =>
|
|
20144
|
+
mainModel: () => mainModel,
|
|
20145
|
+
subagentModel: () => childModel,
|
|
20110
20146
|
llmServiceName: () => effectiveLlm?.serviceName,
|
|
20111
20147
|
permissionMode: () => harness.permissionMode,
|
|
20112
20148
|
...palServices === void 0 ? {} : { pals: palServices },
|
|
@@ -20180,6 +20216,8 @@ async function createProductionRuntime(options) {
|
|
|
20180
20216
|
}
|
|
20181
20217
|
}
|
|
20182
20218
|
harness.setModel(role, id);
|
|
20219
|
+
if (role === "main") mainModel = id;
|
|
20220
|
+
else childModel = id;
|
|
20183
20221
|
await persist();
|
|
20184
20222
|
},
|
|
20185
20223
|
setPermissionMode: async (mode) => {
|
|
@@ -20426,12 +20464,48 @@ ${renderMemoryDocument(entries)}`;
|
|
|
20426
20464
|
goalOrchestrator.setModels(mainModel, mainModel);
|
|
20427
20465
|
delete selectedModels.mainError;
|
|
20428
20466
|
delete selectedModels.childError;
|
|
20467
|
+
await retainOnlyCredentials(tokenStore, credentialId);
|
|
20429
20468
|
if (!secrets.includes(next.accessToken)) secrets.push(next.accessToken);
|
|
20430
20469
|
await persist();
|
|
20431
20470
|
return `Authenticated to "${next.serviceName}". Main model ${mainModel}; subagent ${childModel}; gateway ${next.baseURL}. Configuration is active now.`;
|
|
20432
20471
|
} catch (error) {
|
|
20433
20472
|
return `Login failed: ${message(error)}`;
|
|
20434
20473
|
}
|
|
20474
|
+
},
|
|
20475
|
+
async logout() {
|
|
20476
|
+
const tokenStore = createFileTokenStore(join22(home, ".flavor-code", "auth.json"));
|
|
20477
|
+
const tokens = await tokenStore.load();
|
|
20478
|
+
const hadCredentials = Object.keys(tokens).length > 0 || effectiveLlm !== void 0;
|
|
20479
|
+
if (!hadCredentials) {
|
|
20480
|
+
return "Not authenticated \u2014 no stored OAuth credentials to clear.";
|
|
20481
|
+
}
|
|
20482
|
+
for (let i = registeredProviders.length - 1; i >= 0; i -= 1) {
|
|
20483
|
+
const provider = registeredProviders[i];
|
|
20484
|
+
if (provider !== void 0 && provider.pkceManaged === true) {
|
|
20485
|
+
registry.unregister(provider.name);
|
|
20486
|
+
registeredProviders.splice(i, 1);
|
|
20487
|
+
}
|
|
20488
|
+
}
|
|
20489
|
+
if (effectiveLlm !== void 0) {
|
|
20490
|
+
registry.unregister(effectiveLlm.providerId);
|
|
20491
|
+
effectiveLlm = void 0;
|
|
20492
|
+
}
|
|
20493
|
+
await tokenStore.save({});
|
|
20494
|
+
const fallback = selectModels(config, registeredProviders, diagnostics);
|
|
20495
|
+
mainModel = fallback.main;
|
|
20496
|
+
childModel = fallback.child;
|
|
20497
|
+
if (fallback.mainError === void 0) delete selectedModels.mainError;
|
|
20498
|
+
else selectedModels.mainError = fallback.mainError;
|
|
20499
|
+
if (fallback.childError === void 0) delete selectedModels.childError;
|
|
20500
|
+
else selectedModels.childError = fallback.childError;
|
|
20501
|
+
if (fallback.mainError === void 0 && registry.has(safeProvider(mainModel)) && registry.has(safeProvider(childModel))) {
|
|
20502
|
+
harness.setModel("main", mainModel);
|
|
20503
|
+
harness.setModel("subagent", childModel);
|
|
20504
|
+
hallucinationGuard.setModel(childModel);
|
|
20505
|
+
goalOrchestrator.setModels(mainModel, mainModel);
|
|
20506
|
+
}
|
|
20507
|
+
await persist();
|
|
20508
|
+
return fallback.mainError === void 0 ? `Logged out. Cleared OAuth credentials. Main model ${mainModel}; subagent ${childModel}.` : `Logged out. Cleared OAuth credentials. ${fallback.mainError}`;
|
|
20435
20509
|
}
|
|
20436
20510
|
};
|
|
20437
20511
|
if (config.sleep) {
|
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createRequire } from "node:module"; const require = createRequire(impor
|
|
|
3
3
|
import {
|
|
4
4
|
FlavorRpcServer,
|
|
5
5
|
TraceRecorder
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-PGS3M32Y.js";
|
|
7
7
|
import {
|
|
8
8
|
staticTaskLines
|
|
9
9
|
} from "./chunk-KKIBYDJI.js";
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
packageVersion,
|
|
23
23
|
redactErrorText,
|
|
24
24
|
runPalBroker
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-5SRARNAC.js";
|
|
26
26
|
import {
|
|
27
27
|
McpServerConfigSchema,
|
|
28
28
|
McpServerNameSchema,
|
|
@@ -861,7 +861,7 @@ async function runInteractiveCli(props) {
|
|
|
861
861
|
const [{ render, AlternateScreen }, { createElement }, { App }] = await Promise.all([
|
|
862
862
|
import("./claude-ink-ORUA7GWG.js"),
|
|
863
863
|
import("react"),
|
|
864
|
-
import("./app-
|
|
864
|
+
import("./app-7ZCJ3UOI.js")
|
|
865
865
|
]);
|
|
866
866
|
const instance = await render(createElement(
|
|
867
867
|
AlternateScreen,
|
package/dist/desktop/main.js
CHANGED
|
@@ -505,6 +505,7 @@ var DESKTOP_CHANNELS = {
|
|
|
505
505
|
d2cRunQualityJudge: "desktop:d2c-run-quality-judge",
|
|
506
506
|
d2cResolveQualityIssue: "desktop:d2c-resolve-quality-issue",
|
|
507
507
|
d2cSetManualAcceptance: "desktop:d2c-set-manual-acceptance",
|
|
508
|
+
e2eGetDeliveryRun: "desktop:e2e-get-delivery-run",
|
|
508
509
|
event: "desktop:event"
|
|
509
510
|
};
|
|
510
511
|
|
|
@@ -11210,7 +11211,7 @@ import { readFile as readFile12 } from "fs/promises";
|
|
|
11210
11211
|
import { join as join17 } from "path";
|
|
11211
11212
|
|
|
11212
11213
|
// src/tools/shell.ts
|
|
11213
|
-
import { spawn as spawn3 } from "child_process";
|
|
11214
|
+
import { spawn as spawn3, spawnSync } from "child_process";
|
|
11214
11215
|
import { isAbsolute as isAbsolute8, relative as relative11, resolve as resolve13, sep as sep10 } from "path";
|
|
11215
11216
|
import { z as z21 } from "zod";
|
|
11216
11217
|
|
|
@@ -11340,6 +11341,29 @@ function tokenizeCommandLine(command) {
|
|
|
11340
11341
|
function unquoteToken(token) {
|
|
11341
11342
|
return token.length >= 2 && token.startsWith('"') && token.endsWith('"') ? token.slice(1, -1) : token;
|
|
11342
11343
|
}
|
|
11344
|
+
var cachedWindowsShell;
|
|
11345
|
+
function hasExecutable(name) {
|
|
11346
|
+
try {
|
|
11347
|
+
return spawnSync("where", [name], { stdio: "ignore", windowsHide: true }).status === 0;
|
|
11348
|
+
} catch {
|
|
11349
|
+
return false;
|
|
11350
|
+
}
|
|
11351
|
+
}
|
|
11352
|
+
function detectWindowsShell() {
|
|
11353
|
+
if (cachedWindowsShell !== void 0) return cachedWindowsShell;
|
|
11354
|
+
cachedWindowsShell = hasExecutable("pwsh") ? "pwsh" : hasExecutable("powershell") ? "powershell" : "cmd";
|
|
11355
|
+
return cachedWindowsShell;
|
|
11356
|
+
}
|
|
11357
|
+
function psQuote(token) {
|
|
11358
|
+
return `'${token.replace(/'/g, "''")}'`;
|
|
11359
|
+
}
|
|
11360
|
+
function buildWindowsCommandLine(kind, commandLine, command, args) {
|
|
11361
|
+
if (kind === "cmd") return `chcp 65001>nul & ${commandLine}`;
|
|
11362
|
+
const executable = kind === "pwsh" ? "pwsh" : "powershell";
|
|
11363
|
+
const script = `& ${psQuote(command)}${args.length > 0 ? ` ${args.map(psQuote).join(" ")}` : ""}; exit $LASTEXITCODE`;
|
|
11364
|
+
const encoded = Buffer.from(script, "utf16le").toString("base64");
|
|
11365
|
+
return `chcp 65001>nul & ${executable} -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -EncodedCommand ${encoded}`;
|
|
11366
|
+
}
|
|
11343
11367
|
function createShellTool(workspace, options = {}) {
|
|
11344
11368
|
const root = resolve13(workspace);
|
|
11345
11369
|
const maxBytes = options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES2;
|
|
@@ -11460,7 +11484,7 @@ async function executeShell(root, input, cancellation, maxBytes, onOutput) {
|
|
|
11460
11484
|
const quoteArg = (s) => s.includes(" ") ? `"${s.replace(/"/g, '""')}"` : s;
|
|
11461
11485
|
const quoted = input.args.map(quoteArg).join(" ");
|
|
11462
11486
|
const commandLine = quoted.length > 0 ? `${quoteArg(input.command)} ${quoted}` : quoteArg(input.command);
|
|
11463
|
-
const shellCommandLine = process.platform === "win32" ?
|
|
11487
|
+
const shellCommandLine = process.platform === "win32" ? buildWindowsCommandLine(detectWindowsShell(), commandLine, input.command, input.args) : commandLine;
|
|
11464
11488
|
const child = spawn3(shellCommandLine, {
|
|
11465
11489
|
cwd,
|
|
11466
11490
|
shell: true,
|
|
@@ -13090,6 +13114,11 @@ function escapeHtml(text) {
|
|
|
13090
13114
|
|
|
13091
13115
|
// src/auth/store.ts
|
|
13092
13116
|
import { dirname as dirname13 } from "path";
|
|
13117
|
+
async function retainOnlyCredentials(store, keepCredentialId) {
|
|
13118
|
+
const tokens2 = await store.load();
|
|
13119
|
+
const retained = Object.fromEntries(Object.entries(tokens2).filter(([id]) => id === keepCredentialId));
|
|
13120
|
+
await store.save(retained);
|
|
13121
|
+
}
|
|
13093
13122
|
function createFileTokenStore(filePath) {
|
|
13094
13123
|
let baseline = {};
|
|
13095
13124
|
const store = {
|
|
@@ -18789,6 +18818,7 @@ var MVP_COMMANDS = [
|
|
|
18789
18818
|
"init",
|
|
18790
18819
|
"config",
|
|
18791
18820
|
"login",
|
|
18821
|
+
"logout",
|
|
18792
18822
|
"permissions",
|
|
18793
18823
|
"skills",
|
|
18794
18824
|
"plugins",
|
|
@@ -19066,6 +19096,7 @@ var HELP = [
|
|
|
19066
19096
|
"/model <main|subagent> <provider:model> switch any configured model",
|
|
19067
19097
|
"/permissions <default|acceptEdits|plan|bypassPermissions|auto|bubble>",
|
|
19068
19098
|
"/login authenticate via OAuth PKCE",
|
|
19099
|
+
"/logout clear stored OAuth credentials",
|
|
19069
19100
|
"/init /config /skills /plugins /hooks /tasks",
|
|
19070
19101
|
"/memory /remember [type] <text> /forget <text-or-id> /forget-cold /finish",
|
|
19071
19102
|
"/checkpoint [label] /tree /rewind <node> /unrevert /fork <node>",
|
|
@@ -19480,6 +19511,8 @@ var FlavorSession = class {
|
|
|
19480
19511
|
} else if (command.name === "login") {
|
|
19481
19512
|
this.#notice("Opening browser for authentication...");
|
|
19482
19513
|
this.#notice(await this.#services.login());
|
|
19514
|
+
} else if (command.name === "logout") {
|
|
19515
|
+
this.#notice(await this.#services.logout());
|
|
19483
19516
|
} else if (command.name === "help") this.#notice(HELP);
|
|
19484
19517
|
else if (command.name === "exit") this.#services.output({ type: "exit" });
|
|
19485
19518
|
}
|
|
@@ -23167,7 +23200,10 @@ async function createProductionRuntime(options) {
|
|
|
23167
23200
|
states: { ...taskStates },
|
|
23168
23201
|
results: { ...taskResults }
|
|
23169
23202
|
},
|
|
23170
|
-
|
|
23203
|
+
// Persist the resolved decision, not the harness snapshot: after logout the
|
|
23204
|
+
// harness may still hold the old login model, and resuming from that stale
|
|
23205
|
+
// value is what made the welcome card show a previous service.
|
|
23206
|
+
models: { main: mainModel, subagent: childModel },
|
|
23171
23207
|
permissionMode: harness.permissionMode,
|
|
23172
23208
|
memory: memoryLifecycle,
|
|
23173
23209
|
timeline: { version: 1, state: timelineState }
|
|
@@ -23808,8 +23844,8 @@ async function createProductionRuntime(options) {
|
|
|
23808
23844
|
const services = {
|
|
23809
23845
|
hooks,
|
|
23810
23846
|
workspace,
|
|
23811
|
-
mainModel: () =>
|
|
23812
|
-
subagentModel: () =>
|
|
23847
|
+
mainModel: () => mainModel,
|
|
23848
|
+
subagentModel: () => childModel,
|
|
23813
23849
|
llmServiceName: () => effectiveLlm?.serviceName,
|
|
23814
23850
|
permissionMode: () => harness.permissionMode,
|
|
23815
23851
|
...palServices === void 0 ? {} : { pals: palServices },
|
|
@@ -23883,6 +23919,8 @@ async function createProductionRuntime(options) {
|
|
|
23883
23919
|
}
|
|
23884
23920
|
}
|
|
23885
23921
|
harness.setModel(role, id);
|
|
23922
|
+
if (role === "main") mainModel = id;
|
|
23923
|
+
else childModel = id;
|
|
23886
23924
|
await persist();
|
|
23887
23925
|
},
|
|
23888
23926
|
setPermissionMode: async (mode) => {
|
|
@@ -24129,12 +24167,48 @@ ${renderMemoryDocument(entries)}`;
|
|
|
24129
24167
|
goalOrchestrator.setModels(mainModel, mainModel);
|
|
24130
24168
|
delete selectedModels.mainError;
|
|
24131
24169
|
delete selectedModels.childError;
|
|
24170
|
+
await retainOnlyCredentials(tokenStore, credentialId);
|
|
24132
24171
|
if (!secrets.includes(next.accessToken)) secrets.push(next.accessToken);
|
|
24133
24172
|
await persist();
|
|
24134
24173
|
return `Authenticated to "${next.serviceName}". Main model ${mainModel}; subagent ${childModel}; gateway ${next.baseURL}. Configuration is active now.`;
|
|
24135
24174
|
} catch (error) {
|
|
24136
24175
|
return `Login failed: ${message(error)}`;
|
|
24137
24176
|
}
|
|
24177
|
+
},
|
|
24178
|
+
async logout() {
|
|
24179
|
+
const tokenStore = createFileTokenStore(join29(home, ".flavor-code", "auth.json"));
|
|
24180
|
+
const tokens2 = await tokenStore.load();
|
|
24181
|
+
const hadCredentials = Object.keys(tokens2).length > 0 || effectiveLlm !== void 0;
|
|
24182
|
+
if (!hadCredentials) {
|
|
24183
|
+
return "Not authenticated \u2014 no stored OAuth credentials to clear.";
|
|
24184
|
+
}
|
|
24185
|
+
for (let i = registeredProviders.length - 1; i >= 0; i -= 1) {
|
|
24186
|
+
const provider = registeredProviders[i];
|
|
24187
|
+
if (provider !== void 0 && provider.pkceManaged === true) {
|
|
24188
|
+
registry.unregister(provider.name);
|
|
24189
|
+
registeredProviders.splice(i, 1);
|
|
24190
|
+
}
|
|
24191
|
+
}
|
|
24192
|
+
if (effectiveLlm !== void 0) {
|
|
24193
|
+
registry.unregister(effectiveLlm.providerId);
|
|
24194
|
+
effectiveLlm = void 0;
|
|
24195
|
+
}
|
|
24196
|
+
await tokenStore.save({});
|
|
24197
|
+
const fallback = selectModels(config, registeredProviders, diagnostics);
|
|
24198
|
+
mainModel = fallback.main;
|
|
24199
|
+
childModel = fallback.child;
|
|
24200
|
+
if (fallback.mainError === void 0) delete selectedModels.mainError;
|
|
24201
|
+
else selectedModels.mainError = fallback.mainError;
|
|
24202
|
+
if (fallback.childError === void 0) delete selectedModels.childError;
|
|
24203
|
+
else selectedModels.childError = fallback.childError;
|
|
24204
|
+
if (fallback.mainError === void 0 && registry.has(safeProvider(mainModel)) && registry.has(safeProvider(childModel))) {
|
|
24205
|
+
harness.setModel("main", mainModel);
|
|
24206
|
+
harness.setModel("subagent", childModel);
|
|
24207
|
+
hallucinationGuard.setModel(childModel);
|
|
24208
|
+
goalOrchestrator.setModels(mainModel, mainModel);
|
|
24209
|
+
}
|
|
24210
|
+
await persist();
|
|
24211
|
+
return fallback.mainError === void 0 ? `Logged out. Cleared OAuth credentials. Main model ${mainModel}; subagent ${childModel}.` : `Logged out. Cleared OAuth credentials. ${fallback.mainError}`;
|
|
24138
24212
|
}
|
|
24139
24213
|
};
|
|
24140
24214
|
if (config.sleep) {
|
|
@@ -27738,11 +27812,12 @@ var DesktopRuntimeController = class {
|
|
|
27738
27812
|
].join("\n");
|
|
27739
27813
|
const delivery = await readDeliveryRun(workspace, task);
|
|
27740
27814
|
if (delivery?.nodes.api.status === "running") {
|
|
27815
|
+
const apiArtifacts = await Promise.all(generated.files.map(async (file) => artifactRef(file, await readFile33(join39(project, file)))));
|
|
27741
27816
|
const completed = await updateDeliveryRun(
|
|
27742
27817
|
workspace,
|
|
27743
27818
|
task,
|
|
27744
27819
|
delivery.revision,
|
|
27745
|
-
(run) => completeDeliveryNode(run, "api",
|
|
27820
|
+
(run) => completeDeliveryNode(run, "api", apiArtifacts)
|
|
27746
27821
|
);
|
|
27747
27822
|
await updateDeliveryRun(
|
|
27748
27823
|
workspace,
|
|
@@ -28018,6 +28093,12 @@ VITE_API_BASE_URL=${running.url}
|
|
|
28018
28093
|
});
|
|
28019
28094
|
return readD2cProductPlanView(workspace, task).then((view) => view);
|
|
28020
28095
|
}
|
|
28096
|
+
/** Read-only snapshot of the seven-node E2E delivery run; undefined when the task never started a delivery. */
|
|
28097
|
+
async getE2eDeliveryRun(task) {
|
|
28098
|
+
const workspace = this.#workspace;
|
|
28099
|
+
if (workspace === void 0) return void 0;
|
|
28100
|
+
return readDeliveryRun(workspace, task);
|
|
28101
|
+
}
|
|
28021
28102
|
async #assertProductPrdLocked(workspace, task) {
|
|
28022
28103
|
const current = await readD2cProductPlanView(workspace, task);
|
|
28023
28104
|
if (current?.plan.approvedPrd === void 0) return;
|
|
@@ -28742,6 +28823,9 @@ function installIpcHandlers() {
|
|
|
28742
28823
|
const input = D2cQualityIssueDecisionInputSchema.parse(value);
|
|
28743
28824
|
return controller.resolveD2cQualityIssue(input.task, input.issueId, input.decision);
|
|
28744
28825
|
});
|
|
28826
|
+
ipcMain.handle(DESKTOP_CHANNELS.e2eGetDeliveryRun, async (_event, value) => {
|
|
28827
|
+
return controller.getE2eDeliveryRun(D2cTaskActionInputSchema.parse(value).task);
|
|
28828
|
+
});
|
|
28745
28829
|
}
|
|
28746
28830
|
function applicationMenu() {
|
|
28747
28831
|
return Menu.buildFromTemplate([
|
package/dist/desktop/preload.cjs
CHANGED
|
@@ -65,6 +65,7 @@ var DESKTOP_CHANNELS = {
|
|
|
65
65
|
d2cRunQualityJudge: "desktop:d2c-run-quality-judge",
|
|
66
66
|
d2cResolveQualityIssue: "desktop:d2c-resolve-quality-issue",
|
|
67
67
|
d2cSetManualAcceptance: "desktop:d2c-set-manual-acceptance",
|
|
68
|
+
e2eGetDeliveryRun: "desktop:e2e-get-delivery-run",
|
|
68
69
|
event: "desktop:event"
|
|
69
70
|
};
|
|
70
71
|
|
|
@@ -158,6 +159,7 @@ var api = {
|
|
|
158
159
|
saveD2cJudgeConfig: (input) => import_electron.ipcRenderer.invoke(DESKTOP_CHANNELS.d2cSaveJudgeConfig, input),
|
|
159
160
|
runD2cQualityJudge: (task) => import_electron.ipcRenderer.invoke(DESKTOP_CHANNELS.d2cRunQualityJudge, { task }),
|
|
160
161
|
resolveD2cQualityIssue: (task, issueId, decision) => import_electron.ipcRenderer.invoke(DESKTOP_CHANNELS.d2cResolveQualityIssue, { task, issueId, decision }),
|
|
162
|
+
getE2eDeliveryRun: (task) => import_electron.ipcRenderer.invoke(DESKTOP_CHANNELS.e2eGetDeliveryRun, { task }),
|
|
161
163
|
onEvent(listener) {
|
|
162
164
|
const handler = (_event, value) => listener(value);
|
|
163
165
|
import_electron.ipcRenderer.on(DESKTOP_CHANNELS.event, handler);
|