@bike4mind/cli 0.2.29-subagent-delegation.18906 → 0.2.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/HydrationEngine-WGYKF46H.js +9 -0
- package/dist/{artifactExtractor-P6HJHLX3.js → artifactExtractor-4SBIE5OK.js} +1 -1
- package/dist/{chunk-XTJDV3TC.js → chunk-22VR7SKO.js} +2 -2
- package/dist/{chunk-SA634LPQ.js → chunk-5J4RL57F.js} +5 -9
- package/dist/chunk-RUI6HNLO.js +766 -0
- package/dist/{chunk-WKJ6QNRZ.js → chunk-TNFZP7FG.js} +1025 -202
- package/dist/{chunk-TKZJAHDN.js → chunk-UYN4HMRF.js} +2 -2
- package/dist/{chunk-HZNRFX2D.js → chunk-YQWFK5O2.js} +2 -2
- package/dist/{create-KVBSZB62.js → create-DCHG36CP.js} +3 -3
- package/dist/index.js +859 -213
- package/dist/{llmMarkdownGenerator-VSE57EX6.js → llmMarkdownGenerator-6MQKVOWW.js} +1 -1
- package/dist/{markdownGenerator-XWEXPIBL.js → markdownGenerator-4GDO3PTY.js} +1 -1
- package/dist/{mementoService-RYFJCSTB.js → mementoService-WDQFLLRV.js} +3 -3
- package/dist/{src-E6RPPN4X.js → src-DVEE3PS5.js} +9 -2
- package/dist/{src-BLBELFWF.js → src-ZAT7QMNA.js} +153 -1
- package/dist/{subtractCredits-BXCLZQVK.js → subtractCredits-LE54FRKC.js} +3 -3
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -5,7 +5,8 @@ import {
|
|
|
5
5
|
getEffectiveApiKey,
|
|
6
6
|
getOpenWeatherKey,
|
|
7
7
|
getSerperKey
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-22VR7SKO.js";
|
|
9
|
+
import "./chunk-RUI6HNLO.js";
|
|
9
10
|
import {
|
|
10
11
|
ConfigStore,
|
|
11
12
|
logger
|
|
@@ -14,8 +15,8 @@ import {
|
|
|
14
15
|
selectActiveBackgroundAgents,
|
|
15
16
|
useCliStore
|
|
16
17
|
} from "./chunk-TVW4ZESU.js";
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-UYN4HMRF.js";
|
|
19
|
+
import "./chunk-YQWFK5O2.js";
|
|
19
20
|
import {
|
|
20
21
|
BFLImageService,
|
|
21
22
|
BaseStorage,
|
|
@@ -27,7 +28,7 @@ import {
|
|
|
27
28
|
OpenAIBackend,
|
|
28
29
|
OpenAIImageService,
|
|
29
30
|
XAIImageService
|
|
30
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-5J4RL57F.js";
|
|
31
32
|
import {
|
|
32
33
|
AiEvents,
|
|
33
34
|
ApiKeyEvents,
|
|
@@ -83,7 +84,7 @@ import {
|
|
|
83
84
|
XAI_IMAGE_MODELS,
|
|
84
85
|
b4mLLMTools,
|
|
85
86
|
getMcpProviderMetadata
|
|
86
|
-
} from "./chunk-
|
|
87
|
+
} from "./chunk-TNFZP7FG.js";
|
|
87
88
|
import {
|
|
88
89
|
Logger
|
|
89
90
|
} from "./chunk-OCYRD7D6.js";
|
|
@@ -3331,8 +3332,7 @@ ${options.context}` : this.getSystemPrompt()
|
|
|
3331
3332
|
maxTokens,
|
|
3332
3333
|
temperature,
|
|
3333
3334
|
abortSignal: options.signal,
|
|
3334
|
-
tool_choice: this.context.toolChoice
|
|
3335
|
-
executeTools: false
|
|
3335
|
+
tool_choice: this.context.toolChoice
|
|
3336
3336
|
},
|
|
3337
3337
|
async (texts, completionInfo) => {
|
|
3338
3338
|
for (const text of texts) {
|
|
@@ -4073,7 +4073,8 @@ var recalculateUserStorageSchema = z14.object({
|
|
|
4073
4073
|
// ../../b4m-core/packages/services/dist/src/userService/listRecentActivities.js
|
|
4074
4074
|
import { z as z15 } from "zod";
|
|
4075
4075
|
var listRecentActivitiesSchema = z15.object({
|
|
4076
|
-
coverage: z15.enum(["all", "important"]).default("important")
|
|
4076
|
+
coverage: z15.enum(["all", "important"]).default("important"),
|
|
4077
|
+
userId: z15.string().optional()
|
|
4077
4078
|
});
|
|
4078
4079
|
var IMPORTANT_COUNTER_NAMES = [
|
|
4079
4080
|
SessionEvents.CREATE_SESSION,
|
|
@@ -5717,7 +5718,19 @@ import { z as z129 } from "zod";
|
|
|
5717
5718
|
var createArtifactSchema = z129.object({
|
|
5718
5719
|
id: z129.string().optional(),
|
|
5719
5720
|
// Allow custom ID for AI-generated artifacts
|
|
5720
|
-
type: z129.enum([
|
|
5721
|
+
type: z129.enum([
|
|
5722
|
+
"mermaid",
|
|
5723
|
+
"recharts",
|
|
5724
|
+
"python",
|
|
5725
|
+
"react",
|
|
5726
|
+
"html",
|
|
5727
|
+
"svg",
|
|
5728
|
+
"code",
|
|
5729
|
+
"quest",
|
|
5730
|
+
"file",
|
|
5731
|
+
"questmaster",
|
|
5732
|
+
"lattice"
|
|
5733
|
+
]),
|
|
5721
5734
|
title: z129.string().min(1).max(255),
|
|
5722
5735
|
description: z129.string().max(1e3).optional(),
|
|
5723
5736
|
content: z129.string().min(1),
|
|
@@ -10325,6 +10338,819 @@ BLOCKED OPERATIONS:
|
|
|
10325
10338
|
})
|
|
10326
10339
|
};
|
|
10327
10340
|
|
|
10341
|
+
// ../../b4m-core/packages/services/dist/src/llm/tools/implementation/lattice/index.js
|
|
10342
|
+
function createModelData(name, modelType, userId, description, sessionId) {
|
|
10343
|
+
const now = /* @__PURE__ */ new Date();
|
|
10344
|
+
return {
|
|
10345
|
+
name,
|
|
10346
|
+
description: description || "",
|
|
10347
|
+
modelType,
|
|
10348
|
+
userId,
|
|
10349
|
+
sessionId,
|
|
10350
|
+
data: { entities: [], relationships: [] },
|
|
10351
|
+
rules: { rules: [], rulesets: [] },
|
|
10352
|
+
views: { views: [] },
|
|
10353
|
+
settings: {
|
|
10354
|
+
currency: "USD",
|
|
10355
|
+
fiscalYearStart: "01-01",
|
|
10356
|
+
periodGrain: "quarter",
|
|
10357
|
+
defaultDecimalPlaces: 2,
|
|
10358
|
+
negativeFormat: "parentheses"
|
|
10359
|
+
},
|
|
10360
|
+
scenarios: [],
|
|
10361
|
+
operations: [],
|
|
10362
|
+
operationIndex: -1,
|
|
10363
|
+
version: 1,
|
|
10364
|
+
createdAt: now,
|
|
10365
|
+
updatedAt: now
|
|
10366
|
+
};
|
|
10367
|
+
}
|
|
10368
|
+
var latticeCreateModelTool = {
|
|
10369
|
+
name: "lattice_create_model",
|
|
10370
|
+
implementation: (context) => ({
|
|
10371
|
+
toolFn: async (params) => {
|
|
10372
|
+
const { name, description, modelType = "custom", initialData } = params;
|
|
10373
|
+
console.log("[LATTICE DEBUG] \u{1F3D7}\uFE0F lattice_create_model called:", {
|
|
10374
|
+
name,
|
|
10375
|
+
description,
|
|
10376
|
+
modelType,
|
|
10377
|
+
hasInitialData: !!initialData,
|
|
10378
|
+
entityCount: initialData?.entities?.length || 0,
|
|
10379
|
+
ruleCount: initialData?.rules?.length || 0
|
|
10380
|
+
});
|
|
10381
|
+
const modelData = createModelData(name, modelType, context.userId, description);
|
|
10382
|
+
if (initialData?.entities && modelData.data) {
|
|
10383
|
+
const now = /* @__PURE__ */ new Date();
|
|
10384
|
+
for (const entityDef of initialData.entities) {
|
|
10385
|
+
const entityId = entityDef.name.toLowerCase().replace(/\s+/g, "_");
|
|
10386
|
+
const attributes = [];
|
|
10387
|
+
if (entityDef.values) {
|
|
10388
|
+
for (const val of entityDef.values) {
|
|
10389
|
+
attributes.push({
|
|
10390
|
+
key: "period",
|
|
10391
|
+
value: val.period,
|
|
10392
|
+
dataType: "string",
|
|
10393
|
+
isComputed: false
|
|
10394
|
+
});
|
|
10395
|
+
attributes.push({
|
|
10396
|
+
key: "value",
|
|
10397
|
+
value: val.value,
|
|
10398
|
+
dataType: "currency",
|
|
10399
|
+
isComputed: false
|
|
10400
|
+
});
|
|
10401
|
+
attributes.push({
|
|
10402
|
+
key: "category",
|
|
10403
|
+
value: entityDef.name,
|
|
10404
|
+
dataType: "string",
|
|
10405
|
+
isComputed: false
|
|
10406
|
+
});
|
|
10407
|
+
modelData.data.entities.push({
|
|
10408
|
+
id: `${entityId}_${val.period.toLowerCase().replace(/\s+/g, "_")}`,
|
|
10409
|
+
type: entityDef.type || "line_item",
|
|
10410
|
+
name: `${entityDef.name} ${val.period}`,
|
|
10411
|
+
displayName: `${entityDef.name} ${val.period}`,
|
|
10412
|
+
attributes: [
|
|
10413
|
+
{ key: "period", value: val.period, dataType: "string", isComputed: false },
|
|
10414
|
+
{ key: "value", value: val.value, dataType: "currency", isComputed: false },
|
|
10415
|
+
{ key: "category", value: entityDef.name, dataType: "string", isComputed: false }
|
|
10416
|
+
],
|
|
10417
|
+
metadata: {},
|
|
10418
|
+
createdAt: now,
|
|
10419
|
+
updatedAt: now
|
|
10420
|
+
});
|
|
10421
|
+
}
|
|
10422
|
+
}
|
|
10423
|
+
console.log(`[LATTICE DEBUG] \u2795 Created entity: ${entityDef.name} with ${entityDef.values?.length || 0} period values`);
|
|
10424
|
+
}
|
|
10425
|
+
}
|
|
10426
|
+
if (initialData?.rules && modelData.rules) {
|
|
10427
|
+
const now = /* @__PURE__ */ new Date();
|
|
10428
|
+
for (const ruleDef of initialData.rules) {
|
|
10429
|
+
const ruleId = `rule_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`;
|
|
10430
|
+
const parsedRule = parseFormula(ruleDef.formula);
|
|
10431
|
+
modelData.rules.rules.push({
|
|
10432
|
+
id: ruleId,
|
|
10433
|
+
name: ruleDef.name,
|
|
10434
|
+
description: ruleDef.formula,
|
|
10435
|
+
type: "formula",
|
|
10436
|
+
definition: {
|
|
10437
|
+
operation: parsedRule.operation,
|
|
10438
|
+
inputs: parsedRule.inputs.map((ref) => ({ type: "entity", ref })),
|
|
10439
|
+
output: {
|
|
10440
|
+
targetEntityId: parsedRule.outputEntity.toLowerCase().replace(/\s+/g, "_"),
|
|
10441
|
+
targetAttribute: "computed",
|
|
10442
|
+
dataType: "number"
|
|
10443
|
+
}
|
|
10444
|
+
},
|
|
10445
|
+
dependencies: parsedRule.inputs.map((i) => i.toLowerCase().replace(/\s+/g, "_")),
|
|
10446
|
+
priority: 0,
|
|
10447
|
+
enabled: true,
|
|
10448
|
+
createdAt: now,
|
|
10449
|
+
updatedAt: now
|
|
10450
|
+
});
|
|
10451
|
+
console.log(`[LATTICE DEBUG] \u{1F4D0} Created rule: ${ruleDef.name} = ${ruleDef.formula}`);
|
|
10452
|
+
}
|
|
10453
|
+
}
|
|
10454
|
+
let model;
|
|
10455
|
+
let persistenceStatus = "unknown";
|
|
10456
|
+
const dbKeys = Object.keys(context.db || {});
|
|
10457
|
+
const hasLatticeModels = !!context.db?.latticeModels;
|
|
10458
|
+
if (context.db.latticeModels) {
|
|
10459
|
+
try {
|
|
10460
|
+
model = await context.db.latticeModels.create(modelData);
|
|
10461
|
+
persistenceStatus = `PERSISTED to MongoDB (id: ${model.id})`;
|
|
10462
|
+
context.logger.info(`[Lattice] Created model ${model.id} in database`);
|
|
10463
|
+
} catch (error) {
|
|
10464
|
+
persistenceStatus = `FAILED: ${error instanceof Error ? error.message : String(error)}`;
|
|
10465
|
+
context.logger.error(`[Lattice] Failed to persist model to database:`, error);
|
|
10466
|
+
model = {
|
|
10467
|
+
...modelData,
|
|
10468
|
+
id: `lattice_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
|
10469
|
+
};
|
|
10470
|
+
}
|
|
10471
|
+
} else {
|
|
10472
|
+
persistenceStatus = `IN-MEMORY (no latticeModels adapter). DB keys: [${dbKeys.join(", ")}]`;
|
|
10473
|
+
context.logger.warn("[Lattice] No database adapter available, creating in-memory model");
|
|
10474
|
+
model = {
|
|
10475
|
+
...modelData,
|
|
10476
|
+
id: `lattice_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
|
10477
|
+
};
|
|
10478
|
+
}
|
|
10479
|
+
const artifactData = {
|
|
10480
|
+
type: "lattice",
|
|
10481
|
+
id: model.id,
|
|
10482
|
+
title: name,
|
|
10483
|
+
content: JSON.stringify(model),
|
|
10484
|
+
metadata: {
|
|
10485
|
+
modelType,
|
|
10486
|
+
periodGrain: model.settings?.periodGrain || "quarter",
|
|
10487
|
+
currency: model.settings?.currency || "USD",
|
|
10488
|
+
entityCount: model.data?.entities?.length || 0,
|
|
10489
|
+
ruleCount: model.rules?.rules?.length || 0,
|
|
10490
|
+
// DEBUG: Include persistence info in metadata
|
|
10491
|
+
_debug: {
|
|
10492
|
+
persistenceStatus,
|
|
10493
|
+
hasLatticeModels,
|
|
10494
|
+
dbKeys
|
|
10495
|
+
}
|
|
10496
|
+
},
|
|
10497
|
+
createdAt: model.createdAt?.toISOString?.() || (/* @__PURE__ */ new Date()).toISOString(),
|
|
10498
|
+
updatedAt: model.updatedAt?.toISOString?.() || (/* @__PURE__ */ new Date()).toISOString()
|
|
10499
|
+
};
|
|
10500
|
+
const entityCount = model.data?.entities?.length || 0;
|
|
10501
|
+
const ruleCount = model.rules?.rules?.length || 0;
|
|
10502
|
+
return `Created "${name}" model with ${entityCount} entities and ${ruleCount} rules.
|
|
10503
|
+
|
|
10504
|
+
<artifact identifier="${model.id}" type="application/vnd.b4m.lattice" title="${name}">
|
|
10505
|
+
${JSON.stringify(artifactData, null, 2)}
|
|
10506
|
+
</artifact>
|
|
10507
|
+
|
|
10508
|
+
The model is ready for viewing. You can add more data by asking to add line items or create formulas.`;
|
|
10509
|
+
},
|
|
10510
|
+
toolSchema: {
|
|
10511
|
+
name: "lattice_create_model",
|
|
10512
|
+
description: `Create a new Lattice financial model with optional initial data. Use initialData to populate entities and rules in ONE call.
|
|
10513
|
+
|
|
10514
|
+
**IMPORTANT**: Always include initialData when the user provides specific values! This creates a fully populated model immediately.
|
|
10515
|
+
|
|
10516
|
+
**When to use:** When the user wants to:
|
|
10517
|
+
- Create a new financial model, spreadsheet, or pro-forma
|
|
10518
|
+
- Start building an income statement, balance sheet, or cash flow
|
|
10519
|
+
- Set up a SaaS metrics dashboard
|
|
10520
|
+
|
|
10521
|
+
**Example with initialData:**
|
|
10522
|
+
User: "Create income statement with $100K revenue and $60K costs for Q1"
|
|
10523
|
+
Call: lattice_create_model with:
|
|
10524
|
+
- name: "Income Statement"
|
|
10525
|
+
- modelType: "income_statement"
|
|
10526
|
+
- initialData: {
|
|
10527
|
+
entities: [
|
|
10528
|
+
{ name: "Revenue", values: [{ period: "Q1", value: 100000 }] },
|
|
10529
|
+
{ name: "Costs", values: [{ period: "Q1", value: 60000 }] }
|
|
10530
|
+
],
|
|
10531
|
+
rules: [
|
|
10532
|
+
{ name: "Gross Profit", formula: "Gross Profit = Revenue - Costs" }
|
|
10533
|
+
]
|
|
10534
|
+
}`,
|
|
10535
|
+
parameters: {
|
|
10536
|
+
type: "object",
|
|
10537
|
+
properties: {
|
|
10538
|
+
name: {
|
|
10539
|
+
type: "string",
|
|
10540
|
+
description: 'Name of the model (e.g., "2024 Budget", "Q1 Forecast")'
|
|
10541
|
+
},
|
|
10542
|
+
description: {
|
|
10543
|
+
type: "string",
|
|
10544
|
+
description: "Optional description of what this model represents"
|
|
10545
|
+
},
|
|
10546
|
+
modelType: {
|
|
10547
|
+
type: "string",
|
|
10548
|
+
enum: ["income_statement", "balance_sheet", "cashflow", "saas_metrics", "custom"],
|
|
10549
|
+
description: "Type of financial model to create"
|
|
10550
|
+
},
|
|
10551
|
+
initialData: {
|
|
10552
|
+
type: "object",
|
|
10553
|
+
description: "Initial entities and rules to populate the model. ALWAYS use this when user provides data!",
|
|
10554
|
+
properties: {
|
|
10555
|
+
entities: {
|
|
10556
|
+
type: "array",
|
|
10557
|
+
description: "Line items with their period values",
|
|
10558
|
+
items: {
|
|
10559
|
+
type: "object",
|
|
10560
|
+
properties: {
|
|
10561
|
+
name: { type: "string", description: 'Entity name (e.g., "Revenue", "COGS")' },
|
|
10562
|
+
type: { type: "string", description: "Entity type (default: line_item)" },
|
|
10563
|
+
values: {
|
|
10564
|
+
type: "array",
|
|
10565
|
+
description: "Period-value pairs",
|
|
10566
|
+
items: {
|
|
10567
|
+
type: "object",
|
|
10568
|
+
properties: {
|
|
10569
|
+
period: { type: "string", description: 'Period name (e.g., "Q1", "Jan", "2024")' },
|
|
10570
|
+
value: { type: "number", description: "Numeric value" }
|
|
10571
|
+
},
|
|
10572
|
+
required: ["period", "value"]
|
|
10573
|
+
}
|
|
10574
|
+
}
|
|
10575
|
+
},
|
|
10576
|
+
required: ["name"]
|
|
10577
|
+
}
|
|
10578
|
+
},
|
|
10579
|
+
rules: {
|
|
10580
|
+
type: "array",
|
|
10581
|
+
description: "Formulas/calculations to create",
|
|
10582
|
+
items: {
|
|
10583
|
+
type: "object",
|
|
10584
|
+
properties: {
|
|
10585
|
+
name: { type: "string", description: 'Rule name (e.g., "Gross Profit Calculation")' },
|
|
10586
|
+
formula: {
|
|
10587
|
+
type: "string",
|
|
10588
|
+
description: 'Natural language formula (e.g., "Gross Profit = Revenue - Costs")'
|
|
10589
|
+
}
|
|
10590
|
+
},
|
|
10591
|
+
required: ["name", "formula"]
|
|
10592
|
+
}
|
|
10593
|
+
}
|
|
10594
|
+
}
|
|
10595
|
+
}
|
|
10596
|
+
},
|
|
10597
|
+
required: ["name"]
|
|
10598
|
+
}
|
|
10599
|
+
}
|
|
10600
|
+
})
|
|
10601
|
+
};
|
|
10602
|
+
var latticeAddEntityTool = {
|
|
10603
|
+
name: "lattice_add_entity",
|
|
10604
|
+
implementation: (context) => ({
|
|
10605
|
+
toolFn: async (params) => {
|
|
10606
|
+
const { modelId, name, type, displayName, initialValues = [] } = params;
|
|
10607
|
+
console.log("[LATTICE DEBUG] \u2795 lattice_add_entity called:", { modelId, name, type, initialValues });
|
|
10608
|
+
const entityId = name.toLowerCase().replace(/\s+/g, "_");
|
|
10609
|
+
const entityData = {
|
|
10610
|
+
id: entityId,
|
|
10611
|
+
type,
|
|
10612
|
+
name,
|
|
10613
|
+
displayName: displayName || name,
|
|
10614
|
+
attributes: initialValues.map((v) => ({
|
|
10615
|
+
key: v.key,
|
|
10616
|
+
value: v.value,
|
|
10617
|
+
dataType: v.dataType || (typeof v.value === "number" ? "number" : "string"),
|
|
10618
|
+
isComputed: false
|
|
10619
|
+
})),
|
|
10620
|
+
metadata: {},
|
|
10621
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
10622
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
10623
|
+
};
|
|
10624
|
+
if (context.db.latticeModels && modelId && /^[a-f0-9]{24}$/.test(modelId)) {
|
|
10625
|
+
try {
|
|
10626
|
+
const model = await context.db.latticeModels.findById(modelId);
|
|
10627
|
+
if (model) {
|
|
10628
|
+
const existingIndex = model.data.entities.findIndex((e) => e.id === entityId);
|
|
10629
|
+
if (existingIndex >= 0) {
|
|
10630
|
+
model.data.entities[existingIndex] = entityData;
|
|
10631
|
+
} else {
|
|
10632
|
+
model.data.entities.push(entityData);
|
|
10633
|
+
}
|
|
10634
|
+
await context.db.latticeModels.update({
|
|
10635
|
+
id: modelId,
|
|
10636
|
+
data: model.data,
|
|
10637
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
10638
|
+
});
|
|
10639
|
+
context.logger.info(`[Lattice] Added entity ${entityId} to model ${modelId}`);
|
|
10640
|
+
} else {
|
|
10641
|
+
context.logger.warn(`[Lattice] Model ${modelId} not found in database`);
|
|
10642
|
+
}
|
|
10643
|
+
} catch (error) {
|
|
10644
|
+
context.logger.error(`[Lattice] Failed to persist entity to database:`, error);
|
|
10645
|
+
}
|
|
10646
|
+
}
|
|
10647
|
+
return JSON.stringify({
|
|
10648
|
+
success: true,
|
|
10649
|
+
action: "ADD_ENTITY",
|
|
10650
|
+
modelId,
|
|
10651
|
+
entityId,
|
|
10652
|
+
data: entityData,
|
|
10653
|
+
message: `Added ${type} "${displayName || name}" to model. ${initialValues.length > 0 ? `Set initial values: ${initialValues.map((v) => `${v.key}=${v.value}`).join(", ")}` : "No initial values set."}`
|
|
10654
|
+
});
|
|
10655
|
+
},
|
|
10656
|
+
toolSchema: {
|
|
10657
|
+
name: "lattice_add_entity",
|
|
10658
|
+
description: `Add a line item, account, period, or other entity to a Lattice model.
|
|
10659
|
+
|
|
10660
|
+
**When to use:** When the user mentions:
|
|
10661
|
+
- Adding a revenue line, expense category, or account
|
|
10662
|
+
- Creating periods (Q1, Q2, Jan, Feb, etc.)
|
|
10663
|
+
- Adding any measurable item to their model
|
|
10664
|
+
|
|
10665
|
+
**Entity types:**
|
|
10666
|
+
- line_item: Revenue streams, expense lines, KPIs
|
|
10667
|
+
- account: Cash, AR, AP, inventory, etc.
|
|
10668
|
+
- period: Q1 2024, Jan, FY2025, etc.
|
|
10669
|
+
- category: Groups of line items (Operating Expenses)
|
|
10670
|
+
- scenario: Base case, upside, downside
|
|
10671
|
+
- custom: Any other structured element
|
|
10672
|
+
|
|
10673
|
+
**Examples:**
|
|
10674
|
+
- "Add Revenue" \u2192 line_item named "Revenue"
|
|
10675
|
+
- "Create a Marketing Expenses category" \u2192 category named "Marketing Expenses"
|
|
10676
|
+
- "Add quarters Q1 through Q4" \u2192 4 period entities`,
|
|
10677
|
+
parameters: {
|
|
10678
|
+
type: "object",
|
|
10679
|
+
properties: {
|
|
10680
|
+
modelId: {
|
|
10681
|
+
type: "string",
|
|
10682
|
+
description: "ID of the model to add the entity to"
|
|
10683
|
+
},
|
|
10684
|
+
name: {
|
|
10685
|
+
type: "string",
|
|
10686
|
+
description: "Internal name for the entity (used in formulas)"
|
|
10687
|
+
},
|
|
10688
|
+
type: {
|
|
10689
|
+
type: "string",
|
|
10690
|
+
enum: ["line_item", "account", "period", "category", "scenario", "custom"],
|
|
10691
|
+
description: "Type of entity"
|
|
10692
|
+
},
|
|
10693
|
+
displayName: {
|
|
10694
|
+
type: "string",
|
|
10695
|
+
description: "Human-readable display name (defaults to name)"
|
|
10696
|
+
},
|
|
10697
|
+
initialValues: {
|
|
10698
|
+
type: "array",
|
|
10699
|
+
items: {
|
|
10700
|
+
type: "object",
|
|
10701
|
+
properties: {
|
|
10702
|
+
key: { type: "string", description: 'Period or attribute key (e.g., "Q1_2024")' },
|
|
10703
|
+
value: { type: "string", description: "The value (number or string)" },
|
|
10704
|
+
dataType: {
|
|
10705
|
+
type: "string",
|
|
10706
|
+
enum: ["number", "currency", "percentage", "string"],
|
|
10707
|
+
description: "Data type for the value"
|
|
10708
|
+
}
|
|
10709
|
+
},
|
|
10710
|
+
required: ["key", "value"]
|
|
10711
|
+
},
|
|
10712
|
+
description: "Optional initial values for this entity"
|
|
10713
|
+
}
|
|
10714
|
+
},
|
|
10715
|
+
required: ["modelId", "name", "type"]
|
|
10716
|
+
}
|
|
10717
|
+
}
|
|
10718
|
+
})
|
|
10719
|
+
};
|
|
10720
|
+
var latticeSetValueTool = {
|
|
10721
|
+
name: "lattice_set_value",
|
|
10722
|
+
implementation: (context) => ({
|
|
10723
|
+
toolFn: async (params) => {
|
|
10724
|
+
const { modelId, entityName, attributeKey, value: rawValue } = params;
|
|
10725
|
+
console.log("[LATTICE DEBUG] \u{1F4DD} lattice_set_value called:", { modelId, entityName, attributeKey, rawValue });
|
|
10726
|
+
let value = rawValue;
|
|
10727
|
+
const numValue = parseFloat(rawValue);
|
|
10728
|
+
if (!isNaN(numValue)) {
|
|
10729
|
+
value = numValue;
|
|
10730
|
+
} else if (rawValue.toLowerCase() === "true") {
|
|
10731
|
+
value = true;
|
|
10732
|
+
} else if (rawValue.toLowerCase() === "false") {
|
|
10733
|
+
value = false;
|
|
10734
|
+
}
|
|
10735
|
+
const entityId = entityName.toLowerCase().replace(/\s+/g, "_");
|
|
10736
|
+
if (context.db.latticeModels && modelId && /^[a-f0-9]{24}$/.test(modelId)) {
|
|
10737
|
+
try {
|
|
10738
|
+
const model = await context.db.latticeModels.findById(modelId);
|
|
10739
|
+
if (model) {
|
|
10740
|
+
const entity = model.data.entities.find((e) => e.id === entityId || e.name === entityName);
|
|
10741
|
+
if (entity) {
|
|
10742
|
+
const attrIndex = entity.attributes.findIndex((a) => a.key === attributeKey);
|
|
10743
|
+
const dataType = typeof value === "number" ? "number" : typeof value === "boolean" ? "boolean" : "string";
|
|
10744
|
+
const attributeData = {
|
|
10745
|
+
key: attributeKey,
|
|
10746
|
+
value,
|
|
10747
|
+
dataType,
|
|
10748
|
+
isComputed: false
|
|
10749
|
+
};
|
|
10750
|
+
if (attrIndex >= 0) {
|
|
10751
|
+
entity.attributes[attrIndex] = attributeData;
|
|
10752
|
+
} else {
|
|
10753
|
+
entity.attributes.push(attributeData);
|
|
10754
|
+
}
|
|
10755
|
+
entity.updatedAt = /* @__PURE__ */ new Date();
|
|
10756
|
+
await context.db.latticeModels.update({
|
|
10757
|
+
id: modelId,
|
|
10758
|
+
data: model.data,
|
|
10759
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
10760
|
+
});
|
|
10761
|
+
context.logger.info(`[Lattice] Set ${entityId}.${attributeKey} = ${value} in model ${modelId}`);
|
|
10762
|
+
} else {
|
|
10763
|
+
context.logger.warn(`[Lattice] Entity ${entityName} not found in model ${modelId}`);
|
|
10764
|
+
}
|
|
10765
|
+
} else {
|
|
10766
|
+
context.logger.warn(`[Lattice] Model ${modelId} not found in database`);
|
|
10767
|
+
}
|
|
10768
|
+
} catch (error) {
|
|
10769
|
+
context.logger.error(`[Lattice] Failed to persist value to database:`, error);
|
|
10770
|
+
}
|
|
10771
|
+
}
|
|
10772
|
+
return JSON.stringify({
|
|
10773
|
+
success: true,
|
|
10774
|
+
action: "SET_VALUE",
|
|
10775
|
+
modelId,
|
|
10776
|
+
data: {
|
|
10777
|
+
entityName,
|
|
10778
|
+
attributeKey,
|
|
10779
|
+
value
|
|
10780
|
+
},
|
|
10781
|
+
message: `Set ${entityName}.${attributeKey} = ${value}`
|
|
10782
|
+
});
|
|
10783
|
+
},
|
|
10784
|
+
toolSchema: {
|
|
10785
|
+
name: "lattice_set_value",
|
|
10786
|
+
description: `Set a specific value in a Lattice model.
|
|
10787
|
+
|
|
10788
|
+
**When to use:** When the user provides a specific number:
|
|
10789
|
+
- "Revenue in Q1 is 150,000"
|
|
10790
|
+
- "Set marketing spend to 50k for January"
|
|
10791
|
+
- "COGS is 40% of revenue" (use lattice_create_rule for formulas)
|
|
10792
|
+
|
|
10793
|
+
**Important:** This tool is for setting raw input values. For calculated values (formulas), use \`lattice_create_rule\` instead.
|
|
10794
|
+
|
|
10795
|
+
**Examples:**
|
|
10796
|
+
- "Q1 revenue is $100,000" \u2192 entityName="Revenue", attributeKey="Q1", value=100000
|
|
10797
|
+
- "Set headcount to 25" \u2192 entityName="Headcount", attributeKey="current", value=25`,
|
|
10798
|
+
parameters: {
|
|
10799
|
+
type: "object",
|
|
10800
|
+
properties: {
|
|
10801
|
+
modelId: {
|
|
10802
|
+
type: "string",
|
|
10803
|
+
description: "ID of the model"
|
|
10804
|
+
},
|
|
10805
|
+
entityName: {
|
|
10806
|
+
type: "string",
|
|
10807
|
+
description: "Name of the entity (line item, account, etc.)"
|
|
10808
|
+
},
|
|
10809
|
+
attributeKey: {
|
|
10810
|
+
type: "string",
|
|
10811
|
+
description: 'Period or attribute key (e.g., "Q1_2024", "current", "budget")'
|
|
10812
|
+
},
|
|
10813
|
+
value: {
|
|
10814
|
+
type: "string",
|
|
10815
|
+
description: "The value to set (will be parsed as number if numeric)"
|
|
10816
|
+
}
|
|
10817
|
+
},
|
|
10818
|
+
required: ["modelId", "entityName", "attributeKey", "value"]
|
|
10819
|
+
}
|
|
10820
|
+
}
|
|
10821
|
+
})
|
|
10822
|
+
};
|
|
10823
|
+
var latticeCreateRuleTool = {
|
|
10824
|
+
name: "lattice_create_rule",
|
|
10825
|
+
implementation: (context) => ({
|
|
10826
|
+
toolFn: async (params) => {
|
|
10827
|
+
const { modelId, name, description, formula } = params;
|
|
10828
|
+
console.log("[LATTICE DEBUG] \u{1F4D0} lattice_create_rule called:", { modelId, name, formula });
|
|
10829
|
+
const parsedRule = parseFormula(formula);
|
|
10830
|
+
const ruleId = `rule_${Date.now()}`;
|
|
10831
|
+
const ruleData = {
|
|
10832
|
+
id: ruleId,
|
|
10833
|
+
name,
|
|
10834
|
+
description: description || formula,
|
|
10835
|
+
type: "formula",
|
|
10836
|
+
definition: {
|
|
10837
|
+
operation: parsedRule.operation,
|
|
10838
|
+
inputs: parsedRule.inputs.map((ref) => ({
|
|
10839
|
+
type: "entity",
|
|
10840
|
+
ref
|
|
10841
|
+
})),
|
|
10842
|
+
output: {
|
|
10843
|
+
targetEntityId: parsedRule.outputEntity.toLowerCase().replace(/\s+/g, "_"),
|
|
10844
|
+
targetAttribute: "computed",
|
|
10845
|
+
dataType: "number"
|
|
10846
|
+
}
|
|
10847
|
+
},
|
|
10848
|
+
dependencies: parsedRule.inputs.map((i) => i.toLowerCase().replace(/\s+/g, "_")),
|
|
10849
|
+
priority: 0,
|
|
10850
|
+
enabled: true,
|
|
10851
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
10852
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
10853
|
+
};
|
|
10854
|
+
const outputEntityId = parsedRule.outputEntity.toLowerCase().replace(/\s+/g, "_");
|
|
10855
|
+
let entityCreatedMessage = "";
|
|
10856
|
+
if (context.db.latticeModels && modelId && /^[a-f0-9]{24}$/.test(modelId)) {
|
|
10857
|
+
try {
|
|
10858
|
+
const model = await context.db.latticeModels.findById(modelId);
|
|
10859
|
+
if (model) {
|
|
10860
|
+
const outputEntityExists = model.data.entities.some((e) => e.id === outputEntityId || e.name.toLowerCase() === parsedRule.outputEntity.toLowerCase());
|
|
10861
|
+
if (!outputEntityExists && parsedRule.outputEntity !== "unknown") {
|
|
10862
|
+
const now = /* @__PURE__ */ new Date();
|
|
10863
|
+
const newEntity = {
|
|
10864
|
+
id: outputEntityId,
|
|
10865
|
+
type: "line_item",
|
|
10866
|
+
name: parsedRule.outputEntity,
|
|
10867
|
+
displayName: parsedRule.outputEntity,
|
|
10868
|
+
attributes: [
|
|
10869
|
+
{
|
|
10870
|
+
key: "value",
|
|
10871
|
+
value: 0,
|
|
10872
|
+
dataType: "currency",
|
|
10873
|
+
isComputed: true
|
|
10874
|
+
},
|
|
10875
|
+
{
|
|
10876
|
+
key: "category",
|
|
10877
|
+
value: "Computed",
|
|
10878
|
+
dataType: "string",
|
|
10879
|
+
isComputed: false
|
|
10880
|
+
}
|
|
10881
|
+
],
|
|
10882
|
+
metadata: { isComputed: true },
|
|
10883
|
+
createdAt: now,
|
|
10884
|
+
updatedAt: now
|
|
10885
|
+
};
|
|
10886
|
+
model.data.entities.push(newEntity);
|
|
10887
|
+
entityCreatedMessage = ` Created output entity "${parsedRule.outputEntity}".`;
|
|
10888
|
+
context.logger.info(`[Lattice] Auto-created output entity ${outputEntityId} for rule ${ruleId}`);
|
|
10889
|
+
}
|
|
10890
|
+
const existingIndex = model.rules.rules.findIndex((r) => r.id === ruleId || r.name === name);
|
|
10891
|
+
if (existingIndex >= 0) {
|
|
10892
|
+
model.rules.rules[existingIndex] = ruleData;
|
|
10893
|
+
} else {
|
|
10894
|
+
model.rules.rules.push(ruleData);
|
|
10895
|
+
}
|
|
10896
|
+
await context.db.latticeModels.update({
|
|
10897
|
+
id: modelId,
|
|
10898
|
+
data: model.data,
|
|
10899
|
+
rules: model.rules,
|
|
10900
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
10901
|
+
});
|
|
10902
|
+
context.logger.info(`[Lattice] Created rule ${ruleId} in model ${modelId}`);
|
|
10903
|
+
} else {
|
|
10904
|
+
context.logger.warn(`[Lattice] Model ${modelId} not found in database`);
|
|
10905
|
+
}
|
|
10906
|
+
} catch (error) {
|
|
10907
|
+
context.logger.error(`[Lattice] Failed to persist rule to database:`, error);
|
|
10908
|
+
}
|
|
10909
|
+
}
|
|
10910
|
+
return JSON.stringify({
|
|
10911
|
+
success: true,
|
|
10912
|
+
action: "CREATE_RULE",
|
|
10913
|
+
modelId,
|
|
10914
|
+
ruleId,
|
|
10915
|
+
data: {
|
|
10916
|
+
name,
|
|
10917
|
+
description,
|
|
10918
|
+
formula,
|
|
10919
|
+
parsed: parsedRule,
|
|
10920
|
+
outputEntityCreated: entityCreatedMessage !== ""
|
|
10921
|
+
},
|
|
10922
|
+
message: `Created rule "${name}": ${formula}.${entityCreatedMessage}`
|
|
10923
|
+
});
|
|
10924
|
+
},
|
|
10925
|
+
toolSchema: {
|
|
10926
|
+
name: "lattice_create_rule",
|
|
10927
|
+
description: `Create a formula or calculation rule in a Lattice model.
|
|
10928
|
+
|
|
10929
|
+
**When to use:** When the user defines a calculation:
|
|
10930
|
+
- "Gross profit equals revenue minus COGS"
|
|
10931
|
+
- "Net margin is net income divided by revenue times 100"
|
|
10932
|
+
- "Total expenses is the sum of all expense line items"
|
|
10933
|
+
|
|
10934
|
+
**IMPORTANT: For per-period calculations like "calculate X for each quarter", you MUST call this tool ONCE for EACH period.** For example, if asked to "calculate gross margin for each quarter", call this tool 4 times:
|
|
10935
|
+
1. lattice_create_rule with formula "Q1 Gross Margin = Q1 Revenue - Q1 COGS"
|
|
10936
|
+
2. lattice_create_rule with formula "Q2 Gross Margin = Q2 Revenue - Q2 COGS"
|
|
10937
|
+
3. lattice_create_rule with formula "Q3 Gross Margin = Q3 Revenue - Q3 COGS"
|
|
10938
|
+
4. lattice_create_rule with formula "Q4 Gross Margin = Q4 Revenue - Q4 COGS"
|
|
10939
|
+
|
|
10940
|
+
**Formula syntax (natural language):**
|
|
10941
|
+
- Arithmetic: "X equals Y plus Z", "A minus B", "C times D"
|
|
10942
|
+
- Aggregation: "sum of", "average of", "total"
|
|
10943
|
+
- Percentage: "X percent of Y", "as a percentage"
|
|
10944
|
+
- Comparison: "if X is greater than Y then A else B"
|
|
10945
|
+
|
|
10946
|
+
**Examples:**
|
|
10947
|
+
- "Gross Profit = Revenue - COGS"
|
|
10948
|
+
- "Gross Margin = Gross Profit / Revenue * 100"
|
|
10949
|
+
- "Total OpEx = sum of all Operating Expenses"
|
|
10950
|
+
- "YoY Growth = (Current Year - Prior Year) / Prior Year * 100"
|
|
10951
|
+
- "Q1 Gross Margin = Q1 Revenue - Q1 COGS" (per-period)`,
|
|
10952
|
+
parameters: {
|
|
10953
|
+
type: "object",
|
|
10954
|
+
properties: {
|
|
10955
|
+
modelId: {
|
|
10956
|
+
type: "string",
|
|
10957
|
+
description: "ID of the model"
|
|
10958
|
+
},
|
|
10959
|
+
name: {
|
|
10960
|
+
type: "string",
|
|
10961
|
+
description: 'Name for this rule (e.g., "Gross Profit Calculation")'
|
|
10962
|
+
},
|
|
10963
|
+
description: {
|
|
10964
|
+
type: "string",
|
|
10965
|
+
description: "Optional description of what this rule calculates"
|
|
10966
|
+
},
|
|
10967
|
+
formula: {
|
|
10968
|
+
type: "string",
|
|
10969
|
+
description: "The formula in natural language or equation format"
|
|
10970
|
+
}
|
|
10971
|
+
},
|
|
10972
|
+
required: ["modelId", "name", "formula"]
|
|
10973
|
+
}
|
|
10974
|
+
}
|
|
10975
|
+
})
|
|
10976
|
+
};
|
|
10977
|
+
var latticeQueryTool = {
|
|
10978
|
+
name: "lattice_query",
|
|
10979
|
+
implementation: () => ({
|
|
10980
|
+
toolFn: async (params) => {
|
|
10981
|
+
const { modelId, query } = params;
|
|
10982
|
+
const parsedQuery = parseQuery(query);
|
|
10983
|
+
return JSON.stringify({
|
|
10984
|
+
success: true,
|
|
10985
|
+
action: "QUERY",
|
|
10986
|
+
modelId,
|
|
10987
|
+
data: {
|
|
10988
|
+
query,
|
|
10989
|
+
parsed: parsedQuery
|
|
10990
|
+
},
|
|
10991
|
+
message: `Querying model for: ${query}`
|
|
10992
|
+
});
|
|
10993
|
+
},
|
|
10994
|
+
toolSchema: {
|
|
10995
|
+
name: "lattice_query",
|
|
10996
|
+
description: `Query a Lattice model for specific values or aggregations.
|
|
10997
|
+
|
|
10998
|
+
**When to use:** When the user asks about values in the model:
|
|
10999
|
+
- "What's Q1 gross margin?"
|
|
11000
|
+
- "Show me total revenue for 2024"
|
|
11001
|
+
- "What are all the expense categories?"
|
|
11002
|
+
- "Compare Q1 vs Q2 performance"
|
|
11003
|
+
|
|
11004
|
+
**Query types:**
|
|
11005
|
+
- Single value: "What is [entity] for [period]?"
|
|
11006
|
+
- Aggregation: "Total [entity] for [range]"
|
|
11007
|
+
- Comparison: "Compare [entity] across [periods]"
|
|
11008
|
+
- List: "Show all [entity type]"
|
|
11009
|
+
|
|
11010
|
+
**Examples:**
|
|
11011
|
+
- "What's Q2 revenue?" \u2192 Returns specific value
|
|
11012
|
+
- "Total revenue for 2024" \u2192 Sums Q1-Q4
|
|
11013
|
+
- "Compare gross margin Q1 vs Q2" \u2192 Side-by-side comparison`,
|
|
11014
|
+
parameters: {
|
|
11015
|
+
type: "object",
|
|
11016
|
+
properties: {
|
|
11017
|
+
modelId: {
|
|
11018
|
+
type: "string",
|
|
11019
|
+
description: "ID of the model to query"
|
|
11020
|
+
},
|
|
11021
|
+
query: {
|
|
11022
|
+
type: "string",
|
|
11023
|
+
description: "Natural language query about the model"
|
|
11024
|
+
}
|
|
11025
|
+
},
|
|
11026
|
+
required: ["modelId", "query"]
|
|
11027
|
+
}
|
|
11028
|
+
}
|
|
11029
|
+
})
|
|
11030
|
+
};
|
|
11031
|
+
var latticeExplainTool = {
|
|
11032
|
+
name: "lattice_explain",
|
|
11033
|
+
implementation: () => ({
|
|
11034
|
+
toolFn: async (params) => {
|
|
11035
|
+
const { modelId, entityName, attributeKey } = params;
|
|
11036
|
+
return JSON.stringify({
|
|
11037
|
+
success: true,
|
|
11038
|
+
action: "EXPLAIN",
|
|
11039
|
+
modelId,
|
|
11040
|
+
data: {
|
|
11041
|
+
entityName,
|
|
11042
|
+
attributeKey
|
|
11043
|
+
},
|
|
11044
|
+
message: `Explaining calculation for ${entityName}.${attributeKey}`
|
|
11045
|
+
});
|
|
11046
|
+
},
|
|
11047
|
+
toolSchema: {
|
|
11048
|
+
name: "lattice_explain",
|
|
11049
|
+
description: `Explain how a value in a Lattice model was calculated.
|
|
11050
|
+
|
|
11051
|
+
**When to use:** When the user wants to understand a calculation:
|
|
11052
|
+
- "How did you calculate gross profit?"
|
|
11053
|
+
- "Explain the Q2 margin number"
|
|
11054
|
+
- "Show me the formula for total expenses"
|
|
11055
|
+
- "Why is this number so high?"
|
|
11056
|
+
|
|
11057
|
+
This tool traces the calculation chain from the target value back through all its inputs and rules, providing a step-by-step explanation.`,
|
|
11058
|
+
parameters: {
|
|
11059
|
+
type: "object",
|
|
11060
|
+
properties: {
|
|
11061
|
+
modelId: {
|
|
11062
|
+
type: "string",
|
|
11063
|
+
description: "ID of the model"
|
|
11064
|
+
},
|
|
11065
|
+
entityName: {
|
|
11066
|
+
type: "string",
|
|
11067
|
+
description: "Name of the entity containing the value to explain"
|
|
11068
|
+
},
|
|
11069
|
+
attributeKey: {
|
|
11070
|
+
type: "string",
|
|
11071
|
+
description: "Period or attribute key of the value to explain"
|
|
11072
|
+
}
|
|
11073
|
+
},
|
|
11074
|
+
required: ["modelId", "entityName", "attributeKey"]
|
|
11075
|
+
}
|
|
11076
|
+
}
|
|
11077
|
+
})
|
|
11078
|
+
};
|
|
11079
|
+
function parseFormula(formula) {
|
|
11080
|
+
const normalized = formula.toLowerCase().trim();
|
|
11081
|
+
const equalsMatch = normalized.match(/^(.+?)\s*(?:=|equals?)\s*(.+)$/i);
|
|
11082
|
+
if (equalsMatch) {
|
|
11083
|
+
const [, output, expression] = equalsMatch;
|
|
11084
|
+
if (expression.includes("+") || expression.includes("plus")) {
|
|
11085
|
+
return {
|
|
11086
|
+
operation: "ADD",
|
|
11087
|
+
outputEntity: output,
|
|
11088
|
+
inputs: expression.split(/[+]|plus/i).map((s) => s.trim())
|
|
11089
|
+
};
|
|
11090
|
+
}
|
|
11091
|
+
if (expression.includes("-") || expression.includes("minus")) {
|
|
11092
|
+
return {
|
|
11093
|
+
operation: "SUBTRACT",
|
|
11094
|
+
outputEntity: output,
|
|
11095
|
+
inputs: expression.split(/[-]|minus/i).map((s) => s.trim())
|
|
11096
|
+
};
|
|
11097
|
+
}
|
|
11098
|
+
if (expression.includes("*") || expression.includes("times") || expression.includes("x")) {
|
|
11099
|
+
return {
|
|
11100
|
+
operation: "MULTIPLY",
|
|
11101
|
+
outputEntity: output,
|
|
11102
|
+
inputs: expression.split(/[*x]|times/i).map((s) => s.trim())
|
|
11103
|
+
};
|
|
11104
|
+
}
|
|
11105
|
+
if (expression.includes("/") || expression.includes("divided")) {
|
|
11106
|
+
return {
|
|
11107
|
+
operation: "DIVIDE",
|
|
11108
|
+
outputEntity: output,
|
|
11109
|
+
inputs: expression.split(/[/]|divided by/i).map((s) => s.trim())
|
|
11110
|
+
};
|
|
11111
|
+
}
|
|
11112
|
+
if (expression.includes("sum")) {
|
|
11113
|
+
return {
|
|
11114
|
+
operation: "SUM",
|
|
11115
|
+
outputEntity: output,
|
|
11116
|
+
inputs: [expression.replace(/sum of/i, "").trim()]
|
|
11117
|
+
};
|
|
11118
|
+
}
|
|
11119
|
+
}
|
|
11120
|
+
return {
|
|
11121
|
+
operation: "REFERENCE",
|
|
11122
|
+
outputEntity: "unknown",
|
|
11123
|
+
inputs: [formula]
|
|
11124
|
+
};
|
|
11125
|
+
}
|
|
11126
|
+
function parseQuery(query) {
|
|
11127
|
+
const normalized = query.toLowerCase();
|
|
11128
|
+
let type = "single_value";
|
|
11129
|
+
if (normalized.includes("total") || normalized.includes("sum")) {
|
|
11130
|
+
type = "aggregation";
|
|
11131
|
+
} else if (normalized.includes("compare") || normalized.includes("vs")) {
|
|
11132
|
+
type = "comparison";
|
|
11133
|
+
} else if (normalized.includes("list") || normalized.includes("show all")) {
|
|
11134
|
+
type = "list";
|
|
11135
|
+
}
|
|
11136
|
+
const entities = [];
|
|
11137
|
+
const periods = [];
|
|
11138
|
+
const periodPatterns = [/q[1-4]/gi, /\d{4}/g, /jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/gi];
|
|
11139
|
+
for (const pattern of periodPatterns) {
|
|
11140
|
+
const matches = query.match(pattern);
|
|
11141
|
+
if (matches) {
|
|
11142
|
+
periods.push(...matches);
|
|
11143
|
+
}
|
|
11144
|
+
}
|
|
11145
|
+
const commonEntities = ["revenue", "expenses", "profit", "margin", "income", "cost", "cogs", "ebitda"];
|
|
11146
|
+
for (const entity of commonEntities) {
|
|
11147
|
+
if (normalized.includes(entity)) {
|
|
11148
|
+
entities.push(entity);
|
|
11149
|
+
}
|
|
11150
|
+
}
|
|
11151
|
+
return { type, entities, periods };
|
|
11152
|
+
}
|
|
11153
|
+
|
|
10328
11154
|
// ../../b4m-core/packages/services/dist/src/llm/tools/implementation/editLocalFile/index.js
|
|
10329
11155
|
import { promises as fs10 } from "fs";
|
|
10330
11156
|
import { existsSync as existsSync7 } from "fs";
|
|
@@ -10796,7 +11622,14 @@ var cliOnlyTools = {
|
|
|
10796
11622
|
// Shell execution
|
|
10797
11623
|
bash_execute: bashExecuteTool,
|
|
10798
11624
|
// Git operations
|
|
10799
|
-
recent_changes: recentChangesTool
|
|
11625
|
+
recent_changes: recentChangesTool,
|
|
11626
|
+
// Lattice financial modeling tools
|
|
11627
|
+
lattice_create_model: latticeCreateModelTool,
|
|
11628
|
+
lattice_add_entity: latticeAddEntityTool,
|
|
11629
|
+
lattice_set_value: latticeSetValueTool,
|
|
11630
|
+
lattice_create_rule: latticeCreateRuleTool,
|
|
11631
|
+
lattice_query: latticeQueryTool,
|
|
11632
|
+
lattice_explain: latticeExplainTool
|
|
10800
11633
|
};
|
|
10801
11634
|
var generateTools = (userId, user, logger2, { db }, storage, imageGenerateStorage, statusUpdate, onStart, onFinish, llm, config, model, imageProcessorLambdaName, tools = b4mTools) => {
|
|
10802
11635
|
const context = {
|
|
@@ -10902,194 +11735,6 @@ var generateMcpTools = async (mcpData) => {
|
|
|
10902
11735
|
return result;
|
|
10903
11736
|
};
|
|
10904
11737
|
|
|
10905
|
-
// ../../b4m-core/packages/services/dist/src/llm/agents/ExploreAgent.js
|
|
10906
|
-
var ExploreAgent = (config) => ({
|
|
10907
|
-
name: "explore",
|
|
10908
|
-
description: "Fast research, exploration, and information search",
|
|
10909
|
-
model: config?.model ?? "claude-3-5-haiku-20241022",
|
|
10910
|
-
defaultThoroughness: config?.defaultThoroughness ?? "medium",
|
|
10911
|
-
maxIterations: { quick: 2, medium: 5, very_thorough: 10 },
|
|
10912
|
-
deniedTools: [
|
|
10913
|
-
"image_generation",
|
|
10914
|
-
"edit_image",
|
|
10915
|
-
"deep_research",
|
|
10916
|
-
"delegate_to_agent",
|
|
10917
|
-
...config?.extraDeniedTools ?? []
|
|
10918
|
-
],
|
|
10919
|
-
allowedTools: config?.extraAllowedTools,
|
|
10920
|
-
systemPrompt: `You are a research and exploration specialist. Your job is to search and analyze information efficiently.
|
|
10921
|
-
|
|
10922
|
-
## Focus Areas
|
|
10923
|
-
- Finding relevant information across knowledge bases and the web
|
|
10924
|
-
- Understanding context and patterns
|
|
10925
|
-
- Providing clear, concise summaries
|
|
10926
|
-
|
|
10927
|
-
## Tool Usage
|
|
10928
|
-
Use these tools strategically:
|
|
10929
|
-
- \`web_search\` - Search the web for information
|
|
10930
|
-
- \`web_fetch\` - Fetch and read full webpage content
|
|
10931
|
-
- \`search_knowledge_base\` - Search the user's knowledge bases
|
|
10932
|
-
- \`current_datetime\` - Get the current date and time
|
|
10933
|
-
|
|
10934
|
-
## Search Strategy
|
|
10935
|
-
1. Start with targeted searches using specific keywords
|
|
10936
|
-
2. Use web_fetch to read full content from promising results
|
|
10937
|
-
3. Cross-reference findings from multiple sources
|
|
10938
|
-
4. Check knowledge bases for relevant internal information
|
|
10939
|
-
|
|
10940
|
-
## Output Format
|
|
10941
|
-
Provide a clear summary including:
|
|
10942
|
-
1. What you found (key facts, sources, patterns)
|
|
10943
|
-
2. Key insights or observations
|
|
10944
|
-
3. Relevant source references
|
|
10945
|
-
|
|
10946
|
-
Be thorough but concise. Your summary will be used by the main agent.`
|
|
10947
|
-
});
|
|
10948
|
-
|
|
10949
|
-
// ../../b4m-core/packages/services/dist/src/llm/agents/PlanAgent.js
|
|
10950
|
-
var PlanAgent = (config) => ({
|
|
10951
|
-
name: "plan",
|
|
10952
|
-
description: "Task breakdown and implementation planning",
|
|
10953
|
-
model: config?.model ?? "claude-3-5-haiku-20241022",
|
|
10954
|
-
defaultThoroughness: config?.defaultThoroughness ?? "medium",
|
|
10955
|
-
maxIterations: { quick: 3, medium: 7, very_thorough: 12 },
|
|
10956
|
-
deniedTools: [
|
|
10957
|
-
"image_generation",
|
|
10958
|
-
"edit_image",
|
|
10959
|
-
"deep_research",
|
|
10960
|
-
"delegate_to_agent",
|
|
10961
|
-
...config?.extraDeniedTools ?? []
|
|
10962
|
-
],
|
|
10963
|
-
allowedTools: config?.extraAllowedTools,
|
|
10964
|
-
systemPrompt: `You are a task planning specialist. Your job is to break down complex tasks into clear, actionable steps.
|
|
10965
|
-
|
|
10966
|
-
## Focus Areas
|
|
10967
|
-
- Identifying dependencies and blockers
|
|
10968
|
-
- Creating logical sequence of steps
|
|
10969
|
-
- Researching context before planning
|
|
10970
|
-
|
|
10971
|
-
## Process
|
|
10972
|
-
1. First, research the topic to understand the current landscape
|
|
10973
|
-
2. Identify what already exists vs. what needs to be done
|
|
10974
|
-
3. Break down work into discrete, actionable steps
|
|
10975
|
-
4. Order steps by dependencies
|
|
10976
|
-
|
|
10977
|
-
## Output Format
|
|
10978
|
-
Provide a structured plan:
|
|
10979
|
-
|
|
10980
|
-
### Prerequisites
|
|
10981
|
-
- What must exist before starting
|
|
10982
|
-
|
|
10983
|
-
### Steps
|
|
10984
|
-
1. Step with clear deliverable
|
|
10985
|
-
2. Next step (depends on: Step 1)
|
|
10986
|
-
...
|
|
10987
|
-
|
|
10988
|
-
### Risks & Considerations
|
|
10989
|
-
- Potential issues to watch for
|
|
10990
|
-
|
|
10991
|
-
Be specific and actionable. Your plan will be used by the main agent.`
|
|
10992
|
-
});
|
|
10993
|
-
|
|
10994
|
-
// ../../b4m-core/packages/services/dist/src/llm/agents/ReviewAgent.js
|
|
10995
|
-
var ReviewAgent = (config) => ({
|
|
10996
|
-
name: "review",
|
|
10997
|
-
description: "Content quality analysis and review",
|
|
10998
|
-
model: config?.model ?? "claude-sonnet-4-5-20250929",
|
|
10999
|
-
defaultThoroughness: config?.defaultThoroughness ?? "medium",
|
|
11000
|
-
maxIterations: { quick: 3, medium: 8, very_thorough: 15 },
|
|
11001
|
-
deniedTools: ["image_generation", "edit_image", "delegate_to_agent", ...config?.extraDeniedTools ?? []],
|
|
11002
|
-
allowedTools: config?.extraAllowedTools,
|
|
11003
|
-
systemPrompt: `You are a review specialist. Your job is to analyze content quality and identify issues.
|
|
11004
|
-
|
|
11005
|
-
## Focus Areas
|
|
11006
|
-
- Content quality and accuracy
|
|
11007
|
-
- Potential errors and edge cases
|
|
11008
|
-
- Completeness and thoroughness
|
|
11009
|
-
- Consistency and clarity
|
|
11010
|
-
|
|
11011
|
-
## Review Process
|
|
11012
|
-
1. Understand the context and purpose of the content
|
|
11013
|
-
2. Check for common issues (errors, inconsistencies, gaps)
|
|
11014
|
-
3. Verify claims against available sources
|
|
11015
|
-
4. Look for areas of improvement
|
|
11016
|
-
|
|
11017
|
-
## Output Format
|
|
11018
|
-
Provide actionable feedback:
|
|
11019
|
-
|
|
11020
|
-
### Critical Issues
|
|
11021
|
-
- Description of issue and why it matters
|
|
11022
|
-
|
|
11023
|
-
### Suggestions
|
|
11024
|
-
- Improvement suggestion with rationale
|
|
11025
|
-
|
|
11026
|
-
### Positive Observations
|
|
11027
|
-
- What's done well (optional)
|
|
11028
|
-
|
|
11029
|
-
Focus on actionable feedback. Your review will be used by the main agent.`
|
|
11030
|
-
});
|
|
11031
|
-
|
|
11032
|
-
// ../../b4m-core/packages/services/dist/src/llm/agents/ProjectManagerAgent.js
|
|
11033
|
-
var ProjectManagerAgent = (config) => ({
|
|
11034
|
-
name: "project_manager",
|
|
11035
|
-
description: "Project management via Jira and Confluence (create issues, search, update status, write docs). ALWAYS delegate Jira/Confluence requests to this agent \u2014 you do not have direct access to these tools",
|
|
11036
|
-
model: config?.model ?? "claude-sonnet-4-5-20250929",
|
|
11037
|
-
defaultThoroughness: config?.defaultThoroughness ?? "medium",
|
|
11038
|
-
maxIterations: { quick: 3, medium: 8, very_thorough: 15 },
|
|
11039
|
-
allowedTools: [...config?.extraAllowedTools ?? []],
|
|
11040
|
-
deniedTools: [...config?.extraDeniedTools ?? []],
|
|
11041
|
-
systemPrompt: `You are a project management specialist with access to Jira and Confluence. Your job is to help manage projects, issues, documentation, and team workflows.
|
|
11042
|
-
|
|
11043
|
-
## Capabilities
|
|
11044
|
-
|
|
11045
|
-
### Jira
|
|
11046
|
-
- Search for issues using JQL
|
|
11047
|
-
- Create, update, and transition issues
|
|
11048
|
-
- Add comments and manage watchers
|
|
11049
|
-
- List projects and issue types
|
|
11050
|
-
|
|
11051
|
-
### Confluence
|
|
11052
|
-
- Search for documentation
|
|
11053
|
-
- Create and update pages
|
|
11054
|
-
- Browse spaces and page hierarchies
|
|
11055
|
-
|
|
11056
|
-
## Best Practices
|
|
11057
|
-
1. When searching Jira, use precise JQL queries (e.g., \`project = PROJ AND status = "In Progress"\`)
|
|
11058
|
-
2. When creating issues, always check available issue types first with \`atlassian__jira_list_issue_types\`
|
|
11059
|
-
3. When updating issue status, use \`atlassian__jira_update_issue_transition\` with the target status name
|
|
11060
|
-
4. When creating Confluence pages, use the user's personal space if no space is specified
|
|
11061
|
-
5. Always confirm destructive operations (delete) with the user before proceeding
|
|
11062
|
-
|
|
11063
|
-
## Output Format
|
|
11064
|
-
Provide a clear summary of actions taken:
|
|
11065
|
-
1. What was done (created, updated, searched, etc.)
|
|
11066
|
-
2. Links or keys to relevant items (e.g., PROJ-123)
|
|
11067
|
-
3. Any issues or warnings encountered
|
|
11068
|
-
|
|
11069
|
-
Be precise with issue keys and project names. Your results will be used by the main agent.`
|
|
11070
|
-
});
|
|
11071
|
-
|
|
11072
|
-
// ../../b4m-core/packages/services/dist/src/llm/agents/ServerAgentStore.js
|
|
11073
|
-
var ServerAgentStore = class {
|
|
11074
|
-
constructor() {
|
|
11075
|
-
const builtInAgents = [ExploreAgent(), PlanAgent(), ReviewAgent(), ProjectManagerAgent()];
|
|
11076
|
-
this.agents = new Map(builtInAgents.map((a) => [a.name, a]));
|
|
11077
|
-
}
|
|
11078
|
-
getAgent(name) {
|
|
11079
|
-
return this.agents.get(name);
|
|
11080
|
-
}
|
|
11081
|
-
getAllAgents() {
|
|
11082
|
-
return Array.from(this.agents.values());
|
|
11083
|
-
}
|
|
11084
|
-
getAgentNames() {
|
|
11085
|
-
return Array.from(this.agents.keys());
|
|
11086
|
-
}
|
|
11087
|
-
hasAgent(name) {
|
|
11088
|
-
return this.agents.has(name);
|
|
11089
|
-
}
|
|
11090
|
-
};
|
|
11091
|
-
var serverAgentStore = new ServerAgentStore();
|
|
11092
|
-
|
|
11093
11738
|
// ../../b4m-core/packages/services/dist/src/llm/ChatCompletionProcess.js
|
|
11094
11739
|
import throttle2 from "lodash/throttle.js";
|
|
11095
11740
|
|
|
@@ -11110,6 +11755,7 @@ var QuestStartBodySchema = z139.object({
|
|
|
11110
11755
|
enableMementos: z139.boolean().optional(),
|
|
11111
11756
|
enableArtifacts: z139.boolean().optional(),
|
|
11112
11757
|
enableAgents: z139.boolean().optional(),
|
|
11758
|
+
enableLattice: z139.boolean().optional(),
|
|
11113
11759
|
promptMeta: PromptMetaZodSchema,
|
|
11114
11760
|
tools: z139.array(z139.union([b4mLLMTools, z139.string()])).optional(),
|
|
11115
11761
|
mcpServers: z139.array(z139.string()).optional(),
|
|
@@ -11954,7 +12600,7 @@ async function executeCommandHook(hook, context) {
|
|
|
11954
12600
|
}
|
|
11955
12601
|
}
|
|
11956
12602
|
var MAX_PATTERN_LENGTH = 200;
|
|
11957
|
-
function
|
|
12603
|
+
function matchesToolPattern(toolName, pattern) {
|
|
11958
12604
|
if (pattern.length > MAX_PATTERN_LENGTH) {
|
|
11959
12605
|
console.warn(`Hook pattern exceeds max length (${MAX_PATTERN_LENGTH}), skipping: ${pattern.slice(0, 50)}...`);
|
|
11960
12606
|
return false;
|
|
@@ -11972,7 +12618,7 @@ async function executeHooks(hooks, context) {
|
|
|
11972
12618
|
}
|
|
11973
12619
|
const matchingHooks = [];
|
|
11974
12620
|
for (const matcher of hooks) {
|
|
11975
|
-
const shouldMatch = !matcher.matcher || !context.tool_name ||
|
|
12621
|
+
const shouldMatch = !matcher.matcher || !context.tool_name || matchesToolPattern(context.tool_name, matcher.matcher);
|
|
11976
12622
|
if (shouldMatch) {
|
|
11977
12623
|
matchingHooks.push(...matcher.hooks);
|
|
11978
12624
|
}
|
|
@@ -13989,7 +14635,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
|
|
|
13989
14635
|
// package.json
|
|
13990
14636
|
var package_default = {
|
|
13991
14637
|
name: "@bike4mind/cli",
|
|
13992
|
-
version: "0.2.29
|
|
14638
|
+
version: "0.2.29",
|
|
13993
14639
|
type: "module",
|
|
13994
14640
|
description: "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
13995
14641
|
license: "UNLICENSED",
|
|
@@ -14103,10 +14749,10 @@ var package_default = {
|
|
|
14103
14749
|
},
|
|
14104
14750
|
devDependencies: {
|
|
14105
14751
|
"@bike4mind/agents": "0.1.0",
|
|
14106
|
-
"@bike4mind/common": "2.
|
|
14107
|
-
"@bike4mind/mcp": "1.
|
|
14108
|
-
"@bike4mind/services": "2.
|
|
14109
|
-
"@bike4mind/utils": "2.
|
|
14752
|
+
"@bike4mind/common": "2.51.0",
|
|
14753
|
+
"@bike4mind/mcp": "1.30.0",
|
|
14754
|
+
"@bike4mind/services": "2.49.0",
|
|
14755
|
+
"@bike4mind/utils": "2.6.0",
|
|
14110
14756
|
"@types/better-sqlite3": "^7.6.13",
|
|
14111
14757
|
"@types/diff": "^5.0.9",
|
|
14112
14758
|
"@types/jsonwebtoken": "^9.0.4",
|
|
@@ -14124,7 +14770,7 @@ var package_default = {
|
|
|
14124
14770
|
optionalDependencies: {
|
|
14125
14771
|
"@vscode/ripgrep": "^1.17.0"
|
|
14126
14772
|
},
|
|
14127
|
-
gitHead: "
|
|
14773
|
+
gitHead: "dd78e3f7ac6eb31fbbae8df3be1f33310779a9d5"
|
|
14128
14774
|
};
|
|
14129
14775
|
|
|
14130
14776
|
// src/config/constants.ts
|
|
@@ -14133,25 +14779,25 @@ var MODEL_NAME_COLUMN_WIDTH = 18;
|
|
|
14133
14779
|
var USAGE_CACHE_TTL = 5 * 60 * 1e3;
|
|
14134
14780
|
|
|
14135
14781
|
// src/agents/toolFilter.ts
|
|
14136
|
-
function
|
|
14782
|
+
function matchesToolPattern2(toolName, pattern) {
|
|
14137
14783
|
const regexPattern = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
14138
14784
|
return new RegExp(`^${regexPattern}$`).test(toolName);
|
|
14139
14785
|
}
|
|
14140
|
-
function
|
|
14141
|
-
return patterns.some((pattern) =>
|
|
14786
|
+
function matchesAnyPattern(toolName, patterns) {
|
|
14787
|
+
return patterns.some((pattern) => matchesToolPattern2(toolName, pattern));
|
|
14142
14788
|
}
|
|
14143
|
-
function
|
|
14789
|
+
function filterToolsByPatterns(allTools, allowedPatterns, deniedPatterns) {
|
|
14144
14790
|
return allTools.filter((tool) => {
|
|
14145
14791
|
const toolName = tool.toolSchema.name;
|
|
14146
14792
|
if (deniedPatterns && deniedPatterns.length > 0) {
|
|
14147
|
-
if (
|
|
14793
|
+
if (matchesAnyPattern(toolName, deniedPatterns)) {
|
|
14148
14794
|
return false;
|
|
14149
14795
|
}
|
|
14150
14796
|
}
|
|
14151
14797
|
if (!allowedPatterns || allowedPatterns.length === 0) {
|
|
14152
14798
|
return true;
|
|
14153
14799
|
}
|
|
14154
|
-
return
|
|
14800
|
+
return matchesAnyPattern(toolName, allowedPatterns);
|
|
14155
14801
|
});
|
|
14156
14802
|
}
|
|
14157
14803
|
|
|
@@ -14422,7 +15068,7 @@ var SubagentOrchestrator = class {
|
|
|
14422
15068
|
this.deps.configStore,
|
|
14423
15069
|
this.deps.apiClient
|
|
14424
15070
|
);
|
|
14425
|
-
const filteredTools =
|
|
15071
|
+
const filteredTools = filterToolsByPatterns(allTools, toolFilter.allowedTools, toolFilter.deniedTools);
|
|
14426
15072
|
if (this.deps.customCommandStore) {
|
|
14427
15073
|
const skillTool = createSkillTool({
|
|
14428
15074
|
customCommandStore: this.deps.customCommandStore,
|