@wrongstack/cli 1.0.6 → 1.0.8
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/{acp-GOQURNC2.js → acp-A5EQEXQO.js} +61 -6
- package/dist/{auth-WBXXIQUO.js → auth-3K6EN5JP.js} +3 -3
- package/dist/boot/container-wiring.d.ts +2 -0
- package/dist/{chunk-VUVOMXWP.js → chunk-3VXYY5JC.js} +8 -1
- package/dist/{chunk-NR7BD73C.js → chunk-4OLAZIIN.js} +2 -2
- package/dist/{chunk-5A5GCSJC.js → chunk-FSZ5QU3M.js} +2 -2
- package/dist/{chunk-KNMIBKLV.js → chunk-JY52HWL6.js} +47 -1
- package/dist/{chunk-QDQPF4PB.js → chunk-RLCKKLJA.js} +7 -7
- package/dist/{chunk-VPS2SJW4.js → chunk-RMQNCHGO.js} +5 -3
- package/dist/{chunk-PQZPHGGD.js → chunk-XIZZ2EXG.js} +34 -2
- package/dist/{cli-context-BYKJDAFF.js → cli-context-TIAP6YQK.js} +83 -12
- package/dist/cli-context.d.ts +2 -0
- package/dist/{cli-main-5WZBH3WA.js → cli-main-AKJHDSHX.js} +1006 -634
- package/dist/config-doctor.d.ts +1 -1
- package/dist/execute-deps.d.ts +3 -1
- package/dist/{execution-Z6A26EG6.js → execution-FJE27VQ6.js} +80 -3
- package/dist/{hq-V4PHEETW.js → hq-G5PCP325.js} +7 -5
- package/dist/hq-command-controller.d.ts +15 -0
- package/dist/{hq-server-MZ7DV6X7.js → hq-server-G3VVVMIG.js} +2 -2
- package/dist/index.js +3 -3
- package/dist/input-reader.d.ts +2 -2
- package/dist/{modeldiag-46CMWUNM.js → modeldiag-CJSFHZ3J.js} +55 -31
- package/dist/permission-prompt-mirror.d.ts +70 -0
- package/dist/permission-prompt.d.ts +10 -1
- package/dist/{providers-models-6MOGAOVK.js → providers-models-LFNZ5WI7.js} +2 -2
- package/dist/{short-circuit-flags-KBTYSJTW.js → short-circuit-flags-RAT6UZVI.js} +2 -2
- package/dist/slash-commands/subagent-models.d.ts +4 -0
- package/dist/subagent-models/panel-service.d.ts +28 -0
- package/dist/subcommands/handlers/modeldiag-test.d.ts +7 -0
- package/dist/{subcommands-DEYSYHIM.js → subcommands-VFVUTYAV.js} +2 -2
- package/dist/webui-server/prefs-seeding.d.ts +8 -0
- package/dist/{webui-server-OBV5JYJV.js → webui-server-3NYXBZHX.js} +36 -12
- package/dist/wiring/hq-telemetry.d.ts +7 -0
- package/package.json +28 -28
package/dist/config-doctor.d.ts
CHANGED
|
@@ -47,7 +47,7 @@ export interface PluginSchemaInfo {
|
|
|
47
47
|
* every theme change), and a phantom `agents` entry (that field is nested
|
|
48
48
|
* under `acp`, never top-level) waved a stray top-level `agents` block
|
|
49
49
|
* through. Add a field to `Config` and `tsc` now names it here. */
|
|
50
|
-
declare const KNOWN_TOP_LEVEL_KEYS: readonly ['version', 'activeProfile', 'provider', 'model', 'apiKey', 'baseUrl', 'maxConcurrent', 'uiLocale', 'themePreset', 'providers', 'models', 'modelMatrix', 'modelTiers', 'favoriteModels', 'favoriteModelsOnly', 'modelAvailabilitySchedule', 'context', 'tools', 'mcpServers', 'acp', 'fallbackModels', 'fallbackBridge', 'fallbackProfiles', 'fallbackProfile', 'fallbackAuto', 'fallbackMaxLastResortCandidates', 'fallbackStickiness', 'fallbackGateSeconds', 'hooks', 'plugins', 'pluginManager', 'log', 'features', 'Sage', 'skills', 'yolo', 'nextPrediction', 'cwd', 'autonomy', 'hints', 'debugStream', 'configScope', 'indexing', 'circuitBreaker', 'adaptiveConcurrency', 'launch', 'session', 'chronicle', 'modelRuntime', 'systemPrompt', 'hq', 'fleet', 'brain', 'sync', 'cloudSync', 'git', 'extensions'];
|
|
50
|
+
declare const KNOWN_TOP_LEVEL_KEYS: readonly ['version', 'activeProfile', 'provider', 'model', 'apiKey', 'baseUrl', 'maxConcurrent', 'uiLocale', 'themePreset', 'providers', 'models', 'modelMatrix', 'modelTiers', 'favoriteModels', 'disabledModels', 'favoriteModelsOnly', 'modelAvailabilitySchedule', 'context', 'tools', 'mcpServers', 'acp', 'fallbackModels', 'fallbackBridge', 'fallbackProfiles', 'fallbackProfile', 'fallbackAuto', 'fallbackMaxLastResortCandidates', 'fallbackStickiness', 'fallbackGateSeconds', 'hooks', 'plugins', 'pluginManager', 'log', 'features', 'Sage', 'skills', 'yolo', 'nextPrediction', 'cwd', 'autonomy', 'hints', 'debugStream', 'configScope', 'indexing', 'circuitBreaker', 'adaptiveConcurrency', 'launch', 'session', 'chronicle', 'modelRuntime', 'systemPrompt', 'hq', 'fleet', 'brain', 'sync', 'cloudSync', 'git', 'extensions'];
|
|
51
51
|
/** Compile-time `never` assertion: instantiating it with a non-empty union
|
|
52
52
|
* fails and the TS error text spells out the offending key names. */
|
|
53
53
|
type AssertNever<T extends never> = T;
|
package/dist/execute-deps.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ import type { BrainAutoRisk } from '@wrongstack/core/execution';
|
|
|
14
14
|
import type { JournalEntry } from '@wrongstack/core/goal';
|
|
15
15
|
import type { EventBus } from '@wrongstack/core/kernel';
|
|
16
16
|
import type { SlashCommandRegistry } from '@wrongstack/core/registry';
|
|
17
|
+
import type { StatuslineDensities, StatuslineLines } from '@wrongstack/core/statusline';
|
|
17
18
|
import type { QueueStore } from '@wrongstack/core/storage';
|
|
18
19
|
import type { AttachmentStore, AutonomyStage, Config, ConfigStore, MemoryPort, Message, ModelsRegistry, ModeStore, PromptLoader, ProviderConfig, ResolvedProvider, SessionEvent, SessionStore, SessionWriter, SkillLoader, TokenCounter } from '@wrongstack/core/types';
|
|
19
20
|
import type { WstackPaths } from '@wrongstack/core/utils';
|
|
@@ -25,7 +26,6 @@ import type { ReadlineInputReader } from './input-reader.js';
|
|
|
25
26
|
import type { LiveSettingsInput } from './live-settings-input.js';
|
|
26
27
|
import type { TerminalRenderer } from './renderer.js';
|
|
27
28
|
import type { AutonomyMode } from './services/autonomy-mode.js';
|
|
28
|
-
import type { StatuslineDensities, StatuslineLines } from '@wrongstack/core/statusline';
|
|
29
29
|
import type { StatuslineConfigKey } from './services/statusline-config.js';
|
|
30
30
|
import type { SessionStats } from './session-stats.js';
|
|
31
31
|
import type { UpdateInfo } from './update-check.js';
|
|
@@ -163,6 +163,8 @@ interface ProviderDeps {
|
|
|
163
163
|
tools?: boolean | undefined;
|
|
164
164
|
vision?: boolean | undefined;
|
|
165
165
|
reasoning?: boolean | undefined;
|
|
166
|
+
/** Documented reasoning-effort levels (drives the picker strip). */
|
|
167
|
+
effortLevels?: readonly string[] | undefined;
|
|
166
168
|
maxContext?: number | undefined;
|
|
167
169
|
maxOutput?: number | undefined;
|
|
168
170
|
inputCost?: number | undefined;
|
|
@@ -212,7 +212,7 @@ async function runWebUIDispatch(ctx) {
|
|
|
212
212
|
const isSimpleUi = !isSessionChild && flags["simpleui"] === true;
|
|
213
213
|
agent.disableInteractiveConfirmation();
|
|
214
214
|
renderer.setSilent(true);
|
|
215
|
-
const { runWebUI } = await import("./webui-server-
|
|
215
|
+
const { runWebUI } = await import("./webui-server-3NYXBZHX.js");
|
|
216
216
|
const flagValue = (names) => {
|
|
217
217
|
for (const name of names) {
|
|
218
218
|
if (!Object.hasOwn(flags, name)) continue;
|
|
@@ -1255,7 +1255,10 @@ async function onSDDOutput(output) {
|
|
|
1255
1255
|
|
|
1256
1256
|
// src/boot/tui-session-resume.ts
|
|
1257
1257
|
import * as path7 from "node:path";
|
|
1258
|
-
import {
|
|
1258
|
+
import {
|
|
1259
|
+
restoreSessionSubagentModelPlan,
|
|
1260
|
+
restoreSessionSubagentPolicy
|
|
1261
|
+
} from "@wrongstack/core/coordination";
|
|
1259
1262
|
import { attachTodosCheckpoint, loadTodosCheckpoint } from "@wrongstack/core/storage";
|
|
1260
1263
|
import { projectLastRequestTokens } from "@wrongstack/core/types/session-timeline";
|
|
1261
1264
|
import { sessionScopedPath as sessionScopedPath2, toErrorMessage } from "@wrongstack/core/utils";
|
|
@@ -1425,6 +1428,7 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1425
1428
|
try {
|
|
1426
1429
|
agent.ctx.state.replaceMessages(resumed.data.messages);
|
|
1427
1430
|
restoreSessionSubagentPolicy(agent.ctx, resumed.data.events, resumed.data.subagentsAllowed);
|
|
1431
|
+
restoreSessionSubagentModelPlan(agent.ctx, resumed.data.events);
|
|
1428
1432
|
} catch (err) {
|
|
1429
1433
|
agent.ctx.session = oldWriter;
|
|
1430
1434
|
agent.ctx.state.replaceMessages(oldMessages);
|
|
@@ -3203,6 +3207,75 @@ var FleetStatusLine = class {
|
|
|
3203
3207
|
}
|
|
3204
3208
|
};
|
|
3205
3209
|
|
|
3210
|
+
// src/subagent-models/panel-service.ts
|
|
3211
|
+
import {
|
|
3212
|
+
emptySubagentModelPlan,
|
|
3213
|
+
formatSubagentSlot,
|
|
3214
|
+
getSessionSubagentModelPlan,
|
|
3215
|
+
setSessionSubagentModelPlan,
|
|
3216
|
+
subagentSlotOccupancy
|
|
3217
|
+
} from "@wrongstack/core/coordination";
|
|
3218
|
+
function currentPlan(sessionId) {
|
|
3219
|
+
return getSessionSubagentModelPlan(sessionId) ?? emptySubagentModelPlan();
|
|
3220
|
+
}
|
|
3221
|
+
function createSubagentModelsPanelHost(deps) {
|
|
3222
|
+
const write = async (mutate) => {
|
|
3223
|
+
const ctx = deps.getContext();
|
|
3224
|
+
if (!ctx?.session) return "No active session \u2014 the plan cannot be saved.";
|
|
3225
|
+
const plan = structuredClone(currentPlan(ctx.session.id));
|
|
3226
|
+
mutate(plan);
|
|
3227
|
+
try {
|
|
3228
|
+
await setSessionSubagentModelPlan(ctx, plan);
|
|
3229
|
+
return null;
|
|
3230
|
+
} catch (err) {
|
|
3231
|
+
return err instanceof Error ? err.message : String(err);
|
|
3232
|
+
}
|
|
3233
|
+
};
|
|
3234
|
+
return {
|
|
3235
|
+
snapshot() {
|
|
3236
|
+
const sessionId = deps.getContext()?.session?.id;
|
|
3237
|
+
const plan = currentPlan(sessionId);
|
|
3238
|
+
const occupancy = subagentSlotOccupancy(sessionId);
|
|
3239
|
+
const session = deps.getSessionTarget?.();
|
|
3240
|
+
return {
|
|
3241
|
+
enabled: plan.enabled,
|
|
3242
|
+
lock: plan.lock,
|
|
3243
|
+
followSessionModel: plan.followSessionModel === true,
|
|
3244
|
+
sessionTarget: session?.provider ? `${session.provider}/${session.model ?? "?"}` : session?.model ?? "",
|
|
3245
|
+
lanes: plan.slots.map((slot, i) => ({
|
|
3246
|
+
target: formatSubagentSlot(slot),
|
|
3247
|
+
busy: occupancy[i]?.subagentIds.length ?? 0,
|
|
3248
|
+
...slot.label ? { label: slot.label } : {}
|
|
3249
|
+
})),
|
|
3250
|
+
roles: Object.entries(plan.roles ?? {}).map(([role, slot]) => ({ role, target: formatSubagentSlot(slot) })).sort((a, b) => a.role.localeCompare(b.role))
|
|
3251
|
+
};
|
|
3252
|
+
},
|
|
3253
|
+
setLane(index, target) {
|
|
3254
|
+
return write((plan) => {
|
|
3255
|
+
if (index < 0 || index >= plan.slots.length) return;
|
|
3256
|
+
const slot = {};
|
|
3257
|
+
if (target.provider) slot.provider = target.provider;
|
|
3258
|
+
if (target.model) slot.model = target.model;
|
|
3259
|
+
if (target.tier) slot.tier = target.tier;
|
|
3260
|
+
if (target.fallbackProfile) slot.fallbackProfile = target.fallbackProfile;
|
|
3261
|
+
if (target.label) slot.label = target.label;
|
|
3262
|
+
plan.slots[index] = slot;
|
|
3263
|
+
});
|
|
3264
|
+
},
|
|
3265
|
+
clearLane(index) {
|
|
3266
|
+
return write((plan) => {
|
|
3267
|
+
if (index < 0 || index >= plan.slots.length) return;
|
|
3268
|
+
plan.slots[index] = {};
|
|
3269
|
+
});
|
|
3270
|
+
},
|
|
3271
|
+
toggle(field) {
|
|
3272
|
+
return write((plan) => {
|
|
3273
|
+
plan[field] = plan[field] !== true;
|
|
3274
|
+
});
|
|
3275
|
+
}
|
|
3276
|
+
};
|
|
3277
|
+
}
|
|
3278
|
+
|
|
3206
3279
|
// src/chimera-work-registry.ts
|
|
3207
3280
|
function createChimeraWorkRegistry() {
|
|
3208
3281
|
const pending = /* @__PURE__ */ new Set();
|
|
@@ -6554,6 +6627,10 @@ async function execute(deps) {
|
|
|
6554
6627
|
getBrainData,
|
|
6555
6628
|
onBrainRiskLevel,
|
|
6556
6629
|
brainPanelHost: brainRuntime ? createBrainPanelHost({ brainRuntime }) : void 0,
|
|
6630
|
+
subagentModelsHost: createSubagentModelsPanelHost({
|
|
6631
|
+
getContext: () => agent.ctx,
|
|
6632
|
+
getSessionTarget: () => ({ provider: config.provider, model: config.model })
|
|
6633
|
+
}),
|
|
6557
6634
|
getShadowData,
|
|
6558
6635
|
onShadowStart,
|
|
6559
6636
|
onShadowStop,
|
|
@@ -6840,4 +6917,4 @@ export {
|
|
|
6840
6917
|
execute,
|
|
6841
6918
|
resolveReviewerFallbackModels
|
|
6842
6919
|
};
|
|
6843
|
-
//# sourceMappingURL=execution-
|
|
6920
|
+
//# sourceMappingURL=execution-FJE27VQ6.js.map
|
|
@@ -62,7 +62,7 @@ var hqCmd = async (args, deps) => {
|
|
|
62
62
|
return 1;
|
|
63
63
|
};
|
|
64
64
|
async function startServer(deps) {
|
|
65
|
-
const { startHqServer } = await import("./hq-server-
|
|
65
|
+
const { startHqServer } = await import("./hq-server-G3VVVMIG.js");
|
|
66
66
|
const dataDir = resolveDataDir(deps);
|
|
67
67
|
const flags = deps.flags ?? {};
|
|
68
68
|
const rawPublicUrl = typeof flags["hq-public-url"] === "string" ? flags["hq-public-url"] : process.env.WRONGSTACK_HQ_PUBLIC_URL;
|
|
@@ -357,7 +357,9 @@ async function computeAuditHashField(dataDir, warn) {
|
|
|
357
357
|
return hash !== void 0 ? { contentHash: hash } : {};
|
|
358
358
|
}
|
|
359
359
|
var TOKEN_CAPABILITIES = {
|
|
360
|
-
|
|
360
|
+
// `control.approve` is grantable but never default — see
|
|
361
|
+
// DEFAULT_TOKEN_CAPABILITIES below.
|
|
362
|
+
browser: ["control.enqueue", "control.approve"],
|
|
361
363
|
client: ["telemetry.publish", "control.execute"]
|
|
362
364
|
};
|
|
363
365
|
var DEFAULT_TOKEN_CAPABILITIES = {
|
|
@@ -727,7 +729,7 @@ function printHelp(deps) {
|
|
|
727
729
|
`
|
|
728
730
|
);
|
|
729
731
|
deps.renderer.write(
|
|
730
|
-
` --capabilities <csv> Token grants (browser: control.enqueue; client: telemetry.publish,control.execute).
|
|
732
|
+
` --capabilities <csv> Token grants (browser: control.enqueue,control.approve; client: telemetry.publish,control.execute).
|
|
731
733
|
`
|
|
732
734
|
);
|
|
733
735
|
deps.renderer.write(
|
|
@@ -785,7 +787,7 @@ function printTokenHelp(deps) {
|
|
|
785
787
|
`
|
|
786
788
|
);
|
|
787
789
|
deps.renderer.write(
|
|
788
|
-
` --capabilities <csv> Comma-separated capability grants (browser: control.enqueue; client: telemetry.publish,control.execute).
|
|
790
|
+
` --capabilities <csv> Comma-separated capability grants (browser: control.enqueue,control.approve; client: telemetry.publish,control.execute).
|
|
789
791
|
`
|
|
790
792
|
);
|
|
791
793
|
deps.renderer.write(
|
|
@@ -827,4 +829,4 @@ export {
|
|
|
827
829
|
hqCmd,
|
|
828
830
|
resolveAuditActor
|
|
829
831
|
};
|
|
830
|
-
//# sourceMappingURL=hq-
|
|
832
|
+
//# sourceMappingURL=hq-G5PCP325.js.map
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import type { RemoteMailbox } from '@wrongstack/core/coordination';
|
|
19
19
|
import type { HqPublisherCommandResult } from '@wrongstack/core/hq';
|
|
20
|
+
import type { UserInputResponse } from '@wrongstack/core/types';
|
|
20
21
|
/**
|
|
21
22
|
* Mutable holder for the command dispatch targets. Each field is populated
|
|
22
23
|
* lazily as the corresponding subsystem comes online (director on
|
|
@@ -68,6 +69,20 @@ export interface HqCommandController {
|
|
|
68
69
|
ownsSession?: ((sessionId: string) => boolean) | undefined;
|
|
69
70
|
/** Whether raw shell execution is explicitly opted-in by the operator. */
|
|
70
71
|
allowRunCommand: () => boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Answer a permission prompt that is live on this host.
|
|
74
|
+
*
|
|
75
|
+
* Returns false when the prompt is no longer pending — it was answered at
|
|
76
|
+
* the keyboard, aborted, or timed out. HQ mirrors prompts rather than owning
|
|
77
|
+
* them, so losing the race is the normal case and must be reported back
|
|
78
|
+
* instead of silently swallowed.
|
|
79
|
+
*
|
|
80
|
+
* Bound to the process-wide approval registry
|
|
81
|
+
* (`createApprovalRegistry` in `@wrongstack/core/hq`), which is the only
|
|
82
|
+
* holder of the resolver closures.
|
|
83
|
+
*/
|
|
84
|
+
resolveApproval?: ((toolUseId: string, decision: 'yes' | 'no' | 'always' | 'deny', sessionId?: string | undefined) => boolean) | undefined;
|
|
85
|
+
resolveUserInput?: ((requestId: string, response: UserInputResponse, sessionId?: string | undefined) => boolean) | undefined;
|
|
71
86
|
/** Apply a lifecycle transition through the project's Kanban IPC client. */
|
|
72
87
|
kanbanTransition?: ((input: {
|
|
73
88
|
boardId: string;
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
readLocalSubagentTranscript,
|
|
11
11
|
sanitizeApiError,
|
|
12
12
|
startHqServer
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-XIZZ2EXG.js";
|
|
14
14
|
import "./chunk-HXJYHAR4.js";
|
|
15
15
|
import "./chunk-5EA6OTLJ.js";
|
|
16
16
|
import "./chunk-Q7E3BPDU.js";
|
|
@@ -27,4 +27,4 @@ export {
|
|
|
27
27
|
sanitizeApiError,
|
|
28
28
|
startHqServer
|
|
29
29
|
};
|
|
30
|
-
//# sourceMappingURL=hq-server-
|
|
30
|
+
//# sourceMappingURL=hq-server-G3VVVMIG.js.map
|
package/dist/index.js
CHANGED
|
@@ -16,14 +16,14 @@ async function main(argv) {
|
|
|
16
16
|
applySessionShellDefault();
|
|
17
17
|
const earlyFlags = parseArgs(argv).flags;
|
|
18
18
|
if (earlyFlags["help"] === true || earlyFlags["version"] === true) {
|
|
19
|
-
const { handleHelpVersionShortCircuit } = await import("./short-circuit-flags-
|
|
19
|
+
const { handleHelpVersionShortCircuit } = await import("./short-circuit-flags-RAT6UZVI.js");
|
|
20
20
|
const earlyExit = await handleHelpVersionShortCircuit(argv);
|
|
21
21
|
if (earlyExit !== null) return earlyExit;
|
|
22
22
|
}
|
|
23
|
-
const { initializeCli } = await import("./cli-context-
|
|
23
|
+
const { initializeCli } = await import("./cli-context-TIAP6YQK.js");
|
|
24
24
|
const cliCtx = await initializeCli(argv);
|
|
25
25
|
if (typeof cliCtx === "number") return cliCtx;
|
|
26
|
-
const { runInteractive } = await import("./cli-main-
|
|
26
|
+
const { runInteractive } = await import("./cli-main-AKJHDSHX.js");
|
|
27
27
|
return runInteractive(cliCtx);
|
|
28
28
|
}
|
|
29
29
|
|
package/dist/input-reader.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { InputReader, PromptOption } from '@wrongstack/core/types';
|
|
1
|
+
import type { InputReader, PromptOption, ReadKeyOptions } from '@wrongstack/core/types';
|
|
2
2
|
interface ReadlineInputReaderOptions {
|
|
3
3
|
historyFile?: string | undefined;
|
|
4
4
|
prompt?: string | undefined;
|
|
@@ -30,7 +30,7 @@ export declare class ReadlineInputReader implements InputReader {
|
|
|
30
30
|
* protect and the ANSI clear/repaint would be noise in a file.
|
|
31
31
|
*/
|
|
32
32
|
private installPromptGuard;
|
|
33
|
-
readKey(prompt: string, options: PromptOption[]): Promise<string>;
|
|
33
|
+
readKey(prompt: string, options: PromptOption[], opts?: ReadKeyOptions): Promise<string>;
|
|
34
34
|
/**
|
|
35
35
|
* Read a line of input while masking each character with a bullet so the
|
|
36
36
|
* user gets visual confirmation that bytes are arriving (especially on
|
|
@@ -52,6 +52,17 @@ var MODEL_PROFILES = [
|
|
|
52
52
|
costTier: "premium",
|
|
53
53
|
speedTier: "normal"
|
|
54
54
|
},
|
|
55
|
+
{
|
|
56
|
+
provider: "openai",
|
|
57
|
+
// Must precede /gpt-4/ — every gpt-4o-mini id also contains gpt-4.
|
|
58
|
+
pattern: /gpt-4o-mini/i,
|
|
59
|
+
family: "GPT-4o Mini",
|
|
60
|
+
strengths: ["speed"],
|
|
61
|
+
bestFor: ["lightweight", "docs"],
|
|
62
|
+
avoidFor: ["planning"],
|
|
63
|
+
costTier: "budget",
|
|
64
|
+
speedTier: "fast"
|
|
65
|
+
},
|
|
55
66
|
{
|
|
56
67
|
provider: "openai",
|
|
57
68
|
pattern: /gpt-4/i,
|
|
@@ -62,9 +73,11 @@ var MODEL_PROFILES = [
|
|
|
62
73
|
speedTier: "fast"
|
|
63
74
|
},
|
|
64
75
|
{
|
|
65
|
-
provider: "
|
|
66
|
-
|
|
67
|
-
|
|
76
|
+
provider: "google",
|
|
77
|
+
// Must precede /gemini-(?:2\.5|3)/ — flash variants (gemini-2.5-flash,
|
|
78
|
+
// gemini-3-flash, …) are budget/fast models and need this profile.
|
|
79
|
+
pattern: /gemini.*flash/i,
|
|
80
|
+
family: "Gemini Flash",
|
|
68
81
|
strengths: ["speed"],
|
|
69
82
|
bestFor: ["lightweight", "docs"],
|
|
70
83
|
avoidFor: ["planning"],
|
|
@@ -80,16 +93,6 @@ var MODEL_PROFILES = [
|
|
|
80
93
|
costTier: "standard",
|
|
81
94
|
speedTier: "normal"
|
|
82
95
|
},
|
|
83
|
-
{
|
|
84
|
-
provider: "google",
|
|
85
|
-
pattern: /gemini.*flash/i,
|
|
86
|
-
family: "Gemini Flash",
|
|
87
|
-
strengths: ["speed"],
|
|
88
|
-
bestFor: ["lightweight", "docs"],
|
|
89
|
-
avoidFor: ["planning"],
|
|
90
|
-
costTier: "budget",
|
|
91
|
-
speedTier: "fast"
|
|
92
|
-
},
|
|
93
96
|
{
|
|
94
97
|
provider: "deepseek",
|
|
95
98
|
pattern: /deepseek/i,
|
|
@@ -685,7 +688,11 @@ async function runModeldiagBench(args, deps, providers, config, hasKey) {
|
|
|
685
688
|
|
|
686
689
|
// src/subcommands/handlers/modeldiag-test.ts
|
|
687
690
|
import { color as color4, toErrorMessage as toErrorMessage3 } from "@wrongstack/core/utils";
|
|
688
|
-
import {
|
|
691
|
+
import {
|
|
692
|
+
buildProviderFactoriesFromRegistry,
|
|
693
|
+
makeProviderFromConfig as makeProviderFromConfig2,
|
|
694
|
+
setOAuthTokenPersister
|
|
695
|
+
} from "@wrongstack/providers";
|
|
689
696
|
|
|
690
697
|
// src/subcommands/handlers/model-smoke-test.ts
|
|
691
698
|
import { ProviderError } from "@wrongstack/core/types";
|
|
@@ -876,6 +883,28 @@ async function runModelSmokeTests(params) {
|
|
|
876
883
|
}
|
|
877
884
|
|
|
878
885
|
// src/subcommands/handlers/modeldiag-test.ts
|
|
886
|
+
async function createModelDiagSmokeProvider(params) {
|
|
887
|
+
const { providerId, config, modelsRegistry, providerFactories } = params;
|
|
888
|
+
const saved = config.providers?.[providerId];
|
|
889
|
+
const factoryType = saved?.type ?? providerId;
|
|
890
|
+
const resolved = await modelsRegistry.getProvider(providerId).catch(() => void 0) ?? (factoryType !== providerId ? await modelsRegistry.getProvider(factoryType).catch(() => void 0) : void 0);
|
|
891
|
+
const providerConfig = {
|
|
892
|
+
...providerId === config.provider ? {
|
|
893
|
+
...config.apiKey ? { apiKey: config.apiKey } : {},
|
|
894
|
+
...config.baseUrl ? { baseUrl: config.baseUrl } : {}
|
|
895
|
+
} : {},
|
|
896
|
+
...saved,
|
|
897
|
+
// Keep the user-visible alias on the factory input. The selected factory
|
|
898
|
+
// already captures the canonical models.dev provider and its per-model
|
|
899
|
+
// wire metadata.
|
|
900
|
+
type: providerId,
|
|
901
|
+
...saved?.family ?? resolved?.family ? { family: saved?.family ?? resolved?.family } : {},
|
|
902
|
+
...saved?.baseUrl ?? resolved?.apiBase ? { baseUrl: saved?.baseUrl ?? resolved?.apiBase } : {},
|
|
903
|
+
...saved?.envVars ?? resolved?.envVars ? { envVars: saved?.envVars ?? resolved?.envVars } : {}
|
|
904
|
+
};
|
|
905
|
+
const factory = providerFactories.get(factoryType);
|
|
906
|
+
return factory ? factory.create(providerConfig) : makeProviderFromConfig2(providerId, providerConfig);
|
|
907
|
+
}
|
|
879
908
|
async function runModeldiagTest(args, deps, config) {
|
|
880
909
|
const writeLine = (line = "") => {
|
|
881
910
|
deps.renderer.write(`${line}
|
|
@@ -1010,25 +1039,20 @@ async function runModeldiagTest(args, deps, config) {
|
|
|
1010
1039
|
});
|
|
1011
1040
|
let results;
|
|
1012
1041
|
try {
|
|
1042
|
+
const providerFactories = new Map(
|
|
1043
|
+
(await buildProviderFactoriesFromRegistry({ registry: deps.modelsRegistry })).map(
|
|
1044
|
+
(factory) => [factory.type, factory]
|
|
1045
|
+
)
|
|
1046
|
+
);
|
|
1013
1047
|
results = await runModelSmokeTests({
|
|
1014
1048
|
targets,
|
|
1015
1049
|
options: smokeOptions,
|
|
1016
|
-
createProvider:
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
...config.baseUrl ? { baseUrl: config.baseUrl } : {}
|
|
1023
|
-
} : {},
|
|
1024
|
-
...saved,
|
|
1025
|
-
type: providerId,
|
|
1026
|
-
...saved?.family ?? resolved?.family ? { family: saved?.family ?? resolved?.family } : {},
|
|
1027
|
-
...saved?.baseUrl ?? resolved?.apiBase ? { baseUrl: saved?.baseUrl ?? resolved?.apiBase } : {},
|
|
1028
|
-
...saved?.envVars ?? resolved?.envVars ? { envVars: saved?.envVars ?? resolved?.envVars } : {}
|
|
1029
|
-
};
|
|
1030
|
-
return makeProviderFromConfig2(providerId, providerConfig);
|
|
1031
|
-
},
|
|
1050
|
+
createProvider: (providerId) => createModelDiagSmokeProvider({
|
|
1051
|
+
providerId,
|
|
1052
|
+
config,
|
|
1053
|
+
modelsRegistry: deps.modelsRegistry,
|
|
1054
|
+
providerFactories
|
|
1055
|
+
}),
|
|
1032
1056
|
onTargetComplete: resultLines
|
|
1033
1057
|
});
|
|
1034
1058
|
} finally {
|
|
@@ -1329,4 +1353,4 @@ var modeldiagCmd = async (args, deps) => {
|
|
|
1329
1353
|
export {
|
|
1330
1354
|
modeldiagCmd
|
|
1331
1355
|
};
|
|
1332
|
-
//# sourceMappingURL=modeldiag-
|
|
1356
|
+
//# sourceMappingURL=modeldiag-CJSFHZ3J.js.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mirror the plain REPL's permission prompt to HQ.
|
|
3
|
+
*
|
|
4
|
+
* Every other surface converges on the executor's confirm path, so one
|
|
5
|
+
* listener on the EventBus mirrors them all. The REPL does not: its prompt is
|
|
6
|
+
* asked by the permission policy's own `promptDelegate` inside `evaluate()`,
|
|
7
|
+
* which never reaches that path and raises no event. Without this wrapper the
|
|
8
|
+
* REPL is the one surface whose approvals are invisible from HQ — a partial
|
|
9
|
+
* guarantee that is worse than either a whole one or none, because an operator
|
|
10
|
+
* cannot tell which kind of session they are looking at.
|
|
11
|
+
*
|
|
12
|
+
* Two things make this honest rather than a hack:
|
|
13
|
+
*
|
|
14
|
+
* - **The terminal read is cancellable.** When HQ answers first, the pending
|
|
15
|
+
* `readKey` is aborted so stdin comes out of raw mode and the user's next
|
|
16
|
+
* keystroke is not eaten by a question nobody is asking.
|
|
17
|
+
* - **The mirrored card has a heartbeat, not a fake deadline.** A terminal
|
|
18
|
+
* prompt waits for a keypress however long that takes, so it has no natural
|
|
19
|
+
* deadline to publish — but a card with no deadline breaks the single
|
|
20
|
+
* invariant the dashboard relies on ("pending cannot outlive its
|
|
21
|
+
* deadline"), and a card with a fake one vanishes while the question is
|
|
22
|
+
* still on screen. Renewing a short window on a timer keeps both true.
|
|
23
|
+
*
|
|
24
|
+
* The terminal prompt's own behaviour is deliberately unchanged: it still
|
|
25
|
+
* blocks until answered, with no timeout of its own.
|
|
26
|
+
*
|
|
27
|
+
* @module permission-prompt-mirror
|
|
28
|
+
*/
|
|
29
|
+
import type { ApprovalRegistry } from '@wrongstack/core/hq';
|
|
30
|
+
import type { Tool } from '@wrongstack/core/types';
|
|
31
|
+
type PromptDecision = 'yes' | 'no' | 'always' | 'deny';
|
|
32
|
+
type PromptDelegate = (tool: Tool, input: unknown, suggestedPattern: string) => Promise<PromptDecision>;
|
|
33
|
+
type AbortablePromptDelegate = (tool: Tool, input: unknown, suggestedPattern: string, signal: AbortSignal) => Promise<PromptDecision>;
|
|
34
|
+
/**
|
|
35
|
+
* How long a mirrored REPL card stays pending without a renewal, and how often
|
|
36
|
+
* it is renewed. The gap between them is the worst-case time a card outlives
|
|
37
|
+
* the process that raised it — a laptop that sleeps mid-prompt should not park
|
|
38
|
+
* a permanent card on someone's dashboard.
|
|
39
|
+
*/
|
|
40
|
+
export declare const REPL_MIRROR_TTL_MS = 60000;
|
|
41
|
+
export declare const REPL_MIRROR_HEARTBEAT_MS = 20000;
|
|
42
|
+
export interface MirroredPromptDelegateDeps {
|
|
43
|
+
/** The real terminal prompt. Must honour the abort signal it is handed. */
|
|
44
|
+
inner: AbortablePromptDelegate;
|
|
45
|
+
/**
|
|
46
|
+
* Looked up per call, not captured: the registry is created during boot and
|
|
47
|
+
* this delegate is built before it exists. Returning undefined simply means
|
|
48
|
+
* no mirroring — the terminal prompt still works.
|
|
49
|
+
*/
|
|
50
|
+
getRegistry: () => ApprovalRegistry | undefined;
|
|
51
|
+
/** The session the prompt belongs to, so an HQ answer lands on it. */
|
|
52
|
+
getSessionId?: (() => string | undefined) | undefined;
|
|
53
|
+
now?: (() => number) | undefined;
|
|
54
|
+
}
|
|
55
|
+
export declare function makeMirroredPromptDelegate(deps: MirroredPromptDelegateDeps): PromptDelegate;
|
|
56
|
+
/**
|
|
57
|
+
* Late-bound handle to the approval registry.
|
|
58
|
+
*
|
|
59
|
+
* The prompt delegate is built during container wiring; the registry is
|
|
60
|
+
* created later, once the HQ telemetry layer comes up. Rather than reorder
|
|
61
|
+
* boot for a feature that is optional by nature, the delegate reads through
|
|
62
|
+
* this holder at call time — a prompt only ever fires long after both exist.
|
|
63
|
+
* Empty simply means no mirroring.
|
|
64
|
+
*/
|
|
65
|
+
export interface ApprovalMirrorRef {
|
|
66
|
+
current?: ApprovalRegistry | undefined;
|
|
67
|
+
sessionId?: (() => string | undefined) | undefined;
|
|
68
|
+
}
|
|
69
|
+
export {};
|
|
70
|
+
//# sourceMappingURL=permission-prompt-mirror.d.ts.map
|
|
@@ -2,7 +2,16 @@ import type { InputReader, Tool } from '@wrongstack/core/types';
|
|
|
2
2
|
type PromptDecision = 'yes' | 'no' | 'always' | 'deny';
|
|
3
3
|
/** Signature the Agent expects for confirming tool calls. */
|
|
4
4
|
export type ConfirmAwaiter = (tool: Tool, input: unknown, toolUseId: string, suggestedPattern: string) => Promise<'yes' | 'no' | 'always' | 'deny'>;
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* The terminal approval prompt.
|
|
7
|
+
*
|
|
8
|
+
* `signal` exists because the same question can now be answered somewhere else
|
|
9
|
+
* — from the HQ dashboard — while this prompt is on screen. Aborting takes it
|
|
10
|
+
* down and, crucially, gets stdin back out of raw mode; see
|
|
11
|
+
* `permission-prompt-mirror.ts`. Absent, behaviour is exactly as before: the
|
|
12
|
+
* prompt blocks until a key is pressed.
|
|
13
|
+
*/
|
|
14
|
+
export declare function makePromptDelegate(reader: InputReader): (tool: Tool, input: unknown, suggestedPattern: string, signal?: AbortSignal) => Promise<PromptDecision>;
|
|
6
15
|
/**
|
|
7
16
|
* Create a ConfirmAwaiter for the CLI path. Wraps makePromptDelegate
|
|
8
17
|
* with the ConfirmAwaiter type signature expected by the Agent.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
visibleModelIds
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-3VXYY5JC.js";
|
|
4
4
|
import {
|
|
5
5
|
activeProfileConfigPath
|
|
6
6
|
} from "./chunk-YMXXOOFN.js";
|
|
@@ -660,4 +660,4 @@ export {
|
|
|
660
660
|
modelsCmd,
|
|
661
661
|
providersCmd
|
|
662
662
|
};
|
|
663
|
-
//# sourceMappingURL=providers-models-
|
|
663
|
+
//# sourceMappingURL=providers-models-LFNZ5WI7.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
handleHelpVersionShortCircuit
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4OLAZIIN.js";
|
|
4
4
|
import "./chunk-6WRKAACA.js";
|
|
5
5
|
import "./chunk-XJXDOF63.js";
|
|
6
6
|
import "./chunk-EK2P53GL.js";
|
|
7
7
|
export {
|
|
8
8
|
handleHelpVersionShortCircuit
|
|
9
9
|
};
|
|
10
|
-
//# sourceMappingURL=short-circuit-flags-
|
|
10
|
+
//# sourceMappingURL=short-circuit-flags-RAT6UZVI.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host bridge for the TUI `/subagent-models` panel.
|
|
3
|
+
*
|
|
4
|
+
* The panel is presentational; the session-scoped plan lives in core and is
|
|
5
|
+
* journaled through the session writer, which only the CLI has. Mutations
|
|
6
|
+
* return an error STRING rather than throwing so a rejected write lands as a
|
|
7
|
+
* panel hint instead of unmounting the TUI.
|
|
8
|
+
*/
|
|
9
|
+
import { setSessionSubagentModelPlan } from '@wrongstack/core/coordination';
|
|
10
|
+
import type { SubagentModelsPanelHost } from '@wrongstack/tui';
|
|
11
|
+
/** The slice of the agent context the plan writer needs. */
|
|
12
|
+
type PlanWriteContext = Parameters<typeof setSessionSubagentModelPlan>[0];
|
|
13
|
+
export interface SubagentModelsPanelServiceDeps {
|
|
14
|
+
/** The session's own provider/model — the target of "use session model". */
|
|
15
|
+
getSessionTarget?: (() => {
|
|
16
|
+
provider?: string;
|
|
17
|
+
model?: string;
|
|
18
|
+
}) | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* Live agent context — re-read on every call so a session swap (F1/F10,
|
|
21
|
+
* /resume) is picked up. Typed off the core writer contract rather than the
|
|
22
|
+
* full AgentContext so this bridge only depends on what it actually uses.
|
|
23
|
+
*/
|
|
24
|
+
getContext: () => PlanWriteContext | undefined;
|
|
25
|
+
}
|
|
26
|
+
export declare function createSubagentModelsPanelHost(deps: SubagentModelsPanelServiceDeps): SubagentModelsPanelHost;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=panel-service.d.ts.map
|
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module subcommands/handlers/modeldiag-test
|
|
5
5
|
*/
|
|
6
|
+
import type { Config, ModelsRegistry, Provider, ProviderFactory } from '@wrongstack/core/types';
|
|
6
7
|
import type { SubcommandDeps } from '../contracts.js';
|
|
8
|
+
export declare function createModelDiagSmokeProvider(params: {
|
|
9
|
+
providerId: string;
|
|
10
|
+
config: Config;
|
|
11
|
+
modelsRegistry: ModelsRegistry;
|
|
12
|
+
providerFactories: ReadonlyMap<string, ProviderFactory>;
|
|
13
|
+
}): Promise<Provider>;
|
|
7
14
|
export declare function runModeldiagTest(args: string[], deps: SubcommandDeps, config: Record<string, unknown>): Promise<number>;
|
|
8
15
|
//# sourceMappingURL=modeldiag-test.d.ts.map
|
|
@@ -10,9 +10,17 @@ interface CliWebUIOptions {
|
|
|
10
10
|
globalConfigPath?: string | undefined;
|
|
11
11
|
profileConfigPath: string;
|
|
12
12
|
appConfig?: {
|
|
13
|
+
/**
|
|
14
|
+
* The live default selection. Carried here so a model switch can move
|
|
15
|
+
* it in-process, not just in config.json — `session.new` reads the
|
|
16
|
+
* live object to stamp a new tab.
|
|
17
|
+
*/
|
|
18
|
+
provider?: string | undefined;
|
|
19
|
+
model?: string | undefined;
|
|
13
20
|
fallbackModels?: string[] | undefined;
|
|
14
21
|
fallbackProfiles?: Record<string, string[]> | undefined;
|
|
15
22
|
favoriteModels?: string[] | undefined;
|
|
23
|
+
disabledModels?: string[] | undefined;
|
|
16
24
|
favoriteModelsOnly?: boolean | undefined;
|
|
17
25
|
modelAvailabilitySchedule?: ModelBlackoutRule[] | undefined;
|
|
18
26
|
fallbackAuto?: boolean | undefined;
|