@bike4mind/cli 0.16.0 → 0.17.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/bin/bike4mind-cli.mjs +8 -0
- package/dist/{tools-D9eSRR7Q.mjs → BackgroundAgentManager-CcetLt8q.mjs} +8565 -8372
- package/dist/{ConfigStore-CtGc4fF2.mjs → ConfigStore-CNveAjEv.mjs} +354 -21
- package/dist/commands/apiCommand.mjs +1 -1
- package/dist/commands/doctorCommand.mjs +1 -1
- package/dist/commands/envCommand.mjs +1 -1
- package/dist/commands/headlessCommand.mjs +6 -2
- package/dist/commands/mcpCommand.mjs +1 -1
- package/dist/commands/updateCommand.mjs +1 -1
- package/dist/index.mjs +2241 -2055
- package/dist/{package-3pouvthv.mjs → package-BJU2qiwQ.mjs} +1 -1
- package/package.json +13 -9
|
@@ -590,7 +590,8 @@ const b4mLLMTools = z.enum([
|
|
|
590
590
|
"navigate_view",
|
|
591
591
|
"generate_jupyter_notebook",
|
|
592
592
|
"excel_generation",
|
|
593
|
-
"fmp_financial_data"
|
|
593
|
+
"fmp_financial_data",
|
|
594
|
+
"skill"
|
|
594
595
|
]);
|
|
595
596
|
b4mLLMTools.options.map((tool) => tool);
|
|
596
597
|
/**
|
|
@@ -902,6 +903,45 @@ const ClaudeArtifactMimeTypes = {
|
|
|
902
903
|
PYTHON: "application/vnd.ant.python",
|
|
903
904
|
BLOG_DRAFT: "application/vnd.b4m.blog-draft"
|
|
904
905
|
};
|
|
906
|
+
/**
|
|
907
|
+
* Map a MIME type (or AI-provider artifact-type string) to an internal {@link ArtifactType}.
|
|
908
|
+
*
|
|
909
|
+
* Single source of truth — consumed by the artifact parsers (b4m-core/utils + client) and the
|
|
910
|
+
* tool_result dedup in ChatCompletionProcess. Exact blessed-type matches first (case-insensitive,
|
|
911
|
+
* since MIME types are), then language/format inference; returns null if unrecognized.
|
|
912
|
+
*
|
|
913
|
+
* #8907: this previously lived as three hand-maintained copies that drifted — e.g. the lattice
|
|
914
|
+
* tool emits `application/vnd.b4m.lattice` but a copy matched `application/vnd.ant.lattice`,
|
|
915
|
+
* letting lattice tool_result artifacts dodge the dedup set (#8905).
|
|
916
|
+
*/
|
|
917
|
+
function mapMimeTypeToArtifactType(mimeType) {
|
|
918
|
+
if (!mimeType) return null;
|
|
919
|
+
const normalized = mimeType.toLowerCase().trim();
|
|
920
|
+
switch (normalized) {
|
|
921
|
+
case ClaudeArtifactMimeTypes.REACT.toLowerCase(): return "react";
|
|
922
|
+
case ClaudeArtifactMimeTypes.HTML.toLowerCase(): return "html";
|
|
923
|
+
case ClaudeArtifactMimeTypes.SVG.toLowerCase(): return "svg";
|
|
924
|
+
case ClaudeArtifactMimeTypes.MERMAID.toLowerCase(): return "mermaid";
|
|
925
|
+
case ClaudeArtifactMimeTypes.RECHARTS.toLowerCase(): return "recharts";
|
|
926
|
+
case ClaudeArtifactMimeTypes.CHESS.toLowerCase(): return "chess";
|
|
927
|
+
case ClaudeArtifactMimeTypes.CODE.toLowerCase(): return "code";
|
|
928
|
+
case ClaudeArtifactMimeTypes.MARKDOWN.toLowerCase(): return "code";
|
|
929
|
+
case ClaudeArtifactMimeTypes.LATTICE.toLowerCase(): return "lattice";
|
|
930
|
+
case ClaudeArtifactMimeTypes.PYTHON.toLowerCase(): return "python";
|
|
931
|
+
case ClaudeArtifactMimeTypes.BLOG_DRAFT.toLowerCase(): return "blog-draft";
|
|
932
|
+
}
|
|
933
|
+
if (normalized.includes("jsx") || normalized.includes("react")) return "react";
|
|
934
|
+
if (normalized.includes("javascript") || normalized.includes("typescript")) return "code";
|
|
935
|
+
if (normalized.includes("python") || normalized === "text/x-python") return "python";
|
|
936
|
+
if (normalized.includes("java") || normalized.includes("c++") || normalized.includes("rust") || normalized.includes("go") || normalized.includes("ruby") || normalized.includes("php") || normalized.includes("swift") || normalized.includes("kotlin") || normalized.includes("csharp") || normalized.includes("c#")) return "code";
|
|
937
|
+
if (normalized.includes("html") || normalized.includes("xhtml")) return "html";
|
|
938
|
+
if (normalized.includes("svg")) return "svg";
|
|
939
|
+
if (normalized.includes("markdown") || normalized.includes("md")) return "code";
|
|
940
|
+
if (normalized.includes("mermaid")) return "mermaid";
|
|
941
|
+
if (normalized.includes("recharts") || normalized.includes("chart")) return "recharts";
|
|
942
|
+
if (normalized.includes("chess")) return "chess";
|
|
943
|
+
return null;
|
|
944
|
+
}
|
|
905
945
|
let KnowledgeType = /* @__PURE__ */ function(KnowledgeType) {
|
|
906
946
|
/**
|
|
907
947
|
* A knowledge that is from a URL.
|
|
@@ -1275,7 +1315,7 @@ const SreRepoConfigSchema = z.object({
|
|
|
1275
1315
|
/** Whether this repo's SRE pipeline is active */
|
|
1276
1316
|
enabled: z.boolean().default(false),
|
|
1277
1317
|
/** LLM model ID for Diagnostician */
|
|
1278
|
-
modelId: z.string().default("claude-sonnet-4-
|
|
1318
|
+
modelId: z.string().default("claude-sonnet-4-6"),
|
|
1279
1319
|
/** Max diff lines per fix */
|
|
1280
1320
|
maxDiffLines: z.number().min(1).default(50),
|
|
1281
1321
|
/** Max fixes dispatched per day for this repo */
|
|
@@ -3628,11 +3668,22 @@ const OpenAIImageStyleSchema = z.enum(["vivid", "natural"]);
|
|
|
3628
3668
|
* and they are structural-control models — silently remapping them to a plain
|
|
3629
3669
|
* text-to-image model would drop the control image and return the wrong kind of result,
|
|
3630
3670
|
* so a clear "unsupported model" error is the more honest response.
|
|
3671
|
+
*
|
|
3672
|
+
* The three `grok-2-image*` ids are the prior xAI image-model ids, all superseded
|
|
3673
|
+
* in the enum by `grok-imagine-image-quality`. The id went through an un-aliased
|
|
3674
|
+
* rename chain — `grok-2-image-1212` (original) → `grok-2-image` → `grok-2-image-gen`
|
|
3675
|
+
* → `grok-imagine-image-quality` — so any of the three could survive in stale
|
|
3676
|
+
* persisted client state (`grok-2-image-1212` was the one observed in #9211). All are
|
|
3677
|
+
* xAI text-to-image models, so remapping to the current id is a faithful
|
|
3678
|
+
* same-provider, same-modality replacement.
|
|
3631
3679
|
*/
|
|
3632
3680
|
const LEGACY_IMAGE_MODEL_MAP = {
|
|
3633
3681
|
"dall-e-3": "gpt-image-1",
|
|
3634
3682
|
"dall-e-2": "gpt-image-1",
|
|
3635
|
-
"flux-dev": "flux-pro-1.1"
|
|
3683
|
+
"flux-dev": "flux-pro-1.1",
|
|
3684
|
+
"grok-2-image-1212": "grok-imagine-image-quality",
|
|
3685
|
+
"grok-2-image": "grok-imagine-image-quality",
|
|
3686
|
+
"grok-2-image-gen": "grok-imagine-image-quality"
|
|
3636
3687
|
};
|
|
3637
3688
|
const OpenAIImageGenerationInput = z.object({
|
|
3638
3689
|
prompt: z.string(),
|
|
@@ -3929,8 +3980,36 @@ const OrchestrationDefaultsSchema = z.object({
|
|
|
3929
3980
|
"code_execute",
|
|
3930
3981
|
"coordinate_task"
|
|
3931
3982
|
]),
|
|
3932
|
-
/**
|
|
3933
|
-
|
|
3983
|
+
/**
|
|
3984
|
+
* Tool names explicitly forbidden. Enforced as a final subtraction in
|
|
3985
|
+
* `pickEffectiveEnabledTools` — wins even over payload-pinned tools — so this
|
|
3986
|
+
* is the defense-in-depth backstop for the case where an admin broadens
|
|
3987
|
+
* `allowedTools` without realizing a parallel denylist is also needed.
|
|
3988
|
+
*
|
|
3989
|
+
* Seeded with every tool that mutates user data (#8945, the spec's
|
|
3990
|
+
* "anything tagged `mutates_user_data`"): destructive/overwriting filesystem
|
|
3991
|
+
* writes, arbitrary shell execution, blog authoring/publishing, persisted
|
|
3992
|
+
* lattice-model writes, and storage-backed artifact generation. New mutating
|
|
3993
|
+
* tools should be added here until the tag-derived denylist (Option B, #8923/
|
|
3994
|
+
* #8924) replaces this hand-curated list.
|
|
3995
|
+
*/
|
|
3996
|
+
deniedTools: z.array(z.string()).default([
|
|
3997
|
+
"create_file",
|
|
3998
|
+
"edit_file",
|
|
3999
|
+
"edit_local_file",
|
|
4000
|
+
"delete_file",
|
|
4001
|
+
"bash_execute",
|
|
4002
|
+
"blog_draft",
|
|
4003
|
+
"blog_edit",
|
|
4004
|
+
"blog_publish",
|
|
4005
|
+
"lattice_create_model",
|
|
4006
|
+
"lattice_add_entity",
|
|
4007
|
+
"lattice_set_value",
|
|
4008
|
+
"lattice_create_rule",
|
|
4009
|
+
"image_generation",
|
|
4010
|
+
"edit_image",
|
|
4011
|
+
"excel_generation"
|
|
4012
|
+
]),
|
|
3934
4013
|
/** Per-thoroughness iteration ceiling. Matches `IAgent.maxIterations`. */
|
|
3935
4014
|
maxIterations: z.object({
|
|
3936
4015
|
quick: z.number().int().positive(),
|
|
@@ -7261,6 +7340,13 @@ const PromptMetaZodSchema = z.object({
|
|
|
7261
7340
|
generatedImageReferences: z.array(z.string()).optional(),
|
|
7262
7341
|
promptErrors: z.array(z.string()).optional(),
|
|
7263
7342
|
warnings: z.array(z.string()).optional(),
|
|
7343
|
+
/**
|
|
7344
|
+
* The provider's reason for ending generation (Anthropic vocabulary:
|
|
7345
|
+
* 'end_turn' | 'max_tokens' | 'tool_use' | 'stop_sequence' | 'pause_turn').
|
|
7346
|
+
* 'max_tokens' signals the response was truncated against the output ceiling,
|
|
7347
|
+
* letting the client render a truncated-artifact recovery affordance (#9259).
|
|
7348
|
+
*/
|
|
7349
|
+
finishReason: z.string().optional(),
|
|
7264
7350
|
statusLog: z.array(z.object({
|
|
7265
7351
|
status: z.string(),
|
|
7266
7352
|
timestamp: z.date().or(z.string())
|
|
@@ -7982,12 +8068,14 @@ z$1.object({
|
|
|
7982
8068
|
slug: z$1.string().min(2).max(60).regex(slugRegex, "Slug must be lowercase alphanumeric with hyphens (e.g. \"my-data-lake\")"),
|
|
7983
8069
|
description: z$1.string().max(2e3).optional(),
|
|
7984
8070
|
fileTagPrefix: z$1.string().min(2).max(30).refine((s) => s.endsWith(":"), "Tag prefix must end with \":\" (e.g. \"acme:\")"),
|
|
7985
|
-
requiredUserTag: z$1.string().min(1).max(100).optional()
|
|
8071
|
+
requiredUserTag: z$1.string().min(1).max(100).optional(),
|
|
8072
|
+
requiredEntitlement: z$1.string().min(3).max(100).refine((s) => s.includes(":") && s.split(":").every((part) => part.length > 0), "Entitlement key must be namespaced with non-empty parts (e.g. \"product:pro\")").optional()
|
|
7986
8073
|
});
|
|
7987
8074
|
z$1.object({
|
|
7988
8075
|
name: z$1.string().min(1).max(200).optional(),
|
|
7989
8076
|
description: z$1.string().max(2e3).optional(),
|
|
7990
|
-
requiredUserTag: z$1.string().min(1).max(100).optional()
|
|
8077
|
+
requiredUserTag: z$1.string().min(1).max(100).optional(),
|
|
8078
|
+
requiredEntitlement: z$1.string().min(3).max(100).refine((s) => s.includes(":") && s.split(":").every((part) => part.length > 0), "Entitlement key must be namespaced with non-empty parts (e.g. \"product:pro\")").optional()
|
|
7991
8079
|
});
|
|
7992
8080
|
z$1.object({
|
|
7993
8081
|
organizationId: z$1.string().optional(),
|
|
@@ -8133,37 +8221,68 @@ const DATA_LAKES = [{
|
|
|
8133
8221
|
id: "ionq-sales",
|
|
8134
8222
|
name: "IonQ Sales Intelligence",
|
|
8135
8223
|
requiredUserTag: "Opti",
|
|
8224
|
+
requiredEntitlement: "optihashi:pro",
|
|
8136
8225
|
fileTagPrefix: "ionq:",
|
|
8137
8226
|
datalakeTag: "datalake:ionq-sales"
|
|
8138
8227
|
}, {
|
|
8139
8228
|
id: "opti-knowledge",
|
|
8140
8229
|
name: "Optimization Knowledge Base",
|
|
8141
8230
|
requiredUserTag: "Opti",
|
|
8231
|
+
requiredEntitlement: "optihashi:pro",
|
|
8142
8232
|
fileTagPrefix: "opti:",
|
|
8143
8233
|
datalakeTag: "datalake:opti-knowledge"
|
|
8144
8234
|
}];
|
|
8145
8235
|
/**
|
|
8146
|
-
*
|
|
8147
|
-
*
|
|
8148
|
-
*
|
|
8149
|
-
*
|
|
8236
|
+
* Canonical normalization for entitlement keys + `requiredEntitlement` values — the ONE
|
|
8237
|
+
* rule, applied at write time (create/update/stamp) and at match time. Mirrors the
|
|
8238
|
+
* entitlement registry's `normalizeTag` (trim + lowercase) so a value authored in any
|
|
8239
|
+
* casing matches the lowercase keys the resolver produces.
|
|
8240
|
+
*/
|
|
8241
|
+
const normalizeEntitlementKey = (key) => key.trim().toLowerCase();
|
|
8242
|
+
/**
|
|
8243
|
+
* Single projection from a persisted lake document to the lightweight DataLakeConfig
|
|
8244
|
+
* the access filters operate on. Centralized so the `requiredEntitlement` field (and any
|
|
8245
|
+
* future field) cannot be silently dropped at one of the many former inline projections.
|
|
8246
|
+
*/
|
|
8247
|
+
function toDataLakeConfig(dl) {
|
|
8248
|
+
return {
|
|
8249
|
+
id: dl.id,
|
|
8250
|
+
name: dl.name,
|
|
8251
|
+
requiredUserTag: dl.requiredUserTag,
|
|
8252
|
+
requiredEntitlement: dl.requiredEntitlement,
|
|
8253
|
+
fileTagPrefix: dl.fileTagPrefix,
|
|
8254
|
+
datalakeTag: dl.datalakeTag
|
|
8255
|
+
};
|
|
8256
|
+
}
|
|
8257
|
+
/**
|
|
8258
|
+
* Returns data lakes accessible to a user.
|
|
8259
|
+
*
|
|
8260
|
+
* Access rule (generic, any-of declared requirements): a lake is accessible iff it
|
|
8261
|
+
* declares NO access requirement, OR the user satisfies ANY declared requirement —
|
|
8262
|
+
* either `requiredUserTag` (matched against the user's tags) or `requiredEntitlement`
|
|
8263
|
+
* (matched against the caller's resolved `entitlementKeys`). A lake declaring an
|
|
8264
|
+
* entitlement but no tag is therefore NOT public (it is gated by the key).
|
|
8265
|
+
*
|
|
8266
|
+
* Data lakes without any requirement are accessible to all authenticated users.
|
|
8267
|
+
* When dynamicDataLakes is provided (fetched from DB), those take precedence over
|
|
8268
|
+
* hardcoded DATA_LAKES entries with the same id. `entitlementKeys` is optional — callers
|
|
8269
|
+
* that don't resolve entitlements (tag-only surfaces) omit it and get tag-only matching.
|
|
8150
8270
|
*/
|
|
8151
|
-
function getAccessibleDataLakes(userTags, dynamicDataLakes) {
|
|
8271
|
+
function getAccessibleDataLakes(userTags, dynamicDataLakes, entitlementKeys) {
|
|
8152
8272
|
const normalizedUserTags = userTags.map((tag) => tag.toLowerCase());
|
|
8273
|
+
const normalizedKeys = (entitlementKeys ?? []).map(normalizeEntitlementKey);
|
|
8153
8274
|
let allLakes;
|
|
8154
8275
|
if (dynamicDataLakes && dynamicDataLakes.length > 0) {
|
|
8155
8276
|
const dynamicIds = new Set(dynamicDataLakes.map((d) => d.id));
|
|
8156
8277
|
const fallbacks = DATA_LAKES.filter((dl) => !dynamicIds.has(dl.id));
|
|
8157
8278
|
allLakes = [...dynamicDataLakes, ...fallbacks];
|
|
8158
8279
|
} else allLakes = DATA_LAKES;
|
|
8159
|
-
return allLakes.filter((dl) =>
|
|
8160
|
-
|
|
8161
|
-
|
|
8162
|
-
|
|
8163
|
-
|
|
8164
|
-
|
|
8165
|
-
function getDataLakeTags(userTags, dynamicDataLakes) {
|
|
8166
|
-
return getAccessibleDataLakes(userTags, dynamicDataLakes).map((dl) => dl.datalakeTag);
|
|
8280
|
+
return allLakes.filter((dl) => {
|
|
8281
|
+
if (!(!!dl.requiredUserTag || !!dl.requiredEntitlement)) return true;
|
|
8282
|
+
const tagMatch = !!dl.requiredUserTag && normalizedUserTags.includes(dl.requiredUserTag.toLowerCase());
|
|
8283
|
+
const entMatch = !!dl.requiredEntitlement && normalizedKeys.includes(normalizeEntitlementKey(dl.requiredEntitlement));
|
|
8284
|
+
return tagMatch || entMatch;
|
|
8285
|
+
});
|
|
8167
8286
|
}
|
|
8168
8287
|
/**
|
|
8169
8288
|
* Jupyter Kernel Constants and Validation
|
|
@@ -8316,6 +8435,8 @@ z.object({
|
|
|
8316
8435
|
/** Notebook session ID */
|
|
8317
8436
|
sessionId: z.string(),
|
|
8318
8437
|
historyCount: z.number(),
|
|
8438
|
+
/** Epoch ms when the client submitted the prompt (for the request-lifecycle status log). */
|
|
8439
|
+
clientSubmittedAt: z.number().optional(),
|
|
8319
8440
|
imageConfig: GenerateImageToolCallSchema.optional(),
|
|
8320
8441
|
deepResearchConfig: z.object({
|
|
8321
8442
|
maxDepth: z.number().optional(),
|
|
@@ -8596,6 +8717,114 @@ BaseArtifactSchema.extend({
|
|
|
8596
8717
|
})
|
|
8597
8718
|
});
|
|
8598
8719
|
/**
|
|
8720
|
+
* Annotation schemas — the collaboration layer that sits on top of a
|
|
8721
|
+
* PublishedArtifact. An annotation is a structured input keyed to an artifact
|
|
8722
|
+
* by its `publicId`. The `kind` discriminator is deliberately generic: v1 ships
|
|
8723
|
+
* only `comment`, but `approval`/`vote`/`signature` are reserved so the layer
|
|
8724
|
+
* can grow into approval workflows and e-signature without a model migration.
|
|
8725
|
+
*
|
|
8726
|
+
* Anchoring is PINS-FIRST: an annotation may carry normalized viewport
|
|
8727
|
+
* coordinates (0..1) and a best-effort CSS selector. Robust element-range
|
|
8728
|
+
* anchoring is deferred. An annotation with no anchor is document-level.
|
|
8729
|
+
*
|
|
8730
|
+
* Every annotation records the artifact version it was made against
|
|
8731
|
+
* (`artifactVersionSha`, the artifact's `sha256Index` at the time) so feedback
|
|
8732
|
+
* stays pinned to the version it critiqued — this is also the input the AI
|
|
8733
|
+
* revision loop (Phase C) consumes.
|
|
8734
|
+
*/
|
|
8735
|
+
const AnnotationKindSchema = z.enum([
|
|
8736
|
+
"comment",
|
|
8737
|
+
"approval",
|
|
8738
|
+
"vote",
|
|
8739
|
+
"signature"
|
|
8740
|
+
]);
|
|
8741
|
+
/** Owner-controlled gate on WHO may annotate, orthogonal to artifact visibility
|
|
8742
|
+
* (which controls who may VIEW). `none` = read-only (today's behavior, default).
|
|
8743
|
+
* `open` = any authenticated viewer who passes the visibility gate. `restricted`
|
|
8744
|
+
* = owner + explicit allowlist (allowlist UI deferred). */
|
|
8745
|
+
const CommentPolicySchema = z.enum([
|
|
8746
|
+
"none",
|
|
8747
|
+
"open",
|
|
8748
|
+
"restricted"
|
|
8749
|
+
]);
|
|
8750
|
+
const AnnotationAnchorSchema = z.object({
|
|
8751
|
+
/** Normalized horizontal position within the artifact viewport, 0..1. */
|
|
8752
|
+
x: z.number().min(0).max(1).optional(),
|
|
8753
|
+
/** Normalized vertical position within the artifact document, 0..1. */
|
|
8754
|
+
y: z.number().min(0).max(1).optional(),
|
|
8755
|
+
/** Best-effort CSS selector path captured by the widget (may be stale). */
|
|
8756
|
+
selector: z.string().max(1024).optional(),
|
|
8757
|
+
/** Optional scroll-section label / fragment the pin was dropped in. */
|
|
8758
|
+
scrollSection: z.string().max(256).optional()
|
|
8759
|
+
});
|
|
8760
|
+
const AnnotationPayloadSchema = z.object({
|
|
8761
|
+
/** kind === 'approval' */
|
|
8762
|
+
decision: z.enum(["approve", "reject"]).optional(),
|
|
8763
|
+
/** kind === 'vote' */
|
|
8764
|
+
choice: z.string().max(256).optional(),
|
|
8765
|
+
/** kind === 'signature' */
|
|
8766
|
+
signedName: z.string().max(200).optional(),
|
|
8767
|
+
signatureHash: z.string().max(128).optional()
|
|
8768
|
+
}).optional();
|
|
8769
|
+
const ANNOTATION_BODY_MAX = 5e3;
|
|
8770
|
+
z.object({
|
|
8771
|
+
id: z.string(),
|
|
8772
|
+
/** FK → PublishedArtifact.publicId. */
|
|
8773
|
+
publicId: z.string(),
|
|
8774
|
+
/** PublishedArtifact.sha256Index at the time the annotation was made. */
|
|
8775
|
+
artifactVersionSha: z.string().optional(),
|
|
8776
|
+
kind: AnnotationKindSchema.prefault("comment"),
|
|
8777
|
+
authorId: z.string(),
|
|
8778
|
+
/** Denormalized for render — annotation authorship is immutable. */
|
|
8779
|
+
authorDisplayName: z.string().max(200),
|
|
8780
|
+
body: z.string().max(ANNOTATION_BODY_MAX),
|
|
8781
|
+
anchor: AnnotationAnchorSchema.optional(),
|
|
8782
|
+
/** null/absent = top-level; else this is a reply to another annotation. */
|
|
8783
|
+
threadRootId: z.string().nullish(),
|
|
8784
|
+
payload: AnnotationPayloadSchema,
|
|
8785
|
+
resolvedAt: z.date().nullish(),
|
|
8786
|
+
resolvedBy: z.string().nullish(),
|
|
8787
|
+
createdAt: z.date(),
|
|
8788
|
+
updatedAt: z.date(),
|
|
8789
|
+
deletedAt: z.date().nullish(),
|
|
8790
|
+
deletedBy: z.string().nullish()
|
|
8791
|
+
});
|
|
8792
|
+
z.object({
|
|
8793
|
+
body: z.string().min(1).max(ANNOTATION_BODY_MAX),
|
|
8794
|
+
/** v1 accepts only 'comment'; defaulted server-side. */
|
|
8795
|
+
kind: AnnotationKindSchema.optional(),
|
|
8796
|
+
anchor: AnnotationAnchorSchema.optional(),
|
|
8797
|
+
threadRootId: z.string().optional(),
|
|
8798
|
+
artifactVersionSha: z.string().optional(),
|
|
8799
|
+
payload: AnnotationPayloadSchema
|
|
8800
|
+
});
|
|
8801
|
+
z.object({
|
|
8802
|
+
body: z.string().min(1).max(ANNOTATION_BODY_MAX).optional(),
|
|
8803
|
+
/** Toggle resolution. true → resolve, false → reopen. */
|
|
8804
|
+
resolved: z.boolean().optional()
|
|
8805
|
+
}).refine((v) => v.body !== void 0 || v.resolved !== void 0, { message: "Nothing to update" });
|
|
8806
|
+
const AnnotationDtoSchema = z.object({
|
|
8807
|
+
id: z.string(),
|
|
8808
|
+
publicId: z.string(),
|
|
8809
|
+
kind: AnnotationKindSchema,
|
|
8810
|
+
authorId: z.string(),
|
|
8811
|
+
authorDisplayName: z.string(),
|
|
8812
|
+
body: z.string(),
|
|
8813
|
+
anchor: AnnotationAnchorSchema.optional(),
|
|
8814
|
+
threadRootId: z.string().nullish(),
|
|
8815
|
+
payload: AnnotationPayloadSchema,
|
|
8816
|
+
artifactVersionSha: z.string().optional(),
|
|
8817
|
+
resolvedAt: z.string().nullish(),
|
|
8818
|
+
createdAt: z.string()
|
|
8819
|
+
});
|
|
8820
|
+
z.object({
|
|
8821
|
+
annotations: z.array(AnnotationDtoSchema),
|
|
8822
|
+
/** Echoed so the widget can render the right affordance without a 2nd call. */
|
|
8823
|
+
commentPolicy: CommentPolicySchema,
|
|
8824
|
+
/** Whether the CURRENT caller may create an annotation right now. */
|
|
8825
|
+
canComment: z.boolean()
|
|
8826
|
+
});
|
|
8827
|
+
/**
|
|
8599
8828
|
* Published-artifact schemas — the B4M instantiation of the `artifact-publishing`
|
|
8600
8829
|
* blueprint (MillionOnMars/blueprints, extracted from Polaris Publish v1).
|
|
8601
8830
|
*
|
|
@@ -8677,6 +8906,9 @@ z.object({
|
|
|
8677
8906
|
visibility: VisibilitySchema.prefault("private"),
|
|
8678
8907
|
/** Group id a viewer must belong to when gated cross-scope. */
|
|
8679
8908
|
gatedToGroupId: z.string().optional(),
|
|
8909
|
+
/** Collaboration gate: who (among viewers) may annotate. Orthogonal to
|
|
8910
|
+
* `visibility`. Defaults to `none` (read-only) until the owner opts in. */
|
|
8911
|
+
commentPolicy: CommentPolicySchema.prefault("none"),
|
|
8680
8912
|
ownerId: z.string(),
|
|
8681
8913
|
lastPublishedBy: z.string().optional(),
|
|
8682
8914
|
source: PublishSourceSchema,
|
|
@@ -8694,6 +8926,8 @@ z.object({
|
|
|
8694
8926
|
publishedAt: z.date(),
|
|
8695
8927
|
previousVersionMeta: ArtifactVersionMetaSchema.optional(),
|
|
8696
8928
|
viewCount: z.int().nonnegative().prefault(0),
|
|
8929
|
+
/** Concurrency lock for AI revise (set while a revision is in flight). */
|
|
8930
|
+
revisingAt: z.date().nullish(),
|
|
8697
8931
|
createdAt: z.date(),
|
|
8698
8932
|
updatedAt: z.date(),
|
|
8699
8933
|
deletedAt: z.date().nullish(),
|
|
@@ -8728,6 +8962,8 @@ z.object({
|
|
|
8728
8962
|
description: z.string().max(1e3).optional(),
|
|
8729
8963
|
visibility: VisibilitySchema.optional(),
|
|
8730
8964
|
gatedToGroupId: z.string().optional(),
|
|
8965
|
+
/** Who may annotate the published artifact. Defaults to `none` (read-only). */
|
|
8966
|
+
commentPolicy: CommentPolicySchema.optional(),
|
|
8731
8967
|
source: PublishSourceSchema.optional(),
|
|
8732
8968
|
files: z.array(FileDescriptorSchema).min(1).max(PUBLISH_LIMITS.maxFiles)
|
|
8733
8969
|
});
|
|
@@ -8883,6 +9119,33 @@ function isGPTImage2Model(model) {
|
|
|
8883
9119
|
return model === "gpt-image-2" || model.startsWith("gpt-image-2");
|
|
8884
9120
|
}
|
|
8885
9121
|
/**
|
|
9122
|
+
* Whether a user can access a model. Access is any-of (mirrors the Q3b data-lake
|
|
9123
|
+
* rule, `getAccessibleDataLakes`): a non-admin reaches the model via
|
|
9124
|
+
* `allowedUserTags ∩ userTags` OR `allowedEntitlements ∩ entitlementKeys`.
|
|
9125
|
+
*
|
|
9126
|
+
* `entitlementKeys` is optional — when omitted/empty the entitlement branch is
|
|
9127
|
+
* inert, so a model with no `allowedEntitlements` behaves exactly as before
|
|
9128
|
+
* (tag-only). This lets a tag-less subscriber reach an entitlement-gated model
|
|
9129
|
+
* while leaving every existing tag-gated model unchanged (zero regression).
|
|
9130
|
+
*
|
|
9131
|
+
* Pure + zero-dependency (only types + the shared key normalizer), so it lives
|
|
9132
|
+
* in `@bike4mind/common` as the SINGLE source of truth — imported by the core
|
|
9133
|
+
* `@bike4mind/utils` re-export (server/services) AND the client
|
|
9134
|
+
* `useAccessibleModels` hook, which previously kept a hand-rolled twin "to avoid
|
|
9135
|
+
* AWS SDK imports". Common is browser-safe, so there is no longer any reason to
|
|
9136
|
+
* duplicate the logic.
|
|
9137
|
+
*/
|
|
9138
|
+
function isModelAccessible(model, userTags, isAdmin = false, entitlementKeys = []) {
|
|
9139
|
+
if (!model.enabled) return false;
|
|
9140
|
+
if (isAdmin) return true;
|
|
9141
|
+
const normalizedUserTags = userTags.map((tag) => tag.toLowerCase());
|
|
9142
|
+
const normalizedAllowedTags = (model.allowedUserTags ?? []).map((tag) => tag.toLowerCase());
|
|
9143
|
+
if (normalizedUserTags.some((tag) => normalizedAllowedTags.includes(tag))) return true;
|
|
9144
|
+
const normalizedKeys = entitlementKeys.map(normalizeEntitlementKey);
|
|
9145
|
+
const normalizedAllowedEntitlements = (model.allowedEntitlements ?? []).map(normalizeEntitlementKey);
|
|
9146
|
+
return normalizedKeys.some((key) => normalizedAllowedEntitlements.includes(key));
|
|
9147
|
+
}
|
|
9148
|
+
/**
|
|
8886
9149
|
* Telemetry Error Sanitizer
|
|
8887
9150
|
*
|
|
8888
9151
|
* Removes PII (Personally Identifiable Information) from error messages
|
|
@@ -9008,6 +9271,67 @@ z.array(triggerWordSchema).max(20, "Up to 20 trigger words allowed.").transform(
|
|
|
9008
9271
|
}
|
|
9009
9272
|
return out;
|
|
9010
9273
|
});
|
|
9274
|
+
/**
|
|
9275
|
+
* Skill body argument substitution. Shared by the server-side SkillsFeature,
|
|
9276
|
+
* the LLM `skill` tool, and the CLI's skill executor so the same patterns
|
|
9277
|
+
* resolve identically across surfaces.
|
|
9278
|
+
*
|
|
9279
|
+
* Supports Claude Code's substitution syntax:
|
|
9280
|
+
* - `$ARGUMENTS` — all positional args joined by spaces
|
|
9281
|
+
* - `$1`, `$2`, ... — individual positional args
|
|
9282
|
+
*
|
|
9283
|
+
* Why a shared helper: the CLI already implemented this in
|
|
9284
|
+
* `apps/cli/src/utils/argumentSubstitution.ts`. Centralizing here avoids a
|
|
9285
|
+
* second drift surface — a skill body authored on the web and run in the CLI
|
|
9286
|
+
* (or vice versa) must expand identically.
|
|
9287
|
+
*/
|
|
9288
|
+
function substituteArguments(template, args) {
|
|
9289
|
+
let result = template;
|
|
9290
|
+
for (let i = args.length; i >= 1; i--) {
|
|
9291
|
+
const pattern = new RegExp(`\\$${i}`, "g");
|
|
9292
|
+
result = result.replace(pattern, args[i - 1] ?? "");
|
|
9293
|
+
}
|
|
9294
|
+
return result.replace(/\$ARGUMENTS/g, args.join(" "));
|
|
9295
|
+
}
|
|
9296
|
+
/**
|
|
9297
|
+
* Shell-style argument splitter — supports double / single quotes for
|
|
9298
|
+
* grouping. Identical semantics to the CLI's `parseArguments`.
|
|
9299
|
+
*
|
|
9300
|
+
* parseSkillArguments('hello world') => ['hello', 'world']
|
|
9301
|
+
* parseSkillArguments('"hello world" test') => ['hello world', 'test']
|
|
9302
|
+
* parseSkillArguments("'one two' three") => ['one two', 'three']
|
|
9303
|
+
* parseSkillArguments('') => []
|
|
9304
|
+
*
|
|
9305
|
+
* Unclosed quotes are forgiven, not flagged: `parseSkillArguments('"unclosed')`
|
|
9306
|
+
* returns `['unclosed']`. This matches the CLI's pre-existing behavior and is
|
|
9307
|
+
* deliberate — skills are user-authored prose, not a shell, and surfacing a
|
|
9308
|
+
* parse error for a stray `"` would punish a typo more than the cost of a
|
|
9309
|
+
* slightly-wrong split warrants.
|
|
9310
|
+
*/
|
|
9311
|
+
function parseSkillArguments(input) {
|
|
9312
|
+
if (!input) return [];
|
|
9313
|
+
const args = [];
|
|
9314
|
+
let current = "";
|
|
9315
|
+
let inQuotes = false;
|
|
9316
|
+
let quoteChar = "";
|
|
9317
|
+
for (let i = 0; i < input.length; i++) {
|
|
9318
|
+
const char = input[i];
|
|
9319
|
+
if (!inQuotes && (char === "\"" || char === "'")) {
|
|
9320
|
+
inQuotes = true;
|
|
9321
|
+
quoteChar = char;
|
|
9322
|
+
} else if (inQuotes && char === quoteChar) {
|
|
9323
|
+
inQuotes = false;
|
|
9324
|
+
quoteChar = "";
|
|
9325
|
+
} else if (!inQuotes && /\s/.test(char)) {
|
|
9326
|
+
if (current.length > 0) {
|
|
9327
|
+
args.push(current);
|
|
9328
|
+
current = "";
|
|
9329
|
+
}
|
|
9330
|
+
} else current += char;
|
|
9331
|
+
}
|
|
9332
|
+
if (current.length > 0) args.push(current);
|
|
9333
|
+
return args;
|
|
9334
|
+
}
|
|
9011
9335
|
const VIEW_REGISTRY = [
|
|
9012
9336
|
{
|
|
9013
9337
|
id: "opti.root",
|
|
@@ -10364,6 +10688,14 @@ const CliConfigSchema = z.object({
|
|
|
10364
10688
|
exportFormat: z.enum(["markdown", "json"]),
|
|
10365
10689
|
maxIterations: z.number().nullable().prefault(10),
|
|
10366
10690
|
enableSkillTool: z.boolean().optional().prefault(true),
|
|
10691
|
+
/**
|
|
10692
|
+
* When false (or set via the `--no-remote-skills` CLI flag / the
|
|
10693
|
+
* `B4M_NO_REMOTE_SKILLS=1` env var), the CLI skips fetching skills from
|
|
10694
|
+
* the B4M backend's `/api/skills` endpoint and runs with local files only.
|
|
10695
|
+
* Defaults to true so authenticated users get cross-machine skill sync
|
|
10696
|
+
* out of the box.
|
|
10697
|
+
*/
|
|
10698
|
+
enableRemoteSkills: z.boolean().optional().prefault(true),
|
|
10367
10699
|
enableDynamicAgentCreation: z.boolean().optional().prefault(false),
|
|
10368
10700
|
enableCoordinatorMode: z.boolean().optional().prefault(false),
|
|
10369
10701
|
/**
|
|
@@ -10455,6 +10787,7 @@ const DEFAULT_CONFIG = {
|
|
|
10455
10787
|
exportFormat: "markdown",
|
|
10456
10788
|
maxIterations: 10,
|
|
10457
10789
|
enableSkillTool: true,
|
|
10790
|
+
enableRemoteSkills: true,
|
|
10458
10791
|
enableDynamicAgentCreation: false,
|
|
10459
10792
|
enableCoordinatorMode: false,
|
|
10460
10793
|
promptVariant: "current"
|
|
@@ -11121,4 +11454,4 @@ var ConfigStore = class {
|
|
|
11121
11454
|
}
|
|
11122
11455
|
};
|
|
11123
11456
|
//#endregion
|
|
11124
|
-
export { ProjectEvents as $, GenerateImageToolCallSchema as A, dayjsConfig_default as At, InviteEvents as B,
|
|
11457
|
+
export { ProjectEvents as $, parseRateLimitHeaders as $t, GenerateImageToolCallSchema as A, dayjsConfig_default as At, InviteEvents as B, obfuscateApiKey as Bt, ElabsEvents as C, UnauthorizedError as Ct, ForbiddenError as D, VideoModels as Dt, FileEvents as E, VideoGenerationUsageTransaction as Et, ImageEditUsageTransaction as F, isGPTImageModel as Ft, ModalEvents as G, settingsMap as Gt, KnowledgeType as H, resolveNavigationIntents as Ht, ImageGenerationUsageTransaction as I, isModelAccessible as It, OpenAIEmbeddingModel as J, validateJupyterKernelName as Jt, ModelBackend as K, substituteArguments as Kt, ImageModels as L, isSupportedEmbeddingModel as Lt, GenericCreditDeductTransaction as M, getMcpProviderMetadata as Mt, HTTPError as N, getViewById as Nt, FriendshipEvents as O, XAI_IMAGE_MODELS as Ot, HttpStatus as P, isGPTImage2Model as Pt, ProfileEvents as Q, isNearLimit as Qt, InboxEvents as R, isZodError as Rt, DashboardParamsSchema as S, UiNavigationEvents as St, FeedbackEvents as T, VIDEO_SIZE_CONSTRAINTS as Tt, LLMEvents as U, sanitizeTelemetryError as Ut, InviteType as V, parseSkillArguments as Vt, MiscEvents as W, secureParameters as Wt, Permission as X, buildRateLimitLogEntry as Xt, OpenAIImageGenerationInput as Y, validateNotebookPath as Yt, PermissionDeniedError as Z, extractSnippetMeta as Zt, ChatCompletionCreateInputSchema as _, TaskScheduleHandler as _t, ALERT_THRESHOLDS as a, ReceivedCreditTransaction as at, CompletionApiUsageTransaction as b, ToolUsageTransaction as bt, ApiKeyScope as c, ResearchModeParamsSchema as ct, ArtifactTypeSchema as d, ResearchTaskType as dt, CollectionType as en, PromptIntentSchema as et, AuthEvents as f, SessionEvents as ft, CREDIT_DEDUCT_TRANSACTION_TYPES as g, TagType as gt, BadRequestError as h, SupportedFabFileMimeTypes as ht, getEnvironmentName as i, RealtimeVoiceUsageTransaction as it, GenericCreditAddTransaction as j, getAccessibleDataLakes as jt, GEMINI_IMAGE_MODELS as k, b4mLLMTools as kt, ApiKeyType as l, ResearchTaskExecutionType as lt, BFL_SAFETY_TOLERANCE as m, SubscriptionCreditTransaction as mt, logger as n, PurchaseTransaction as nt, AiEvents as o, RechartsChartTypeList as ot, BFL_IMAGE_MODELS as p, SpeechToTextUsageTransaction as pt, NotFoundError as q, toDataLakeConfig as qt, getApiUrl as r, QuestMasterParamsSchema as rt, ApiKeyEvents as s, RegInviteEvents as st, ConfigStore as t, PromptMetaZodSchema as tt, AppFileEvents as u, ResearchTaskPeriodicFrequencyType as ut, ChatModels as v, TextGenerationUsageTransaction as vt, FavoriteDocumentType as w, UnprocessableEntityError as wt, CorruptedFileError as x, TransferCreditTransaction as xt, ClaudeArtifactMimeTypes as y, TooManyRequestsError as yt, InternalServerError as z, mapMimeTypeToArtifactType as zt };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { t as version } from "../package-
|
|
2
|
+
import { t as version } from "../package-BJU2qiwQ.mjs";
|
|
3
3
|
import { a as fetchLatestVersion, c as isNpmPrefixWritable, i as compareSemver } from "../updateChecker-C8xsNY2L.mjs";
|
|
4
4
|
import { t as checkRipgrep } from "../ripgrepCheck-BmkyTK2i.mjs";
|
|
5
5
|
import { execSync } from "child_process";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import { n as logger, r as getApiUrl, t as ConfigStore } from "../ConfigStore-
|
|
2
|
+
import { C as createCoordinateTaskTool, D as FallbackLlmBackend, E as ApiClient, F as generateCliTools, G as ReActAgent, N as loadContextFiles, O as ServerLlmBackend, P as PermissionManager, Q as CheckpointStore, T as createAgentDelegateTool, W as setWebSocketToolExecutor, X as RemoteSkillSource, Y as isReadOnlyTool, Z as CustomCommandStore, _ as createGetFileStructureTool, a as WebSocketToolExecutor, b as createWriteTodosTool, et as SessionStore, i as McpManager, n as SubagentOrchestrator, o as WebSocketConnectionManager, q as buildSystemPrompt, r as AgentStore, s as WebSocketLlmBackend, t as BackgroundAgentManager, v as createFindDefinitionTool, w as createBackgroundAgentTools, x as createSkillTool, y as createTodoStore } from "../BackgroundAgentManager-CcetLt8q.mjs";
|
|
3
|
+
import { n as logger, r as getApiUrl, t as ConfigStore } from "../ConfigStore-CNveAjEv.mjs";
|
|
4
4
|
import { t as DEFAULT_SANDBOX_CONFIG } from "../types-LyRNHOiS.mjs";
|
|
5
5
|
import { t as createSandboxRuntime } from "../SandboxRuntimeAdapter-ChGlxSGQ.mjs";
|
|
6
6
|
import { t as SandboxOrchestrator } from "../SandboxOrchestrator-BoINxbX4.mjs";
|
|
@@ -62,6 +62,10 @@ async function handleHeadlessCommand(options) {
|
|
|
62
62
|
process.exit(1);
|
|
63
63
|
}
|
|
64
64
|
const apiClient = new ApiClient(getApiUrl(config.apiConfig), configStore);
|
|
65
|
+
if (process.env.B4M_NO_REMOTE_SKILLS !== "1" && config.preferences.enableRemoteSkills !== false) try {
|
|
66
|
+
customCommandStore.setRemoteSource(new RemoteSkillSource(apiClient));
|
|
67
|
+
await customCommandStore.mergeRemoteCommands();
|
|
68
|
+
} catch {}
|
|
65
69
|
const tokenGetter = async () => {
|
|
66
70
|
return (await configStore.getAuthTokens())?.accessToken ?? null;
|
|
67
71
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { t as version } from "../package-
|
|
2
|
+
import { t as version } from "../package-BJU2qiwQ.mjs";
|
|
3
3
|
import { c as isNpmPrefixWritable, l as setAutoUpdatePreference, n as REEXEC_GUARD_ENV, o as forceCheckForUpdate, r as checkForUpdate, s as getAutoUpdatePreference, t as INSTALL_CMD, u as shouldAttemptAutoUpdate } from "../updateChecker-C8xsNY2L.mjs";
|
|
4
4
|
import { t as checkRipgrep } from "../ripgrepCheck-BmkyTK2i.mjs";
|
|
5
5
|
import { execSync, spawnSync } from "child_process";
|