@m8t-stack/cli 0.2.72 → 0.2.73
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 +79 -40
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1370,7 +1370,7 @@ var init_enable_hosted_brain = __esm({
|
|
|
1370
1370
|
import { Builtins, Cli } from "clipanion";
|
|
1371
1371
|
|
|
1372
1372
|
// src/lib/package-version.ts
|
|
1373
|
-
var CLI_VERSION = "0.2.
|
|
1373
|
+
var CLI_VERSION = "0.2.73";
|
|
1374
1374
|
|
|
1375
1375
|
// src/lib/render-error.ts
|
|
1376
1376
|
init_errors();
|
|
@@ -15663,10 +15663,16 @@ import * as fs9 from "fs";
|
|
|
15663
15663
|
import * as path9 from "path";
|
|
15664
15664
|
var SEED_MANIFEST_PATH = ".m8t/seed-manifest.json";
|
|
15665
15665
|
var SEED_PATHS = ["skills", "references", "targets"];
|
|
15666
|
+
function isUpstream(v) {
|
|
15667
|
+
if (v === void 0) return true;
|
|
15668
|
+
if (!v || typeof v !== "object") return false;
|
|
15669
|
+
const u = v;
|
|
15670
|
+
return typeof u.repo === "string" && u.repo.length > 0 && typeof u.ref === "string" && u.ref.length > 0;
|
|
15671
|
+
}
|
|
15666
15672
|
function isLineage(v) {
|
|
15667
15673
|
if (!v || typeof v !== "object") return false;
|
|
15668
15674
|
const l = v;
|
|
15669
|
-
return typeof l.name === "string" && typeof l.refreshedToCommit === "string" && typeof l.refreshedToVersion === "string" && Array.isArray(l.ownedPaths) && l.ownedPaths.every((p) => typeof p === "string");
|
|
15675
|
+
return typeof l.name === "string" && typeof l.refreshedToCommit === "string" && typeof l.refreshedToVersion === "string" && Array.isArray(l.ownedPaths) && l.ownedPaths.every((p) => typeof p === "string") && isUpstream(l.upstream);
|
|
15670
15676
|
}
|
|
15671
15677
|
function parseSeedManifest(text) {
|
|
15672
15678
|
if (!text?.trim()) return null;
|
|
@@ -15684,6 +15690,11 @@ function parseSeedManifest(text) {
|
|
|
15684
15690
|
function buildSeedManifest(seeds) {
|
|
15685
15691
|
return { schemaVersion: 1, seeds };
|
|
15686
15692
|
}
|
|
15693
|
+
function carryUpstream(prior, lineage) {
|
|
15694
|
+
if (lineage.upstream) return lineage;
|
|
15695
|
+
const before = prior?.seeds.find((s) => s.name === lineage.name)?.upstream;
|
|
15696
|
+
return before ? { ...lineage, upstream: before } : lineage;
|
|
15697
|
+
}
|
|
15687
15698
|
function upsertLineage(manifest, lineage) {
|
|
15688
15699
|
const prior = manifest?.seeds ?? [];
|
|
15689
15700
|
const others = prior.filter((s) => s.name !== lineage.name);
|
|
@@ -15960,6 +15971,15 @@ async function syncAgentContent(args) {
|
|
|
15960
15971
|
await hydrateAgentsInto(args.root, pin.agents, args.deps);
|
|
15961
15972
|
return Object.values(pin.agents).map((a) => ({ persona: a.persona, repo: a.repo, ref: a.ref }));
|
|
15962
15973
|
}
|
|
15974
|
+
function upstreamForSeed(root, seedName) {
|
|
15975
|
+
try {
|
|
15976
|
+
const pin = parseReleasePin(fs12.readFileSync(path12.join(root, PIN_REL_PATH), "utf8"), PIN_REL_PATH);
|
|
15977
|
+
const agent = Object.values(pin.agents).find((a) => a.persona === seedName);
|
|
15978
|
+
return agent ? { repo: agent.repo, ref: agent.ref } : void 0;
|
|
15979
|
+
} catch {
|
|
15980
|
+
return void 0;
|
|
15981
|
+
}
|
|
15982
|
+
}
|
|
15963
15983
|
function agentContentHint(root, persona) {
|
|
15964
15984
|
try {
|
|
15965
15985
|
const pin = parseReleasePin(fs12.readFileSync(path12.join(root, PIN_REL_PATH), "utf8"), PIN_REL_PATH);
|
|
@@ -16034,7 +16054,8 @@ function writeSeedMarker(args) {
|
|
|
16034
16054
|
name: args.seedName,
|
|
16035
16055
|
refreshedToCommit: args.refreshedToCommit,
|
|
16036
16056
|
refreshedToVersion: args.version,
|
|
16037
|
-
ownedPaths: deriveOwnedPaths(args.seedDir)
|
|
16057
|
+
ownedPaths: deriveOwnedPaths(args.seedDir),
|
|
16058
|
+
...args.upstream ? { upstream: args.upstream } : {}
|
|
16038
16059
|
}]);
|
|
16039
16060
|
const dest = path13.join(args.destDir, SEED_MANIFEST_PATH);
|
|
16040
16061
|
fs13.mkdirSync(path13.dirname(dest), { recursive: true });
|
|
@@ -16658,7 +16679,15 @@ var BrainCreateCommand = class extends M8tCommand {
|
|
|
16658
16679
|
materializeBrainTree({ templateSrc, destDir: tmpDir, seedDir });
|
|
16659
16680
|
if (seedName && seedDir) {
|
|
16660
16681
|
const headSha = resolveScaffoldCommit(repoRoot, env);
|
|
16661
|
-
|
|
16682
|
+
const upstream = upstreamForSeed(repoRoot, seedName);
|
|
16683
|
+
writeSeedMarker({
|
|
16684
|
+
destDir: tmpDir,
|
|
16685
|
+
seedName,
|
|
16686
|
+
seedDir,
|
|
16687
|
+
refreshedToCommit: headSha,
|
|
16688
|
+
version: "(scaffold)",
|
|
16689
|
+
...upstream ? { upstream } : {}
|
|
16690
|
+
});
|
|
16662
16691
|
}
|
|
16663
16692
|
this.context.stdout.write(
|
|
16664
16693
|
seedName ? `${colors.dim("\u2192")} copied brain-template/ + overlaid seed ${colors.field(seedName)} to ${tmpDir}
|
|
@@ -21534,14 +21563,15 @@ async function refreshBrainRepo(args) {
|
|
|
21534
21563
|
const ownedNow = new Set(args.trees.ownedAtTheirs);
|
|
21535
21564
|
assertNoDanglingIndexRefs(finalPaths, (p) => ownedNow.has(p), indexBodies);
|
|
21536
21565
|
const newOwned = deriveOwnedPaths(args.trees.theirsDir);
|
|
21566
|
+
const priorManifest = args.priorManifest ?? (args.lineage ? { schemaVersion: 1, seeds: [args.lineage] } : null);
|
|
21537
21567
|
const nextManifest = upsertLineage(
|
|
21538
|
-
|
|
21539
|
-
{
|
|
21568
|
+
priorManifest,
|
|
21569
|
+
carryUpstream(priorManifest, {
|
|
21540
21570
|
name: args.seedName,
|
|
21541
21571
|
refreshedToCommit: args.targetCommit ?? "",
|
|
21542
21572
|
refreshedToVersion: args.version,
|
|
21543
21573
|
ownedPaths: newOwned
|
|
21544
|
-
}
|
|
21574
|
+
})
|
|
21545
21575
|
);
|
|
21546
21576
|
files.push({ path: SEED_MANIFEST_PATH, content: serializeSeedManifest(nextManifest) });
|
|
21547
21577
|
for (const sb of args.supersedeBranches ?? []) {
|
|
@@ -29925,7 +29955,7 @@ ${colors.error("\u2717")} The GitHub App on disk is installed on ${colors.field(
|
|
|
29925
29955
|
// src/commands/bootstrap/launch.ts
|
|
29926
29956
|
var DEFAULT_RG = "rg-m8t-stack";
|
|
29927
29957
|
var DEFAULT_INSTALLER = "ghcr.io/m8t-labs/m8t-installer";
|
|
29928
|
-
var DEFAULT_INSTALLER_TAG = "v0.1.
|
|
29958
|
+
var DEFAULT_INSTALLER_TAG = "v0.1.59";
|
|
29929
29959
|
var ACI_NAME = "m8t-installer";
|
|
29930
29960
|
var MI_NAME = "m8t-installer-mi";
|
|
29931
29961
|
var BootstrapLaunchCommand = class extends M8tCommand {
|
|
@@ -30892,19 +30922,22 @@ async function resolveSeedContext(opts) {
|
|
|
30892
30922
|
if (!appCreds) return null;
|
|
30893
30923
|
let endpoint = opts.endpointOverride;
|
|
30894
30924
|
let subscriptionId = opts.subscriptionId;
|
|
30895
|
-
|
|
30925
|
+
let recorded = opts.brainsOverride;
|
|
30926
|
+
if (!endpoint || !opts.brainOverride && recorded === void 0) {
|
|
30896
30927
|
const state = await readBootstrapState();
|
|
30897
30928
|
if (!state) {
|
|
30898
30929
|
throw new LocalCliError({ code: "BOOTSTRAP_NO_STATE", message: "No bootstrap state found.", hint: "Run 'm8t bootstrap launch' first, or pass --endpoint." });
|
|
30899
30930
|
}
|
|
30900
30931
|
subscriptionId ??= state.subscriptionId;
|
|
30901
30932
|
const doc = await readStatusBlob({ saName: state.statusSaName, resourceGroup: state.resourceGroup, subscriptionId: state.subscriptionId });
|
|
30902
|
-
endpoint
|
|
30933
|
+
endpoint ??= doc.result?.foundryEndpoint;
|
|
30934
|
+
recorded ??= doc.result?.brains;
|
|
30903
30935
|
if (!endpoint) {
|
|
30904
30936
|
throw new LocalCliError({ code: "SEED_NO_ENDPOINT", message: "Could not resolve the Foundry endpoint from the install status.", hint: "Pass --endpoint <foundryEndpoint>." });
|
|
30905
30937
|
}
|
|
30906
30938
|
}
|
|
30907
|
-
const brainRepos = opts.brainOverride ? [opts.brainOverride] : [
|
|
30939
|
+
const brainRepos = opts.brainOverride ? [opts.brainOverride] : recorded ?? [];
|
|
30940
|
+
if (brainRepos.length === 0) return null;
|
|
30908
30941
|
return { endpoint, brainRepos, appCreds, subscriptionId };
|
|
30909
30942
|
}
|
|
30910
30943
|
var MEMORY_INDEX_PATH = "memory/MEMORY.md";
|
|
@@ -31051,7 +31084,12 @@ function spawnDetachedSeedWatch() {
|
|
|
31051
31084
|
}
|
|
31052
31085
|
}
|
|
31053
31086
|
async function reactiveSeedOnInstallComplete(args) {
|
|
31054
|
-
const ctx = await resolveSeedContext({
|
|
31087
|
+
const ctx = await resolveSeedContext({
|
|
31088
|
+
endpointOverride: args.endpoint,
|
|
31089
|
+
appCredsOverride: args.appCredsOverride,
|
|
31090
|
+
subscriptionId: args.subscriptionId,
|
|
31091
|
+
brainsOverride: args.brains
|
|
31092
|
+
});
|
|
31055
31093
|
if (!ctx) return;
|
|
31056
31094
|
const token = await (args.getFoundryTokenImpl ?? getFoundryToken)();
|
|
31057
31095
|
const { hadIntake, block } = await findOnboardingProfile({ endpoint: ctx.endpoint, token, fetchImpl: args.fetchImpl });
|
|
@@ -31081,8 +31119,7 @@ async function reactiveSeedOnInstallComplete(args) {
|
|
|
31081
31119
|
|
|
31082
31120
|
// src/lib/install-summary.ts
|
|
31083
31121
|
var DEFAULT_WORKERS = [
|
|
31084
|
-
{ name: "
|
|
31085
|
-
{ name: "ezra", label: "Ezra - Azure Expert", brain: "ezra-brain", executor: "ezra-executor" }
|
|
31122
|
+
{ name: "ezra", label: "Ezra - Azure Expert", brain: "ezra-brain" }
|
|
31086
31123
|
];
|
|
31087
31124
|
function renderInstallSummary(args) {
|
|
31088
31125
|
const open3 = args.webappUrl ? `${args.webappUrl} (or run: m8t open)` : "run: m8t open";
|
|
@@ -31094,11 +31131,11 @@ function renderInstallSummary(args) {
|
|
|
31094
31131
|
if (args.brainOrg) {
|
|
31095
31132
|
lines.push(" Your team:");
|
|
31096
31133
|
for (const w of DEFAULT_WORKERS) {
|
|
31097
|
-
lines.push(` \u2022 ${w.label} \xB7 brain: ${args.brainOrg}/${w.brain}
|
|
31134
|
+
lines.push(` \u2022 ${w.label} \xB7 brain: ${args.brainOrg}/${w.brain}`);
|
|
31098
31135
|
}
|
|
31099
31136
|
lines.push(
|
|
31100
31137
|
"",
|
|
31101
|
-
" Reach them: @
|
|
31138
|
+
" Reach them: @ezra (or /ezra) in your coding agent",
|
|
31102
31139
|
" \xB7 the webapp \xB7 or connect Telegram in the webapp (Channels)"
|
|
31103
31140
|
);
|
|
31104
31141
|
} else {
|
|
@@ -32192,7 +32229,7 @@ async function runCompanionInstallCommand(stdout, install) {
|
|
|
32192
32229
|
return 1;
|
|
32193
32230
|
}
|
|
32194
32231
|
stdout.write(
|
|
32195
|
-
`Desktop companions installed
|
|
32232
|
+
`Desktop companions installed - they are at the edge of your screen.
|
|
32196
32233
|
Version: ${state.version}
|
|
32197
32234
|
`
|
|
32198
32235
|
);
|
|
@@ -32352,7 +32389,7 @@ async function finalizeInstall(args, deps = defaultDeps2) {
|
|
|
32352
32389
|
args.stdout(renderInstallSummary({ webappUrl, brainOrg }) + "\n");
|
|
32353
32390
|
args.stdout(
|
|
32354
32391
|
`${colors.field("Optional local tooling for your coding agent:")}
|
|
32355
|
-
\u2022 Talk to your deployed workers from agent sessions (e.g. /
|
|
32392
|
+
\u2022 Talk to your deployed workers from agent sessions (e.g. /ezra) \u2014 install the m8t plugin: guides/install/m8t-plugin.md.
|
|
32356
32393
|
\u2022 Azure-capable MCP servers (microsoft/azure-skills, Microsoft Learn) \u2014 see the optional steps in guides/install.md.
|
|
32357
32394
|
\u2022 Deploy workers conversationally with the opt-in persona skills \u2014 see guides/workers.md.
|
|
32358
32395
|
\u2022 Make sure your m8t CLI is current: npm i -g @m8t-stack/cli@latest
|
|
@@ -32363,6 +32400,9 @@ ${colors.field("Then open a brand new chat/session")} \u2014 new skills + MCP se
|
|
|
32363
32400
|
try {
|
|
32364
32401
|
await deps.reactiveSeed({
|
|
32365
32402
|
endpoint: args.doc.result?.foundryEndpoint,
|
|
32403
|
+
// What the install RECORDED creating. Seeding a fixed roster instead used to
|
|
32404
|
+
// fail every default install against a brain that was never created.
|
|
32405
|
+
brains: args.doc.result?.brains,
|
|
32366
32406
|
subscriptionId: args.subscriptionId,
|
|
32367
32407
|
stdout: args.stdout
|
|
32368
32408
|
});
|
|
@@ -32384,14 +32424,14 @@ ${colors.field("Then open a brand new chat/session")} \u2014 new skills + MCP se
|
|
|
32384
32424
|
const alreadyHasCompanion = await deps.companionStatus().then((s) => s.state !== "not-installed").catch(() => true);
|
|
32385
32425
|
const pinned = alreadyHasCompanion ? void 0 : args.doc.result?.platformVersion;
|
|
32386
32426
|
args.stdout(
|
|
32387
|
-
(pinned === void 0 ? "Putting
|
|
32427
|
+
(pinned === void 0 ? "Putting your mates on your desktop \u2014 fetching the latest released build\n" : `Putting your mates on your desktop \u2014 fetching the build ${pinned} pins
|
|
32388
32428
|
`) + ` ${colors.hint("(about 120 MB; on a slow link this takes a few minutes)")}
|
|
32389
32429
|
`
|
|
32390
32430
|
);
|
|
32391
32431
|
try {
|
|
32392
32432
|
const companion = await deps.convergeCompanion(pinned);
|
|
32393
32433
|
if (companion.state === "installed") {
|
|
32394
|
-
args.stdout("Desktop companions installed
|
|
32434
|
+
args.stdout("Desktop companions installed - they are at the edge of your screen.\n\n");
|
|
32395
32435
|
} else if (companion.state === "not-released") {
|
|
32396
32436
|
args.stdout(
|
|
32397
32437
|
`${pinned === void 0 ? "The latest platform release carries no desktop companions." : `The release this platform is pinned to (${pinned}) carries no desktop companions.`}
|
|
@@ -34230,11 +34270,11 @@ function parseEvent(value) {
|
|
|
34230
34270
|
};
|
|
34231
34271
|
}
|
|
34232
34272
|
if (value.type === "roster") {
|
|
34233
|
-
if (!hasExactKeys(value, ["type", "origin", "mates"]) || !isGatewayOrigin(value.origin) || !Array.isArray(value.mates) || value.mates.length
|
|
34273
|
+
if (!hasExactKeys(value, ["type", "origin", "mates"]) || !isGatewayOrigin(value.origin) || !Array.isArray(value.mates) || value.mates.length === 0) {
|
|
34234
34274
|
return eventError();
|
|
34235
34275
|
}
|
|
34236
34276
|
const mates = value.mates.map(parseMate);
|
|
34237
|
-
if (new Set(mates.map(({ personaKey }) => personaKey)).size !==
|
|
34277
|
+
if (new Set(mates.map(({ personaKey }) => personaKey)).size !== mates.length || new Set(mates.map(({ agentName }) => agentName)).size !== mates.length) {
|
|
34238
34278
|
return eventError();
|
|
34239
34279
|
}
|
|
34240
34280
|
return { type: "roster", origin: value.origin, mates };
|
|
@@ -34425,7 +34465,8 @@ function resolveAgentName(agents, personaKey) {
|
|
|
34425
34465
|
const matches = agents.filter(
|
|
34426
34466
|
(agent) => agent.personaKey === personaKey && isAgentName(agent.name)
|
|
34427
34467
|
);
|
|
34428
|
-
if (matches.length
|
|
34468
|
+
if (matches.length === 0) return null;
|
|
34469
|
+
if (matches.length > 1) {
|
|
34429
34470
|
throw new PredispatchFailure("mate-unavailable");
|
|
34430
34471
|
}
|
|
34431
34472
|
const match = matches[0];
|
|
@@ -34434,6 +34475,11 @@ function resolveAgentName(agents, personaKey) {
|
|
|
34434
34475
|
}
|
|
34435
34476
|
return match.name;
|
|
34436
34477
|
}
|
|
34478
|
+
function requireAgentName(agents, personaKey) {
|
|
34479
|
+
const name = resolveAgentName(agents, personaKey);
|
|
34480
|
+
if (name === null) throw new PredispatchFailure("mate-unavailable");
|
|
34481
|
+
return name;
|
|
34482
|
+
}
|
|
34437
34483
|
function decodeConversationId(data) {
|
|
34438
34484
|
if (!isRecord3(data) || typeof data.id !== "string" || !OPAQUE_ID.test(data.id)) {
|
|
34439
34485
|
throw new PredispatchFailure("not-connected");
|
|
@@ -34598,22 +34644,15 @@ async function rosterCompanions(sink, deps = {}) {
|
|
|
34598
34644
|
const activeSince = new Date(
|
|
34599
34645
|
installed === null || installed > now ? now : installed
|
|
34600
34646
|
).toISOString();
|
|
34601
|
-
const
|
|
34602
|
-
{
|
|
34603
|
-
|
|
34604
|
-
agentName: resolveAgentName(agents, "startup-advisor"),
|
|
34605
|
-
displayName: "Stacey",
|
|
34606
|
-
portraitKey: "stacey",
|
|
34607
|
-
activeSince
|
|
34608
|
-
},
|
|
34609
|
-
{
|
|
34610
|
-
personaKey: "ezra",
|
|
34611
|
-
agentName: resolveAgentName(agents, "ezra"),
|
|
34612
|
-
displayName: "Ezra",
|
|
34613
|
-
portraitKey: "ezra",
|
|
34614
|
-
activeSince
|
|
34615
|
-
}
|
|
34647
|
+
const PRESENTABLE = [
|
|
34648
|
+
{ personaKey: "startup-advisor", displayName: "Stacey", portraitKey: "stacey" },
|
|
34649
|
+
{ personaKey: "ezra", displayName: "Ezra", portraitKey: "ezra" }
|
|
34616
34650
|
];
|
|
34651
|
+
const mates = PRESENTABLE.flatMap((mate) => {
|
|
34652
|
+
const agentName = resolveAgentName(agents, mate.personaKey);
|
|
34653
|
+
return agentName === null ? [] : [{ ...mate, agentName, activeSince }];
|
|
34654
|
+
});
|
|
34655
|
+
if (mates.length === 0) throw new PredispatchFailure("mate-unavailable");
|
|
34617
34656
|
const event = parseEvent({ type: "roster", origin, mates });
|
|
34618
34657
|
sink(event);
|
|
34619
34658
|
return event;
|
|
@@ -34745,7 +34784,7 @@ async function dispatchConversation(request, sink, deps, consume, readDesktopMar
|
|
|
34745
34784
|
token,
|
|
34746
34785
|
controller.signal
|
|
34747
34786
|
);
|
|
34748
|
-
const agentName =
|
|
34787
|
+
const agentName = requireAgentName(agents, request.personaKey);
|
|
34749
34788
|
const conversationId = await (deps.resolveConversationId ?? resolveConversationId)(
|
|
34750
34789
|
fetchImpl,
|
|
34751
34790
|
origin,
|
|
@@ -34856,7 +34895,7 @@ async function historyCompanionMessages(request, sink, deps = {}) {
|
|
|
34856
34895
|
token,
|
|
34857
34896
|
controller.signal
|
|
34858
34897
|
);
|
|
34859
|
-
const agentName =
|
|
34898
|
+
const agentName = requireAgentName(agents, request.personaKey);
|
|
34860
34899
|
const conversationId = await (deps.resolveConversationId ?? resolveConversationId)(
|
|
34861
34900
|
fetchImpl,
|
|
34862
34901
|
origin,
|