@m8t-stack/cli 0.2.11 → 0.2.12

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 CHANGED
@@ -1195,7 +1195,7 @@ var init_enable_hosted_brain = __esm({
1195
1195
  import { Builtins, Cli } from "clipanion";
1196
1196
 
1197
1197
  // src/lib/package-version.ts
1198
- var CLI_VERSION = "0.2.11";
1198
+ var CLI_VERSION = "0.2.12";
1199
1199
 
1200
1200
  // src/lib/render-error.ts
1201
1201
  init_errors();
@@ -15196,6 +15196,109 @@ init_errors();
15196
15196
  init_foundry_agent_get();
15197
15197
  import { randomBytes as randomBytes2, createHash } from "crypto";
15198
15198
 
15199
+ // src/lib/data-plane-ready.ts
15200
+ init_errors();
15201
+ async function awaitDataPlaneReady(opts) {
15202
+ const consecutive = opts.consecutive ?? 3;
15203
+ const attempts = opts.attempts ?? 60;
15204
+ const intervalMs = opts.intervalMs ?? 5e3;
15205
+ const sleep2 = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
15206
+ let streak = 0;
15207
+ for (let i = 1; i <= attempts; i++) {
15208
+ const r = await opts.probe();
15209
+ if (r.ok) {
15210
+ streak++;
15211
+ opts.onProgress?.(`data-plane ok (${streak.toString()}/${consecutive.toString()})`);
15212
+ if (streak >= consecutive) return { ready: true, attempts: i };
15213
+ } else {
15214
+ const cls = classifyFoundryError({ status: r.status, message: r.message ?? "" });
15215
+ const forcedRetryable = r.status !== void 0 && (opts.retryableStatuses?.includes(r.status) ?? false);
15216
+ if (!forcedRetryable && !cls.retryable) {
15217
+ throw new LocalCliError({
15218
+ code: "FOUNDRY_NOT_READY_FATAL",
15219
+ message: `Foundry data plane returned a non-retryable error: ${cls.message}`,
15220
+ hint: "This is not a transient data-plane delay \u2014 check `az login`/permissions and the endpoint.",
15221
+ retryable: false
15222
+ });
15223
+ }
15224
+ streak = 0;
15225
+ opts.onProgress?.(`data-plane not ready (${forcedRetryable ? `status ${(r.status ?? 0).toString()}` : cls.category}), waiting\u2026`);
15226
+ }
15227
+ if (i < attempts) await sleep2(intervalMs);
15228
+ }
15229
+ return { ready: false, attempts };
15230
+ }
15231
+
15232
+ // src/lib/foundry-ready-probe.ts
15233
+ init_http();
15234
+ var FOUNDRY_SCOPE3 = "https://ai.azure.com/.default";
15235
+ function makeAgentsProbe(credential2, endpoint) {
15236
+ return async () => {
15237
+ try {
15238
+ const r = await authedJsonResult({
15239
+ credential: credential2,
15240
+ scope: FOUNDRY_SCOPE3,
15241
+ method: "GET",
15242
+ url: `${endpoint}/agents?api-version=v1`,
15243
+ okStatuses: [404, 500, 502, 503]
15244
+ // don't throw — return the status so the loop classifies it
15245
+ });
15246
+ if (r.status === 200) return { ok: true, status: 200, message: "" };
15247
+ const body = r.data?.error?.message ?? "";
15248
+ return { ok: false, status: r.status, message: `${r.status.toString()} ${body}`.trim() };
15249
+ } catch (e) {
15250
+ return { ok: false, message: e instanceof Error ? e.message : String(e) };
15251
+ }
15252
+ };
15253
+ }
15254
+ function makeAgentProbe(credential2, endpoint, agentName) {
15255
+ return async () => {
15256
+ try {
15257
+ const r = await authedJsonResult({
15258
+ credential: credential2,
15259
+ scope: FOUNDRY_SCOPE3,
15260
+ method: "GET",
15261
+ url: `${endpoint}/agents/${agentName}?api-version=v1`,
15262
+ okStatuses: [404, 500, 502, 503]
15263
+ // don't throw — return the status so the loop classifies it
15264
+ });
15265
+ if (r.status === 200) return { ok: true, status: 200, message: "" };
15266
+ const body = r.data?.error?.message ?? "";
15267
+ return { ok: false, status: r.status, message: `${r.status.toString()} ${body}`.trim() };
15268
+ } catch (e) {
15269
+ return { ok: false, message: e instanceof Error ? e.message : String(e) };
15270
+ }
15271
+ };
15272
+ }
15273
+
15274
+ // src/lib/agent-ready.ts
15275
+ init_errors();
15276
+ async function awaitAgentQueryable(args) {
15277
+ const attemptsMax = args.attempts ?? 40;
15278
+ const intervalMs = args.intervalMs ?? 3e3;
15279
+ const probe = args.probe ?? makeAgentProbe(args.credential, args.projectEndpoint, args.agentName);
15280
+ const { ready, attempts } = await awaitDataPlaneReady({
15281
+ probe,
15282
+ consecutive: args.consecutive ?? 2,
15283
+ attempts: attemptsMax,
15284
+ intervalMs,
15285
+ sleep: args.sleep,
15286
+ onProgress: args.onProgress,
15287
+ retryableStatuses: [404]
15288
+ });
15289
+ if (!ready) {
15290
+ const approxSec = Math.round(attemptsMax * intervalMs / 1e3);
15291
+ throw new LocalCliError({
15292
+ code: "AGENT_NOT_QUERYABLE",
15293
+ message: `Agent '${args.agentName}' did not become queryable within ${attempts.toString()} probes (~${approxSec.toString()}s) after deploy.`,
15294
+ hint: "Foundry agent registration propagates asynchronously after deploy; a retry usually clears it. Re-run shortly (e.g. 'm8t bootstrap launch' or 'm8t a2a enable <name>').",
15295
+ category: "data_plane_not_ready",
15296
+ retryable: false
15297
+ });
15298
+ }
15299
+ return { attempts };
15300
+ }
15301
+
15199
15302
  // src/lib/persona-a2a.ts
15200
15303
  init_errors();
15201
15304
  init_esm();
@@ -15251,6 +15354,13 @@ async function enableA2a(args) {
15251
15354
  const connectionName = `a2a-${args.agentName}`;
15252
15355
  progress("Reading persona a2a-card\u2026");
15253
15356
  const { serialized: a2aCardJson } = readPersonaA2aCard(args.personaPath);
15357
+ progress("Waiting for the agent to become queryable\u2026");
15358
+ await awaitAgentQueryable({
15359
+ credential: args.credential,
15360
+ projectEndpoint: args.projectEndpoint,
15361
+ agentName: args.agentName,
15362
+ onProgress: args.onProgress
15363
+ });
15254
15364
  progress("Reading current agent definition\u2026");
15255
15365
  const current = await getAgentVersion({ credential: args.credential, projectEndpoint: args.projectEndpoint, agentName: args.agentName });
15256
15366
  if (current.definition.kind === "hosted") {
@@ -22147,62 +22257,6 @@ var FoundryCreateCommand = class extends M8tCommand {
22147
22257
  // src/commands/foundry/await-ready.ts
22148
22258
  import { Command as Command44, Option as Option42 } from "clipanion";
22149
22259
  import { AzureCliCredential as AzureCliCredential2 } from "@azure/identity";
22150
-
22151
- // src/lib/data-plane-ready.ts
22152
- init_errors();
22153
- async function awaitDataPlaneReady(opts) {
22154
- const consecutive = opts.consecutive ?? 3;
22155
- const attempts = opts.attempts ?? 60;
22156
- const intervalMs = opts.intervalMs ?? 5e3;
22157
- const sleep2 = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
22158
- let streak = 0;
22159
- for (let i = 1; i <= attempts; i++) {
22160
- const r = await opts.probe();
22161
- if (r.ok) {
22162
- streak++;
22163
- opts.onProgress?.(`data-plane ok (${streak.toString()}/${consecutive.toString()})`);
22164
- if (streak >= consecutive) return { ready: true, attempts: i };
22165
- } else {
22166
- const cls = classifyFoundryError({ status: r.status, message: r.message ?? "" });
22167
- if (!cls.retryable) {
22168
- throw new LocalCliError({
22169
- code: "FOUNDRY_NOT_READY_FATAL",
22170
- message: `Foundry data plane returned a non-retryable error: ${cls.message}`,
22171
- hint: "This is not a transient data-plane delay \u2014 check `az login`/permissions and the endpoint."
22172
- });
22173
- }
22174
- streak = 0;
22175
- opts.onProgress?.(`data-plane not ready (${cls.category}), waiting\u2026`);
22176
- }
22177
- if (i < attempts) await sleep2(intervalMs);
22178
- }
22179
- return { ready: false, attempts };
22180
- }
22181
-
22182
- // src/lib/foundry-ready-probe.ts
22183
- init_http();
22184
- var FOUNDRY_SCOPE3 = "https://ai.azure.com/.default";
22185
- function makeAgentsProbe(credential2, endpoint) {
22186
- return async () => {
22187
- try {
22188
- const r = await authedJsonResult({
22189
- credential: credential2,
22190
- scope: FOUNDRY_SCOPE3,
22191
- method: "GET",
22192
- url: `${endpoint}/agents?api-version=v1`,
22193
- okStatuses: [404, 500, 502, 503]
22194
- // don't throw — return the status so the loop classifies it
22195
- });
22196
- if (r.status === 200) return { ok: true, status: 200, message: "" };
22197
- const body = r.data?.error?.message ?? "";
22198
- return { ok: false, status: r.status, message: `${r.status.toString()} ${body}`.trim() };
22199
- } catch (e) {
22200
- return { ok: false, message: e instanceof Error ? e.message : String(e) };
22201
- }
22202
- };
22203
- }
22204
-
22205
- // src/commands/foundry/await-ready.ts
22206
22260
  init_errors();
22207
22261
  var FoundryAwaitReadyCommand = class extends M8tCommand {
22208
22262
  static paths = [["foundry", "await-ready"]];