@m8t-stack/cli 0.2.37 → 0.2.40
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/cli.js +276 -13
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1298,7 +1298,7 @@ var init_enable_hosted_brain = __esm({
|
|
|
1298
1298
|
import { Builtins, Cli } from "clipanion";
|
|
1299
1299
|
|
|
1300
1300
|
// src/lib/package-version.ts
|
|
1301
|
-
var CLI_VERSION = "0.2.
|
|
1301
|
+
var CLI_VERSION = "0.2.40";
|
|
1302
1302
|
|
|
1303
1303
|
// src/lib/render-error.ts
|
|
1304
1304
|
init_errors();
|
|
@@ -16963,7 +16963,7 @@ async function listModelQuota(region) {
|
|
|
16963
16963
|
function usageModelName(usageName) {
|
|
16964
16964
|
return usageName.split(".").slice(2).join(".");
|
|
16965
16965
|
}
|
|
16966
|
-
var REASONING_USAGE_RE = /gpt-5|o[1-9]/i;
|
|
16966
|
+
var REASONING_USAGE_RE = /gpt-5|o[1-9]|grok-4/i;
|
|
16967
16967
|
function isReasoningModel(modelDeployment) {
|
|
16968
16968
|
return REASONING_USAGE_RE.test(modelDeployment);
|
|
16969
16969
|
}
|
|
@@ -25476,7 +25476,7 @@ async function ensureDeployment(args) {
|
|
|
25476
25476
|
"--model-version",
|
|
25477
25477
|
args.modelVersion,
|
|
25478
25478
|
"--model-format",
|
|
25479
|
-
"OpenAI",
|
|
25479
|
+
args.format ?? "OpenAI",
|
|
25480
25480
|
"--sku-name",
|
|
25481
25481
|
"GlobalStandard",
|
|
25482
25482
|
"--sku-capacity",
|
|
@@ -26928,8 +26928,7 @@ function orderNewest(values) {
|
|
|
26928
26928
|
return values.sort((a, b) => b.createdAt - a.createdAt || a.ordinal - b.ordinal || b.id.localeCompare(a.id));
|
|
26929
26929
|
}
|
|
26930
26930
|
async function findOnboardingProfile(args) {
|
|
26931
|
-
|
|
26932
|
-
if (!userId) return { ...EMPTY_PROFILE_RESULT };
|
|
26931
|
+
if (!decodeFoundryUser(args.token)) return { ...EMPTY_PROFILE_RESULT };
|
|
26933
26932
|
const doFetch = args.fetchImpl ?? fetch;
|
|
26934
26933
|
const H = { Authorization: `Bearer ${args.token}` };
|
|
26935
26934
|
const base = args.endpoint.replace(/\/+$/, "");
|
|
@@ -26942,7 +26941,7 @@ async function findOnboardingProfile(args) {
|
|
|
26942
26941
|
const conversations = orderNewest(listed.flatMap((value, ordinal) => {
|
|
26943
26942
|
if (!isRecord(value) || typeof value.id !== "string" || value.id.length === 0 || !isRecord(value.metadata)) return [];
|
|
26944
26943
|
const metadata = value.metadata;
|
|
26945
|
-
if (metadata.app !== "m8t-webapp" || metadata.agent !== "stacey-intake"
|
|
26944
|
+
if (metadata.app !== "m8t-webapp" || metadata.agent !== "stacey-intake") return [];
|
|
26946
26945
|
return [{
|
|
26947
26946
|
id: value.id,
|
|
26948
26947
|
createdAt: timestamp(value.created_at) !== Number.NEGATIVE_INFINITY ? timestamp(value.created_at) : timestamp(metadata.createdAt),
|
|
@@ -27466,6 +27465,7 @@ async function deploySimpleStacey(args) {
|
|
|
27466
27465
|
repoRoot: args.repoRoot,
|
|
27467
27466
|
persona: SIMPLE_STACEY_PERSONA,
|
|
27468
27467
|
agentName: SIMPLE_STACEY_AGENT,
|
|
27468
|
+
model: args.model,
|
|
27469
27469
|
fieldOverrides: args.fieldOverrides
|
|
27470
27470
|
});
|
|
27471
27471
|
} catch (e) {
|
|
@@ -27534,6 +27534,7 @@ async function deploySimpleStaceyWithRetry(args) {
|
|
|
27534
27534
|
credential: args.credential,
|
|
27535
27535
|
endpoint: args.endpoint,
|
|
27536
27536
|
repoRoot: args.repoRoot,
|
|
27537
|
+
model: args.model,
|
|
27537
27538
|
fieldOverrides: args.fieldOverrides
|
|
27538
27539
|
});
|
|
27539
27540
|
} catch (error) {
|
|
@@ -27930,6 +27931,257 @@ function stopOnboardingUi(home = os17.homedir()) {
|
|
|
27930
27931
|
return uiStopped || relayStopped;
|
|
27931
27932
|
}
|
|
27932
27933
|
|
|
27934
|
+
// src/lib/model-catalog.ts
|
|
27935
|
+
async function listAgentModels(region) {
|
|
27936
|
+
let out;
|
|
27937
|
+
try {
|
|
27938
|
+
out = await runAz(["cognitiveservices", "model", "list", "-l", region, "--output", "json"]);
|
|
27939
|
+
} catch (e) {
|
|
27940
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
27941
|
+
const denied = /AuthorizationFailed|Forbidden|\b403\b|does not have authorization/i.test(msg);
|
|
27942
|
+
return { ok: false, error: denied ? "denied" : "unavailable" };
|
|
27943
|
+
}
|
|
27944
|
+
let raw;
|
|
27945
|
+
try {
|
|
27946
|
+
raw = JSON.parse(out);
|
|
27947
|
+
} catch {
|
|
27948
|
+
return { ok: false, error: "malformed" };
|
|
27949
|
+
}
|
|
27950
|
+
if (!Array.isArray(raw) || raw.some((e) => typeof e !== "object" || e === null)) {
|
|
27951
|
+
return { ok: false, error: "malformed" };
|
|
27952
|
+
}
|
|
27953
|
+
try {
|
|
27954
|
+
const rows = raw.map((e) => ({
|
|
27955
|
+
format: e.model?.format ?? "",
|
|
27956
|
+
name: e.model?.name ?? "",
|
|
27957
|
+
version: e.model?.version ?? "",
|
|
27958
|
+
skus: [...new Set((e.model?.skus ?? []).map((s) => s.name ?? "").filter(Boolean))],
|
|
27959
|
+
agentsV2: e.model?.capabilities?.agentsV2 === "true"
|
|
27960
|
+
}));
|
|
27961
|
+
return { ok: true, rows };
|
|
27962
|
+
} catch {
|
|
27963
|
+
return { ok: false, error: "malformed" };
|
|
27964
|
+
}
|
|
27965
|
+
}
|
|
27966
|
+
|
|
27967
|
+
// src/lib/model-cascade.ts
|
|
27968
|
+
var WHITELIST = [
|
|
27969
|
+
{ model: "gpt-5.6-luna", format: "OpenAI", version: "2026-07-09", capacity: 100 },
|
|
27970
|
+
{ model: "gpt-5.6-sol", format: "OpenAI", version: "2026-07-09", capacity: 100 },
|
|
27971
|
+
{ model: "gpt-5.6-terra", format: "OpenAI", version: "2026-07-09", capacity: 100 },
|
|
27972
|
+
{ model: "gpt-5.4", format: "OpenAI", version: "2026-03-05", capacity: 100 },
|
|
27973
|
+
{ model: "grok-4.3", format: "xAI", version: "1", capacity: 100 },
|
|
27974
|
+
{ model: "gpt-4.1-mini", format: "OpenAI", version: "2025-04-14", capacity: 50 }
|
|
27975
|
+
];
|
|
27976
|
+
var GLOBAL_STANDARD = "GlobalStandard";
|
|
27977
|
+
function planCascade(whitelist, catalog, quota) {
|
|
27978
|
+
if (!catalog.ok) {
|
|
27979
|
+
return {
|
|
27980
|
+
candidates: [],
|
|
27981
|
+
skipped: whitelist.map((r) => ({ model: r.model, outcome: "catalog-unverified", detail: catalog.error }))
|
|
27982
|
+
};
|
|
27983
|
+
}
|
|
27984
|
+
const rowsByName = /* @__PURE__ */ new Map();
|
|
27985
|
+
for (const row of catalog.rows) {
|
|
27986
|
+
const list = rowsByName.get(row.name);
|
|
27987
|
+
if (list) list.push(row);
|
|
27988
|
+
else rowsByName.set(row.name, [row]);
|
|
27989
|
+
}
|
|
27990
|
+
const candidates = [];
|
|
27991
|
+
const skipped = [];
|
|
27992
|
+
for (const rung of whitelist) {
|
|
27993
|
+
const rows = rowsByName.get(rung.model);
|
|
27994
|
+
if (!rows || rows.length === 0) {
|
|
27995
|
+
skipped.push({ model: rung.model, outcome: "not-in-catalog" });
|
|
27996
|
+
continue;
|
|
27997
|
+
}
|
|
27998
|
+
const agentRows = rows.filter((r) => r.agentsV2);
|
|
27999
|
+
if (agentRows.length === 0) {
|
|
28000
|
+
skipped.push({ model: rung.model, outcome: "not-agent-eligible" });
|
|
28001
|
+
continue;
|
|
28002
|
+
}
|
|
28003
|
+
if (!agentRows.some((r) => r.skus.includes(GLOBAL_STANDARD))) {
|
|
28004
|
+
skipped.push({ model: rung.model, outcome: "no-global-standard" });
|
|
28005
|
+
continue;
|
|
28006
|
+
}
|
|
28007
|
+
if (modelQuotaVerdict(quota, rung.model).verdict === "no_quota") {
|
|
28008
|
+
skipped.push({ model: rung.model, outcome: "no-quota" });
|
|
28009
|
+
continue;
|
|
28010
|
+
}
|
|
28011
|
+
candidates.push(rung);
|
|
28012
|
+
}
|
|
28013
|
+
return { candidates, skipped };
|
|
28014
|
+
}
|
|
28015
|
+
var QUOTA_RE = /insufficient\s*quota|not enough quota|quota limit|quota\b[^.]{0,40}exceed|exceed\w*\b[^.]{0,40}quota|capacity[^.]{0,40}exceed|exceed\w*\b[^.]{0,40}capacity/i;
|
|
28016
|
+
var REGION_RE = /not available in|not supported in|NotAvailableInRegion|InvalidResourceLocation/i;
|
|
28017
|
+
var CONFLICT_RE = /\bconflict\b|\b409\b/i;
|
|
28018
|
+
function classifyDeployError(message) {
|
|
28019
|
+
if (QUOTA_RE.test(message)) return "deploy-rejected-quota";
|
|
28020
|
+
if (REGION_RE.test(message)) return "deploy-rejected-region";
|
|
28021
|
+
return "deploy-unverified";
|
|
28022
|
+
}
|
|
28023
|
+
async function walkCascade(whitelist, plan, deploy, opts) {
|
|
28024
|
+
const outcomes = /* @__PURE__ */ new Map();
|
|
28025
|
+
for (const s of plan.skipped) outcomes.set(s.model, s);
|
|
28026
|
+
let chosen = null;
|
|
28027
|
+
let aborted = false;
|
|
28028
|
+
for (const rung of plan.candidates) {
|
|
28029
|
+
if (chosen) break;
|
|
28030
|
+
if (opts.now() >= opts.deadlineAt) {
|
|
28031
|
+
aborted = true;
|
|
28032
|
+
break;
|
|
28033
|
+
}
|
|
28034
|
+
let row;
|
|
28035
|
+
try {
|
|
28036
|
+
await deploy(rung);
|
|
28037
|
+
row = { model: rung.model, outcome: "deployed" };
|
|
28038
|
+
chosen = rung;
|
|
28039
|
+
} catch (e) {
|
|
28040
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
28041
|
+
if (CONFLICT_RE.test(msg)) {
|
|
28042
|
+
try {
|
|
28043
|
+
await deploy(rung);
|
|
28044
|
+
row = { model: rung.model, outcome: "deployed" };
|
|
28045
|
+
chosen = rung;
|
|
28046
|
+
} catch (e2) {
|
|
28047
|
+
const msg2 = e2 instanceof Error ? e2.message : String(e2);
|
|
28048
|
+
row = {
|
|
28049
|
+
model: rung.model,
|
|
28050
|
+
outcome: CONFLICT_RE.test(msg2) ? "deploy-unverified" : classifyDeployError(msg2),
|
|
28051
|
+
detail: msg2
|
|
28052
|
+
};
|
|
28053
|
+
}
|
|
28054
|
+
} else {
|
|
28055
|
+
row = { model: rung.model, outcome: classifyDeployError(msg), detail: msg };
|
|
28056
|
+
}
|
|
28057
|
+
}
|
|
28058
|
+
outcomes.set(rung.model, row);
|
|
28059
|
+
opts.onRung?.(row.model, row.outcome);
|
|
28060
|
+
}
|
|
28061
|
+
const trace = whitelist.map(
|
|
28062
|
+
(r) => outcomes.get(r.model) ?? { model: r.model, outcome: aborted ? "aborted-deadline" : "not-reached" }
|
|
28063
|
+
);
|
|
28064
|
+
return { chosen, trace };
|
|
28065
|
+
}
|
|
28066
|
+
var CERTAIN_UNAVAILABLE = /* @__PURE__ */ new Set([
|
|
28067
|
+
"not-in-catalog",
|
|
28068
|
+
"not-agent-eligible",
|
|
28069
|
+
"no-global-standard",
|
|
28070
|
+
"deploy-rejected-region"
|
|
28071
|
+
]);
|
|
28072
|
+
var QUOTA_BLOCKED = /* @__PURE__ */ new Set(["no-quota", "deploy-rejected-quota"]);
|
|
28073
|
+
function decideNote(whitelist, result) {
|
|
28074
|
+
const chosenIdx = result.chosen ? whitelist.findIndex((r) => r.model === result.chosen?.model) : whitelist.length;
|
|
28075
|
+
const better = result.trace.slice(0, Math.max(chosenIdx, 0));
|
|
28076
|
+
const runningModel = result.chosen?.model ?? null;
|
|
28077
|
+
if (chosenIdx === 0) {
|
|
28078
|
+
return { status: "top", runningModel, pitchModel: null, unavailableAbovePitch: [] };
|
|
28079
|
+
}
|
|
28080
|
+
const pitch = better.find((t) => QUOTA_BLOCKED.has(t.outcome));
|
|
28081
|
+
if (pitch) {
|
|
28082
|
+
const pitchIdx = better.findIndex((t) => t.model === pitch.model);
|
|
28083
|
+
return {
|
|
28084
|
+
status: "lesser-quota",
|
|
28085
|
+
runningModel,
|
|
28086
|
+
pitchModel: pitch.model,
|
|
28087
|
+
unavailableAbovePitch: better.slice(0, pitchIdx).filter((t) => CERTAIN_UNAVAILABLE.has(t.outcome)).map((t) => t.model)
|
|
28088
|
+
};
|
|
28089
|
+
}
|
|
28090
|
+
const allCertain = better.length > 0 && better.every((t) => CERTAIN_UNAVAILABLE.has(t.outcome));
|
|
28091
|
+
return {
|
|
28092
|
+
status: allCertain ? "lesser-unavailable" : "lesser-unverified",
|
|
28093
|
+
runningModel,
|
|
28094
|
+
pitchModel: null,
|
|
28095
|
+
unavailableAbovePitch: []
|
|
28096
|
+
};
|
|
28097
|
+
}
|
|
28098
|
+
var listNames = (names) => names.length <= 1 ? names[0] ?? "" : `${names.slice(0, -1).join(", ")} and ${names[names.length - 1]}`;
|
|
28099
|
+
function renderChosenModelNote(d) {
|
|
28100
|
+
const subject = d.runningModel ? `You are running on ${d.runningModel}.` : "You are running on this install's default model.";
|
|
28101
|
+
switch (d.status) {
|
|
28102
|
+
case "top":
|
|
28103
|
+
return `${subject} That is the best available model for this install.`;
|
|
28104
|
+
case "lesser-quota": {
|
|
28105
|
+
const aside = d.unavailableAbovePitch.length > 0 ? ` ${listNames(d.unavailableAbovePitch)} ${d.unavailableAbovePitch.length > 1 ? "are" : "is"} not offered for this install.` : "";
|
|
28106
|
+
return `${subject} A stronger model, ${d.pitchModel ?? ""}, is offered here, but this subscription has no quota for it.${aside} You can offer to help request that quota.`;
|
|
28107
|
+
}
|
|
28108
|
+
case "lesser-unavailable":
|
|
28109
|
+
return `${subject} No stronger model is offered for this install right now.`;
|
|
28110
|
+
case "lesser-unverified":
|
|
28111
|
+
return `${subject} It was not possible to check which stronger models this subscription can run, so do not make claims about what is or is not available.`;
|
|
28112
|
+
}
|
|
28113
|
+
}
|
|
28114
|
+
|
|
28115
|
+
// src/lib/intake-model.ts
|
|
28116
|
+
var DEFAULT_DEADLINE_MS = 18e4;
|
|
28117
|
+
var SCOPE_RE = /\/resourceGroups\/([^/]+)\/providers\/Microsoft\.CognitiveServices\/accounts\/([^/]+)/i;
|
|
28118
|
+
function parseAccountScope(scope) {
|
|
28119
|
+
const m = SCOPE_RE.exec(scope);
|
|
28120
|
+
return m ? { resourceGroup: m[1], account: m[2] } : null;
|
|
28121
|
+
}
|
|
28122
|
+
function narrate(model, outcome, region) {
|
|
28123
|
+
if (outcome === "deployed") return `${model} - ready`;
|
|
28124
|
+
return `${model} - not available for your subscription in ${region}`;
|
|
28125
|
+
}
|
|
28126
|
+
async function accountRegion(account, resourceGroup, fallback) {
|
|
28127
|
+
try {
|
|
28128
|
+
const out = await runAz([
|
|
28129
|
+
"cognitiveservices",
|
|
28130
|
+
"account",
|
|
28131
|
+
"show",
|
|
28132
|
+
"--name",
|
|
28133
|
+
account,
|
|
28134
|
+
"--resource-group",
|
|
28135
|
+
resourceGroup,
|
|
28136
|
+
"--query",
|
|
28137
|
+
"location",
|
|
28138
|
+
"-o",
|
|
28139
|
+
"tsv"
|
|
28140
|
+
]);
|
|
28141
|
+
return out.trim() || fallback;
|
|
28142
|
+
} catch {
|
|
28143
|
+
return fallback;
|
|
28144
|
+
}
|
|
28145
|
+
}
|
|
28146
|
+
async function resolveIntakeModel(args) {
|
|
28147
|
+
const floorTrace = (outcome, detail) => WHITELIST.map((r) => ({ model: r.model, outcome, ...detail === void 0 ? {} : { detail } }));
|
|
28148
|
+
const degradeToFloor = (detail) => {
|
|
28149
|
+
const trace = floorTrace("catalog-unverified", detail);
|
|
28150
|
+
return { model: void 0, note: renderChosenModelNote(decideNote(WHITELIST, { chosen: null, trace })), trace };
|
|
28151
|
+
};
|
|
28152
|
+
const parsed = parseAccountScope(args.accountScope);
|
|
28153
|
+
if (!parsed) return degradeToFloor(`unparseable account scope: ${args.accountScope}`);
|
|
28154
|
+
try {
|
|
28155
|
+
const region = await accountRegion(parsed.account, parsed.resourceGroup, args.fallbackRegion);
|
|
28156
|
+
args.onNarrate?.("choosing the best model your subscription can run...");
|
|
28157
|
+
const [catalog, quota] = await Promise.all([listAgentModels(region), listModelQuota(region)]);
|
|
28158
|
+
const plan = planCascade(WHITELIST, catalog, quota);
|
|
28159
|
+
const deploy = async (rung) => {
|
|
28160
|
+
await ensureDeployment({
|
|
28161
|
+
account: parsed.account,
|
|
28162
|
+
resourceGroup: parsed.resourceGroup,
|
|
28163
|
+
model: rung.model,
|
|
28164
|
+
modelVersion: rung.version,
|
|
28165
|
+
capacity: rung.capacity,
|
|
28166
|
+
format: rung.format
|
|
28167
|
+
});
|
|
28168
|
+
};
|
|
28169
|
+
const start = Date.now();
|
|
28170
|
+
const result = await walkCascade(WHITELIST, plan, deploy, {
|
|
28171
|
+
now: () => Date.now(),
|
|
28172
|
+
deadlineAt: start + (args.deadlineMs ?? DEFAULT_DEADLINE_MS),
|
|
28173
|
+
onRung: (model, outcome) => args.onNarrate?.(narrate(model, outcome, region))
|
|
28174
|
+
});
|
|
28175
|
+
return {
|
|
28176
|
+
model: result.chosen?.model,
|
|
28177
|
+
note: renderChosenModelNote(decideNote(WHITELIST, result)),
|
|
28178
|
+
trace: result.trace
|
|
28179
|
+
};
|
|
28180
|
+
} catch (e) {
|
|
28181
|
+
return degradeToFloor(e instanceof Error ? e.message : String(e));
|
|
28182
|
+
}
|
|
28183
|
+
}
|
|
28184
|
+
|
|
27933
28185
|
// src/commands/bootstrap/ui.ts
|
|
27934
28186
|
function renderDeploySuccess(version, envPath) {
|
|
27935
28187
|
return `${colors.success("\u2713")} Simple Stacey is live (stacey-intake v${version}).
|
|
@@ -28031,13 +28283,24 @@ var BootstrapUiCommand = class extends M8tCommand {
|
|
|
28031
28283
|
await ensureFounderFoundryRole({ credential: credential2, subscriptionId: state.subscriptionId, principalId: oid, accountScope });
|
|
28032
28284
|
const identity = await getSignedInUserIdentity();
|
|
28033
28285
|
out("deploying Simple Stacey (stacey-intake) in the background...");
|
|
28034
|
-
const deployOutcome =
|
|
28035
|
-
|
|
28036
|
-
|
|
28037
|
-
|
|
28038
|
-
|
|
28039
|
-
|
|
28040
|
-
|
|
28286
|
+
const deployOutcome = (async () => {
|
|
28287
|
+
const choice = await resolveIntakeModel({
|
|
28288
|
+
accountScope,
|
|
28289
|
+
fallbackRegion: state.location,
|
|
28290
|
+
onNarrate: out
|
|
28291
|
+
});
|
|
28292
|
+
return deploySimpleStaceyWithRetry({
|
|
28293
|
+
credential: credential2,
|
|
28294
|
+
endpoint,
|
|
28295
|
+
repoRoot,
|
|
28296
|
+
model: choice.model,
|
|
28297
|
+
fieldOverrides: {
|
|
28298
|
+
founder_identity_note: composeFounderIdentityNote(identity),
|
|
28299
|
+
chosen_model_note: choice.note
|
|
28300
|
+
},
|
|
28301
|
+
onWait: out
|
|
28302
|
+
});
|
|
28303
|
+
})().then(
|
|
28041
28304
|
(version) => ({ ok: true, version }),
|
|
28042
28305
|
(error) => ({ ok: false, error: error instanceof Error ? error : new Error(String(error)) })
|
|
28043
28306
|
);
|