@m8t-stack/cli 0.2.20 → 0.2.21
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 +140 -16
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1157,6 +1157,10 @@ async function enableHostedBrain(args) {
|
|
|
1157
1157
|
memory: def.memory,
|
|
1158
1158
|
env,
|
|
1159
1159
|
metadata: {
|
|
1160
|
+
// Spread the current metadata first so unmanaged keys (a2a, a2aCard, …)
|
|
1161
|
+
// survive the relink version; the managed fields are re-asserted over the
|
|
1162
|
+
// spread, and createCoderVersion applies the `brain` arg last.
|
|
1163
|
+
...current.metadata,
|
|
1160
1164
|
source: "m8t-stack-POC",
|
|
1161
1165
|
kind: "hosted",
|
|
1162
1166
|
persona: current.metadata?.persona ?? "coding-agent",
|
|
@@ -1227,7 +1231,7 @@ var init_enable_hosted_brain = __esm({
|
|
|
1227
1231
|
import { Builtins, Cli } from "clipanion";
|
|
1228
1232
|
|
|
1229
1233
|
// src/lib/package-version.ts
|
|
1230
|
-
var CLI_VERSION = "0.2.
|
|
1234
|
+
var CLI_VERSION = "0.2.21";
|
|
1231
1235
|
|
|
1232
1236
|
// src/lib/render-error.ts
|
|
1233
1237
|
init_errors();
|
|
@@ -22568,7 +22572,7 @@ init_errors();
|
|
|
22568
22572
|
// ../../packages/brain/engine/dist/esm/types.js
|
|
22569
22573
|
var ENGINE_VERSION = "0.1.0";
|
|
22570
22574
|
var DEFAULT_SAFETY_LAG_SECONDS = 3600;
|
|
22571
|
-
var SOURCES = ["webapp", "a2a", "mcp", "telegram"];
|
|
22575
|
+
var SOURCES = ["webapp", "a2a", "mcp", "telegram", "voice-relay"];
|
|
22572
22576
|
var WORKER_ALIASES = { "azure-advisor": "azzy" };
|
|
22573
22577
|
function canonicalWorker(pk) {
|
|
22574
22578
|
const lower = pk.toLowerCase();
|
|
@@ -22632,9 +22636,11 @@ var TableCursor = class {
|
|
|
22632
22636
|
throw e;
|
|
22633
22637
|
}
|
|
22634
22638
|
const watermarks = row.watermarks ? JSON.parse(row.watermarks) : {};
|
|
22639
|
+
const fetchFailures = row.fetchFailures ? JSON.parse(row.fetchFailures) : void 0;
|
|
22635
22640
|
return {
|
|
22636
22641
|
worker: canonical,
|
|
22637
22642
|
watermarks,
|
|
22643
|
+
...fetchFailures && Object.keys(fetchFailures).length > 0 ? { fetchFailures } : {},
|
|
22638
22644
|
safetyLagSeconds: row.safetyLagSeconds ?? DEFAULT_SAFETY_LAG_SECONDS,
|
|
22639
22645
|
engineVersion: row.engineVersion ?? ENGINE_VERSION,
|
|
22640
22646
|
...row.lastDreamAt ? { lastDreamAt: row.lastDreamAt } : {}
|
|
@@ -22657,9 +22663,12 @@ var TableCursor = class {
|
|
|
22657
22663
|
safetyLagSeconds: cursor.safetyLagSeconds,
|
|
22658
22664
|
engineVersion: cursor.engineVersion
|
|
22659
22665
|
};
|
|
22666
|
+
if (cursor.fetchFailures && Object.keys(cursor.fetchFailures).length > 0) {
|
|
22667
|
+
entity.fetchFailures = JSON.stringify(cursor.fetchFailures);
|
|
22668
|
+
}
|
|
22660
22669
|
if (cursor.lastDreamAt)
|
|
22661
22670
|
entity.lastDreamAt = cursor.lastDreamAt;
|
|
22662
|
-
await this.client.upsertEntity(entity);
|
|
22671
|
+
await this.client.upsertEntity(entity, "Replace");
|
|
22663
22672
|
}
|
|
22664
22673
|
async ensureTable() {
|
|
22665
22674
|
try {
|
|
@@ -22695,9 +22704,22 @@ function computeWatermark(rows, now, safetyLagSeconds) {
|
|
|
22695
22704
|
}
|
|
22696
22705
|
async function commitCursorAdvance(plan, cursor) {
|
|
22697
22706
|
const prior = await cursor.read(plan.worker);
|
|
22707
|
+
const watermarks = {};
|
|
22708
|
+
for (const [pk, watermark] of Object.entries(plan.watermarks)) {
|
|
22709
|
+
const priorWatermark = Object.hasOwn(prior.watermarks, pk) ? prior.watermarks[pk] : void 0;
|
|
22710
|
+
if (priorWatermark && watermark.ts <= priorWatermark.ts) {
|
|
22711
|
+
watermarks[pk] = {
|
|
22712
|
+
ts: watermark.ts,
|
|
22713
|
+
consumedRowKeys: [.../* @__PURE__ */ new Set([...priorWatermark.consumedRowKeys, ...watermark.consumedRowKeys])]
|
|
22714
|
+
};
|
|
22715
|
+
} else {
|
|
22716
|
+
watermarks[pk] = watermark;
|
|
22717
|
+
}
|
|
22718
|
+
}
|
|
22698
22719
|
const next = {
|
|
22699
22720
|
worker: plan.worker,
|
|
22700
|
-
watermarks
|
|
22721
|
+
watermarks,
|
|
22722
|
+
...plan.fetchFailures && Object.keys(plan.fetchFailures).length > 0 ? { fetchFailures: plan.fetchFailures } : {},
|
|
22701
22723
|
safetyLagSeconds: prior.safetyLagSeconds || DEFAULT_SAFETY_LAG_SECONDS,
|
|
22702
22724
|
engineVersion: ENGINE_VERSION,
|
|
22703
22725
|
lastDreamAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -22951,6 +22973,7 @@ function normalize(group, items, enrichment) {
|
|
|
22951
22973
|
|
|
22952
22974
|
// ../../packages/brain/engine/dist/esm/pipeline.js
|
|
22953
22975
|
var isKnownSource = (s) => SOURCES.includes(s);
|
|
22976
|
+
var MAX_CONV_FETCH_ATTEMPTS = 3;
|
|
22954
22977
|
async function runPipeline(args) {
|
|
22955
22978
|
const { worker, sources, now, since, reset } = args;
|
|
22956
22979
|
const monotonicNow = args.monotonicNow ?? Date.now;
|
|
@@ -22977,6 +23000,7 @@ async function runPipeline(args) {
|
|
|
22977
23000
|
let recovered = 0;
|
|
22978
23001
|
const consumedRowsByPk = {};
|
|
22979
23002
|
const failedTsByPk = {};
|
|
23003
|
+
const newFailures = {};
|
|
22980
23004
|
const window2 = windowFor(rows, now, since);
|
|
22981
23005
|
for (const g of groups) {
|
|
22982
23006
|
const pk = g.worker;
|
|
@@ -23067,8 +23091,17 @@ async function runPipeline(args) {
|
|
|
23067
23091
|
else
|
|
23068
23092
|
recovered += 1;
|
|
23069
23093
|
} else {
|
|
23070
|
-
|
|
23071
|
-
if (outcome === "conv-fetch-failed"
|
|
23094
|
+
let lastError = fetchError?.message;
|
|
23095
|
+
if (outcome === "conv-fetch-failed") {
|
|
23096
|
+
const id = conversationId ?? "";
|
|
23097
|
+
const next = (cursor.fetchFailures?.[id] ?? 0) + 1;
|
|
23098
|
+
newFailures[id] = next;
|
|
23099
|
+
if (next >= MAX_CONV_FETCH_ATTEMPTS) {
|
|
23100
|
+
lastError = `terminal after ${String(next)} cycles \u2014 watermark released`;
|
|
23101
|
+
}
|
|
23102
|
+
}
|
|
23103
|
+
skips.addSkip(outcome, sampleId(g), lastError);
|
|
23104
|
+
if (outcome === "auth-failed" || outcome === "conv-fetch-failed" && conversationId && newFailures[conversationId] < MAX_CONV_FETCH_ATTEMPTS) {
|
|
23072
23105
|
const cur = failedTsByPk[pk];
|
|
23073
23106
|
if (!cur || g.startedAt < cur)
|
|
23074
23107
|
failedTsByPk[pk] = g.startedAt;
|
|
@@ -23088,7 +23121,7 @@ async function runPipeline(args) {
|
|
|
23088
23121
|
latencyMs: Math.round(monotonicNow() - t0)
|
|
23089
23122
|
};
|
|
23090
23123
|
assertInvariant(stats, groups.length);
|
|
23091
|
-
const advance = buildAdvancePlan(target, cursor, physicalPks, consumedRowsByPk, failedTsByPk, now, safetyLag);
|
|
23124
|
+
const advance = buildAdvancePlan(target, cursor, physicalPks, consumedRowsByPk, failedTsByPk, newFailures, now, safetyLag);
|
|
23092
23125
|
const out = {
|
|
23093
23126
|
worker: target,
|
|
23094
23127
|
window: window2,
|
|
@@ -23167,7 +23200,7 @@ function windowFor(rows, now, since) {
|
|
|
23167
23200
|
from = r.eventTimestamp;
|
|
23168
23201
|
return { from, to };
|
|
23169
23202
|
}
|
|
23170
|
-
function buildAdvancePlan(worker, cursor, physicalPks, consumedRowsByPk, failedTsByPk, now, safetyLagSeconds) {
|
|
23203
|
+
function buildAdvancePlan(worker, cursor, physicalPks, consumedRowsByPk, failedTsByPk, fetchFailures, now, safetyLagSeconds) {
|
|
23171
23204
|
const watermarks = {};
|
|
23172
23205
|
const consumedKeysByPk = {};
|
|
23173
23206
|
const priorTsByPk = {};
|
|
@@ -23191,6 +23224,7 @@ function buildAdvancePlan(worker, cursor, physicalPks, consumedRowsByPk, failedT
|
|
|
23191
23224
|
watermarks,
|
|
23192
23225
|
consumedRowsByPk: consumedKeysByPk,
|
|
23193
23226
|
failedTsByPk,
|
|
23227
|
+
...Object.keys(fetchFailures).length > 0 ? { fetchFailures } : {},
|
|
23194
23228
|
now: now.toISOString(),
|
|
23195
23229
|
safetyLagSeconds,
|
|
23196
23230
|
priorTsByPk
|
|
@@ -24183,6 +24217,7 @@ function narrowAdvance(src, kept) {
|
|
|
24183
24217
|
watermarks,
|
|
24184
24218
|
consumedRowsByPk,
|
|
24185
24219
|
failedTsByPk: src.failedTsByPk,
|
|
24220
|
+
...src.fetchFailures ? { fetchFailures: src.fetchFailures } : {},
|
|
24186
24221
|
now,
|
|
24187
24222
|
safetyLagSeconds,
|
|
24188
24223
|
priorTsByPk
|
|
@@ -24200,7 +24235,13 @@ function filterAdvance(src, keptRowsByPk) {
|
|
|
24200
24235
|
consumedRowsByPk[pk] = (src.consumedRowsByPk[pk] ?? []).filter((rk) => keep.has(rk));
|
|
24201
24236
|
watermarks[pk] = { ts: wm.ts, consumedRowKeys: wm.consumedRowKeys.filter((rk) => keep.has(rk)) };
|
|
24202
24237
|
}
|
|
24203
|
-
return {
|
|
24238
|
+
return {
|
|
24239
|
+
worker: src.worker,
|
|
24240
|
+
watermarks,
|
|
24241
|
+
consumedRowsByPk,
|
|
24242
|
+
failedTsByPk: src.failedTsByPk,
|
|
24243
|
+
...src.fetchFailures ? { fetchFailures: src.fetchFailures } : {}
|
|
24244
|
+
};
|
|
24204
24245
|
}
|
|
24205
24246
|
|
|
24206
24247
|
// ../../packages/brain/engine/dist/esm/dream/index.js
|
|
@@ -24218,6 +24259,18 @@ async function runDream(input, deps, seams = defaultDreamSeams()) {
|
|
|
24218
24259
|
});
|
|
24219
24260
|
}
|
|
24220
24261
|
input = capped;
|
|
24262
|
+
if (input.conversations.length === 0) {
|
|
24263
|
+
await commitCursorAdvance(input.advance, deps.cursor);
|
|
24264
|
+
deps.logger.info({
|
|
24265
|
+
at: "runDream",
|
|
24266
|
+
worker: input.worker,
|
|
24267
|
+
terminal: "no-corpus",
|
|
24268
|
+
skipped: input.stats.skipped,
|
|
24269
|
+
advanced: true,
|
|
24270
|
+
skipLedger: input.skipLedger.map((s) => `${s.reason}:${String(s.count)}`)
|
|
24271
|
+
});
|
|
24272
|
+
return { worker: input.worker, applied: [], digest, advanced: true };
|
|
24273
|
+
}
|
|
24221
24274
|
const proposed = await seams.propose(input, deps);
|
|
24222
24275
|
digest.push({ kind: "cost", model: proposed.cost.model, inputTokens: proposed.cost.inputTokens, outputTokens: proposed.cost.outputTokens, ms: proposed.cost.ms });
|
|
24223
24276
|
if (!proposed.deltas) {
|
|
@@ -26439,6 +26492,7 @@ function writeWebEnvLocal(args) {
|
|
|
26439
26492
|
`AZURE_TENANT_ID=${args.tenantId}`,
|
|
26440
26493
|
`AZURE_CLIENT_ID=${args.clientId}`,
|
|
26441
26494
|
`FOUNDRY_PROJECT_ENDPOINT=${args.foundryEndpoint}`,
|
|
26495
|
+
"VOICE_RELAY_PUBLIC_URL=ws://localhost:8790",
|
|
26442
26496
|
"STORAGE_ACCOUNT_NAME=",
|
|
26443
26497
|
"M8T_DISABLE_WORKER=1",
|
|
26444
26498
|
"M8T_ONBOARDING=1",
|
|
@@ -26493,11 +26547,16 @@ function onboardingUiPaths(home = os17.homedir()) {
|
|
|
26493
26547
|
pidPath: path35.join(dir, "onboarding-ui.pid")
|
|
26494
26548
|
};
|
|
26495
26549
|
}
|
|
26496
|
-
|
|
26497
|
-
const
|
|
26498
|
-
|
|
26499
|
-
|
|
26500
|
-
|
|
26550
|
+
function onboardingRelayPaths(home = os17.homedir()) {
|
|
26551
|
+
const dir = path35.join(home, ".m8t-stack");
|
|
26552
|
+
return {
|
|
26553
|
+
logPath: path35.join(dir, "onboarding-relay.log"),
|
|
26554
|
+
pidPath: path35.join(dir, "onboarding-relay.pid")
|
|
26555
|
+
};
|
|
26556
|
+
}
|
|
26557
|
+
function isLocalPortOpen(port) {
|
|
26558
|
+
return new Promise((resolve3) => {
|
|
26559
|
+
const s = net.createConnection({ host: "127.0.0.1", port });
|
|
26501
26560
|
s.setTimeout(1e3);
|
|
26502
26561
|
s.on("connect", () => {
|
|
26503
26562
|
s.destroy();
|
|
@@ -26511,6 +26570,11 @@ async function serveOnboardingUiDetached(args) {
|
|
|
26511
26570
|
resolve3(false);
|
|
26512
26571
|
});
|
|
26513
26572
|
});
|
|
26573
|
+
}
|
|
26574
|
+
async function serveOnboardingUiDetached(args) {
|
|
26575
|
+
const { logPath, pidPath } = onboardingUiPaths();
|
|
26576
|
+
const portNum = Number(args.port);
|
|
26577
|
+
const isPortOpen = () => isLocalPortOpen(portNum);
|
|
26514
26578
|
if (await isPortOpen()) {
|
|
26515
26579
|
return { alreadyRunning: true, logPath };
|
|
26516
26580
|
}
|
|
@@ -26541,6 +26605,46 @@ async function serveOnboardingUiDetached(args) {
|
|
|
26541
26605
|
}
|
|
26542
26606
|
return { alreadyRunning: false, logPath };
|
|
26543
26607
|
}
|
|
26608
|
+
async function serveOnboardingRelayDetached(args) {
|
|
26609
|
+
const { logPath, pidPath } = onboardingRelayPaths();
|
|
26610
|
+
const portNum = 8790;
|
|
26611
|
+
if (await isLocalPortOpen(portNum)) {
|
|
26612
|
+
return { alreadyRunning: true, logPath };
|
|
26613
|
+
}
|
|
26614
|
+
fs32.mkdirSync(path35.dirname(logPath), { recursive: true });
|
|
26615
|
+
const fd = fs32.openSync(logPath, "a");
|
|
26616
|
+
const child = spawn7("pnpm", ["--filter", "web", "exec", "tsx", "voice-relay-entry.ts"], {
|
|
26617
|
+
cwd: args.repoRoot,
|
|
26618
|
+
detached: true,
|
|
26619
|
+
stdio: ["ignore", fd, fd],
|
|
26620
|
+
env: {
|
|
26621
|
+
...process.env,
|
|
26622
|
+
FOUNDRY_PROJECT_ENDPOINT: args.foundryEndpoint,
|
|
26623
|
+
AZURE_TENANT_ID: args.tenantId,
|
|
26624
|
+
AZURE_CLIENT_ID: args.clientId,
|
|
26625
|
+
RELAY_ALLOWED_ORIGINS: "http://localhost:3000",
|
|
26626
|
+
RELAY_PORT: "8790"
|
|
26627
|
+
},
|
|
26628
|
+
shell: false
|
|
26629
|
+
});
|
|
26630
|
+
fs32.closeSync(fd);
|
|
26631
|
+
if (child.pid == null) {
|
|
26632
|
+
throw new LocalCliError({
|
|
26633
|
+
code: "BOOTSTRAP_UI_RELAY_SPAWN_FAILED",
|
|
26634
|
+
message: "Could not start the voice relay (pnpm did not spawn).",
|
|
26635
|
+
hint: "Check that pnpm + Node 20+ are installed; see the log at " + logPath + "."
|
|
26636
|
+
});
|
|
26637
|
+
}
|
|
26638
|
+
child.unref();
|
|
26639
|
+
fs32.writeFileSync(pidPath, String(child.pid), "utf8");
|
|
26640
|
+
const deadline = Date.now() + 45e3;
|
|
26641
|
+
const sleep3 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
26642
|
+
while (Date.now() < deadline) {
|
|
26643
|
+
await sleep3(500);
|
|
26644
|
+
if (await isLocalPortOpen(portNum)) break;
|
|
26645
|
+
}
|
|
26646
|
+
return { alreadyRunning: false, logPath };
|
|
26647
|
+
}
|
|
26544
26648
|
function autoOpenOnboardingUi(url, open = tryOpenUrl) {
|
|
26545
26649
|
try {
|
|
26546
26650
|
const result = open(url);
|
|
@@ -26551,8 +26655,7 @@ function autoOpenOnboardingUi(url, open = tryOpenUrl) {
|
|
|
26551
26655
|
} catch {
|
|
26552
26656
|
}
|
|
26553
26657
|
}
|
|
26554
|
-
function
|
|
26555
|
-
const { pidPath } = onboardingUiPaths(home);
|
|
26658
|
+
function stopPidFile(pidPath) {
|
|
26556
26659
|
let pidStr;
|
|
26557
26660
|
try {
|
|
26558
26661
|
pidStr = fs32.readFileSync(pidPath, "utf8").trim();
|
|
@@ -26573,6 +26676,11 @@ function stopOnboardingUi(home = os17.homedir()) {
|
|
|
26573
26676
|
}
|
|
26574
26677
|
return true;
|
|
26575
26678
|
}
|
|
26679
|
+
function stopOnboardingUi(home = os17.homedir()) {
|
|
26680
|
+
const uiStopped = stopPidFile(onboardingUiPaths(home).pidPath);
|
|
26681
|
+
const relayStopped = stopPidFile(onboardingRelayPaths(home).pidPath);
|
|
26682
|
+
return uiStopped || relayStopped;
|
|
26683
|
+
}
|
|
26576
26684
|
|
|
26577
26685
|
// src/lib/simple-stacey.ts
|
|
26578
26686
|
var SIMPLE_STACEY_PERSONA = "startup-advisor-intake";
|
|
@@ -26734,10 +26842,26 @@ var BootstrapUiCommand = class extends M8tCommand {
|
|
|
26734
26842
|
return 0;
|
|
26735
26843
|
}
|
|
26736
26844
|
if (this.foreground === true) {
|
|
26845
|
+
out("starting the voice relay on :8790 in the background\u2026");
|
|
26846
|
+
await serveOnboardingRelayDetached({
|
|
26847
|
+
repoRoot,
|
|
26848
|
+
foundryEndpoint: endpoint,
|
|
26849
|
+
tenantId: account.tenantId,
|
|
26850
|
+
clientId: state.appRegClientId
|
|
26851
|
+
});
|
|
26852
|
+
out("voice relay on :8790");
|
|
26737
26853
|
out("starting the webapp on :3000 (Ctrl-C to stop)\u2026");
|
|
26738
26854
|
await runInherit("pnpm", ["--filter", "web", "dev"], repoRoot, "BOOTSTRAP_UI_DEV_FAILED");
|
|
26739
26855
|
return 0;
|
|
26740
26856
|
}
|
|
26857
|
+
out("starting the voice relay on :8790 in the background\u2026");
|
|
26858
|
+
await serveOnboardingRelayDetached({
|
|
26859
|
+
repoRoot,
|
|
26860
|
+
foundryEndpoint: endpoint,
|
|
26861
|
+
tenantId: account.tenantId,
|
|
26862
|
+
clientId: state.appRegClientId
|
|
26863
|
+
});
|
|
26864
|
+
out("voice relay on :8790");
|
|
26741
26865
|
out("starting the webapp on :3000 in the background\u2026");
|
|
26742
26866
|
const { alreadyRunning, logPath } = await serveOnboardingUiDetached({ repoRoot, port: this.port });
|
|
26743
26867
|
if (alreadyRunning) {
|