@bike4mind/cli 3.0.0 → 3.1.0

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/README.md CHANGED
@@ -395,7 +395,7 @@ You can also run any MCP server via npx or custom executables:
395
395
 
396
396
  #### Serve Bike4Mind itself as an MCP server (`b4m mcp serve`)
397
397
 
398
- The reverse of adding a server: `b4m mcp serve` exposes your Bike4Mind backend to any MCP client (Claude Desktop, editors, other agents). It advertises eighteen tools (`list_notebooks`, `get_notebook`, `create_notebook`, `rename_notebook`, `clone_notebook`, `delete_notebook`, `list_projects`, `get_project`, `create_project`, `send_message`, `search_knowledge_base`, `list_lakes`, `list_files`, `get_file`, `generate_sound_effect`, `text_to_speech`, `generate_image`, `publish_artifact`) plus four resource templates (`b4m://notebook/{id}`, `b4m://file/{id}`, `b4m://project/{id}`, `b4m://artifact/{id}`), each listable and readable as JSON, and `b4m://agent-quest` - the credential-free manifest for The Open Door, the onboarding quest for agents.
398
+ The reverse of adding a server: `b4m mcp serve` exposes your Bike4Mind backend to any MCP client (Claude Desktop, editors, other agents). It advertises nineteen tools (`list_notebooks`, `get_notebook`, `create_notebook`, `rename_notebook`, `clone_notebook`, `delete_notebook`, `list_projects`, `get_project`, `create_project`, `send_message`, `search_knowledge_base`, `list_lakes`, `list_files`, `get_file`, `generate_sound_effect`, `text_to_speech`, `generate_image`, `create_artifact`, `publish_artifact`) plus four resource templates (`b4m://notebook/{id}`, `b4m://file/{id}`, `b4m://project/{id}`, `b4m://artifact/{id}`), each listable and readable as JSON, and `b4m://agent-quest` - the credential-free manifest for The Open Door, the onboarding quest for agents.
399
399
 
400
400
  To get answers grounded in a data lake, call `list_lakes`, then `create_notebook { dataLakeId }` with a lake's id, then `send_message { notebookId }` on that notebook: the result carries the `reply` plus the `citables` it was grounded in. `list_lakes` needs a key with `datalake:read` (and data lakes enabled on the instance).
401
401
 
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { Ct as secureParameters, F as ChatModels, H as LOCATION_MAP_LANGUAGE, Ht as WEBSITE_URL, J as OpenAIEmbeddingModel, K as NotFoundError, Nt as withRetry, O as ApiKeyType, Q as SEARCH_RESULT_CARDS_LANGUAGE, S as escapeArtifactBodyJson, Tt as splitEquals, Vt as APP_NAME, W as McpServerName, X as PermissionDeniedError, _ as logger, _t as isRetryableError, a as getToolCategory, at as assertAuthOriginMatchesApiKey, b as htmlErrorTitle, bt as obfuscateApiKey, dt as getMcpProviderMetadata, gt as isPlaceholderImageSigningSecret, i as canTrustTool, it as WORK_ITEM_STATUSES, j as BedrockEmbeddingModel, o as isReadOnlyTool, pt as googleMapsSearchUrl, q as OllamaEmbeddingModel, r as loadContextFiles, rt as VoyageAIEmbeddingModel, tt as SupportedFabFileMimeTypes, v as SESSION_ID_PATTERN, wt as signImageUrl, x as htmlFirstH1, y as isValidSessionId } from "./ConfigStore-51UaP9pJ.mjs";
2
+ import { $ as SEARCH_RESULT_CARDS_LANGUAGE, Et as splitEquals, F as ChatModels, G as McpServerName, Ht as APP_NAME, J as OllamaEmbeddingModel, O as ApiKeyType, Pt as withRetry, S as escapeArtifactBodyJson, Tt as signImageUrl, U as LOCATION_MAP_LANGUAGE, Ut as WEBSITE_URL, Y as OpenAIEmbeddingModel, Z as PermissionDeniedError, _ as logger, _t as isPlaceholderImageSigningSecret, a as getToolCategory, at as WORK_ITEM_STATUSES, b as htmlErrorTitle, ft as getMcpProviderMetadata, i as canTrustTool, it as VoyageAIEmbeddingModel, j as BedrockEmbeddingModel, mt as googleMapsSearchUrl, nt as SupportedFabFileMimeTypes, o as isReadOnlyTool, ot as assertAuthOriginMatchesApiKey, q as NotFoundError, r as loadContextFiles, v as SESSION_ID_PATTERN, vt as isRetryableError, wt as secureParameters, x as htmlFirstH1, xt as obfuscateApiKey, y as isValidSessionId } from "./ConfigStore-RHqyXcSS.mjs";
3
3
  import { n as isPathAllowed, t as assertPathAllowed } from "./pathValidation-BRqf4HFX-CHwtwp3O.mjs";
4
4
  import { n as isTerminalShellStatus, t as getShellSessionManager } from "./ShellSessionManager-6o8KZzl1-vrbPAUTq.mjs";
5
- import { n as B4mStreamEndedError, r as createClient, t as B4mApiError } from "./dist-BsG2Hlp-.mjs";
5
+ import { n as B4mStreamEndedError, r as createClient, t as B4mApiError } from "./dist-B1bGf-yn.mjs";
6
6
  import { createHash, randomBytes } from "crypto";
7
7
  import { existsSync, lstatSync, promises, readdirSync, realpathSync, rmSync, statSync } from "fs";
8
8
  import os, { homedir } from "os";
@@ -11361,6 +11361,10 @@ function observationForResult(result) {
11361
11361
  if (message.toLowerCase().includes("aborted")) return CANCELLED_TOOL_RESULT;
11362
11362
  return `Error: ${message}`;
11363
11363
  }
11364
+ /** True when `observationForResult` reported a real tool failure (not a cancellation). */
11365
+ function isFailedResult(result) {
11366
+ return result?.status === "rejected" && observationForResult(result) !== CANCELLED_TOOL_RESULT;
11367
+ }
11364
11368
  /**
11365
11369
  * True when an error is an abort/cancellation (user stop or execution timeout)
11366
11370
  * rather than a real failure. Aborts are benign and must NOT be logged at error
@@ -11411,6 +11415,10 @@ var ReActAgent = class extends EventEmitter {
11411
11415
  confidenceLog = [];
11412
11416
  /** Confidence scores collected during the current iteration (reset each iteration) */
11413
11417
  iterationConfidences = [];
11418
+ /** Parallel to `iterationConfidences`: whether that score came from a failed tool call */
11419
+ iterationToolFailed = [];
11420
+ /** Ids of calls `executeToolWithQueueFallback` saw fail; drained by `takeToolFailure`. */
11421
+ failedToolCallIds = /* @__PURE__ */ new Set();
11414
11422
  /** Conversation history, promoted from run()-local to instance for checkpoint/resume */
11415
11423
  messages = [];
11416
11424
  /** Current iteration count, promoted from run()-local to instance for checkpoint/resume */
@@ -11523,7 +11531,7 @@ var ReActAgent = class extends EventEmitter {
11523
11531
  this.turnUsage = [];
11524
11532
  this.toolCallCount = 0;
11525
11533
  this.confidenceLog = [];
11526
- this.iterationConfidences = [];
11534
+ this.resetIterationConfidences();
11527
11535
  this.lastStopReason = void 0;
11528
11536
  this.repeatedCallGuard.reset();
11529
11537
  this.isReadOnlyToolFn = options.isReadOnlyTool ?? defaultIsReadOnlyTool;
@@ -11681,9 +11689,10 @@ var ReActAgent = class extends EventEmitter {
11681
11689
  const plan = categorizeTools(unprocessedTools, options.isReadOnlyTool ?? defaultIsReadOnlyTool);
11682
11690
  const results = await this.runToolBatchAbortTolerant(plan, options.signal);
11683
11691
  for (const toolUse of unprocessedTools) {
11684
- const observation = observationForResult(results.get(getToolId(toolUse)));
11692
+ const result = results.get(getToolId(toolUse));
11693
+ const observation = observationForResult(result);
11685
11694
  this.appendToolMessages(messages, toolUse, observation, thinkingBlocks);
11686
- this.emitObservationStep(toolUse.name, observation);
11695
+ this.emitObservationStep(toolUse.name, observation, isFailedResult(result) || this.takeToolFailure(toolUse));
11687
11696
  }
11688
11697
  } else for (const toolUse of unprocessedTools) {
11689
11698
  this.emitActionStep(toolUse);
@@ -11698,7 +11707,7 @@ var ReActAgent = class extends EventEmitter {
11698
11707
  observation = await this.executeToolWithQueueFallback(toolUse);
11699
11708
  this.appendToolMessages(messages, toolUse, observation, thinkingBlocks);
11700
11709
  }
11701
- this.emitObservationStep(toolUse.name, observation);
11710
+ this.emitObservationStep(toolUse.name, observation, this.takeToolFailure(toolUse));
11702
11711
  }
11703
11712
  }
11704
11713
  }
@@ -11775,7 +11784,7 @@ var ReActAgent = class extends EventEmitter {
11775
11784
  iteration: iterations
11776
11785
  });
11777
11786
  }
