@m8t-stack/cli 0.2.69 → 0.2.70
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 +471 -325
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1364,7 +1364,7 @@ var init_enable_hosted_brain = __esm({
|
|
|
1364
1364
|
import { Builtins, Cli } from "clipanion";
|
|
1365
1365
|
|
|
1366
1366
|
// src/lib/package-version.ts
|
|
1367
|
-
var CLI_VERSION = "0.2.
|
|
1367
|
+
var CLI_VERSION = "0.2.70";
|
|
1368
1368
|
|
|
1369
1369
|
// src/lib/render-error.ts
|
|
1370
1370
|
init_errors();
|
|
@@ -3698,12 +3698,12 @@ function encodeURIPath(str4) {
|
|
|
3698
3698
|
return str4.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent);
|
|
3699
3699
|
}
|
|
3700
3700
|
var EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));
|
|
3701
|
-
var createPathTagFunction = (pathEncoder = encodeURIPath) => function
|
|
3701
|
+
var createPathTagFunction = (pathEncoder = encodeURIPath) => function path43(statics, ...params) {
|
|
3702
3702
|
if (statics.length === 1)
|
|
3703
3703
|
return statics[0];
|
|
3704
3704
|
let postPath = false;
|
|
3705
3705
|
const invalidSegments = [];
|
|
3706
|
-
const
|
|
3706
|
+
const path44 = statics.reduce((previousValue, currentValue, index) => {
|
|
3707
3707
|
if (/[?#]/.test(currentValue)) {
|
|
3708
3708
|
postPath = true;
|
|
3709
3709
|
}
|
|
@@ -3720,7 +3720,7 @@ var createPathTagFunction = (pathEncoder = encodeURIPath) => function path42(sta
|
|
|
3720
3720
|
}
|
|
3721
3721
|
return previousValue + currentValue + (index === params.length ? "" : encoded);
|
|
3722
3722
|
}, "");
|
|
3723
|
-
const pathOnly =
|
|
3723
|
+
const pathOnly = path44.split(/[?#]/, 1)[0];
|
|
3724
3724
|
const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi;
|
|
3725
3725
|
let match;
|
|
3726
3726
|
while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) {
|
|
@@ -3741,10 +3741,10 @@ var createPathTagFunction = (pathEncoder = encodeURIPath) => function path42(sta
|
|
|
3741
3741
|
}, "");
|
|
3742
3742
|
throw new OpenAIError(`Path parameters result in path with invalid segments:
|
|
3743
3743
|
${invalidSegments.map((e) => e.error).join("\n")}
|
|
3744
|
-
${
|
|
3744
|
+
${path44}
|
|
3745
3745
|
${underline}`);
|
|
3746
3746
|
}
|
|
3747
|
-
return
|
|
3747
|
+
return path44;
|
|
3748
3748
|
};
|
|
3749
3749
|
var path = /* @__PURE__ */ createPathTagFunction(encodeURIPath);
|
|
3750
3750
|
|
|
@@ -12012,9 +12012,9 @@ var OpenAI = class {
|
|
|
12012
12012
|
this.apiKey = token;
|
|
12013
12013
|
return true;
|
|
12014
12014
|
}
|
|
12015
|
-
buildURL(
|
|
12015
|
+
buildURL(path43, query, defaultBaseURL) {
|
|
12016
12016
|
const baseURL = !__classPrivateFieldGet(this, _OpenAI_instances, "m", _OpenAI_baseURLOverridden).call(this) && defaultBaseURL || this.baseURL;
|
|
12017
|
-
const url = isAbsoluteURL(
|
|
12017
|
+
const url = isAbsoluteURL(path43) ? new URL(path43) : new URL(baseURL + (baseURL.endsWith("/") && path43.startsWith("/") ? path43.slice(1) : path43));
|
|
12018
12018
|
const defaultQuery = this.defaultQuery();
|
|
12019
12019
|
const pathQuery = Object.fromEntries(url.searchParams);
|
|
12020
12020
|
if (!isEmptyObj(defaultQuery) || !isEmptyObj(pathQuery)) {
|
|
@@ -12044,24 +12044,24 @@ var OpenAI = class {
|
|
|
12044
12044
|
*/
|
|
12045
12045
|
async prepareRequest(request, { url, options }) {
|
|
12046
12046
|
}
|
|
12047
|
-
get(
|
|
12048
|
-
return this.methodRequest("get",
|
|
12047
|
+
get(path43, opts) {
|
|
12048
|
+
return this.methodRequest("get", path43, opts);
|
|
12049
12049
|
}
|
|
12050
|
-
post(
|
|
12051
|
-
return this.methodRequest("post",
|
|
12050
|
+
post(path43, opts) {
|
|
12051
|
+
return this.methodRequest("post", path43, opts);
|
|
12052
12052
|
}
|
|
12053
|
-
patch(
|
|
12054
|
-
return this.methodRequest("patch",
|
|
12053
|
+
patch(path43, opts) {
|
|
12054
|
+
return this.methodRequest("patch", path43, opts);
|
|
12055
12055
|
}
|
|
12056
|
-
put(
|
|
12057
|
-
return this.methodRequest("put",
|
|
12056
|
+
put(path43, opts) {
|
|
12057
|
+
return this.methodRequest("put", path43, opts);
|
|
12058
12058
|
}
|
|
12059
|
-
delete(
|
|
12060
|
-
return this.methodRequest("delete",
|
|
12059
|
+
delete(path43, opts) {
|
|
12060
|
+
return this.methodRequest("delete", path43, opts);
|
|
12061
12061
|
}
|
|
12062
|
-
methodRequest(method,
|
|
12062
|
+
methodRequest(method, path43, opts) {
|
|
12063
12063
|
return this.request(Promise.resolve(opts).then((opts2) => {
|
|
12064
|
-
return { method, path:
|
|
12064
|
+
return { method, path: path43, ...opts2 };
|
|
12065
12065
|
}));
|
|
12066
12066
|
}
|
|
12067
12067
|
request(options, remainingRetries = null) {
|
|
@@ -12186,8 +12186,8 @@ var OpenAI = class {
|
|
|
12186
12186
|
}));
|
|
12187
12187
|
return { response, options, controller, requestLogID, retryOfRequestLogID, startTime };
|
|
12188
12188
|
}
|
|
12189
|
-
getAPIList(
|
|
12190
|
-
return this.requestAPIList(Page2, opts && "then" in opts ? opts.then((opts2) => ({ method: "get", path:
|
|
12189
|
+
getAPIList(path43, Page2, opts) {
|
|
12190
|
+
return this.requestAPIList(Page2, opts && "then" in opts ? opts.then((opts2) => ({ method: "get", path: path43, ...opts2 })) : { method: "get", path: path43, ...opts });
|
|
12191
12191
|
}
|
|
12192
12192
|
requestAPIList(Page2, options) {
|
|
12193
12193
|
const request = this.makeRequest(options, null, void 0);
|
|
@@ -12281,8 +12281,8 @@ var OpenAI = class {
|
|
|
12281
12281
|
}
|
|
12282
12282
|
async buildRequest(inputOptions, { retryCount = 0 } = {}) {
|
|
12283
12283
|
const options = { ...inputOptions };
|
|
12284
|
-
const { method, path:
|
|
12285
|
-
const url = this.buildURL(
|
|
12284
|
+
const { method, path: path43, query, defaultBaseURL } = options;
|
|
12285
|
+
const url = this.buildURL(path43, query, defaultBaseURL);
|
|
12286
12286
|
if ("timeout" in options)
|
|
12287
12287
|
validatePositiveInteger("timeout", options.timeout);
|
|
12288
12288
|
options.timeout = options.timeout ?? this.timeout;
|
|
@@ -12510,6 +12510,9 @@ function classifyFoundryError(err) {
|
|
|
12510
12510
|
}
|
|
12511
12511
|
|
|
12512
12512
|
// src/lib/render-error.ts
|
|
12513
|
+
function renderHint(hint) {
|
|
12514
|
+
return hint.split("\n").join("\n ");
|
|
12515
|
+
}
|
|
12513
12516
|
function renderError(err, opts) {
|
|
12514
12517
|
const mode = resolveOutputMode(opts.output, opts.stderr);
|
|
12515
12518
|
if (err instanceof Error && (err.name === "ExitPromptError" || err.message === "User force closed the prompt")) {
|
|
@@ -12533,7 +12536,7 @@ function renderError(err, opts) {
|
|
|
12533
12536
|
opts.stderr.write(`${colors.error("error:")} ${err.envelope.message}
|
|
12534
12537
|
`);
|
|
12535
12538
|
const hint = resolveBackendHint(err.envelope);
|
|
12536
|
-
if (hint) opts.stderr.write(` ${colors.hint("hint:")} ${hint}
|
|
12539
|
+
if (hint) opts.stderr.write(` ${colors.hint("hint:")} ${renderHint(hint)}
|
|
12537
12540
|
`);
|
|
12538
12541
|
if (opts.verbose) {
|
|
12539
12542
|
opts.stderr.write("\n" + colors.dim(renderJson(err.envelope)) + "\n");
|
|
@@ -12560,7 +12563,7 @@ function renderError(err, opts) {
|
|
|
12560
12563
|
opts.stderr.write(`${colors.error("error:")} ${err.message}
|
|
12561
12564
|
`);
|
|
12562
12565
|
const hint = err.hint ?? resolveLocalHint(err.code);
|
|
12563
|
-
if (hint) opts.stderr.write(` ${colors.hint("hint:")} ${hint}
|
|
12566
|
+
if (hint) opts.stderr.write(` ${colors.hint("hint:")} ${renderHint(hint)}
|
|
12564
12567
|
`);
|
|
12565
12568
|
if (opts.verbose && err.cause instanceof Error) {
|
|
12566
12569
|
opts.stderr.write("\n" + colors.dim(`caused by: ${err.cause.stack ?? err.cause.message}`) + "\n");
|
|
@@ -13325,10 +13328,10 @@ var BindListCommand = class extends M8tCommand {
|
|
|
13325
13328
|
const qs = new URLSearchParams();
|
|
13326
13329
|
if (this.channel) qs.set("channel", this.channel);
|
|
13327
13330
|
if (this.status) qs.set("status", this.status);
|
|
13328
|
-
const
|
|
13331
|
+
const path43 = qs.toString().length > 0 ? `/api/bindings?${qs.toString()}` : "/api/bindings";
|
|
13329
13332
|
const data = await apiCall(
|
|
13330
13333
|
{ gatewayUrl: ctx.gatewayUrl, gatewayClientId: ctx.gatewayClientId },
|
|
13331
|
-
{ method: "GET", path:
|
|
13334
|
+
{ method: "GET", path: path43 },
|
|
13332
13335
|
(msg) => this.context.stderr.write(msg + "\n")
|
|
13333
13336
|
);
|
|
13334
13337
|
if (mode === "json") {
|
|
@@ -14159,7 +14162,7 @@ var TeamShowCommand = class extends M8tCommand {
|
|
|
14159
14162
|
// src/commands/brain/app-create.ts
|
|
14160
14163
|
import * as fs4 from "fs";
|
|
14161
14164
|
import * as os from "os";
|
|
14162
|
-
import * as
|
|
14165
|
+
import * as path5 from "path";
|
|
14163
14166
|
import { randomBytes } from "crypto";
|
|
14164
14167
|
import * as readline from "readline/promises";
|
|
14165
14168
|
import { Command as Command16, Option as Option15 } from "clipanion";
|
|
@@ -14359,6 +14362,41 @@ async function findValidBrainApp(credsPath, org, deps = {}) {
|
|
|
14359
14362
|
}
|
|
14360
14363
|
}
|
|
14361
14364
|
|
|
14365
|
+
// src/lib/github-app-paths.ts
|
|
14366
|
+
import * as path4 from "path";
|
|
14367
|
+
function brainAppPointerPath(home) {
|
|
14368
|
+
return path4.join(home, ".m8t", "github-app.json");
|
|
14369
|
+
}
|
|
14370
|
+
function orgFileSegment(org) {
|
|
14371
|
+
return org.replace(/[^A-Za-z0-9-]+/g, "-");
|
|
14372
|
+
}
|
|
14373
|
+
function brainAppFilePaths(home, org, appId) {
|
|
14374
|
+
const dir = path4.join(home, ".m8t");
|
|
14375
|
+
const stem = `github-app-${orgFileSegment(org)}-${appId}`;
|
|
14376
|
+
return {
|
|
14377
|
+
pemPath: path4.join(dir, `${stem}.pem`),
|
|
14378
|
+
sidecarPath: path4.join(dir, `${stem}.json`)
|
|
14379
|
+
};
|
|
14380
|
+
}
|
|
14381
|
+
function isPreservable(v) {
|
|
14382
|
+
if (typeof v !== "object" || v === null) return false;
|
|
14383
|
+
const c = v;
|
|
14384
|
+
return typeof c.org === "string" && c.org !== "" && typeof c.appId === "string" && c.appId !== "";
|
|
14385
|
+
}
|
|
14386
|
+
function outgoingSidecarToPreserve(home, pointerText, sidecarExists) {
|
|
14387
|
+
if (pointerText === null) return null;
|
|
14388
|
+
let parsed;
|
|
14389
|
+
try {
|
|
14390
|
+
parsed = JSON.parse(pointerText);
|
|
14391
|
+
} catch {
|
|
14392
|
+
return null;
|
|
14393
|
+
}
|
|
14394
|
+
if (!isPreservable(parsed)) return null;
|
|
14395
|
+
const { sidecarPath } = brainAppFilePaths(home, parsed.org, parsed.appId);
|
|
14396
|
+
if (sidecarExists(sidecarPath)) return null;
|
|
14397
|
+
return { path: sidecarPath, org: parsed.org, appId: parsed.appId };
|
|
14398
|
+
}
|
|
14399
|
+
|
|
14362
14400
|
// src/lib/gh-helpers.ts
|
|
14363
14401
|
init_errors();
|
|
14364
14402
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -14539,8 +14577,8 @@ ${r.stderr}`;
|
|
|
14539
14577
|
message: `gh api /repos/${slug} failed (exit ${r.exitCode.toString()}): ${(r.stderr || r.stdout).slice(0, 200)}`
|
|
14540
14578
|
});
|
|
14541
14579
|
},
|
|
14542
|
-
getFile: async (
|
|
14543
|
-
const r = await exec("gh", ["api", "-H", "Accept: application/vnd.github.raw+json", `/repos/${slug}/contents/${
|
|
14580
|
+
getFile: async (path43) => {
|
|
14581
|
+
const r = await exec("gh", ["api", "-H", "Accept: application/vnd.github.raw+json", `/repos/${slug}/contents/${path43}`]);
|
|
14544
14582
|
return r.exitCode === 0 ? r.stdout : null;
|
|
14545
14583
|
},
|
|
14546
14584
|
isEmpty: async () => {
|
|
@@ -14607,6 +14645,36 @@ var BrainAppCreateCommand = class extends M8tCommand {
|
|
|
14607
14645
|
forceNew = Option15.Boolean("--new", false, {
|
|
14608
14646
|
description: "Create a new brain App even if one is already installed on the org."
|
|
14609
14647
|
});
|
|
14648
|
+
/**
|
|
14649
|
+
* Copy the currently-active App's record to its own per-App file when it has
|
|
14650
|
+
* none. Best-effort: a pointer that cannot be read or written is not a reason
|
|
14651
|
+
* to refuse to create an App, and the outcome is announced either way rather
|
|
14652
|
+
* than swallowed — losing this record silently is the failure being prevented.
|
|
14653
|
+
*/
|
|
14654
|
+
preserveOutgoingRecord(credsOut) {
|
|
14655
|
+
let pointerText;
|
|
14656
|
+
try {
|
|
14657
|
+
pointerText = fs4.readFileSync(credsOut, "utf8");
|
|
14658
|
+
} catch {
|
|
14659
|
+
return;
|
|
14660
|
+
}
|
|
14661
|
+
const outgoing = outgoingSidecarToPreserve(os.homedir(), pointerText, fs4.existsSync);
|
|
14662
|
+
if (!outgoing) return;
|
|
14663
|
+
try {
|
|
14664
|
+
fs4.mkdirSync(path5.dirname(outgoing.path), { recursive: true });
|
|
14665
|
+
fs4.writeFileSync(outgoing.path, pointerText, { mode: 384 });
|
|
14666
|
+
this.context.stderr.write(
|
|
14667
|
+
` ${colors.dim(`kept the current App's record (${outgoing.org}, id ${outgoing.appId}) at ${outgoing.path}`)}
|
|
14668
|
+
`
|
|
14669
|
+
);
|
|
14670
|
+
} catch (e) {
|
|
14671
|
+
this.context.stderr.write(
|
|
14672
|
+
` ${colors.warn(`could not save the current App's record to ${outgoing.path}: ${e.message}`)}
|
|
14673
|
+
${colors.warn(`back up ${credsOut} yourself if you need to switch back to that App.`)}
|
|
14674
|
+
`
|
|
14675
|
+
);
|
|
14676
|
+
}
|
|
14677
|
+
}
|
|
14610
14678
|
async executeCommand() {
|
|
14611
14679
|
if (!this.org) {
|
|
14612
14680
|
throw new LocalCliError({
|
|
@@ -14616,11 +14684,12 @@ var BrainAppCreateCommand = class extends M8tCommand {
|
|
|
14616
14684
|
});
|
|
14617
14685
|
}
|
|
14618
14686
|
const org = this.org;
|
|
14619
|
-
const
|
|
14620
|
-
const credsOut = typeof this.credsOut === "string" ? this.credsOut :
|
|
14687
|
+
const pemOutOverride = typeof this.pemOut === "string" ? this.pemOut : void 0;
|
|
14688
|
+
const credsOut = typeof this.credsOut === "string" ? this.credsOut : brainAppPointerPath(os.homedir());
|
|
14621
14689
|
const port = Number(this.port);
|
|
14622
14690
|
const onProgress = (m) => this.context.stderr.write(` ${colors.dim(m)}
|
|
14623
14691
|
`);
|
|
14692
|
+
this.preserveOutgoingRecord(credsOut);
|
|
14624
14693
|
const existing = await findValidBrainApp(credsOut, org);
|
|
14625
14694
|
if (existing) {
|
|
14626
14695
|
const isTTY = this.context.stdout.isTTY === true;
|
|
@@ -14669,7 +14738,9 @@ var BrainAppCreateCommand = class extends M8tCommand {
|
|
|
14669
14738
|
}),
|
|
14670
14739
|
onProgress
|
|
14671
14740
|
});
|
|
14672
|
-
|
|
14741
|
+
const layout = brainAppFilePaths(os.homedir(), org, app.id);
|
|
14742
|
+
const pemOut = pemOutOverride ?? layout.pemPath;
|
|
14743
|
+
fs4.mkdirSync(path5.dirname(pemOut), { recursive: true });
|
|
14673
14744
|
fs4.writeFileSync(pemOut, app.pem, { mode: 384 });
|
|
14674
14745
|
this.context.stdout.write(
|
|
14675
14746
|
`${colors.success("\u2713")} App created: ${colors.field(app.slug)} (id ${app.id}); pem \u2192 ${pemOut}
|
|
@@ -14683,11 +14754,16 @@ ${colors.success("\u2713")} installed on ${org} (installation ${installationId})
|
|
|
14683
14754
|
installationId,
|
|
14684
14755
|
pemPath: pemOut
|
|
14685
14756
|
};
|
|
14686
|
-
|
|
14687
|
-
|
|
14757
|
+
const credsJson = JSON.stringify(creds, null, 2);
|
|
14758
|
+
if (!pemOutOverride) {
|
|
14759
|
+
fs4.writeFileSync(layout.sidecarPath, credsJson, { mode: 384 });
|
|
14760
|
+
}
|
|
14761
|
+
fs4.mkdirSync(path5.dirname(credsOut), { recursive: true });
|
|
14762
|
+
fs4.writeFileSync(credsOut, credsJson, { mode: 384 });
|
|
14688
14763
|
this.context.stdout.write(
|
|
14689
|
-
`${colors.success("\u2713")} creds \u2192 ${credsOut}
|
|
14690
|
-
`
|
|
14764
|
+
`${colors.success("\u2713")} creds \u2192 ${credsOut} ${colors.dim("(this App is now the active one)")}
|
|
14765
|
+
` + (pemOutOverride ? "" : ` ${colors.dim(`kept alongside the key: ${layout.sidecarPath}`)}
|
|
14766
|
+
`)
|
|
14691
14767
|
);
|
|
14692
14768
|
if (this.output === "json") this.context.stdout.write(JSON.stringify(creds) + "\n");
|
|
14693
14769
|
return 0;
|
|
@@ -14703,7 +14779,7 @@ import { DefaultAzureCredential as DefaultAzureCredential3 } from "@azure/identi
|
|
|
14703
14779
|
init_errors();
|
|
14704
14780
|
import * as fs5 from "fs";
|
|
14705
14781
|
import * as os2 from "os";
|
|
14706
|
-
import * as
|
|
14782
|
+
import * as path6 from "path";
|
|
14707
14783
|
function discoverKvUri(env, override) {
|
|
14708
14784
|
if (override) return override;
|
|
14709
14785
|
const v = env.AZURE_KEYVAULT_URI ?? env.KEYVAULT_URI;
|
|
@@ -14715,7 +14791,7 @@ function discoverKvUri(env, override) {
|
|
|
14715
14791
|
});
|
|
14716
14792
|
}
|
|
14717
14793
|
function tryResolveRepoRoot() {
|
|
14718
|
-
const marker =
|
|
14794
|
+
const marker = path6.join(os2.homedir(), ".m8t", "repo-root");
|
|
14719
14795
|
if (!fs5.existsSync(marker)) return null;
|
|
14720
14796
|
const root = fs5.readFileSync(marker, "utf8").trim();
|
|
14721
14797
|
return root.length > 0 ? root : null;
|
|
@@ -14785,10 +14861,10 @@ var BrainCheckAppCommand = class extends M8tCommand {
|
|
|
14785
14861
|
init_esm2();
|
|
14786
14862
|
import { Command as Command18, Option as Option17 } from "clipanion";
|
|
14787
14863
|
import { execFileSync, spawnSync } from "child_process";
|
|
14788
|
-
import { readFileSync as
|
|
14864
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
14789
14865
|
import * as fs11 from "fs";
|
|
14790
14866
|
import * as os4 from "os";
|
|
14791
|
-
import * as
|
|
14867
|
+
import * as path11 from "path";
|
|
14792
14868
|
import * as readline2 from "readline/promises";
|
|
14793
14869
|
import { DefaultAzureCredential as DefaultAzureCredential4 } from "@azure/identity";
|
|
14794
14870
|
init_errors();
|
|
@@ -14808,6 +14884,9 @@ async function listProjectsForAccount(credential2, accountId) {
|
|
|
14808
14884
|
function formatProjectCandidate(c) {
|
|
14809
14885
|
return `${c.projectName} (account=${c.accountName}, ${c.region})`;
|
|
14810
14886
|
}
|
|
14887
|
+
function resourceGroupOfArmId(id) {
|
|
14888
|
+
return /\/resourceGroups\/([^/]+)/i.exec(id)?.[1].toLowerCase();
|
|
14889
|
+
}
|
|
14811
14890
|
async function resolveFoundryProject(opts) {
|
|
14812
14891
|
const candidates = [];
|
|
14813
14892
|
const accounts = await authedJsonPagedValues({
|
|
@@ -14844,29 +14923,37 @@ async function resolveFoundryProject(opts) {
|
|
|
14844
14923
|
const match = candidates.find((c) => c.endpoint === opts.agentEndpoint);
|
|
14845
14924
|
if (match) return match;
|
|
14846
14925
|
}
|
|
14847
|
-
|
|
14926
|
+
let scoped = candidates;
|
|
14927
|
+
if (opts.resourceGroup) {
|
|
14928
|
+
const want = opts.resourceGroup.toLowerCase();
|
|
14929
|
+
scoped = candidates.filter((c) => resourceGroupOfArmId(c.accountScope) === want);
|
|
14930
|
+
const dropped = candidates.filter((c) => !scoped.includes(c));
|
|
14931
|
+
if (dropped.length > 0) opts.onScopedOut?.(dropped);
|
|
14932
|
+
}
|
|
14933
|
+
const searched = opts.resourceGroup ? `resource group ${opts.resourceGroup} (subscription ${opts.subscriptionId})` : `subscription ${opts.subscriptionId}`;
|
|
14934
|
+
if (scoped.length === 0) {
|
|
14848
14935
|
throw new LocalCliError({
|
|
14849
14936
|
code: "FOUNDRY_PROJECT_ZERO",
|
|
14850
|
-
message: `No AIServices Foundry project found in
|
|
14937
|
+
message: `No AIServices Foundry project found in ${searched}.`,
|
|
14851
14938
|
hint: "Create one with 'm8t foundry create --resource-group <rg> --location <region>', switch subscription with 'az account set --subscription <id>', or pass --endpoint."
|
|
14852
14939
|
});
|
|
14853
14940
|
}
|
|
14854
|
-
if (
|
|
14941
|
+
if (scoped.length === 1) return scoped[0];
|
|
14855
14942
|
if (!opts.interactive) {
|
|
14856
14943
|
throw new LocalCliError({
|
|
14857
14944
|
code: "FOUNDRY_PROJECT_MULTIPLE",
|
|
14858
|
-
message: `Multiple Foundry projects found: ${
|
|
14859
|
-
hint: `Pass --endpoint <url> to choose. Endpoints: ${
|
|
14945
|
+
message: opts.resourceGroup ? `Resource group ${opts.resourceGroup} holds more than one Foundry project: ${scoped.map(formatProjectCandidate).join("; ")}.` : `Multiple Foundry projects found: ${scoped.map(formatProjectCandidate).join("; ")}.`,
|
|
14946
|
+
hint: `Pass --endpoint <url> to choose. Endpoints: ${scoped.map((c) => c.endpoint).join(" | ")}`
|
|
14860
14947
|
});
|
|
14861
14948
|
}
|
|
14862
14949
|
const endpoint = await select2({
|
|
14863
|
-
message: `Multiple Foundry projects in
|
|
14864
|
-
choices:
|
|
14950
|
+
message: `Multiple Foundry projects in ${searched}. Choose one:`,
|
|
14951
|
+
choices: scoped.map((c) => ({
|
|
14865
14952
|
name: formatProjectCandidate(c),
|
|
14866
14953
|
value: c.endpoint
|
|
14867
14954
|
}))
|
|
14868
14955
|
});
|
|
14869
|
-
const chosen =
|
|
14956
|
+
const chosen = scoped.find((c) => c.endpoint === endpoint);
|
|
14870
14957
|
if (!chosen) {
|
|
14871
14958
|
throw new LocalCliError({ code: "FOUNDRY_PROJECT_SELECTION_FAILED", message: "No project selected." });
|
|
14872
14959
|
}
|
|
@@ -14876,11 +14963,11 @@ async function resolveFoundryProject(opts) {
|
|
|
14876
14963
|
// src/lib/agent-yaml.ts
|
|
14877
14964
|
init_errors();
|
|
14878
14965
|
import * as fs6 from "fs";
|
|
14879
|
-
import * as
|
|
14966
|
+
import * as path7 from "path";
|
|
14880
14967
|
import * as os3 from "os";
|
|
14881
14968
|
import { parse as parseYaml3, stringify as stringifyYaml3 } from "yaml";
|
|
14882
14969
|
function agentYamlPath(agentName, home = os3.homedir()) {
|
|
14883
|
-
return
|
|
14970
|
+
return path7.join(home, ".m8t", "foundry", `${agentName}.yaml`);
|
|
14884
14971
|
}
|
|
14885
14972
|
function readAgentYaml(agentName, home) {
|
|
14886
14973
|
const file = agentYamlPath(agentName, home);
|
|
@@ -14890,7 +14977,7 @@ function readAgentYaml(agentName, home) {
|
|
|
14890
14977
|
}
|
|
14891
14978
|
function writeAgentYaml(agentName, data, home) {
|
|
14892
14979
|
const file = agentYamlPath(agentName, home);
|
|
14893
|
-
fs6.mkdirSync(
|
|
14980
|
+
fs6.mkdirSync(path7.dirname(file), { recursive: true });
|
|
14894
14981
|
fs6.writeFileSync(file, stringifyYaml3(data), { mode: 384 });
|
|
14895
14982
|
}
|
|
14896
14983
|
function patchAgentYaml(agentName, patch, home) {
|
|
@@ -14933,7 +15020,7 @@ function patchAgentYaml(agentName, patch, home) {
|
|
|
14933
15020
|
init_esm2();
|
|
14934
15021
|
init_esm();
|
|
14935
15022
|
init_errors();
|
|
14936
|
-
import * as
|
|
15023
|
+
import * as path8 from "path";
|
|
14937
15024
|
import * as fs8 from "fs";
|
|
14938
15025
|
|
|
14939
15026
|
// src/lib/persona-render.ts
|
|
@@ -15116,7 +15203,7 @@ async function linkBrain(args) {
|
|
|
15116
15203
|
progress(`Token rotated (expires ${rotation.expiresAt.toISOString()})`);
|
|
15117
15204
|
let foundryVersion;
|
|
15118
15205
|
if (!alreadyLinked) {
|
|
15119
|
-
const loaderPath =
|
|
15206
|
+
const loaderPath = path8.join(args.repoRoot, "targets/foundry/brain-loader.md");
|
|
15120
15207
|
const loaderTemplate = fs8.readFileSync(loaderPath, "utf8");
|
|
15121
15208
|
const loader = loaderTemplate.replaceAll("{{brain_repo}}", args.repo);
|
|
15122
15209
|
const yaml = readAgentYaml(args.agentName, args.home);
|
|
@@ -15124,7 +15211,7 @@ async function linkBrain(args) {
|
|
|
15124
15211
|
let base;
|
|
15125
15212
|
if (personaPath) {
|
|
15126
15213
|
progress("Re-rendering persona body with brain loader\u2026");
|
|
15127
|
-
const resolved = personaPath.startsWith("/") ? personaPath :
|
|
15214
|
+
const resolved = personaPath.startsWith("/") ? personaPath : path8.join(args.repoRoot, personaPath);
|
|
15128
15215
|
base = renderPersonaBody(resolved, yaml?.fillableFieldValues ?? {}, args.agentName);
|
|
15129
15216
|
} else {
|
|
15130
15217
|
progress("No local persona yaml \u2014 basing instructions on the deployed agent\u2026");
|
|
@@ -15281,11 +15368,11 @@ async function createBrainEnabledVersion(args) {
|
|
|
15281
15368
|
// src/lib/brain-seed.ts
|
|
15282
15369
|
init_errors();
|
|
15283
15370
|
import * as fs10 from "fs";
|
|
15284
|
-
import * as
|
|
15371
|
+
import * as path10 from "path";
|
|
15285
15372
|
|
|
15286
15373
|
// src/lib/seed-manifest.ts
|
|
15287
15374
|
import * as fs9 from "fs";
|
|
15288
|
-
import * as
|
|
15375
|
+
import * as path9 from "path";
|
|
15289
15376
|
var SEED_MANIFEST_PATH = ".m8t/seed-manifest.json";
|
|
15290
15377
|
var SEED_PATHS = ["skills", "references", "targets"];
|
|
15291
15378
|
function isLineage(v) {
|
|
@@ -15318,7 +15405,7 @@ function serializeSeedManifest(m) {
|
|
|
15318
15405
|
return JSON.stringify(m, null, 2) + "\n";
|
|
15319
15406
|
}
|
|
15320
15407
|
function walkFiles(root, rel = "") {
|
|
15321
|
-
const abs =
|
|
15408
|
+
const abs = path9.join(root, rel);
|
|
15322
15409
|
if (!fs9.existsSync(abs)) return [];
|
|
15323
15410
|
const out = [];
|
|
15324
15411
|
for (const entry of fs9.readdirSync(abs, { withFileTypes: true })) {
|
|
@@ -15331,14 +15418,14 @@ function walkFiles(root, rel = "") {
|
|
|
15331
15418
|
function deriveOwnedPaths(seedDir) {
|
|
15332
15419
|
const owned = /* @__PURE__ */ new Set([SEED_MANIFEST_PATH]);
|
|
15333
15420
|
for (const sub of SEED_PATHS) {
|
|
15334
|
-
for (const rel of walkFiles(
|
|
15421
|
+
for (const rel of walkFiles(path9.join(seedDir, sub))) owned.add(`${sub}/${rel}`);
|
|
15335
15422
|
}
|
|
15336
15423
|
return [...owned].sort((a, b) => a.localeCompare(b));
|
|
15337
15424
|
}
|
|
15338
15425
|
|
|
15339
15426
|
// src/lib/brain-seed.ts
|
|
15340
15427
|
function resolveSeed(name) {
|
|
15341
|
-
const dir =
|
|
15428
|
+
const dir = path10.join(resolveRepoRoot(), "brain-seeds", name);
|
|
15342
15429
|
if (!fs10.existsSync(dir)) {
|
|
15343
15430
|
throw new LocalCliError({
|
|
15344
15431
|
code: "SEED_NOT_FOUND",
|
|
@@ -15361,8 +15448,8 @@ function writeSeedMarker(args) {
|
|
|
15361
15448
|
refreshedToVersion: args.version,
|
|
15362
15449
|
ownedPaths: deriveOwnedPaths(args.seedDir)
|
|
15363
15450
|
}]);
|
|
15364
|
-
const dest =
|
|
15365
|
-
fs10.mkdirSync(
|
|
15451
|
+
const dest = path10.join(args.destDir, SEED_MANIFEST_PATH);
|
|
15452
|
+
fs10.mkdirSync(path10.dirname(dest), { recursive: true });
|
|
15366
15453
|
fs10.writeFileSync(dest, serializeSeedManifest(manifest));
|
|
15367
15454
|
}
|
|
15368
15455
|
|
|
@@ -15607,7 +15694,7 @@ function appRepoProbe(args) {
|
|
|
15607
15694
|
const res = await doFetch(`${GH_API}/repos/${args.repo}`, { headers: H, signal: AbortSignal.timeout(GH_REQUEST_TIMEOUT_MS) });
|
|
15608
15695
|
return res.status;
|
|
15609
15696
|
},
|
|
15610
|
-
getFile: (
|
|
15697
|
+
getFile: (path43) => readRepoFileViaApp({ token: args.token, repo: args.repo, path: path43, fetchImpl: args.fetchImpl }),
|
|
15611
15698
|
isEmpty: async () => {
|
|
15612
15699
|
const res = await doFetch(`${GH_API}/repos/${args.repo}/contents`, { headers: H, signal: AbortSignal.timeout(GH_REQUEST_TIMEOUT_MS) });
|
|
15613
15700
|
return res.status === 404;
|
|
@@ -15904,7 +15991,7 @@ var BrainCreateCommand = class extends M8tCommand {
|
|
|
15904
15991
|
if (useAppPath) {
|
|
15905
15992
|
await assertInstallationPermissions({
|
|
15906
15993
|
appId: appIdOpt,
|
|
15907
|
-
privateKeyPem:
|
|
15994
|
+
privateKeyPem: readFileSync7(appPemOpt, "utf8"),
|
|
15908
15995
|
installationId: installationIdOpt,
|
|
15909
15996
|
org: owner,
|
|
15910
15997
|
onUnverified: (m) => this.context.stderr.write(` ${colors.dim(`warning: ${m}`)}
|
|
@@ -15936,7 +16023,7 @@ var BrainCreateCommand = class extends M8tCommand {
|
|
|
15936
16023
|
agentEndpoint
|
|
15937
16024
|
});
|
|
15938
16025
|
const repoRoot = resolveRepoRoot();
|
|
15939
|
-
const templateSrc =
|
|
16026
|
+
const templateSrc = path11.join(repoRoot, "brain-template");
|
|
15940
16027
|
if (!fs11.existsSync(templateSrc)) {
|
|
15941
16028
|
throw new LocalCliError({
|
|
15942
16029
|
code: "TEMPLATE_MISSING",
|
|
@@ -15944,7 +16031,7 @@ var BrainCreateCommand = class extends M8tCommand {
|
|
|
15944
16031
|
hint: "Ensure brain-template/ exists at the repo root (same level as apps/)."
|
|
15945
16032
|
});
|
|
15946
16033
|
}
|
|
15947
|
-
const tmpDir = fs11.mkdtempSync(
|
|
16034
|
+
const tmpDir = fs11.mkdtempSync(path11.join(os4.tmpdir(), `m8t-brain-create-${worker}-`));
|
|
15948
16035
|
let result2;
|
|
15949
16036
|
let resolvedInstallationId = null;
|
|
15950
16037
|
const force = this.reuse === true ? "reuse" : this.newName === true ? "new" : void 0;
|
|
@@ -15954,7 +16041,7 @@ var BrainCreateCommand = class extends M8tCommand {
|
|
|
15954
16041
|
if (useAppPath) {
|
|
15955
16042
|
token = await mintInstallationTokenFromPem({
|
|
15956
16043
|
appId: appIdOpt,
|
|
15957
|
-
privateKeyPem:
|
|
16044
|
+
privateKeyPem: readFileSync7(appPemOpt, "utf8"),
|
|
15958
16045
|
installationId: installationIdOpt
|
|
15959
16046
|
});
|
|
15960
16047
|
const tok = token;
|
|
@@ -16530,7 +16617,7 @@ init_esm2();
|
|
|
16530
16617
|
init_errors();
|
|
16531
16618
|
import * as fs12 from "fs";
|
|
16532
16619
|
import * as os5 from "os";
|
|
16533
|
-
import * as
|
|
16620
|
+
import * as path12 from "path";
|
|
16534
16621
|
init_foundry_agent_get();
|
|
16535
16622
|
init_foundry_agent_version();
|
|
16536
16623
|
var FOUNDRY_ARM_API2 = "2025-04-01-preview";
|
|
@@ -16561,7 +16648,7 @@ async function unlinkBrain(args) {
|
|
|
16561
16648
|
if (yaml?.personaPath) {
|
|
16562
16649
|
let personaPath = yaml.personaPath;
|
|
16563
16650
|
if (!personaPath.startsWith("/")) {
|
|
16564
|
-
const marker =
|
|
16651
|
+
const marker = path12.join(args.home ?? os5.homedir(), ".m8t", "repo-root");
|
|
16565
16652
|
if (!fs12.existsSync(marker)) {
|
|
16566
16653
|
throw new LocalCliError({
|
|
16567
16654
|
code: "PERSONA_PATH_NOT_ABSOLUTE",
|
|
@@ -16569,7 +16656,7 @@ async function unlinkBrain(args) {
|
|
|
16569
16656
|
hint: "Re-run 'm8t install' from a fresh m8t checkout (writes ~/.m8t/repo-root) \u2014 or edit the personaPath to absolute."
|
|
16570
16657
|
});
|
|
16571
16658
|
}
|
|
16572
|
-
personaPath =
|
|
16659
|
+
personaPath = path12.join(fs12.readFileSync(marker, "utf8").trim(), personaPath);
|
|
16573
16660
|
}
|
|
16574
16661
|
strippedInstructions = renderPersonaBody(personaPath, yaml.fillableFieldValues ?? {}, args.agentName);
|
|
16575
16662
|
} else {
|
|
@@ -16791,24 +16878,24 @@ init_errors();
|
|
|
16791
16878
|
|
|
16792
16879
|
// src/lib/deploy-prompt-advisor.ts
|
|
16793
16880
|
import * as fs13 from "fs";
|
|
16794
|
-
import * as
|
|
16881
|
+
import * as path13 from "path";
|
|
16795
16882
|
import { parse as parseYaml6 } from "yaml";
|
|
16796
16883
|
init_foundry_agents();
|
|
16797
16884
|
init_errors();
|
|
16798
16885
|
init_esm();
|
|
16799
16886
|
function findPersonasRoot(hint) {
|
|
16800
|
-
let dir =
|
|
16801
|
-
const fsRoot =
|
|
16887
|
+
let dir = path13.resolve(hint);
|
|
16888
|
+
const fsRoot = path13.parse(dir).root;
|
|
16802
16889
|
for (; ; ) {
|
|
16803
|
-
if (fs13.existsSync(
|
|
16804
|
-
const parent =
|
|
16890
|
+
if (fs13.existsSync(path13.join(dir, "personas"))) return dir;
|
|
16891
|
+
const parent = path13.dirname(dir);
|
|
16805
16892
|
if (parent === dir || dir === fsRoot) return null;
|
|
16806
16893
|
dir = parent;
|
|
16807
16894
|
}
|
|
16808
16895
|
}
|
|
16809
16896
|
async function deployPromptAdvisor(args) {
|
|
16810
16897
|
const resolvedRoot = findPersonasRoot(args.repoRoot);
|
|
16811
|
-
const personaPath = resolvedRoot ?
|
|
16898
|
+
const personaPath = resolvedRoot ? path13.join(resolvedRoot, "personas", args.persona, "persona.md") : path13.join(args.repoRoot, "personas", args.persona, "persona.md");
|
|
16812
16899
|
let raw;
|
|
16813
16900
|
try {
|
|
16814
16901
|
raw = fs13.readFileSync(personaPath, "utf8");
|
|
@@ -17572,7 +17659,7 @@ ${colors.success("\u2713")} removed ${colors.field(name)}.
|
|
|
17572
17659
|
};
|
|
17573
17660
|
|
|
17574
17661
|
// src/commands/a2a/enable.ts
|
|
17575
|
-
import * as
|
|
17662
|
+
import * as path15 from "path";
|
|
17576
17663
|
import { Command as Command26, Option as Option25 } from "clipanion";
|
|
17577
17664
|
import { DefaultAzureCredential as DefaultAzureCredential11 } from "@azure/identity";
|
|
17578
17665
|
init_errors();
|
|
@@ -17581,7 +17668,7 @@ init_errors();
|
|
|
17581
17668
|
init_errors();
|
|
17582
17669
|
import * as fs16 from "fs";
|
|
17583
17670
|
import * as os6 from "os";
|
|
17584
|
-
import * as
|
|
17671
|
+
import * as path14 from "path";
|
|
17585
17672
|
import { parse as parseYaml8 } from "yaml";
|
|
17586
17673
|
var A2A_PATH = "/api/a2a/mcp";
|
|
17587
17674
|
function resolveBridgeUrl(opts) {
|
|
@@ -17603,7 +17690,7 @@ function clean(v) {
|
|
|
17603
17690
|
return t.length ? t : void 0;
|
|
17604
17691
|
}
|
|
17605
17692
|
function readConfigGatewayUrl(home) {
|
|
17606
|
-
const cfg =
|
|
17693
|
+
const cfg = path14.join(home ?? os6.homedir(), ".m8t", "config.yaml");
|
|
17607
17694
|
if (!fs16.existsSync(cfg)) return void 0;
|
|
17608
17695
|
try {
|
|
17609
17696
|
const o = parseYaml8(fs16.readFileSync(cfg, "utf8"));
|
|
@@ -17675,11 +17762,11 @@ var A2aEnableCommand = class extends M8tCommand {
|
|
|
17675
17762
|
resolvePersonaPath() {
|
|
17676
17763
|
if (typeof this.persona === "string" && this.persona.length > 0) {
|
|
17677
17764
|
if (this.persona.includes("/") || this.persona.endsWith(".md")) return this.persona;
|
|
17678
|
-
return
|
|
17765
|
+
return path15.join(resolveRepoRoot(), "personas", this.persona, "persona.md");
|
|
17679
17766
|
}
|
|
17680
17767
|
const yaml = readAgentYaml(this.worker);
|
|
17681
17768
|
if (yaml?.personaPath) {
|
|
17682
|
-
return yaml.personaPath.startsWith("/") ? yaml.personaPath :
|
|
17769
|
+
return yaml.personaPath.startsWith("/") ? yaml.personaPath : path15.join(resolveRepoRoot(), yaml.personaPath);
|
|
17683
17770
|
}
|
|
17684
17771
|
throw new LocalCliError({ code: "A2A_NO_PERSONA", message: `Could not resolve a persona for '${this.worker}'. Pass --persona <name>.` });
|
|
17685
17772
|
}
|
|
@@ -17737,7 +17824,7 @@ import { Command as Command28 } from "clipanion";
|
|
|
17737
17824
|
import { createHash as createHash2 } from "crypto";
|
|
17738
17825
|
import * as fs17 from "fs";
|
|
17739
17826
|
import * as os7 from "os";
|
|
17740
|
-
import * as
|
|
17827
|
+
import * as path16 from "path";
|
|
17741
17828
|
function readVersionFrontmatter(file) {
|
|
17742
17829
|
if (!fs17.existsSync(file)) return "";
|
|
17743
17830
|
const text = fs17.readFileSync(file, "utf8");
|
|
@@ -17755,20 +17842,20 @@ var SIDECAR_FILENAME = "m8t-architect.m8t-skill.json";
|
|
|
17755
17842
|
var LEGACY_SIDECAR_FILENAME = ".m8t-skill.json";
|
|
17756
17843
|
function vsCodeUserDataDir() {
|
|
17757
17844
|
if (process.platform === "darwin") {
|
|
17758
|
-
return
|
|
17845
|
+
return path16.join(os7.homedir(), "Library", "Application Support", "Code", "User");
|
|
17759
17846
|
}
|
|
17760
17847
|
if (process.platform === "win32") {
|
|
17761
|
-
const appData = process.env.APPDATA ??
|
|
17762
|
-
return
|
|
17848
|
+
const appData = process.env.APPDATA ?? path16.join(os7.homedir(), "AppData", "Roaming");
|
|
17849
|
+
return path16.join(appData, "Code", "User");
|
|
17763
17850
|
}
|
|
17764
17851
|
return null;
|
|
17765
17852
|
}
|
|
17766
17853
|
function vsCodePromptsDir() {
|
|
17767
17854
|
const userData = vsCodeUserDataDir();
|
|
17768
17855
|
if (!userData) return null;
|
|
17769
|
-
const prompts =
|
|
17856
|
+
const prompts = path16.join(userData, "prompts");
|
|
17770
17857
|
if (fs17.existsSync(prompts)) return prompts;
|
|
17771
|
-
const promptFiles =
|
|
17858
|
+
const promptFiles = path16.join(userData, "prompt-files");
|
|
17772
17859
|
if (fs17.existsSync(promptFiles)) return promptFiles;
|
|
17773
17860
|
return prompts;
|
|
17774
17861
|
}
|
|
@@ -17780,7 +17867,7 @@ var COPILOT_CLI_SKILLS_ROOTS = [
|
|
|
17780
17867
|
function sidecarLocations() {
|
|
17781
17868
|
const home = os7.homedir();
|
|
17782
17869
|
const locations = [
|
|
17783
|
-
{ host: "Claude Code", dir:
|
|
17870
|
+
{ host: "Claude Code", dir: path16.join(home, ".claude", "skills", "m8t-architect") }
|
|
17784
17871
|
];
|
|
17785
17872
|
const vsCodeDir = vsCodePromptsDir();
|
|
17786
17873
|
if (vsCodeDir) {
|
|
@@ -17789,7 +17876,7 @@ function sidecarLocations() {
|
|
|
17789
17876
|
for (const segments of COPILOT_CLI_SKILLS_ROOTS) {
|
|
17790
17877
|
locations.push({
|
|
17791
17878
|
host: "GitHub Copilot CLI",
|
|
17792
|
-
dir:
|
|
17879
|
+
dir: path16.join(home, ...segments, "m8t-architect")
|
|
17793
17880
|
});
|
|
17794
17881
|
}
|
|
17795
17882
|
return locations;
|
|
@@ -17798,7 +17885,7 @@ function resolveSidecar() {
|
|
|
17798
17885
|
let best = null;
|
|
17799
17886
|
for (const loc of sidecarLocations()) {
|
|
17800
17887
|
for (const filename of [SIDECAR_FILENAME, LEGACY_SIDECAR_FILENAME]) {
|
|
17801
|
-
const candidate2 =
|
|
17888
|
+
const candidate2 = path16.join(loc.dir, filename);
|
|
17802
17889
|
let mtimeMs;
|
|
17803
17890
|
try {
|
|
17804
17891
|
mtimeMs = fs17.statSync(candidate2).mtimeMs;
|
|
@@ -17813,7 +17900,7 @@ function resolveSidecar() {
|
|
|
17813
17900
|
return best;
|
|
17814
17901
|
}
|
|
17815
17902
|
function checkArchitectDrift() {
|
|
17816
|
-
const sourcePath =
|
|
17903
|
+
const sourcePath = path16.join(
|
|
17817
17904
|
resolveRepoRoot(),
|
|
17818
17905
|
"personas",
|
|
17819
17906
|
"m8t-architect",
|
|
@@ -17896,7 +17983,7 @@ var ArchitectCheckCommand = class extends M8tCommand {
|
|
|
17896
17983
|
|
|
17897
17984
|
// src/commands/coder/deploy.ts
|
|
17898
17985
|
init_esm2();
|
|
17899
|
-
import * as
|
|
17986
|
+
import * as path18 from "path";
|
|
17900
17987
|
import { Command as Command29, Option as Option27 } from "clipanion";
|
|
17901
17988
|
import { DefaultAzureCredential as DefaultAzureCredential13 } from "@azure/identity";
|
|
17902
17989
|
init_errors();
|
|
@@ -18164,13 +18251,13 @@ async function deployHostedWorker(args) {
|
|
|
18164
18251
|
|
|
18165
18252
|
// src/lib/persona.ts
|
|
18166
18253
|
import * as fs18 from "fs";
|
|
18167
|
-
import * as
|
|
18254
|
+
import * as path17 from "path";
|
|
18168
18255
|
import { parse as parseYaml9 } from "yaml";
|
|
18169
18256
|
function findRepoRoot(startDir) {
|
|
18170
|
-
let dir =
|
|
18257
|
+
let dir = path17.resolve(startDir);
|
|
18171
18258
|
for (; ; ) {
|
|
18172
|
-
if (fs18.existsSync(
|
|
18173
|
-
const parent =
|
|
18259
|
+
if (fs18.existsSync(path17.join(dir, "personas"))) return dir;
|
|
18260
|
+
const parent = path17.dirname(dir);
|
|
18174
18261
|
if (parent === dir) return null;
|
|
18175
18262
|
dir = parent;
|
|
18176
18263
|
}
|
|
@@ -18178,7 +18265,7 @@ function findRepoRoot(startDir) {
|
|
|
18178
18265
|
function resolvePersona(persona, cwd = process.cwd()) {
|
|
18179
18266
|
const root = findRepoRoot(cwd);
|
|
18180
18267
|
if (!root) return { persona, personaVersion: null };
|
|
18181
|
-
const file =
|
|
18268
|
+
const file = path17.join(root, "personas", persona, "persona.md");
|
|
18182
18269
|
let raw;
|
|
18183
18270
|
try {
|
|
18184
18271
|
raw = fs18.readFileSync(file, "utf-8");
|
|
@@ -18538,7 +18625,7 @@ var CoderDeployCommand = class extends M8tCommand {
|
|
|
18538
18625
|
projectEndpoint: project.endpoint,
|
|
18539
18626
|
projectArmId: `${project.accountScope}/projects/${project.projectName}`,
|
|
18540
18627
|
agentName: this.name,
|
|
18541
|
-
personaPath:
|
|
18628
|
+
personaPath: path18.join(resolveRepoRoot(), "personas", personaName, "persona.md"),
|
|
18542
18629
|
bridgeUrl,
|
|
18543
18630
|
onProgress
|
|
18544
18631
|
});
|
|
@@ -18665,7 +18752,7 @@ var CoderTeardownCommand = class extends M8tCommand {
|
|
|
18665
18752
|
|
|
18666
18753
|
// src/commands/azure-exec/deploy.ts
|
|
18667
18754
|
init_esm2();
|
|
18668
|
-
import * as
|
|
18755
|
+
import * as path19 from "path";
|
|
18669
18756
|
import { Command as Command31, Option as Option29 } from "clipanion";
|
|
18670
18757
|
import { DefaultAzureCredential as DefaultAzureCredential15 } from "@azure/identity";
|
|
18671
18758
|
init_errors();
|
|
@@ -18941,7 +19028,7 @@ var AzureExecDeployCommand = class extends M8tCommand {
|
|
|
18941
19028
|
kvUri
|
|
18942
19029
|
});
|
|
18943
19030
|
onProgress?.("a2a-enabling as a target\u2026");
|
|
18944
|
-
const personaPath =
|
|
19031
|
+
const personaPath = path19.join(resolveRepoRoot(), "personas", "azure-executor", "persona.md");
|
|
18945
19032
|
const bridgeUrl = resolveBridgeUrl({
|
|
18946
19033
|
flag: typeof this.gatewayUrl === "string" ? this.gatewayUrl : void 0,
|
|
18947
19034
|
env: processEnv
|
|
@@ -19107,8 +19194,8 @@ async function fetchPublicTags(repo, fetchImpl = fetch) {
|
|
|
19107
19194
|
hint: "Pass a ghcr.io/<owner>/<name> repo, or use the BYOC private-ACR deploy flow."
|
|
19108
19195
|
});
|
|
19109
19196
|
}
|
|
19110
|
-
const
|
|
19111
|
-
const tokenRes = await fetchImpl(`https://ghcr.io/token?scope=repository:${
|
|
19197
|
+
const path43 = repo.replace(/^ghcr\.io\//, "");
|
|
19198
|
+
const tokenRes = await fetchImpl(`https://ghcr.io/token?scope=repository:${path43}:pull`);
|
|
19112
19199
|
if (!tokenRes.ok) {
|
|
19113
19200
|
throw new LocalCliError({
|
|
19114
19201
|
code: "PLATFORM_GHCR_TOKEN_FAILED",
|
|
@@ -19124,7 +19211,7 @@ async function fetchPublicTags(repo, fetchImpl = fetch) {
|
|
|
19124
19211
|
hint: "Make the package public (deploy/ghcr-package-visibility.md), then retry."
|
|
19125
19212
|
});
|
|
19126
19213
|
}
|
|
19127
|
-
const tagsRes = await fetchImpl(`https://ghcr.io/v2/${
|
|
19214
|
+
const tagsRes = await fetchImpl(`https://ghcr.io/v2/${path43}/tags/list`, {
|
|
19128
19215
|
headers: { Authorization: `Bearer ${token}` }
|
|
19129
19216
|
});
|
|
19130
19217
|
if (!tagsRes.ok) {
|
|
@@ -19409,7 +19496,7 @@ async function fetchManifest(source, deps = {}) {
|
|
|
19409
19496
|
// src/lib/release-content.ts
|
|
19410
19497
|
import * as fs20 from "fs";
|
|
19411
19498
|
import * as os8 from "os";
|
|
19412
|
-
import * as
|
|
19499
|
+
import * as path20 from "path";
|
|
19413
19500
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
19414
19501
|
init_errors();
|
|
19415
19502
|
var OWNER_REPO = "m8t-labs/m8t";
|
|
@@ -19448,15 +19535,15 @@ function verifyPersonaTrees(manifest, tree) {
|
|
|
19448
19535
|
}
|
|
19449
19536
|
async function resolveReleaseContent(manifest, opts = {}) {
|
|
19450
19537
|
if (opts.contentDir) {
|
|
19451
|
-
if (!fs20.existsSync(
|
|
19538
|
+
if (!fs20.existsSync(path20.join(opts.contentDir, "personas"))) {
|
|
19452
19539
|
throw new LocalCliError({ code: "PLATFORM_CONTENT_DIR_INVALID", message: `--content-dir '${opts.contentDir}' has no personas/ \u2014 not a repo checkout.` });
|
|
19453
19540
|
}
|
|
19454
19541
|
return opts.contentDir;
|
|
19455
19542
|
}
|
|
19456
19543
|
const commit = manifest.platform.commit;
|
|
19457
|
-
const cacheRoot = opts.cacheRoot ??
|
|
19458
|
-
const dest =
|
|
19459
|
-
if (fs20.existsSync(
|
|
19544
|
+
const cacheRoot = opts.cacheRoot ?? path20.join(os8.homedir(), ".m8t", "cache");
|
|
19545
|
+
const dest = path20.join(cacheRoot, `release-${commit}`);
|
|
19546
|
+
if (fs20.existsSync(path20.join(dest, "personas"))) return dest;
|
|
19460
19547
|
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
19461
19548
|
const ghToken = opts.ghToken ?? getGhToken;
|
|
19462
19549
|
let token;
|
|
@@ -19471,18 +19558,18 @@ async function resolveReleaseContent(manifest, opts = {}) {
|
|
|
19471
19558
|
throw new LocalCliError({ code: "PLATFORM_TARBALL_FETCH_FAILED", message: `GET ${url} \u2192 HTTP ${res.status.toString()}.` });
|
|
19472
19559
|
}
|
|
19473
19560
|
fs20.mkdirSync(cacheRoot, { recursive: true });
|
|
19474
|
-
const tmp = fs20.mkdtempSync(
|
|
19561
|
+
const tmp = fs20.mkdtempSync(path20.join(cacheRoot, `.dl-${commit.slice(0, 8)}-`));
|
|
19475
19562
|
try {
|
|
19476
|
-
const tgz =
|
|
19563
|
+
const tgz = path20.join(tmp, "src.tar.gz");
|
|
19477
19564
|
fs20.writeFileSync(tgz, Buffer.from(await res.arrayBuffer()));
|
|
19478
|
-
const unpacked =
|
|
19565
|
+
const unpacked = path20.join(tmp, "unpacked");
|
|
19479
19566
|
fs20.mkdirSync(unpacked);
|
|
19480
19567
|
extractTarGz(tgz, unpacked);
|
|
19481
19568
|
try {
|
|
19482
19569
|
fs20.renameSync(unpacked, dest);
|
|
19483
19570
|
} catch (e) {
|
|
19484
19571
|
const err = e;
|
|
19485
|
-
const isBenignRace = (err.code === "EEXIST" || err.code === "ENOTEMPTY") && fs20.existsSync(
|
|
19572
|
+
const isBenignRace = (err.code === "EEXIST" || err.code === "ENOTEMPTY") && fs20.existsSync(path20.join(dest, "personas"));
|
|
19486
19573
|
if (!isBenignRace) {
|
|
19487
19574
|
throw new LocalCliError({
|
|
19488
19575
|
code: "PLATFORM_CACHE_PUBLISH_FAILED",
|
|
@@ -19649,13 +19736,13 @@ async function readStamp(opts) {
|
|
|
19649
19736
|
// src/lib/platform-converge.ts
|
|
19650
19737
|
init_esm();
|
|
19651
19738
|
import * as fs22 from "fs";
|
|
19652
|
-
import * as
|
|
19739
|
+
import * as path22 from "path";
|
|
19653
19740
|
import { parse as parseYaml10 } from "yaml";
|
|
19654
19741
|
|
|
19655
19742
|
// src/lib/deploy.ts
|
|
19656
19743
|
import * as fs21 from "fs/promises";
|
|
19657
19744
|
import * as os9 from "os";
|
|
19658
|
-
import * as
|
|
19745
|
+
import * as path21 from "path";
|
|
19659
19746
|
init_errors();
|
|
19660
19747
|
var FOUNDRY_TRACING_MODES = ["project", "account", "skip"];
|
|
19661
19748
|
function parseFoundryTracingMode(v) {
|
|
@@ -19714,7 +19801,7 @@ function buildBicepParams(p) {
|
|
|
19714
19801
|
return params;
|
|
19715
19802
|
}
|
|
19716
19803
|
async function resolveRepoRoot2(home = os9.homedir()) {
|
|
19717
|
-
const marker =
|
|
19804
|
+
const marker = path21.join(home, ".m8t", "repo-root");
|
|
19718
19805
|
try {
|
|
19719
19806
|
const root = (await fs21.readFile(marker, "utf8")).trim();
|
|
19720
19807
|
if (!root) throw new Error("empty");
|
|
@@ -19802,7 +19889,7 @@ function buildDeployResult(args) {
|
|
|
19802
19889
|
};
|
|
19803
19890
|
}
|
|
19804
19891
|
async function runBicepDeployment(opts) {
|
|
19805
|
-
const bicepPath =
|
|
19892
|
+
const bicepPath = path21.join(opts.repoRoot, "deploy", "main.bicep");
|
|
19806
19893
|
const result2 = JSON.parse(
|
|
19807
19894
|
await runAz([
|
|
19808
19895
|
"deployment",
|
|
@@ -20212,7 +20299,7 @@ function brainRepoOf(current) {
|
|
|
20212
20299
|
}
|
|
20213
20300
|
async function applyPersona(a, ctx, opts) {
|
|
20214
20301
|
const current = await getAgentVersion({ credential: ctx.credential, projectEndpoint: opts.project.endpoint, agentName: opts.agentName });
|
|
20215
|
-
const personaPath =
|
|
20302
|
+
const personaPath = path22.join(opts.personaDir, "persona.md");
|
|
20216
20303
|
const yamlValues = readAgentYaml(opts.agentName)?.fillableFieldValues ?? null;
|
|
20217
20304
|
const values = resolveFillableValues(current, yamlValues);
|
|
20218
20305
|
const declared = declaredFillableFields(personaPath);
|
|
@@ -20317,6 +20404,33 @@ function renderLiveVerify(v, apiVersion, fmt2 = { ok: (s) => s, warn: (s) => s }
|
|
|
20317
20404
|
];
|
|
20318
20405
|
}
|
|
20319
20406
|
|
|
20407
|
+
// src/lib/gateway-api.ts
|
|
20408
|
+
function versionFromEnvelope(body) {
|
|
20409
|
+
if (typeof body !== "object" || body === null) return void 0;
|
|
20410
|
+
const data = body.data;
|
|
20411
|
+
if (typeof data !== "object" || data === null) return void 0;
|
|
20412
|
+
const version = data.version;
|
|
20413
|
+
return typeof version === "string" && version.length > 0 ? version : void 0;
|
|
20414
|
+
}
|
|
20415
|
+
function renderVersionRead(read) {
|
|
20416
|
+
if (read.kind === "version") return read.version;
|
|
20417
|
+
if (read.kind === "auth-gated") return "unknown (auth-gated)";
|
|
20418
|
+
return "unknown";
|
|
20419
|
+
}
|
|
20420
|
+
async function readGatewayVersion(gatewayUrl, fetchImpl = fetch) {
|
|
20421
|
+
let res;
|
|
20422
|
+
try {
|
|
20423
|
+
res = await fetchImpl(`${gatewayUrl}/api/version`, { method: "GET" });
|
|
20424
|
+
} catch (e) {
|
|
20425
|
+
return { kind: "unreachable", detail: e.message };
|
|
20426
|
+
}
|
|
20427
|
+
if (res.status === 401 || res.status === 403) return { kind: "auth-gated", status: res.status };
|
|
20428
|
+
if (!res.ok) return { kind: "http-error", status: res.status };
|
|
20429
|
+
const body = await res.json().catch(() => void 0);
|
|
20430
|
+
const version = versionFromEnvelope(body);
|
|
20431
|
+
return version === void 0 ? { kind: "no-version" } : { kind: "version", version };
|
|
20432
|
+
}
|
|
20433
|
+
|
|
20320
20434
|
// src/commands/platform/status.ts
|
|
20321
20435
|
var PlatformStatusCommand = class extends M8tCommand {
|
|
20322
20436
|
static paths = [["platform", "status"]];
|
|
@@ -20440,18 +20554,7 @@ var PlatformStatusCommand = class extends M8tCommand {
|
|
|
20440
20554
|
} catch {
|
|
20441
20555
|
liveImage = void 0;
|
|
20442
20556
|
}
|
|
20443
|
-
|
|
20444
|
-
try {
|
|
20445
|
-
const res = await fetch(`${gatewayUrl}/api/version`, { method: "GET" });
|
|
20446
|
-
if (res.ok) {
|
|
20447
|
-
const body = await res.json().catch(() => ({}));
|
|
20448
|
-
apiVersion = body.version ?? "unknown";
|
|
20449
|
-
} else if (res.status === 401 || res.status === 403) {
|
|
20450
|
-
apiVersion = "unknown (auth-gated)";
|
|
20451
|
-
}
|
|
20452
|
-
} catch {
|
|
20453
|
-
apiVersion = "unknown";
|
|
20454
|
-
}
|
|
20557
|
+
const apiVersion = renderVersionRead(await readGatewayVersion(gatewayUrl));
|
|
20455
20558
|
return {
|
|
20456
20559
|
gateway: compareGatewayBinding({
|
|
20457
20560
|
stampTag: stampGatewayTag ?? "unknown",
|
|
@@ -20472,7 +20575,7 @@ import { confirm as confirm5 } from "@inquirer/prompts";
|
|
|
20472
20575
|
import { DefaultAzureCredential as DefaultAzureCredential17 } from "@azure/identity";
|
|
20473
20576
|
|
|
20474
20577
|
// src/lib/platform-converge-cli.ts
|
|
20475
|
-
import * as
|
|
20578
|
+
import * as path26 from "path";
|
|
20476
20579
|
|
|
20477
20580
|
// src/lib/platform-infra-params.ts
|
|
20478
20581
|
import { TableClient as TableClient3 } from "@azure/data-tables";
|
|
@@ -20557,17 +20660,17 @@ init_errors();
|
|
|
20557
20660
|
|
|
20558
20661
|
// src/lib/seed-refresh-driver.ts
|
|
20559
20662
|
init_esm2();
|
|
20560
|
-
import * as
|
|
20663
|
+
import * as path25 from "path";
|
|
20561
20664
|
|
|
20562
20665
|
// src/lib/seed-refresh.ts
|
|
20563
20666
|
init_errors();
|
|
20564
20667
|
import * as fs24 from "fs";
|
|
20565
|
-
import * as
|
|
20668
|
+
import * as path24 from "path";
|
|
20566
20669
|
|
|
20567
20670
|
// src/lib/seed-merge.ts
|
|
20568
20671
|
import * as fs23 from "fs";
|
|
20569
20672
|
import * as os10 from "os";
|
|
20570
|
-
import * as
|
|
20673
|
+
import * as path23 from "path";
|
|
20571
20674
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
20572
20675
|
function isProbablyText(s) {
|
|
20573
20676
|
return !s.includes("\0");
|
|
@@ -20577,11 +20680,11 @@ function mergeThreeWay(ours, base, theirs) {
|
|
|
20577
20680
|
return { ok: false, merged: "" };
|
|
20578
20681
|
}
|
|
20579
20682
|
const lf = (s) => s.replace(/\r\n/g, "\n");
|
|
20580
|
-
const dir = fs23.mkdtempSync(
|
|
20683
|
+
const dir = fs23.mkdtempSync(path23.join(os10.tmpdir(), "seed-merge-"));
|
|
20581
20684
|
try {
|
|
20582
|
-
const o =
|
|
20583
|
-
const b =
|
|
20584
|
-
const t =
|
|
20685
|
+
const o = path23.join(dir, "ours");
|
|
20686
|
+
const b = path23.join(dir, "base");
|
|
20687
|
+
const t = path23.join(dir, "theirs");
|
|
20585
20688
|
fs23.writeFileSync(o, lf(ours));
|
|
20586
20689
|
fs23.writeFileSync(b, lf(base));
|
|
20587
20690
|
fs23.writeFileSync(t, lf(theirs));
|
|
@@ -20601,25 +20704,25 @@ function mergeThreeWay(ours, base, theirs) {
|
|
|
20601
20704
|
fs23.rmSync(dir, { recursive: true, force: true });
|
|
20602
20705
|
}
|
|
20603
20706
|
}
|
|
20604
|
-
var skip = (
|
|
20707
|
+
var skip = (path43, skipReason) => ({ path: path43, kind: "skip", skipReason });
|
|
20605
20708
|
function classifyCandidate(c) {
|
|
20606
|
-
const { path:
|
|
20607
|
-
if (theirs === base) return { path:
|
|
20709
|
+
const { path: path43, base, ours, theirs } = c;
|
|
20710
|
+
if (theirs === base) return { path: path43, kind: "noop" };
|
|
20608
20711
|
if (base === null) {
|
|
20609
|
-
if (theirs === null) return { path:
|
|
20610
|
-
if (ours === null) return { path:
|
|
20611
|
-
if (ours === theirs) return { path:
|
|
20612
|
-
return skip(
|
|
20712
|
+
if (theirs === null) return { path: path43, kind: "noop" };
|
|
20713
|
+
if (ours === null) return { path: path43, kind: "add", content: theirs };
|
|
20714
|
+
if (ours === theirs) return { path: path43, kind: "noop" };
|
|
20715
|
+
return skip(path43, "you already have a file at this path");
|
|
20613
20716
|
}
|
|
20614
20717
|
if (ours === null) {
|
|
20615
|
-
return theirs === null ? { path:
|
|
20718
|
+
return theirs === null ? { path: path43, kind: "noop" } : skip(path43, "you removed this file; upstream changed it");
|
|
20616
20719
|
}
|
|
20617
20720
|
if (theirs === null) {
|
|
20618
|
-
return ours === base ? { path:
|
|
20721
|
+
return ours === base ? { path: path43, kind: "delete" } : skip(path43, "you edited this file; upstream removed it");
|
|
20619
20722
|
}
|
|
20620
|
-
if (ours === base) return { path:
|
|
20723
|
+
if (ours === base) return { path: path43, kind: "update", content: theirs };
|
|
20621
20724
|
const m = mergeThreeWay(ours, base, theirs);
|
|
20622
|
-
return m.ok ? { path:
|
|
20725
|
+
return m.ok ? { path: path43, kind: "update", content: m.merged } : skip(path43, "your edits conflict with the update");
|
|
20623
20726
|
}
|
|
20624
20727
|
|
|
20625
20728
|
// src/lib/seed-pr-body.ts
|
|
@@ -20654,7 +20757,7 @@ function composeSeedPrBody(s) {
|
|
|
20654
20757
|
// src/lib/seed-refresh.ts
|
|
20655
20758
|
function readIf(dir, rel) {
|
|
20656
20759
|
if (!dir) return null;
|
|
20657
|
-
const abs =
|
|
20760
|
+
const abs = path24.join(dir, rel);
|
|
20658
20761
|
return fs24.existsSync(abs) ? fs24.readFileSync(abs, "utf8") : null;
|
|
20659
20762
|
}
|
|
20660
20763
|
async function assembleCandidates(args) {
|
|
@@ -20787,7 +20890,7 @@ function dedupeBrainRepos(agents) {
|
|
|
20787
20890
|
function seedContentDir(contentRoot, manifest, seedName) {
|
|
20788
20891
|
const items = manifest.components.brainSeeds.items;
|
|
20789
20892
|
if (!Object.hasOwn(items, seedName)) return null;
|
|
20790
|
-
return
|
|
20893
|
+
return path25.join(contentRoot, items[seedName].path);
|
|
20791
20894
|
}
|
|
20792
20895
|
function bindRepoApi(token, repo) {
|
|
20793
20896
|
return {
|
|
@@ -20804,7 +20907,7 @@ function bindRepoApi(token, repo) {
|
|
|
20804
20907
|
openPr: (head, base, title, body) => openPullRequestViaApp({ token, repo, base, head, title, body }),
|
|
20805
20908
|
updatePr: (n, title, body) => updatePullRequestViaApp({ token, repo, number: n, title, body }),
|
|
20806
20909
|
closePr: (n, comment) => closePullRequestViaApp({ token, repo, number: n, comment }),
|
|
20807
|
-
readFileAtRef: (
|
|
20910
|
+
readFileAtRef: (path43, ref) => readRepoFileViaApp({ token, repo, path: path43, ref })
|
|
20808
20911
|
};
|
|
20809
20912
|
}
|
|
20810
20913
|
async function runSeedRefresh(args) {
|
|
@@ -20917,7 +21020,7 @@ async function buildConvergeDeps(args) {
|
|
|
20917
21020
|
const persona = a.metadata.persona;
|
|
20918
21021
|
if (persona) discovered[persona] = a.name;
|
|
20919
21022
|
}
|
|
20920
|
-
const loaderPath =
|
|
21023
|
+
const loaderPath = path26.join(args.contentDir, "targets/foundry/brain-loader.md");
|
|
20921
21024
|
return {
|
|
20922
21025
|
async applyPersona(a, ctx) {
|
|
20923
21026
|
const personaName = a.personaName;
|
|
@@ -20933,7 +21036,7 @@ async function buildConvergeDeps(args) {
|
|
|
20933
21036
|
return applyPersona(a, ctx, {
|
|
20934
21037
|
agentName,
|
|
20935
21038
|
project: args.project,
|
|
20936
|
-
personaDir:
|
|
21039
|
+
personaDir: path26.join(ctx.contentDir, personaItem.path),
|
|
20937
21040
|
loaderPath
|
|
20938
21041
|
});
|
|
20939
21042
|
},
|
|
@@ -21007,18 +21110,23 @@ async function buildConvergeDeps(args) {
|
|
|
21007
21110
|
await awaitAgentQueryable({ credential: args.credential, projectEndpoint: args.project.endpoint, agentName, onProgress: args.onProgress });
|
|
21008
21111
|
}
|
|
21009
21112
|
if (args.gatewayUrl) {
|
|
21010
|
-
|
|
21011
|
-
|
|
21012
|
-
|
|
21013
|
-
|
|
21014
|
-
|
|
21015
|
-
|
|
21016
|
-
args.onProgress?.(
|
|
21017
|
-
|
|
21018
|
-
|
|
21019
|
-
|
|
21020
|
-
|
|
21021
|
-
|
|
21113
|
+
const read = await readGatewayVersion(args.gatewayUrl);
|
|
21114
|
+
switch (read.kind) {
|
|
21115
|
+
case "version":
|
|
21116
|
+
args.onProgress?.(`gateway reachable (version: ${read.version}).`);
|
|
21117
|
+
break;
|
|
21118
|
+
case "no-version":
|
|
21119
|
+
args.onProgress?.("gateway reachable (version: unknown).");
|
|
21120
|
+
break;
|
|
21121
|
+
case "auth-gated":
|
|
21122
|
+
args.onProgress?.(`gateway reachable (auth-gated, HTTP ${read.status.toString()}).`);
|
|
21123
|
+
break;
|
|
21124
|
+
case "http-error":
|
|
21125
|
+
warn(`gateway health probe returned HTTP ${read.status.toString()} \u2014 not treated as fatal.`);
|
|
21126
|
+
break;
|
|
21127
|
+
case "unreachable":
|
|
21128
|
+
warn(`gateway health probe failed: ${read.detail} \u2014 not treated as fatal.`);
|
|
21129
|
+
break;
|
|
21022
21130
|
}
|
|
21023
21131
|
}
|
|
21024
21132
|
},
|
|
@@ -21363,14 +21471,14 @@ async function patchApplyRequest(client, mutate) {
|
|
|
21363
21471
|
|
|
21364
21472
|
// src/lib/platform-self-update.ts
|
|
21365
21473
|
import * as fs25 from "fs";
|
|
21366
|
-
import * as
|
|
21474
|
+
import * as path27 from "path";
|
|
21367
21475
|
function toVTag2(v) {
|
|
21368
21476
|
return v.startsWith("v") ? v : `v${v}`;
|
|
21369
21477
|
}
|
|
21370
21478
|
function readBakedReleaseVersion(repoRoot) {
|
|
21371
21479
|
if (!repoRoot) return null;
|
|
21372
21480
|
try {
|
|
21373
|
-
const raw = fs25.readFileSync(
|
|
21481
|
+
const raw = fs25.readFileSync(path27.join(repoRoot, "installer", "version.json"), "utf8");
|
|
21374
21482
|
const v = JSON.parse(raw).version;
|
|
21375
21483
|
return typeof v === "string" && v.length > 0 ? v : null;
|
|
21376
21484
|
} catch {
|
|
@@ -21515,17 +21623,20 @@ async function reconvergeToPrevious(args, previousVersion) {
|
|
|
21515
21623
|
await applyPlan(rollbackPlan, args.deps, rollbackCtx);
|
|
21516
21624
|
}
|
|
21517
21625
|
async function defaultGatewayProbe(gatewayUrl, expected) {
|
|
21518
|
-
|
|
21519
|
-
|
|
21520
|
-
|
|
21521
|
-
|
|
21522
|
-
|
|
21523
|
-
|
|
21524
|
-
|
|
21525
|
-
|
|
21526
|
-
|
|
21527
|
-
|
|
21528
|
-
|
|
21626
|
+
const read = await readGatewayVersion(gatewayUrl);
|
|
21627
|
+
switch (read.kind) {
|
|
21628
|
+
case "unreachable":
|
|
21629
|
+
return { ok: false, detail: `gateway unreachable: ${read.detail}` };
|
|
21630
|
+
case "http-error":
|
|
21631
|
+
return { ok: false, detail: `gateway /api/version returned HTTP ${read.status.toString()}` };
|
|
21632
|
+
case "auth-gated":
|
|
21633
|
+
case "no-version":
|
|
21634
|
+
return { ok: true };
|
|
21635
|
+
case "version":
|
|
21636
|
+
return versionMatches(read.version, expected) ? { ok: true } : {
|
|
21637
|
+
ok: true,
|
|
21638
|
+
detail: `gateway reports version '${read.version}', target '${expected}' \u2014 recorded, not gated (see defaultGatewayProbe)`
|
|
21639
|
+
};
|
|
21529
21640
|
}
|
|
21530
21641
|
}
|
|
21531
21642
|
function versionMatches(running, expected) {
|
|
@@ -21787,7 +21898,7 @@ function targetManifestSource(ctx, target) {
|
|
|
21787
21898
|
}
|
|
21788
21899
|
|
|
21789
21900
|
// src/commands/platform/seed-stamp.ts
|
|
21790
|
-
import { readFileSync as
|
|
21901
|
+
import { readFileSync as readFileSync18 } from "fs";
|
|
21791
21902
|
import { Command as Command35, Option as Option32 } from "clipanion";
|
|
21792
21903
|
import { DefaultAzureCredential as DefaultAzureCredential18, ManagedIdentityCredential as ManagedIdentityCredential2 } from "@azure/identity";
|
|
21793
21904
|
init_errors();
|
|
@@ -21874,7 +21985,7 @@ function buildSeedStamp(d, cliVersion, nowIso) {
|
|
|
21874
21985
|
|
|
21875
21986
|
// src/commands/platform/seed-stamp.ts
|
|
21876
21987
|
async function seedStamp2(args) {
|
|
21877
|
-
const readFileImpl = args.readFileImpl ?? ((p) =>
|
|
21988
|
+
const readFileImpl = args.readFileImpl ?? ((p) => readFileSync18(p, "utf8"));
|
|
21878
21989
|
const readStampImpl = args.readStampImpl ?? readStamp;
|
|
21879
21990
|
const writeStampImpl = args.writeStampImpl ?? ((stamp2, o) => writeStamp({ ...o, stamp: stamp2 }));
|
|
21880
21991
|
const discoverImpl = args.discoverImpl ?? discoverStampStorage;
|
|
@@ -22752,7 +22863,7 @@ async function patchRedirectUris(appObjectId, fqdn) {
|
|
|
22752
22863
|
init_errors();
|
|
22753
22864
|
|
|
22754
22865
|
// src/lib/whatif.ts
|
|
22755
|
-
import * as
|
|
22866
|
+
import * as path28 from "path";
|
|
22756
22867
|
|
|
22757
22868
|
// src/lib/identifier-patterns.ts
|
|
22758
22869
|
var IDENTIFIER_PATTERNS = [
|
|
@@ -22808,7 +22919,7 @@ function deriveResourceType(resourceId) {
|
|
|
22808
22919
|
return parts.join("/");
|
|
22809
22920
|
}
|
|
22810
22921
|
async function runWhatIf(opts) {
|
|
22811
|
-
const bicepPath =
|
|
22922
|
+
const bicepPath = path28.join(opts.repoRoot, "deploy", "main.bicep");
|
|
22812
22923
|
const out = await runAz([
|
|
22813
22924
|
"deployment",
|
|
22814
22925
|
"group",
|
|
@@ -22906,9 +23017,9 @@ function flattenDelta(delta, prefix = "") {
|
|
|
22906
23017
|
const out = [];
|
|
22907
23018
|
for (const d of delta) {
|
|
22908
23019
|
const segment = /^[0-9]+$/.test(d.path) ? `[${d.path}]` : prefix ? `.${d.path}` : d.path;
|
|
22909
|
-
const
|
|
22910
|
-
if (d.children && d.children.length > 0) out.push(...flattenDelta(d.children,
|
|
22911
|
-
else out.push({ ...d, path:
|
|
23020
|
+
const path43 = prefix ? `${prefix}${segment}` : d.path;
|
|
23021
|
+
if (d.children && d.children.length > 0) out.push(...flattenDelta(d.children, path43));
|
|
23022
|
+
else out.push({ ...d, path: path43 });
|
|
22912
23023
|
}
|
|
22913
23024
|
return out;
|
|
22914
23025
|
}
|
|
@@ -23271,7 +23382,7 @@ var EvalSkillCommand = class extends M8tCommand {
|
|
|
23271
23382
|
|
|
23272
23383
|
// src/commands/eval/exam.ts
|
|
23273
23384
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
23274
|
-
import { writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, readFileSync as
|
|
23385
|
+
import { writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync19, existsSync as existsSync16, readdirSync as readdirSync2 } from "fs";
|
|
23275
23386
|
import { join as join27 } from "path";
|
|
23276
23387
|
import { Command as Command42, Option as Option39 } from "clipanion";
|
|
23277
23388
|
init_errors();
|
|
@@ -23454,10 +23565,10 @@ function resolveRefereeHome(refereeHomeOut, env) {
|
|
|
23454
23565
|
return null;
|
|
23455
23566
|
}
|
|
23456
23567
|
function resolveTaskSetDir(base, worker, version) {
|
|
23457
|
-
if (
|
|
23568
|
+
if (existsSync16(join27(base, version))) return version;
|
|
23458
23569
|
const prefixed = `${worker}-${version}`;
|
|
23459
|
-
if (
|
|
23460
|
-
if (version === "latest" &&
|
|
23570
|
+
if (existsSync16(join27(base, prefixed))) return prefixed;
|
|
23571
|
+
if (version === "latest" && existsSync16(base)) {
|
|
23461
23572
|
const dirs = readdirSync2(base, { withFileTypes: true }).filter((d) => d.isDirectory() && d.name.startsWith(`${worker}-`)).map((d) => d.name).sort();
|
|
23462
23573
|
if (dirs.length > 0) return dirs[dirs.length - 1];
|
|
23463
23574
|
}
|
|
@@ -23476,7 +23587,7 @@ function readSealedTaskIds(taskSetVersion, refereeHomeOut, env = process.env) {
|
|
|
23476
23587
|
const manifestPath = join27(home, "tasksets", worker, versionDir, "manifest.yaml");
|
|
23477
23588
|
let text;
|
|
23478
23589
|
try {
|
|
23479
|
-
text =
|
|
23590
|
+
text = readFileSync19(manifestPath, "utf-8");
|
|
23480
23591
|
} catch (e) {
|
|
23481
23592
|
throw new LocalCliError({
|
|
23482
23593
|
code: "EXAM_REDACTION_UNSAFE",
|
|
@@ -23864,7 +23975,7 @@ import { Command as Command46, Option as Option43 } from "clipanion";
|
|
|
23864
23975
|
import { DefaultAzureCredential as DefaultAzureCredential22 } from "@azure/identity";
|
|
23865
23976
|
import * as fs26 from "fs";
|
|
23866
23977
|
import * as os11 from "os";
|
|
23867
|
-
import * as
|
|
23978
|
+
import * as path29 from "path";
|
|
23868
23979
|
|
|
23869
23980
|
// src/lib/doctor-checks.ts
|
|
23870
23981
|
function checkAzSignedIn(az) {
|
|
@@ -24343,7 +24454,7 @@ async function resolveAccountLocation(accountId) {
|
|
|
24343
24454
|
}
|
|
24344
24455
|
}
|
|
24345
24456
|
function probeRepoRoot() {
|
|
24346
|
-
const marker =
|
|
24457
|
+
const marker = path29.join(os11.homedir(), ".m8t", "repo-root");
|
|
24347
24458
|
if (!fs26.existsSync(marker)) {
|
|
24348
24459
|
return { markerExists: false, path: null, isDir: false, isGitCheckout: false };
|
|
24349
24460
|
}
|
|
@@ -24360,13 +24471,13 @@ function probeRepoRoot() {
|
|
|
24360
24471
|
} catch {
|
|
24361
24472
|
isDir = false;
|
|
24362
24473
|
}
|
|
24363
|
-
const isGitCheckout = isDir && fs26.existsSync(
|
|
24474
|
+
const isGitCheckout = isDir && fs26.existsSync(path29.join(repoPath, ".git"));
|
|
24364
24475
|
return { markerExists: true, path: repoPath, isDir, isGitCheckout };
|
|
24365
24476
|
}
|
|
24366
24477
|
function probeLegacyStateDir() {
|
|
24367
24478
|
return {
|
|
24368
|
-
legacyExists: fs26.existsSync(
|
|
24369
|
-
currentExists: fs26.existsSync(
|
|
24479
|
+
legacyExists: fs26.existsSync(path29.join(os11.homedir(), ".m8t-stack")),
|
|
24480
|
+
currentExists: fs26.existsSync(path29.join(os11.homedir(), ".m8t"))
|
|
24370
24481
|
};
|
|
24371
24482
|
}
|
|
24372
24483
|
var DoctorCommand = class extends M8tCommand {
|
|
@@ -25297,14 +25408,14 @@ import { Command as Command48, Option as Option45 } from "clipanion";
|
|
|
25297
25408
|
|
|
25298
25409
|
// src/lib/profiles.ts
|
|
25299
25410
|
import * as fs27 from "fs/promises";
|
|
25300
|
-
import * as
|
|
25411
|
+
import * as path30 from "path";
|
|
25301
25412
|
import { parse as parseYaml11, stringify as stringifyYaml4 } from "yaml";
|
|
25302
25413
|
function profilesDir() {
|
|
25303
25414
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
25304
|
-
return
|
|
25415
|
+
return path30.join(home, ".m8t", "profiles");
|
|
25305
25416
|
}
|
|
25306
25417
|
function getProfilePath(name) {
|
|
25307
|
-
return
|
|
25418
|
+
return path30.join(profilesDir(), `${path30.basename(name)}.yaml`);
|
|
25308
25419
|
}
|
|
25309
25420
|
function slugifyTenant(domainOrId) {
|
|
25310
25421
|
const base = domainOrId.split(".")[0].toLowerCase();
|
|
@@ -26580,7 +26691,7 @@ function buildAdvancePlan(worker, cursor, physicalPks, consumedRowsByPk, failedT
|
|
|
26580
26691
|
// ../../packages/brain/engine/dist/esm/dream/writer.js
|
|
26581
26692
|
var API2 = "https://api.github.com";
|
|
26582
26693
|
var WRITER_ALLOWED_PREFIX = /^(memory|inbox|quarantine|artifacts)\//;
|
|
26583
|
-
var isAllowedWritePath = (
|
|
26694
|
+
var isAllowedWritePath = (path43, allowedPrefix) => allowedPrefix.test(path43) && !path43.split("/").includes("..");
|
|
26584
26695
|
var unquote = (s) => s.trim().replace(/^["']|["']$/g, "");
|
|
26585
26696
|
function parseFrontmatter(content) {
|
|
26586
26697
|
const m = /^---\r?\n([\s\S]*?)\r?\n---/.exec(content);
|
|
@@ -26623,8 +26734,8 @@ function makeGitDataWriter(args) {
|
|
|
26623
26734
|
if (args.allowedPathPrefix && !args.allowedPathPrefix.source.startsWith("^")) {
|
|
26624
26735
|
throw new Error(`makeGitDataWriter: allowedPathPrefix must be anchored with "^" (got /${args.allowedPathPrefix.source}/) \u2014 an unanchored regex would widen the B1 write-path allowlist`);
|
|
26625
26736
|
}
|
|
26626
|
-
async function gh(token, method,
|
|
26627
|
-
const res = await doFetch(`${API2}/repos/${repoPath}${
|
|
26737
|
+
async function gh(token, method, path43, body) {
|
|
26738
|
+
const res = await doFetch(`${API2}/repos/${repoPath}${path43}`, {
|
|
26628
26739
|
method,
|
|
26629
26740
|
headers: {
|
|
26630
26741
|
Authorization: `Bearer ${token}`,
|
|
@@ -26637,8 +26748,8 @@ function makeGitDataWriter(args) {
|
|
|
26637
26748
|
const text = await res.text();
|
|
26638
26749
|
return { status: res.status, ok: res.ok, json: text ? JSON.parse(text) : {} };
|
|
26639
26750
|
}
|
|
26640
|
-
async function readFileWith(token,
|
|
26641
|
-
const encodedPath =
|
|
26751
|
+
async function readFileWith(token, path43) {
|
|
26752
|
+
const encodedPath = path43.split("/").map(encodeURIComponent).join("/");
|
|
26642
26753
|
const r = await gh(token, "GET", `/contents/${encodedPath}?ref=${args.branch}`);
|
|
26643
26754
|
if (r.status === 404)
|
|
26644
26755
|
return null;
|
|
@@ -26654,9 +26765,9 @@ function makeGitDataWriter(args) {
|
|
|
26654
26765
|
throw new Error(`fetchTip: HTTP ${String(r.status)}`);
|
|
26655
26766
|
return r.json.object.sha;
|
|
26656
26767
|
},
|
|
26657
|
-
async readFile(
|
|
26768
|
+
async readFile(path43) {
|
|
26658
26769
|
const token = await args.mintToken();
|
|
26659
|
-
return readFileWith(token,
|
|
26770
|
+
return readFileWith(token, path43);
|
|
26660
26771
|
},
|
|
26661
26772
|
async listMemory() {
|
|
26662
26773
|
const token = await args.mintToken();
|
|
@@ -26665,9 +26776,9 @@ function makeGitDataWriter(args) {
|
|
|
26665
26776
|
return [];
|
|
26666
26777
|
const paths = r.json.tree.filter((e) => e.type === "blob" && e.path.startsWith("memory/") && e.path.endsWith(".md")).map((e) => e.path);
|
|
26667
26778
|
const out = [];
|
|
26668
|
-
for (const
|
|
26669
|
-
const content = await readFileWith(token,
|
|
26670
|
-
out.push({ path:
|
|
26779
|
+
for (const path43 of paths) {
|
|
26780
|
+
const content = await readFileWith(token, path43);
|
|
26781
|
+
out.push({ path: path43, frontmatter: content ? parseFrontmatter(content) : {} });
|
|
26671
26782
|
}
|
|
26672
26783
|
return out;
|
|
26673
26784
|
},
|
|
@@ -27106,7 +27217,7 @@ async function loadMemoryContext(brain) {
|
|
|
27106
27217
|
return {
|
|
27107
27218
|
files,
|
|
27108
27219
|
indexEntries,
|
|
27109
|
-
originOf: (
|
|
27220
|
+
originOf: (path43) => originByPath.get(path43) ?? "worker"
|
|
27110
27221
|
};
|
|
27111
27222
|
}
|
|
27112
27223
|
|
|
@@ -27127,14 +27238,14 @@ function checkEvidenceMembership(delta, harvested) {
|
|
|
27127
27238
|
}
|
|
27128
27239
|
var BatchAbort = class extends Error {
|
|
27129
27240
|
path;
|
|
27130
|
-
constructor(
|
|
27241
|
+
constructor(path43, message) {
|
|
27131
27242
|
super(message);
|
|
27132
|
-
this.path =
|
|
27243
|
+
this.path = path43;
|
|
27133
27244
|
this.name = "BatchAbort";
|
|
27134
27245
|
}
|
|
27135
27246
|
};
|
|
27136
|
-
var isIndexFile = (
|
|
27137
|
-
var isMemoryIndex = (
|
|
27247
|
+
var isIndexFile = (path43) => /(^|\/)[^/]*_index\.md$/.test(path43);
|
|
27248
|
+
var isMemoryIndex = (path43) => path43 === "memory/MEMORY.md";
|
|
27138
27249
|
function targetPath(delta) {
|
|
27139
27250
|
switch (delta.verb) {
|
|
27140
27251
|
case "new":
|
|
@@ -27151,29 +27262,29 @@ function targetPath(delta) {
|
|
|
27151
27262
|
}
|
|
27152
27263
|
async function checkOriginTier(delta, lookup) {
|
|
27153
27264
|
const evidence = evidenceOf(delta) ?? [];
|
|
27154
|
-
const
|
|
27155
|
-
if (
|
|
27265
|
+
const path43 = targetPath(delta);
|
|
27266
|
+
if (path43 === null)
|
|
27156
27267
|
return { ok: true };
|
|
27157
|
-
if (isIndexFile(
|
|
27158
|
-
return { ok: false, flagged: { kind: "flagged", path:
|
|
27268
|
+
if (isIndexFile(path43) && !isMemoryIndex(path43)) {
|
|
27269
|
+
return { ok: false, flagged: { kind: "flagged", path: path43, tension: `refused: ${path43} is an index file (only memory/MEMORY.md is editable)`, evidence } };
|
|
27159
27270
|
}
|
|
27160
|
-
const target = await lookup(
|
|
27161
|
-
const isStructural =
|
|
27271
|
+
const target = await lookup(path43);
|
|
27272
|
+
const isStructural = path43.startsWith("references/");
|
|
27162
27273
|
const origin = target?.frontmatter.origin ?? (isStructural ? "operator" : "worker");
|
|
27163
27274
|
const editable = origin === "worker" || origin === "dream";
|
|
27164
27275
|
if (editable)
|
|
27165
27276
|
return { ok: true };
|
|
27166
27277
|
const removesOperatorTarget = delta.verb === "retract" || delta.verb === "supersede" && delta.oldPath !== delta.newPath;
|
|
27167
27278
|
if (removesOperatorTarget) {
|
|
27168
|
-
throw new BatchAbort(
|
|
27279
|
+
throw new BatchAbort(path43, `supersede/retract OLD target ${path43} is origin: ${origin} \u2014 aborting batch (never half-apply)`);
|
|
27169
27280
|
}
|
|
27170
|
-
return { ok: false, flagged: { kind: "flagged", path:
|
|
27281
|
+
return { ok: false, flagged: { kind: "flagged", path: path43, tension: `operator-origin (${origin}); flag-only`, evidence } };
|
|
27171
27282
|
}
|
|
27172
27283
|
var ALLOWED_MEMORY = /^memory\/.+\.md$/;
|
|
27173
27284
|
var ALLOWED_INBOX = /^inbox\//;
|
|
27174
27285
|
var ALLOWED_QUARANTINE = /^quarantine\//;
|
|
27175
27286
|
var ALLOWED_FLAG = /^memory\//;
|
|
27176
|
-
var hasTraversal = (
|
|
27287
|
+
var hasTraversal = (path43) => path43.split("/").includes("..");
|
|
27177
27288
|
function checkPathAllowed(delta) {
|
|
27178
27289
|
const evidence = evidenceOf(delta) ?? [];
|
|
27179
27290
|
const reject = (detail) => ({ ok: false, rejected: { kind: "rejected", detail, evidence } });
|
|
@@ -27280,7 +27391,7 @@ ${inject}
|
|
|
27280
27391
|
---
|
|
27281
27392
|
` + body.slice(m[0].length);
|
|
27282
27393
|
}
|
|
27283
|
-
var indexLine = (
|
|
27394
|
+
var indexLine = (path43, title, date, tags) => `- \`${path43}\` \u2014 **${title}**: ${title}. (${date} \xB7 ${tags.join(", ")})`;
|
|
27284
27395
|
function splitIndex(index) {
|
|
27285
27396
|
const all = index.split("\n");
|
|
27286
27397
|
const firstLineIdx = all.findIndex((l) => l.startsWith("- `memory/"));
|
|
@@ -27453,16 +27564,16 @@ function defaultDreamSeams(opts = {}) {
|
|
|
27453
27564
|
const mem = await memory(deps.brain);
|
|
27454
27565
|
const harvested = harvestedIds(input);
|
|
27455
27566
|
const ctx = { readFile: (p) => deps.brain.readFile(p), at: deps.clock() };
|
|
27456
|
-
const lookup = (
|
|
27567
|
+
const lookup = (path43) => Promise.resolve(mem.files.find((f) => f.path === path43) ?? null);
|
|
27457
27568
|
const digest = [...pendingRejected];
|
|
27458
27569
|
let changes = [];
|
|
27459
27570
|
let indexEdit;
|
|
27460
27571
|
try {
|
|
27461
27572
|
for (const raw of deltas) {
|
|
27462
27573
|
const delta = forcePolicyQuarantine(raw);
|
|
27463
|
-
const
|
|
27464
|
-
if (!
|
|
27465
|
-
digest.push(
|
|
27574
|
+
const path43 = checkPathAllowed(delta);
|
|
27575
|
+
if (!path43.ok) {
|
|
27576
|
+
digest.push(path43.rejected);
|
|
27466
27577
|
continue;
|
|
27467
27578
|
}
|
|
27468
27579
|
const ev = checkEvidenceMembership(delta, harvested);
|
|
@@ -28590,9 +28701,9 @@ var DISCLOSURE_TIER1 = "Operational data. To support your installation, m8t rece
|
|
|
28590
28701
|
|
|
28591
28702
|
// ../../packages/telemetry-contract/src/endpoints.ts
|
|
28592
28703
|
var INGEST_BASE_URL = (process.env.M8T_INGEST_BASE_URL ?? "").trim() || "https://m8t-admin.wonderfuldesert-721e332f.eastus2.azurecontainerapps.io";
|
|
28593
|
-
function ingestUrl(
|
|
28704
|
+
function ingestUrl(path43) {
|
|
28594
28705
|
const base = INGEST_BASE_URL.replace(/\/+$/, "");
|
|
28595
|
-
return `${base}${
|
|
28706
|
+
return `${base}${path43.startsWith("/") ? path43 : `/${path43}`}`;
|
|
28596
28707
|
}
|
|
28597
28708
|
|
|
28598
28709
|
// src/commands/bootstrap/preflight.ts
|
|
@@ -28726,7 +28837,7 @@ ${colors.error(" " + why)}
|
|
|
28726
28837
|
// src/commands/bootstrap/launch.ts
|
|
28727
28838
|
import * as fs30 from "fs";
|
|
28728
28839
|
import * as os14 from "os";
|
|
28729
|
-
import * as
|
|
28840
|
+
import * as path33 from "path";
|
|
28730
28841
|
import { Command as Command54, Option as Option51 } from "clipanion";
|
|
28731
28842
|
init_errors();
|
|
28732
28843
|
|
|
@@ -28885,7 +28996,7 @@ async function kickInstaller(s) {
|
|
|
28885
28996
|
import { createHash as createHash4, randomUUID as randomUUID2 } from "crypto";
|
|
28886
28997
|
import * as fs28 from "fs/promises";
|
|
28887
28998
|
import * as os12 from "os";
|
|
28888
|
-
import * as
|
|
28999
|
+
import * as path31 from "path";
|
|
28889
29000
|
init_errors();
|
|
28890
29001
|
var STATUS_CONTAINER = "status";
|
|
28891
29002
|
var STATUS_BLOB = "status.json";
|
|
@@ -28924,7 +29035,7 @@ async function readStatusBlob(opts) {
|
|
|
28924
29035
|
cause: e
|
|
28925
29036
|
});
|
|
28926
29037
|
}
|
|
28927
|
-
const tmpFile =
|
|
29038
|
+
const tmpFile = path31.join(os12.tmpdir(), `m8t-status-${randomUUID2()}.json`);
|
|
28928
29039
|
try {
|
|
28929
29040
|
await runAz([
|
|
28930
29041
|
"storage",
|
|
@@ -28960,12 +29071,12 @@ async function readStatusBlob(opts) {
|
|
|
28960
29071
|
// src/lib/bootstrap-state.ts
|
|
28961
29072
|
import * as fs29 from "fs/promises";
|
|
28962
29073
|
import * as os13 from "os";
|
|
28963
|
-
import * as
|
|
29074
|
+
import * as path32 from "path";
|
|
28964
29075
|
function stateDir(home) {
|
|
28965
|
-
return
|
|
29076
|
+
return path32.join(home, ".m8t");
|
|
28966
29077
|
}
|
|
28967
29078
|
function statePath(home) {
|
|
28968
|
-
return
|
|
29079
|
+
return path32.join(stateDir(home), "bootstrap.json");
|
|
28969
29080
|
}
|
|
28970
29081
|
async function readBootstrapState(home = os13.homedir()) {
|
|
28971
29082
|
try {
|
|
@@ -29166,7 +29277,7 @@ var BootstrapLaunchCommand = class extends M8tCommand {
|
|
|
29166
29277
|
`);
|
|
29167
29278
|
return 0;
|
|
29168
29279
|
}
|
|
29169
|
-
const credsPath = typeof this.githubAppCreds === "string" ? this.githubAppCreds :
|
|
29280
|
+
const credsPath = typeof this.githubAppCreds === "string" ? this.githubAppCreds : path33.join(os14.homedir(), ".m8t", "github-app.json");
|
|
29170
29281
|
const skipBrains = this.noBrains === true;
|
|
29171
29282
|
const requestedOrg = typeof this.org === "string" ? this.org : void 0;
|
|
29172
29283
|
let githubApp;
|
|
@@ -29316,13 +29427,13 @@ async function getAciState(opts) {
|
|
|
29316
29427
|
// src/lib/bootstrap-finalize.ts
|
|
29317
29428
|
import * as fs34 from "fs/promises";
|
|
29318
29429
|
import * as os18 from "os";
|
|
29319
|
-
import * as
|
|
29430
|
+
import * as path39 from "path";
|
|
29320
29431
|
|
|
29321
29432
|
// src/lib/company-profile-seed.ts
|
|
29322
29433
|
import { spawn as spawn6 } from "child_process";
|
|
29323
|
-
import { closeSync, openSync, readFileSync as
|
|
29434
|
+
import { closeSync, openSync, readFileSync as readFileSync22 } from "fs";
|
|
29324
29435
|
import * as os15 from "os";
|
|
29325
|
-
import * as
|
|
29436
|
+
import * as path34 from "path";
|
|
29326
29437
|
init_errors();
|
|
29327
29438
|
|
|
29328
29439
|
// src/lib/onboarding-profile.ts
|
|
@@ -30047,9 +30158,9 @@ function composeFounderIdentityNote(id) {
|
|
|
30047
30158
|
|
|
30048
30159
|
// src/lib/company-profile-seed.ts
|
|
30049
30160
|
function readGithubAppCreds(credsPath) {
|
|
30050
|
-
const p = credsPath ??
|
|
30161
|
+
const p = credsPath ?? path34.join(os15.homedir(), ".m8t", "github-app.json");
|
|
30051
30162
|
try {
|
|
30052
|
-
return JSON.parse(
|
|
30163
|
+
return JSON.parse(readFileSync22(p, "utf8"));
|
|
30053
30164
|
} catch {
|
|
30054
30165
|
return null;
|
|
30055
30166
|
}
|
|
@@ -30115,7 +30226,7 @@ function upsertMemoryIndexOnce(existing, line2, targetPath2) {
|
|
|
30115
30226
|
async function applyProfileToBrain(args) {
|
|
30116
30227
|
const token = await mintInstallationTokenFromPem({
|
|
30117
30228
|
appId: args.appCreds.appId,
|
|
30118
|
-
privateKeyPem:
|
|
30229
|
+
privateKeyPem: readFileSync22(args.appCreds.pemPath, "utf8"),
|
|
30119
30230
|
installationId: args.appCreds.installationId,
|
|
30120
30231
|
fetchImpl: args.fetchImpl
|
|
30121
30232
|
});
|
|
@@ -30205,7 +30316,7 @@ async function applyProfileToBrains(args) {
|
|
|
30205
30316
|
}
|
|
30206
30317
|
}
|
|
30207
30318
|
function spawnDetachedSeedWatch() {
|
|
30208
|
-
const logPath =
|
|
30319
|
+
const logPath = path34.join(os15.homedir(), ".m8t", "seed-profile.log");
|
|
30209
30320
|
const fd = openSync(logPath, "a");
|
|
30210
30321
|
try {
|
|
30211
30322
|
const child = spawn6(process.execPath, [process.argv[1] ?? "", "bootstrap", "seed-profile", "--watch"], {
|
|
@@ -30280,7 +30391,7 @@ function renderInstallSummary(args) {
|
|
|
30280
30391
|
// src/lib/companion-install.ts
|
|
30281
30392
|
import { constants as constants2 } from "fs";
|
|
30282
30393
|
import * as fs32 from "fs/promises";
|
|
30283
|
-
import * as
|
|
30394
|
+
import * as path36 from "path";
|
|
30284
30395
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
30285
30396
|
import { execFile, spawn as spawn7 } from "child_process";
|
|
30286
30397
|
|
|
@@ -30288,7 +30399,7 @@ import { execFile, spawn as spawn7 } from "child_process";
|
|
|
30288
30399
|
import { createHash as createHash5 } from "crypto";
|
|
30289
30400
|
import { constants } from "fs";
|
|
30290
30401
|
import * as fs31 from "fs/promises";
|
|
30291
|
-
import * as
|
|
30402
|
+
import * as path35 from "path";
|
|
30292
30403
|
var SHA256 = /^[a-f0-9]{64}$/u;
|
|
30293
30404
|
var VERSION2 = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/u;
|
|
30294
30405
|
function exactKeys(value, expected) {
|
|
@@ -30296,23 +30407,23 @@ function exactKeys(value, expected) {
|
|
|
30296
30407
|
return actual.length === expected.length && actual.every((key2, index) => key2 === [...expected].sort()[index]);
|
|
30297
30408
|
}
|
|
30298
30409
|
function normalizedRelative(value) {
|
|
30299
|
-
if (value.length === 0 || value.includes("\\") || value.includes("\0") ||
|
|
30410
|
+
if (value.length === 0 || value.includes("\\") || value.includes("\0") || path35.posix.isAbsolute(value)) {
|
|
30300
30411
|
throw new Error("Artifact path must be a normalized relative POSIX path");
|
|
30301
30412
|
}
|
|
30302
|
-
const normalized =
|
|
30413
|
+
const normalized = path35.posix.normalize(value);
|
|
30303
30414
|
if (normalized !== value || normalized === "." || normalized === ".." || normalized.startsWith("../")) {
|
|
30304
30415
|
throw new Error("Artifact path escapes the payload root");
|
|
30305
30416
|
}
|
|
30306
30417
|
return value;
|
|
30307
30418
|
}
|
|
30308
30419
|
function validateLink(entryPath, target) {
|
|
30309
|
-
if (target.length === 0 || target.includes("\\") || target.includes("\0") ||
|
|
30420
|
+
if (target.length === 0 || target.includes("\\") || target.includes("\0") || path35.posix.isAbsolute(target)) {
|
|
30310
30421
|
throw new Error("Artifact symlink target must be relative");
|
|
30311
30422
|
}
|
|
30312
|
-
const resolved =
|
|
30313
|
-
|
|
30423
|
+
const resolved = path35.posix.normalize(
|
|
30424
|
+
path35.posix.join(path35.posix.dirname(entryPath), target)
|
|
30314
30425
|
);
|
|
30315
|
-
if (resolved === ".." || resolved.startsWith("../") ||
|
|
30426
|
+
if (resolved === ".." || resolved.startsWith("../") || path35.posix.isAbsolute(resolved)) {
|
|
30316
30427
|
throw new Error("Artifact symlink target escapes the payload root");
|
|
30317
30428
|
}
|
|
30318
30429
|
return target;
|
|
@@ -30396,13 +30507,13 @@ async function sha256File2(filePath) {
|
|
|
30396
30507
|
return createHash5("sha256").update(await fs31.readFile(filePath)).digest("hex");
|
|
30397
30508
|
}
|
|
30398
30509
|
async function walk(root, relative3 = "") {
|
|
30399
|
-
const directory =
|
|
30510
|
+
const directory = path35.join(root, ...relative3.split("/").filter(Boolean));
|
|
30400
30511
|
const children = await fs31.readdir(directory, { withFileTypes: true });
|
|
30401
30512
|
const entries = [];
|
|
30402
30513
|
for (const child of children.sort((left, right) => left.name.localeCompare(right.name))) {
|
|
30403
30514
|
const childRelative = relative3 ? `${relative3}/${child.name}` : child.name;
|
|
30404
30515
|
normalizedRelative(childRelative);
|
|
30405
|
-
const childPath =
|
|
30516
|
+
const childPath = path35.join(directory, child.name);
|
|
30406
30517
|
const stat5 = await fs31.lstat(childPath);
|
|
30407
30518
|
if (stat5.isDirectory()) {
|
|
30408
30519
|
entries.push(...await walk(root, childRelative));
|
|
@@ -30437,10 +30548,10 @@ async function validateResolvedLinks(root, entries) {
|
|
|
30437
30548
|
for (const entry of entries) {
|
|
30438
30549
|
if (entry.type !== "symlink") continue;
|
|
30439
30550
|
try {
|
|
30440
|
-
const linkPath =
|
|
30551
|
+
const linkPath = path35.join(root, ...entry.path.split("/"));
|
|
30441
30552
|
const resolved = await fs31.realpath(linkPath);
|
|
30442
|
-
const relative3 =
|
|
30443
|
-
if (relative3 === ".." || relative3.startsWith(`..${
|
|
30553
|
+
const relative3 = path35.relative(realRoot, resolved);
|
|
30554
|
+
if (relative3 === ".." || relative3.startsWith(`..${path35.sep}`) || path35.isAbsolute(relative3)) {
|
|
30444
30555
|
throw new Error("Artifact symlink chain escapes the payload root");
|
|
30445
30556
|
}
|
|
30446
30557
|
} catch (error) {
|
|
@@ -30493,9 +30604,9 @@ async function readArtifactManifest(manifestPath) {
|
|
|
30493
30604
|
}
|
|
30494
30605
|
}
|
|
30495
30606
|
function ensureContainedEntry(root, entryPath) {
|
|
30496
|
-
const absolute =
|
|
30497
|
-
const relative3 =
|
|
30498
|
-
if (relative3.startsWith("..") ||
|
|
30607
|
+
const absolute = path35.join(root, ...entryPath.split("/"));
|
|
30608
|
+
const relative3 = path35.relative(root, absolute);
|
|
30609
|
+
if (relative3.startsWith("..") || path35.isAbsolute(relative3)) {
|
|
30499
30610
|
throw new Error("Artifact entry escapes payload root");
|
|
30500
30611
|
}
|
|
30501
30612
|
return absolute;
|
|
@@ -30549,7 +30660,7 @@ async function copyArtifactPayload(sourceRoot, targetRoot, manifest) {
|
|
|
30549
30660
|
for (const entry of manifest.entries) {
|
|
30550
30661
|
const source = ensureContainedEntry(sourceRoot, entry.path);
|
|
30551
30662
|
const target = ensureContainedEntry(targetRoot, entry.path);
|
|
30552
|
-
await fs31.mkdir(
|
|
30663
|
+
await fs31.mkdir(path35.dirname(target), { recursive: true, mode: 448 });
|
|
30553
30664
|
if (entry.type === "file") {
|
|
30554
30665
|
await fs31.copyFile(source, target);
|
|
30555
30666
|
await fs31.chmod(target, entry.mode);
|
|
@@ -30593,8 +30704,8 @@ function execFileOutput(file, args) {
|
|
|
30593
30704
|
}
|
|
30594
30705
|
async function setCompanionStartAtLogin(input) {
|
|
30595
30706
|
if (input.platform === "darwin") {
|
|
30596
|
-
const launchAgents =
|
|
30597
|
-
const registration =
|
|
30707
|
+
const launchAgents = path36.join(input.homeDirectory, "Library", "LaunchAgents");
|
|
30708
|
+
const registration = path36.join(
|
|
30598
30709
|
launchAgents,
|
|
30599
30710
|
"com.m8t.companion.plist"
|
|
30600
30711
|
);
|
|
@@ -30655,7 +30766,7 @@ async function setCompanionStartAtLogin(input) {
|
|
|
30655
30766
|
}
|
|
30656
30767
|
async function getCompanionStartAtLogin(input) {
|
|
30657
30768
|
if (input.platform === "darwin") {
|
|
30658
|
-
const registration =
|
|
30769
|
+
const registration = path36.join(
|
|
30659
30770
|
input.homeDirectory,
|
|
30660
30771
|
"Library",
|
|
30661
30772
|
"LaunchAgents",
|
|
@@ -30717,26 +30828,26 @@ function assertSupported(options) {
|
|
|
30717
30828
|
}
|
|
30718
30829
|
function companionInstallPaths(options) {
|
|
30719
30830
|
assertSupported(options);
|
|
30720
|
-
const companionState =
|
|
30831
|
+
const companionState = path36.join(
|
|
30721
30832
|
options.homeDirectory,
|
|
30722
30833
|
".m8t",
|
|
30723
30834
|
"companion"
|
|
30724
30835
|
);
|
|
30725
|
-
const targetRoot = options.platform === "darwin" ?
|
|
30836
|
+
const targetRoot = options.platform === "darwin" ? path36.join(
|
|
30726
30837
|
options.homeDirectory,
|
|
30727
30838
|
"Applications",
|
|
30728
30839
|
"m8t Companion.app"
|
|
30729
|
-
) :
|
|
30730
|
-
options.localAppData ??
|
|
30840
|
+
) : path36.join(
|
|
30841
|
+
options.localAppData ?? path36.join(options.homeDirectory, "AppData", "Local"),
|
|
30731
30842
|
"m8t",
|
|
30732
30843
|
"companion",
|
|
30733
30844
|
"app"
|
|
30734
30845
|
);
|
|
30735
30846
|
return {
|
|
30736
30847
|
targetRoot,
|
|
30737
|
-
installManifest:
|
|
30738
|
-
runtimeBinding:
|
|
30739
|
-
preferences:
|
|
30848
|
+
installManifest: path36.join(companionState, "install-v1.json"),
|
|
30849
|
+
runtimeBinding: path36.join(companionState, "runtime-v1.json"),
|
|
30850
|
+
preferences: path36.join(companionState, "preferences-v1.json")
|
|
30740
30851
|
};
|
|
30741
30852
|
}
|
|
30742
30853
|
function exactKeys2(value, keys) {
|
|
@@ -30747,7 +30858,7 @@ function parseInstallManifest(value) {
|
|
|
30747
30858
|
throw new Error("Install manifest schema is invalid");
|
|
30748
30859
|
}
|
|
30749
30860
|
const record = value;
|
|
30750
|
-
if (!exactKeys2(record, INSTALL_KEYS) || record.schemaVersion !== 1 || typeof record.version !== "string" || record.platform !== "darwin" && record.platform !== "win32" || record.architecture !== "arm64" && record.architecture !== "x64" || typeof record.entryRelativePath !== "string" || typeof record.artifactTreeSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(record.artifactTreeSha256) || typeof record.ownedTargetRoot !== "string" || !
|
|
30861
|
+
if (!exactKeys2(record, INSTALL_KEYS) || record.schemaVersion !== 1 || typeof record.version !== "string" || record.platform !== "darwin" && record.platform !== "win32" || record.architecture !== "arm64" && record.architecture !== "x64" || typeof record.entryRelativePath !== "string" || typeof record.artifactTreeSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(record.artifactTreeSha256) || typeof record.ownedTargetRoot !== "string" || !path36.isAbsolute(record.ownedTargetRoot)) {
|
|
30751
30862
|
throw new Error("Install manifest schema is invalid");
|
|
30752
30863
|
}
|
|
30753
30864
|
return record;
|
|
@@ -30757,7 +30868,7 @@ function parseRuntimeBinding(value, platform) {
|
|
|
30757
30868
|
throw new Error("Runtime binding schema is invalid");
|
|
30758
30869
|
}
|
|
30759
30870
|
const record = value;
|
|
30760
|
-
const paths = platform === "win32" ?
|
|
30871
|
+
const paths = platform === "win32" ? path36.win32 : path36.posix;
|
|
30761
30872
|
if (!exactKeys2(record, RUNTIME_KEYS) || record.schemaVersion !== 1 || typeof record.nodeExecutable !== "string" || !paths.isAbsolute(record.nodeExecutable) || typeof record.cliEntry !== "string" || !paths.isAbsolute(record.cliEntry) || typeof record.gatewayOrigin !== "string") {
|
|
30762
30873
|
throw new Error("Runtime binding schema is invalid");
|
|
30763
30874
|
}
|
|
@@ -30791,18 +30902,18 @@ async function assertNotSymlink(filePath, kind) {
|
|
|
30791
30902
|
}
|
|
30792
30903
|
}
|
|
30793
30904
|
async function assertOwnedDirectoryChain(anchor, targetDirectory) {
|
|
30794
|
-
const relative3 =
|
|
30795
|
-
if (relative3 === ".." || relative3.startsWith(`..${
|
|
30905
|
+
const relative3 = path36.relative(anchor, targetDirectory);
|
|
30906
|
+
if (relative3 === ".." || relative3.startsWith(`..${path36.sep}`) || path36.isAbsolute(relative3)) {
|
|
30796
30907
|
throw new Error("Companion owned directory escapes its trusted anchor");
|
|
30797
30908
|
}
|
|
30798
|
-
const segments = relative3.split(
|
|
30909
|
+
const segments = relative3.split(path36.sep).filter(Boolean);
|
|
30799
30910
|
let current = anchor;
|
|
30800
30911
|
const anchorStatus = await fs32.lstat(anchor);
|
|
30801
30912
|
if (anchorStatus.isSymbolicLink() || !anchorStatus.isDirectory()) {
|
|
30802
30913
|
throw new Error("Companion owned directory anchor is unsafe");
|
|
30803
30914
|
}
|
|
30804
30915
|
for (const segment of segments) {
|
|
30805
|
-
current =
|
|
30916
|
+
current = path36.join(current, segment);
|
|
30806
30917
|
try {
|
|
30807
30918
|
const status = await fs32.lstat(current);
|
|
30808
30919
|
if (status.isSymbolicLink() || !status.isDirectory()) {
|
|
@@ -30817,10 +30928,10 @@ async function assertOwnedDirectoryChain(anchor, targetDirectory) {
|
|
|
30817
30928
|
async function assertOwnedParents(options, paths) {
|
|
30818
30929
|
await assertOwnedDirectoryChain(
|
|
30819
30930
|
options.homeDirectory,
|
|
30820
|
-
|
|
30931
|
+
path36.dirname(paths.installManifest)
|
|
30821
30932
|
);
|
|
30822
|
-
const targetAnchor = options.platform === "win32" ? options.localAppData ??
|
|
30823
|
-
await assertOwnedDirectoryChain(targetAnchor,
|
|
30933
|
+
const targetAnchor = options.platform === "win32" ? options.localAppData ?? path36.join(options.homeDirectory, "AppData", "Local") : options.homeDirectory;
|
|
30934
|
+
await assertOwnedDirectoryChain(targetAnchor, path36.dirname(paths.targetRoot));
|
|
30824
30935
|
}
|
|
30825
30936
|
async function readRegularText(filePath, maxBytes) {
|
|
30826
30937
|
const before = await fs32.lstat(filePath);
|
|
@@ -30852,7 +30963,7 @@ async function atomicWriteJson(filePath, value) {
|
|
|
30852
30963
|
}
|
|
30853
30964
|
async function atomicWriteText(filePath, contents, mode) {
|
|
30854
30965
|
await assertNotSymlink(filePath, "Companion state file");
|
|
30855
|
-
await fs32.mkdir(
|
|
30966
|
+
await fs32.mkdir(path36.dirname(filePath), {
|
|
30856
30967
|
recursive: true,
|
|
30857
30968
|
mode: 448
|
|
30858
30969
|
});
|
|
@@ -30969,7 +31080,7 @@ async function statusCompanion(options) {
|
|
|
30969
31080
|
realRegularFile(runtime.nodeExecutable, options.platform !== "win32"),
|
|
30970
31081
|
realRegularFile(runtime.cliEntry, false)
|
|
30971
31082
|
]);
|
|
30972
|
-
const executable =
|
|
31083
|
+
const executable = path36.join(
|
|
30973
31084
|
paths.targetRoot,
|
|
30974
31085
|
...install.entryRelativePath.split("/")
|
|
30975
31086
|
);
|
|
@@ -31017,8 +31128,8 @@ async function converge(options, force) {
|
|
|
31017
31128
|
if (artifactManifest.platform !== options.platform || artifactManifest.architecture !== options.architecture) {
|
|
31018
31129
|
throw new Error("Companion artifact does not match this OS and architecture");
|
|
31019
31130
|
}
|
|
31020
|
-
const payloadRoot =
|
|
31021
|
-
|
|
31131
|
+
const payloadRoot = path36.join(
|
|
31132
|
+
path36.dirname(options.artifactManifestPath),
|
|
31022
31133
|
"payload"
|
|
31023
31134
|
);
|
|
31024
31135
|
await verifyArtifactSource(payloadRoot, artifactManifest);
|
|
@@ -31038,7 +31149,7 @@ async function converge(options, force) {
|
|
|
31038
31149
|
if (priorInstalled) {
|
|
31039
31150
|
await assertCompanionNotRunning(
|
|
31040
31151
|
options,
|
|
31041
|
-
|
|
31152
|
+
path36.join(
|
|
31042
31153
|
priorInstalled.paths.targetRoot,
|
|
31043
31154
|
...priorInstalled.install.entryRelativePath.split("/")
|
|
31044
31155
|
)
|
|
@@ -31057,7 +31168,7 @@ async function converge(options, force) {
|
|
|
31057
31168
|
const stage = `${paths.targetRoot}.m8t-stage-${randomUUID3()}`;
|
|
31058
31169
|
const backup = `${paths.targetRoot}.m8t-backup-${randomUUID3()}`;
|
|
31059
31170
|
const copy = options.copyPayload ?? copyArtifactPayload;
|
|
31060
|
-
await fs32.mkdir(
|
|
31171
|
+
await fs32.mkdir(path36.dirname(paths.targetRoot), {
|
|
31061
31172
|
recursive: true,
|
|
31062
31173
|
mode: 448
|
|
31063
31174
|
});
|
|
@@ -31121,7 +31232,7 @@ async function converge(options, force) {
|
|
|
31121
31232
|
await readClosedJson(paths.runtimeBinding),
|
|
31122
31233
|
options.platform
|
|
31123
31234
|
);
|
|
31124
|
-
const executable =
|
|
31235
|
+
const executable = path36.join(
|
|
31125
31236
|
paths.targetRoot,
|
|
31126
31237
|
...artifactManifest.entryRelativePath.split("/")
|
|
31127
31238
|
);
|
|
@@ -31131,7 +31242,7 @@ async function converge(options, force) {
|
|
|
31131
31242
|
platform: options.platform,
|
|
31132
31243
|
executable: ownedExecutable
|
|
31133
31244
|
}));
|
|
31134
|
-
priorLoginExecutable = priorInstalled ?
|
|
31245
|
+
priorLoginExecutable = priorInstalled ? path36.join(
|
|
31135
31246
|
priorInstalled.paths.targetRoot,
|
|
31136
31247
|
...priorInstalled.install.entryRelativePath.split("/")
|
|
31137
31248
|
) : executable;
|
|
@@ -31190,7 +31301,7 @@ async function uninstallCompanion(options) {
|
|
|
31190
31301
|
if (install.ownedTargetRoot !== paths.targetRoot) {
|
|
31191
31302
|
throw new Error("Refusing to remove a non-owned companion target");
|
|
31192
31303
|
}
|
|
31193
|
-
const executable =
|
|
31304
|
+
const executable = path36.join(
|
|
31194
31305
|
paths.targetRoot,
|
|
31195
31306
|
...install.entryRelativePath.split("/")
|
|
31196
31307
|
);
|
|
@@ -31208,7 +31319,7 @@ async function uninstallCompanion(options) {
|
|
|
31208
31319
|
|
|
31209
31320
|
// src/commands/companion/install.ts
|
|
31210
31321
|
import * as os17 from "os";
|
|
31211
|
-
import * as
|
|
31322
|
+
import * as path38 from "path";
|
|
31212
31323
|
import { Command as Command55, Option as Option52 } from "clipanion";
|
|
31213
31324
|
|
|
31214
31325
|
// src/lib/companion-channel.ts
|
|
@@ -31228,7 +31339,7 @@ import { createHash as createHash6 } from "crypto";
|
|
|
31228
31339
|
import { execFile as execFile2 } from "child_process";
|
|
31229
31340
|
import * as fs33 from "fs/promises";
|
|
31230
31341
|
import * as os16 from "os";
|
|
31231
|
-
import * as
|
|
31342
|
+
import * as path37 from "path";
|
|
31232
31343
|
init_errors();
|
|
31233
31344
|
var MAX_ASSET_BYTES = 512 * 1024 * 1024;
|
|
31234
31345
|
function extractArchive(archive, into) {
|
|
@@ -31281,20 +31392,20 @@ async function downloadCompanionArtifact(component, deps = {}) {
|
|
|
31281
31392
|
hint: "Nothing was unpacked. This is what a corrupted download or a substituted file looks like \u2014 retry, and report it if it persists."
|
|
31282
31393
|
});
|
|
31283
31394
|
}
|
|
31284
|
-
const root = await (deps.makeTemporaryDirectory ?? (() => fs33.mkdtemp(
|
|
31395
|
+
const root = await (deps.makeTemporaryDirectory ?? (() => fs33.mkdtemp(path37.join(os16.tmpdir(), "m8t-companion-"))))();
|
|
31285
31396
|
const dispose = async () => {
|
|
31286
31397
|
await fs33.rm(root, { recursive: true, force: true }).catch(() => void 0);
|
|
31287
31398
|
};
|
|
31288
31399
|
try {
|
|
31289
|
-
const archive =
|
|
31400
|
+
const archive = path37.join(root, pinned.asset);
|
|
31290
31401
|
await fs33.writeFile(archive, bytes, { mode: 384 });
|
|
31291
|
-
const unpacked =
|
|
31402
|
+
const unpacked = path37.join(root, "unpacked");
|
|
31292
31403
|
await fs33.mkdir(unpacked, { recursive: false, mode: 448 });
|
|
31293
31404
|
await (deps.extract ?? extractArchive)(archive, unpacked);
|
|
31294
31405
|
await fs33.rm(archive, { force: true });
|
|
31295
31406
|
return {
|
|
31296
31407
|
version: component.version,
|
|
31297
|
-
artifactManifestPath:
|
|
31408
|
+
artifactManifestPath: path37.join(unpacked, "artifact-v1.json"),
|
|
31298
31409
|
dispose
|
|
31299
31410
|
};
|
|
31300
31411
|
} catch (error) {
|
|
@@ -31325,7 +31436,7 @@ async function convergeCompanionFromChannel(converge2, options = {}) {
|
|
|
31325
31436
|
let artifactManifestPath;
|
|
31326
31437
|
let dispose = () => Promise.resolve();
|
|
31327
31438
|
if (stagedDirectory !== void 0) {
|
|
31328
|
-
artifactManifestPath =
|
|
31439
|
+
artifactManifestPath = path38.resolve(stagedDirectory, "artifact-v1.json");
|
|
31329
31440
|
} else {
|
|
31330
31441
|
const release = await readCompanionRelease(
|
|
31331
31442
|
platformVersion !== void 0 ? { channel: true, version: platformTag(platformVersion) } : { url: CHANNEL_LATEST_URL }
|
|
@@ -31403,7 +31514,7 @@ function resolveRepoRootMarker(args) {
|
|
|
31403
31514
|
}
|
|
31404
31515
|
async function looksLikeCheckout(dir) {
|
|
31405
31516
|
try {
|
|
31406
|
-
return (await fs34.stat(
|
|
31517
|
+
return (await fs34.stat(path39.join(dir, "brain-template"))).isDirectory();
|
|
31407
31518
|
} catch {
|
|
31408
31519
|
return false;
|
|
31409
31520
|
}
|
|
@@ -31422,8 +31533,8 @@ var defaultDeps2 = {
|
|
|
31422
31533
|
homedir: () => os18.homedir()
|
|
31423
31534
|
};
|
|
31424
31535
|
async function finalizeInstall(args, deps = defaultDeps2) {
|
|
31425
|
-
const markerDir =
|
|
31426
|
-
const markerPath =
|
|
31536
|
+
const markerDir = path39.join(deps.homedir(), ".m8t");
|
|
31537
|
+
const markerPath = path39.join(markerDir, "repo-root");
|
|
31427
31538
|
const cwd = process.cwd();
|
|
31428
31539
|
const existing = await fs34.readFile(markerPath, "utf8").then((s) => s.trim()).catch(() => null);
|
|
31429
31540
|
const repoRoot = resolveRepoRootMarker({
|
|
@@ -31511,7 +31622,7 @@ async function finalizeInstall(args, deps = defaultDeps2) {
|
|
|
31511
31622
|
}
|
|
31512
31623
|
let brainOrg = null;
|
|
31513
31624
|
try {
|
|
31514
|
-
const credsRaw = await fs34.readFile(
|
|
31625
|
+
const credsRaw = await fs34.readFile(path39.join(markerDir, "github-app.json"), "utf8");
|
|
31515
31626
|
const creds = JSON.parse(credsRaw);
|
|
31516
31627
|
brainOrg = typeof creds.org === "string" ? creds.org : null;
|
|
31517
31628
|
} catch {
|
|
@@ -31942,7 +32053,7 @@ Found ${String(total)} orphaned assignment(s) (${breakdown}) (dry-run). ${colors
|
|
|
31942
32053
|
// src/commands/bootstrap/ui.ts
|
|
31943
32054
|
import * as fs36 from "fs";
|
|
31944
32055
|
import * as os20 from "os";
|
|
31945
|
-
import * as
|
|
32056
|
+
import * as path41 from "path";
|
|
31946
32057
|
import { Command as Command58, Option as Option55 } from "clipanion";
|
|
31947
32058
|
import { DefaultAzureCredential as DefaultAzureCredential24 } from "@azure/identity";
|
|
31948
32059
|
init_errors();
|
|
@@ -31951,7 +32062,7 @@ init_errors();
|
|
|
31951
32062
|
import * as fs35 from "fs";
|
|
31952
32063
|
import * as net from "net";
|
|
31953
32064
|
import * as os19 from "os";
|
|
31954
|
-
import * as
|
|
32065
|
+
import * as path40 from "path";
|
|
31955
32066
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
31956
32067
|
import { spawn as spawn8, spawnSync as spawnSync6 } from "child_process";
|
|
31957
32068
|
init_errors();
|
|
@@ -32057,20 +32168,46 @@ async function deployIntakeAgentWithRetry(args) {
|
|
|
32057
32168
|
}
|
|
32058
32169
|
}
|
|
32059
32170
|
}
|
|
32171
|
+
function renderNotReadyHint(resourceGroup, excluded) {
|
|
32172
|
+
const lines = ["Check 'm8t bootstrap status --watch' \u2014 the install may have stalled in foundry-create."];
|
|
32173
|
+
if (resourceGroup) {
|
|
32174
|
+
if (excluded.length > 0) {
|
|
32175
|
+
const count = excluded.length === 1 ? "1 project" : `${excluded.length.toString()} projects`;
|
|
32176
|
+
const verb = excluded.length === 1 ? "was" : "were";
|
|
32177
|
+
lines.push(
|
|
32178
|
+
`Discovery is scoped to this install's resource group (${resourceGroup}) on purpose, so it can`,
|
|
32179
|
+
`never deploy into someone else's project. ${count} elsewhere in this subscription ${verb}`,
|
|
32180
|
+
"skipped:",
|
|
32181
|
+
...excluded.map((c) => ` ${c.endpoint}`)
|
|
32182
|
+
);
|
|
32183
|
+
}
|
|
32184
|
+
lines.push(
|
|
32185
|
+
"If ~/.m8t/bootstrap.json names a different install than the one you meant, re-run with",
|
|
32186
|
+
"--endpoint <projectEndpoint>."
|
|
32187
|
+
);
|
|
32188
|
+
}
|
|
32189
|
+
return lines.join("\n");
|
|
32190
|
+
}
|
|
32060
32191
|
async function resolveFoundryEndpointWithWait(args, opts = {}) {
|
|
32061
32192
|
const pollMs = opts.pollMs ?? 1e4;
|
|
32062
32193
|
const timeoutMs = opts.timeoutMs ?? 15 * 6e4;
|
|
32063
32194
|
const deadline = Date.now() + timeoutMs;
|
|
32195
|
+
let excluded = [];
|
|
32064
32196
|
for (; ; ) {
|
|
32065
32197
|
try {
|
|
32198
|
+
excluded = [];
|
|
32066
32199
|
const p = await resolveFoundryProject({
|
|
32067
32200
|
credential: args.credential,
|
|
32068
32201
|
subscriptionId: args.subscriptionId,
|
|
32069
32202
|
interactive: false,
|
|
32070
|
-
// When the
|
|
32071
|
-
//
|
|
32072
|
-
//
|
|
32073
|
-
endpoint: args.endpoint
|
|
32203
|
+
// When the install's own resource group holds multiple projects, an
|
|
32204
|
+
// explicit endpoint disambiguates instead of FOUNDRY_PROJECT_MULTIPLE.
|
|
32205
|
+
// Omitted → single-project auto-discovery within that group.
|
|
32206
|
+
endpoint: args.endpoint,
|
|
32207
|
+
resourceGroup: args.resourceGroup,
|
|
32208
|
+
onScopedOut: (dropped) => {
|
|
32209
|
+
excluded = dropped;
|
|
32210
|
+
}
|
|
32074
32211
|
});
|
|
32075
32212
|
return { endpoint: p.endpoint, accountScope: p.accountScope };
|
|
32076
32213
|
} catch (e) {
|
|
@@ -32078,7 +32215,11 @@ async function resolveFoundryEndpointWithWait(args, opts = {}) {
|
|
|
32078
32215
|
throw new LocalCliError({
|
|
32079
32216
|
code: "BOOTSTRAP_UI_MULTIPLE_PROJECTS",
|
|
32080
32217
|
message: `${e.message} bootstrap ui can't pick one safely (it must not deploy the intake agent into the wrong project).`,
|
|
32081
|
-
hint:
|
|
32218
|
+
hint: [
|
|
32219
|
+
"Re-run naming the project you want:",
|
|
32220
|
+
'm8t bootstrap ui --repo-root "$(pwd)" --endpoint <projectEndpoint>',
|
|
32221
|
+
"'m8t bootstrap status' prints this install's endpoint (result.foundryEndpoint)."
|
|
32222
|
+
].join("\n"),
|
|
32082
32223
|
cause: e
|
|
32083
32224
|
});
|
|
32084
32225
|
}
|
|
@@ -32088,8 +32229,8 @@ async function resolveFoundryEndpointWithWait(args, opts = {}) {
|
|
|
32088
32229
|
if (Date.now() >= deadline) {
|
|
32089
32230
|
throw new LocalCliError({
|
|
32090
32231
|
code: "BOOTSTRAP_UI_FOUNDRY_NOT_READY",
|
|
32091
|
-
message: "Foundry is not ready yet \u2014 no AI project appeared in your subscription before the timeout.",
|
|
32092
|
-
hint:
|
|
32232
|
+
message: args.resourceGroup ? `Foundry is not ready yet \u2014 no AI project appeared in resource group ${args.resourceGroup} before the timeout.` : "Foundry is not ready yet \u2014 no AI project appeared in your subscription before the timeout.",
|
|
32233
|
+
hint: renderNotReadyHint(args.resourceGroup, excluded),
|
|
32093
32234
|
cause: e
|
|
32094
32235
|
});
|
|
32095
32236
|
}
|
|
@@ -32119,7 +32260,7 @@ async function ensureFounderFoundryRole(args) {
|
|
|
32119
32260
|
});
|
|
32120
32261
|
}
|
|
32121
32262
|
function writeWebEnvLocal(args) {
|
|
32122
|
-
const envPath =
|
|
32263
|
+
const envPath = path40.join(args.repoRoot, "apps", "web", ".env.local");
|
|
32123
32264
|
let prior = "";
|
|
32124
32265
|
if (fs35.existsSync(envPath)) {
|
|
32125
32266
|
prior = fs35.readFileSync(envPath, "utf8");
|
|
@@ -32167,7 +32308,7 @@ function readValidInternalSecret(envText) {
|
|
|
32167
32308
|
return isValidInternalSecret(values[0]) ? values[0] : void 0;
|
|
32168
32309
|
}
|
|
32169
32310
|
function readWebInternalSecret(repoRoot) {
|
|
32170
|
-
const envPath =
|
|
32311
|
+
const envPath = path40.join(repoRoot, "apps", "web", ".env.local");
|
|
32171
32312
|
let secret;
|
|
32172
32313
|
try {
|
|
32173
32314
|
secret = readValidInternalSecret(fs35.readFileSync(envPath, "utf8"));
|
|
@@ -32222,17 +32363,17 @@ async function installWebDeps(repoRoot) {
|
|
|
32222
32363
|
await runInherit("pnpm", ["install"], repoRoot, "BOOTSTRAP_UI_INSTALL_FAILED");
|
|
32223
32364
|
}
|
|
32224
32365
|
function onboardingUiPaths(home = os19.homedir()) {
|
|
32225
|
-
const dir =
|
|
32366
|
+
const dir = path40.join(home, ".m8t");
|
|
32226
32367
|
return {
|
|
32227
|
-
logPath:
|
|
32228
|
-
pidPath:
|
|
32368
|
+
logPath: path40.join(dir, "onboarding-ui.log"),
|
|
32369
|
+
pidPath: path40.join(dir, "onboarding-ui.pid")
|
|
32229
32370
|
};
|
|
32230
32371
|
}
|
|
32231
32372
|
function onboardingRelayPaths(home = os19.homedir()) {
|
|
32232
|
-
const dir =
|
|
32373
|
+
const dir = path40.join(home, ".m8t");
|
|
32233
32374
|
return {
|
|
32234
|
-
logPath:
|
|
32235
|
-
pidPath:
|
|
32375
|
+
logPath: path40.join(dir, "onboarding-relay.log"),
|
|
32376
|
+
pidPath: path40.join(dir, "onboarding-relay.pid")
|
|
32236
32377
|
};
|
|
32237
32378
|
}
|
|
32238
32379
|
function isLocalPortOpen(port) {
|
|
@@ -32306,7 +32447,7 @@ async function serveOnboardingUiDetached(args) {
|
|
|
32306
32447
|
});
|
|
32307
32448
|
}
|
|
32308
32449
|
if (managedPid != null) return { alreadyRunning: true, logPath };
|
|
32309
|
-
fs35.mkdirSync(
|
|
32450
|
+
fs35.mkdirSync(path40.dirname(logPath), { recursive: true });
|
|
32310
32451
|
const fd = fs35.openSync(logPath, "a");
|
|
32311
32452
|
const child = spawn8("pnpm", ["--filter", "web", "dev"], {
|
|
32312
32453
|
cwd: args.repoRoot,
|
|
@@ -32357,7 +32498,7 @@ async function serveOnboardingRelayDetached(args) {
|
|
|
32357
32498
|
});
|
|
32358
32499
|
}
|
|
32359
32500
|
if (managedPid != null) return { alreadyRunning: true, logPath };
|
|
32360
|
-
fs35.mkdirSync(
|
|
32501
|
+
fs35.mkdirSync(path40.dirname(logPath), { recursive: true });
|
|
32361
32502
|
const fd = fs35.openSync(logPath, "a");
|
|
32362
32503
|
const child = spawn8("pnpm", ["--filter", "web", "exec", "tsx", "voice-relay-entry.ts"], {
|
|
32363
32504
|
cwd: args.repoRoot,
|
|
@@ -32775,7 +32916,7 @@ var BootstrapUiCommand = class extends M8tCommand {
|
|
|
32775
32916
|
repoRoot = Option55.String("--repo-root");
|
|
32776
32917
|
port = Option55.String("--port", "3000");
|
|
32777
32918
|
endpoint = Option55.String("--endpoint", {
|
|
32778
|
-
description: "Foundry project endpoint to target \u2014
|
|
32919
|
+
description: "Foundry project endpoint to target \u2014 overrides discovery when this install's resource group holds more than one Foundry project."
|
|
32779
32920
|
});
|
|
32780
32921
|
prepOnly = Option55.Boolean("--prep-only", false);
|
|
32781
32922
|
skipInstall = Option55.Boolean("--skip-install", false);
|
|
@@ -32816,7 +32957,7 @@ var BootstrapUiCommand = class extends M8tCommand {
|
|
|
32816
32957
|
this.context.stderr.write(` ${colors.dim(m)}
|
|
32817
32958
|
`);
|
|
32818
32959
|
};
|
|
32819
|
-
if (fs36.existsSync(
|
|
32960
|
+
if (fs36.existsSync(path41.join(os20.homedir(), ".m8t", "config.yaml"))) {
|
|
32820
32961
|
out(colors.error("\u26A0 an existing ~/.m8t/config.yaml will override the onboarding app registration in apps/web \u2014 if Microsoft sign-in fails, move it aside and retry."));
|
|
32821
32962
|
}
|
|
32822
32963
|
const credential2 = new DefaultAzureCredential24();
|
|
@@ -32827,7 +32968,12 @@ var BootstrapUiCommand = class extends M8tCommand {
|
|
|
32827
32968
|
{
|
|
32828
32969
|
credential: credential2,
|
|
32829
32970
|
subscriptionId: state.subscriptionId,
|
|
32830
|
-
endpoint: typeof this.endpoint === "string" ? this.endpoint : void 0
|
|
32971
|
+
endpoint: typeof this.endpoint === "string" ? this.endpoint : void 0,
|
|
32972
|
+
// Scoped to the resource group this install owns — the state file names
|
|
32973
|
+
// it (and the installer was handed the same one), so there is no
|
|
32974
|
+
// guessing between deployments in a shared subscription. Same rationale
|
|
32975
|
+
// as discoverGateway in bootstrap-finalize.ts.
|
|
32976
|
+
resourceGroup: state.resourceGroup
|
|
32831
32977
|
},
|
|
32832
32978
|
{ onWait: out }
|
|
32833
32979
|
);
|
|
@@ -33020,7 +33166,7 @@ var BootstrapSeedProfileCommand = class extends M8tCommand {
|
|
|
33020
33166
|
// src/commands/telemetry/enroll.ts
|
|
33021
33167
|
import * as fs37 from "fs";
|
|
33022
33168
|
import * as os21 from "os";
|
|
33023
|
-
import * as
|
|
33169
|
+
import * as path42 from "path";
|
|
33024
33170
|
import { Command as Command60, Option as Option57 } from "clipanion";
|
|
33025
33171
|
init_errors();
|
|
33026
33172
|
|
|
@@ -33148,8 +33294,8 @@ var TelemetryEnrollCommand = class extends M8tCommand {
|
|
|
33148
33294
|
...company ? { company } : {},
|
|
33149
33295
|
...contactEmail ? { contactEmail } : {}
|
|
33150
33296
|
});
|
|
33151
|
-
const keyDir = fs37.mkdtempSync(
|
|
33152
|
-
const keyFile =
|
|
33297
|
+
const keyDir = fs37.mkdtempSync(path42.join(os21.tmpdir(), "m8t-ingest-key-"));
|
|
33298
|
+
const keyFile = path42.join(keyDir, "key");
|
|
33153
33299
|
try {
|
|
33154
33300
|
fs37.writeFileSync(keyFile, ingestKey, { mode: 384 });
|
|
33155
33301
|
await runAz(["keyvault", "secret", "set", "--vault-name", kvName, "--name", INGEST_KEY_SECRET, "--file", keyFile, "--only-show-errors"]);
|