@m8t-stack/cli 0.2.44 → 0.2.46
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 +453 -235
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -204,6 +204,19 @@ var init_founder_benchmark = __esm({
|
|
|
204
204
|
}
|
|
205
205
|
});
|
|
206
206
|
|
|
207
|
+
// ../../packages/api-contract/dist/esm/agent-roster.js
|
|
208
|
+
function productVisibilityFor(agentName) {
|
|
209
|
+
return PUBLIC_PRODUCT_AGENTS.has(agentName) ? "public" : "internal";
|
|
210
|
+
}
|
|
211
|
+
var INTAKE_AGENT_NAME, PUBLIC_PRODUCT_AGENTS;
|
|
212
|
+
var init_agent_roster = __esm({
|
|
213
|
+
"../../packages/api-contract/dist/esm/agent-roster.js"() {
|
|
214
|
+
"use strict";
|
|
215
|
+
INTAKE_AGENT_NAME = "azzy-intake";
|
|
216
|
+
PUBLIC_PRODUCT_AGENTS = /* @__PURE__ */ new Set(["stacey", "azzy"]);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
|
|
207
220
|
// ../../packages/api-contract/dist/esm/index.js
|
|
208
221
|
var init_esm = __esm({
|
|
209
222
|
"../../packages/api-contract/dist/esm/index.js"() {
|
|
@@ -220,6 +233,7 @@ var init_esm = __esm({
|
|
|
220
233
|
init_a2a_card();
|
|
221
234
|
init_brain_eval();
|
|
222
235
|
init_founder_benchmark();
|
|
236
|
+
init_agent_roster();
|
|
223
237
|
}
|
|
224
238
|
});
|
|
225
239
|
|
|
@@ -948,7 +962,12 @@ async function createPromptVersion(args) {
|
|
|
948
962
|
const metadata = {
|
|
949
963
|
source: METADATA_SOURCE,
|
|
950
964
|
kind: "prompt",
|
|
951
|
-
persona: args.metadata.persona
|
|
965
|
+
persona: args.metadata.persona,
|
|
966
|
+
// Read by the web app to decide roster membership. Written on EVERY version:
|
|
967
|
+
// createVersion replaces version metadata wholesale rather than merging the
|
|
968
|
+
// previous version's, so omitting it here silently un-publishes an agent on
|
|
969
|
+
// its next re-deploy.
|
|
970
|
+
productVisibility: args.metadata.productVisibility
|
|
952
971
|
};
|
|
953
972
|
if (args.metadata.personaVersion !== null) metadata.personaVersion = args.metadata.personaVersion;
|
|
954
973
|
if (args.metadata.fillableFieldValues !== void 0) {
|
|
@@ -1310,7 +1329,7 @@ var init_enable_hosted_brain = __esm({
|
|
|
1310
1329
|
import { Builtins, Cli } from "clipanion";
|
|
1311
1330
|
|
|
1312
1331
|
// src/lib/package-version.ts
|
|
1313
|
-
var CLI_VERSION = "0.2.
|
|
1332
|
+
var CLI_VERSION = "0.2.46";
|
|
1314
1333
|
|
|
1315
1334
|
// src/lib/render-error.ts
|
|
1316
1335
|
init_errors();
|
|
@@ -16551,6 +16570,7 @@ import * as path12 from "path";
|
|
|
16551
16570
|
import { parse as parseYaml6 } from "yaml";
|
|
16552
16571
|
init_foundry_agents();
|
|
16553
16572
|
init_errors();
|
|
16573
|
+
init_esm();
|
|
16554
16574
|
function findPersonasRoot(hint) {
|
|
16555
16575
|
let dir = path12.resolve(hint);
|
|
16556
16576
|
const fsRoot = path12.parse(dir).root;
|
|
@@ -16616,7 +16636,14 @@ async function deployPromptAdvisor(args) {
|
|
|
16616
16636
|
model,
|
|
16617
16637
|
instructions,
|
|
16618
16638
|
reasoningEffort,
|
|
16619
|
-
metadata: {
|
|
16639
|
+
metadata: {
|
|
16640
|
+
persona: args.persona,
|
|
16641
|
+
personaVersion,
|
|
16642
|
+
fillableFieldValues: JSON.stringify(valuesMap),
|
|
16643
|
+
// Derived here, once, from the agent NAME — so no call site can forget it
|
|
16644
|
+
// and no two call sites can disagree.
|
|
16645
|
+
productVisibility: productVisibilityFor(args.agentName)
|
|
16646
|
+
},
|
|
16620
16647
|
...args.onNotice ? { onNotice: args.onNotice } : {}
|
|
16621
16648
|
});
|
|
16622
16649
|
}
|
|
@@ -18046,6 +18073,7 @@ async function stagePublicImageIfNeeded(args) {
|
|
|
18046
18073
|
}
|
|
18047
18074
|
|
|
18048
18075
|
// src/commands/coder/deploy.ts
|
|
18076
|
+
init_esm();
|
|
18049
18077
|
var SIZE_PRESETS = {
|
|
18050
18078
|
small: { cpu: "0.5", memory: "1Gi" },
|
|
18051
18079
|
medium: { cpu: "1", memory: "2Gi" },
|
|
@@ -18188,7 +18216,14 @@ var CoderDeployCommand = class extends M8tCommand {
|
|
|
18188
18216
|
cpu: preset.cpu,
|
|
18189
18217
|
memory: preset.memory,
|
|
18190
18218
|
env,
|
|
18191
|
-
metadata: {
|
|
18219
|
+
metadata: {
|
|
18220
|
+
...currentMetadata,
|
|
18221
|
+
source: "m8t",
|
|
18222
|
+
kind: "hosted",
|
|
18223
|
+
persona: personaName,
|
|
18224
|
+
personaVersion,
|
|
18225
|
+
productVisibility: productVisibilityFor(this.name)
|
|
18226
|
+
},
|
|
18192
18227
|
onProgress
|
|
18193
18228
|
});
|
|
18194
18229
|
if (typeof this.brain === "string") {
|
|
@@ -18396,6 +18431,7 @@ import * as path18 from "path";
|
|
|
18396
18431
|
import { Command as Command30, Option as Option28 } from "clipanion";
|
|
18397
18432
|
import { DefaultAzureCredential as DefaultAzureCredential15 } from "@azure/identity";
|
|
18398
18433
|
init_errors();
|
|
18434
|
+
init_foundry_agent_get();
|
|
18399
18435
|
init_rbac();
|
|
18400
18436
|
|
|
18401
18437
|
// src/lib/acs-provision.ts
|
|
@@ -18542,6 +18578,12 @@ var AzureExecDeployCommand = class extends M8tCommand {
|
|
|
18542
18578
|
interactive,
|
|
18543
18579
|
endpoint: this.endpoint
|
|
18544
18580
|
});
|
|
18581
|
+
let currentMetadata = {};
|
|
18582
|
+
try {
|
|
18583
|
+
const current = await getAgentVersion({ credential: credential2, projectEndpoint: project.endpoint, agentName: this.name });
|
|
18584
|
+
currentMetadata = { ...current.metadata ?? {} };
|
|
18585
|
+
} catch {
|
|
18586
|
+
}
|
|
18545
18587
|
const staged = await stagePublicImageIfNeeded({ image: requestedImage, project });
|
|
18546
18588
|
for (const n of staged.notes) {
|
|
18547
18589
|
this.context.stderr.write(`${colors.hint("note:")} ${n}
|
|
@@ -18635,7 +18677,7 @@ var AzureExecDeployCommand = class extends M8tCommand {
|
|
|
18635
18677
|
cpu: preset.cpu,
|
|
18636
18678
|
memory: preset.memory,
|
|
18637
18679
|
env,
|
|
18638
|
-
metadata: { source: "m8t", kind: "hosted", persona: personaName, personaVersion },
|
|
18680
|
+
metadata: { ...currentMetadata, source: "m8t", kind: "hosted", persona: personaName, personaVersion, productVisibility: "internal" },
|
|
18639
18681
|
onProgress
|
|
18640
18682
|
});
|
|
18641
18683
|
onProgress?.(`granting Contributor at ${grantScope}\u2026`);
|
|
@@ -19303,6 +19345,7 @@ async function readStamp(opts) {
|
|
|
19303
19345
|
}
|
|
19304
19346
|
|
|
19305
19347
|
// src/lib/platform-converge.ts
|
|
19348
|
+
init_esm();
|
|
19306
19349
|
import * as fs22 from "fs";
|
|
19307
19350
|
import * as path21 from "path";
|
|
19308
19351
|
import { parse as parseYaml10 } from "yaml";
|
|
@@ -19894,6 +19937,10 @@ async function applyPersona(a, ctx, opts) {
|
|
|
19894
19937
|
const metadata = {
|
|
19895
19938
|
...current.metadata ?? {},
|
|
19896
19939
|
persona: a.personaName ?? opts.agentName,
|
|
19940
|
+
// Re-asserted on every converge, not just at initial deploy — heals an install whose
|
|
19941
|
+
// advisor was deployed by a CLI that predates the roster-visibility stamp (see
|
|
19942
|
+
// deploy-prompt-advisor.ts). Derived from the deployed agent name, same as there.
|
|
19943
|
+
productVisibility: productVisibilityFor(opts.agentName),
|
|
19897
19944
|
...values ? { fillableFieldValues: JSON.stringify(values) } : {}
|
|
19898
19945
|
};
|
|
19899
19946
|
const candidate2 = { definition: { ...current.definition, instructions }, metadata };
|
|
@@ -28057,6 +28104,35 @@ import * as path33 from "path";
|
|
|
28057
28104
|
init_errors();
|
|
28058
28105
|
|
|
28059
28106
|
// src/lib/onboarding-profile.ts
|
|
28107
|
+
init_esm();
|
|
28108
|
+
function describeBlockRejection(reason) {
|
|
28109
|
+
switch (reason) {
|
|
28110
|
+
case "unknown-schema-version":
|
|
28111
|
+
return "the onboarding block's schema_version was missing or unrecognized";
|
|
28112
|
+
case "unexpected-key":
|
|
28113
|
+
return "the onboarding JSON carried a field it shouldn't have";
|
|
28114
|
+
case "missing-key":
|
|
28115
|
+
return "the onboarding block was missing a required field";
|
|
28116
|
+
case "non-string-value":
|
|
28117
|
+
return "the onboarding block held a value of the wrong type";
|
|
28118
|
+
case "disallowed-value":
|
|
28119
|
+
return "an onboarding block field held a value outside its allowed set";
|
|
28120
|
+
case "too-many-pending-requests":
|
|
28121
|
+
return "the onboarding block listed more pending requests than the one allowed";
|
|
28122
|
+
case "malformed-json":
|
|
28123
|
+
return "the onboarding block's JSON could not be safely parsed \u2014 check for duplicate keys, excessive nesting, or a syntax error";
|
|
28124
|
+
case "multiple-artifacts":
|
|
28125
|
+
return "more than one onboarding block was found in your onboarding conversation";
|
|
28126
|
+
case "unreadable-fences":
|
|
28127
|
+
return "the message's code fences could not be reliably delimited, so any onboarding block inside them could not be safely read";
|
|
28128
|
+
case "mistagged-fence":
|
|
28129
|
+
return "the onboarding block was inside a code fence that wasn't tagged json, so it could not be safely read";
|
|
28130
|
+
case "unfenced-artifact":
|
|
28131
|
+
return "the onboarding block appeared outside of any code fence, so it could not be safely read";
|
|
28132
|
+
case "no-artifact":
|
|
28133
|
+
return "no onboarding block was found";
|
|
28134
|
+
}
|
|
28135
|
+
}
|
|
28060
28136
|
var COMPANY_PROFILE_PATH = "memory/company-profile.md";
|
|
28061
28137
|
var DEFAULT_MEMORY_INDEX_HEADER = [
|
|
28062
28138
|
`# Memory index`,
|
|
@@ -28178,24 +28254,96 @@ function hasValidUniqueJsonKeys(source) {
|
|
|
28178
28254
|
return false;
|
|
28179
28255
|
}
|
|
28180
28256
|
}
|
|
28257
|
+
var V3_BLOCK_KEYS = ["schema_version", "founder", "company", "advisor_email", "pending_requests"];
|
|
28258
|
+
var V3_FOUNDER_KEYS = ["name", "email", "azure_identity_note"];
|
|
28259
|
+
var V3_COMPANY_KEYS = ["name", "one_liner"];
|
|
28260
|
+
var V3_ADDRESS_KEYS = ["address", "city", "postal_code", "country"];
|
|
28261
|
+
var V3_REQUEST_KEYS = ["type", "model", "region", "consent", "company_address"];
|
|
28262
|
+
function exactStringRecord(value, keys) {
|
|
28263
|
+
if (!isRecord(value)) return "non-string-value";
|
|
28264
|
+
const present = new Set(Object.keys(value));
|
|
28265
|
+
for (const key2 of keys) if (!present.has(key2)) return "missing-key";
|
|
28266
|
+
if (present.size !== keys.length) return "unexpected-key";
|
|
28267
|
+
for (const key2 of keys) if (typeof value[key2] !== "string") return "non-string-value";
|
|
28268
|
+
return null;
|
|
28269
|
+
}
|
|
28270
|
+
function canonicalPendingRequests(value) {
|
|
28271
|
+
if (!Array.isArray(value)) return { ok: false, reason: "non-string-value" };
|
|
28272
|
+
if (value.length > 1) return { ok: false, reason: "too-many-pending-requests" };
|
|
28273
|
+
const requests = [];
|
|
28274
|
+
for (const entry of value) {
|
|
28275
|
+
if (!isRecord(entry)) return { ok: false, reason: "non-string-value" };
|
|
28276
|
+
const present = new Set(Object.keys(entry));
|
|
28277
|
+
for (const key2 of V3_REQUEST_KEYS) {
|
|
28278
|
+
if (!present.has(key2)) return { ok: false, reason: "missing-key" };
|
|
28279
|
+
}
|
|
28280
|
+
if (present.size !== V3_REQUEST_KEYS.length) return { ok: false, reason: "unexpected-key" };
|
|
28281
|
+
if (entry.type !== "quota") return { ok: false, reason: "disallowed-value" };
|
|
28282
|
+
if (entry.consent !== "submit" && entry.consent !== "prepare") return { ok: false, reason: "disallowed-value" };
|
|
28283
|
+
if (typeof entry.model !== "string" || typeof entry.region !== "string") {
|
|
28284
|
+
return { ok: false, reason: "non-string-value" };
|
|
28285
|
+
}
|
|
28286
|
+
if (entry.company_address !== null) {
|
|
28287
|
+
const bad = exactStringRecord(entry.company_address, V3_ADDRESS_KEYS);
|
|
28288
|
+
if (bad) return { ok: false, reason: bad };
|
|
28289
|
+
}
|
|
28290
|
+
requests.push(entry);
|
|
28291
|
+
}
|
|
28292
|
+
return { ok: true, requests };
|
|
28293
|
+
}
|
|
28294
|
+
function canonicalV3Block(value) {
|
|
28295
|
+
const present = new Set(Object.keys(value));
|
|
28296
|
+
for (const key2 of V3_BLOCK_KEYS) if (!present.has(key2)) return { ok: false, reason: "missing-key" };
|
|
28297
|
+
if (present.size !== V3_BLOCK_KEYS.length) return { ok: false, reason: "unexpected-key" };
|
|
28298
|
+
const founderBad = exactStringRecord(value.founder, V3_FOUNDER_KEYS);
|
|
28299
|
+
if (founderBad) return { ok: false, reason: founderBad };
|
|
28300
|
+
const companyBad = exactStringRecord(value.company, V3_COMPANY_KEYS);
|
|
28301
|
+
if (companyBad) return { ok: false, reason: companyBad };
|
|
28302
|
+
if (value.advisor_email !== null && typeof value.advisor_email !== "string") {
|
|
28303
|
+
return { ok: false, reason: "non-string-value" };
|
|
28304
|
+
}
|
|
28305
|
+
const requests = canonicalPendingRequests(value.pending_requests);
|
|
28306
|
+
if (!requests.ok) return requests;
|
|
28307
|
+
const founder = value.founder;
|
|
28308
|
+
const company = value.company;
|
|
28309
|
+
return {
|
|
28310
|
+
ok: true,
|
|
28311
|
+
block: {
|
|
28312
|
+
schema_version: "3",
|
|
28313
|
+
founder_name: founder.name,
|
|
28314
|
+
founder_email: founder.email,
|
|
28315
|
+
azure_identity_note: founder.azure_identity_note,
|
|
28316
|
+
company_name: company.name,
|
|
28317
|
+
context: company.one_liner,
|
|
28318
|
+
advisor_name: "",
|
|
28319
|
+
advisor_email: typeof value.advisor_email === "string" ? value.advisor_email : "",
|
|
28320
|
+
pending_requests: requests.requests
|
|
28321
|
+
}
|
|
28322
|
+
};
|
|
28323
|
+
}
|
|
28181
28324
|
function canonicalBlock(value) {
|
|
28182
|
-
if (!isRecord(value)) return
|
|
28183
|
-
|
|
28184
|
-
|
|
28185
|
-
|
|
28186
|
-
if (value.schema_version !== "2") return null;
|
|
28325
|
+
if (!isRecord(value)) return { ok: false, reason: "non-string-value" };
|
|
28326
|
+
if (value.schema_version === "3") return canonicalV3Block(value);
|
|
28327
|
+
if (value.schema_version !== "2") return { ok: false, reason: "unknown-schema-version" };
|
|
28328
|
+
const keys = new Set(Object.keys(value));
|
|
28187
28329
|
for (const key2 of ONBOARDING_BLOCK_KEYS) {
|
|
28188
|
-
if (
|
|
28330
|
+
if (!keys.has(key2)) return { ok: false, reason: "missing-key" };
|
|
28189
28331
|
}
|
|
28190
|
-
return
|
|
28332
|
+
if (keys.size !== ONBOARDING_BLOCK_KEYS.length) return { ok: false, reason: "unexpected-key" };
|
|
28333
|
+
for (const key2 of ONBOARDING_BLOCK_KEYS) {
|
|
28334
|
+
if (typeof value[key2] !== "string") return { ok: false, reason: "non-string-value" };
|
|
28335
|
+
}
|
|
28336
|
+
return { ok: true, block: value };
|
|
28191
28337
|
}
|
|
28192
|
-
function
|
|
28338
|
+
function parseOnboardingArtifactResult(machineText) {
|
|
28193
28339
|
const fencePattern = /^```([^\r\n]*)\r?\n([\s\S]*?)^```[ \t]*(?=\r?$)/gm;
|
|
28194
28340
|
const fences = [...machineText.matchAll(fencePattern)];
|
|
28195
28341
|
const jsonFenceStarts = [...machineText.matchAll(/^```[ \t]*json[ \t]*\r?$/gm)];
|
|
28196
28342
|
const matchedJsonFences = fences.filter((match) => match[1].trim() === "json");
|
|
28197
|
-
if (jsonFenceStarts.length !== matchedJsonFences.length) return
|
|
28198
|
-
if (fences.some((match) => match[1].trim() !== "json" && /"m8t_onboarding"\s*:/.test(match[2])))
|
|
28343
|
+
if (jsonFenceStarts.length !== matchedJsonFences.length) return { ok: false, reason: "unreadable-fences" };
|
|
28344
|
+
if (fences.some((match) => match[1].trim() !== "json" && /"m8t_onboarding"\s*:/.test(match[2]))) {
|
|
28345
|
+
return { ok: false, reason: "mistagged-fence" };
|
|
28346
|
+
}
|
|
28199
28347
|
let outsideFences = "";
|
|
28200
28348
|
let previousEnd = 0;
|
|
28201
28349
|
for (const fence of fences) {
|
|
@@ -28204,43 +28352,48 @@ function parseOnboardingArtifact(machineText) {
|
|
|
28204
28352
|
previousEnd = start + fence[0].length;
|
|
28205
28353
|
}
|
|
28206
28354
|
outsideFences += machineText.slice(previousEnd);
|
|
28207
|
-
if (/"m8t_onboarding"\s*:/.test(outsideFences)) return
|
|
28355
|
+
if (/"m8t_onboarding"\s*:/.test(outsideFences)) return { ok: false, reason: "unfenced-artifact" };
|
|
28208
28356
|
const artifacts = [];
|
|
28209
28357
|
for (const fence of matchedJsonFences) {
|
|
28210
28358
|
const json = fence[2].trim();
|
|
28211
28359
|
let parsed;
|
|
28212
28360
|
if (!hasValidUniqueJsonKeys(json)) {
|
|
28213
|
-
if (json.includes("m8t_onboarding")) return
|
|
28361
|
+
if (json.includes("m8t_onboarding")) return { ok: false, reason: "malformed-json" };
|
|
28214
28362
|
continue;
|
|
28215
28363
|
}
|
|
28216
28364
|
try {
|
|
28217
28365
|
parsed = JSON.parse(json);
|
|
28218
28366
|
} catch {
|
|
28219
|
-
if (json.includes("m8t_onboarding")) return
|
|
28367
|
+
if (json.includes("m8t_onboarding")) return { ok: false, reason: "malformed-json" };
|
|
28220
28368
|
continue;
|
|
28221
28369
|
}
|
|
28222
28370
|
if (!isRecord(parsed) || !Object.hasOwn(parsed, "m8t_onboarding")) continue;
|
|
28223
|
-
if (Object.keys(parsed).length !== 1) return
|
|
28224
|
-
const
|
|
28225
|
-
if (!
|
|
28371
|
+
if (Object.keys(parsed).length !== 1) return { ok: false, reason: "unexpected-key" };
|
|
28372
|
+
const outcome = canonicalBlock(parsed.m8t_onboarding);
|
|
28373
|
+
if (!outcome.ok) return outcome;
|
|
28226
28374
|
const start = fence.index;
|
|
28227
|
-
artifacts.push({ block, start, end: start + fence[0].length });
|
|
28375
|
+
artifacts.push({ block: outcome.block, start, end: start + fence[0].length });
|
|
28228
28376
|
}
|
|
28229
|
-
if (artifacts.length
|
|
28377
|
+
if (artifacts.length === 0) return { ok: false, reason: "no-artifact" };
|
|
28378
|
+
if (artifacts.length > 1) return { ok: false, reason: "multiple-artifacts" };
|
|
28230
28379
|
const artifact = artifacts[0];
|
|
28231
28380
|
const before = machineText.slice(0, artifact.start).trimEnd();
|
|
28232
28381
|
const after = machineText.slice(artifact.end).trimStart();
|
|
28233
28382
|
return {
|
|
28234
|
-
|
|
28235
|
-
|
|
28236
|
-
|
|
28383
|
+
ok: true,
|
|
28384
|
+
artifact: {
|
|
28385
|
+
block: artifact.block,
|
|
28386
|
+
machineText,
|
|
28387
|
+
speechText: [before, after].filter((part) => part.length > 0).join("\n").trim()
|
|
28388
|
+
}
|
|
28237
28389
|
};
|
|
28238
28390
|
}
|
|
28239
28391
|
var EMPTY_PROFILE_RESULT = {
|
|
28240
28392
|
hadIntake: false,
|
|
28241
28393
|
block: null,
|
|
28242
28394
|
machineText: null,
|
|
28243
|
-
speechText: null
|
|
28395
|
+
speechText: null,
|
|
28396
|
+
rejection: null
|
|
28244
28397
|
};
|
|
28245
28398
|
async function readCursorPages(args) {
|
|
28246
28399
|
const all = [];
|
|
@@ -28314,7 +28467,7 @@ async function findOnboardingProfile(args) {
|
|
|
28314
28467
|
const conversations = orderNewest(listed.flatMap((value, ordinal) => {
|
|
28315
28468
|
if (!isRecord(value) || typeof value.id !== "string" || value.id.length === 0 || !isRecord(value.metadata)) return [];
|
|
28316
28469
|
const metadata = value.metadata;
|
|
28317
|
-
if (metadata.app !== "m8t-webapp" || metadata.agent !==
|
|
28470
|
+
if (metadata.app !== "m8t-webapp" || metadata.agent !== INTAKE_AGENT_NAME) return [];
|
|
28318
28471
|
return [{
|
|
28319
28472
|
id: value.id,
|
|
28320
28473
|
createdAt: timestamp(value.created_at) !== Number.NEGATIVE_INFINITY ? timestamp(value.created_at) : timestamp(metadata.createdAt),
|
|
@@ -28328,14 +28481,14 @@ async function findOnboardingProfile(args) {
|
|
|
28328
28481
|
headers: H,
|
|
28329
28482
|
fetchImpl: doFetch
|
|
28330
28483
|
});
|
|
28331
|
-
if (!items) return { hadIntake: true, block: null, machineText: null, speechText: null };
|
|
28484
|
+
if (!items) return { hadIntake: true, block: null, machineText: null, speechText: null, rejection: null };
|
|
28332
28485
|
const assistantItems = orderNewest(items.flatMap((value, ordinal) => {
|
|
28333
28486
|
if (!isRecord(value) || value.type !== "message" || value.role !== "assistant" || !Array.isArray(value.content)) return [];
|
|
28334
28487
|
const id = typeof value.id === "string" ? value.id : "";
|
|
28335
28488
|
return [{ value, id, createdAt: timestamp(value.created_at), ordinal }];
|
|
28336
28489
|
}));
|
|
28337
28490
|
const artifacts = [];
|
|
28338
|
-
let
|
|
28491
|
+
let rejection = null;
|
|
28339
28492
|
for (const item of assistantItems) {
|
|
28340
28493
|
const content = item.value.content;
|
|
28341
28494
|
const machineText = content.flatMap((part) => {
|
|
@@ -28344,23 +28497,32 @@ async function findOnboardingProfile(args) {
|
|
|
28344
28497
|
if (typeof part.transcript === "string") return [part.transcript];
|
|
28345
28498
|
return [];
|
|
28346
28499
|
}).join("\n");
|
|
28347
|
-
const
|
|
28348
|
-
if (
|
|
28349
|
-
else if (machineText.includes("m8t_onboarding"))
|
|
28500
|
+
const result = parseOnboardingArtifactResult(machineText);
|
|
28501
|
+
if (result.ok) artifacts.push(result.artifact);
|
|
28502
|
+
else if (machineText.includes("m8t_onboarding")) rejection ??= result.reason;
|
|
28350
28503
|
}
|
|
28351
|
-
if (
|
|
28352
|
-
return {
|
|
28504
|
+
if (artifacts.length === 0) {
|
|
28505
|
+
return {
|
|
28506
|
+
hadIntake: true,
|
|
28507
|
+
block: null,
|
|
28508
|
+
machineText: null,
|
|
28509
|
+
speechText: null,
|
|
28510
|
+
rejection: rejection ?? "no-artifact"
|
|
28511
|
+
};
|
|
28353
28512
|
}
|
|
28354
28513
|
const artifact = artifacts[0];
|
|
28355
28514
|
return {
|
|
28356
28515
|
hadIntake: true,
|
|
28357
28516
|
block: artifact.block,
|
|
28358
28517
|
machineText: artifact.machineText,
|
|
28359
|
-
speechText: artifact.speechText
|
|
28518
|
+
speechText: artifact.speechText,
|
|
28519
|
+
rejection: null,
|
|
28520
|
+
...artifacts.length > 1 ? { supersededCount: artifacts.length - 1 } : {}
|
|
28360
28521
|
};
|
|
28361
28522
|
}
|
|
28523
|
+
var dash = (v) => v?.trim() ? v.trim() : "\u2014";
|
|
28524
|
+
var bullet = (label, value) => value === void 0 ? [] : [`- **${label}:** ${dash(value)}`];
|
|
28362
28525
|
function renderCompanyProfile(block, now = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
28363
|
-
const dash = (v) => v?.trim() ? v.trim() : "\u2014";
|
|
28364
28526
|
const profileMd = [
|
|
28365
28527
|
`---`,
|
|
28366
28528
|
`type: memory`,
|
|
@@ -28375,22 +28537,30 @@ function renderCompanyProfile(block, now = (/* @__PURE__ */ new Date()).toISOStr
|
|
|
28375
28537
|
``,
|
|
28376
28538
|
`_Seeded from the onboarding questionnaire._`,
|
|
28377
28539
|
``,
|
|
28378
|
-
|
|
28379
|
-
|
|
28380
|
-
|
|
28381
|
-
|
|
28540
|
+
...bullet("Company", block.company_name),
|
|
28541
|
+
...bullet("Stage", block.company_stage),
|
|
28542
|
+
...bullet("ICP", block.icp),
|
|
28543
|
+
...bullet("Industry", block.industry),
|
|
28544
|
+
...bullet("Team size", block.team_size),
|
|
28382
28545
|
``,
|
|
28383
28546
|
`## Context`,
|
|
28384
28547
|
``,
|
|
28385
|
-
block.context.trim(),
|
|
28548
|
+
(block.context ?? "").trim(),
|
|
28386
28549
|
``
|
|
28387
28550
|
].join("\n");
|
|
28388
|
-
const bits = [
|
|
28389
|
-
|
|
28551
|
+
const bits = [
|
|
28552
|
+
block.company_name?.trim(),
|
|
28553
|
+
block.company_stage?.trim(),
|
|
28554
|
+
block.industry?.trim(),
|
|
28555
|
+
block.icp?.trim() ? `ICP ${block.icp.trim()}` : void 0
|
|
28556
|
+
].filter(Boolean).join(" \xB7 ");
|
|
28557
|
+
const summary = bits || (block.schema_version === "3" ? "no details captured at intake" : "");
|
|
28558
|
+
const memoryIndexLine = `- \`${COMPANY_PROFILE_PATH}\` \u2014 **Company profile**: ${summary}. (seeded from onboarding)`;
|
|
28390
28559
|
return { profileMd, memoryIndexLine };
|
|
28391
28560
|
}
|
|
28392
28561
|
var FOUNDER_RECORD_PATH = "memory/founder.md";
|
|
28393
|
-
var NOT_CAPTURED = "_not captured yet \u2014
|
|
28562
|
+
var NOT_CAPTURED = "_not captured yet \u2014 just tell me and I'll add it_";
|
|
28563
|
+
var REGION_UNKNOWN_AT_INTAKE = "_not known at intake \u2014 filled in when the request is filed_";
|
|
28394
28564
|
function renderFounderRecord(block, inputs, now = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
28395
28565
|
const pick = (...vals) => vals.map((v) => v?.trim()).find(Boolean) ?? "";
|
|
28396
28566
|
const founderName = pick(block.founder_name, inputs.azIdentity?.name);
|
|
@@ -28398,8 +28568,29 @@ function renderFounderRecord(block, inputs, now = (/* @__PURE__ */ new Date()).t
|
|
|
28398
28568
|
const advisorName = (block.advisor_name ?? "").trim();
|
|
28399
28569
|
const advisorEmail = (block.advisor_email ?? "").trim();
|
|
28400
28570
|
const subscription = (inputs.subscriptionId ?? "").trim();
|
|
28401
|
-
const teamSize = (block.team_size ?? "").trim();
|
|
28402
28571
|
const advisorRendered = advisorName || advisorEmail ? [advisorName, advisorEmail ? `<${advisorEmail}>` : ""].filter(Boolean).join(" ") : NOT_CAPTURED;
|
|
28572
|
+
const request = block.pending_requests?.[0];
|
|
28573
|
+
const requestLines = request === void 0 ? [] : (() => {
|
|
28574
|
+
const modelLabel = request.model.trim() ? `\`${request.model.trim()}\`` : "(model not recorded)";
|
|
28575
|
+
const consentLabel = request.consent === "submit" ? "submit the request" : "prepare it only, don't submit";
|
|
28576
|
+
const addressLine = request.company_address === null ? "not provided \u2014 the founder skipped it" : [
|
|
28577
|
+
request.company_address.address,
|
|
28578
|
+
request.company_address.city,
|
|
28579
|
+
request.company_address.postal_code,
|
|
28580
|
+
request.company_address.country
|
|
28581
|
+
].map((part) => part.trim()).filter(Boolean).join(", ") || "not provided";
|
|
28582
|
+
return [
|
|
28583
|
+
``,
|
|
28584
|
+
`## Requested at onboarding`,
|
|
28585
|
+
``,
|
|
28586
|
+
`_The founder asked for this during setup. Act on it when they bring it up._`,
|
|
28587
|
+
``,
|
|
28588
|
+
`- **What:** ${request.type} increase for ${modelLabel}`,
|
|
28589
|
+
`- **Region:** ${request.region.trim() || REGION_UNKNOWN_AT_INTAKE}`,
|
|
28590
|
+
`- **Consent:** ${consentLabel}`,
|
|
28591
|
+
`- **Company address:** ${addressLine}`
|
|
28592
|
+
];
|
|
28593
|
+
})();
|
|
28403
28594
|
const founderMd = [
|
|
28404
28595
|
`---`,
|
|
28405
28596
|
`type: memory`,
|
|
@@ -28418,7 +28609,8 @@ function renderFounderRecord(block, inputs, now = (/* @__PURE__ */ new Date()).t
|
|
|
28418
28609
|
`- **Founder email (company_email):** ${founderEmail || NOT_CAPTURED}`,
|
|
28419
28610
|
`- **Microsoft Startup Advisor (SA):** ${advisorRendered}`,
|
|
28420
28611
|
`- **Azure subscription:** ${subscription || NOT_CAPTURED}`,
|
|
28421
|
-
|
|
28612
|
+
...bullet("Team size", block.team_size),
|
|
28613
|
+
...requestLines,
|
|
28422
28614
|
``
|
|
28423
28615
|
].join("\n");
|
|
28424
28616
|
const idxAdvisor = advisorEmail || advisorName || "\u2014";
|
|
@@ -28427,7 +28619,168 @@ function renderFounderRecord(block, inputs, now = (/* @__PURE__ */ new Date()).t
|
|
|
28427
28619
|
return { founderMd, memoryIndexLine };
|
|
28428
28620
|
}
|
|
28429
28621
|
|
|
28622
|
+
// src/lib/model-cascade.ts
|
|
28623
|
+
var WHITELIST = [
|
|
28624
|
+
{ model: "gpt-5.6-luna", format: "OpenAI", version: "2026-07-09", capacity: 100 },
|
|
28625
|
+
{ model: "gpt-5.6-sol", format: "OpenAI", version: "2026-07-09", capacity: 100 },
|
|
28626
|
+
{ model: "gpt-5.6-terra", format: "OpenAI", version: "2026-07-09", capacity: 100 },
|
|
28627
|
+
{ model: "gpt-5.4", format: "OpenAI", version: "2026-03-05", capacity: 100 },
|
|
28628
|
+
{ model: "grok-4.3", format: "xAI", version: "1", capacity: 100 },
|
|
28629
|
+
{ model: "gpt-4.1-mini", format: "OpenAI", version: "2025-04-14", capacity: 50 }
|
|
28630
|
+
];
|
|
28631
|
+
var GLOBAL_STANDARD = "GlobalStandard";
|
|
28632
|
+
function planCascade(whitelist, catalog, quota) {
|
|
28633
|
+
if (!catalog.ok) {
|
|
28634
|
+
return {
|
|
28635
|
+
candidates: [],
|
|
28636
|
+
skipped: whitelist.map((r) => ({ model: r.model, outcome: "catalog-unverified", detail: catalog.error }))
|
|
28637
|
+
};
|
|
28638
|
+
}
|
|
28639
|
+
const rowsByName = /* @__PURE__ */ new Map();
|
|
28640
|
+
for (const row of catalog.rows) {
|
|
28641
|
+
const list = rowsByName.get(row.name);
|
|
28642
|
+
if (list) list.push(row);
|
|
28643
|
+
else rowsByName.set(row.name, [row]);
|
|
28644
|
+
}
|
|
28645
|
+
const candidates = [];
|
|
28646
|
+
const skipped = [];
|
|
28647
|
+
for (const rung of whitelist) {
|
|
28648
|
+
const rows = rowsByName.get(rung.model);
|
|
28649
|
+
if (!rows || rows.length === 0) {
|
|
28650
|
+
skipped.push({ model: rung.model, outcome: "not-in-catalog" });
|
|
28651
|
+
continue;
|
|
28652
|
+
}
|
|
28653
|
+
const agentRows = rows.filter((r) => r.agentsV2);
|
|
28654
|
+
if (agentRows.length === 0) {
|
|
28655
|
+
skipped.push({ model: rung.model, outcome: "not-agent-eligible" });
|
|
28656
|
+
continue;
|
|
28657
|
+
}
|
|
28658
|
+
if (!agentRows.some((r) => r.skus.includes(GLOBAL_STANDARD))) {
|
|
28659
|
+
skipped.push({ model: rung.model, outcome: "no-global-standard" });
|
|
28660
|
+
continue;
|
|
28661
|
+
}
|
|
28662
|
+
if (modelQuotaVerdict(quota, rung.model).verdict === "no_quota") {
|
|
28663
|
+
skipped.push({ model: rung.model, outcome: "no-quota" });
|
|
28664
|
+
continue;
|
|
28665
|
+
}
|
|
28666
|
+
candidates.push(rung);
|
|
28667
|
+
}
|
|
28668
|
+
return { candidates, skipped };
|
|
28669
|
+
}
|
|
28670
|
+
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;
|
|
28671
|
+
var REGION_RE = /not available in|not supported in|NotAvailableInRegion|InvalidResourceLocation/i;
|
|
28672
|
+
var CONFLICT_RE = /\bconflict\b|\b409\b/i;
|
|
28673
|
+
function classifyDeployError(message) {
|
|
28674
|
+
if (QUOTA_RE.test(message)) return "deploy-rejected-quota";
|
|
28675
|
+
if (REGION_RE.test(message)) return "deploy-rejected-region";
|
|
28676
|
+
return "deploy-unverified";
|
|
28677
|
+
}
|
|
28678
|
+
async function walkCascade(whitelist, plan, deploy, opts) {
|
|
28679
|
+
const outcomes = /* @__PURE__ */ new Map();
|
|
28680
|
+
for (const s of plan.skipped) outcomes.set(s.model, s);
|
|
28681
|
+
let chosen = null;
|
|
28682
|
+
let aborted = false;
|
|
28683
|
+
for (const rung of plan.candidates) {
|
|
28684
|
+
if (chosen) break;
|
|
28685
|
+
if (opts.now() >= opts.deadlineAt) {
|
|
28686
|
+
aborted = true;
|
|
28687
|
+
break;
|
|
28688
|
+
}
|
|
28689
|
+
let row;
|
|
28690
|
+
try {
|
|
28691
|
+
await deploy(rung);
|
|
28692
|
+
row = { model: rung.model, outcome: "deployed" };
|
|
28693
|
+
chosen = rung;
|
|
28694
|
+
} catch (e) {
|
|
28695
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
28696
|
+
if (CONFLICT_RE.test(msg)) {
|
|
28697
|
+
try {
|
|
28698
|
+
await deploy(rung);
|
|
28699
|
+
row = { model: rung.model, outcome: "deployed" };
|
|
28700
|
+
chosen = rung;
|
|
28701
|
+
} catch (e2) {
|
|
28702
|
+
const msg2 = e2 instanceof Error ? e2.message : String(e2);
|
|
28703
|
+
row = {
|
|
28704
|
+
model: rung.model,
|
|
28705
|
+
outcome: CONFLICT_RE.test(msg2) ? "deploy-unverified" : classifyDeployError(msg2),
|
|
28706
|
+
detail: msg2
|
|
28707
|
+
};
|
|
28708
|
+
}
|
|
28709
|
+
} else {
|
|
28710
|
+
row = { model: rung.model, outcome: classifyDeployError(msg), detail: msg };
|
|
28711
|
+
}
|
|
28712
|
+
}
|
|
28713
|
+
outcomes.set(rung.model, row);
|
|
28714
|
+
opts.onRung?.(row.model, row.outcome);
|
|
28715
|
+
}
|
|
28716
|
+
const trace = whitelist.map(
|
|
28717
|
+
(r) => outcomes.get(r.model) ?? { model: r.model, outcome: aborted ? "aborted-deadline" : "not-reached" }
|
|
28718
|
+
);
|
|
28719
|
+
return { chosen, trace };
|
|
28720
|
+
}
|
|
28721
|
+
var QUOTA_INVITATION = "You can offer to help request that quota.";
|
|
28722
|
+
var CERTAIN_UNAVAILABLE = /* @__PURE__ */ new Set([
|
|
28723
|
+
"not-in-catalog",
|
|
28724
|
+
"not-agent-eligible",
|
|
28725
|
+
"no-global-standard",
|
|
28726
|
+
"deploy-rejected-region"
|
|
28727
|
+
]);
|
|
28728
|
+
var QUOTA_BLOCKED = /* @__PURE__ */ new Set(["no-quota", "deploy-rejected-quota"]);
|
|
28729
|
+
function decideNote(whitelist, result) {
|
|
28730
|
+
const chosenIdx = result.chosen ? whitelist.findIndex((r) => r.model === result.chosen?.model) : whitelist.length;
|
|
28731
|
+
const better = result.trace.slice(0, Math.max(chosenIdx, 0));
|
|
28732
|
+
const runningModel = result.chosen?.model ?? null;
|
|
28733
|
+
if (chosenIdx === 0) {
|
|
28734
|
+
return { status: "top", runningModel, pitchModel: null, unavailableAbovePitch: [] };
|
|
28735
|
+
}
|
|
28736
|
+
const pitch = better.find((t) => QUOTA_BLOCKED.has(t.outcome));
|
|
28737
|
+
if (pitch) {
|
|
28738
|
+
const pitchIdx = better.findIndex((t) => t.model === pitch.model);
|
|
28739
|
+
return {
|
|
28740
|
+
status: "lesser-quota",
|
|
28741
|
+
runningModel,
|
|
28742
|
+
pitchModel: pitch.model,
|
|
28743
|
+
unavailableAbovePitch: better.slice(0, pitchIdx).filter((t) => CERTAIN_UNAVAILABLE.has(t.outcome)).map((t) => t.model)
|
|
28744
|
+
};
|
|
28745
|
+
}
|
|
28746
|
+
const allCertain = better.length > 0 && better.every((t) => CERTAIN_UNAVAILABLE.has(t.outcome));
|
|
28747
|
+
return {
|
|
28748
|
+
status: allCertain ? "lesser-unavailable" : "lesser-unverified",
|
|
28749
|
+
runningModel,
|
|
28750
|
+
pitchModel: null,
|
|
28751
|
+
unavailableAbovePitch: []
|
|
28752
|
+
};
|
|
28753
|
+
}
|
|
28754
|
+
var listNames = (names) => names.length <= 1 ? names[0] ?? "" : `${names.slice(0, -1).join(", ")} and ${names[names.length - 1]}`;
|
|
28755
|
+
function renderChosenModelNote(d) {
|
|
28756
|
+
const subject = d.runningModel ? `You are running on ${d.runningModel}.` : "You are running on this install's default model.";
|
|
28757
|
+
switch (d.status) {
|
|
28758
|
+
case "top":
|
|
28759
|
+
return `${subject} That is the best available model for this install.`;
|
|
28760
|
+
case "lesser-quota": {
|
|
28761
|
+
const aside = d.unavailableAbovePitch.length > 0 ? ` ${listNames(d.unavailableAbovePitch)} ${d.unavailableAbovePitch.length > 1 ? "are" : "is"} not offered for this install.` : "";
|
|
28762
|
+
return `${subject} A stronger model, ${d.pitchModel ?? ""}, is offered here, but this subscription has no quota for it.${aside} ${QUOTA_INVITATION}`;
|
|
28763
|
+
}
|
|
28764
|
+
case "lesser-unavailable":
|
|
28765
|
+
return `${subject} No stronger model is offered for this install right now.`;
|
|
28766
|
+
case "lesser-unverified":
|
|
28767
|
+
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.`;
|
|
28768
|
+
}
|
|
28769
|
+
}
|
|
28770
|
+
|
|
28430
28771
|
// src/lib/founder-identity.ts
|
|
28772
|
+
var INVENTORY_INVITATION = "You can offer to walk the founder through these resources.";
|
|
28773
|
+
var NOTE_INVITATIONS = [QUOTA_INVITATION, INVENTORY_INVITATION];
|
|
28774
|
+
function escapeRegExp(value) {
|
|
28775
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
28776
|
+
}
|
|
28777
|
+
function stripNoteInvitations(value) {
|
|
28778
|
+
let out = value;
|
|
28779
|
+
for (const sentence of NOTE_INVITATIONS) {
|
|
28780
|
+
out = out.replace(new RegExp(escapeRegExp(sentence), "gi"), " ");
|
|
28781
|
+
}
|
|
28782
|
+
return out.replace(/\s{2,}/g, " ").trim();
|
|
28783
|
+
}
|
|
28431
28784
|
function deriveEmailCandidate(raw) {
|
|
28432
28785
|
const mail = (raw.mail ?? "").trim();
|
|
28433
28786
|
if (mail) return mail;
|
|
@@ -28459,11 +28812,13 @@ async function getSignedInUserIdentity(runAzImpl = runAz) {
|
|
|
28459
28812
|
}
|
|
28460
28813
|
}
|
|
28461
28814
|
function composeFounderIdentityNote(id) {
|
|
28462
|
-
|
|
28463
|
-
|
|
28815
|
+
const name = stripNoteInvitations(id.name);
|
|
28816
|
+
const email = stripNoteInvitations(id.email);
|
|
28817
|
+
if (name && email) {
|
|
28818
|
+
return `You're speaking with **${name}**, signed in to Azure (their email looks like **${email}**). Open by confirming both, in your own voice \u2014 e.g. "I see you're signed in as ${name}, and I'll use ${email} for your advisor handoffs and cost reports \u2014 is that right, or should I change either?" Record exactly what they approve or correct.`;
|
|
28464
28819
|
}
|
|
28465
|
-
if (
|
|
28466
|
-
return `You're speaking with **${
|
|
28820
|
+
if (name) {
|
|
28821
|
+
return `You're speaking with **${name}** (signed in to Azure). Confirm their name, then ask for the best contact email to reach them (that's where advisor handoffs and cost reports go).`;
|
|
28467
28822
|
}
|
|
28468
28823
|
return `Ask the founder their name and the best contact email to reach them (that's where advisor handoffs and cost reports go).`;
|
|
28469
28824
|
}
|
|
@@ -28663,7 +29018,7 @@ async function reactiveSeedOnFinish(args) {
|
|
|
28663
29018
|
if (!hadIntake) return;
|
|
28664
29019
|
(args.spawnWatch ?? spawnDetachedSeedWatch)();
|
|
28665
29020
|
args.stdout(
|
|
28666
|
-
`${colors.dim("\u2139 Your advisors will pick up your company profile when you finish the
|
|
29021
|
+
`${colors.dim("\u2139 Your advisors will pick up your company profile when you finish the intake (watching in the background).")}
|
|
28667
29022
|
${colors.hint("or run:")} m8t bootstrap seed-profile
|
|
28668
29023
|
`
|
|
28669
29024
|
);
|
|
@@ -28705,7 +29060,7 @@ var BootstrapFinishCommand = class extends M8tCommand {
|
|
|
28705
29060
|
static paths = [["bootstrap", "finish"]];
|
|
28706
29061
|
static usage = Command55.Usage({
|
|
28707
29062
|
description: "Point your local tools at the now-live platform (repo-root marker, discovery cache, next steps).",
|
|
28708
|
-
details: "Final step of `m8t bootstrap` (after the install reaches done). Writes ~/.m8t/repo-root, points your local tools at the live gateway, and \u2014 if you completed the onboarding
|
|
29063
|
+
details: "Final step of `m8t bootstrap` (after the install reaches done). Writes ~/.m8t/repo-root, points your local tools at the live gateway, and \u2014 if you completed the onboarding intake \u2014 seeds your brain-backed advisor's brain with your company profile (best-effort; never blocks finish). Run `m8t bootstrap seed-profile` to seed manually later.",
|
|
28709
29064
|
examples: [["Finish local", "$0 bootstrap finish --repo-root /path/to/m8t"]]
|
|
28710
29065
|
});
|
|
28711
29066
|
repoRoot = Option52.String("--repo-root");
|
|
@@ -28827,17 +29182,18 @@ import { spawn as spawn7, spawnSync as spawnSync6 } from "child_process";
|
|
|
28827
29182
|
init_errors();
|
|
28828
29183
|
init_rbac();
|
|
28829
29184
|
|
|
28830
|
-
// src/lib/
|
|
28831
|
-
|
|
28832
|
-
var
|
|
28833
|
-
|
|
29185
|
+
// src/lib/intake-agent.ts
|
|
29186
|
+
init_esm();
|
|
29187
|
+
var INTAKE_PERSONA = "azure-advisor-intake";
|
|
29188
|
+
var INTAKE_AGENT = INTAKE_AGENT_NAME;
|
|
29189
|
+
async function deployIntakeAgent(args) {
|
|
28834
29190
|
try {
|
|
28835
29191
|
return await deployPromptAdvisor({
|
|
28836
29192
|
credential: args.credential,
|
|
28837
29193
|
endpoint: args.endpoint,
|
|
28838
29194
|
repoRoot: args.repoRoot,
|
|
28839
|
-
persona:
|
|
28840
|
-
agentName:
|
|
29195
|
+
persona: INTAKE_PERSONA,
|
|
29196
|
+
agentName: INTAKE_AGENT,
|
|
28841
29197
|
model: args.model,
|
|
28842
29198
|
fieldOverrides: args.fieldOverrides
|
|
28843
29199
|
});
|
|
@@ -28847,7 +29203,7 @@ async function deploySimpleStacey(args) {
|
|
|
28847
29203
|
if (err.code === "ADVISOR_PERSONA_MISSING") {
|
|
28848
29204
|
const { LocalCliError: LocalCliError2 } = await Promise.resolve().then(() => (init_errors(), errors_exports));
|
|
28849
29205
|
throw new LocalCliError2({
|
|
28850
|
-
code: "
|
|
29206
|
+
code: "INTAKE_PERSONA_MISSING",
|
|
28851
29207
|
message: err.message,
|
|
28852
29208
|
hint: err.hint,
|
|
28853
29209
|
cause: err.cause
|
|
@@ -28856,7 +29212,7 @@ async function deploySimpleStacey(args) {
|
|
|
28856
29212
|
if (err.code === "ADVISOR_NO_MODEL") {
|
|
28857
29213
|
const { LocalCliError: LocalCliError2 } = await Promise.resolve().then(() => (init_errors(), errors_exports));
|
|
28858
29214
|
throw new LocalCliError2({
|
|
28859
|
-
code: "
|
|
29215
|
+
code: "INTAKE_NO_MODEL",
|
|
28860
29216
|
message: err.message,
|
|
28861
29217
|
hint: err.hint,
|
|
28862
29218
|
cause: err.cause
|
|
@@ -28865,7 +29221,7 @@ async function deploySimpleStacey(args) {
|
|
|
28865
29221
|
if (err.code === "ADVISOR_BAD_EFFORT") {
|
|
28866
29222
|
const { LocalCliError: LocalCliError2 } = await Promise.resolve().then(() => (init_errors(), errors_exports));
|
|
28867
29223
|
throw new LocalCliError2({
|
|
28868
|
-
code: "
|
|
29224
|
+
code: "INTAKE_BAD_EFFORT",
|
|
28869
29225
|
message: err.message,
|
|
28870
29226
|
hint: err.hint,
|
|
28871
29227
|
cause: err.cause
|
|
@@ -28897,13 +29253,13 @@ function isAuthorizationShapedError(error) {
|
|
|
28897
29253
|
}
|
|
28898
29254
|
return false;
|
|
28899
29255
|
}
|
|
28900
|
-
async function
|
|
29256
|
+
async function deployIntakeAgentWithRetry(args) {
|
|
28901
29257
|
const maxWaitMs = args.maxWaitMs ?? 3e5;
|
|
28902
29258
|
const intervalMs = args.intervalMs ?? 1e4;
|
|
28903
29259
|
const deadline = Date.now() + maxWaitMs;
|
|
28904
29260
|
for (; ; ) {
|
|
28905
29261
|
try {
|
|
28906
|
-
return await
|
|
29262
|
+
return await deployIntakeAgent({
|
|
28907
29263
|
credential: args.credential,
|
|
28908
29264
|
endpoint: args.endpoint,
|
|
28909
29265
|
repoRoot: args.repoRoot,
|
|
@@ -28916,7 +29272,7 @@ async function deploySimpleStaceyWithRetry(args) {
|
|
|
28916
29272
|
if (remainingMs <= 0) {
|
|
28917
29273
|
throw new LocalCliError({
|
|
28918
29274
|
code: "BOOTSTRAP_UI_ROLE_PROPAGATION_TIMEOUT",
|
|
28919
|
-
message: "Timed out waiting for Azure role propagation before deploying
|
|
29275
|
+
message: "Timed out waiting for Azure role propagation before deploying the intake agent.",
|
|
28920
29276
|
hint: "Azure role propagation can take a few minutes - re-run 'm8t bootstrap ui' (idempotent).",
|
|
28921
29277
|
cause: error
|
|
28922
29278
|
});
|
|
@@ -28946,7 +29302,7 @@ async function resolveFoundryEndpointWithWait(args, opts = {}) {
|
|
|
28946
29302
|
if (e instanceof LocalCliError && e.code === "FOUNDRY_PROJECT_MULTIPLE") {
|
|
28947
29303
|
throw new LocalCliError({
|
|
28948
29304
|
code: "BOOTSTRAP_UI_MULTIPLE_PROJECTS",
|
|
28949
|
-
message: `${e.message} bootstrap ui can't pick one safely (it must not deploy
|
|
29305
|
+
message: `${e.message} bootstrap ui can't pick one safely (it must not deploy the intake agent into the wrong project).`,
|
|
28950
29306
|
hint: `Re-run with the throwaway project's endpoint, e.g. 'm8t bootstrap ui --repo-root "$(pwd)" --endpoint https://<account>.services.ai.azure.com/api/projects/m8t'. The installer prints it in 'm8t bootstrap status'.`,
|
|
28951
29307
|
cause: e
|
|
28952
29308
|
});
|
|
@@ -29003,7 +29359,7 @@ function writeWebEnvLocal(args) {
|
|
|
29003
29359
|
});
|
|
29004
29360
|
}
|
|
29005
29361
|
const body = [
|
|
29006
|
-
"# Written by `m8t bootstrap ui` \u2014 local onboarding run (
|
|
29362
|
+
"# Written by `m8t bootstrap ui` \u2014 local onboarding run (the onboarding intake agent).",
|
|
29007
29363
|
"# Text-first: the intake voice stack is off unless the run passed --voice.",
|
|
29008
29364
|
"# STORAGE unset \u2192 gateway boot skipped; the webapp forwards your MSAL token to Foundry.",
|
|
29009
29365
|
`AZURE_TENANT_ID=${args.tenantId}`,
|
|
@@ -29344,154 +29700,6 @@ async function listAgentModels(region) {
|
|
|
29344
29700
|
}
|
|
29345
29701
|
}
|
|
29346
29702
|
|
|
29347
|
-
// src/lib/model-cascade.ts
|
|
29348
|
-
var WHITELIST = [
|
|
29349
|
-
{ model: "gpt-5.6-luna", format: "OpenAI", version: "2026-07-09", capacity: 100 },
|
|
29350
|
-
{ model: "gpt-5.6-sol", format: "OpenAI", version: "2026-07-09", capacity: 100 },
|
|
29351
|
-
{ model: "gpt-5.6-terra", format: "OpenAI", version: "2026-07-09", capacity: 100 },
|
|
29352
|
-
{ model: "gpt-5.4", format: "OpenAI", version: "2026-03-05", capacity: 100 },
|
|
29353
|
-
{ model: "grok-4.3", format: "xAI", version: "1", capacity: 100 },
|
|
29354
|
-
{ model: "gpt-4.1-mini", format: "OpenAI", version: "2025-04-14", capacity: 50 }
|
|
29355
|
-
];
|
|
29356
|
-
var GLOBAL_STANDARD = "GlobalStandard";
|
|
29357
|
-
function planCascade(whitelist, catalog, quota) {
|
|
29358
|
-
if (!catalog.ok) {
|
|
29359
|
-
return {
|
|
29360
|
-
candidates: [],
|
|
29361
|
-
skipped: whitelist.map((r) => ({ model: r.model, outcome: "catalog-unverified", detail: catalog.error }))
|
|
29362
|
-
};
|
|
29363
|
-
}
|
|
29364
|
-
const rowsByName = /* @__PURE__ */ new Map();
|
|
29365
|
-
for (const row of catalog.rows) {
|
|
29366
|
-
const list = rowsByName.get(row.name);
|
|
29367
|
-
if (list) list.push(row);
|
|
29368
|
-
else rowsByName.set(row.name, [row]);
|
|
29369
|
-
}
|
|
29370
|
-
const candidates = [];
|
|
29371
|
-
const skipped = [];
|
|
29372
|
-
for (const rung of whitelist) {
|
|
29373
|
-
const rows = rowsByName.get(rung.model);
|
|
29374
|
-
if (!rows || rows.length === 0) {
|
|
29375
|
-
skipped.push({ model: rung.model, outcome: "not-in-catalog" });
|
|
29376
|
-
continue;
|
|
29377
|
-
}
|
|
29378
|
-
const agentRows = rows.filter((r) => r.agentsV2);
|
|
29379
|
-
if (agentRows.length === 0) {
|
|
29380
|
-
skipped.push({ model: rung.model, outcome: "not-agent-eligible" });
|
|
29381
|
-
continue;
|
|
29382
|
-
}
|
|
29383
|
-
if (!agentRows.some((r) => r.skus.includes(GLOBAL_STANDARD))) {
|
|
29384
|
-
skipped.push({ model: rung.model, outcome: "no-global-standard" });
|
|
29385
|
-
continue;
|
|
29386
|
-
}
|
|
29387
|
-
if (modelQuotaVerdict(quota, rung.model).verdict === "no_quota") {
|
|
29388
|
-
skipped.push({ model: rung.model, outcome: "no-quota" });
|
|
29389
|
-
continue;
|
|
29390
|
-
}
|
|
29391
|
-
candidates.push(rung);
|
|
29392
|
-
}
|
|
29393
|
-
return { candidates, skipped };
|
|
29394
|
-
}
|
|
29395
|
-
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;
|
|
29396
|
-
var REGION_RE = /not available in|not supported in|NotAvailableInRegion|InvalidResourceLocation/i;
|
|
29397
|
-
var CONFLICT_RE = /\bconflict\b|\b409\b/i;
|
|
29398
|
-
function classifyDeployError(message) {
|
|
29399
|
-
if (QUOTA_RE.test(message)) return "deploy-rejected-quota";
|
|
29400
|
-
if (REGION_RE.test(message)) return "deploy-rejected-region";
|
|
29401
|
-
return "deploy-unverified";
|
|
29402
|
-
}
|
|
29403
|
-
async function walkCascade(whitelist, plan, deploy, opts) {
|
|
29404
|
-
const outcomes = /* @__PURE__ */ new Map();
|
|
29405
|
-
for (const s of plan.skipped) outcomes.set(s.model, s);
|
|
29406
|
-
let chosen = null;
|
|
29407
|
-
let aborted = false;
|
|
29408
|
-
for (const rung of plan.candidates) {
|
|
29409
|
-
if (chosen) break;
|
|
29410
|
-
if (opts.now() >= opts.deadlineAt) {
|
|
29411
|
-
aborted = true;
|
|
29412
|
-
break;
|
|
29413
|
-
}
|
|
29414
|
-
let row;
|
|
29415
|
-
try {
|
|
29416
|
-
await deploy(rung);
|
|
29417
|
-
row = { model: rung.model, outcome: "deployed" };
|
|
29418
|
-
chosen = rung;
|
|
29419
|
-
} catch (e) {
|
|
29420
|
-
const msg = e instanceof Error ? e.message : String(e);
|
|
29421
|
-
if (CONFLICT_RE.test(msg)) {
|
|
29422
|
-
try {
|
|
29423
|
-
await deploy(rung);
|
|
29424
|
-
row = { model: rung.model, outcome: "deployed" };
|
|
29425
|
-
chosen = rung;
|
|
29426
|
-
} catch (e2) {
|
|
29427
|
-
const msg2 = e2 instanceof Error ? e2.message : String(e2);
|
|
29428
|
-
row = {
|
|
29429
|
-
model: rung.model,
|
|
29430
|
-
outcome: CONFLICT_RE.test(msg2) ? "deploy-unverified" : classifyDeployError(msg2),
|
|
29431
|
-
detail: msg2
|
|
29432
|
-
};
|
|
29433
|
-
}
|
|
29434
|
-
} else {
|
|
29435
|
-
row = { model: rung.model, outcome: classifyDeployError(msg), detail: msg };
|
|
29436
|
-
}
|
|
29437
|
-
}
|
|
29438
|
-
outcomes.set(rung.model, row);
|
|
29439
|
-
opts.onRung?.(row.model, row.outcome);
|
|
29440
|
-
}
|
|
29441
|
-
const trace = whitelist.map(
|
|
29442
|
-
(r) => outcomes.get(r.model) ?? { model: r.model, outcome: aborted ? "aborted-deadline" : "not-reached" }
|
|
29443
|
-
);
|
|
29444
|
-
return { chosen, trace };
|
|
29445
|
-
}
|
|
29446
|
-
var CERTAIN_UNAVAILABLE = /* @__PURE__ */ new Set([
|
|
29447
|
-
"not-in-catalog",
|
|
29448
|
-
"not-agent-eligible",
|
|
29449
|
-
"no-global-standard",
|
|
29450
|
-
"deploy-rejected-region"
|
|
29451
|
-
]);
|
|
29452
|
-
var QUOTA_BLOCKED = /* @__PURE__ */ new Set(["no-quota", "deploy-rejected-quota"]);
|
|
29453
|
-
function decideNote(whitelist, result) {
|
|
29454
|
-
const chosenIdx = result.chosen ? whitelist.findIndex((r) => r.model === result.chosen?.model) : whitelist.length;
|
|
29455
|
-
const better = result.trace.slice(0, Math.max(chosenIdx, 0));
|
|
29456
|
-
const runningModel = result.chosen?.model ?? null;
|
|
29457
|
-
if (chosenIdx === 0) {
|
|
29458
|
-
return { status: "top", runningModel, pitchModel: null, unavailableAbovePitch: [] };
|
|
29459
|
-
}
|
|
29460
|
-
const pitch = better.find((t) => QUOTA_BLOCKED.has(t.outcome));
|
|
29461
|
-
if (pitch) {
|
|
29462
|
-
const pitchIdx = better.findIndex((t) => t.model === pitch.model);
|
|
29463
|
-
return {
|
|
29464
|
-
status: "lesser-quota",
|
|
29465
|
-
runningModel,
|
|
29466
|
-
pitchModel: pitch.model,
|
|
29467
|
-
unavailableAbovePitch: better.slice(0, pitchIdx).filter((t) => CERTAIN_UNAVAILABLE.has(t.outcome)).map((t) => t.model)
|
|
29468
|
-
};
|
|
29469
|
-
}
|
|
29470
|
-
const allCertain = better.length > 0 && better.every((t) => CERTAIN_UNAVAILABLE.has(t.outcome));
|
|
29471
|
-
return {
|
|
29472
|
-
status: allCertain ? "lesser-unavailable" : "lesser-unverified",
|
|
29473
|
-
runningModel,
|
|
29474
|
-
pitchModel: null,
|
|
29475
|
-
unavailableAbovePitch: []
|
|
29476
|
-
};
|
|
29477
|
-
}
|
|
29478
|
-
var listNames = (names) => names.length <= 1 ? names[0] ?? "" : `${names.slice(0, -1).join(", ")} and ${names[names.length - 1]}`;
|
|
29479
|
-
function renderChosenModelNote(d) {
|
|
29480
|
-
const subject = d.runningModel ? `You are running on ${d.runningModel}.` : "You are running on this install's default model.";
|
|
29481
|
-
switch (d.status) {
|
|
29482
|
-
case "top":
|
|
29483
|
-
return `${subject} That is the best available model for this install.`;
|
|
29484
|
-
case "lesser-quota": {
|
|
29485
|
-
const aside = d.unavailableAbovePitch.length > 0 ? ` ${listNames(d.unavailableAbovePitch)} ${d.unavailableAbovePitch.length > 1 ? "are" : "is"} not offered for this install.` : "";
|
|
29486
|
-
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.`;
|
|
29487
|
-
}
|
|
29488
|
-
case "lesser-unavailable":
|
|
29489
|
-
return `${subject} No stronger model is offered for this install right now.`;
|
|
29490
|
-
case "lesser-unverified":
|
|
29491
|
-
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.`;
|
|
29492
|
-
}
|
|
29493
|
-
}
|
|
29494
|
-
|
|
29495
29703
|
// src/lib/intake-model.ts
|
|
29496
29704
|
var DEFAULT_DEADLINE_MS = 18e4;
|
|
29497
29705
|
var SCOPE_RE = /\/resourceGroups\/([^/]+)\/providers\/Microsoft\.CognitiveServices\/accounts\/([^/]+)/i;
|
|
@@ -29564,7 +29772,7 @@ async function resolveIntakeModel(args) {
|
|
|
29564
29772
|
|
|
29565
29773
|
// src/lib/inventory-summary.ts
|
|
29566
29774
|
var HEAVY_THRESHOLD = 10;
|
|
29567
|
-
var
|
|
29775
|
+
var INVENTORY_INVITATION2 = "You can offer to walk the founder through these resources.";
|
|
29568
29776
|
var NOTABLE_TYPES = {
|
|
29569
29777
|
// storage
|
|
29570
29778
|
"microsoft.storage/storageaccounts": "storage accounts",
|
|
@@ -29694,7 +29902,7 @@ function regionAgeClause(s) {
|
|
|
29694
29902
|
}
|
|
29695
29903
|
function renderInventoryNote(summary) {
|
|
29696
29904
|
const body = summary.notableCount === 0 ? `${LEAD} There are no notable pre-existing resources.` : `${LEAD} ${piecesClause(summary)}${regionAgeClause(summary)}.`;
|
|
29697
|
-
return summary.verdict === "heavy" ? `${body} ${
|
|
29905
|
+
return summary.verdict === "heavy" ? `${body} ${INVENTORY_INVITATION2}` : body;
|
|
29698
29906
|
}
|
|
29699
29907
|
|
|
29700
29908
|
// src/lib/subscription-inventory.ts
|
|
@@ -29753,27 +29961,28 @@ async function resolveSubscriptionInventory(args) {
|
|
|
29753
29961
|
|
|
29754
29962
|
// src/commands/bootstrap/ui.ts
|
|
29755
29963
|
function renderDeploySuccess(version, envPath) {
|
|
29756
|
-
return `${colors.success("\u2713")}
|
|
29964
|
+
return `${colors.success("\u2713")} Azzy is live (${INTAKE_AGENT} v${version}).
|
|
29757
29965
|
env: ${envPath}
|
|
29758
|
-
Opening ${colors.field("http://localhost:3000")} in your browser \u2192 Sign in with Microsoft \u2192 chat with
|
|
29966
|
+
Opening ${colors.field("http://localhost:3000")} in your browser \u2192 Sign in with Microsoft \u2192 chat with Azzy.
|
|
29759
29967
|
${colors.dim("(If it doesn't open, browse to http://localhost:3000 yourself.)")}
|
|
29760
29968
|
${colors.dim("First turn may say 'warming up' for a few minutes while access propagates \u2014 that's expected.")}
|
|
29761
29969
|
`;
|
|
29762
29970
|
}
|
|
29763
29971
|
function renderDeployFailure(error) {
|
|
29764
29972
|
const hint = error instanceof LocalCliError && error.hint ? error.hint : "Re-run 'm8t bootstrap ui' (idempotent).";
|
|
29765
|
-
return `${colors.error("\u2717")}
|
|
29973
|
+
return `${colors.error("\u2717")} Azzy deploy failed: ${error.message}
|
|
29766
29974
|
${colors.hint(hint)}
|
|
29767
29975
|
`;
|
|
29768
29976
|
}
|
|
29769
29977
|
var BootstrapUiCommand = class extends M8tCommand {
|
|
29770
29978
|
static paths = [["bootstrap", "ui"]];
|
|
29771
29979
|
static usage = Command56.Usage({
|
|
29772
|
-
description: "Deploy
|
|
29980
|
+
description: "Deploy Azzy + start the local onboarding chat UI in the background (returns immediately).",
|
|
29773
29981
|
details: [
|
|
29774
29982
|
"Run after `m8t bootstrap launch`, in parallel with `status --watch`. Waits for the cloud",
|
|
29775
|
-
"installer's foundry-create phase, grants you Foundry data-plane access, deploys
|
|
29776
|
-
"
|
|
29983
|
+
"installer's foundry-create phase, grants you Foundry data-plane access, deploys the no-brain",
|
|
29984
|
+
"onboarding intake agent (azzy-intake), writes apps/web/.env.local (voice relay config is added",
|
|
29985
|
+
"only when --voice is set \u2014 see --voice for what that does and does not affect),",
|
|
29777
29986
|
"installs deps, and starts the webapp detached so a coding agent can continue without opening",
|
|
29778
29987
|
"a separate terminal.",
|
|
29779
29988
|
"",
|
|
@@ -29785,7 +29994,7 @@ var BootstrapUiCommand = class extends M8tCommand {
|
|
|
29785
29994
|
["Stop the running onboarding UI", "$0 bootstrap ui --stop"],
|
|
29786
29995
|
["Prep only (don't serve at all)", "$0 bootstrap ui --repo-root /path/to/m8t --prep-only"],
|
|
29787
29996
|
["Foreground (blocking, old behaviour)", "$0 bootstrap ui --repo-root /path/to/m8t --foreground"],
|
|
29788
|
-
["Experimental:
|
|
29997
|
+
["Experimental: start the voice relay (no effect on the text-only intake)", "$0 bootstrap ui --repo-root /path/to/m8t --voice"]
|
|
29789
29998
|
]
|
|
29790
29999
|
});
|
|
29791
30000
|
repoRoot = Option53.String("--repo-root");
|
|
@@ -29798,7 +30007,7 @@ var BootstrapUiCommand = class extends M8tCommand {
|
|
|
29798
30007
|
stop = Option53.Boolean("--stop", false);
|
|
29799
30008
|
foreground = Option53.Boolean("--foreground", false);
|
|
29800
30009
|
voice = Option53.Boolean("--voice", false, {
|
|
29801
|
-
description: "Experimental
|
|
30010
|
+
description: "Experimental: when serving, starts the voice relay and writes the intake voice env var. The onboarding intake is text-only and is unaffected by this flag \u2014 no voice worker is registered for it."
|
|
29802
30011
|
});
|
|
29803
30012
|
async executeCommand() {
|
|
29804
30013
|
if (this.stop === true) {
|
|
@@ -29851,7 +30060,7 @@ var BootstrapUiCommand = class extends M8tCommand {
|
|
|
29851
30060
|
const oid = await getSignedInUserOid();
|
|
29852
30061
|
await ensureFounderFoundryRole({ credential: credential2, subscriptionId: state.subscriptionId, principalId: oid, accountScope });
|
|
29853
30062
|
const identity = await getSignedInUserIdentity();
|
|
29854
|
-
out("deploying
|
|
30063
|
+
out("deploying the intake agent (azzy-intake) in the background...");
|
|
29855
30064
|
const deployOutcome = (async () => {
|
|
29856
30065
|
const [choice, inventory] = await Promise.all([
|
|
29857
30066
|
resolveIntakeModel({
|
|
@@ -29865,7 +30074,7 @@ var BootstrapUiCommand = class extends M8tCommand {
|
|
|
29865
30074
|
onNarrate: out
|
|
29866
30075
|
})
|
|
29867
30076
|
]);
|
|
29868
|
-
return
|
|
30077
|
+
return deployIntakeAgentWithRetry({
|
|
29869
30078
|
credential: credential2,
|
|
29870
30079
|
endpoint,
|
|
29871
30080
|
repoRoot,
|
|
@@ -29963,16 +30172,16 @@ import { Command as Command57, Option as Option54 } from "clipanion";
|
|
|
29963
30172
|
var BootstrapSeedProfileCommand = class extends M8tCommand {
|
|
29964
30173
|
static paths = [["bootstrap", "seed-profile"]];
|
|
29965
30174
|
static usage = Command57.Usage({
|
|
29966
|
-
description: "Seed your advisors' brains with the founder + company profile from the onboarding
|
|
29967
|
-
details: "Reads the latest
|
|
30175
|
+
description: "Seed your advisors' brains with the founder + company profile from the onboarding intake.",
|
|
30176
|
+
details: "Reads the latest onboarding conversation, renders memory/founder.md + memory/company-profile.md (+ their MEMORY.md index lines), and commits them to both <org>/stacey-brain and <org>/azzy-brain via the GitHub App. Idempotent. --watch polls until the founder finishes the intake.",
|
|
29968
30177
|
examples: [
|
|
29969
30178
|
["Seed now (idempotent)", "$0 bootstrap seed-profile"],
|
|
29970
30179
|
["Wait for the founder to finish", "$0 bootstrap seed-profile --watch"]
|
|
29971
30180
|
]
|
|
29972
30181
|
});
|
|
29973
30182
|
endpoint = Option54.String("--endpoint", { description: "Override the Foundry endpoint (else read from the install status)." });
|
|
29974
|
-
brain = Option54.String("--brain", { description: "
|
|
29975
|
-
watch = Option54.Boolean("--watch", false, { description: "Poll until the
|
|
30183
|
+
brain = Option54.String("--brain", { description: "Seed only this one brain repo, instead of both <org>/stacey-brain and <org>/azzy-brain." });
|
|
30184
|
+
watch = Option54.Boolean("--watch", false, { description: "Poll until the intake completes (or --timeout)." });
|
|
29976
30185
|
timeout = Option54.String("--timeout", { description: "Watch timeout in minutes (default 20)." });
|
|
29977
30186
|
githubAppCreds = Option54.String("--github-app-creds");
|
|
29978
30187
|
async executeCommand() {
|
|
@@ -29994,7 +30203,7 @@ var BootstrapSeedProfileCommand = class extends M8tCommand {
|
|
|
29994
30203
|
const sleep5 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
29995
30204
|
for (; ; ) {
|
|
29996
30205
|
const token = await getFoundryToken();
|
|
29997
|
-
const { hadIntake, block } = await findOnboardingProfile({ endpoint: ctx.endpoint, token });
|
|
30206
|
+
const { hadIntake, block, rejection } = await findOnboardingProfile({ endpoint: ctx.endpoint, token });
|
|
29998
30207
|
if (block) {
|
|
29999
30208
|
const azIdentity = await getSignedInUserIdentity();
|
|
30000
30209
|
await applyProfileToBrains({
|
|
@@ -30005,19 +30214,28 @@ var BootstrapSeedProfileCommand = class extends M8tCommand {
|
|
|
30005
30214
|
subscriptionId: ctx.subscriptionId,
|
|
30006
30215
|
azIdentity
|
|
30007
30216
|
});
|
|
30008
|
-
this.context.stdout.write(`${colors.success("\u2713")} seeded your advisors' brains (${ctx.brainRepos.join(", ")}) from your
|
|
30217
|
+
this.context.stdout.write(`${colors.success("\u2713")} seeded your advisors' brains (${ctx.brainRepos.join(", ")}) from your intake.
|
|
30009
30218
|
`);
|
|
30010
30219
|
return 0;
|
|
30011
30220
|
}
|
|
30012
30221
|
if (!watch || Date.now() >= deadline) {
|
|
30222
|
+
if (rejection !== null && rejection !== "no-artifact") {
|
|
30223
|
+
this.context.stderr.write(
|
|
30224
|
+
` ${colors.dim(`found an onboarding block but could not read it \u2014 ${describeBlockRejection(rejection)}.`)}
|
|
30225
|
+
${colors.hint("fix:")} delete this onboarding conversation in the Azure AI Foundry portal, then redo the intake and run: m8t bootstrap seed-profile
|
|
30226
|
+
`
|
|
30227
|
+
);
|
|
30228
|
+
return 3;
|
|
30229
|
+
}
|
|
30230
|
+
const why = hadIntake ? "intake not complete yet \u2014 no m8t_onboarding block found." : "no onboarding intake found.";
|
|
30013
30231
|
this.context.stderr.write(
|
|
30014
|
-
` ${colors.dim(
|
|
30232
|
+
` ${colors.dim(why)}
|
|
30015
30233
|
${colors.hint("retry:")} m8t bootstrap seed-profile
|
|
30016
30234
|
`
|
|
30017
30235
|
);
|
|
30018
30236
|
return 3;
|
|
30019
30237
|
}
|
|
30020
|
-
this.context.stderr.write(` ${colors.dim("waiting for the
|
|
30238
|
+
this.context.stderr.write(` ${colors.dim("waiting for the intake to complete\u2026")}
|
|
30021
30239
|
`);
|
|
30022
30240
|
await sleep5(2e4);
|
|
30023
30241
|
}
|