11778
- this.iterationConfidences = [];
11787
+ this.resetIterationConfidences();
11779
11788
  if (!iterationComplete && hadToolCalls) {
11780
11789
  const feedback = await drainHostFeedback(options.drainFeedback, "turn", this.context.logger);
11781
11790
  messages.push({
@@ -12087,6 +12096,7 @@ Remember: You are an autonomous AGENT. Act independently and solve problems proa
12087
12096
  this.toolCallCount = checkpoint.toolCallCount;
12088
12097
  this.confidenceLog = structuredClone(checkpoint.confidenceLog);
12089
12098
  this.iterationConfidences = [...checkpoint.iterationConfidences];
12099
+ this.iterationToolFailed = checkpoint.iterationConfidences.map(() => false);
12090
12100
  this.initialMessageCount = checkpoint.initialMessageCount ?? this.messages.length;
12091
12101
  this.lastStopReason = checkpoint.finishReason;
12092
12102
  this.observationQueue = [];
@@ -12139,7 +12149,8 @@ Remember: You are an autonomous AGENT. Act independently and solve problems proa
12139
12149
  this.turnUsage = [];
12140
12150
  this.toolCallCount = 0;
12141
12151
  this.confidenceLog = [];
12142
- this.iterationConfidences = [];
12152
+ this.resetIterationConfidences();
12153
+ this.failedToolCallIds.clear();
12143
12154
  this.lastStopReason = void 0;
12144
12155
  this.iterations = 0;
12145
12156
  this.repeatedCallGuard.reset();
@@ -12197,7 +12208,7 @@ Remember: You are an autonomous AGENT. Act independently and solve problems proa
12197
12208
  }
12198
12209
  const preIterationCheckpoint = this.toCheckpoint();
12199
12210
  this.iterations++;
12200
- this.iterationConfidences = [];
12211
+ this.resetIterationConfidences();
12201
12212
  const iterationSteps = [];
12202
12213
  try {
12203
12214
  if (this.iterations > 1 && options.iterationDelayMs && options.iterationDelayMs > 0) await new Promise((resolve) => setTimeout(resolve, options.iterationDelayMs));
@@ -12320,9 +12331,10 @@ Remember: You are an autonomous AGENT. Act independently and solve problems proa
12320
12331
  this.appendToolMessages(this.messages, toolUse, GATED_TOOL_OBSERVATION, thinkingBlocks);
12321
12332
  continue;
12322
12333
  }
12323
- const observation = observationForResult(results.get(getToolId(toolUse)));
12334
+ const result = results.get(getToolId(toolUse));
12335
+ const observation = observationForResult(result);
12324
12336
  this.appendToolMessages(this.messages, toolUse, observation, thinkingBlocks);
12325
- const obsStep = this.buildObservationStep(toolUse.name, observation);
12337
+ const obsStep = this.buildObservationStep(toolUse.name, observation, isFailedResult(result) || this.takeToolFailure(toolUse));
12326
12338
  iterationSteps.push(obsStep);
12327
12339
  }
12328
12340
  } else for (const toolUse of unprocessedTools) {
@@ -12345,7 +12357,7 @@ Remember: You are an autonomous AGENT. Act independently and solve problems proa
12345
12357
  observation = await this.executeToolWithQueueFallback(toolUse);
12346
12358
  this.appendToolMessages(this.messages, toolUse, observation, thinkingBlocks);
12347
12359
  }
12348
- const obsStep = this.buildObservationStep(toolUse.name, observation);
12360
+ const obsStep = this.buildObservationStep(toolUse.name, observation, this.takeToolFailure(toolUse));
12349
12361
  iterationSteps.push(obsStep);
12350
12362
  }
12351
12363
  }
@@ -12410,7 +12422,7 @@ Remember: You are an autonomous AGENT. Act independently and solve problems proa
12410
12422
  iteration: this.iterations
12411
12423
  });
12412
12424
  }
