@adhdev/daemon-core 0.9.82-rc.483 → 0.9.82-rc.484
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/commands/cli-manager.d.ts +20 -0
- package/dist/config/mesh-config.d.ts +14 -1
- package/dist/index.js +305 -17
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +305 -17
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-events-pending.d.ts +12 -0
- package/dist/mesh/mesh-runtime-store.d.ts +14 -0
- package/dist/mesh/mesh-work-queue.d.ts +17 -0
- package/dist/providers/cli-provider-instance.d.ts +14 -0
- package/dist/providers/contracts.d.ts +47 -0
- package/dist/repo-mesh-types.d.ts +10 -1
- package/dist/shared-types.d.ts +4 -0
- package/package.json +3 -3
- package/src/commands/cli-manager.ts +64 -3
- package/src/commands/med-family/mesh-crud.ts +24 -0
- package/src/config/mesh-config.ts +30 -1
- package/src/mesh/coordinator-prompt.ts +36 -0
- package/src/mesh/mesh-events-pending.ts +35 -1
- package/src/mesh/mesh-queue-assignment.ts +46 -4
- package/src/mesh/mesh-reconcile-loop.ts +69 -1
- package/src/mesh/mesh-runtime-store.ts +22 -0
- package/src/mesh/mesh-work-queue.ts +36 -3
- package/src/providers/cli-provider-instance.ts +46 -0
- package/src/providers/contracts.ts +47 -0
- package/src/providers/provider-schema.ts +6 -0
- package/src/providers/sdk/v1/schemas/cli/provider.schema.json +29 -0
- package/src/repo-mesh-types.ts +10 -1
- package/src/shared-types.ts +4 -0
- package/src/status/snapshot.ts +4 -0
|
@@ -80,6 +80,10 @@ type CliStartOptions = {
|
|
|
80
80
|
resumeSessionId?: string;
|
|
81
81
|
settingsOverride?: Record<string, any>;
|
|
82
82
|
extraEnv?: Record<string, string>;
|
|
83
|
+
/** BRAIN-ROUTING thinking axis: standard level ('low'|'medium'|'high') applied
|
|
84
|
+
* at launch via the provider's thinkingLaunchArgs (CLI) or setConfigOption
|
|
85
|
+
* ('thought_level', ACP). Best-effort — ignored by providers with no support. */
|
|
86
|
+
initialThinkingLevel?: string;
|
|
83
87
|
};
|
|
84
88
|
export interface CoordinatorDelegatedCliLaunchOptionsInput {
|
|
85
89
|
cliType: string;
|
|
@@ -111,6 +115,22 @@ export interface CoordinatorDelegatedCliLaunchOptions {
|
|
|
111
115
|
*/
|
|
112
116
|
export declare function resolveHostedSpawnedAtMs(attachExisting: boolean, attachStartedAtMs: number | undefined, nowMs: number): number;
|
|
113
117
|
export declare function buildCoordinatorDelegatedCliLaunchOptions(input: CoordinatorDelegatedCliLaunchOptionsInput): CoordinatorDelegatedCliLaunchOptions;
|
|
118
|
+
/**
|
|
119
|
+
* Expand a provider's `modelLaunchArgs` template with the requested model, mirroring
|
|
120
|
+
* expandResumeArgs. `{{model}}` → the trimmed model string. Returns undefined when
|
|
121
|
+
* there is no template or no model (a model request without a template is a no-op —
|
|
122
|
+
* see startSession, where the caller logs the skip). MAGI kind-panel model axis.
|
|
123
|
+
*/
|
|
124
|
+
export declare function expandModelLaunchArgs(template: string[] | undefined, model: string | undefined): string[] | undefined;
|
|
125
|
+
/**
|
|
126
|
+
* Expand a provider's `thinkingLaunchArgs` template with the requested thinking
|
|
127
|
+
* level, parallel to expandModelLaunchArgs. The standard level ('low'|'medium'|
|
|
128
|
+
* 'high') is first mapped through the provider's `thinkingLevelMap` (a level absent
|
|
129
|
+
* from the map passes through unchanged), then substituted into every `{{level}}`
|
|
130
|
+
* token. Returns undefined when there is no template or no level (best-effort; a
|
|
131
|
+
* thinking request without a template is a no-op). BRAIN-ROUTING thinking axis.
|
|
132
|
+
*/
|
|
133
|
+
export declare function expandThinkingLaunchArgs(template: string[] | undefined, level: string | undefined, levelMap: Partial<Record<string, string>> | undefined): string[] | undefined;
|
|
114
134
|
export declare function supportsExplicitSessionResume(resume?: ProviderResumeCapability): boolean;
|
|
115
135
|
export declare function resolveCliSessionBinding(provider: ProviderModule | undefined, normalizedType: string, cliArgs?: string[], requestedResumeSessionId?: string): CliSessionBinding;
|
|
116
136
|
export declare class DaemonCliManager {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* uses this file as the single source of truth.
|
|
7
7
|
*/
|
|
8
8
|
import type { LocalMeshEntry, LocalMeshNodeEntry, RepoMeshPolicy, RepoMeshNodePolicy, RepoMeshNodeCapabilities, RepoMeshCoordinatorConfig, RepoMeshHostMetadata, RepoMeshDaemonRole } from '../repo-mesh-types.js';
|
|
9
|
-
import type { MagiKindPanelMap, MagiSlot } from '@adhdev/mesh-shared';
|
|
9
|
+
import type { MagiKindPanelMap, MagiSlot, DifficultyBrainMap } from '@adhdev/mesh-shared';
|
|
10
10
|
/**
|
|
11
11
|
* Normalize a Git remote URL into a stable identity string.
|
|
12
12
|
* e.g. "git@github.com:user/repo.git" → "github.com/user/repo"
|
|
@@ -166,3 +166,16 @@ export declare function getMagiKindPanel(kind: string): MagiSlot[] | undefined;
|
|
|
166
166
|
export declare function setMagiKindPanel(kind: string, slots: unknown): MagiSlot[];
|
|
167
167
|
/** Remove the binding for one task_kind. Returns true when a binding was removed. */
|
|
168
168
|
export declare function removeMagiKindPanel(kind: string): boolean;
|
|
169
|
+
/**
|
|
170
|
+
* The difficulty→brain presets, machine-local. When nothing is configured yet,
|
|
171
|
+
* returns the sensible DEFAULT_DIFFICULTY_BRAINS so the coordinator always has a
|
|
172
|
+
* usable mapping (the operator can override via setDifficultyBrains). Returns a
|
|
173
|
+
* normalized copy — never the stored reference.
|
|
174
|
+
*/
|
|
175
|
+
export declare function getDifficultyBrains(): DifficultyBrainMap;
|
|
176
|
+
/**
|
|
177
|
+
* Replace the difficulty→brain presets wholesale (the editor pushes the full map).
|
|
178
|
+
* Passing an empty/normalized-empty map clears the override, so getDifficultyBrains
|
|
179
|
+
* falls back to the defaults again. Returns the normalized, persisted map.
|
|
180
|
+
*/
|
|
181
|
+
export declare function setDifficultyBrains(map: unknown): DifficultyBrainMap;
|
package/dist/index.js
CHANGED
|
@@ -409,10 +409,10 @@ function readInjected(value) {
|
|
|
409
409
|
}
|
|
410
410
|
function getDaemonBuildInfo() {
|
|
411
411
|
if (cached) return cached;
|
|
412
|
-
const commit = readInjected(true ? "
|
|
413
|
-
const commitShort = readInjected(true ? "
|
|
414
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
415
|
-
const builtAt = readInjected(true ? "2026-07-
|
|
412
|
+
const commit = readInjected(true ? "a503a00d57fbcdc84cd252c6d5caee90cfae6706" : void 0) ?? "unknown";
|
|
413
|
+
const commitShort = readInjected(true ? "a503a00d" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
414
|
+
const version = readInjected(true ? "0.9.82-rc.484" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
415
|
+
const builtAt = readInjected(true ? "2026-07-08T13:24:54.463Z" : void 0);
|
|
416
416
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
417
417
|
return cached;
|
|
418
418
|
}
|
|
@@ -2771,12 +2771,45 @@ function summarizeGitShape(status) {
|
|
|
2771
2771
|
submodules
|
|
2772
2772
|
};
|
|
2773
2773
|
}
|
|
2774
|
-
|
|
2774
|
+
function isMeshTaskDifficulty(value) {
|
|
2775
|
+
return typeof value === "string" && MESH_TASK_DIFFICULTIES.includes(value);
|
|
2776
|
+
}
|
|
2777
|
+
function normalizeThinkingLevel(value) {
|
|
2778
|
+
const v = typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
2779
|
+
return v === "low" || v === "medium" || v === "high" ? v : void 0;
|
|
2780
|
+
}
|
|
2781
|
+
function normalizeBrainSlot(raw) {
|
|
2782
|
+
const r = raw && typeof raw === "object" ? raw : {};
|
|
2783
|
+
const provider = typeof r.provider === "string" ? r.provider.trim() : "";
|
|
2784
|
+
const model = typeof r.model === "string" ? r.model.trim() : "";
|
|
2785
|
+
const thinkingLevel = normalizeThinkingLevel(r.thinkingLevel);
|
|
2786
|
+
return {
|
|
2787
|
+
...provider ? { provider } : {},
|
|
2788
|
+
...model ? { model } : {},
|
|
2789
|
+
...thinkingLevel ? { thinkingLevel } : {}
|
|
2790
|
+
};
|
|
2791
|
+
}
|
|
2792
|
+
function normalizeDifficultyBrainMap(raw) {
|
|
2793
|
+
const out = {};
|
|
2794
|
+
if (!raw || typeof raw !== "object") return out;
|
|
2795
|
+
for (const key2 of MESH_TASK_DIFFICULTIES) {
|
|
2796
|
+
const slot = normalizeBrainSlot(raw[key2]);
|
|
2797
|
+
if (slot.provider || slot.model || slot.thinkingLevel) out[key2] = slot;
|
|
2798
|
+
}
|
|
2799
|
+
return out;
|
|
2800
|
+
}
|
|
2801
|
+
var DAEMON_ID_PREFIXES, MAGI_RAW_ANSWER_CAP, MESH_TASK_DIFFICULTIES, DEFAULT_DIFFICULTY_BRAINS, CANONICAL_MESH_TOOL_NAMES, CANONICAL_MESH_TOOL_COUNT;
|
|
2775
2802
|
var init_dist = __esm({
|
|
2776
2803
|
"../mesh-shared/dist/index.mjs"() {
|
|
2777
2804
|
"use strict";
|
|
2778
2805
|
DAEMON_ID_PREFIXES = ["daemon_", "standalone_"];
|
|
2779
2806
|
MAGI_RAW_ANSWER_CAP = 4e3;
|
|
2807
|
+
MESH_TASK_DIFFICULTIES = ["easy", "medium", "difficult", "freeform"];
|
|
2808
|
+
DEFAULT_DIFFICULTY_BRAINS = {
|
|
2809
|
+
easy: { model: "haiku", thinkingLevel: "low" },
|
|
2810
|
+
medium: { model: "sonnet", thinkingLevel: "medium" },
|
|
2811
|
+
difficult: { model: "opus", thinkingLevel: "high" }
|
|
2812
|
+
};
|
|
2780
2813
|
CANONICAL_MESH_TOOL_NAMES = [
|
|
2781
2814
|
"mesh_status",
|
|
2782
2815
|
"mesh_list_nodes",
|
|
@@ -2917,6 +2950,7 @@ __export(mesh_config_exports, {
|
|
|
2917
2950
|
createMesh: () => createMesh,
|
|
2918
2951
|
createMeshHostPairingToken: () => createMeshHostPairingToken,
|
|
2919
2952
|
deleteMesh: () => deleteMesh,
|
|
2953
|
+
getDifficultyBrains: () => getDifficultyBrains,
|
|
2920
2954
|
getMagiKindPanel: () => getMagiKindPanel,
|
|
2921
2955
|
getMesh: () => getMesh,
|
|
2922
2956
|
getMeshByRepo: () => getMeshByRepo,
|
|
@@ -2927,6 +2961,7 @@ __export(mesh_config_exports, {
|
|
|
2927
2961
|
normalizeRepoIdentity: () => normalizeRepoIdentity,
|
|
2928
2962
|
removeMagiKindPanel: () => removeMagiKindPanel,
|
|
2929
2963
|
removeNode: () => removeNode,
|
|
2964
|
+
setDifficultyBrains: () => setDifficultyBrains,
|
|
2930
2965
|
setMagiKindPanel: () => setMagiKindPanel,
|
|
2931
2966
|
tokenIdForManualPairing: () => tokenIdForManualPairing,
|
|
2932
2967
|
updateMesh: () => updateMesh,
|
|
@@ -3402,6 +3437,19 @@ function removeMagiKindPanel(kind) {
|
|
|
3402
3437
|
saveMeshConfig(stored);
|
|
3403
3438
|
return true;
|
|
3404
3439
|
}
|
|
3440
|
+
function getDifficultyBrains() {
|
|
3441
|
+
const stored = loadMeshConfig().difficultyBrains;
|
|
3442
|
+
const normalized = normalizeDifficultyBrainMap(stored);
|
|
3443
|
+
return Object.keys(normalized).length > 0 ? normalized : { ...DEFAULT_DIFFICULTY_BRAINS };
|
|
3444
|
+
}
|
|
3445
|
+
function setDifficultyBrains(map) {
|
|
3446
|
+
const normalized = normalizeDifficultyBrainMap(map);
|
|
3447
|
+
const stored = loadMeshConfig();
|
|
3448
|
+
if (Object.keys(normalized).length > 0) stored.difficultyBrains = normalized;
|
|
3449
|
+
else delete stored.difficultyBrains;
|
|
3450
|
+
saveMeshConfig(stored);
|
|
3451
|
+
return normalized;
|
|
3452
|
+
}
|
|
3405
3453
|
var import_fs3, import_path3, import_crypto3, mergeMeshPolicy, MAGI_KIND_PANEL_KINDS, MAX_MAGI_KIND_SLOTS;
|
|
3406
3454
|
var init_mesh_config = __esm({
|
|
3407
3455
|
"src/config/mesh-config.ts"() {
|
|
@@ -3411,6 +3459,7 @@ var init_mesh_config = __esm({
|
|
|
3411
3459
|
import_crypto3 = require("crypto");
|
|
3412
3460
|
init_hash();
|
|
3413
3461
|
init_config();
|
|
3462
|
+
init_dist();
|
|
3414
3463
|
init_repo_mesh_types();
|
|
3415
3464
|
init_mesh_host_ownership();
|
|
3416
3465
|
mergeMeshPolicy = mergeAndNormalizePolicy;
|
|
@@ -3507,6 +3556,7 @@ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
|
|
|
3507
3556
|
if (operatingNotes) sections.push(operatingNotes);
|
|
3508
3557
|
}
|
|
3509
3558
|
sections.push(buildPolicySection(mergeAndNormalizePolicy(void 0, mesh.policy)));
|
|
3559
|
+
sections.push(buildBrainPresetsSection());
|
|
3510
3560
|
sections.push(TOOLS_SECTION);
|
|
3511
3561
|
sections.push(TOOL_EXPOSURE_PREFLIGHT_SECTION);
|
|
3512
3562
|
sections.push(WORKFLOW_SECTION);
|
|
@@ -3695,6 +3745,34 @@ function truncateNote(text) {
|
|
|
3695
3745
|
if (text.length <= OPERATING_NOTE_MAX_CHARS) return text;
|
|
3696
3746
|
return `${text.slice(0, OPERATING_NOTE_MAX_CHARS).trimEnd()}\u2026 [truncated]`;
|
|
3697
3747
|
}
|
|
3748
|
+
function buildBrainPresetsSection() {
|
|
3749
|
+
let brains;
|
|
3750
|
+
try {
|
|
3751
|
+
brains = getDifficultyBrains();
|
|
3752
|
+
} catch {
|
|
3753
|
+
brains = {};
|
|
3754
|
+
}
|
|
3755
|
+
const lines = [
|
|
3756
|
+
"## Brain presets",
|
|
3757
|
+
"",
|
|
3758
|
+
"When you pass `difficulty` on `mesh_enqueue_task`, it resolves to this model / thinking level (an explicit model/thinkingLevel on the task overrides it). Pick easy for trivial work to save tokens, difficult for hard reasoning.",
|
|
3759
|
+
""
|
|
3760
|
+
];
|
|
3761
|
+
for (const key2 of MESH_TASK_DIFFICULTIES) {
|
|
3762
|
+
const slot = brains[key2];
|
|
3763
|
+
if (!slot || !slot.provider && !slot.model && !slot.thinkingLevel) {
|
|
3764
|
+
lines.push(`- **${key2}**: (no preset \u2014 ordinary routing)`);
|
|
3765
|
+
continue;
|
|
3766
|
+
}
|
|
3767
|
+
const parts = [
|
|
3768
|
+
slot.provider ? `provider: \`${slot.provider}\`` : "",
|
|
3769
|
+
slot.model ? `model: \`${slot.model}\`` : "",
|
|
3770
|
+
slot.thinkingLevel ? `thinking: \`${slot.thinkingLevel}\`` : ""
|
|
3771
|
+
].filter(Boolean).join(" | ");
|
|
3772
|
+
lines.push(`- **${key2}**: ${parts}`);
|
|
3773
|
+
}
|
|
3774
|
+
return lines.join("\n");
|
|
3775
|
+
}
|
|
3698
3776
|
function buildPolicySection(policy) {
|
|
3699
3777
|
const rules = [];
|
|
3700
3778
|
if (policy.requirePreTaskCheckpoint) rules.push("- Create a git checkpoint **before** starting each task");
|
|
@@ -3723,6 +3801,7 @@ function buildRulesSection(coordinatorCliType) {
|
|
|
3723
3801
|
- **Front-load task messages.** Include everything the agent needs (files, problem, expected fix) in \`mesh_enqueue_task\` / \`mesh_send_task\`. Append a structured result request at the end: ask the worker to conclude with a JSON block containing \`status\`, \`changedFiles\`, \`gitStatus\`, \`validationResults\`, \`errors\`, \`nextAction\`. The daemon parses this automatically; you can read it from \`mesh_task_history\`.
|
|
3724
3802
|
- **Reuse idle sessions.** For follow-up, retry, commit/push, or cleanup on the same issue, send only the delta to the existing idle session. Start fresh only for independent work, provider mismatch, transcript contamination, or required worktree isolation.
|
|
3725
3803
|
- **Worktree affinity.** A worktree is a durable per-branch workspace; keep all of a branch's code_change/fix/review work on its worktree node by targeting \`required_tags: ["worktree=<branch>"]\` or \`target_node_id\`. Get the id/branch from the \`mesh_clone_node\` result or a live \`mesh_status\` \u2014 the Configured Nodes snapshot won't list a worktree cloned after launch. Untargeted same-branch follow-ups drift to the base node. Only \`convergence\` (merge/push) runs on the base, never pinned to the worktree.
|
|
3804
|
+
- **Classify task difficulty to save tokens.** For each task you enqueue, judge its execution difficulty and pass \`difficulty\`: \`easy\` (extraction, renames, doc tweaks, trivial fixes), \`medium\` (ordinary feature/bugfix work), \`difficult\` (architecture, tricky debugging, multi-file refactors, subtle reasoning), or \`freeform\`. The mesh's per-difficulty brain preset then runs easy tasks on a cheaper model at low reasoning effort and hard tasks on a stronger model at high effort \u2014 real token savings on simple work. The current presets are shown in the "Brain presets" section below. You may still pass an explicit \`model\`/\`thinkingLevel\` to override the preset for one task.
|
|
3726
3805
|
- **Respect explicit provider requests.** Map: Hermes \u2192 \`hermes-cli\`, Claude/Claude Code \u2192 \`claude-cli\`, Codex \u2192 \`codex-cli\`, Gemini \u2192 \`gemini-cli\`, Antigravity \u2192 \`antigravity-cli\`. Never substitute the coordinator's own runtime.
|
|
3727
3806
|
- **Verify via git, not source.** Use \`mesh_git_status\` to confirm side effects. Treat agent summaries as self-reports, not verification.
|
|
3728
3807
|
- **Limit parallelism.** Start with 1\u20132 tasks; scale only on success. Never duplicate a session because \`mesh_read_chat\` shows no final message while tool/terminal activity is ongoing. This caps *concurrent* load \u2014 it does not mean serialize independent work: when a new, independent request arrives and there is headroom under \`maxParallelTasks\`, dispatch it right away rather than waiting for an in-flight task or a user nudge (read-only diagnosis especially, since it has no merge cost).
|
|
@@ -3752,6 +3831,8 @@ var init_coordinator_prompt = __esm({
|
|
|
3752
3831
|
os2 = __toESM(require("os"));
|
|
3753
3832
|
path8 = __toESM(require("path"));
|
|
3754
3833
|
init_repo_mesh_types();
|
|
3834
|
+
init_mesh_config();
|
|
3835
|
+
init_dist();
|
|
3755
3836
|
PROMPT_SOFT_CAP_BYTES = 60 * 1024;
|
|
3756
3837
|
OPERATING_NOTES_PROMPT_CAP = 20;
|
|
3757
3838
|
OPERATING_NOTE_MAX_CHARS = 300;
|
|
@@ -5747,6 +5828,18 @@ function enqueueTask(meshId, message, opts) {
|
|
|
5747
5828
|
const priority = normalizeMeshTaskPriority(opts?.priority);
|
|
5748
5829
|
const notBefore = resolveNotBefore(opts?.notBefore);
|
|
5749
5830
|
const maxRetries = typeof opts?.maxRetries === "number" && Number.isFinite(opts.maxRetries) && opts.maxRetries >= 0 ? Math.floor(opts.maxRetries) : void 0;
|
|
5831
|
+
let effectiveModel = typeof opts?.model === "string" && opts.model.trim() ? opts.model.trim() : void 0;
|
|
5832
|
+
let effectiveThinkingLevel = typeof opts?.thinkingLevel === "string" && opts.thinkingLevel.trim() ? opts.thinkingLevel.trim() : void 0;
|
|
5833
|
+
if (isMeshTaskDifficulty(opts?.difficulty)) {
|
|
5834
|
+
try {
|
|
5835
|
+
const preset = getDifficultyBrains()[opts.difficulty];
|
|
5836
|
+
if (preset) {
|
|
5837
|
+
if (!effectiveModel && preset.model) effectiveModel = preset.model;
|
|
5838
|
+
if (!effectiveThinkingLevel && preset.thinkingLevel) effectiveThinkingLevel = preset.thinkingLevel;
|
|
5839
|
+
}
|
|
5840
|
+
} catch {
|
|
5841
|
+
}
|
|
5842
|
+
}
|
|
5750
5843
|
const result = withQueueLock(meshId, () => {
|
|
5751
5844
|
if (MeshRuntimeStore.getInstance().findQueueEntryById(meshId, id)) {
|
|
5752
5845
|
throw new Error(`duplicate_task_id: task '${id}' already exists in mesh '${meshId}'`);
|
|
@@ -5778,7 +5871,8 @@ function enqueueTask(meshId, message, opts) {
|
|
|
5778
5871
|
...maxRetries !== void 0 ? { maxRetries } : {},
|
|
5779
5872
|
...typeof opts?.missionId === "string" && opts.missionId.trim() ? { missionId: opts.missionId.trim() } : {},
|
|
5780
5873
|
...typeof opts?.consensusGroupId === "string" && opts.consensusGroupId.trim() ? { consensusGroupId: opts.consensusGroupId.trim() } : {},
|
|
5781
|
-
...
|
|
5874
|
+
...effectiveModel ? { model: effectiveModel } : {},
|
|
5875
|
+
...effectiveThinkingLevel ? { thinkingLevel: effectiveThinkingLevel } : {},
|
|
5782
5876
|
...typeof opts?.sourceCoordinatorSessionId === "string" && opts.sourceCoordinatorSessionId.trim() ? { sourceCoordinatorSessionId: opts.sourceCoordinatorSessionId.trim() } : {},
|
|
5783
5877
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5784
5878
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -7353,6 +7447,27 @@ var init_mesh_runtime_store = __esm({
|
|
|
7353
7447
|
`).get(meshId, taskId);
|
|
7354
7448
|
return !!row;
|
|
7355
7449
|
}
|
|
7450
|
+
/**
|
|
7451
|
+
* DELIVERED-NOT-CONSUMED re-drive support: true when at least one delivery record for
|
|
7452
|
+
* the task has reached a CONSUMED status ('acked' / 'completed'). Distinct from
|
|
7453
|
+
* {@link taskHasConfirmedDelivery} ('delivered' | 'acked' | 'completed'): a delivery is
|
|
7454
|
+
* flipped to 'delivered' the instant the transport hands the dispatch off, but only
|
|
7455
|
+
* flipped to 'acked' when the worker's agent:generating_started event arrives (see the
|
|
7456
|
+
* generating_started handler in mesh-event-forwarding) — i.e. when the session has
|
|
7457
|
+
* actually begun the turn. That distinction is the cross-daemon consumption signal the
|
|
7458
|
+
* short-grace re-drive uses: a row whose delivery is 'delivered' but never 'acked' was
|
|
7459
|
+
* handed to a REMOTE worker that never started generating — the remote autoLaunch
|
|
7460
|
+
* delivered≠consumed gap — even when the session's busy verdict is UNKNOWN (not locally
|
|
7461
|
+
* observable). Indexed by (mesh_id, task_id).
|
|
7462
|
+
*/
|
|
7463
|
+
taskDeliveryConsumed(meshId, taskId) {
|
|
7464
|
+
const row = this.db.prepare(`
|
|
7465
|
+
SELECT 1 FROM mesh_session_delivery
|
|
7466
|
+
WHERE mesh_id = ? AND task_id = ? AND status IN ('acked','completed')
|
|
7467
|
+
LIMIT 1
|
|
7468
|
+
`).get(meshId, taskId);
|
|
7469
|
+
return !!row;
|
|
7470
|
+
}
|
|
7356
7471
|
expireStaleSessionDeliveries(meshId) {
|
|
7357
7472
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
7358
7473
|
this.db.prepare(`
|
|
@@ -8442,7 +8557,8 @@ function routeV2EventsForDrainer(events, drainer, ctx) {
|
|
|
8442
8557
|
}
|
|
8443
8558
|
if (validated.scope !== "unicast") {
|
|
8444
8559
|
if (validated.scope === "broadcast" && isTerminalTaskEvent(validated.event)) {
|
|
8445
|
-
|
|
8560
|
+
const deliverSelfFallback = event.dispatchedBySelfFallback && daemonIdsEquivalent(validated.dispatchedBy.daemonId, drainer.daemonId);
|
|
8561
|
+
if (deliverSelfFallback || identityDeliversTo(validated.dispatchedBy, drainer)) {
|
|
8446
8562
|
ctx.batchSeen.add(eventId);
|
|
8447
8563
|
bump("v2Delivered");
|
|
8448
8564
|
kept.push(event);
|
|
@@ -8714,13 +8830,15 @@ function stampPendingEventV2(event, hint) {
|
|
|
8714
8830
|
scope: hint?.scope ?? (selfFallback ? "broadcast" : void 0)
|
|
8715
8831
|
});
|
|
8716
8832
|
if (!stamp) return event;
|
|
8833
|
+
const dispatchedBySelfFallback = selfFallback && stamp.scope === "broadcast";
|
|
8717
8834
|
return {
|
|
8718
8835
|
...event,
|
|
8719
8836
|
protocolVersion: stamp.protocolVersion,
|
|
8720
8837
|
eventId: stamp.eventId,
|
|
8721
8838
|
scope: stamp.scope,
|
|
8722
8839
|
dispatchedBy: stamp.dispatchedBy,
|
|
8723
|
-
...stamp.intendedFor ? { intendedFor: stamp.intendedFor } : {}
|
|
8840
|
+
...stamp.intendedFor ? { intendedFor: stamp.intendedFor } : {},
|
|
8841
|
+
...dispatchedBySelfFallback ? { dispatchedBySelfFallback: true } : {}
|
|
8724
8842
|
};
|
|
8725
8843
|
}
|
|
8726
8844
|
function readCoordinatorIdentityFromWire(raw) {
|
|
@@ -15246,8 +15364,23 @@ function mergeInlineCacheOnlyNodes(localMesh, cachedMesh) {
|
|
|
15246
15364
|
if (!cachedId) return false;
|
|
15247
15365
|
return !localNodes.some((localNode) => meshNodeIdMatches(localNode, cachedId));
|
|
15248
15366
|
});
|
|
15249
|
-
|
|
15250
|
-
|
|
15367
|
+
let overlaidLocalNodes = localNodes;
|
|
15368
|
+
let overlaid = false;
|
|
15369
|
+
for (let i = 0; i < localNodes.length; i++) {
|
|
15370
|
+
const localNode = localNodes[i];
|
|
15371
|
+
const localId = readMeshNodeId(localNode);
|
|
15372
|
+
if (!localId) continue;
|
|
15373
|
+
const inlineMatch = cachedNodes.find((cachedNode) => meshNodeIdMatches(cachedNode, localId));
|
|
15374
|
+
const inlineBootstrapStatus = readNonEmptyString2(inlineMatch?.worktreeBootstrap?.status);
|
|
15375
|
+
if (!inlineMatch || !inlineBootstrapStatus) continue;
|
|
15376
|
+
if (!overlaid) {
|
|
15377
|
+
overlaidLocalNodes = [...localNodes];
|
|
15378
|
+
overlaid = true;
|
|
15379
|
+
}
|
|
15380
|
+
overlaidLocalNodes[i] = { ...localNode, worktreeBootstrap: inlineMatch.worktreeBootstrap };
|
|
15381
|
+
}
|
|
15382
|
+
if (!cacheOnly.length && !overlaid) return localMesh;
|
|
15383
|
+
return { ...localMesh, nodes: [...overlaidLocalNodes, ...cacheOnly] };
|
|
15251
15384
|
}
|
|
15252
15385
|
function warnDispatchWarmupGetterMissingOnce(daemonId) {
|
|
15253
15386
|
if (dispatchWarmupGetterMissingWarned.has(daemonId)) return;
|
|
@@ -16117,7 +16250,9 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
|
|
|
16117
16250
|
settings: remoteSettings,
|
|
16118
16251
|
// MAGI-KIND-PANEL model axis: forward the task's model override so the
|
|
16119
16252
|
// remote worker session launches with it (initialModel). Best-effort.
|
|
16120
|
-
...typeof task.model === "string" && task.model.trim() ? { initialModel: task.model.trim() } : {}
|
|
16253
|
+
...typeof task.model === "string" && task.model.trim() ? { initialModel: task.model.trim() } : {},
|
|
16254
|
+
// BRAIN-ROUTING thinking axis: forward the task's thinking level (initialThinkingLevel).
|
|
16255
|
+
...typeof task.thinkingLevel === "string" && task.thinkingLevel.trim() ? { initialThinkingLevel: task.thinkingLevel.trim() } : {}
|
|
16121
16256
|
});
|
|
16122
16257
|
} catch (e) {
|
|
16123
16258
|
markAutoLaunch(meshId, task.id, { status: "failed", reason: `remote_launch_dispatch_failed: ${e?.message || String(e)}`, nodeId, providerType: resolved.providerType });
|
|
@@ -16146,7 +16281,9 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
|
|
|
16146
16281
|
settings: launchSettings,
|
|
16147
16282
|
// MAGI-KIND-PANEL model axis: local launch forwards the task's model
|
|
16148
16283
|
// override as initialModel (CLI → modelLaunchArgs; ACP → setConfigOption).
|
|
16149
|
-
...typeof task.model === "string" && task.model.trim() ? { initialModel: task.model.trim() } : {}
|
|
16284
|
+
...typeof task.model === "string" && task.model.trim() ? { initialModel: task.model.trim() } : {},
|
|
16285
|
+
// BRAIN-ROUTING thinking axis: forward the task's thinking level (initialThinkingLevel).
|
|
16286
|
+
...typeof task.thinkingLevel === "string" && task.thinkingLevel.trim() ? { initialThinkingLevel: task.thinkingLevel.trim() } : {}
|
|
16150
16287
|
});
|
|
16151
16288
|
if (!launchResult?.success) {
|
|
16152
16289
|
const reason = launchResult?.error || "launch_cli_failed";
|
|
@@ -18706,6 +18843,8 @@ function buildAvailableProviders(providerLoader) {
|
|
|
18706
18843
|
...sourceLayer ? { sourceLayer } : {},
|
|
18707
18844
|
...sourceName ? { sourceName } : {},
|
|
18708
18845
|
...provider.providerVersion ? { providerVersion: provider.providerVersion } : {},
|
|
18846
|
+
...Array.isArray(provider.modelOptions) && provider.modelOptions.length ? { modelOptions: provider.modelOptions } : {},
|
|
18847
|
+
...Array.isArray(provider.thinkingLevelOptions) && provider.thinkingLevelOptions.length ? { thinkingLevelOptions: provider.thinkingLevelOptions } : {},
|
|
18709
18848
|
...provider.binary ? { binary: provider.binary } : {},
|
|
18710
18849
|
...provider.status ? { status: provider.status } : {},
|
|
18711
18850
|
...provider.details ? { details: provider.details } : {},
|
|
@@ -21043,7 +21182,34 @@ function recoverStrandedAssignedDispatches(components, meshId, store) {
|
|
|
21043
21182
|
for (const row of assigned) {
|
|
21044
21183
|
const dispatchedAtMs = Date.parse(row.dispatchTimestamp ?? "");
|
|
21045
21184
|
if (!Number.isFinite(dispatchedAtMs)) continue;
|
|
21046
|
-
|
|
21185
|
+
const ageMs = nowMs - dispatchedAtMs;
|
|
21186
|
+
if (ageMs >= ASSIGNED_DELIVERED_UNCONSUMED_REDRIVE_MS && ageMs < ASSIGNED_STRANDED_DEADLINE_MS && store.taskHasConfirmedDelivery(meshId, row.id) && !store.taskDeliveryConsumed(meshId, row.id)) {
|
|
21187
|
+
const terminal2 = findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id });
|
|
21188
|
+
if (terminal2) {
|
|
21189
|
+
const status = terminal2.kind === "task_completed" ? "completed" : "failed";
|
|
21190
|
+
updateTaskStatus(meshId, row.id, status);
|
|
21191
|
+
continue;
|
|
21192
|
+
}
|
|
21193
|
+
const verdict = row.assignedSessionId ? resolveSessionBusyVerdict(components, row.assignedSessionId) : "IDLE_CONFIRMED";
|
|
21194
|
+
if (verdict !== "GENERATING") {
|
|
21195
|
+
const redriven = reclaimStrandedAssignedTask(meshId, row.id, {
|
|
21196
|
+
reason: "delivered_not_consumed_redrive",
|
|
21197
|
+
ageMs
|
|
21198
|
+
});
|
|
21199
|
+
if (redriven) {
|
|
21200
|
+
LOG.warn("MeshReconcile", `Re-drove delivered-but-unconsumed task ${row.id} on mesh ${meshId} (node=${row.assignedNodeId ?? "?"} session=${row.assignedSessionId ?? "?"}, delivered but no generating_started in ${Math.round(ageMs / 1e3)}s, verdict ${verdict} \u2192 ${redriven.status})`);
|
|
21201
|
+
traceMeshEventDrop("assigned_delivered_not_consumed_redrive", {
|
|
21202
|
+
taskId: row.id,
|
|
21203
|
+
sessionId: row.assignedSessionId,
|
|
21204
|
+
nodeId: row.assignedNodeId,
|
|
21205
|
+
meshId,
|
|
21206
|
+
event: "agent:generating_started"
|
|
21207
|
+
}, `delivered_not_consumed ${Math.round(ageMs / 1e3)}s \u2192 ${redriven.status}`);
|
|
21208
|
+
continue;
|
|
21209
|
+
}
|
|
21210
|
+
}
|
|
21211
|
+
}
|
|
21212
|
+
if (ageMs < ASSIGNED_STRANDED_DEADLINE_MS) continue;
|
|
21047
21213
|
const terminal = findTerminalLedgerEvidenceForTask({
|
|
21048
21214
|
meshId,
|
|
21049
21215
|
taskId: row.id
|
|
@@ -21558,7 +21724,7 @@ function setupMeshReconcileLoop(components) {
|
|
|
21558
21724
|
}
|
|
21559
21725
|
};
|
|
21560
21726
|
}
|
|
21561
|
-
var coordinatorModalParkState, heldEventLedgerRecorded, ASSIGNED_STRANDED_DEADLINE_MS, DELIVERED_NO_TURN_DEADLINE_MS, RECLAIM_UNKNOWN_GRACE_TICKS, deliveredNoTurnUnknownStreak, ZOMBIE_ASSIGNED_MIN_AGE_MS, STRICT_SESSION_MATCH_TTL_MS, unresolvedForwardRejectionCounts, MAX_FORWARD_REJECTIONS, UNRESOLVED_FORWARD_NUDGE_DELAY_MS, unresolvedForwardNudgeTimer, unresolvedForwardNudgeRunning;
|
|
21727
|
+
var coordinatorModalParkState, heldEventLedgerRecorded, ASSIGNED_STRANDED_DEADLINE_MS, DELIVERED_NO_TURN_DEADLINE_MS, ASSIGNED_DELIVERED_UNCONSUMED_REDRIVE_MS, RECLAIM_UNKNOWN_GRACE_TICKS, deliveredNoTurnUnknownStreak, ZOMBIE_ASSIGNED_MIN_AGE_MS, STRICT_SESSION_MATCH_TTL_MS, unresolvedForwardRejectionCounts, MAX_FORWARD_REJECTIONS, UNRESOLVED_FORWARD_NUDGE_DELAY_MS, unresolvedForwardNudgeTimer, unresolvedForwardNudgeRunning;
|
|
21562
21728
|
var init_mesh_reconcile_loop = __esm({
|
|
21563
21729
|
"src/mesh/mesh-reconcile-loop.ts"() {
|
|
21564
21730
|
"use strict";
|
|
@@ -21588,6 +21754,7 @@ var init_mesh_reconcile_loop = __esm({
|
|
|
21588
21754
|
heldEventLedgerRecorded = /* @__PURE__ */ new Set();
|
|
21589
21755
|
ASSIGNED_STRANDED_DEADLINE_MS = 5 * 6e4;
|
|
21590
21756
|
DELIVERED_NO_TURN_DEADLINE_MS = 15 * 6e4;
|
|
21757
|
+
ASSIGNED_DELIVERED_UNCONSUMED_REDRIVE_MS = 25e3;
|
|
21591
21758
|
RECLAIM_UNKNOWN_GRACE_TICKS = 3;
|
|
21592
21759
|
deliveredNoTurnUnknownStreak = /* @__PURE__ */ new Map();
|
|
21593
21760
|
ZOMBIE_ASSIGNED_MIN_AGE_MS = 30 * 60 * 1e3;
|
|
@@ -21863,6 +22030,35 @@ var init_provider_schema = __esm({
|
|
|
21863
22030
|
items: { type: "string" },
|
|
21864
22031
|
description: "Template for expanding an initialModel selection into launch args. '{{model}}' is substituted with the model string (e.g. ['--model', '{{model}}'] \u2192 --model opus). Applied at launch when a model is requested for this CLI provider (MAGI kind-panel model axis). Absent \u2192 no launch-time model selection."
|
|
21865
22032
|
},
|
|
22033
|
+
modelOptions: {
|
|
22034
|
+
type: "array",
|
|
22035
|
+
items: { type: "string" },
|
|
22036
|
+
description: "Suggested model values shown as dropdown options in the new-session dialog (brain-routing model axis), e.g. ['opus','sonnet','haiku']. Advisory \u2014 the UI still accepts free text, so a stale list never blocks an accepted model."
|
|
22037
|
+
},
|
|
22038
|
+
thinkingLaunchArgs: {
|
|
22039
|
+
type: "array",
|
|
22040
|
+
items: { type: "string" },
|
|
22041
|
+
description: "Template for expanding an initialThinkingLevel selection into launch args (brain-routing thinking axis, parallel to modelLaunchArgs). '{{level}}' is substituted with the provider-mapped reasoning-effort value (e.g. ['--effort', '{{level}}'] \u2192 --effort high; ['-c', 'model_reasoning_effort={{level}}']). Applied at launch when a thinking level is requested. Absent \u2192 no launch-time thinking selection."
|
|
22042
|
+
},
|
|
22043
|
+
thinkingLevelMap: {
|
|
22044
|
+
type: "object",
|
|
22045
|
+
properties: {
|
|
22046
|
+
low: { type: "string" },
|
|
22047
|
+
medium: { type: "string" },
|
|
22048
|
+
high: { type: "string" }
|
|
22049
|
+
},
|
|
22050
|
+
additionalProperties: false,
|
|
22051
|
+
description: "Optional map from the standard thinking levels (low/medium/high) to this provider's own reasoning-effort vocabulary, used to fill {{level}} in thinkingLaunchArgs. A level absent from the map passes through unchanged."
|
|
22052
|
+
},
|
|
22053
|
+
thinkingLevelOptions: {
|
|
22054
|
+
type: "array",
|
|
22055
|
+
items: { type: "string" },
|
|
22056
|
+
description: "Reasoning-effort values this provider accepts, shown as the thinking-level dropdown in the new-session dialog (e.g. ['low','medium','high','max']). Absent \u2192 the UI falls back to standard low/medium/high. Provider's own vocabulary, passed through verbatim."
|
|
22057
|
+
},
|
|
22058
|
+
thinkingControlId: {
|
|
22059
|
+
type: "string",
|
|
22060
|
+
description: "For a provider with no thinkingLaunchArgs but a runtime reasoning-effort control (e.g. hermes 'reasoning'), the controls[].id to drive at launch for the thinking level. The control's setScript is invoked with { value: <mapped level> }."
|
|
22061
|
+
},
|
|
21866
22062
|
scriptCallBudgetMs: {
|
|
21867
22063
|
type: "integer",
|
|
21868
22064
|
minimum: 1,
|
|
@@ -44967,6 +45163,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
44967
45163
|
this.presentationMode = "chat";
|
|
44968
45164
|
this.providerSessionId = options?.providerSessionId;
|
|
44969
45165
|
this.launchMode = options?.launchMode || "new";
|
|
45166
|
+
this.initialThinkingLevel = options?.initialThinkingLevel;
|
|
44970
45167
|
this.onProviderSessionResolved = options?.onProviderSessionResolved;
|
|
44971
45168
|
this.adapter = createCliAdapter(provider, workingDir, cliArgs, options?.extraEnv || {}, transportFactory);
|
|
44972
45169
|
if (this.providerSessionId) {
|
|
@@ -45188,6 +45385,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
45188
45385
|
presentationMode;
|
|
45189
45386
|
providerSessionId;
|
|
45190
45387
|
launchMode;
|
|
45388
|
+
initialThinkingLevel;
|
|
45191
45389
|
startedAt = Date.now();
|
|
45192
45390
|
onProviderSessionResolved;
|
|
45193
45391
|
refreshProviderDefinition(provider) {
|
|
@@ -45216,6 +45414,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
45216
45414
|
});
|
|
45217
45415
|
await this.adapter.spawn();
|
|
45218
45416
|
await this.enforceFreshSessionLaunchIfNeeded();
|
|
45417
|
+
await this.applyInitialThinkingLevelViaControl();
|
|
45219
45418
|
this.maybeAppendRuntimeRecoveryMessage(this.adapter.getRuntimeMetadata());
|
|
45220
45419
|
if (this.providerSessionId && this.shouldHydrateExistingProviderHistory()) {
|
|
45221
45420
|
this.restorePersistedHistoryFromCurrentSession();
|
|
@@ -45833,6 +46032,43 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
45833
46032
|
}
|
|
45834
46033
|
this.applyProviderResponse(parsed.payload, { phase: "immediate" });
|
|
45835
46034
|
}
|
|
46035
|
+
/**
|
|
46036
|
+
* BRAIN-ROUTING (runtime-control thinking axis): for a provider that selects
|
|
46037
|
+
* reasoning effort via a runtime control instead of a launch arg (e.g. hermes
|
|
46038
|
+
* `reasoning`), apply the requested initialThinkingLevel after spawn by invoking
|
|
46039
|
+
* that control's setScript. The provider names the control via thinkingControlId.
|
|
46040
|
+
* The standard level is mapped through thinkingLevelMap first (same as the
|
|
46041
|
+
* launch-arg path). Best-effort: any failure logs and never blocks launch.
|
|
46042
|
+
*/
|
|
46043
|
+
async applyInitialThinkingLevelViaControl() {
|
|
46044
|
+
const level = typeof this.initialThinkingLevel === "string" ? this.initialThinkingLevel.trim() : "";
|
|
46045
|
+
if (!level) return;
|
|
46046
|
+
const controlId = this.provider.thinkingControlId;
|
|
46047
|
+
if (!controlId) return;
|
|
46048
|
+
const controls = Array.isArray(this.provider.controls) ? this.provider.controls : [];
|
|
46049
|
+
const control = controls.find((c) => c && c.id === controlId);
|
|
46050
|
+
if (!control || !control.setScript) return;
|
|
46051
|
+
const map = this.provider.thinkingLevelMap;
|
|
46052
|
+
const mapped = map && typeof map[level] === "string" && map[level].trim() ? map[level].trim() : level;
|
|
46053
|
+
try {
|
|
46054
|
+
await waitForCliAdapterReady(this.adapter);
|
|
46055
|
+
const raw = await this.adapter.invokeScript(control.setScript, { value: mapped });
|
|
46056
|
+
const parsed = parseCliScriptResult(raw);
|
|
46057
|
+
if (!parsed.success) {
|
|
46058
|
+
LOG.warn("CLI", `[${this.type}] thinking control '${controlId}' set to '${mapped}' failed: ${parsed.payload?.error || "unknown"}`);
|
|
46059
|
+
return;
|
|
46060
|
+
}
|
|
46061
|
+
const cliCommand = getCliScriptCommand(parsed.payload);
|
|
46062
|
+
if (cliCommand?.type === "send_message" && cliCommand.text) {
|
|
46063
|
+
await this.adapter.sendMessage(cliCommand.text);
|
|
46064
|
+
} else if (cliCommand?.type === "pty_write" && cliCommand.text) {
|
|
46065
|
+
await this.adapter.writeRaw(cliCommand.text + "\r");
|
|
46066
|
+
}
|
|
46067
|
+
LOG.info("CLI", `[${this.type}] applied thinking level '${mapped}' via control '${controlId}'`);
|
|
46068
|
+
} catch (e) {
|
|
46069
|
+
LOG.warn("CLI", `[${this.type}] thinking control apply threw: ${e?.message || e}`);
|
|
46070
|
+
}
|
|
46071
|
+
}
|
|
45836
46072
|
completionHasFinalAssistantMessage(messages, turnStartedAt) {
|
|
45837
46073
|
const visibleMessages = (Array.isArray(messages) ? messages : []).filter((message) => isUserFacingChatMessage(message));
|
|
45838
46074
|
const lastVisible = visibleMessages[visibleMessages.length - 1];
|
|
@@ -48939,7 +49175,13 @@ function expandResumeArgs(template, sessionId) {
|
|
|
48939
49175
|
function expandModelLaunchArgs(template, model) {
|
|
48940
49176
|
const m = typeof model === "string" ? model.trim() : "";
|
|
48941
49177
|
if (!m || !Array.isArray(template) || template.length === 0) return void 0;
|
|
48942
|
-
return template.map((part) => part
|
|
49178
|
+
return template.map((part) => part.includes("{{model}}") ? part.split("{{model}}").join(m) : part);
|
|
49179
|
+
}
|
|
49180
|
+
function expandThinkingLaunchArgs(template, level, levelMap) {
|
|
49181
|
+
const raw = typeof level === "string" ? level.trim() : "";
|
|
49182
|
+
if (!raw || !Array.isArray(template) || template.length === 0) return void 0;
|
|
49183
|
+
const mapped = levelMap && typeof levelMap[raw] === "string" && levelMap[raw].trim() ? levelMap[raw].trim() : raw;
|
|
49184
|
+
return template.map((part) => part.includes("{{level}}") ? part.replace("{{level}}", mapped) : part);
|
|
48943
49185
|
}
|
|
48944
49186
|
function readSubcommandSessionId(args, subcommands) {
|
|
48945
49187
|
const resumeIndex = args.findIndex((arg) => subcommands.includes(arg));
|
|
@@ -49323,6 +49565,15 @@ ${installInfo}`
|
|
|
49323
49565
|
LOG.warn("CLI", `[ACP] Initial model set failed: ${e?.message}`);
|
|
49324
49566
|
}
|
|
49325
49567
|
}
|
|
49568
|
+
if (options?.initialThinkingLevel) {
|
|
49569
|
+
const lvl = options.initialThinkingLevel;
|
|
49570
|
+
try {
|
|
49571
|
+
await acpInstance.setConfigOption("thought_level", lvl);
|
|
49572
|
+
console.log(colorize("green", ` \u{1F9E0} Initial thinking level set: ${lvl}`));
|
|
49573
|
+
} catch (e) {
|
|
49574
|
+
LOG.warn("CLI", `[ACP] Initial thinking level set failed (provider may not support thought_level): ${e?.message}`);
|
|
49575
|
+
}
|
|
49576
|
+
}
|
|
49326
49577
|
this.persistRecentActivity({
|
|
49327
49578
|
kind: "acp",
|
|
49328
49579
|
providerType: normalizedType,
|
|
@@ -49358,7 +49609,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
49358
49609
|
if (initialModel && !modelLaunchArgs) {
|
|
49359
49610
|
LOG.warn("CLI", `[${normalizedType}] initialModel='${initialModel}' requested but provider declares no modelLaunchArgs template \u2014 launching without model selection.`);
|
|
49360
49611
|
}
|
|
49361
|
-
const
|
|
49612
|
+
const initialThinkingLevel = options?.initialThinkingLevel;
|
|
49613
|
+
const thinkingLaunchArgs = expandThinkingLaunchArgs(provider?.thinkingLaunchArgs, initialThinkingLevel, provider?.thinkingLevelMap);
|
|
49614
|
+
const cliArgsWithBrain = thinkingLaunchArgs ? [...thinkingLaunchArgs, ...cliArgsWithModel || []] : cliArgsWithModel;
|
|
49615
|
+
if (initialThinkingLevel && !thinkingLaunchArgs) {
|
|
49616
|
+
LOG.warn("CLI", `[${normalizedType}] initialThinkingLevel='${initialThinkingLevel}' requested but provider declares no thinkingLaunchArgs template \u2014 launching without thinking-level selection.`);
|
|
49617
|
+
}
|
|
49618
|
+
const sessionBinding = resolveCliSessionBinding(provider, normalizedType, cliArgsWithBrain, options?.resumeSessionId);
|
|
49362
49619
|
const resolvedCliArgs = sessionBinding.cliArgs;
|
|
49363
49620
|
const instanceManager = this.deps.getInstanceManager();
|
|
49364
49621
|
if (provider && instanceManager) {
|
|
@@ -49376,6 +49633,10 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
49376
49633
|
providerSessionId: sessionBinding.providerSessionId,
|
|
49377
49634
|
launchMode: sessionBinding.launchMode,
|
|
49378
49635
|
extraEnv: options?.extraEnv,
|
|
49636
|
+
// BRAIN-ROUTING: for a provider with no thinkingLaunchArgs but a
|
|
49637
|
+
// runtime reasoning control (hermes), apply the level post-launch.
|
|
49638
|
+
// The launch-arg providers (claude/codex) already consumed it at spawn.
|
|
49639
|
+
...options?.initialThinkingLevel && !provider?.thinkingLaunchArgs ? { initialThinkingLevel: options.initialThinkingLevel } : {},
|
|
49379
49640
|
onProviderSessionResolved: ({ providerSessionId, providerName, providerType, workspace }) => {
|
|
49380
49641
|
this.persistRecentActivity({
|
|
49381
49642
|
kind: "cli",
|
|
@@ -49723,7 +49984,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
49723
49984
|
{
|
|
49724
49985
|
resumeSessionId: args?.resumeSessionId,
|
|
49725
49986
|
settingsOverride,
|
|
49726
|
-
extraEnv: delegatedLaunch ? delegatedLaunch.env : args?.env
|
|
49987
|
+
extraEnv: delegatedLaunch ? delegatedLaunch.env : args?.env,
|
|
49988
|
+
...typeof args?.initialThinkingLevel === "string" && args.initialThinkingLevel.trim() ? { initialThinkingLevel: args.initialThinkingLevel.trim() } : {}
|
|
49727
49989
|
}
|
|
49728
49990
|
);
|
|
49729
49991
|
return {
|
|
@@ -50168,6 +50430,12 @@ var KNOWN_PROVIDER_FIELDS = /* @__PURE__ */ new Set([
|
|
|
50168
50430
|
"providerVersion",
|
|
50169
50431
|
"status",
|
|
50170
50432
|
"details",
|
|
50433
|
+
"modelLaunchArgs",
|
|
50434
|
+
"modelOptions",
|
|
50435
|
+
"thinkingLaunchArgs",
|
|
50436
|
+
"thinkingLevelMap",
|
|
50437
|
+
"thinkingLevelOptions",
|
|
50438
|
+
"thinkingControlId",
|
|
50171
50439
|
"sendDelayMs",
|
|
50172
50440
|
"sendKey",
|
|
50173
50441
|
"submitStrategy",
|
|
@@ -54881,6 +55149,26 @@ var meshCrudHandlers = {
|
|
|
54881
55149
|
return { success: false, error: e.message };
|
|
54882
55150
|
}
|
|
54883
55151
|
},
|
|
55152
|
+
// ─── Brain routing: per-difficulty brain presets (machine-local) ───
|
|
55153
|
+
// getDifficultyBrains returns the seeded defaults when nothing is configured,
|
|
55154
|
+
// so the editor always shows a usable mapping. set replaces the whole map.
|
|
55155
|
+
difficulty_brains_get: async (_ctx, _args) => {
|
|
55156
|
+
try {
|
|
55157
|
+
const { getDifficultyBrains: getDifficultyBrains2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
55158
|
+
return { success: true, difficultyBrains: getDifficultyBrains2() };
|
|
55159
|
+
} catch (e) {
|
|
55160
|
+
return { success: false, error: e.message };
|
|
55161
|
+
}
|
|
55162
|
+
},
|
|
55163
|
+
difficulty_brains_set: async (_ctx, args) => {
|
|
55164
|
+
try {
|
|
55165
|
+
const { setDifficultyBrains: setDifficultyBrains2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
55166
|
+
const difficultyBrains = setDifficultyBrains2(args?.difficultyBrains);
|
|
55167
|
+
return { success: true, difficultyBrains };
|
|
55168
|
+
} catch (e) {
|
|
55169
|
+
return { success: false, error: e.message };
|
|
55170
|
+
}
|
|
55171
|
+
},
|
|
54884
55172
|
add_mesh_node: async (ctx, args) => {
|
|
54885
55173
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
54886
55174
|
const workspace = typeof args?.workspace === "string" ? args.workspace.trim() : "";
|