@jmanuelcorral/openteam 0.9.4 → 0.11.0
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/AGENTS.md +1 -1
- package/README.es.md +8 -5
- package/README.md +16 -5
- package/dist/cli.js +475 -102
- package/dist/commands/dispatch.d.ts.map +1 -1
- package/dist/commands/doctor.d.ts +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/local.d.ts +13 -0
- package/dist/commands/local.d.ts.map +1 -1
- package/dist/commands/rolesInit.d.ts +55 -0
- package/dist/commands/rolesInit.d.ts.map +1 -0
- package/dist/commands/setup.d.ts +17 -0
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/config/errors.d.ts.map +1 -1
- package/dist/config/schema.d.ts +2 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +222 -92
- package/dist/messages/commands.d.ts +50 -2
- package/dist/messages/commands.d.ts.map +1 -1
- package/dist/orchestrator/roles.d.ts +20 -0
- package/dist/orchestrator/roles.d.ts.map +1 -1
- package/dist/orchestrator/runtimeSelection.d.ts.map +1 -1
- package/dist/plugin/registerCastTool.d.ts +19 -0
- package/dist/plugin/registerCastTool.d.ts.map +1 -1
- package/dist/router/chooseModel.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -95,7 +95,8 @@ var AgentRoleProfileSchema = z.object({
|
|
|
95
95
|
preferredFrontierModels: z.array(z.union([modelSelectionSchema, z.literal("auto")])),
|
|
96
96
|
localFirst: z.boolean(),
|
|
97
97
|
requiresLocalRuntime: z.boolean().optional(),
|
|
98
|
-
localRuntimes: z.array(z.enum(["ollama", "lmstudio", "foundry-local", "lemonade"])).optional()
|
|
98
|
+
localRuntimes: z.array(z.enum(["ollama", "lmstudio", "foundry-local", "lemonade"])).optional(),
|
|
99
|
+
localModels: z.partialRecord(z.enum(["ollama", "lmstudio", "foundry-local", "lemonade"]), z.string().min(1)).optional()
|
|
99
100
|
}).strict();
|
|
100
101
|
var TEAM_ROLES = {
|
|
101
102
|
architect: {
|
|
@@ -386,6 +387,9 @@ var OrchestratorRolesSchema = z2.record(z2.string().min(1), z2.unknown()).defaul
|
|
|
386
387
|
if (parsed.data.localRuntimes !== undefined) {
|
|
387
388
|
profile.localRuntimes = parsed.data.localRuntimes;
|
|
388
389
|
}
|
|
390
|
+
if (parsed.data.localModels !== undefined) {
|
|
391
|
+
profile.localModels = parsed.data.localModels;
|
|
392
|
+
}
|
|
389
393
|
parsedRoles[roleID] = profile;
|
|
390
394
|
}
|
|
391
395
|
return parsedRoles;
|
|
@@ -468,13 +472,23 @@ var OpenTeamConfigObjectSchema = z2.object({
|
|
|
468
472
|
localDefault: ModelRefSchema.nullable().default(null),
|
|
469
473
|
trivialPromptMaxChars: z2.number().int().positive().default(280),
|
|
470
474
|
frontierPromptMinChars: z2.number().int().positive().default(2000),
|
|
471
|
-
frontierOnly: z2.boolean().default(false)
|
|
472
|
-
|
|
475
|
+
frontierOnly: z2.boolean().default(false),
|
|
476
|
+
localOnly: z2.boolean().default(false)
|
|
477
|
+
}).strict().superRefine((router, ctx) => {
|
|
478
|
+
if (router.frontierOnly && router.localOnly) {
|
|
479
|
+
ctx.addIssue({
|
|
480
|
+
code: "custom",
|
|
481
|
+
path: ["localOnly"],
|
|
482
|
+
message: "router.localOnly and router.frontierOnly cannot both be true"
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
}).default({
|
|
473
486
|
mode: "balanced",
|
|
474
487
|
localDefault: null,
|
|
475
488
|
trivialPromptMaxChars: 280,
|
|
476
489
|
frontierPromptMinChars: 2000,
|
|
477
|
-
frontierOnly: false
|
|
490
|
+
frontierOnly: false,
|
|
491
|
+
localOnly: false
|
|
478
492
|
}),
|
|
479
493
|
local: z2.object({
|
|
480
494
|
runtimes: z2.array(LocalRuntimeSchema).default([])
|
|
@@ -2650,7 +2664,8 @@ var KNOWN_CONFIG_KEYS_BY_PATH = new Map([
|
|
|
2650
2664
|
"localDefault",
|
|
2651
2665
|
"trivialPromptMaxChars",
|
|
2652
2666
|
"frontierPromptMinChars",
|
|
2653
|
-
"frontierOnly"
|
|
2667
|
+
"frontierOnly",
|
|
2668
|
+
"localOnly"
|
|
2654
2669
|
]
|
|
2655
2670
|
],
|
|
2656
2671
|
["router.localDefault", MODEL_REF_KEYS],
|
|
@@ -5790,6 +5805,16 @@ function chooseModel(input) {
|
|
|
5790
5805
|
if (override === "alwaysFrontier") {
|
|
5791
5806
|
return finalizeDecision(input, tier, frontier, budgetAction, decision(frontier.model, "frontier", ["explicit-always-frontier"], []));
|
|
5792
5807
|
}
|
|
5808
|
+
if (input.config.router.localOnly) {
|
|
5809
|
+
if (local === null) {
|
|
5810
|
+
return finalizeDecision(input, tier, frontier, budgetAction, blockedDecision(frontier.model, ["router-local-only", "forced-local-none-configured"], "forced-local-none-configured"));
|
|
5811
|
+
}
|
|
5812
|
+
return finalizeDecision(input, tier, frontier, budgetAction, resolveLocalPrimary(input, local, frontier.model, {
|
|
5813
|
+
baseRationale: ["router-local-only"],
|
|
5814
|
+
allowFrontier: false,
|
|
5815
|
+
noLocalRationale: "forced-local-unavailable"
|
|
5816
|
+
}));
|
|
5817
|
+
}
|
|
5793
5818
|
if (input.config.router.frontierOnly) {
|
|
5794
5819
|
return finalizeDecision(input, tier, frontier, budgetAction, decision(frontier.model, "frontier", ["router-frontier-only"], []));
|
|
5795
5820
|
}
|
|
@@ -5900,6 +5925,10 @@ function configuredRuntime(runtimeId, config) {
|
|
|
5900
5925
|
function runtimeIdOfModel(model, config) {
|
|
5901
5926
|
return config.local.runtimes.find((runtime) => sameModel(runtime.defaultModel, model))?.id;
|
|
5902
5927
|
}
|
|
5928
|
+
function roleLocalModel(role, runtimeId, fallback) {
|
|
5929
|
+
const pinned = role.localModels?.[runtimeId];
|
|
5930
|
+
return pinned === undefined ? fallback : { providerID: runtimeId, modelID: pinned };
|
|
5931
|
+
}
|
|
5903
5932
|
function selectDispatchRuntime(role, decision2, reachable, config) {
|
|
5904
5933
|
if (decision2.routeKind !== "local") {
|
|
5905
5934
|
return { runtimeId: undefined, decision: decision2 };
|
|
@@ -5914,15 +5943,25 @@ function selectDispatchRuntime(role, decision2, reachable, config) {
|
|
|
5914
5943
|
if (runtime === undefined) {
|
|
5915
5944
|
continue;
|
|
5916
5945
|
}
|
|
5917
|
-
const model = runtime.defaultModel;
|
|
5946
|
+
const model = roleLocalModel(role, runtimeId, runtime.defaultModel);
|
|
5918
5947
|
return {
|
|
5919
5948
|
runtimeId,
|
|
5920
5949
|
decision: { ...decision2, selected: model }
|
|
5921
5950
|
};
|
|
5922
5951
|
}
|
|
5923
5952
|
}
|
|
5953
|
+
const resolvedRuntimeId = runtimeIdOfModel(decision2.selected, config);
|
|
5954
|
+
if (resolvedRuntimeId !== undefined) {
|
|
5955
|
+
const pinned = roleLocalModel(role, resolvedRuntimeId, decision2.selected);
|
|
5956
|
+
if (pinned !== decision2.selected) {
|
|
5957
|
+
return {
|
|
5958
|
+
runtimeId: resolvedRuntimeId,
|
|
5959
|
+
decision: { ...decision2, selected: pinned }
|
|
5960
|
+
};
|
|
5961
|
+
}
|
|
5962
|
+
}
|
|
5924
5963
|
return {
|
|
5925
|
-
runtimeId:
|
|
5964
|
+
runtimeId: resolvedRuntimeId,
|
|
5926
5965
|
decision: decision2
|
|
5927
5966
|
};
|
|
5928
5967
|
}
|
|
@@ -7138,6 +7177,84 @@ function activityEventFrom(event, now) {
|
|
|
7138
7177
|
// src/plugin/commandTool.ts
|
|
7139
7178
|
import { tool } from "@opencode-ai/plugin";
|
|
7140
7179
|
|
|
7180
|
+
// src/messages/commands.ts
|
|
7181
|
+
var clearCacheMessages = {
|
|
7182
|
+
header: "openteam clear-cache — frozen plugin cache entries:",
|
|
7183
|
+
columns: {
|
|
7184
|
+
specDir: "spec dir",
|
|
7185
|
+
pinned: "spec-pinned",
|
|
7186
|
+
installed: "installed",
|
|
7187
|
+
mtime: "mtime"
|
|
7188
|
+
},
|
|
7189
|
+
reparseSkipSuffix: " [SKIP — reparse point]",
|
|
7190
|
+
deletedLabel: "deleted.",
|
|
7191
|
+
lockedLabel: (message) => `[LOCKED] ${message}`,
|
|
7192
|
+
pathOutsideWarning: (specDir, absolutePath) => ` ⚠ ${specDir}: path outside cacheRoot (${absolutePath}), skipped.`,
|
|
7193
|
+
processed: (count) => `${count} entry(ies) processed.`,
|
|
7194
|
+
found: (count) => `${count} entry(ies) found. Use --delete to remove them.`
|
|
7195
|
+
};
|
|
7196
|
+
var baselineMessages = {
|
|
7197
|
+
effectiveAuto: "cheapest-capable (auto)",
|
|
7198
|
+
pinnedSuffix: (ref) => `${ref} (pinned)`,
|
|
7199
|
+
summary: (params) => [
|
|
7200
|
+
"openteam baseline:",
|
|
7201
|
+
` mode: ${params.mode}`,
|
|
7202
|
+
` pinned: ${params.pinned}`,
|
|
7203
|
+
` hardDefault: ${params.hardDefault}`,
|
|
7204
|
+
` effective: ${params.effective}`
|
|
7205
|
+
],
|
|
7206
|
+
invalidModel: (input) => `Invalid model "${input}". Use the provider/model format, e.g. anthropic/claude-sonnet-4-5.`,
|
|
7207
|
+
pinnedTo: (ref) => `Baseline pinned to ${ref} (pinned mode).`,
|
|
7208
|
+
autoMode: "Baseline set to auto mode (cheapest-capable)."
|
|
7209
|
+
};
|
|
7210
|
+
var localMessages = {
|
|
7211
|
+
help: {
|
|
7212
|
+
status: " openteam local status Show the routing mode (local-first / local-only / frontier-only)",
|
|
7213
|
+
off: " openteam local off Use frontier models only (no local runtime)",
|
|
7214
|
+
only: " openteam local only Use local models only (never frontier)",
|
|
7215
|
+
on: " openteam local on Re-enable local-first routing"
|
|
7216
|
+
},
|
|
7217
|
+
noRuntimes: "none",
|
|
7218
|
+
modeFrontierOnly: "frontier-only (frontierOnly)",
|
|
7219
|
+
modeLocalOnly: "local-only (localOnly)",
|
|
7220
|
+
modeLocalFirst: "local-first",
|
|
7221
|
+
summary: (params) => [
|
|
7222
|
+
"openteam local:",
|
|
7223
|
+
` mode: ${params.mode}`,
|
|
7224
|
+
` frontierOnly: ${params.frontierOnly}`,
|
|
7225
|
+
` localOnly: ${params.localOnly}`,
|
|
7226
|
+
` privacy: ${params.privacy}`,
|
|
7227
|
+
` runtimes: ${params.runtimes}`
|
|
7228
|
+
],
|
|
7229
|
+
frontierOnlyNoChange: "No change: already in frontier-only mode.",
|
|
7230
|
+
privacyAdjustedNote: " Privacy adjusted to 'consentBeforeFrontier' (forceLocalOnSensitive requires a local runtime).",
|
|
7231
|
+
frontierOnlyEnabled: "Frontier-only mode enabled (frontierOnly=true, localOnly=false).",
|
|
7232
|
+
localOnlyNoRuntimes: "Cannot enable local-only mode: no enabled local runtime is configured. Run 'openteam setup' or enable a local runtime in .opencode/openteam.json first.",
|
|
7233
|
+
localOnlyNoChange: "No change: already in local-only mode.",
|
|
7234
|
+
localOnlyEnabled: "Local-only mode enabled (localOnly=true, frontierOnly=false).",
|
|
7235
|
+
localFirstNoChange: "No change: local-first routing is already active.",
|
|
7236
|
+
localFirstReEnabled: "Local-first routing re-enabled (frontierOnly=false, localOnly=false). Make sure a local runtime is reachable.",
|
|
7237
|
+
unknownSubcommand: (subcommand, help) => `Unknown local subcommand: ${subcommand}
|
|
7238
|
+
|
|
7239
|
+
${help}`
|
|
7240
|
+
};
|
|
7241
|
+
var migrateMessages = {
|
|
7242
|
+
header: "openteam migrate:",
|
|
7243
|
+
nothingToMigrate: " nothing to migrate — the P15b layout is already in place.",
|
|
7244
|
+
counts: (params) => [
|
|
7245
|
+
` moved: ${params.moved} file(s)`,
|
|
7246
|
+
` deduped: ${params.deduped} file(s) (destination already identical)`,
|
|
7247
|
+
` conflicts: ${params.conflicts} file(s)`
|
|
7248
|
+
],
|
|
7249
|
+
relocatedHeader: " relocated:",
|
|
7250
|
+
relocatedEntry: (from, to, deduped) => ` · ${from} → ${to}${deduped ? " (deduped)" : ""}`,
|
|
7251
|
+
conflictsHeader: " ⚠ left in place (destination exists with different content — no data lost):",
|
|
7252
|
+
conflictEntry: (from, to) => ` · ${from} → ${to}`,
|
|
7253
|
+
manualWorktreesHeader: " ⚠ legacy git worktree(s) need a manual move (run `git worktree move`):",
|
|
7254
|
+
manualWorktreeEntry: (label, from, to) => ` · ${label}: ${from} → ${to}`,
|
|
7255
|
+
success: " ✓ machine-local runtime output relocated under .opencode/openteam-local/."
|
|
7256
|
+
};
|
|
7257
|
+
|
|
7141
7258
|
// src/orchestrator/worktreeReconciler.ts
|
|
7142
7259
|
function planOne(wt) {
|
|
7143
7260
|
const base = { runID: wt.runID, path: wt.path };
|
|
@@ -7691,70 +7808,6 @@ function diagnoseAgentModels(files, context) {
|
|
|
7691
7808
|
});
|
|
7692
7809
|
}
|
|
7693
7810
|
|
|
7694
|
-
// src/messages/commands.ts
|
|
7695
|
-
var clearCacheMessages = {
|
|
7696
|
-
header: "openteam clear-cache — frozen plugin cache entries:",
|
|
7697
|
-
columns: {
|
|
7698
|
-
specDir: "spec dir",
|
|
7699
|
-
pinned: "spec-pinned",
|
|
7700
|
-
installed: "installed",
|
|
7701
|
-
mtime: "mtime"
|
|
7702
|
-
},
|
|
7703
|
-
reparseSkipSuffix: " [SKIP — reparse point]",
|
|
7704
|
-
deletedLabel: "deleted.",
|
|
7705
|
-
lockedLabel: (message) => `[LOCKED] ${message}`,
|
|
7706
|
-
pathOutsideWarning: (specDir, absolutePath) => ` ⚠ ${specDir}: path outside cacheRoot (${absolutePath}), skipped.`,
|
|
7707
|
-
processed: (count) => `${count} entry(ies) processed.`,
|
|
7708
|
-
found: (count) => `${count} entry(ies) found. Use --delete to remove them.`
|
|
7709
|
-
};
|
|
7710
|
-
var baselineMessages = {
|
|
7711
|
-
effectiveAuto: "cheapest-capable (auto)",
|
|
7712
|
-
pinnedSuffix: (ref) => `${ref} (pinned)`,
|
|
7713
|
-
summary: (params) => [
|
|
7714
|
-
"openteam baseline:",
|
|
7715
|
-
` mode: ${params.mode}`,
|
|
7716
|
-
` pinned: ${params.pinned}`,
|
|
7717
|
-
` hardDefault: ${params.hardDefault}`,
|
|
7718
|
-
` effective: ${params.effective}`
|
|
7719
|
-
],
|
|
7720
|
-
invalidModel: (input) => `Invalid model "${input}". Use the provider/model format, e.g. anthropic/claude-sonnet-4-5.`,
|
|
7721
|
-
pinnedTo: (ref) => `Baseline pinned to ${ref} (pinned mode).`,
|
|
7722
|
-
autoMode: "Baseline set to auto mode (cheapest-capable)."
|
|
7723
|
-
};
|
|
7724
|
-
var localMessages = {
|
|
7725
|
-
noRuntimes: "none",
|
|
7726
|
-
modeFrontierOnly: "frontier-only (frontierOnly)",
|
|
7727
|
-
modeLocalFirst: "local-first",
|
|
7728
|
-
summary: (params) => [
|
|
7729
|
-
"openteam local:",
|
|
7730
|
-
` mode: ${params.mode}`,
|
|
7731
|
-
` frontierOnly: ${params.frontierOnly}`,
|
|
7732
|
-
` privacy: ${params.privacy}`,
|
|
7733
|
-
` runtimes: ${params.runtimes}`
|
|
7734
|
-
],
|
|
7735
|
-
frontierOnlyNoChange: "No change: already in frontier-only mode.",
|
|
7736
|
-
privacyAdjustedNote: " Privacy adjusted to 'consentBeforeFrontier' (forceLocalOnSensitive requires a local runtime).",
|
|
7737
|
-
frontierOnlyEnabled: "Frontier-only mode enabled (frontierOnly=true).",
|
|
7738
|
-
localFirstNoChange: "No change: local-first routing is already active.",
|
|
7739
|
-
localFirstReEnabled: "Local-first routing re-enabled (frontierOnly=false). Make sure a local runtime is reachable."
|
|
7740
|
-
};
|
|
7741
|
-
var migrateMessages = {
|
|
7742
|
-
header: "openteam migrate:",
|
|
7743
|
-
nothingToMigrate: " nothing to migrate — the P15b layout is already in place.",
|
|
7744
|
-
counts: (params) => [
|
|
7745
|
-
` moved: ${params.moved} file(s)`,
|
|
7746
|
-
` deduped: ${params.deduped} file(s) (destination already identical)`,
|
|
7747
|
-
` conflicts: ${params.conflicts} file(s)`
|
|
7748
|
-
],
|
|
7749
|
-
relocatedHeader: " relocated:",
|
|
7750
|
-
relocatedEntry: (from, to, deduped) => ` · ${from} → ${to}${deduped ? " (deduped)" : ""}`,
|
|
7751
|
-
conflictsHeader: " ⚠ left in place (destination exists with different content — no data lost):",
|
|
7752
|
-
conflictEntry: (from, to) => ` · ${from} → ${to}`,
|
|
7753
|
-
manualWorktreesHeader: " ⚠ legacy git worktree(s) need a manual move (run `git worktree move`):",
|
|
7754
|
-
manualWorktreeEntry: (label, from, to) => ` · ${label}: ${from} → ${to}`,
|
|
7755
|
-
success: " ✓ machine-local runtime output relocated under .opencode/openteam-local/."
|
|
7756
|
-
};
|
|
7757
|
-
|
|
7758
7811
|
// src/commands/baseline.ts
|
|
7759
7812
|
function formatRef(ref) {
|
|
7760
7813
|
return ref === null ? "—" : `${ref.providerID}/${ref.modelID}`;
|
|
@@ -7897,10 +7950,23 @@ function renderConsoleStatus(console_) {
|
|
|
7897
7950
|
}
|
|
7898
7951
|
|
|
7899
7952
|
// src/commands/doctor.ts
|
|
7900
|
-
function runtimeLine(snapshot) {
|
|
7953
|
+
function runtimeLine(snapshot, runtime) {
|
|
7901
7954
|
const mark = snapshot.reachable ? "✓" : "✗";
|
|
7902
7955
|
const detail = snapshot.reachable ? `${snapshot.models.length} model(s)` : snapshot.error ?? "unreachable";
|
|
7903
|
-
|
|
7956
|
+
const declared = runtime?.maxConcurrency;
|
|
7957
|
+
const slots = declared === undefined ? ` · ${DEFAULT_LOCAL_MAX_CONCURRENCY} slot(s) (default)` : ` · ${declared} slot(s) (declared)`;
|
|
7958
|
+
return ` ${mark} ${snapshot.id.padEnd(14)} ${snapshot.baseURL || "(no baseURL)"} — ${detail}${slots}`;
|
|
7959
|
+
}
|
|
7960
|
+
function isNetworkRuntime(baseURL) {
|
|
7961
|
+
if (baseURL.length === 0) {
|
|
7962
|
+
return false;
|
|
7963
|
+
}
|
|
7964
|
+
try {
|
|
7965
|
+
const host = new URL(baseURL).hostname.toLowerCase();
|
|
7966
|
+
return host !== "localhost" && host !== "127.0.0.1" && host !== "::1" && host !== "[::1]" && !host.endsWith(".localhost");
|
|
7967
|
+
} catch {
|
|
7968
|
+
return false;
|
|
7969
|
+
}
|
|
7904
7970
|
}
|
|
7905
7971
|
function failureReasonText(reason, searchedPaths) {
|
|
7906
7972
|
switch (reason) {
|
|
@@ -8056,7 +8122,8 @@ function rosterHealthSection(audit, loadError, rosterRoleCount) {
|
|
|
8056
8122
|
if (unprofiled.length > 0) {
|
|
8057
8123
|
const roleIDs = unprofiled.map((entry) => entry.roleID).join(", ");
|
|
8058
8124
|
lines.push(` · unprofiled roleID(s): ${roleIDs}`);
|
|
8059
|
-
lines.push("
|
|
8125
|
+
lines.push(" routing: no profile means frontier-eligible — work for these roles can escalate to a frontier model. A 'local only' note in the roster prose does NOT prevent this: prose outside the JSON fence is never read.");
|
|
8126
|
+
lines.push(' remedy: run `openteam roles init` to compose a profile interactively, or add one by hand under orchestrator.roles in .opencode/openteam.json with "requiresLocalRuntime": true to pin the role local; for curated routing, change roleID to a TEAM_ROLES key instead.');
|
|
8060
8127
|
}
|
|
8061
8128
|
return lines;
|
|
8062
8129
|
}
|
|
@@ -8091,9 +8158,17 @@ function renderDoctor(input) {
|
|
|
8091
8158
|
lines.push(" (no runtime enabled)");
|
|
8092
8159
|
} else {
|
|
8093
8160
|
for (const snapshot of input.snapshots) {
|
|
8094
|
-
lines.push(runtimeLine(snapshot));
|
|
8161
|
+
lines.push(runtimeLine(snapshot, enabledRuntimes.find((r) => r.id === snapshot.id)));
|
|
8095
8162
|
}
|
|
8096
8163
|
}
|
|
8164
|
+
for (const snapshot of input.snapshots) {
|
|
8165
|
+
if (!isNetworkRuntime(snapshot.baseURL)) {
|
|
8166
|
+
continue;
|
|
8167
|
+
}
|
|
8168
|
+
const runtime = enabledRuntimes.find((r) => r.id === snapshot.id);
|
|
8169
|
+
const cap = runtime?.maxConcurrency ?? DEFAULT_LOCAL_MAX_CONCURRENCY;
|
|
8170
|
+
lines.push(` ⚠ ${snapshot.id} is reached over the network: its ${cap}-slot cap is enforced per openteam process, so`, " two processes at once (an opencode session plus 'openteam console') can together exceed it.");
|
|
8171
|
+
}
|
|
8097
8172
|
lines.push(` telemetry: ${input.telemetryPath} — ${input.telemetryRecords} record(s)`);
|
|
8098
8173
|
if (input.diagnostics !== undefined) {
|
|
8099
8174
|
lines.push(...diagnosticsSection(input.diagnostics));
|
|
@@ -8249,6 +8324,9 @@ function renderWorktreeReconciliation(report) {
|
|
|
8249
8324
|
}
|
|
8250
8325
|
|
|
8251
8326
|
// src/commands/local.ts
|
|
8327
|
+
function hasEnabledLocalRuntime(config) {
|
|
8328
|
+
return config.local.runtimes.some((runtime) => runtime.enabled);
|
|
8329
|
+
}
|
|
8252
8330
|
function enabledRuntimesSummary(config) {
|
|
8253
8331
|
const enabled = config.local.runtimes.filter((runtime) => runtime.enabled);
|
|
8254
8332
|
if (enabled.length === 0) {
|
|
@@ -8261,10 +8339,11 @@ function enabledRuntimesSummary(config) {
|
|
|
8261
8339
|
}).join(", ");
|
|
8262
8340
|
}
|
|
8263
8341
|
function showLocal(config) {
|
|
8264
|
-
const mode = config.router.frontierOnly ? localMessages.modeFrontierOnly : localMessages.modeLocalFirst;
|
|
8342
|
+
const mode = config.router.localOnly ? localMessages.modeLocalOnly : config.router.frontierOnly ? localMessages.modeFrontierOnly : localMessages.modeLocalFirst;
|
|
8265
8343
|
const lines = localMessages.summary({
|
|
8266
8344
|
mode,
|
|
8267
8345
|
frontierOnly: config.router.frontierOnly,
|
|
8346
|
+
localOnly: config.router.localOnly,
|
|
8268
8347
|
privacy: config.privacyMode,
|
|
8269
8348
|
runtimes: enabledRuntimesSummary(config)
|
|
8270
8349
|
});
|
|
@@ -8272,13 +8351,13 @@ function showLocal(config) {
|
|
|
8272
8351
|
`) };
|
|
8273
8352
|
}
|
|
8274
8353
|
function setFrontierOnly(config) {
|
|
8275
|
-
if (config.router.frontierOnly) {
|
|
8354
|
+
if (config.router.frontierOnly && !config.router.localOnly) {
|
|
8276
8355
|
return { message: localMessages.frontierOnlyNoChange };
|
|
8277
8356
|
}
|
|
8278
8357
|
const flipsPrivacy = config.privacyMode === "forceLocalOnSensitive";
|
|
8279
8358
|
const next = {
|
|
8280
8359
|
...config,
|
|
8281
|
-
router: { ...config.router, frontierOnly: true },
|
|
8360
|
+
router: { ...config.router, frontierOnly: true, localOnly: false },
|
|
8282
8361
|
privacyMode: flipsPrivacy ? "consentBeforeFrontier" : config.privacyMode
|
|
8283
8362
|
};
|
|
8284
8363
|
const privacyNote = flipsPrivacy ? localMessages.privacyAdjustedNote : "";
|
|
@@ -8287,13 +8366,29 @@ function setFrontierOnly(config) {
|
|
|
8287
8366
|
message: `${localMessages.frontierOnlyEnabled}${privacyNote}`
|
|
8288
8367
|
};
|
|
8289
8368
|
}
|
|
8369
|
+
function setLocalOnly(config) {
|
|
8370
|
+
if (!hasEnabledLocalRuntime(config)) {
|
|
8371
|
+
return { message: localMessages.localOnlyNoRuntimes };
|
|
8372
|
+
}
|
|
8373
|
+
if (config.router.localOnly && !config.router.frontierOnly) {
|
|
8374
|
+
return { message: localMessages.localOnlyNoChange };
|
|
8375
|
+
}
|
|
8376
|
+
const next = {
|
|
8377
|
+
...config,
|
|
8378
|
+
router: { ...config.router, frontierOnly: false, localOnly: true }
|
|
8379
|
+
};
|
|
8380
|
+
return {
|
|
8381
|
+
config: next,
|
|
8382
|
+
message: localMessages.localOnlyEnabled
|
|
8383
|
+
};
|
|
8384
|
+
}
|
|
8290
8385
|
function setLocalFirst(config) {
|
|
8291
|
-
if (!config.router.frontierOnly) {
|
|
8386
|
+
if (!config.router.frontierOnly && !config.router.localOnly) {
|
|
8292
8387
|
return { message: localMessages.localFirstNoChange };
|
|
8293
8388
|
}
|
|
8294
8389
|
const next = {
|
|
8295
8390
|
...config,
|
|
8296
|
-
router: { ...config.router, frontierOnly: false }
|
|
8391
|
+
router: { ...config.router, frontierOnly: false, localOnly: false }
|
|
8297
8392
|
};
|
|
8298
8393
|
return {
|
|
8299
8394
|
config: next,
|
|
@@ -9134,10 +9229,12 @@ var HELP = [
|
|
|
9134
9229
|
" openteam baseline show Show the effective baseline",
|
|
9135
9230
|
" openteam baseline set <p/model> Pin the baseline (pinned mode)",
|
|
9136
9231
|
" openteam baseline auto Cheapest-capable baseline (auto mode)",
|
|
9137
|
-
|
|
9138
|
-
|
|
9139
|
-
|
|
9232
|
+
localMessages.help.status,
|
|
9233
|
+
localMessages.help.off,
|
|
9234
|
+
localMessages.help.only,
|
|
9235
|
+
localMessages.help.on,
|
|
9140
9236
|
" openteam doctor Diagnose runtimes and config",
|
|
9237
|
+
" openteam roles init Compose per-role routing policy for unprofiled roster roles",
|
|
9141
9238
|
" openteam migrate Relocate pre-P15b artifacts to their split homes (idempotent)",
|
|
9142
9239
|
" openteam agents List agents and each one's LLM (local/frontier)",
|
|
9143
9240
|
" openteam console Launch the multi-session web Console (Ctrl+C to stop; --open opens the browser)",
|
|
@@ -9306,23 +9403,40 @@ ${HELP}`
|
|
|
9306
9403
|
}
|
|
9307
9404
|
async function runLocal(positionals, deps, configPath, configResolution) {
|
|
9308
9405
|
const sub = positionals[1] ?? "status";
|
|
9309
|
-
if (sub !== "status" && sub !== "off" && sub !== "on") {
|
|
9406
|
+
if (sub !== "status" && sub !== "off" && sub !== "only" && sub !== "on") {
|
|
9310
9407
|
return {
|
|
9311
9408
|
exitCode: 1,
|
|
9312
|
-
stdout:
|
|
9313
|
-
|
|
9314
|
-
${HELP}`
|
|
9409
|
+
stdout: localMessages.unknownSubcommand(sub, HELP)
|
|
9315
9410
|
};
|
|
9316
9411
|
}
|
|
9317
9412
|
const config = await deps.loadConfig(configPath, configResolution);
|
|
9318
9413
|
if (sub === "status") {
|
|
9319
9414
|
return { exitCode: 0, stdout: showLocal(config).message };
|
|
9320
9415
|
}
|
|
9321
|
-
|
|
9416
|
+
let outcome;
|
|
9417
|
+
switch (sub) {
|
|
9418
|
+
case "off":
|
|
9419
|
+
outcome = setFrontierOnly(config);
|
|
9420
|
+
break;
|
|
9421
|
+
case "only":
|
|
9422
|
+
outcome = setLocalOnly(config);
|
|
9423
|
+
break;
|
|
9424
|
+
case "on":
|
|
9425
|
+
outcome = setLocalFirst(config);
|
|
9426
|
+
break;
|
|
9427
|
+
default:
|
|
9428
|
+
return {
|
|
9429
|
+
exitCode: 1,
|
|
9430
|
+
stdout: localMessages.unknownSubcommand(sub, HELP)
|
|
9431
|
+
};
|
|
9432
|
+
}
|
|
9322
9433
|
if (outcome.config !== undefined) {
|
|
9323
9434
|
await deps.saveConfig(outcome.config, configPath, configResolution);
|
|
9324
9435
|
}
|
|
9325
|
-
return {
|
|
9436
|
+
return {
|
|
9437
|
+
exitCode: sub === "only" && !hasEnabledLocalRuntime(config) ? 1 : 0,
|
|
9438
|
+
stdout: outcome.message
|
|
9439
|
+
};
|
|
9326
9440
|
}
|
|
9327
9441
|
async function runYolo(positionals, deps, opencodeConfigPaths) {
|
|
9328
9442
|
const sub = positionals[1] ?? "status";
|
|
@@ -12602,6 +12716,9 @@ async function registerCast(storage, draft, path4 = OPENTEAM_ROSTER_PATH) {
|
|
|
12602
12716
|
const written = await persistRosterPreservingProse(storage, roster, path4);
|
|
12603
12717
|
return { ok: true, path: written, roster };
|
|
12604
12718
|
}
|
|
12719
|
+
function unprofiledRoleIDs(roster, configuredRoles) {
|
|
12720
|
+
return roster.entries.filter((entry) => getRoleProfile(entry.roleID, configuredRoles) === undefined && !isKnownNonWorkerRole(entry.roleID)).map((entry) => entry.roleID);
|
|
12721
|
+
}
|
|
12605
12722
|
function createRegisterCastTool(deps) {
|
|
12606
12723
|
return tool5({
|
|
12607
12724
|
description: "Registers the orchestrator's cast as the project roster. Use this " + "instead of writing the roster file directly: the payload is validated " + "before anything is persisted, guaranteed roles are added automatically, " + "and curated prose already in the document is preserved.",
|
|
@@ -12618,7 +12735,17 @@ function createRegisterCastTool(deps) {
|
|
|
12618
12735
|
return `validation error: ${result.error}`;
|
|
12619
12736
|
}
|
|
12620
12737
|
const roles = result.roster.entries.map((entry) => `${entry.roleID}=${entry.agentName}`).join(", ");
|
|
12621
|
-
|
|
12738
|
+
const registered = `registered ${result.roster.entries.length} roles in ${result.path} (${roles})`;
|
|
12739
|
+
const unprofiled = unprofiledRoleIDs(result.roster, deps.configuredRoles);
|
|
12740
|
+
if (unprofiled.length === 0) {
|
|
12741
|
+
return registered;
|
|
12742
|
+
}
|
|
12743
|
+
return [
|
|
12744
|
+
registered,
|
|
12745
|
+
`warning: ${unprofiled.join(", ")} resolve no routing profile, so they are frontier-eligible — their work can escalate to a frontier model. Describing a role as "local only" in the roster prose does NOT prevent this: prose outside the JSON block is never read.`,
|
|
12746
|
+
'remedy: tell the human to run `openteam roles init` to pin those roles local, or add a profile under orchestrator.roles in .opencode/openteam.json with "requiresLocalRuntime": true.'
|
|
12747
|
+
].join(`
|
|
12748
|
+
`);
|
|
12622
12749
|
}
|
|
12623
12750
|
});
|
|
12624
12751
|
}
|
|
@@ -12895,7 +13022,7 @@ var createOtlpSpanExporter = (connection, config) => {
|
|
|
12895
13022
|
// package.json
|
|
12896
13023
|
var package_default = {
|
|
12897
13024
|
name: "@jmanuelcorral/openteam",
|
|
12898
|
-
version: "0.
|
|
13025
|
+
version: "0.11.0",
|
|
12899
13026
|
packageManager: "bun@1.3.14",
|
|
12900
13027
|
description: "Cost-aware, local-first routing plugin for opencode with cheapest-capable frontier fallback and multi-agent orchestration.",
|
|
12901
13028
|
license: "MIT",
|
|
@@ -13674,7 +13801,10 @@ var server = async (ctx, rawOptions) => {
|
|
|
13674
13801
|
runtimeLimiter
|
|
13675
13802
|
}
|
|
13676
13803
|
});
|
|
13677
|
-
const registerCastTool = createRegisterCastTool({
|
|
13804
|
+
const registerCastTool = createRegisterCastTool({
|
|
13805
|
+
storage,
|
|
13806
|
+
configuredRoles: config.orchestrator?.roles
|
|
13807
|
+
});
|
|
13678
13808
|
return {
|
|
13679
13809
|
...hooks,
|
|
13680
13810
|
tool: {
|
|
@@ -44,20 +44,32 @@ export declare const baselineMessages: {
|
|
|
44
44
|
};
|
|
45
45
|
/** Messages for `openteam local`. */
|
|
46
46
|
export declare const localMessages: {
|
|
47
|
+
readonly help: {
|
|
48
|
+
readonly status: " openteam local status Show the routing mode (local-first / local-only / frontier-only)";
|
|
49
|
+
readonly off: " openteam local off Use frontier models only (no local runtime)";
|
|
50
|
+
readonly only: " openteam local only Use local models only (never frontier)";
|
|
51
|
+
readonly on: " openteam local on Re-enable local-first routing";
|
|
52
|
+
};
|
|
47
53
|
readonly noRuntimes: "none";
|
|
48
54
|
readonly modeFrontierOnly: "frontier-only (frontierOnly)";
|
|
55
|
+
readonly modeLocalOnly: "local-only (localOnly)";
|
|
49
56
|
readonly modeLocalFirst: "local-first";
|
|
50
57
|
readonly summary: (params: {
|
|
51
58
|
mode: string;
|
|
52
59
|
frontierOnly: boolean;
|
|
60
|
+
localOnly: boolean;
|
|
53
61
|
privacy: string;
|
|
54
62
|
runtimes: string;
|
|
55
63
|
}) => string[];
|
|
56
64
|
readonly frontierOnlyNoChange: "No change: already in frontier-only mode.";
|
|
57
65
|
readonly privacyAdjustedNote: " Privacy adjusted to 'consentBeforeFrontier' (forceLocalOnSensitive requires a local runtime).";
|
|
58
|
-
readonly frontierOnlyEnabled: "Frontier-only mode enabled (frontierOnly=true).";
|
|
66
|
+
readonly frontierOnlyEnabled: "Frontier-only mode enabled (frontierOnly=true, localOnly=false).";
|
|
67
|
+
readonly localOnlyNoRuntimes: "Cannot enable local-only mode: no enabled local runtime is configured. Run 'openteam setup' or enable a local runtime in .opencode/openteam.json first.";
|
|
68
|
+
readonly localOnlyNoChange: "No change: already in local-only mode.";
|
|
69
|
+
readonly localOnlyEnabled: "Local-only mode enabled (localOnly=true, frontierOnly=false).";
|
|
59
70
|
readonly localFirstNoChange: "No change: local-first routing is already active.";
|
|
60
|
-
readonly localFirstReEnabled: "Local-first routing re-enabled (frontierOnly=false). Make sure a local runtime is reachable.";
|
|
71
|
+
readonly localFirstReEnabled: "Local-first routing re-enabled (frontierOnly=false, localOnly=false). Make sure a local runtime is reachable.";
|
|
72
|
+
readonly unknownSubcommand: (subcommand: string, help: string) => string;
|
|
61
73
|
};
|
|
62
74
|
/** Messages for the frontier catalog rendered during `init`. */
|
|
63
75
|
export declare const frontierCatalogMessages: {
|
|
@@ -81,4 +93,40 @@ export declare const migrateMessages: {
|
|
|
81
93
|
readonly manualWorktreeEntry: (label: string, from: string, to: string) => string;
|
|
82
94
|
readonly success: " ✓ machine-local runtime output relocated under .opencode/openteam-local/.";
|
|
83
95
|
};
|
|
96
|
+
/**
|
|
97
|
+
* Messages for `openteam roles init` (#206) — assisted composition of per-role
|
|
98
|
+
* routing policy. The wording carries the whole point of the command: a roster
|
|
99
|
+
* role with no profile is frontier-eligible, and the "local only" note a human
|
|
100
|
+
* writes in the roster prose is never read because it sits outside the JSON
|
|
101
|
+
* fence. Keep that consequence stated explicitly; softening it recreates the bug.
|
|
102
|
+
*/
|
|
103
|
+
export declare const rolesInitMessages: {
|
|
104
|
+
readonly header: "openteam roles init:";
|
|
105
|
+
readonly title: "openteam roles init";
|
|
106
|
+
readonly noRoster: (path: string) => string;
|
|
107
|
+
readonly noRosterRemedy: " Cast the team first: run `openteam setup`, then ask the orchestrator to register the cast.";
|
|
108
|
+
readonly unparseableRoster: (path: string, error: string) => string;
|
|
109
|
+
readonly unparseableRosterRemedy: " Run `openteam doctor` for the remedy, then re-run this command.";
|
|
110
|
+
readonly allProfiled: (count: number) => string;
|
|
111
|
+
readonly whyTitle: "Why you are being asked";
|
|
112
|
+
readonly why: (count: number) => string;
|
|
113
|
+
readonly policyQuestion: (roleID: string, agentName: string) => string;
|
|
114
|
+
readonly localOnlyLabel: (roleID: string, agentName: string) => string;
|
|
115
|
+
readonly localOnlyHint: "sets requiresLocalRuntime; the role fails closed when no local runtime is reachable";
|
|
116
|
+
readonly frontierOkLabel: "Local first, frontier allowed";
|
|
117
|
+
readonly frontierOkHint: "records today's implicit behaviour: cheapest-capable frontier when the task warrants it";
|
|
118
|
+
readonly skipLabel: "Skip for now";
|
|
119
|
+
readonly skipHint: "leaves the role unprofiled, so it stays frontier-eligible and doctor keeps reporting it";
|
|
120
|
+
readonly runtimeQuestion: (roleID: string) => string;
|
|
121
|
+
readonly runtimeHint: "machine-local — written to the git-ignored overlay";
|
|
122
|
+
readonly cancelled: (reason: string) => string;
|
|
123
|
+
readonly invalidResult: (reason: string) => string;
|
|
124
|
+
readonly nothingWritten: (skipped: string) => string;
|
|
125
|
+
readonly nothingToWriteOutro: "Nothing to write.";
|
|
126
|
+
readonly pinnedLocal: (roleIDs: string, path: string) => string;
|
|
127
|
+
readonly frontierAllowed: (roleIDs: string, path: string) => string;
|
|
128
|
+
readonly runtimeBinding: (path: string) => string;
|
|
129
|
+
readonly skippedSummary: (roleIDs: string) => string;
|
|
130
|
+
readonly outro: "Role policy updated.";
|
|
131
|
+
};
|
|
84
132
|
//# sourceMappingURL=commands.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/messages/commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,2CAA2C;AAC3C,eAAO,MAAM,kBAAkB;aAC7B,MAAM,EAAE,qDAAqD;aAC7D,OAAO;iBACL,OAAO,EAAE,UAAU;iBACnB,MAAM,EAAE,aAAa;iBACrB,SAAS,EAAE,WAAW;iBACtB,KAAK,EAAE,OAAO;;aAEhB,iBAAiB,EAAE,0BAA0B;aAC7C,YAAY,EAAE,UAAU;aACxB,WAAW,YAAY,MAAM,KAAG,MAAM;aACtC,kBAAkB,YAAY,MAAM,gBAAgB,MAAM,KAAG,MAAM;aAEnE,SAAS,UAAU,MAAM,KAAG,MAAM;aAClC,KAAK,UAAU,MAAM,KAAG,MAAM;CAEtB,CAAC;AAEX,wCAAwC;AACxC,eAAO,MAAM,gBAAgB;aAC3B,aAAa,EAAE,yBAAyB;aACxC,YAAY,QAAQ,MAAM,KAAG,MAAM;aACnC,OAAO,WAAW;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;KACnB,KAAG,MAAM,EAAE;aAOZ,YAAY,UAAU,MAAM,KAAG,MAAM;aAErC,QAAQ,QAAQ,MAAM,KAAG,MAAM;aAC/B,QAAQ,EAAE,+CAA+C;CACjD,CAAC;AAEX,qCAAqC;AACrC,eAAO,MAAM,aAAa;aACxB,UAAU,EAAE,MAAM;aAClB,gBAAgB,EAAE,8BAA8B;aAChD,cAAc,EAAE,aAAa;aAC7B,OAAO,WAAW;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,OAAO,CAAC;QACtB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;KAClB,KAAG,MAAM,EAAE;
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/messages/commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,2CAA2C;AAC3C,eAAO,MAAM,kBAAkB;aAC7B,MAAM,EAAE,qDAAqD;aAC7D,OAAO;iBACL,OAAO,EAAE,UAAU;iBACnB,MAAM,EAAE,aAAa;iBACrB,SAAS,EAAE,WAAW;iBACtB,KAAK,EAAE,OAAO;;aAEhB,iBAAiB,EAAE,0BAA0B;aAC7C,YAAY,EAAE,UAAU;aACxB,WAAW,YAAY,MAAM,KAAG,MAAM;aACtC,kBAAkB,YAAY,MAAM,gBAAgB,MAAM,KAAG,MAAM;aAEnE,SAAS,UAAU,MAAM,KAAG,MAAM;aAClC,KAAK,UAAU,MAAM,KAAG,MAAM;CAEtB,CAAC;AAEX,wCAAwC;AACxC,eAAO,MAAM,gBAAgB;aAC3B,aAAa,EAAE,yBAAyB;aACxC,YAAY,QAAQ,MAAM,KAAG,MAAM;aACnC,OAAO,WAAW;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;KACnB,KAAG,MAAM,EAAE;aAOZ,YAAY,UAAU,MAAM,KAAG,MAAM;aAErC,QAAQ,QAAQ,MAAM,KAAG,MAAM;aAC/B,QAAQ,EAAE,+CAA+C;CACjD,CAAC;AAEX,qCAAqC;AACrC,eAAO,MAAM,aAAa;aACxB,IAAI;iBACF,MAAM,EACJ,sGAAsG;iBACxG,GAAG,EAAE,iFAAiF;iBACtF,IAAI,EAAE,4EAA4E;iBAClF,EAAE,EAAE,mEAAmE;;aAEzE,UAAU,EAAE,MAAM;aAClB,gBAAgB,EAAE,8BAA8B;aAChD,aAAa,EAAE,wBAAwB;aACvC,cAAc,EAAE,aAAa;aAC7B,OAAO,WAAW;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,OAAO,CAAC;QACtB,SAAS,EAAE,OAAO,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;KAClB,KAAG,MAAM,EAAE;aAQZ,oBAAoB,EAAE,2CAA2C;aACjE,mBAAmB,EACjB,gGAAgG;aAClG,mBAAmB,EACjB,kEAAkE;aACpE,mBAAmB,EACjB,yJAAyJ;aAC3J,iBAAiB,EAAE,wCAAwC;aAC3D,gBAAgB,EACd,+DAA+D;aACjE,kBAAkB,EAAE,mDAAmD;aACvE,mBAAmB,EACjB,+GAA+G;aACjH,iBAAiB,eAAe,MAAM,QAAQ,MAAM,KAAG,MAAM;CAErD,CAAC;AAEX,gEAAgE;AAChE,eAAO,MAAM,uBAAuB;aAClC,IAAI,EAAE,MAAM;aACZ,cAAc,aAAa,MAAM,aAAa,MAAM,KAAG,MAAM;CAErD,CAAC;AAEX,uCAAuC;AACvC,eAAO,MAAM,eAAe;aAC1B,MAAM,EAAE,mBAAmB;aAC3B,gBAAgB,EACd,6DAA6D;aAC/D,MAAM,WAAW;QACf,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;KACnB,KAAG,MAAM,EAAE;aAKZ,eAAe,EAAE,cAAc;aAC/B,cAAc,SAAS,MAAM,MAAM,MAAM,WAAW,OAAO,KAAG,MAAM;aAEpE,eAAe,EACb,+EAA+E;aACjF,aAAa,SAAS,MAAM,MAAM,MAAM,KAAG,MAAM;aACjD,qBAAqB,EACnB,0EAA0E;aAC5E,mBAAmB,UAAU,MAAM,QAAQ,MAAM,MAAM,MAAM,KAAG,MAAM;aAEtE,OAAO,EACL,6EAA6E;CACvE,CAAC;AAEX;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB;aAC5B,MAAM,EAAE,sBAAsB;aAC9B,KAAK,EAAE,qBAAqB;aAC5B,QAAQ,SAAS,MAAM,KAAG,MAAM;aAChC,cAAc,EACZ,gGAAgG;aAClG,iBAAiB,SAAS,MAAM,SAAS,MAAM,KAAG,MAAM;aAExD,uBAAuB,EACrB,qEAAqE;aACvE,WAAW,UAAU,MAAM,KAAG,MAAM;aAEpC,QAAQ,EAAE,yBAAyB;aACnC,GAAG,UAAU,MAAM,KAAG,MAAM;aAO5B,cAAc,WAAW,MAAM,aAAa,MAAM,KAAG,MAAM;aAE3D,cAAc,WAAW,MAAM,aAAa,MAAM,KAAG,MAAM;aAE3D,aAAa,EACX,qFAAqF;aACvF,eAAe,EAAE,+BAA+B;aAChD,cAAc,EACZ,yFAAyF;aAC3F,SAAS,EAAE,cAAc;aACzB,QAAQ,EACN,yFAAyF;aAC3F,eAAe,WAAW,MAAM,KAAG,MAAM;aAEzC,WAAW,EAAE,oDAAoD;aACjE,SAAS,WAAW,MAAM,KAAG,MAAM;aAEnC,aAAa,WAAW,MAAM,KAAG,MAAM;aAEvC,cAAc,YAAY,MAAM,KAAG,MAAM;aAEzC,mBAAmB,EAAE,mBAAmB;aACxC,WAAW,YAAY,MAAM,QAAQ,MAAM,KAAG,MAAM;aAEpD,eAAe,YAAY,MAAM,QAAQ,MAAM,KAAG,MAAM;aAExD,cAAc,SAAS,MAAM,KAAG,MAAM;aAEtC,cAAc,YAAY,MAAM,KAAG,MAAM;aAEzC,KAAK,EAAE,sBAAsB;CACrB,CAAC"}
|
|
@@ -37,6 +37,20 @@ export type AgentRoleProfile = {
|
|
|
37
37
|
* on that runtime.
|
|
38
38
|
*/
|
|
39
39
|
localRuntimes?: LocalRuntimeId[];
|
|
40
|
+
/**
|
|
41
|
+
* Per-runtime model override for this role (#210).
|
|
42
|
+
*
|
|
43
|
+
* Without this, every role dispatched to a runtime shares that runtime's
|
|
44
|
+
* `defaultModel`, so a reviewer role cannot run a larger local model than a
|
|
45
|
+
* bookkeeping role on the same box — the local counterpart of
|
|
46
|
+
* `preferredFrontierModels`, which has always been able to pin a concrete
|
|
47
|
+
* frontier model.
|
|
48
|
+
*
|
|
49
|
+
* Keyed BY RUNTIME rather than a single model id so failover stays safe: a
|
|
50
|
+
* model that only exists on lemonade can never be sent to ollama. When the
|
|
51
|
+
* chosen runtime has no entry, the runtime's `defaultModel` stands.
|
|
52
|
+
*/
|
|
53
|
+
localModels?: Partial<Record<LocalRuntimeId, string>>;
|
|
40
54
|
};
|
|
41
55
|
export declare const AgentRoleProfileSchema: z.ZodObject<{
|
|
42
56
|
roleID: z.ZodString;
|
|
@@ -62,6 +76,12 @@ export declare const AgentRoleProfileSchema: z.ZodObject<{
|
|
|
62
76
|
lmstudio: "lmstudio";
|
|
63
77
|
ollama: "ollama";
|
|
64
78
|
}>>>;
|
|
79
|
+
localModels: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
|
|
80
|
+
"foundry-local": "foundry-local";
|
|
81
|
+
lemonade: "lemonade";
|
|
82
|
+
lmstudio: "lmstudio";
|
|
83
|
+
ollama: "ollama";
|
|
84
|
+
}> & z.core.$partial, z.ZodString>>;
|
|
65
85
|
}, z.core.$strict>;
|
|
66
86
|
export declare const TEAM_ROLES: Record<string, AgentRoleProfile>;
|
|
67
87
|
export declare function isKnownNonWorkerRole(roleID: string): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roles.d.ts","sourceRoot":"","sources":["../../src/orchestrator/roles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EACV,qBAAqB,EACrB,cAAc,EACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,cAAc,CAAC;IAC5B,gBAAgB,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACpC,kBAAkB,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACtC,yBAAyB,EAAE,OAAO,CAAC;IACnC,uBAAuB,EAAE,KAAK,CAAC,cAAc,GAAG,MAAM,CAAC,CAAC;IACxD,UAAU,EAAE,OAAO,CAAC;IACpB;;;;;;;;;OASG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;;;;;;;;;;;OAaG;IACH,aAAa,CAAC,EAAE,cAAc,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"roles.d.ts","sourceRoot":"","sources":["../../src/orchestrator/roles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EACV,qBAAqB,EACrB,cAAc,EACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,cAAc,CAAC;IAC5B,gBAAgB,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACpC,kBAAkB,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACtC,yBAAyB,EAAE,OAAO,CAAC;IACnC,uBAAuB,EAAE,KAAK,CAAC,cAAc,GAAG,MAAM,CAAC,CAAC;IACxD,UAAU,EAAE,OAAO,CAAC;IACpB;;;;;;;;;OASG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;;;;;;;;;;;OAaG;IACH,aAAa,CAAC,EAAE,cAAc,EAAE,CAAC;IACjC;;;;;;;;;;;;OAYG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;CACvD,CAAC;AAiBF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAwBxB,CAAC;AAGZ,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CA8FvD,CAAC;AAcF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAI5D;AA6BD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,eAAe,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,GAC3D,gBAAgB,GAAG,SAAS,CAO9B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAW1E;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,gBAAgB,EACtB,IAAI,EAAE,WAAW,EACjB,IAAI,CAAC,EAAE,cAAc,GACpB,qBAAqB,CAevB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtimeSelection.d.ts","sourceRoot":"","sources":["../../src/orchestrator/runtimeSelection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,CAAC,SAAS,EAAE,cAAc,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;CACpC,CAAC;AASF;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,cAAc,GACrB,cAAc,GAAG,SAAS,CAI5B;
|
|
1
|
+
{"version":3,"file":"runtimeSelection.d.ts","sourceRoot":"","sources":["../../src/orchestrator/runtimeSelection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,CAAC,SAAS,EAAE,cAAc,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;CACpC,CAAC;AASF;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,cAAc,GACrB,cAAc,GAAG,SAAS,CAI5B;AAoBD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,gBAAgB,EACtB,QAAQ,EAAE,eAAe,EACzB,SAAS,EAAE,WAAW,CAAC,cAAc,CAAC,GAAG,SAAS,EAClD,MAAM,EAAE,cAAc,GACrB,wBAAwB,CAsC1B"}
|