12413
- this.iterationConfidences = [];
12425
+ this.resetIterationConfidences();
12414
12426
  if (!iterationComplete && hadToolCalls) {
12415
12427
  const feedback = await drainHostFeedback(options.drainFeedback, "turn", this.context.logger);
12416
12428
  this.messages.push({
@@ -12543,7 +12555,7 @@ Remember: You are an autonomous AGENT. Act independently and solve problems proa
12543
12555
  * Build an observation step, score confidence, push to steps, and emit.
12544
12556
  * Returns the step for callers that need to collect iteration steps.
12545
12557
  */
12546
- buildObservationStep(toolName, observation) {
12558
+ buildObservationStep(toolName, observation, toolFailed = false) {
12547
12559
  const confidence = this.scoreToolResult(toolName, observation);
12548
12560
  const confidenceSource = observation.startsWith("Error:") ? "deterministic" : "default";
12549
12561
  this.confidenceLog.push({
@@ -12553,6 +12565,7 @@ Remember: You are an autonomous AGENT. Act independently and solve problems proa
12553
12565
  timestamp: Date.now()
12554
12566
  });
12555
12567
  this.iterationConfidences.push(confidence);
12568
+ this.iterationToolFailed.push(toolFailed);
12556
12569
  const observationStep = {
12557
12570
  type: "observation",
12558
12571
  content: observation,
@@ -12561,7 +12574,8 @@ Remember: You are an autonomous AGENT. Act independently and solve problems proa
12561
12574
  timestamp: Date.now(),
12562
12575
  iteration: this.iterations - 1,
12563
12576
  confidence,
12564
- confidenceSource
12577
+ confidenceSource,
12578
+ ...toolFailed ? { toolFailed: true } : {}
12565
12579
  }
12566
12580
  };
12567
12581
  this.steps.push(observationStep);
@@ -12571,8 +12585,8 @@ Remember: You are an autonomous AGENT. Act independently and solve problems proa
12571
12585
  /**
12572
12586
  * Create and emit an observation step, scoring confidence for the result
12573
12587
  */
12574
- emitObservationStep(toolName, observation) {
12575
- this.buildObservationStep(toolName, observation);
12588
+ emitObservationStep(toolName, observation, toolFailed = false) {
12589
+ this.buildObservationStep(toolName, observation, toolFailed);
12576
12590
  }
12577
12591
  /**
12578
12592
  * Score the confidence of a tool result.
@@ -12643,13 +12657,14 @@ Remember: You are an autonomous AGENT. Act independently and solve problems proa
12643
12657
  */
12644
12658
  async executeGatedToolCall(call) {
12645
12659
  if (!this.supportsGatedReplay()) throw new Error(`ReActAgent.executeGatedToolCall: backend (${this.context.llm.currentModel}) cannot record a replayed tool result, so an approval-gated tool cannot be run on it`);
12646
- const observation = await this.executeToolWithQueueFallback({
12660
+ const toolUse = {
12647
12661
  id: call.id,
12648
12662
  name: call.name,
12649
12663
  arguments: typeof call.input === "string" || call.input === void 0 ? call.input : JSON.stringify(call.input)
12650
- });
12664
+ };
12665
+ const observation = await this.executeToolWithQueueFallback(toolUse);
12651
12666
  this.replaceLastToolResultObservation(call.id, observation);
12652
- this.buildObservationStep(call.name, observation);
12667
+ this.buildObservationStep(call.name, observation, this.takeToolFailure(toolUse));
12653
12668
  return observation;
12654
12669
  }
12655
12670
  /**
@@ -12664,15 +12679,27 @@ Remember: You are an autonomous AGENT. Act independently and solve problems proa
12664
12679
  * `iterationConfidences` at its own start regardless, discarding the score
12665
12680
  * before anything reads it. The host calls this right after replaying an
12666
12681
  * approved batch (see `resumeApprovedPause` / `gateReplayConfidence`) so a
12667
- * replayed tool that failed still gets the same low-confidence pause a normal
12668
- * iteration would have gotten - resetting `iterationConfidences` here is a
12669
- * no-op for the next `runIteration()`, which resets it again anyway.
12682
+ * replayed tool gets the same low-confidence pause a normal iteration would
12683
+ * have gotten - resetting `iterationConfidences` here is a no-op for the next
12684
+ * `runIteration()`, which resets it again anyway.
12685
+ *
12686
+ * Scores from calls that failed to run (`toolFailed`) are left out, matching the
12687
+ * web executor's iteration gate (`evaluateConfidenceGate`); `null` when every
12688
+ * scored call failed.
12670
12689
  */
12671
12690
  takeIterationConfidence() {
12672
- if (this.iterationConfidences.length === 0) return null;
12673
- const avg = this.iterationConfidences.reduce((a, b) => a + b, 0) / this.iterationConfidences.length;
12691
+ const scores = this.iterationConfidences.filter((_, i) => !this.iterationToolFailed[i]);
12692
+ this.resetIterationConfidences();
12693
+ if (scores.length === 0) return null;
12694
+ return scores.reduce((a, b) => a + b, 0) / scores.length;
12695
+ }
12696
+ resetIterationConfidences() {
12674
12697
  this.iterationConfidences = [];
12675
- return avg;
12698
+ this.iterationToolFailed = [];
12699
+ }
12700
+ /** True (once) when `executeToolWithQueueFallback` recorded this call as failed. */
12701
+ takeToolFailure(toolUse) {
12702
+ return this.failedToolCallIds.delete(getToolId(toolUse));
12676
12703
  }
12677
12704
  /**
12678
12705
  * Execute a tool and return the result as a string.
@@ -12699,6 +12726,7 @@ Remember: You are an autonomous AGENT. Act independently and solve problems proa
12699
12726
  })}</function>`;
12700
12727
  }
12701
12728
  }
12729
+ this.failedToolCallIds.add(getToolId(toolUse));
12702
12730
  return `Error: Tool "${toolUse.name}" is not available in this context and cannot be called. Do NOT attempt to call it again. Proceed without it — call other available tools if your plan still needs them, or compose your final answer from the information already gathered if no more tools are needed.`;
12703
12731
  }
12704
12732
  const signature = RepeatedCallGuard.signature(toolUse.name, toolUse.arguments);
@@ -12716,6 +12744,7 @@ Remember: You are an autonomous AGENT. Act independently and solve problems proa
12716
12744
  } catch (error) {
12717
12745
  observation = `Error: ${error instanceof Error ? error.message : String(error)}`;
12718
12746
  succeeded = false;
12747
+ this.failedToolCallIds.add(getToolId(toolUse));
12719
12748
  }
12720
12749
  const { count, warn } = this.repeatedCallGuard.record(signature, observation, isReadOnly);
12721
12750
  if (succeeded && !isReadOnly) this.repeatedCallGuard.invalidateReadOnly();
@@ -269,6 +269,7 @@ var PermissionDeniedError = class extends Error {
269
269
  };
270
270
  const UNKNOWN_MODEL_ERROR_CODE = "unknown_model";
271
271
  const BILLING_ORGANIZATION_MISMATCH_ERROR_CODE = "billing_organization_mismatch";
272
+ const REQUEST_TIMEOUT_ERROR_CODE = "request_timeout";
272
273
  const GROUP_TYPE_CATALOG = Object.freeze([
273
274
  {
274
275
  key: "sales",
@@ -777,6 +778,20 @@ const shareableDocumentSchema = z$1.object({
777
778
  users: z$1.array(userShareSchema),
778
779
  groups: z$1.array(groupShareSchema)
779
780
  });
781
+ /** Bedrock's `[<scope>.]anthropic.` id prefix (any region or `global`), as regex source. Shared with isClaudeModelId. */
782
+ const BEDROCK_ANTHROPIC_PREFIX = "(?:(?:[a-z-]+\\.)?anthropic\\.)?";
783
+ const CLAUDE_MODEL_ID = new RegExp(`^${BEDROCK_ANTHROPIC_PREFIX}claude-(opus|sonnet|haiku|fable|mythos)-(\\d+)(?:-(\\d{1,2}))?(?=$|[:@[]|-(?:\\d{8}(?!\\d)|[a-z]))`);
784
+ /** Family and version of a Claude id (native, Bedrock-scoped, dated or aliased); null for any other shape. */
785
+ function parseClaudeModelId(modelId) {
786
+ const match = CLAUDE_MODEL_ID.exec(modelId);
787
+ if (!match) return null;
788
+ const [, family, major, minor] = match;
789
+ return {
790
+ family,
791
+ major: Number(major),
792
+ minor: minor === void 0 ? null : Number(minor)
793
+ };
794
+ }
780
795
  /**
781
796
  * Model backends
782
797
  */
@@ -1032,6 +1047,7 @@ let ChatModels = /* @__PURE__ */ function(ChatModels) {
1032
1047
  }({});
1033
1048
  const CHAT_MODELS = Object.values(ChatModels);
1034
1049
  const supportedChatModels = z$1.enum(ChatModels);
1050
+ new RegExp(`^${BEDROCK_ANTHROPIC_PREFIX}claude-`);
1035
1051
  /**
1036
1052
  * Models that support OpenAI's `reasoning_effort` request parameter.
1037
1053
  * o1-preview and o1-mini do NOT support reasoning_effort.
@@ -3126,8 +3142,22 @@ z.object({
3126
3142
  /** Set for job-backed generations; the save is idempotent per job. */
3127
3143
  jobId: z.string().optional(),
3128
3144
  prompt: z.string(),
3145
+ /**
3146
+ * Storing caps `prompt` at a prefix of what was generated (sourceMetadata rides every metadata-only
3147
+ * listing). Written on every save, true when it was cut. Absent only on files saved before it existed:
3148
+ * read it through isStoredPromptPossiblyTruncated, which covers those.
3149
+ */
3150
+ promptTruncated: z.boolean().optional(),
3129
3151
  lyrics: z.string().optional(),
3130
- durationSeconds: z.number().positive().optional()
3152
+ durationSeconds: z.number().positive().optional(),
3153
+ /** Speech: the requested voice; absent when the provider default was used or another provider stood in. */
3154
+ voice: z.string().optional(),
3155
+ /** Speech: the output format. */
3156
+ format: z.string().optional(),
3157
+ /** Speech: the requested language; absent when the provider auto-detected it. */
3158
+ languageCode: z.string().optional(),
3159
+ /** Sound effects: how closely the provider followed the prompt, 0-1. */
3160
+ promptInfluence: z.number().min(0).max(1).optional()
3131
3161
  });
3132
3162
  /**
3133
3163
  * Why a generated file was not kept in the user's files. Never fatal: the output was already produced and
@@ -5016,6 +5046,17 @@ const ApiErrorSchema = z$1.object({
5016
5046
  */
5017
5047
  const InsufficientCreditsErrorSchema = ApiErrorSchema.extend({ errorCode: z$1.enum(QUEST_ERROR_CODES).optional() });
5018
5048
  /**
5049
+ * 504 for a `wait: true` turn that ran past the request deadline. The turn is already settled
5050
+ * (timed out, unused credits refunded) when this is sent; `quest_id` is the quest to poll and
5051
+ * `sessionId` is the notebook the turn was recorded in, so a caller that sent no `sessionId` can
5052
+ * continue the conversation it just started (same field name as the ACK and the `wait: true` body).
5053
+ */
5054
+ const ChatWaitTimeoutErrorSchema = ApiErrorSchema.extend({
5055
+ errorCode: z$1.literal(REQUEST_TIMEOUT_ERROR_CODE),
5056
+ quest_id: z$1.string(),
5057
+ sessionId: z$1.string().optional()
5058
+ });
5059
+ /**
5019
5060
  * 400 for an upload refused on size or quota. The typed members are optional because the same 400 also
5020
5061
  * covers errors that carry none (an unsupported file type); when `errorCode` is present all five arrive
5021
5062
  * together, which the endpoint's 400 description states for integrators.
@@ -5205,6 +5246,16 @@ const MUSIC_VALIDATION_ERROR_CODES = [
5205
5246
  "lyrics_with_instrumental",
5206
5247
  "lyrics_too_long"
5207
5248
  ];
5249
+ /**
5250
+ * Building blocks for entity response schemas held to an entity's key list (see
5251
+ * selfUserResponseSchema in ./user.ts for the full rationale). A passthrough value is
5252
+ * `z.unknown()`: the boundary enforces WHICH keys leave the server, not their types, so a
5253
+ * legacy value on a long-lived Mongo document can never 500 a read.
5254
+ */
5255
+ const passthroughField = z$2.unknown().optional();
5256
+ function passthroughShape(fields) {
5257
+ return Object.fromEntries(Object.keys(fields).map((field) => [field, passthroughField]));
5258
+ }
5208
5259
  z$2.enum([
5209
5260
  "",
5210
5261
  "TFG",
@@ -5352,10 +5403,6 @@ const SELF_VIEW_PASSTHROUGH_FIELDS = {
5352
5403
  currentCredits: true,
5353
5404
  lastCreditsPurchasedAt: true
5354
5405
  };
5355
- const passthroughField = z$2.unknown().optional();
5356
- function passthroughShape(fields) {
5357
- return Object.fromEntries(Object.keys(fields).map((field) => [field, passthroughField]));
5358
- }
5359
5406
  /** A redacted integration object: only the named non-secret subfields survive. */
5360
5407
  function redactedSubdocument(fields) {
5361
5408
  return z$2.object(passthroughShape(Object.fromEntries(fields.map((field) => [field, true])))).nullable().optional();
@@ -12860,7 +12907,12 @@ const AgentProgressAction = z$1.object({
12860
12907
  executionId: z$1.string(),
12861
12908
  status: z$1.string().optional(),
12862
12909
  creditsUsed: z$1.number().optional(),
12863
- iteration: z$1.number().optional()
12910
+ iteration: z$1.number().optional(),
12911
+ questId: z$1.string().optional(),
12912
+ generationJobs: z$1.array(z$1.object({
12913
+ id: z$1.string(),
12914
+ kind: z$1.enum(GENERATION_JOB_KINDS)
12915
+ })).optional()
12864
12916
  });
12865
12917
  const AgentCompletedAction = z$1.object({
12866
12918
  action: z$1.literal("completed"),
@@ -14808,6 +14860,89 @@ const CreateSessionRequestSchema = z$1.object({
14808
14860
  tags: z$1.array(SessionTagSchema).optional(),
14809
14861
  lastUsedModel: z$1.string().nullish()
14810
14862
  });
14863
+ z$2.object(passthroughShape({
14864
+ id: true,
14865
+ createdAt: true,
14866
+ updatedAt: true,
14867
+ name: true,
14868
+ description: true,
14869
+ type: true,
14870
+ organizationId: true
14871
+ })).extend({
14872
+ memberIds: z$2.array(z$2.string()),
14873
+ memberCount: z$2.number()
14874
+ });
14875
+ z$2.object(passthroughShape({
14876
+ id: true,
14877
+ createdAt: true,
14878
+ updatedAt: true,
14879
+ deletedAt: true,
14880
+ sessionId: true,
14881
+ conversationItemId: true,
14882
+ openaiMessageId: true,
14883
+ claudeMessageId: true,
14884
+ type: true,
14885
+ timestamp: true,
14886
+ prompt: true,
14887
+ fabFileIds: true,
14888
+ agentIds: true,
14889
+ reply: true,
14890
+ replies: true,
14891
+ structuredReplies: true,
14892
+ toolResults: true,
14893
+ questMasterReply: true,
14894
+ images: true,
14895
+ videos: true,
14896
+ videoJobIds: true,
14897
+ generationJobs: true,
14898
+ agentVideoClipsClaimed: true,
14899
+ agentMusicTracksClaimed: true,
14900
+ oob: true,
14901
+ promptMeta: true,
14902
+ status: true,
14903
+ creditsUsed: true,
14904
+ errorCode: true,
14905
+ questMasterPlanId: true,
14906
+ agentExecutionId: true,
14907
+ correctsQuestId: true,
14908
+ clientFirstTokenTime: true,
14909
+ routingSource: true,
14910
+ pinned: true,
14911
+ researchModeResults: true,
14912
+ deepResearchState: true,
14913
+ fallbackInfo: true,
14914
+ promptEnhancement: true,
14915
+ pendingAction: true,
14916
+ attachmentNotices: true,
14917
+ attachmentDelivery: true,
14918
+ navigationIntents: true,
14919
+ suggestedChoices: true,
14920
+ attachmentList: true,
14921
+ uiSideEffects: true,
14922
+ jupyterNotebook: true
14923
+ }));
14924
+ const questMasterPlanResponseSchema = z$2.object(passthroughShape({
14925
+ id: true,
14926
+ createdAt: true,
14927
+ updatedAt: true,
14928
+ notebookId: true,
14929
+ goal: true,
14930
+ quests: true,
14931
+ userId: true,
14932
+ visibility: true,
14933
+ state: true,
14934
+ lastAccessedAt: true,
14935
+ sessionHistory: true,
14936
+ metrics: true,
14937
+ tags: true,
14938
+ priority: true,
14939
+ parentPlanId: true,
14940
+ sharedWith: true,
14941
+ handoff: true,
14942
+ blockers: true,
14943
+ decisions: true
14944
+ }));
14945
+ z$2.array(questMasterPlanResponseSchema);
14811
14946
  z$1.preprocess((val) => {
14812
14947
  if (typeof val === "string") {
14813
14948
  if (val.toLowerCase() === "true") return true;
@@ -16832,7 +16967,7 @@ defineEndpoint({
16832
16967
  path: "/api/chat",
16833
16968
  operationId: "sendChatMessage",
16834
16969
  summary: "Send a chat message",
16835
- description: "Sends a message to the AI and creates a quest to process it. By default (async) the call returns immediately with a quest id; poll `GET /api/v1/quests/{id}` for the reply. Send `wait: true` to block until the reply is ready and receive it inline. A tool that produced machine-readable state reports it under `toolPayloads` - an array of `{ type, payload }` entries in emission order, alongside (never instead of) the prose reply - on the `wait: true` body and on the polled quest. A turn can FAIL after the ACK - reported on the polled quest as `type: \"error\"`, since the ACK was already sent. A terminal `status: \"stopped\"` (a missing session, a user-cancelled turn) is ALSO a failure even without `type: \"error\"` - it carries an explanatory string in `reply`/`replies` rather than an answer. `type` is the failure signal for the classified failure classes (an abort, a provider timeout, credit exhaustion); `errorCode` is an optional refinement present only when the failure is a classified billing reason. A recovered stuck quest is NOT in that list: one that still has renderable content resolves as a success by design. `QUEST_ERROR_CODES` has two members, but only `insufficient_credits` is raised as a quest errorCode by any current throw site on this endpoint - `spend_cap_exceeded` is thrown only by the embed chat route's pre-flight, which fires outside the process try/catch that would classify it onto a quest. A caller must treat `type: \"error\"` OR a terminal `status: \"stopped\"` as failure even when `errorCode` is absent, and must not read `reply` as an answer without checking those first. Authenticate with an API key (`b4m_live_`) or a JWT. Session resolution: pass `sessionId` to continue an existing notebook. An API-key caller that omits it gets a BRAND-NEW notebook rather than the notebook the human last had open, and `newConversation: true` forces a new notebook for any auth mode; both return the new id as `sessionId`, so the caller can continue the conversation by passing it back. A first-party JWT caller that omits `sessionId` keeps the last-opened-notebook fallback. Sending `sessionId` and `newConversation` together is a 422.",
16970
+ description: "Sends a message to the AI and creates a quest to process it. By default (async) the call returns immediately with a quest id; poll `GET /api/v1/quests/{id}` for the reply. Send `wait: true` to block until the reply is ready and receive it inline. A `wait: true` turn is bounded at about 45 seconds: one that runs longer is ended (unused credits refunded) and answered with a 504 naming the quest in `quest_id`. Send long or tool-heavy turns (large attachments, tool calls) in the default async mode and poll instead. A tool that produced machine-readable state reports it under `toolPayloads` - an array of `{ type, payload }` entries in emission order, alongside (never instead of) the prose reply - on the `wait: true` body and on the polled quest. A turn can FAIL after the ACK - reported on the polled quest as `type: \"error\"`, since the ACK was already sent. A terminal `status: \"stopped\"` (a missing session, a user-cancelled turn) is ALSO a failure even without `type: \"error\"` - it carries an explanatory string in `reply`/`replies` rather than an answer. `type` is the failure signal for the classified failure classes (an abort, a provider timeout, credit exhaustion); `errorCode` is an optional refinement present only when the failure is a classified billing reason. A recovered stuck quest is NOT in that list: one that still has renderable content resolves as a success by design. `QUEST_ERROR_CODES` has two members, but only `insufficient_credits` is raised as a quest errorCode by any current throw site on this endpoint - `spend_cap_exceeded` is thrown only by the embed chat route's pre-flight, which fires outside the process try/catch that would classify it onto a quest. A caller must treat `type: \"error\"` OR a terminal `status: \"stopped\"` as failure even when `errorCode` is absent, and must not read `reply` as an answer without checking those first. Authenticate with an API key (`b4m_live_`) or a JWT. Session resolution: pass `sessionId` to continue an existing notebook. An API-key caller that omits it gets a BRAND-NEW notebook rather than the notebook the human last had open, and `newConversation: true` forces a new notebook for any auth mode; both return the new id as `sessionId`, so the caller can continue the conversation by passing it back. A first-party JWT caller that omits `sessionId` keeps the last-opened-notebook fallback. Sending `sessionId` and `newConversation` together is a 422.",
16836
16971
  tags: ["AI"],
16837
16972
  auth: "apiKeyOrJwt",
16838
16973
  scopes: ["ai:chat", "ai:generate"],
@@ -16873,6 +17008,10 @@ defineEndpoint({
16873
17008
  429: {
16874
17009
  description: "Per-user rate limit exceeded.",
16875
17010
  schema: ApiErrorSchema
17011
+ },
17012
+ 504: {
17013
+ description: "A `wait: true` turn ran past the request deadline. The turn is already ended: its quest (`quest_id`) is settled as timed out with any partial reply kept, and unused reserved credits are refunded. Retry in async mode for a long turn.",
17014
+ schema: ChatWaitTimeoutErrorSchema
16876
17015
  }
16877
17016
  },
16878
17017
  codeSample: {
@@ -21244,7 +21383,11 @@ function stripDeliveredArtifactBlocks(text, deliveredMarkup) {
21244
21383
  */
21245
21384
  const CLAUDE_4_7_PLUS_MULTIPLIER = 1.5;
21246
21385
  const CLAUDE_4_5_MULTIPLIER = 1.09;
21247
- const CLAUDE_FAMILY_VERSION = /(?:^|\.)claude-(?:opus|sonnet|haiku)-(\d+)(?:-(\d{1,2}))?(?=$|[-:])/;
21386
+ const MEASURED_FAMILIES = /* @__PURE__ */ new Set([
21387
+ "opus",
21388
+ "sonnet",
21389
+ "haiku"
21390
+ ]);
21248
21391
  /**
21249
21392
  * Factor to scale a cl100k_base token count by for `modelId`. 1 for anything unmeasured: non-Claude
21250
21393
  * models, Claude before 4.5 (retired on Bedrock, could not be measured), and Fable (Bedrock rejects it
@@ -21252,10 +21395,10 @@ const CLAUDE_FAMILY_VERSION = /(?:^|\.)claude-(?:opus|sonnet|haiku)-(\d+)(?:-(\d
21252
21395
  * assumption they keep its tokenizer; [BILLING_DRIFT] flags it if one does not.
21253
21396
  */
21254
21397
  function tokenEstimateMultiplier(modelId) {
21255
- const match = modelId?.match(CLAUDE_FAMILY_VERSION);
21256
- if (!match) return 1;
21257
- const major = Number(match[1]);
21258
- const minor = Number(match[2] ?? 0);
21398
+ const parsed = modelId ? parseClaudeModelId(modelId) : null;
21399
+ if (!parsed || !MEASURED_FAMILIES.has(parsed.family)) return 1;
21400
+ const { major } = parsed;
21401
+ const minor = parsed.minor ?? 0;
21259
21402
  if (major > 4 || major === 4 && minor >= 7) return CLAUDE_4_7_PLUS_MULTIPLIER;
21260
21403
  if (major === 4 && minor >= 5) return CLAUDE_4_5_MULTIPLIER;
21261
21404
  return 1;
@@ -25172,4 +25315,4 @@ var ConfigStore = class {
25172
25315
  }
25173
25316
  };
25174
25317
  //#endregion
25175
- export { SLUG_OWNED_BY_OTHER as $, BRIEFCASE_CATALOG_QUERIES as A, ttsBase64ResponseSchema as At, ImageModels as B, selfClaimedActorKindSchema as Bt, AGENT_QUEST_ID as C, secureParameters as Ct, ARTIFACT_REMOVED_PLACEHOLDER as D, stripToolArtifactMarkup as Dt, ARTIFACT_DELIVERED_PLACEHOLDER as E, stripDeliveredArtifactBlocks as Et, ChatModels as F, DELEGATION_PAYLOAD_SCHEMA_NAME as Ft, ModelBackend as G, LOCATION_MAP_LANGUAGE as H, WEBSITE_URL as Ht, CompletionReasoningEffortSchema as I, actorColorIndex as It, OpenAIEmbeddingModel as J, NotFoundError as K, DEFAULT_TTS_PROVIDER as L, actorKindMarker as Lt, BriefcasePromptIdSchema as M, ttsResponseTooLargeSchema as Mt, CONTEXT_WINDOW_SAFETY_BUFFER_TOKENS as N, withRetry as Nt, ApiKeyType as O, supportedVoiceGenerationVendor as Ot, CREDIT_DEDUCT_TRANSACTION_TYPES as P, ACTOR_COLOR_SLOTS as Pt, SEARCH_RESULT_CARDS_LANGUAGE as Q, DEGENERATE_FINISH_REASON as R, actorKindSchema as Rt, escapeArtifactBodyJson as S, replacePromptVariables as St, AGENT_QUEST_MCP_URI as T, splitEquals as Tt, MODEL_INFO_FIELD_GROUP_OF as U, ImagePromptResolutionSchema as V, APP_NAME as Vt, McpServerName as W, PermissionDeniedError as X, PROMPT_TEXT_MAX as Y, REVIEW_GATE_STATUS_VALUES as Z, logger as _, isRetryableError as _t, getToolCategory as a, assertAuthOriginMatchesApiKey as at, htmlErrorTitle as b, obfuscateApiKey as bt, getCreditsUrl as c, escapeThinkMarkers as ct, resolveApiEndpoint as d, getMcpProviderMetadata as dt, SUBQUEST_STATUS_VALUES as et, AuthenticatedApiClient as f, getQuestErrorCode as ft, parseApiUrl as g, isPlaceholderImageSigningSecret as gt, NotAuthenticatedError as h, isEarlyStop as ht, canTrustTool as i, WORK_ITEM_STATUSES as it, BedrockEmbeddingModel as j, ttsRequestSchema as jt, ArtifactTypeSchema as k, tokenEstimateMultiplier as kt, getEnvironmentName as l, filterToolArtifactMarkup as lt, LOCAL_DEV_URL as m, hasDeliverablePinnedArtifact as mt, extractCompactInstructions as n, VisibilitySchema as nt, isReadOnlyTool as o, buildPromptContext as ot, DeviceFlowClient as p, googleMapsSearchUrl as pt, OllamaEmbeddingModel as q, loadContextFiles as r, VoyageAIEmbeddingModel as rt, ApiEndpointUnconfiguredError as s, createThinkMarkerEscaper as st, ConfigStore as t, SupportedFabFileMimeTypes as tt, requireApiUrl as u, generatedAudioResponseSchema as ut, SESSION_ID_PATTERN as v, isUserInitiatedAbort as vt, AGENT_QUEST_MANIFEST as w, signImageUrl as wt, htmlFirstH1 as x, questReplyText as xt, isValidSessionId as y, joinReplySlots as yt, GENERATED_IMAGE_EXTENSION_RE as z, delegationPayloadSchema as zt };
25318
+ export { SEARCH_RESULT_CARDS_LANGUAGE as $, BRIEFCASE_CATALOG_QUERIES as A, tokenEstimateMultiplier as At, GENERATED_IMAGE_EXTENSION_RE as B, delegationPayloadSchema as Bt, AGENT_QUEST_ID as C, replacePromptVariables as Ct, ARTIFACT_REMOVED_PLACEHOLDER as D, stripDeliveredArtifactBlocks as Dt, ARTIFACT_DELIVERED_PLACEHOLDER as E, splitEquals as Et, ChatModels as F, ACTOR_COLOR_SLOTS as Ft, McpServerName as G, ImagePromptResolutionSchema as H, APP_NAME as Ht, CompletionReasoningEffortSchema as I, DELEGATION_PAYLOAD_SCHEMA_NAME as It, OllamaEmbeddingModel as J, ModelBackend as K, CreateArtifactRequestSchema as L, actorColorIndex as Lt, BriefcasePromptIdSchema as M, ttsRequestSchema as Mt, CONTEXT_WINDOW_SAFETY_BUFFER_TOKENS as N, ttsResponseTooLargeSchema as Nt, ApiKeyType as O, stripToolArtifactMarkup as Ot, CREDIT_DEDUCT_TRANSACTION_TYPES as P, withRetry as Pt, REVIEW_GATE_STATUS_VALUES as Q, DEFAULT_TTS_PROVIDER as R, actorKindMarker as Rt, escapeArtifactBodyJson as S, questReplyText as St, AGENT_QUEST_MCP_URI as T, signImageUrl as Tt, LOCATION_MAP_LANGUAGE as U, WEBSITE_URL as Ut, ImageModels as V, selfClaimedActorKindSchema as Vt, MODEL_INFO_FIELD_GROUP_OF as W, PROMPT_TEXT_MAX as X, OpenAIEmbeddingModel as Y, PermissionDeniedError as Z, logger as _, isPlaceholderImageSigningSecret as _t, getToolCategory as a, WORK_ITEM_STATUSES as at, htmlErrorTitle as b, joinReplySlots as bt, getCreditsUrl as c, createThinkMarkerEscaper as ct, resolveApiEndpoint as d, generatedAudioResponseSchema as dt, SLUG_OWNED_BY_OTHER as et, AuthenticatedApiClient as f, getMcpProviderMetadata as ft, parseApiUrl as g, isEarlyStop as gt, NotAuthenticatedError as h, hasDeliverablePinnedArtifact as ht, canTrustTool as i, VoyageAIEmbeddingModel as it, BedrockEmbeddingModel as j, ttsBase64ResponseSchema as jt, ArtifactTypeSchema as k, supportedVoiceGenerationVendor as kt, getEnvironmentName as l, escapeThinkMarkers as lt, LOCAL_DEV_URL as m, googleMapsSearchUrl as mt, extractCompactInstructions as n, SupportedFabFileMimeTypes as nt, isReadOnlyTool as o, assertAuthOriginMatchesApiKey as ot, DeviceFlowClient as p, getQuestErrorCode as pt, NotFoundError as q, loadContextFiles as r, VisibilitySchema as rt, ApiEndpointUnconfiguredError as s, buildPromptContext as st, ConfigStore as t, SUBQUEST_STATUS_VALUES as tt, requireApiUrl as u, filterToolArtifactMarkup as ut, SESSION_ID_PATTERN as v, isRetryableError as vt, AGENT_QUEST_MANIFEST as w, secureParameters as wt, htmlFirstH1 as x, obfuscateApiKey as xt, isValidSessionId as y, isUserInitiatedAbort as yt, DEGENERATE_FINISH_REASON as z, actorKindSchema as zt };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { kt as tokenEstimateMultiplier } from "./ConfigStore-51UaP9pJ.mjs";
2
+ import { At as tokenEstimateMultiplier } from "./ConfigStore-RHqyXcSS.mjs";
3
3
  import { v4 } from "uuid";
4
4
  import { get_encoding } from "tiktoken";
5
5
  //#region ../../b4m-core/utils/dist/calibratedTokenizer.mjs
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { J as getPlanModeFilePath, L as generateCliTools, N as ReActAgent, R as wrapTools, Y as buildSystemPrompt, a as loadProjectContext, c as createSseBackend, i as buildProjectAgentStore, l as ServerLlmBackend, lt as Logger, n as BackgroundAgentManager, o as McpManager, q as setWebSocketToolExecutor, r as SubagentOrchestrator, t as AgentHistoryStore } from "./AgentHistoryStore-DVxv1kSO.mjs";
3
- import { D as ARTIFACT_REMOVED_PLACEHOLDER, Dt as stripToolArtifactMarkup, E as ARTIFACT_DELIVERED_PLACEHOLDER, Et as stripDeliveredArtifactBlocks, F as ChatModels, G as ModelBackend, I as CompletionReasoningEffortSchema, N as CONTEXT_WINDOW_SAFETY_BUFFER_TOKENS, U as MODEL_INFO_FIELD_GROUP_OF, X as PermissionDeniedError, _ as logger, ct as escapeThinkMarkers, ft as getQuestErrorCode, lt as filterToolArtifactMarkup, mt as hasDeliverablePinnedArtifact, st as createThinkMarkerEscaper, vt as isUserInitiatedAbort } from "./ConfigStore-51UaP9pJ.mjs";
2
+ import { J as getPlanModeFilePath, L as generateCliTools, N as ReActAgent, R as wrapTools, Y as buildSystemPrompt, a as loadProjectContext, c as createSseBackend, i as buildProjectAgentStore, l as ServerLlmBackend, lt as Logger, n as BackgroundAgentManager, o as McpManager, q as setWebSocketToolExecutor, r as SubagentOrchestrator, t as AgentHistoryStore } from "./AgentHistoryStore-O2gKB5YG.mjs";
3
+ import { D as ARTIFACT_REMOVED_PLACEHOLDER, Dt as stripDeliveredArtifactBlocks, E as ARTIFACT_DELIVERED_PLACEHOLDER, F as ChatModels, I as CompletionReasoningEffortSchema, K as ModelBackend, N as CONTEXT_WINDOW_SAFETY_BUFFER_TOKENS, Ot as stripToolArtifactMarkup, W as MODEL_INFO_FIELD_GROUP_OF, Z as PermissionDeniedError, _ as logger, ct as createThinkMarkerEscaper, ht as hasDeliverablePinnedArtifact, lt as escapeThinkMarkers, pt as getQuestErrorCode, ut as filterToolArtifactMarkup, yt as isUserInitiatedAbort } from "./ConfigStore-RHqyXcSS.mjs";
4
4
  import "crypto";
5
5
  import { v4 } from "uuid";
6
6
  import { z as z$1 } from "zod";
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { A as createAgentDelegateTool, C as createTodoStore, D as createCoordinateTaskTool, F as PermissionManager, I as buildCliToolList, O as createResumeAgentTool, Q as CustomCommandStore, S as createFindDefinitionTool, T as createSkillTool, Z as RemoteSkillSource, b as createGetFileStructureTool, j as FallbackLlmBackend, k as createBackgroundAgentTools, nt as SessionStore, q as setWebSocketToolExecutor, s as buildSandbox, tt as CheckpointStore, w as createWriteTodosTool } from "../AgentHistoryStore-DVxv1kSO.mjs";
3
- import { _ as logger, o as isReadOnlyTool, t as ConfigStore, u as requireApiUrl } from "../ConfigStore-51UaP9pJ.mjs";
4
- import { a as deferredToolRegistry, i as createToolSearchTool, n as buildSupportingStores, o as NotifyingLlmBackend, r as buildLlmBackend, t as buildAgent } from "../buildAgent-CrSRKYU_.mjs";
5
- import { a as ApiClient } from "../dist-BsG2Hlp-.mjs";
2
+ import { A as createAgentDelegateTool, C as createTodoStore, D as createCoordinateTaskTool, F as PermissionManager, I as buildCliToolList, O as createResumeAgentTool, Q as CustomCommandStore, S as createFindDefinitionTool, T as createSkillTool, Z as RemoteSkillSource, b as createGetFileStructureTool, j as FallbackLlmBackend, k as createBackgroundAgentTools, nt as SessionStore, q as setWebSocketToolExecutor, s as buildSandbox, tt as CheckpointStore, w as createWriteTodosTool } from "../AgentHistoryStore-O2gKB5YG.mjs";
3
+ import { _ as logger, o as isReadOnlyTool, t as ConfigStore, u as requireApiUrl } from "../ConfigStore-RHqyXcSS.mjs";
4
+ import { a as deferredToolRegistry, i as createToolSearchTool, n as buildSupportingStores, o as NotifyingLlmBackend, r as buildLlmBackend, t as buildAgent } from "../buildAgent-C0jmyDL4.mjs";
5
+ import { a as ApiClient } from "../dist-B1bGf-yn.mjs";
6
6
  import { randomUUID } from "crypto";
7
7
  import { existsSync, realpathSync, statSync } from "fs";
8
8
  import { isAbsolute } from "path";
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { d as resolveApiEndpoint, g as parseApiUrl, t as ConfigStore } from "../ConfigStore-51UaP9pJ.mjs";
2
+ import { d as resolveApiEndpoint, g as parseApiUrl, t as ConfigStore } from "../ConfigStore-RHqyXcSS.mjs";
3
3
  //#region src/commands/apiCommand.ts
4
4
  /**
5
5
  * External API config command (--api-url / --reset-api)
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as version } from "../package-DEsNSP54.mjs";
2
+ import { t as version } from "../package-DsG8Tgvs.mjs";
3
3
  import { c as isNpmPrefixWritable, i as fetchLatestVersion, r as compareSemver } from "../updateChecker-CCLVVdH0.mjs";
4
4
  import { t as checkRipgrep } from "../ripgrepCheck-BmkyTK2i.mjs";
5
5
  import { existsSync } from "fs";
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as ConfigStore } from "../ConfigStore-51UaP9pJ.mjs";
2
+ import { t as ConfigStore } from "../ConfigStore-RHqyXcSS.mjs";
3
3
  //#region src/commands/envCommand.ts
4
4
  /**
5
5
  * Environment switching for the `--dev` / `--prod` launch flags.
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { A as createAgentDelegateTool, B as SHELL_LIKE_TOOL_COMMAND_FIELDS, C as createTodoStore, D as createCoordinateTaskTool, F as PermissionManager, I as buildCliToolList, K as classifyCommandRisk, L as generateCliTools, N as ReActAgent, O as createResumeAgentTool, Q as CustomCommandStore, R as wrapTools, S as createFindDefinitionTool, T as createSkillTool, Y as buildSystemPrompt, Z as RemoteSkillSource, a as loadProjectContext, b as createGetFileStructureTool, c as createSseBackend, i as buildProjectAgentStore, j as FallbackLlmBackend, k as createBackgroundAgentTools, n as BackgroundAgentManager, nt as SessionStore, o as McpManager, q as setWebSocketToolExecutor, r as SubagentOrchestrator, s as buildSandbox, t as AgentHistoryStore, tt as CheckpointStore, w as createWriteTodosTool, x as createWorkItemTools } from "../AgentHistoryStore-DVxv1kSO.mjs";
3
- import { _ as logger, o as isReadOnlyTool, t as ConfigStore, u as requireApiUrl } from "../ConfigStore-51UaP9pJ.mjs";
4
- import { r as reconstructTurnBlocks, t as WorkItemsClient } from "../WorkItemsClient-BMY0Qq1s.mjs";
5
- import { a as ApiClient } from "../dist-BsG2Hlp-.mjs";
2
+ import { A as createAgentDelegateTool, B as SHELL_LIKE_TOOL_COMMAND_FIELDS, C as createTodoStore, D as createCoordinateTaskTool, F as PermissionManager, I as buildCliToolList, K as classifyCommandRisk, L as generateCliTools, N as ReActAgent, O as createResumeAgentTool, Q as CustomCommandStore, R as wrapTools, S as createFindDefinitionTool, T as createSkillTool, Y as buildSystemPrompt, Z as RemoteSkillSource, a as loadProjectContext, b as createGetFileStructureTool, c as createSseBackend, i as buildProjectAgentStore, j as FallbackLlmBackend, k as createBackgroundAgentTools, n as BackgroundAgentManager, nt as SessionStore, o as McpManager, q as setWebSocketToolExecutor, r as SubagentOrchestrator, s as buildSandbox, t as AgentHistoryStore, tt as CheckpointStore, w as createWriteTodosTool, x as createWorkItemTools } from "../AgentHistoryStore-O2gKB5YG.mjs";
3
+ import { _ as logger, o as isReadOnlyTool, t as ConfigStore, u as requireApiUrl } from "../ConfigStore-RHqyXcSS.mjs";
4
+ import { r as reconstructTurnBlocks, t as WorkItemsClient } from "../WorkItemsClient-cmw7WYBy.mjs";
5
+ import { a as ApiClient } from "../dist-B1bGf-yn.mjs";
6
6
  import { randomBytes } from "crypto";
7
7
  import { v4 } from "uuid";
8
8
  import { readFile } from "fs/promises";
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { t as ConfigStore } from "../ConfigStore-51UaP9pJ.mjs";
3
- import { t as version } from "../package-DEsNSP54.mjs";
2
+ import { t as ConfigStore } from "../ConfigStore-RHqyXcSS.mjs";
3
+ import { t as version } from "../package-DsG8Tgvs.mjs";
4
4
  //#region src/commands/mcpCommand.ts
5
5
  /**
6
6
  * External MCP commands (b4m mcp list, b4m mcp add, etc.)
@@ -70,7 +70,7 @@ async function handleMcpCommand(subcommand, argv) {
70
70
  await handleDisable(config, argv.name, configStore);
71
71
  break;
72
72
  case "serve": {
73
- const { handleMcpServeCommand } = await import("../serve-BaHzVbcm.mjs");
73
+ const { handleMcpServeCommand } = await import("../serve-CAfCQose.mjs");
74
74
  await handleMcpServeCommand({
75
75
  http: Boolean(argv.http),
76
76
  port: typeof argv.port === "number" ? argv.port : void 0,
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as ConfigStore } from "../ConfigStore-51UaP9pJ.mjs";
2
+ import { t as ConfigStore } from "../ConfigStore-RHqyXcSS.mjs";
3
3
  import { n as getDefaultPluginsDir, r as isFeatureEnabled, t as PluginStore } from "../PluginStore-DwvOJ-G3.mjs";
4
4
  import { promises } from "fs";
5
5
  import path from "path";
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as version } from "../package-DEsNSP54.mjs";
2
+ import { t as version } from "../package-DsG8Tgvs.mjs";
3
3
  import { a as forceCheckForUpdate, c as isNpmPrefixWritable, d as shouldAttemptAutoUpdate, l as readCachedUpdate, n as REEXEC_GUARD_ENV, o as getAutoUpdatePreference, t as INSTALL_CMD, u as setAutoUpdatePreference } from "../updateChecker-CCLVVdH0.mjs";
4
4
  import { t as checkRipgrep } from "../ripgrepCheck-BmkyTK2i.mjs";
5
5
  import { execSync, spawnSync } from "child_process";
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { _ as logger, f as AuthenticatedApiClient, p as DeviceFlowClient, t as ConfigStore } from "./ConfigStore-51UaP9pJ.mjs";
3
- import { t as version } from "./package-DEsNSP54.mjs";
2
+ import { _ as logger, f as AuthenticatedApiClient, p as DeviceFlowClient, t as ConfigStore } from "./ConfigStore-RHqyXcSS.mjs";
3
+ import { t as version } from "./package-DsG8Tgvs.mjs";
4
4
  import { isAxiosError } from "axios";
5
5
  import { Readable } from "node:stream";
6
6
  import { createParser } from "eventsource-parser";
package/dist/index.mjs CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
- import { $ as processFileReferences, A as createAgentDelegateTool, C as createTodoStore, D as createCoordinateTaskTool, E as parseAgentConfig, F as PermissionManager, G as DEFAULT_THOROUGHNESS, H as DEFAULT_AGENT_MODEL, I as buildCliToolList, J as getPlanModeFilePath, M as substituteArguments, O as createResumeAgentTool, P as findIterationBoundary, Q as CustomCommandStore, S as createFindDefinitionTool, T as createSkillTool, U as DEFAULT_MAX_ITERATIONS, V as ALWAYS_DENIED_FOR_AGENTS, W as DEFAULT_RETRY_CONFIG, X as buildSkillsPromptSection, Y as buildSystemPrompt, Z as RemoteSkillSource, _ as createDecisionLogTool, at as rewireReservedNames, b as createGetFileStructureTool, ct as warmFileCache, d as createReviewGateStore, et as hasFileReferences, f as createReviewGateTool, ft as MAX_PASTE_SIZE, g as formatBlockersOutput, h as createBlockerTools, it as mergeCommands, j as FallbackLlmBackend, k as createBackgroundAgentTools, m as createBlockerStore, nt as SessionStore, ot as formatFileSize, p as formatReviewGatesOutput, q as setWebSocketToolExecutor, rt as searchCommands, s as buildSandbox, st as searchFiles, tt as CheckpointStore, u as isConnectionDrop, ut as COMPACTION_SUMMARY_MARKER, v as createDecisionStore, w as createWriteTodosTool, x as createWorkItemTools, y as formatDecisionsOutput, z as getProcessHooks } from "./AgentHistoryStore-DVxv1kSO.mjs";
2
+ import { $ as processFileReferences, A as createAgentDelegateTool, C as createTodoStore, D as createCoordinateTaskTool, E as parseAgentConfig, F as PermissionManager, G as DEFAULT_THOROUGHNESS, H as DEFAULT_AGENT_MODEL, I as buildCliToolList, J as getPlanModeFilePath, M as substituteArguments, O as createResumeAgentTool, P as findIterationBoundary, Q as CustomCommandStore, S as createFindDefinitionTool, T as createSkillTool, U as DEFAULT_MAX_ITERATIONS, V as ALWAYS_DENIED_FOR_AGENTS, W as DEFAULT_RETRY_CONFIG, X as buildSkillsPromptSection, Y as buildSystemPrompt, Z as RemoteSkillSource, _ as createDecisionLogTool, at as rewireReservedNames, b as createGetFileStructureTool, ct as warmFileCache, d as createReviewGateStore, et as hasFileReferences, f as createReviewGateTool, ft as MAX_PASTE_SIZE, g as formatBlockersOutput, h as createBlockerTools, it as mergeCommands, j as FallbackLlmBackend, k as createBackgroundAgentTools, m as createBlockerStore, nt as SessionStore, ot as formatFileSize, p as formatReviewGatesOutput, q as setWebSocketToolExecutor, rt as searchCommands, s as buildSandbox, st as searchFiles, tt as CheckpointStore, u as isConnectionDrop, ut as COMPACTION_SUMMARY_MARKER, v as createDecisionStore, w as createWriteTodosTool, x as createWorkItemTools, y as formatDecisionsOutput, z as getProcessHooks } from "./AgentHistoryStore-O2gKB5YG.mjs";
3
3
  import { a as selectLiveSubagentTokens, i as selectLiveSubagentCredits, n as selectActiveBackgroundShells, o as useCliStore, r as selectCompletedBackgroundShells, t as selectActiveBackgroundAgents } from "./store-BxmPEI3v.mjs";
4
- import { Bt as selfClaimedActorKindSchema, F as ChatModels, Ft as DELEGATION_PAYLOAD_SCHEMA_NAME, It as actorColorIndex, Lt as actorKindMarker, P as CREDIT_DEDUCT_TRANSACTION_TYPES, Pt as ACTOR_COLOR_SLOTS, Rt as actorKindSchema, Z as REVIEW_GATE_STATUS_VALUES, _ as logger, c as getCreditsUrl, d as resolveApiEndpoint, et as SUBQUEST_STATUS_VALUES, g as parseApiUrl, ht as isEarlyStop, kt as tokenEstimateMultiplier, l as getEnvironmentName, m as LOCAL_DEV_URL, n as extractCompactInstructions, o as isReadOnlyTool, s as ApiEndpointUnconfiguredError, t as ConfigStore, u as requireApiUrl, v as SESSION_ID_PATTERN, y as isValidSessionId, zt as delegationPayloadSchema } from "./ConfigStore-51UaP9pJ.mjs";
4
+ import { At as tokenEstimateMultiplier, Bt as delegationPayloadSchema, F as ChatModels, Ft as ACTOR_COLOR_SLOTS, It as DELEGATION_PAYLOAD_SCHEMA_NAME, Lt as actorColorIndex, P as CREDIT_DEDUCT_TRANSACTION_TYPES, Q as REVIEW_GATE_STATUS_VALUES, Rt as actorKindMarker, Vt as selfClaimedActorKindSchema, _ as logger, c as getCreditsUrl, d as resolveApiEndpoint, g as parseApiUrl, gt as isEarlyStop, l as getEnvironmentName, m as LOCAL_DEV_URL, n as extractCompactInstructions, o as isReadOnlyTool, s as ApiEndpointUnconfiguredError, t as ConfigStore, tt as SUBQUEST_STATUS_VALUES, u as requireApiUrl, v as SESSION_ID_PATTERN, y as isValidSessionId, zt as actorKindSchema } from "./ConfigStore-RHqyXcSS.mjs";
5
5
  import { r as isFeatureEnabled, t as PluginStore } from "./PluginStore-DwvOJ-G3.mjs";
6
- import { i as getTokenCounter, n as ConversationContext, r as reconstructTurnBlocks, t as WorkItemsClient } from "./WorkItemsClient-BMY0Qq1s.mjs";
7
- import { a as deferredToolRegistry, i as createToolSearchTool, n as buildSupportingStores, o as NotifyingLlmBackend, r as buildLlmBackend, t as buildAgent } from "./buildAgent-CrSRKYU_.mjs";
6
+ import { i as getTokenCounter, n as ConversationContext, r as reconstructTurnBlocks, t as WorkItemsClient } from "./WorkItemsClient-cmw7WYBy.mjs";
7
+ import { a as deferredToolRegistry, i as createToolSearchTool, n as buildSupportingStores, o as NotifyingLlmBackend, r as buildLlmBackend, t as buildAgent } from "./buildAgent-C0jmyDL4.mjs";
8
8
  import { t as getShellSessionManager } from "./ShellSessionManager-6o8KZzl1-vrbPAUTq.mjs";
9
- import { a as ApiClient, s as OAuthClient } from "./dist-BsG2Hlp-.mjs";
10
- import { t as version } from "./package-DEsNSP54.mjs";
9
+ import { a as ApiClient, s as OAuthClient } from "./dist-B1bGf-yn.mjs";
10
+ import { t as version } from "./package-DsG8Tgvs.mjs";
11
11
  import { s as getStartupUpdateStatus } from "./updateChecker-CCLVVdH0.mjs";
12
12
  import React, { useCallback, useEffect, useLayoutEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore } from "react";
13
13
  import { Box, Static, Text, measureElement, render, useApp, useInput, usePaste, useStdout } from "ink";
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  //#region package.json
3
- var version = "3.0.0";
3
+ var version = "3.1.0";
4
4
  //#endregion
5
5
  export { version as t };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { A as BRIEFCASE_CATALOG_QUERIES, At as ttsBase64ResponseSchema, B as ImageModels, C as AGENT_QUEST_ID, L as DEFAULT_TTS_PROVIDER, M as BriefcasePromptIdSchema, Mt as ttsResponseTooLargeSchema, Ot as supportedVoiceGenerationVendor, St as replacePromptVariables, T as AGENT_QUEST_MCP_URI, V as ImagePromptResolutionSchema, Y as PROMPT_TEXT_MAX, _ as logger, g as parseApiUrl, h as NotAuthenticatedError, jt as ttsRequestSchema, k as ArtifactTypeSchema, nt as VisibilitySchema, ot as buildPromptContext, t as ConfigStore, u as requireApiUrl, ut as generatedAudioResponseSchema, w as AGENT_QUEST_MANIFEST, xt as questReplyText, yt as joinReplySlots, z as GENERATED_IMAGE_EXTENSION_RE } from "./ConfigStore-51UaP9pJ.mjs";
3
- import { a as ApiClient, i as parseRetryAfterSeconds, o as isProviderKeyFailure, r as createClient, t as B4mApiError } from "./dist-BsG2Hlp-.mjs";
2
+ import { A as BRIEFCASE_CATALOG_QUERIES, B as GENERATED_IMAGE_EXTENSION_RE, C as AGENT_QUEST_ID, Ct as replacePromptVariables, H as ImagePromptResolutionSchema, L as CreateArtifactRequestSchema, M as BriefcasePromptIdSchema, Mt as ttsRequestSchema, Nt as ttsResponseTooLargeSchema, R as DEFAULT_TTS_PROVIDER, St as questReplyText, T as AGENT_QUEST_MCP_URI, V as ImageModels, X as PROMPT_TEXT_MAX, _ as logger, bt as joinReplySlots, dt as generatedAudioResponseSchema, g as parseApiUrl, h as NotAuthenticatedError, jt as ttsBase64ResponseSchema, k as ArtifactTypeSchema, kt as supportedVoiceGenerationVendor, rt as VisibilitySchema, st as buildPromptContext, t as ConfigStore, u as requireApiUrl, w as AGENT_QUEST_MANIFEST } from "./ConfigStore-RHqyXcSS.mjs";
3
+ import { a as ApiClient, i as parseRetryAfterSeconds, o as isProviderKeyFailure, r as createClient, t as B4mApiError } from "./dist-B1bGf-yn.mjs";
4
4
  import { z as z$1 } from "zod";
5
5
  import { isAxiosError } from "axios";
6
6
  import { createHash, randomUUID } from "node:crypto";
@@ -227,6 +227,27 @@ var B4mApiClient = class {
227
227
  async getArtifact(artifactId) {
228
228
  return this.client.get(`/api/artifacts/${encodeURIComponent(artifactId)}`, { params: { includeContent: "true" } });
229
229
  }
230
+ /** POST /api/v1/artifacts: creates a private artifact at version 1. */
231
+ async createArtifact(args) {
232
+ const artifact = await this.sdk.call("createArtifact", { body: {
233
+ type: args.type,
234
+ title: args.title,
235
+ content: args.content,
236
+ ...args.description !== void 0 ? { description: args.description } : {},
237
+ ...args.notebookId ? { session_id: args.notebookId } : {},
238
+ ...args.projectId ? { project_id: args.projectId } : {},
239
+ ...args.tags?.length ? { tags: args.tags } : {}
240
+ } });
241
+ return {
242
+ id: artifact.id,
243
+ type: artifact.type,
244
+ title: artifact.title,
245
+ version: artifact.version,
246
+ notebookId: artifact.session_id ?? void 0,
247
+ projectId: artifact.project_id ?? void 0,
248
+ createdAt: artifact.created_at
249
+ };
250
+ }
230
251
  /**
231
252
  * The caller's own most recent publication of an artifact, or null. The route is
232
253
  * owner-scoped for `sourceArtifactId`, so another user's page never matches.
@@ -461,6 +482,12 @@ const TOOL_META = [
461
482
  description: "Generate an image from a text prompt and wait for the render. Returns the quest and notebook ids plus each image's file name and download URL. Image names are not file ids and do not work with get_file.",
462
483
  scope: "ai:generate"
463
484
  },
485
+ {
486
+ name: "create_artifact",
487
+ title: "Create artifact",
488
+ description: "Create a private artifact (diagram, chart, code, page) and return its id. There is no markdown type: put a written document in type 'html'. Pass the returned id to publish_artifact to share it.",
489
+ scope: "notebooks:write"
490
+ },
464
491
  {
465
492
  name: "publish_artifact",
466
493
  title: "Publish artifact",
@@ -544,6 +571,15 @@ const publishArtifactShape = {
544
571
  visibility: publishVisibilitySchema.optional().describe("Who can open the link: 'public' (anyone) or 'private' (only you); omit to keep an existing page's visibility (a first publish is public)"),
545
572
  title: z$1.string().min(1).max(200).optional().describe("Page title; defaults to the artifact's title")
546
573
  };
574
+ const createArtifactShape = {
575
+ type: CreateArtifactRequestSchema.shape.type.describe("Artifact type: 'html' for a written document or web page, 'mermaid' for a diagram, 'recharts' for a chart, 'svg', 'react', 'python' or 'code' for source"),
576
+ title: CreateArtifactRequestSchema.shape.title.describe("Artifact title"),
577
+ content: CreateArtifactRequestSchema.shape.content.describe("The artifact's source: HTML, Mermaid, SVG, code and so on, matching type"),
578
+ description: CreateArtifactRequestSchema.shape.description.describe("Short description"),
579
+ notebookId: notebookId("A notebook (session) you can edit, to file the artifact under").optional(),
580
+ projectId: CreateArtifactRequestSchema.shape.project_id.describe("A project you can read, to file the artifact under"),
581
+ tags: CreateArtifactRequestSchema.shape.tags.describe("Up to 20 tags")
582
+ };
547
583
  const textToSpeechShape = {
548
584
  ...ttsRequestSchema.omit({ encoding: true }).shape,
549
585
  text: ttsRequestSchema.shape.text.describe("Text to speak"),
@@ -825,6 +861,9 @@ async function openPublishDraft(client, request) {
825
861
  });
826
862
  }
827
863
  }
864
+ async function createArtifact(client, args) {
865
+ return client.createArtifact(args);
866
+ }
828
867
  /**
829
868
  * Publish an artifact: upload its RAW content and let finalize render it
830
869
  * (source.artifactType), so the page matches an in-app publish byte for byte with
@@ -1118,6 +1157,11 @@ function registerTools(server, client) {
1118
1157
  baseURL,
1119
1158
  onProgress: progressReporter(extra, () => "rendering image")
1120
1159
  })));
1160
+ server.registerTool("create_artifact", {
1161
+ title: meta("create_artifact").title,
1162
+ description: meta("create_artifact").description,
1163
+ inputSchema: createArtifactShape
1164
+ }, (args) => run("notebooks:write", () => createArtifact(client, args)));
1121
1165
  server.registerTool("publish_artifact", {
1122
1166
  title: meta("publish_artifact").title,
1123
1167
  description: meta("publish_artifact").description,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "3.0.0",
3
+ "version": "3.1.0",
4
4
  "mcpName": "io.github.bike4mind/bike4mind",
5
5
  "type": "module",
6
6
  "description": "Interactive CLI tool for Bike4Mind with ReAct agents",
@@ -124,17 +124,17 @@
124
124
  "tsx": "^4.23.0",
125
125
  "typescript": "^5.9.3",
126
126
  "vitest": "^4.1.11",
127
- "@bike4mind/agents": "1.2.0",
127
+ "@bike4mind/agents": "1.2.1",
128
128
  "@bike4mind/client-auth": "0.2.0",
129
- "@bike4mind/common": "15.0.0",
130
- "@bike4mind/fab-pipeline": "2.1.0",
129
+ "@bike4mind/common": "15.1.0",
130
+ "@bike4mind/fab-pipeline": "2.1.1",
131
+ "@bike4mind/llm-adapters": "1.1.1",
131
132
  "@bike4mind/hearth": "0.3.1",
132
- "@bike4mind/llm-adapters": "1.1.0",
133
- "@bike4mind/mcp": "2.1.0",
133
+ "@bike4mind/mcp": "2.1.1",
134
134
  "@bike4mind/observability": "0.2.3",
135
- "@bike4mind/sdk": "1.0.0",
136
- "@bike4mind/services": "17.0.0",
137
- "@bike4mind/utils": "7.1.0"
135
+ "@bike4mind/sdk": "1.0.1",
136
+ "@bike4mind/services": "17.1.0",
137
+ "@bike4mind/utils": "7.1.1"
138
138
  },
139
139
  "optionalDependencies": {
140
140
  "@vscode/ripgrep": "^1.18.0"