@adhdev/daemon-core 0.9.82-rc.436 → 0.9.82-rc.438
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/config/mesh-config.d.ts +21 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +156 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +151 -8
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-work-queue.d.ts +10 -0
- package/dist/providers/contracts.d.ts +10 -0
- package/dist/repo-mesh-types.d.ts +9 -1
- package/package.json +2 -2
- package/src/commands/cli-manager.ts +28 -1
- package/src/commands/med-family/mesh-crud.ts +42 -0
- package/src/config/mesh-config.ts +99 -1
- package/src/index.ts +1 -0
- package/src/mesh/mesh-queue-assignment.ts +6 -0
- package/src/mesh/mesh-work-queue.ts +11 -0
- package/src/providers/contracts.ts +10 -0
- package/src/providers/sdk/v1/schemas/cli/provider.schema.json +5 -0
- package/src/repo-mesh-types.ts +9 -1
|
@@ -72,6 +72,14 @@ export interface MeshWorkQueueEntry {
|
|
|
72
72
|
* replicas. Absent on ordinary tasks. Rides in the payload JSON (no column).
|
|
73
73
|
*/
|
|
74
74
|
consensusGroupId?: string;
|
|
75
|
+
/**
|
|
76
|
+
* MAGI-KIND-PANEL (model axis): model override for the session that executes this
|
|
77
|
+
* task. When the task auto-launches a session, this is passed to launch_cli as
|
|
78
|
+
* `initialModel` (ACP → setConfigOption; CLI → modelLaunchArgs template). Absent on
|
|
79
|
+
* ordinary tasks. Rides in the payload JSON (no column). Best-effort — a provider
|
|
80
|
+
* that cannot honor the model still runs the task (never a fatal launch error).
|
|
81
|
+
*/
|
|
82
|
+
model?: string;
|
|
75
83
|
/**
|
|
76
84
|
* M1: why this task is held back (e.g. "dependency_failed:<taskId>").
|
|
77
85
|
* Only set by the system on dependency failure under the 'block' policy;
|
|
@@ -186,6 +194,8 @@ export declare function enqueueTask(meshId: string, message: string, opts?: {
|
|
|
186
194
|
missionId?: string;
|
|
187
195
|
/** MAGI: consensus group id shared by every replica of a mesh_magi_review fan-out. */
|
|
188
196
|
consensusGroupId?: string;
|
|
197
|
+
/** MAGI-KIND-PANEL: model override forwarded to the executing session's launch (initialModel). */
|
|
198
|
+
model?: string;
|
|
189
199
|
/** Explicit task id for batch/template flows (M5). Random UUID when omitted. */
|
|
190
200
|
id?: string;
|
|
191
201
|
/** (3) Originating coordinator session id (for session-anchored completion routing). */
|
|
@@ -489,6 +489,16 @@ export interface ProviderModule {
|
|
|
489
489
|
/** Auto-implement spawn config — controls how this provider is invoked for autonomous script generation */
|
|
490
490
|
autoImpl?: ProviderAutoImplSpawnConfig;
|
|
491
491
|
};
|
|
492
|
+
/**
|
|
493
|
+
* MAGI-KIND-PANEL (model axis): template for expanding an `initialModel` selection
|
|
494
|
+
* into launch args for a CLI provider. `{{model}}` is substituted with the model
|
|
495
|
+
* string; e.g. `['--model', '{{model}}']` for claude-cli → `--model opus`. Applied
|
|
496
|
+
* at session launch when `initialModel` is passed AND this provider is a plain CLI
|
|
497
|
+
* (ACP providers instead route the model through setConfigOption). A CLI provider
|
|
498
|
+
* with no template silently ignores `initialModel` at launch (best-effort; a model
|
|
499
|
+
* request never fails a launch). Absent → no launch-time model selection for CLI.
|
|
500
|
+
*/
|
|
501
|
+
modelLaunchArgs?: string[];
|
|
492
502
|
/** Delay before submitting typed CLI input (provider-specific TUI tuning) */
|
|
493
503
|
sendDelayMs?: number;
|
|
494
504
|
/** Submit key used after typing into CLI PTY (default: carriage return) */
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import type { GitRepoStatus, GitCompactSummary } from './git/git-types.js';
|
|
14
14
|
import type { MeshMissionSummary, MeshMissionSlimSummary } from './mesh/mesh-missions.js';
|
|
15
15
|
import type { MeshMagiActivitySummary } from './mesh/mesh-magi-status.js';
|
|
16
|
-
import type { MagiPanelMap } from '@adhdev/mesh-shared';
|
|
16
|
+
import type { MagiPanelMap, MagiKindPanelMap } from '@adhdev/mesh-shared';
|
|
17
17
|
export interface RepoMesh {
|
|
18
18
|
id: string;
|
|
19
19
|
name: string;
|
|
@@ -536,6 +536,14 @@ export interface LocalMeshConfig {
|
|
|
536
536
|
* Optional: absent on configs written before MAGI existed.
|
|
537
537
|
*/
|
|
538
538
|
magiPanels?: MagiPanelMap;
|
|
539
|
+
/**
|
|
540
|
+
* MAGI-KIND-PANEL: per-task_kind panel bindings (machine-local). Keyed by
|
|
541
|
+
* task_kind (rca / design / claim_audit / freeform); each maps to ≥1
|
|
542
|
+
* `(node × provider × model?)` slot. A `mesh_magi_review` invoked with a bare
|
|
543
|
+
* `task_kind` resolves its panel from here — an unconfigured kind is a hard
|
|
544
|
+
* error, never a synthesized fallback. Optional; absent on pre-feature configs.
|
|
545
|
+
*/
|
|
546
|
+
magiKindPanels?: MagiKindPanelMap;
|
|
539
547
|
}
|
|
540
548
|
export interface LocalMeshEntry {
|
|
541
549
|
id: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adhdev/daemon-core",
|
|
3
|
-
"version": "0.9.82-rc.
|
|
3
|
+
"version": "0.9.82-rc.438",
|
|
4
4
|
"description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"author": "vilmire",
|
|
47
47
|
"license": "AGPL-3.0-or-later",
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@adhdev/mesh-shared": "0.9.82-rc.
|
|
49
|
+
"@adhdev/mesh-shared": "0.9.82-rc.438",
|
|
50
50
|
"@adhdev/session-host-core": "*",
|
|
51
51
|
"@agentclientprotocol/sdk": "^0.16.1",
|
|
52
52
|
"ajv": "^8.20.0",
|
|
@@ -369,6 +369,18 @@ function expandResumeArgs(template: string[] | undefined, sessionId: string): st
|
|
|
369
369
|
return template.map((part) => part === '{{id}}' ? sessionId : part);
|
|
370
370
|
}
|
|
371
371
|
|
|
372
|
+
/**
|
|
373
|
+
* Expand a provider's `modelLaunchArgs` template with the requested model, mirroring
|
|
374
|
+
* expandResumeArgs. `{{model}}` → the trimmed model string. Returns undefined when
|
|
375
|
+
* there is no template or no model (a model request without a template is a no-op —
|
|
376
|
+
* see startSession, where the caller logs the skip). MAGI kind-panel model axis.
|
|
377
|
+
*/
|
|
378
|
+
function expandModelLaunchArgs(template: string[] | undefined, model: string | undefined): string[] | undefined {
|
|
379
|
+
const m = typeof model === 'string' ? model.trim() : '';
|
|
380
|
+
if (!m || !Array.isArray(template) || template.length === 0) return undefined;
|
|
381
|
+
return template.map((part) => part === '{{model}}' ? m : part);
|
|
382
|
+
}
|
|
383
|
+
|
|
372
384
|
function readSubcommandSessionId(args: string[], subcommands: string[]): string | undefined {
|
|
373
385
|
const resumeIndex = args.findIndex((arg) => subcommands.includes(arg));
|
|
374
386
|
if (resumeIndex < 0) return undefined;
|
|
@@ -895,8 +907,23 @@ export class DaemonCliManager {
|
|
|
895
907
|
console.log(colorize('cyan', ` 📦 Using provider: ${provider.name} (${provider.type})`));
|
|
896
908
|
}
|
|
897
909
|
|
|
910
|
+
// ─── Model axis (MAGI kind-panel): expand initialModel → launch args ───
|
|
911
|
+
// For a plain CLI provider the model is selected at spawn time via the manifest's
|
|
912
|
+
// modelLaunchArgs template ('{{model}}' → the requested model). ACP providers took
|
|
913
|
+
// the setConfigOption path above and never reach here. A provider with no template,
|
|
914
|
+
// or no requested model, is a no-op — model selection is best-effort and must never
|
|
915
|
+
// fail a launch. The model args are prepended so a caller's explicit cliArgs (e.g. a
|
|
916
|
+
// resume flag) still win positionally where order matters.
|
|
917
|
+
const modelLaunchArgs = expandModelLaunchArgs(provider?.modelLaunchArgs, initialModel);
|
|
918
|
+
const cliArgsWithModel = modelLaunchArgs
|
|
919
|
+
? [...modelLaunchArgs, ...(cliArgs || [])]
|
|
920
|
+
: cliArgs;
|
|
921
|
+
if (initialModel && !modelLaunchArgs) {
|
|
922
|
+
LOG.warn('CLI', `[${normalizedType}] initialModel='${initialModel}' requested but provider declares no modelLaunchArgs template — launching without model selection.`);
|
|
923
|
+
}
|
|
924
|
+
|
|
898
925
|
// ─── Resolve launch options → provider session binding ───
|
|
899
|
-
const sessionBinding = resolveCliSessionBinding(provider, normalizedType,
|
|
926
|
+
const sessionBinding = resolveCliSessionBinding(provider, normalizedType, cliArgsWithModel, options?.resumeSessionId);
|
|
900
927
|
const resolvedCliArgs = sessionBinding.cliArgs;
|
|
901
928
|
|
|
902
929
|
// If InstanceManager exists, manage as CliProviderInstance unified
|
|
@@ -302,6 +302,48 @@ export const meshCrudHandlers: Record<string, MedFamilyHandler> = {
|
|
|
302
302
|
}
|
|
303
303
|
},
|
|
304
304
|
|
|
305
|
+
// ─── MAGI kind → panel bindings (MAGI-KIND-PANEL, machine-local config) ───
|
|
306
|
+
// Per-task_kind slot lists in ~/.adhdev/meshes.json `magiKindPanels`. Same
|
|
307
|
+
// owner-only gating and structured-error precedent as the magi_panel_* handlers
|
|
308
|
+
// above (not listed in canPeerUsePrivilegedShareCommand → owner-only). set/remove
|
|
309
|
+
// are WRITE commands; list is read-only. normalizeMagiSlots (inside setMagiKindPanel)
|
|
310
|
+
// surfaces invalid_magi_kind_panel: … messages verbatim for the editor.
|
|
311
|
+
magi_kind_panel_list: async (_ctx: MedFamilyContext, _args: any) => {
|
|
312
|
+
try {
|
|
313
|
+
const { listMagiKindPanels } = await import('../../config/mesh-config.js');
|
|
314
|
+
return { success: true, kindPanels: listMagiKindPanels() };
|
|
315
|
+
} catch (e: any) {
|
|
316
|
+
return { success: false, error: e.message };
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
|
|
320
|
+
magi_kind_panel_set: async (_ctx: MedFamilyContext, args: any) => {
|
|
321
|
+
const kind = typeof args?.kind === 'string' ? args.kind.trim() : '';
|
|
322
|
+
if (!kind) return { success: false, error: 'invalid_magi_kind_panel: task_kind is required' };
|
|
323
|
+
try {
|
|
324
|
+
const { setMagiKindPanel } = await import('../../config/mesh-config.js');
|
|
325
|
+
// normalizeMagiTaskKindKey + normalizeMagiSlots (inside setMagiKindPanel)
|
|
326
|
+
// validate the kind and each slot (provider required; model/nodeId optional;
|
|
327
|
+
// replica counts clamped). Structured errors flow back as `error`.
|
|
328
|
+
const slots = setMagiKindPanel(kind, args?.slots);
|
|
329
|
+
return { success: true, kind, slots };
|
|
330
|
+
} catch (e: any) {
|
|
331
|
+
return { success: false, error: e.message };
|
|
332
|
+
}
|
|
333
|
+
},
|
|
334
|
+
|
|
335
|
+
magi_kind_panel_remove: async (_ctx: MedFamilyContext, args: any) => {
|
|
336
|
+
const kind = typeof args?.kind === 'string' ? args.kind.trim() : '';
|
|
337
|
+
if (!kind) return { success: false, error: 'invalid_magi_kind_panel: task_kind is required' };
|
|
338
|
+
try {
|
|
339
|
+
const { removeMagiKindPanel } = await import('../../config/mesh-config.js');
|
|
340
|
+
const removed = removeMagiKindPanel(kind);
|
|
341
|
+
return { success: true, removed };
|
|
342
|
+
} catch (e: any) {
|
|
343
|
+
return { success: false, error: e.message };
|
|
344
|
+
}
|
|
345
|
+
},
|
|
346
|
+
|
|
305
347
|
add_mesh_node: async (ctx: MedFamilyContext, args: any) => {
|
|
306
348
|
const meshId = typeof args?.meshId === 'string' ? args.meshId.trim() : '';
|
|
307
349
|
const workspace = typeof args?.workspace === 'string' ? args.workspace.trim() : '';
|
|
@@ -22,7 +22,7 @@ import type {
|
|
|
22
22
|
RepoMeshHostMetadata,
|
|
23
23
|
RepoMeshDaemonRole,
|
|
24
24
|
} from '../repo-mesh-types.js';
|
|
25
|
-
import type { MagiPanel, MagiPanelMember, MagiPanelDefaultKind } from '@adhdev/mesh-shared';
|
|
25
|
+
import type { MagiPanel, MagiPanelMember, MagiPanelDefaultKind, MagiKindPanelMap, MagiSlot, MagiTaskKind } from '@adhdev/mesh-shared';
|
|
26
26
|
import { mergeAndNormalizePolicy } from '../repo-mesh-types.js';
|
|
27
27
|
import { createDefaultMeshHostMetadata } from '../mesh/mesh-host-ownership.js';
|
|
28
28
|
|
|
@@ -650,11 +650,13 @@ export function normalizeMagiPanel(config: unknown): MagiPanel {
|
|
|
650
650
|
throw new Error(`invalid_magi_panel: member[${idx}].provider is required`);
|
|
651
651
|
}
|
|
652
652
|
const nodeId = typeof m.nodeId === 'string' && m.nodeId.trim() ? m.nodeId.trim() : undefined;
|
|
653
|
+
const model = typeof m.model === 'string' && m.model.trim() ? m.model.trim() : undefined;
|
|
653
654
|
const capabilityTags = normalizeCapabilityTags(m.capabilityTags);
|
|
654
655
|
const n = normalizeReplicaCount(m.n);
|
|
655
656
|
return {
|
|
656
657
|
provider,
|
|
657
658
|
...(nodeId ? { nodeId } : {}),
|
|
659
|
+
...(model ? { model } : {}),
|
|
658
660
|
...(capabilityTags ? { capabilityTags } : {}),
|
|
659
661
|
...(n !== undefined ? { n } : {}),
|
|
660
662
|
};
|
|
@@ -726,3 +728,99 @@ export function removeMagiPanel(name: string): boolean {
|
|
|
726
728
|
saveMeshConfig(stored);
|
|
727
729
|
return true;
|
|
728
730
|
}
|
|
731
|
+
|
|
732
|
+
// ─── MAGI kind → panel bindings (MAGI-KIND-PANEL) ─────────
|
|
733
|
+
//
|
|
734
|
+
// Per-task_kind slot lists (machine-local, meshes.json `magiKindPanels`). A bare
|
|
735
|
+
// `mesh_magi_review({task_kind})` resolves its panel exclusively from here — an
|
|
736
|
+
// unconfigured kind is a hard error, never a synthesized fallback. Mirrors the named
|
|
737
|
+
// panel accessors above (normalize / list / get / set / remove).
|
|
738
|
+
|
|
739
|
+
/** The task kinds a kind-panel can be bound to. Unlike a named panel's defaultKind,
|
|
740
|
+
* 'freeform' IS a valid kind-panel key (this is a direct kind→slots binding). */
|
|
741
|
+
const MAGI_KIND_PANEL_KINDS: readonly MagiTaskKind[] = ['claim_audit', 'rca', 'design', 'freeform'];
|
|
742
|
+
const MAX_MAGI_KIND_SLOTS = 24;
|
|
743
|
+
|
|
744
|
+
function normalizeMagiTaskKindKey(raw: unknown): MagiTaskKind {
|
|
745
|
+
const s = typeof raw === 'string' ? raw.trim().toLowerCase() : '';
|
|
746
|
+
if (!(MAGI_KIND_PANEL_KINDS as readonly string[]).includes(s)) {
|
|
747
|
+
throw new Error(`invalid_magi_kind_panel: task_kind must be one of ${MAGI_KIND_PANEL_KINDS.join(' / ')} (got '${s || '(empty)'}')`);
|
|
748
|
+
}
|
|
749
|
+
return s as MagiTaskKind;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
/**
|
|
753
|
+
* Validate + normalize a kind-panel's slots. Mirrors normalizeMagiPanel's member
|
|
754
|
+
* normalization: provider required per slot, trims strings, drops empties, clamps
|
|
755
|
+
* replica counts, and additionally carries an optional per-slot `model`. Throws on
|
|
756
|
+
* structurally invalid input (empty list / no provider) so the write returns a clear
|
|
757
|
+
* error. Returns the normalized slot array.
|
|
758
|
+
*/
|
|
759
|
+
export function normalizeMagiSlots(slots: unknown): MagiSlot[] {
|
|
760
|
+
if (!Array.isArray(slots) || slots.length === 0) {
|
|
761
|
+
throw new Error('invalid_magi_kind_panel: slots must be a non-empty array');
|
|
762
|
+
}
|
|
763
|
+
if (slots.length > MAX_MAGI_KIND_SLOTS) {
|
|
764
|
+
throw new Error(`invalid_magi_kind_panel: too many slots (max ${MAX_MAGI_KIND_SLOTS})`);
|
|
765
|
+
}
|
|
766
|
+
return slots.map((entry, idx) => {
|
|
767
|
+
if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
|
|
768
|
+
throw new Error(`invalid_magi_kind_panel: slot[${idx}] must be an object`);
|
|
769
|
+
}
|
|
770
|
+
const s = entry as Record<string, unknown>;
|
|
771
|
+
const provider = typeof s.provider === 'string' ? s.provider.trim() : '';
|
|
772
|
+
if (!provider) {
|
|
773
|
+
throw new Error(`invalid_magi_kind_panel: slot[${idx}].provider is required`);
|
|
774
|
+
}
|
|
775
|
+
const nodeId = typeof s.nodeId === 'string' && s.nodeId.trim() ? s.nodeId.trim() : undefined;
|
|
776
|
+
const model = typeof s.model === 'string' && s.model.trim() ? s.model.trim() : undefined;
|
|
777
|
+
const capabilityTags = normalizeCapabilityTags(s.capabilityTags);
|
|
778
|
+
const n = normalizeReplicaCount(s.n);
|
|
779
|
+
return {
|
|
780
|
+
provider,
|
|
781
|
+
...(nodeId ? { nodeId } : {}),
|
|
782
|
+
...(model ? { model } : {}),
|
|
783
|
+
...(capabilityTags ? { capabilityTags } : {}),
|
|
784
|
+
...(n !== undefined ? { n } : {}),
|
|
785
|
+
};
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
/** All configured kind-panels (machine-local), keyed by task_kind. Empty when none. */
|
|
790
|
+
export function listMagiKindPanels(): MagiKindPanelMap {
|
|
791
|
+
return loadMeshConfig().magiKindPanels ?? {};
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
/** The slot list for one task_kind, or undefined when the kind is not configured. */
|
|
795
|
+
export function getMagiKindPanel(kind: string): MagiSlot[] | undefined {
|
|
796
|
+
let key: MagiTaskKind;
|
|
797
|
+
try { key = normalizeMagiTaskKindKey(kind); } catch { return undefined; }
|
|
798
|
+
return loadMeshConfig().magiKindPanels?.[key];
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
/**
|
|
802
|
+
* Upsert the slot list for one task_kind. Unlike named panels this ALWAYS overwrites
|
|
803
|
+
* (a kind has exactly one binding) — the editor pushes the full desired slot set.
|
|
804
|
+
* Returns the normalized, persisted slots.
|
|
805
|
+
*/
|
|
806
|
+
export function setMagiKindPanel(kind: string, slots: unknown): MagiSlot[] {
|
|
807
|
+
const key = normalizeMagiTaskKindKey(kind);
|
|
808
|
+
const normalized = normalizeMagiSlots(slots);
|
|
809
|
+
const stored = loadMeshConfig();
|
|
810
|
+
const map = stored.magiKindPanels ?? {};
|
|
811
|
+
map[key] = normalized;
|
|
812
|
+
stored.magiKindPanels = map;
|
|
813
|
+
saveMeshConfig(stored);
|
|
814
|
+
return normalized;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
/** Remove the binding for one task_kind. Returns true when a binding was removed. */
|
|
818
|
+
export function removeMagiKindPanel(kind: string): boolean {
|
|
819
|
+
let key: MagiTaskKind;
|
|
820
|
+
try { key = normalizeMagiTaskKindKey(kind); } catch { return false; }
|
|
821
|
+
const stored = loadMeshConfig();
|
|
822
|
+
if (!stored.magiKindPanels || !stored.magiKindPanels[key]) return false;
|
|
823
|
+
delete stored.magiKindPanels[key];
|
|
824
|
+
saveMeshConfig(stored);
|
|
825
|
+
return true;
|
|
826
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -196,6 +196,7 @@ export {
|
|
|
196
196
|
listMeshes, getMesh, getMeshByRepo, createMesh, updateMesh, deleteMesh,
|
|
197
197
|
addNode, removeNode, updateNode, normalizeRepoIdentity,
|
|
198
198
|
listMagiPanels, getMagiPanel, upsertMagiPanel, removeMagiPanel, normalizeMagiPanel,
|
|
199
|
+
listMagiKindPanels, getMagiKindPanel, setMagiKindPanel, removeMagiKindPanel, normalizeMagiSlots,
|
|
199
200
|
} from './config/mesh-config.js';
|
|
200
201
|
export type { CreateMeshOptions, UpdateMeshOptions, AddNodeOptions } from './config/mesh-config.js';
|
|
201
202
|
// MAGI panel / common-output / synthesis types (re-exported from the mesh-shared
|
|
@@ -1538,6 +1538,9 @@ async function maybeAutoLaunchOneQueueSession(components: DaemonComponents, mesh
|
|
|
1538
1538
|
cliType: resolved.providerType,
|
|
1539
1539
|
dir: node.workspace,
|
|
1540
1540
|
settings: remoteSettings,
|
|
1541
|
+
// MAGI-KIND-PANEL model axis: forward the task's model override so the
|
|
1542
|
+
// remote worker session launches with it (initialModel). Best-effort.
|
|
1543
|
+
...(typeof task.model === 'string' && task.model.trim() ? { initialModel: task.model.trim() } : {}),
|
|
1541
1544
|
});
|
|
1542
1545
|
} catch (e: any) {
|
|
1543
1546
|
markAutoLaunch(meshId, task.id, { status: 'failed', reason: `remote_launch_dispatch_failed: ${e?.message || String(e)}`, nodeId, providerType: resolved.providerType });
|
|
@@ -1567,6 +1570,9 @@ async function maybeAutoLaunchOneQueueSession(components: DaemonComponents, mesh
|
|
|
1567
1570
|
cliType: resolved.providerType,
|
|
1568
1571
|
dir: node.workspace,
|
|
1569
1572
|
settings: launchSettings,
|
|
1573
|
+
// MAGI-KIND-PANEL model axis: local launch forwards the task's model
|
|
1574
|
+
// override as initialModel (CLI → modelLaunchArgs; ACP → setConfigOption).
|
|
1575
|
+
...(typeof task.model === 'string' && task.model.trim() ? { initialModel: task.model.trim() } : {}),
|
|
1570
1576
|
});
|
|
1571
1577
|
if (!launchResult?.success) {
|
|
1572
1578
|
const reason = launchResult?.error || 'launch_cli_failed';
|
|
@@ -502,6 +502,14 @@ export interface MeshWorkQueueEntry {
|
|
|
502
502
|
* replicas. Absent on ordinary tasks. Rides in the payload JSON (no column).
|
|
503
503
|
*/
|
|
504
504
|
consensusGroupId?: string;
|
|
505
|
+
/**
|
|
506
|
+
* MAGI-KIND-PANEL (model axis): model override for the session that executes this
|
|
507
|
+
* task. When the task auto-launches a session, this is passed to launch_cli as
|
|
508
|
+
* `initialModel` (ACP → setConfigOption; CLI → modelLaunchArgs template). Absent on
|
|
509
|
+
* ordinary tasks. Rides in the payload JSON (no column). Best-effort — a provider
|
|
510
|
+
* that cannot honor the model still runs the task (never a fatal launch error).
|
|
511
|
+
*/
|
|
512
|
+
model?: string;
|
|
505
513
|
/**
|
|
506
514
|
* M1: why this task is held back (e.g. "dependency_failed:<taskId>").
|
|
507
515
|
* Only set by the system on dependency failure under the 'block' policy;
|
|
@@ -772,6 +780,8 @@ export function enqueueTask(
|
|
|
772
780
|
missionId?: string;
|
|
773
781
|
/** MAGI: consensus group id shared by every replica of a mesh_magi_review fan-out. */
|
|
774
782
|
consensusGroupId?: string;
|
|
783
|
+
/** MAGI-KIND-PANEL: model override forwarded to the executing session's launch (initialModel). */
|
|
784
|
+
model?: string;
|
|
775
785
|
/** Explicit task id for batch/template flows (M5). Random UUID when omitted. */
|
|
776
786
|
id?: string;
|
|
777
787
|
/** (3) Originating coordinator session id (for session-anchored completion routing). */
|
|
@@ -816,6 +826,7 @@ export function enqueueTask(
|
|
|
816
826
|
...(dependsOn.length > 0 ? { dependsOn } : {}),
|
|
817
827
|
...(typeof opts?.missionId === 'string' && opts.missionId.trim() ? { missionId: opts.missionId.trim() } : {}),
|
|
818
828
|
...(typeof opts?.consensusGroupId === 'string' && opts.consensusGroupId.trim() ? { consensusGroupId: opts.consensusGroupId.trim() } : {}),
|
|
829
|
+
...(typeof opts?.model === 'string' && opts.model.trim() ? { model: opts.model.trim() } : {}),
|
|
819
830
|
...(typeof opts?.sourceCoordinatorSessionId === 'string' && opts.sourceCoordinatorSessionId.trim()
|
|
820
831
|
? { sourceCoordinatorSessionId: opts.sourceCoordinatorSessionId.trim() }
|
|
821
832
|
: {}),
|
|
@@ -594,6 +594,16 @@ export interface ProviderModule {
|
|
|
594
594
|
/** Auto-implement spawn config — controls how this provider is invoked for autonomous script generation */
|
|
595
595
|
autoImpl?: ProviderAutoImplSpawnConfig;
|
|
596
596
|
};
|
|
597
|
+
/**
|
|
598
|
+
* MAGI-KIND-PANEL (model axis): template for expanding an `initialModel` selection
|
|
599
|
+
* into launch args for a CLI provider. `{{model}}` is substituted with the model
|
|
600
|
+
* string; e.g. `['--model', '{{model}}']` for claude-cli → `--model opus`. Applied
|
|
601
|
+
* at session launch when `initialModel` is passed AND this provider is a plain CLI
|
|
602
|
+
* (ACP providers instead route the model through setConfigOption). A CLI provider
|
|
603
|
+
* with no template silently ignores `initialModel` at launch (best-effort; a model
|
|
604
|
+
* request never fails a launch). Absent → no launch-time model selection for CLI.
|
|
605
|
+
*/
|
|
606
|
+
modelLaunchArgs?: string[];
|
|
597
607
|
/** Delay before submitting typed CLI input (provider-specific TUI tuning) */
|
|
598
608
|
sendDelayMs?: number;
|
|
599
609
|
/** Submit key used after typing into CLI PTY (default: carriage return) */
|
|
@@ -124,6 +124,11 @@
|
|
|
124
124
|
"minimum": 0,
|
|
125
125
|
"description": "Delay between pasting prompt text and pressing Enter."
|
|
126
126
|
},
|
|
127
|
+
"modelLaunchArgs": {
|
|
128
|
+
"type": "array",
|
|
129
|
+
"items": { "type": "string" },
|
|
130
|
+
"description": "Template for expanding an initialModel selection into launch args. '{{model}}' is substituted with the model string (e.g. ['--model', '{{model}}'] → --model opus). Applied at launch when a model is requested for this CLI provider (MAGI kind-panel model axis). Absent → no launch-time model selection."
|
|
131
|
+
},
|
|
127
132
|
"scriptCallBudgetMs": {
|
|
128
133
|
"type": "integer",
|
|
129
134
|
"minimum": 1,
|
package/src/repo-mesh-types.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import type { GitRepoStatus, GitCompactSummary } from './git/git-types.js';
|
|
15
15
|
import type { MeshMissionSummary, MeshMissionSlimSummary } from './mesh/mesh-missions.js';
|
|
16
16
|
import type { MeshMagiActivitySummary } from './mesh/mesh-magi-status.js';
|
|
17
|
-
import type { MagiPanelMap } from '@adhdev/mesh-shared';
|
|
17
|
+
import type { MagiPanelMap, MagiKindPanelMap } from '@adhdev/mesh-shared';
|
|
18
18
|
|
|
19
19
|
// ─── Core Mesh Types ────────────────────────────
|
|
20
20
|
|
|
@@ -803,6 +803,14 @@ export interface LocalMeshConfig {
|
|
|
803
803
|
* Optional: absent on configs written before MAGI existed.
|
|
804
804
|
*/
|
|
805
805
|
magiPanels?: MagiPanelMap;
|
|
806
|
+
/**
|
|
807
|
+
* MAGI-KIND-PANEL: per-task_kind panel bindings (machine-local). Keyed by
|
|
808
|
+
* task_kind (rca / design / claim_audit / freeform); each maps to ≥1
|
|
809
|
+
* `(node × provider × model?)` slot. A `mesh_magi_review` invoked with a bare
|
|
810
|
+
* `task_kind` resolves its panel from here — an unconfigured kind is a hard
|
|
811
|
+
* error, never a synthesized fallback. Optional; absent on pre-feature configs.
|
|
812
|
+
*/
|
|
813
|
+
magiKindPanels?: MagiKindPanelMap;
|
|
806
814
|
}
|
|
807
815
|
|
|
808
816
|
export interface LocalMeshEntry {
|