@bike4mind/cli 0.3.0 → 0.5.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/dist/{ConfigStore-o5AblHqQ.mjs → ConfigStore-DBUmvCfe.mjs} +8 -1
- package/dist/commands/doctorCommand.mjs +1 -1
- package/dist/commands/headlessCommand.mjs +2 -2
- package/dist/commands/mcpCommand.mjs +1 -1
- package/dist/commands/updateCommand.mjs +1 -1
- package/dist/index.mjs +488 -6
- package/dist/{tools-BImjpPlR.mjs → tools-V5FJ83BJ.mjs} +315 -44
- package/dist/{updateChecker-CEeSpbaK.mjs → updateChecker-Boy2GLk4.mjs} +1 -1
- package/package.json +6 -6
|
@@ -1930,7 +1930,14 @@ const SceneCommandSchema = z.discriminatedUnion("type", [
|
|
|
1930
1930
|
row: z.number(),
|
|
1931
1931
|
gid: z.number()
|
|
1932
1932
|
})),
|
|
1933
|
-
worldVersion: z.number().optional()
|
|
1933
|
+
worldVersion: z.number().optional(),
|
|
1934
|
+
floorId: z.string().optional()
|
|
1935
|
+
}),
|
|
1936
|
+
z.object({
|
|
1937
|
+
type: z.literal("change_floor"),
|
|
1938
|
+
id: z.string(),
|
|
1939
|
+
floorId: z.string(),
|
|
1940
|
+
position: TilePositionSchema
|
|
1934
1941
|
}),
|
|
1935
1942
|
z.object({
|
|
1936
1943
|
type: z.literal("update_metadata"),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { i as version, n as fetchLatestVersion, r as forceCheckForUpdate } from "../updateChecker-
|
|
2
|
+
import { i as version, n as fetchLatestVersion, r as forceCheckForUpdate } from "../updateChecker-Boy2GLk4.mjs";
|
|
3
3
|
import { execSync } from "child_process";
|
|
4
4
|
import { constants, existsSync, promises } from "fs";
|
|
5
5
|
import { homedir } from "os";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import { n as logger, t as ConfigStore } from "../ConfigStore-
|
|
2
|
+
import { A as getApiUrl, C as WebSocketLlmBackend, G as isReadOnlyTool, J as CheckpointStore, K as ReActAgent, M as PermissionManager, N as generateCliTools, S as FallbackLlmBackend, T as McpManager, U as buildCoreSystemPrompt, V as setWebSocketToolExecutor, X as SessionStore, _ as createSkillTool, b as WebSocketToolExecutor, c as createFindDefinitionTool, d as createCoordinateTaskTool, f as createBackgroundAgentTools, g as SubagentOrchestrator, h as AgentStore, k as loadContextFiles, l as createTodoStore, m as createAgentDelegateTool, p as BackgroundAgentManager, q as CustomCommandStore, s as createGetFileStructureTool, u as createWriteTodosTool, w as ServerLlmBackend, x as WebSocketConnectionManager, y as ApiClient } from "../tools-V5FJ83BJ.mjs";
|
|
3
|
+
import { n as logger, t as ConfigStore } from "../ConfigStore-DBUmvCfe.mjs";
|
|
4
4
|
import { t as DEFAULT_SANDBOX_CONFIG } from "../types-DBEjF9YS.mjs";
|
|
5
5
|
import { t as createSandboxRuntime } from "../SandboxRuntimeAdapter-C1B4t20N.mjs";
|
|
6
6
|
import { t as SandboxOrchestrator } from "../SandboxOrchestrator-BEW3rqYi.mjs";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { i as version, r as forceCheckForUpdate } from "../updateChecker-
|
|
2
|
+
import { i as version, r as forceCheckForUpdate } from "../updateChecker-Boy2GLk4.mjs";
|
|
3
3
|
import { execSync } from "child_process";
|
|
4
4
|
//#region src/commands/updateCommand.ts
|
|
5
5
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { n as useCliStore, t as selectActiveBackgroundAgents } from "./store-B7-LLvvx.mjs";
|
|
3
|
-
import { A as
|
|
4
|
-
import { Mt as validateNotebookPath$1, g as ChatModels, jt as validateJupyterKernelName, m as CREDIT_DEDUCT_TRANSACTION_TYPES, n as logger, t as ConfigStore } from "./ConfigStore-
|
|
5
|
-
import { i as version, t as checkForUpdate } from "./updateChecker-
|
|
3
|
+
import { $ as processFileReferences, A as getApiUrl, B as registerFeatureModuleTools, C as WebSocketLlmBackend, D as formatStep, E as substituteArguments, F as DEFAULT_AGENT_MODEL, G as isReadOnlyTool, H as OllamaBackend, I as DEFAULT_MAX_ITERATIONS, J as CheckpointStore, K as ReActAgent, L as DEFAULT_RETRY_CONFIG, M as PermissionManager, N as generateCliTools, O as extractCompactInstructions, P as ALWAYS_DENIED_FOR_AGENTS, Q as hasFileReferences, R as DEFAULT_THOROUGHNESS, S as FallbackLlmBackend, T as McpManager, U as buildCoreSystemPrompt, V as setWebSocketToolExecutor, W as buildSkillsPromptSection, X as SessionStore, Y as CommandHistoryStore, Z as OAuthClient, _ as createSkillTool, a as createDecisionStore, b as WebSocketToolExecutor, c as createFindDefinitionTool, d as createCoordinateTaskTool, et as searchCommands, f as createBackgroundAgentTools, g as SubagentOrchestrator, h as AgentStore, i as createDecisionLogTool, it as warmFileCache, j as getEnvironmentName, k as loadContextFiles, l as createTodoStore, m as createAgentDelegateTool, n as createBlockerTools, nt as formatFileSize, o as formatDecisionsOutput, p as BackgroundAgentManager, q as CustomCommandStore, r as formatBlockersOutput, rt as searchFiles, s as createGetFileStructureTool, t as createBlockerStore, tt as mergeCommands, u as createWriteTodosTool, v as parseAgentConfig, w as ServerLlmBackend, x as WebSocketConnectionManager, y as ApiClient, z as clearFeatureModuleTools } from "./tools-V5FJ83BJ.mjs";
|
|
4
|
+
import { Mt as validateNotebookPath$1, g as ChatModels, jt as validateJupyterKernelName, m as CREDIT_DEDUCT_TRANSACTION_TYPES, n as logger, t as ConfigStore } from "./ConfigStore-DBUmvCfe.mjs";
|
|
5
|
+
import { i as version, t as checkForUpdate } from "./updateChecker-Boy2GLk4.mjs";
|
|
6
6
|
import React, { useCallback, useEffect, useMemo, useReducer, useRef, useState } from "react";
|
|
7
7
|
import { Box, Static, Text, render, useApp, useInput } from "ink";
|
|
8
8
|
import { execSync } from "child_process";
|
|
@@ -3439,6 +3439,27 @@ var TavernService = class {
|
|
|
3439
3439
|
async abortHeartbeats() {
|
|
3440
3440
|
await this.apiClient.post("/api/tavern/abort-heartbeats", { abort: true });
|
|
3441
3441
|
}
|
|
3442
|
+
async getQuestPlan(planId) {
|
|
3443
|
+
return this.apiClient.get(`/api/quest-master-plans/${encodeURIComponent(planId)}`);
|
|
3444
|
+
}
|
|
3445
|
+
async updateReviewGate(planId, questId, subQuestId, reviewStatus, reviewNote) {
|
|
3446
|
+
return this.apiClient.post(`/api/quest-master-plans/${encodeURIComponent(planId)}/review-gate`, {
|
|
3447
|
+
questId,
|
|
3448
|
+
subQuestId,
|
|
3449
|
+
reviewStatus,
|
|
3450
|
+
reviewNote
|
|
3451
|
+
});
|
|
3452
|
+
}
|
|
3453
|
+
async updateSubQuestProgress(planId, questId, subQuestId, updates) {
|
|
3454
|
+
return this.apiClient.post(`/api/quest-master-plans/${encodeURIComponent(planId)}/subquest-progress`, {
|
|
3455
|
+
questId,
|
|
3456
|
+
subQuestId,
|
|
3457
|
+
...updates
|
|
3458
|
+
});
|
|
3459
|
+
}
|
|
3460
|
+
async updateHandoff(planId, handoff) {
|
|
3461
|
+
return this.apiClient.post(`/api/quest-master-plans/${encodeURIComponent(planId)}/handoff`, handoff);
|
|
3462
|
+
}
|
|
3442
3463
|
};
|
|
3443
3464
|
//#endregion
|
|
3444
3465
|
//#region src/features/tavern/types.ts
|
|
@@ -3626,6 +3647,109 @@ z.object({
|
|
|
3626
3647
|
error: z.string().optional()
|
|
3627
3648
|
}))
|
|
3628
3649
|
});
|
|
3650
|
+
/** Sub-quest within a quest */
|
|
3651
|
+
const SubQuestSchema = z.object({
|
|
3652
|
+
id: z.string(),
|
|
3653
|
+
title: z.string(),
|
|
3654
|
+
status: z.enum([
|
|
3655
|
+
"not_started",
|
|
3656
|
+
"in_progress",
|
|
3657
|
+
"completed",
|
|
3658
|
+
"skipped",
|
|
3659
|
+
"deleted"
|
|
3660
|
+
]),
|
|
3661
|
+
questId: z.string().optional(),
|
|
3662
|
+
startedAt: z.number().optional(),
|
|
3663
|
+
evidence: z.string().optional(),
|
|
3664
|
+
reviewGate: z.boolean().optional(),
|
|
3665
|
+
reviewStatus: z.enum([
|
|
3666
|
+
"pending",
|
|
3667
|
+
"approved",
|
|
3668
|
+
"rejected"
|
|
3669
|
+
]).optional(),
|
|
3670
|
+
reviewNote: z.string().optional()
|
|
3671
|
+
});
|
|
3672
|
+
/** Quest containing sub-quests */
|
|
3673
|
+
const QuestDataSchema = z.object({
|
|
3674
|
+
id: z.string(),
|
|
3675
|
+
title: z.string(),
|
|
3676
|
+
description: z.string(),
|
|
3677
|
+
complexity: z.string(),
|
|
3678
|
+
subQuests: z.array(SubQuestSchema)
|
|
3679
|
+
});
|
|
3680
|
+
/** Handoff state for session continuity */
|
|
3681
|
+
const HandoffSchema = z.object({
|
|
3682
|
+
summary: z.string(),
|
|
3683
|
+
nextSteps: z.array(z.string()),
|
|
3684
|
+
pendingDecisions: z.array(z.string()),
|
|
3685
|
+
blockers: z.array(z.string()),
|
|
3686
|
+
lastUpdatedBy: z.string(),
|
|
3687
|
+
updatedAt: z.string()
|
|
3688
|
+
});
|
|
3689
|
+
z.object({
|
|
3690
|
+
_id: z.string(),
|
|
3691
|
+
notebookId: z.string(),
|
|
3692
|
+
goal: z.string(),
|
|
3693
|
+
quests: z.array(QuestDataSchema),
|
|
3694
|
+
state: z.enum([
|
|
3695
|
+
"draft",
|
|
3696
|
+
"active",
|
|
3697
|
+
"paused",
|
|
3698
|
+
"completed",
|
|
3699
|
+
"archived"
|
|
3700
|
+
]).optional(),
|
|
3701
|
+
handoff: HandoffSchema.optional(),
|
|
3702
|
+
metrics: z.object({
|
|
3703
|
+
totalTimeSpent: z.number(),
|
|
3704
|
+
completionRate: z.number(),
|
|
3705
|
+
subQuestsCompleted: z.number(),
|
|
3706
|
+
subQuestsTotal: z.number(),
|
|
3707
|
+
lastProgress: z.string().optional()
|
|
3708
|
+
}).optional()
|
|
3709
|
+
});
|
|
3710
|
+
z.object({
|
|
3711
|
+
planId: z.string(),
|
|
3712
|
+
questId: z.string(),
|
|
3713
|
+
subQuestId: z.string(),
|
|
3714
|
+
reviewStatus: z.enum([
|
|
3715
|
+
"pending",
|
|
3716
|
+
"approved",
|
|
3717
|
+
"rejected"
|
|
3718
|
+
]),
|
|
3719
|
+
reviewNote: z.string().optional()
|
|
3720
|
+
});
|
|
3721
|
+
z.object({
|
|
3722
|
+
planId: z.string(),
|
|
3723
|
+
questId: z.string(),
|
|
3724
|
+
subQuestId: z.string(),
|
|
3725
|
+
status: z.enum([
|
|
3726
|
+
"not_started",
|
|
3727
|
+
"in_progress",
|
|
3728
|
+
"completed",
|
|
3729
|
+
"skipped",
|
|
3730
|
+
"deleted"
|
|
3731
|
+
]).optional(),
|
|
3732
|
+
evidence: z.string().optional(),
|
|
3733
|
+
timeSpent: z.number().optional()
|
|
3734
|
+
});
|
|
3735
|
+
z.object({
|
|
3736
|
+
planId: z.string(),
|
|
3737
|
+
summary: z.string(),
|
|
3738
|
+
nextSteps: z.array(z.string()),
|
|
3739
|
+
pendingDecisions: z.array(z.string()),
|
|
3740
|
+
blockers: z.array(z.string())
|
|
3741
|
+
});
|
|
3742
|
+
z.object({
|
|
3743
|
+
success: z.boolean(),
|
|
3744
|
+
plan: z.unknown().optional(),
|
|
3745
|
+
metrics: z.object({
|
|
3746
|
+
totalTimeSpent: z.number(),
|
|
3747
|
+
completionRate: z.number(),
|
|
3748
|
+
subQuestsCompleted: z.number(),
|
|
3749
|
+
subQuestsTotal: z.number(),
|
|
3750
|
+
lastProgress: z.string().optional()
|
|
3751
|
+
}).optional()
|
|
3752
|
+
});
|
|
3629
3753
|
//#endregion
|
|
3630
3754
|
//#region src/features/tavern/TavernActivityStream.ts
|
|
3631
3755
|
/**
|
|
@@ -3660,6 +3784,39 @@ var TavernActivityStream = class {
|
|
|
3660
3784
|
};
|
|
3661
3785
|
//#endregion
|
|
3662
3786
|
//#region src/features/tavern/tavernTools.ts
|
|
3787
|
+
const GetQuestPlanParamsSchema = z.object({ plan_id: z.string().min(1) });
|
|
3788
|
+
const UpdateReviewGateParamsSchema = z.object({
|
|
3789
|
+
plan_id: z.string().min(1),
|
|
3790
|
+
quest_id: z.string().min(1),
|
|
3791
|
+
sub_quest_id: z.string().min(1),
|
|
3792
|
+
review_status: z.enum([
|
|
3793
|
+
"pending",
|
|
3794
|
+
"approved",
|
|
3795
|
+
"rejected"
|
|
3796
|
+
]),
|
|
3797
|
+
review_note: z.string().optional()
|
|
3798
|
+
});
|
|
3799
|
+
const UpdateQuestProgressParamsSchema = z.object({
|
|
3800
|
+
plan_id: z.string().min(1),
|
|
3801
|
+
quest_id: z.string().min(1),
|
|
3802
|
+
sub_quest_id: z.string().min(1),
|
|
3803
|
+
status: z.enum([
|
|
3804
|
+
"not_started",
|
|
3805
|
+
"in_progress",
|
|
3806
|
+
"completed",
|
|
3807
|
+
"skipped",
|
|
3808
|
+
"deleted"
|
|
3809
|
+
]).optional(),
|
|
3810
|
+
evidence: z.string().optional(),
|
|
3811
|
+
time_spent: z.number().min(0).optional()
|
|
3812
|
+
});
|
|
3813
|
+
const WriteHandoffParamsSchema = z.object({
|
|
3814
|
+
plan_id: z.string().min(1),
|
|
3815
|
+
summary: z.string().min(1),
|
|
3816
|
+
next_steps: z.array(z.string()),
|
|
3817
|
+
pending_decisions: z.array(z.string()),
|
|
3818
|
+
blockers: z.array(z.string())
|
|
3819
|
+
});
|
|
3663
3820
|
/**
|
|
3664
3821
|
* Factory that creates ICompletionOptionTools[] for the Tavern feature.
|
|
3665
3822
|
*
|
|
@@ -3682,7 +3839,11 @@ function createTavernTools(service) {
|
|
|
3682
3839
|
createToggleHeartbeatsTool(service),
|
|
3683
3840
|
createTriggerHeartbeatTool(service),
|
|
3684
3841
|
createAbortHeartbeatsTool(service),
|
|
3685
|
-
createStatusTool(service)
|
|
3842
|
+
createStatusTool(service),
|
|
3843
|
+
createGetQuestPlanTool(service),
|
|
3844
|
+
createUpdateReviewGateTool(service),
|
|
3845
|
+
createUpdateQuestProgressTool(service),
|
|
3846
|
+
createWriteHandoffTool(service)
|
|
3686
3847
|
];
|
|
3687
3848
|
}
|
|
3688
3849
|
function createListAgentsTool(service) {
|
|
@@ -4211,6 +4372,187 @@ function createStatusTool(service) {
|
|
|
4211
4372
|
}
|
|
4212
4373
|
};
|
|
4213
4374
|
}
|
|
4375
|
+
function createGetQuestPlanTool(service) {
|
|
4376
|
+
return {
|
|
4377
|
+
toolSchema: {
|
|
4378
|
+
name: "tavern_get_quest_plan",
|
|
4379
|
+
description: "Fetch a quest master plan by ID. Returns the full plan with all quests, sub-quests, review gate status, handoff state, and progress metrics. Use this to check which sub-quests have review gates and their current status.",
|
|
4380
|
+
parameters: {
|
|
4381
|
+
type: "object",
|
|
4382
|
+
properties: { plan_id: {
|
|
4383
|
+
type: "string",
|
|
4384
|
+
description: "The MongoDB ObjectId of the quest master plan"
|
|
4385
|
+
} },
|
|
4386
|
+
required: ["plan_id"]
|
|
4387
|
+
}
|
|
4388
|
+
},
|
|
4389
|
+
toolFn: async (params) => {
|
|
4390
|
+
const { plan_id } = GetQuestPlanParamsSchema.parse(params);
|
|
4391
|
+
const result = await service.getQuestPlan(plan_id);
|
|
4392
|
+
return JSON.stringify(result);
|
|
4393
|
+
}
|
|
4394
|
+
};
|
|
4395
|
+
}
|
|
4396
|
+
function createUpdateReviewGateTool(service) {
|
|
4397
|
+
return {
|
|
4398
|
+
toolSchema: {
|
|
4399
|
+
name: "tavern_update_review_gate",
|
|
4400
|
+
description: "Approve or reject a review gate on a sub-quest. Review gates are human approval checkpoints — when a sub-quest has reviewGate: true, the AI must stop and wait for human approval before proceeding.",
|
|
4401
|
+
parameters: {
|
|
4402
|
+
type: "object",
|
|
4403
|
+
properties: {
|
|
4404
|
+
plan_id: {
|
|
4405
|
+
type: "string",
|
|
4406
|
+
description: "The MongoDB ObjectId of the quest master plan"
|
|
4407
|
+
},
|
|
4408
|
+
quest_id: {
|
|
4409
|
+
type: "string",
|
|
4410
|
+
description: "The ID of the parent quest"
|
|
4411
|
+
},
|
|
4412
|
+
sub_quest_id: {
|
|
4413
|
+
type: "string",
|
|
4414
|
+
description: "The ID of the sub-quest with the review gate"
|
|
4415
|
+
},
|
|
4416
|
+
review_status: {
|
|
4417
|
+
type: "string",
|
|
4418
|
+
description: "The review decision",
|
|
4419
|
+
enum: [
|
|
4420
|
+
"pending",
|
|
4421
|
+
"approved",
|
|
4422
|
+
"rejected"
|
|
4423
|
+
]
|
|
4424
|
+
},
|
|
4425
|
+
review_note: {
|
|
4426
|
+
type: "string",
|
|
4427
|
+
description: "Optional note explaining the review decision"
|
|
4428
|
+
}
|
|
4429
|
+
},
|
|
4430
|
+
required: [
|
|
4431
|
+
"plan_id",
|
|
4432
|
+
"quest_id",
|
|
4433
|
+
"sub_quest_id",
|
|
4434
|
+
"review_status"
|
|
4435
|
+
]
|
|
4436
|
+
}
|
|
4437
|
+
},
|
|
4438
|
+
toolFn: async (params) => {
|
|
4439
|
+
const { plan_id, quest_id, sub_quest_id, review_status, review_note } = UpdateReviewGateParamsSchema.parse(params);
|
|
4440
|
+
const result = await service.updateReviewGate(plan_id, quest_id, sub_quest_id, review_status, review_note);
|
|
4441
|
+
return JSON.stringify(result);
|
|
4442
|
+
}
|
|
4443
|
+
};
|
|
4444
|
+
}
|
|
4445
|
+
function createUpdateQuestProgressTool(service) {
|
|
4446
|
+
return {
|
|
4447
|
+
toolSchema: {
|
|
4448
|
+
name: "tavern_update_quest_progress",
|
|
4449
|
+
description: "Update a sub-quest's progress. Set status to track completion, add evidence of what was accomplished, and optionally record time spent. Setting status to \"in_progress\" auto-resumes a paused plan.",
|
|
4450
|
+
parameters: {
|
|
4451
|
+
type: "object",
|
|
4452
|
+
properties: {
|
|
4453
|
+
plan_id: {
|
|
4454
|
+
type: "string",
|
|
4455
|
+
description: "The MongoDB ObjectId of the quest master plan"
|
|
4456
|
+
},
|
|
4457
|
+
quest_id: {
|
|
4458
|
+
type: "string",
|
|
4459
|
+
description: "The ID of the parent quest"
|
|
4460
|
+
},
|
|
4461
|
+
sub_quest_id: {
|
|
4462
|
+
type: "string",
|
|
4463
|
+
description: "The ID of the sub-quest to update"
|
|
4464
|
+
},
|
|
4465
|
+
status: {
|
|
4466
|
+
type: "string",
|
|
4467
|
+
description: "New status for the sub-quest",
|
|
4468
|
+
enum: [
|
|
4469
|
+
"not_started",
|
|
4470
|
+
"in_progress",
|
|
4471
|
+
"completed",
|
|
4472
|
+
"skipped",
|
|
4473
|
+
"deleted"
|
|
4474
|
+
]
|
|
4475
|
+
},
|
|
4476
|
+
evidence: {
|
|
4477
|
+
type: "string",
|
|
4478
|
+
description: "Evidence of completion — links to artifacts, descriptions of output, or references to results"
|
|
4479
|
+
},
|
|
4480
|
+
time_spent: {
|
|
4481
|
+
type: "number",
|
|
4482
|
+
description: "Time spent on this sub-quest in milliseconds"
|
|
4483
|
+
}
|
|
4484
|
+
},
|
|
4485
|
+
required: [
|
|
4486
|
+
"plan_id",
|
|
4487
|
+
"quest_id",
|
|
4488
|
+
"sub_quest_id"
|
|
4489
|
+
]
|
|
4490
|
+
}
|
|
4491
|
+
},
|
|
4492
|
+
toolFn: async (params) => {
|
|
4493
|
+
const { plan_id, quest_id, sub_quest_id, status, evidence, time_spent } = UpdateQuestProgressParamsSchema.parse(params);
|
|
4494
|
+
const updates = {};
|
|
4495
|
+
if (status !== void 0) updates.status = status;
|
|
4496
|
+
if (evidence !== void 0) updates.evidence = evidence;
|
|
4497
|
+
if (time_spent !== void 0) updates.timeSpent = time_spent;
|
|
4498
|
+
const result = await service.updateSubQuestProgress(plan_id, quest_id, sub_quest_id, updates);
|
|
4499
|
+
return JSON.stringify(result);
|
|
4500
|
+
}
|
|
4501
|
+
};
|
|
4502
|
+
}
|
|
4503
|
+
function createWriteHandoffTool(service) {
|
|
4504
|
+
return {
|
|
4505
|
+
toolSchema: {
|
|
4506
|
+
name: "tavern_write_handoff",
|
|
4507
|
+
description: "Write a handoff state for session continuity. Called when ending a session so the next session can resume with full context. Includes a summary of progress, next steps, pending decisions, and blockers.",
|
|
4508
|
+
parameters: {
|
|
4509
|
+
type: "object",
|
|
4510
|
+
properties: {
|
|
4511
|
+
plan_id: {
|
|
4512
|
+
type: "string",
|
|
4513
|
+
description: "The MongoDB ObjectId of the quest master plan"
|
|
4514
|
+
},
|
|
4515
|
+
summary: {
|
|
4516
|
+
type: "string",
|
|
4517
|
+
description: "Summary of what was accomplished in this session"
|
|
4518
|
+
},
|
|
4519
|
+
next_steps: {
|
|
4520
|
+
type: "array",
|
|
4521
|
+
items: { type: "string" },
|
|
4522
|
+
description: "List of next steps for the following session"
|
|
4523
|
+
},
|
|
4524
|
+
pending_decisions: {
|
|
4525
|
+
type: "array",
|
|
4526
|
+
items: { type: "string" },
|
|
4527
|
+
description: "Decisions that still need to be made"
|
|
4528
|
+
},
|
|
4529
|
+
blockers: {
|
|
4530
|
+
type: "array",
|
|
4531
|
+
items: { type: "string" },
|
|
4532
|
+
description: "Current blockers preventing progress"
|
|
4533
|
+
}
|
|
4534
|
+
},
|
|
4535
|
+
required: [
|
|
4536
|
+
"plan_id",
|
|
4537
|
+
"summary",
|
|
4538
|
+
"next_steps",
|
|
4539
|
+
"pending_decisions",
|
|
4540
|
+
"blockers"
|
|
4541
|
+
]
|
|
4542
|
+
}
|
|
4543
|
+
},
|
|
4544
|
+
toolFn: async (params) => {
|
|
4545
|
+
const { plan_id, summary, next_steps, pending_decisions, blockers } = WriteHandoffParamsSchema.parse(params);
|
|
4546
|
+
const result = await service.updateHandoff(plan_id, {
|
|
4547
|
+
summary,
|
|
4548
|
+
nextSteps: next_steps,
|
|
4549
|
+
pendingDecisions: pending_decisions,
|
|
4550
|
+
blockers
|
|
4551
|
+
});
|
|
4552
|
+
return JSON.stringify(result);
|
|
4553
|
+
}
|
|
4554
|
+
};
|
|
4555
|
+
}
|
|
4214
4556
|
//#endregion
|
|
4215
4557
|
//#region src/features/tavern/TavernModule.ts
|
|
4216
4558
|
/** Icons for heartbeat log actions shown in /tavern command */
|
|
@@ -4274,9 +4616,23 @@ Available actions:
|
|
|
4274
4616
|
- **tavern_trigger_heartbeat**: Manually trigger a heartbeat cycle
|
|
4275
4617
|
- **tavern_abort_heartbeats**: Emergency stop all in-flight heartbeats
|
|
4276
4618
|
- **tavern_status**: Quick overview of agents, quests, and gates — good for situational awareness
|
|
4619
|
+
- **tavern_get_quest_plan**: Fetch a quest master plan with review gate status and handoff state
|
|
4620
|
+
- **tavern_update_review_gate**: Approve or reject a review gate on a sub-quest
|
|
4621
|
+
- **tavern_update_quest_progress**: Update sub-quest status and record evidence of completion
|
|
4622
|
+
- **tavern_write_handoff**: Write session handoff for continuity across sessions
|
|
4277
4623
|
|
|
4278
4624
|
When the user mentions talking to agents, checking the quest board, or managing the tavern, use these tools.
|
|
4279
|
-
Agents have personalities, moods, quests, and memories — they are autonomous entities, not chatbots
|
|
4625
|
+
Agents have personalities, moods, quests, and memories — they are autonomous entities, not chatbots.
|
|
4626
|
+
|
|
4627
|
+
## Quest Workflow (Review Gates)
|
|
4628
|
+
When working on a quest plan with review gates (reviewGate: true on sub-quests), you MUST:
|
|
4629
|
+
1. Check review gate status with tavern_get_quest_plan before proceeding past a gated step
|
|
4630
|
+
2. If the next sub-quest has reviewGate: true and reviewStatus is not 'approved', STOP and inform the user
|
|
4631
|
+
3. Record evidence of completion with tavern_update_quest_progress when finishing a sub-quest
|
|
4632
|
+
4. Write a handoff with tavern_write_handoff before ending a session with an active quest plan
|
|
4633
|
+
|
|
4634
|
+
## Session Handoff & Resume
|
|
4635
|
+
When the user runs /quest resume <plan_id>, read the handoff context and continue from where the previous session left off. The handoff contains: summary of prior work, next steps, pending decisions, and blockers.`;
|
|
4280
4636
|
}
|
|
4281
4637
|
getCommands() {
|
|
4282
4638
|
return [{
|
|
@@ -4301,6 +4657,95 @@ Agents have personalities, moods, quests, and memories — they are autonomous e
|
|
|
4301
4657
|
}
|
|
4302
4658
|
console.log("");
|
|
4303
4659
|
}
|
|
4660
|
+
}, {
|
|
4661
|
+
name: "quest",
|
|
4662
|
+
description: "Quest workflow commands: review gates, resume from handoff",
|
|
4663
|
+
execute: async (args) => {
|
|
4664
|
+
const subCommand = args[0];
|
|
4665
|
+
if (subCommand === "resume") {
|
|
4666
|
+
const planId = args[1];
|
|
4667
|
+
if (!planId) {
|
|
4668
|
+
console.log("\nUsage: /quest resume <plan_id>");
|
|
4669
|
+
console.log(" Loads the quest plan and displays the session handoff for continuity.\n");
|
|
4670
|
+
return;
|
|
4671
|
+
}
|
|
4672
|
+
try {
|
|
4673
|
+
const plan = await this.service.getQuestPlan(planId);
|
|
4674
|
+
console.log(`\nQuest Plan: ${plan.goal}`);
|
|
4675
|
+
console.log(`State: ${plan.state ?? "unknown"}`);
|
|
4676
|
+
if (plan.metrics) {
|
|
4677
|
+
const pct = Math.round(plan.metrics.completionRate * 100);
|
|
4678
|
+
console.log(`Progress: ${plan.metrics.subQuestsCompleted}/${plan.metrics.subQuestsTotal} sub-quests (${pct}%)`);
|
|
4679
|
+
}
|
|
4680
|
+
if (!plan.handoff) {
|
|
4681
|
+
console.log("\n No handoff found — this plan has no saved session context.");
|
|
4682
|
+
console.log(" The AI can still read the plan via tavern_get_quest_plan.\n");
|
|
4683
|
+
return;
|
|
4684
|
+
}
|
|
4685
|
+
const { handoff } = plan;
|
|
4686
|
+
console.log(`\nSession Handoff (${new Date(handoff.updatedAt).toLocaleString()}):`);
|
|
4687
|
+
console.log(`\n Summary: ${handoff.summary}`);
|
|
4688
|
+
if (handoff.nextSteps.length > 0) {
|
|
4689
|
+
console.log("\n Next Steps:");
|
|
4690
|
+
for (const step of handoff.nextSteps) console.log(` \u2022 ${step}`);
|
|
4691
|
+
}
|
|
4692
|
+
if (handoff.pendingDecisions.length > 0) {
|
|
4693
|
+
console.log("\n Pending Decisions:");
|
|
4694
|
+
for (const decision of handoff.pendingDecisions) console.log(` \u2753 ${decision}`);
|
|
4695
|
+
}
|
|
4696
|
+
if (handoff.blockers.length > 0) {
|
|
4697
|
+
console.log("\n Blockers:");
|
|
4698
|
+
for (const blocker of handoff.blockers) console.log(` \u{1F6D1} ${blocker}`);
|
|
4699
|
+
}
|
|
4700
|
+
console.log("");
|
|
4701
|
+
} catch (error) {
|
|
4702
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4703
|
+
console.log(`\nError fetching quest plan: ${message}\n`);
|
|
4704
|
+
}
|
|
4705
|
+
return;
|
|
4706
|
+
}
|
|
4707
|
+
if (subCommand === "review") {
|
|
4708
|
+
const planId = args[1];
|
|
4709
|
+
if (!planId) {
|
|
4710
|
+
console.log("\nUsage: /quest review <plan_id>");
|
|
4711
|
+
console.log(" Fetches the quest plan and shows sub-quests with pending review gates.\n");
|
|
4712
|
+
return;
|
|
4713
|
+
}
|
|
4714
|
+
try {
|
|
4715
|
+
const plan = await this.service.getQuestPlan(planId);
|
|
4716
|
+
const pendingGates = [];
|
|
4717
|
+
for (const quest of plan.quests) for (const sq of quest.subQuests) if (sq.reviewGate) pendingGates.push({
|
|
4718
|
+
questTitle: quest.title,
|
|
4719
|
+
questId: quest.id,
|
|
4720
|
+
subQuestTitle: sq.title,
|
|
4721
|
+
subQuestId: sq.id,
|
|
4722
|
+
status: sq.reviewStatus ?? "pending"
|
|
4723
|
+
});
|
|
4724
|
+
if (pendingGates.length === 0) {
|
|
4725
|
+
console.log(`\nQuest Plan: ${plan.goal}`);
|
|
4726
|
+
console.log(" No review gates configured in this plan.\n");
|
|
4727
|
+
return;
|
|
4728
|
+
}
|
|
4729
|
+
console.log(`\nQuest Plan: ${plan.goal}`);
|
|
4730
|
+
console.log(`State: ${plan.state ?? "unknown"}\n`);
|
|
4731
|
+
console.log("Review Gates:");
|
|
4732
|
+
for (const gate of pendingGates) {
|
|
4733
|
+
const icon = gate.status === "approved" ? "✅" : gate.status === "rejected" ? "❌" : "⏸️";
|
|
4734
|
+
console.log(` ${icon} [${gate.status}] ${gate.questTitle} > ${gate.subQuestTitle}`);
|
|
4735
|
+
console.log(` quest_id: ${gate.questId} sub_quest_id: ${gate.subQuestId}`);
|
|
4736
|
+
}
|
|
4737
|
+
console.log("\n To approve: ask the AI to approve a review gate, or use tavern_update_review_gate tool.\n");
|
|
4738
|
+
} catch (error) {
|
|
4739
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4740
|
+
console.log(`\nError fetching quest plan: ${message}\n`);
|
|
4741
|
+
}
|
|
4742
|
+
return;
|
|
4743
|
+
}
|
|
4744
|
+
console.log("\nUsage:");
|
|
4745
|
+
console.log(" /quest review <plan_id> — Show review gates and their status");
|
|
4746
|
+
console.log(" /quest resume <plan_id> — Load handoff and resume from where you left off");
|
|
4747
|
+
console.log("");
|
|
4748
|
+
}
|
|
4304
4749
|
}];
|
|
4305
4750
|
}
|
|
4306
4751
|
registerWsHandlers(wsManager) {
|
|
@@ -4591,6 +5036,8 @@ function CliApp() {
|
|
|
4591
5036
|
const [initError, setInitError] = useState(null);
|
|
4592
5037
|
const [commandHistory, setCommandHistory] = useState([]);
|
|
4593
5038
|
const imageStoreInitPromise = useRef(null);
|
|
5039
|
+
const decisionStoreRef = useRef(createDecisionStore());
|
|
5040
|
+
const blockerStoreRef = useRef(createBlockerStore());
|
|
4594
5041
|
const setStoreSession = useCliStore((state) => state.setSession);
|
|
4595
5042
|
const enqueuePermissionPrompt = useCliStore((state) => state.enqueuePermissionPrompt);
|
|
4596
5043
|
const enqueueUserQuestionPrompt = useCliStore((state) => state.enqueueUserQuestionPrompt);
|
|
@@ -5033,6 +5480,15 @@ function CliApp() {
|
|
|
5033
5480
|
logger.warn(`⚠️ Model "${fromModel}" failed (${error.message}) — falling back to "${toModel}"`);
|
|
5034
5481
|
}) : llm, backgroundManager);
|
|
5035
5482
|
const writeTodosTool = createWriteTodosTool(createTodoStore());
|
|
5483
|
+
const decisionLogTool = createDecisionLogTool(decisionStoreRef.current);
|
|
5484
|
+
const blockerTools = createBlockerTools(blockerStoreRef.current);
|
|
5485
|
+
if (newSession.metadata.workflow) {
|
|
5486
|
+
decisionStoreRef.current.decisions = [...newSession.metadata.workflow.decisions];
|
|
5487
|
+
blockerStoreRef.current.blockers = [...newSession.metadata.workflow.blockers];
|
|
5488
|
+
} else {
|
|
5489
|
+
decisionStoreRef.current.decisions = [];
|
|
5490
|
+
blockerStoreRef.current.blockers = [];
|
|
5491
|
+
}
|
|
5036
5492
|
const enableSkillTool = config.preferences.enableSkillTool !== false;
|
|
5037
5493
|
const skillTool = enableSkillTool ? createSkillTool({
|
|
5038
5494
|
customCommandStore: state.customCommandStore,
|
|
@@ -5050,6 +5506,8 @@ function CliApp() {
|
|
|
5050
5506
|
agentDelegateTool,
|
|
5051
5507
|
...backgroundTools,
|
|
5052
5508
|
writeTodosTool,
|
|
5509
|
+
decisionLogTool,
|
|
5510
|
+
...blockerTools,
|
|
5053
5511
|
findDefinitionTool,
|
|
5054
5512
|
getFileStructureTool
|
|
5055
5513
|
];
|
|
@@ -5479,7 +5937,13 @@ function CliApp() {
|
|
|
5479
5937
|
...currentSession.metadata,
|
|
5480
5938
|
totalTokens: currentSession.metadata.totalTokens + result.completionInfo.totalTokens,
|
|
5481
5939
|
totalCredits: (currentSession.metadata.totalCredits || 0) + (result.completionInfo.totalCredits || 0),
|
|
5482
|
-
toolCallCount: currentSession.metadata.toolCallCount + successfulToolCalls
|
|
5940
|
+
toolCallCount: currentSession.metadata.toolCallCount + successfulToolCalls,
|
|
5941
|
+
workflow: decisionStoreRef.current.decisions.length > 0 || blockerStoreRef.current.blockers.length > 0 ? {
|
|
5942
|
+
decisions: decisionStoreRef.current.decisions,
|
|
5943
|
+
blockers: blockerStoreRef.current.blockers,
|
|
5944
|
+
handoff: currentSession.metadata.workflow?.handoff,
|
|
5945
|
+
reviewGates: currentSession.metadata.workflow?.reviewGates
|
|
5946
|
+
} : currentSession.metadata.workflow
|
|
5483
5947
|
}
|
|
5484
5948
|
};
|
|
5485
5949
|
setState((prev) => ({
|
|
@@ -6095,6 +6559,12 @@ Multi-line Input:
|
|
|
6095
6559
|
}
|
|
6096
6560
|
const sessionName = args.join(" ") || state.session.name;
|
|
6097
6561
|
state.session.name = sessionName;
|
|
6562
|
+
if (decisionStoreRef.current.decisions.length > 0 || blockerStoreRef.current.blockers.length > 0) state.session.metadata.workflow = {
|
|
6563
|
+
decisions: decisionStoreRef.current.decisions,
|
|
6564
|
+
blockers: blockerStoreRef.current.blockers,
|
|
6565
|
+
handoff: state.session.metadata.workflow?.handoff,
|
|
6566
|
+
reviewGates: state.session.metadata.workflow?.reviewGates
|
|
6567
|
+
};
|
|
6098
6568
|
await state.sessionStore.save(state.session);
|
|
6099
6569
|
console.log(`✅ Session saved as "${sessionName}"`);
|
|
6100
6570
|
break;
|
|
@@ -6355,6 +6825,8 @@ Multi-line Input:
|
|
|
6355
6825
|
};
|
|
6356
6826
|
await logger.initialize(newSession.id);
|
|
6357
6827
|
logger.debug("=== New Session Started via /clear ===");
|
|
6828
|
+
decisionStoreRef.current.decisions = [];
|
|
6829
|
+
blockerStoreRef.current.blockers = [];
|
|
6358
6830
|
if (state.checkpointStore) state.checkpointStore.setSessionId(newSession.id);
|
|
6359
6831
|
setState((prev) => ({
|
|
6360
6832
|
...prev,
|
|
@@ -7046,6 +7518,16 @@ Multi-line Input:
|
|
|
7046
7518
|
console.log(`✅ Removed directory: ${resolvedRemovePath}`);
|
|
7047
7519
|
break;
|
|
7048
7520
|
}
|
|
7521
|
+
case "decisions":
|
|
7522
|
+
console.log("\n📋 Decision Log\n");
|
|
7523
|
+
console.log(formatDecisionsOutput(decisionStoreRef.current.decisions));
|
|
7524
|
+
console.log("");
|
|
7525
|
+
break;
|
|
7526
|
+
case "blockers":
|
|
7527
|
+
console.log("\n🚧 Blockers\n");
|
|
7528
|
+
console.log(formatBlockersOutput(blockerStoreRef.current.blockers));
|
|
7529
|
+
console.log("");
|
|
7530
|
+
break;
|
|
7049
7531
|
case "dirs": {
|
|
7050
7532
|
const additionalDirs = await state.configStore.getAdditionalDirectories();
|
|
7051
7533
|
const cwd = process.cwd();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as RechartsChartTypeList, A as ImageGenerationUsageTransaction, At as secureParameters, B as NotFoundError, C as FileEvents, Ct as getMcpProviderMetadata, D as GenericCreditAddTransaction, Dt as obfuscateApiKey, E as GenerateImageToolCallSchema, Et as isGPTImageModel, F as KnowledgeType, G as ProfileEvents, H as OpenAIImageGenerationInput, I as LLMEvents, J as PurchaseTransaction, K as ProjectEvents, L as MiscEvents, M as InboxEvents, N as InviteEvents, Nt as CollectionType, O as GenericCreditDeductTransaction, Ot as resolveNavigationIntents, P as InviteType, Q as ReceivedCreditTransaction, R as ModalEvents, S as FeedbackEvents, St as getDataLakeTags, T as GEMINI_IMAGE_MODELS, Tt as isGPTImage2Model, U as Permission, V as OpenAIEmbeddingModel, W as PermissionDeniedError, X as REASONING_SUPPORTED_MODELS, Y as QuestMasterParamsSchema, Z as RealtimeVoiceUsageTransaction, _ as CompletionApiUsageTransaction, _t as VideoModels, a as ApiKeyEvents, at as SessionEvents, b as FIXED_TEMPERATURE_MODELS, bt as b4mLLMTools, c as AppFileEvents, ct as SupportedFabFileMimeTypes, d as BFL_IMAGE_MODELS, dt as TextGenerationUsageTransaction, et as RegInviteEvents, f as BFL_SAFETY_TOLERANCE, ft as ToolUsageTransaction, g as ChatModels, gt as VideoGenerationUsageTransaction, h as ChatCompletionCreateInputSchema, ht as VIDEO_SIZE_CONSTRAINTS, i as AiEvents, it as ResearchTaskType, j as ImageModels, k as ImageEditUsageTransaction, kt as sanitizeTelemetryError, l as ArtifactTypeSchema, lt as TagType, mt as UiNavigationEvents, n as logger, nt as ResearchTaskExecutionType, o as ApiKeyScope, ot as SpeechToTextModels, p as BedrockEmbeddingModel, pt as TransferCreditTransaction, q as PromptMetaZodSchema, r as ALERT_THRESHOLDS, rt as ResearchTaskPeriodicFrequencyType, s as ApiKeyType, st as SubscriptionCreditTransaction, t as ConfigStore, tt as ResearchModeParamsSchema, u as AuthEvents, ut as TaskScheduleHandler, v as DashboardParamsSchema, vt as VoyageAIEmbeddingModel, w as FriendshipEvents, wt as getViewById, x as FavoriteDocumentType, xt as getAccessibleDataLakes, y as ElabsEvents, yt as XAI_IMAGE_MODELS, z as ModelBackend } from "./ConfigStore-
|
|
2
|
+
import { $ as RechartsChartTypeList, A as ImageGenerationUsageTransaction, At as secureParameters, B as NotFoundError, C as FileEvents, Ct as getMcpProviderMetadata, D as GenericCreditAddTransaction, Dt as obfuscateApiKey, E as GenerateImageToolCallSchema, Et as isGPTImageModel, F as KnowledgeType, G as ProfileEvents, H as OpenAIImageGenerationInput, I as LLMEvents, J as PurchaseTransaction, K as ProjectEvents, L as MiscEvents, M as InboxEvents, N as InviteEvents, Nt as CollectionType, O as GenericCreditDeductTransaction, Ot as resolveNavigationIntents, P as InviteType, Q as ReceivedCreditTransaction, R as ModalEvents, S as FeedbackEvents, St as getDataLakeTags, T as GEMINI_IMAGE_MODELS, Tt as isGPTImage2Model, U as Permission, V as OpenAIEmbeddingModel, W as PermissionDeniedError, X as REASONING_SUPPORTED_MODELS, Y as QuestMasterParamsSchema, Z as RealtimeVoiceUsageTransaction, _ as CompletionApiUsageTransaction, _t as VideoModels, a as ApiKeyEvents, at as SessionEvents, b as FIXED_TEMPERATURE_MODELS, bt as b4mLLMTools, c as AppFileEvents, ct as SupportedFabFileMimeTypes, d as BFL_IMAGE_MODELS, dt as TextGenerationUsageTransaction, et as RegInviteEvents, f as BFL_SAFETY_TOLERANCE, ft as ToolUsageTransaction, g as ChatModels, gt as VideoGenerationUsageTransaction, h as ChatCompletionCreateInputSchema, ht as VIDEO_SIZE_CONSTRAINTS, i as AiEvents, it as ResearchTaskType, j as ImageModels, k as ImageEditUsageTransaction, kt as sanitizeTelemetryError, l as ArtifactTypeSchema, lt as TagType, mt as UiNavigationEvents, n as logger, nt as ResearchTaskExecutionType, o as ApiKeyScope, ot as SpeechToTextModels, p as BedrockEmbeddingModel, pt as TransferCreditTransaction, q as PromptMetaZodSchema, r as ALERT_THRESHOLDS, rt as ResearchTaskPeriodicFrequencyType, s as ApiKeyType, st as SubscriptionCreditTransaction, t as ConfigStore, tt as ResearchModeParamsSchema, u as AuthEvents, ut as TaskScheduleHandler, v as DashboardParamsSchema, vt as VoyageAIEmbeddingModel, w as FriendshipEvents, wt as getViewById, x as FavoriteDocumentType, xt as getAccessibleDataLakes, y as ElabsEvents, yt as XAI_IMAGE_MODELS, z as ModelBackend } from "./ConfigStore-DBUmvCfe.mjs";
|
|
3
3
|
import { n as isPathAllowed, t as assertPathAllowed } from "./pathValidation-CIytuhr3-Dt5dntLx.mjs";
|
|
4
4
|
import { execFile, execFileSync, spawn } from "child_process";
|
|
5
5
|
import { createHash, randomBytes } from "crypto";
|
|
@@ -522,6 +522,14 @@ const COMMANDS = [
|
|
|
522
522
|
{
|
|
523
523
|
name: "dirs",
|
|
524
524
|
description: "List all accessible directories"
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
name: "decisions",
|
|
528
|
+
description: "Show decision log for current session"
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
name: "blockers",
|
|
532
|
+
description: "Show tracked blockers for current session"
|
|
525
533
|
}
|
|
526
534
|
];
|
|
527
535
|
/**
|
|
@@ -3015,7 +3023,18 @@ EXAMPLES:
|
|
|
3015
3023
|
- "what packages installed?" → ${TOOL_GLOB_FILES} "**/package.json" → ${TOOL_FILE_READ}
|
|
3016
3024
|
- "find all components using React hooks" → ${TOOL_SUBAGENT_DELEGATE}(task="find all components using React hooks", type="explore")
|
|
3017
3025
|
|
|
3018
|
-
Remember: Use context from previous messages to understand follow-up questions
|
|
3026
|
+
Remember: Use context from previous messages to understand follow-up questions.
|
|
3027
|
+
|
|
3028
|
+
DURABLE WORKFLOW TRACKING:
|
|
3029
|
+
You have tools for tracking decisions and blockers during your work. These create an audit trail that persists across sessions, enabling anyone to understand why things were done and what's still outstanding.
|
|
3030
|
+
|
|
3031
|
+
- log_decision: When you make a significant decision (architecture choice, scope narrowing, interpretation of ambiguous requirements, trade-off between alternatives), log it with rationale. Do NOT log trivial decisions. Log decisions that would matter if someone needed to understand WHY you did something or if they needed to resume this work.
|
|
3032
|
+
|
|
3033
|
+
- track_blocker: When you encounter something blocking progress (missing information, unclear requirements, external dependencies, ambiguous specs that need human clarification), track it. This makes blockers visible so they can be addressed.
|
|
3034
|
+
|
|
3035
|
+
- resolve_blocker: When a blocker is cleared, record how it was resolved. Use the blocker ID from the track_blocker output.
|
|
3036
|
+
|
|
3037
|
+
These tools are lightweight — use them naturally as part of your work, not as a ceremony.${directoriesSection}${projectContextSection}${skillsSection}${featureModulesSection}`;
|
|
3019
3038
|
}
|
|
3020
3039
|
/**
|
|
3021
3040
|
* Build the dynamic agent creation prompt section
|
|
@@ -6675,15 +6694,26 @@ const webSearchTool = {
|
|
|
6675
6694
|
};
|
|
6676
6695
|
//#endregion
|
|
6677
6696
|
//#region ../../b4m-core/services/dist/llm/tools/implementation/webfetch/index.mjs
|
|
6697
|
+
const DEFAULT_TIMEOUT_MS = 6e4;
|
|
6698
|
+
const PDF_TIMEOUT_MS = 9e4;
|
|
6699
|
+
function isPdfUrl(url) {
|
|
6700
|
+
try {
|
|
6701
|
+
const { pathname } = new URL(url);
|
|
6702
|
+
return pathname.toLowerCase().endsWith(".pdf");
|
|
6703
|
+
} catch {
|
|
6704
|
+
return false;
|
|
6705
|
+
}
|
|
6706
|
+
}
|
|
6678
6707
|
/**
|
|
6679
6708
|
* Fetch URL content using Firecrawl (shared function, no ToolContext)
|
|
6680
6709
|
* Pattern follows serpApiSearch from websearch tool
|
|
6681
6710
|
*
|
|
6682
6711
|
* @param adapters - Database adapters for fetching Firecrawl API key
|
|
6683
6712
|
* @param url - URL to fetch
|
|
6713
|
+
* @param options - Optional configuration (e.g. maxTimeoutMs for Lambda-constrained callers)
|
|
6684
6714
|
* @returns Markdown content and title
|
|
6685
6715
|
*/
|
|
6686
|
-
async function firecrawlFetch(adapters, url) {
|
|
6716
|
+
async function firecrawlFetch(adapters, url, options) {
|
|
6687
6717
|
if (!/^https?:\/\/.+/i.test(url)) throw new Error(`Invalid URL format: ${url}. URL must start with http:// or https://`);
|
|
6688
6718
|
const apiKeySetting = await adapters.db.adminSettings.findBySettingName("FirecrawlApiKey");
|
|
6689
6719
|
if (!apiKeySetting?.settingValue) {
|
|
@@ -6691,45 +6721,45 @@ async function firecrawlFetch(adapters, url) {
|
|
|
6691
6721
|
throw new Error("Firecrawl API key not configured");
|
|
6692
6722
|
}
|
|
6693
6723
|
const app = new FirecrawlApp({ apiKey: apiKeySetting.settingValue });
|
|
6694
|
-
const
|
|
6695
|
-
const
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
console.
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
}
|
|
6724
|
+
const isPdf = isPdfUrl(url);
|
|
6725
|
+
const desiredTimeout = isPdf ? PDF_TIMEOUT_MS : DEFAULT_TIMEOUT_MS;
|
|
6726
|
+
const timeoutMs = options?.maxTimeoutMs ? Math.min(desiredTimeout, options.maxTimeoutMs) : desiredTimeout;
|
|
6727
|
+
console.log(`📥 WebFetch Tool: Scraping URL with Firecrawl${isPdf ? " (PDF mode, extended timeout)" : ""}...`);
|
|
6728
|
+
const baseParams = {
|
|
6729
|
+
formats: ["markdown"],
|
|
6730
|
+
timeout: timeoutMs
|
|
6731
|
+
};
|
|
6732
|
+
let result;
|
|
6733
|
+
if (isPdf) result = await app.scrapeUrl(url, baseParams);
|
|
6734
|
+
else try {
|
|
6735
|
+
result = await app.scrapeUrl(url, {
|
|
6736
|
+
...baseParams,
|
|
6737
|
+
actions: [{
|
|
6738
|
+
type: "wait",
|
|
6739
|
+
milliseconds: 1e3
|
|
6740
|
+
}]
|
|
6741
|
+
});
|
|
6742
|
+
} catch (scrapeError) {
|
|
6743
|
+
if ((scrapeError instanceof Error ? scrapeError.message : "").includes("Actions are not supported")) {
|
|
6744
|
+
console.log("📥 WebFetch Tool: Actions not supported, retrying without actions...");
|
|
6745
|
+
result = await app.scrapeUrl(url, baseParams);
|
|
6746
|
+
} else throw scrapeError;
|
|
6747
|
+
}
|
|
6748
|
+
if (!result || result.error) {
|
|
6749
|
+
const errorMessage = result?.error || "Unknown error";
|
|
6750
|
+
console.error("❌ WebFetch Tool: Firecrawl error:", errorMessage);
|
|
6751
|
+
throw new Error(`Failed to fetch content from URL: ${errorMessage}`);
|
|
6752
|
+
}
|
|
6753
|
+
if (!("markdown" in result) || !result.markdown) {
|
|
6754
|
+
console.error("❌ WebFetch Tool: No markdown content returned");
|
|
6755
|
+
throw new Error("No content could be extracted from the URL");
|
|
6756
|
+
}
|
|
6757
|
+
const markdown = result.markdown.slice(0, 5e4);
|
|
6758
|
+
console.log(`📄 WebFetch Tool: Extracted ${markdown.length} characters of content`);
|
|
6759
|
+
return {
|
|
6760
|
+
markdown,
|
|
6761
|
+
title: result.metadata?.title
|
|
6762
|
+
};
|
|
6733
6763
|
}
|
|
6734
6764
|
const webFetchTool = {
|
|
6735
6765
|
name: "web_fetch",
|
|
@@ -6785,6 +6815,14 @@ const webFetchTool = {
|
|
|
6785
6815
|
await context.statusUpdate({}, `WebFetch: ${statusLabel}`);
|
|
6786
6816
|
return userMessage;
|
|
6787
6817
|
}
|
|
6818
|
+
if (error instanceof FirecrawlError && error.statusCode === 500 && errorMessage.includes("PDF")) {
|
|
6819
|
+
context.logger.warn("WebFetch PDF too large for Firecrawl", {
|
|
6820
|
+
url: params.url,
|
|
6821
|
+
error: errorMessage
|
|
6822
|
+
});
|
|
6823
|
+
await context.statusUpdate({}, "WebFetch: PDF too large");
|
|
6824
|
+
return `This PDF is too large to process via URL. Please download the file and upload it directly instead.`;
|
|
6825
|
+
}
|
|
6788
6826
|
if ([
|
|
6789
6827
|
"no response received",
|
|
6790
6828
|
"econnrefused",
|
|
@@ -15356,9 +15394,12 @@ z.object({
|
|
|
15356
15394
|
direction: z.enum(["asc", "desc"])
|
|
15357
15395
|
}).optional(),
|
|
15358
15396
|
options: z.object({
|
|
15397
|
+
textSearch: z.coerce.boolean().optional(),
|
|
15359
15398
|
includeShared: z.coerce.boolean().optional(),
|
|
15360
15399
|
userGroups: z.array(z.string()).optional(),
|
|
15361
|
-
dataLakeTags: z.array(z.string()).optional()
|
|
15400
|
+
dataLakeTags: z.array(z.string()).optional(),
|
|
15401
|
+
dataLakeTagPrefixes: z.array(z.string()).optional(),
|
|
15402
|
+
excludeContent: z.coerce.boolean().optional()
|
|
15362
15403
|
}).optional()
|
|
15363
15404
|
});
|
|
15364
15405
|
z.object({ fileId: z.string() });
|
|
@@ -23476,4 +23517,234 @@ function createGetFileStructureTool() {
|
|
|
23476
23517
|
};
|
|
23477
23518
|
}
|
|
23478
23519
|
//#endregion
|
|
23479
|
-
|
|
23520
|
+
//#region src/tools/decisionLogTool.ts
|
|
23521
|
+
/**
|
|
23522
|
+
* Validate log_decision parameters
|
|
23523
|
+
* @throws Error if validation fails
|
|
23524
|
+
*/
|
|
23525
|
+
function validateParams(args) {
|
|
23526
|
+
const params = args;
|
|
23527
|
+
if (typeof params.summary !== "string" || params.summary.trim() === "") throw new Error("log_decision: summary must be a non-empty string");
|
|
23528
|
+
if (typeof params.rationale !== "string" || params.rationale.trim() === "") throw new Error("log_decision: rationale must be a non-empty string");
|
|
23529
|
+
if (params.alternatives !== void 0) {
|
|
23530
|
+
if (!Array.isArray(params.alternatives)) throw new Error("log_decision: alternatives must be an array of strings");
|
|
23531
|
+
for (const alt of params.alternatives) if (typeof alt !== "string") throw new Error("log_decision: each alternative must be a string");
|
|
23532
|
+
}
|
|
23533
|
+
if (params.context !== void 0 && typeof params.context !== "string") throw new Error("log_decision: context must be a string");
|
|
23534
|
+
return {
|
|
23535
|
+
summary: params.summary.trim(),
|
|
23536
|
+
rationale: params.rationale.trim(),
|
|
23537
|
+
alternatives: params.alternatives,
|
|
23538
|
+
context: typeof params.context === "string" ? params.context.trim() : void 0
|
|
23539
|
+
};
|
|
23540
|
+
}
|
|
23541
|
+
/**
|
|
23542
|
+
* Format decisions for display output
|
|
23543
|
+
*/
|
|
23544
|
+
function formatDecisionsOutput(decisions) {
|
|
23545
|
+
if (decisions.length === 0) return "No decisions logged in this session.";
|
|
23546
|
+
return decisions.map((decision, index) => {
|
|
23547
|
+
const lines = [`${index + 1}. **${decision.summary}**`, ` Rationale: ${decision.rationale}`];
|
|
23548
|
+
if (decision.alternatives && decision.alternatives.length > 0) lines.push(` Alternatives considered: ${decision.alternatives.join(", ")}`);
|
|
23549
|
+
if (decision.context) lines.push(` Context: ${decision.context}`);
|
|
23550
|
+
const timestamp = new Date(decision.timestamp).toLocaleTimeString();
|
|
23551
|
+
lines.push(` Logged at: ${timestamp}`);
|
|
23552
|
+
return lines.join("\n");
|
|
23553
|
+
}).join("\n\n");
|
|
23554
|
+
}
|
|
23555
|
+
/**
|
|
23556
|
+
* Create the log_decision tool.
|
|
23557
|
+
*
|
|
23558
|
+
* Allows the AI to record significant decisions with rationale during a session.
|
|
23559
|
+
* Decisions are persisted in the session's workflow state for audit trail
|
|
23560
|
+
* and cross-session continuity.
|
|
23561
|
+
*/
|
|
23562
|
+
function createDecisionLogTool(store) {
|
|
23563
|
+
return {
|
|
23564
|
+
toolFn: async (args) => {
|
|
23565
|
+
const params = validateParams(args);
|
|
23566
|
+
const decision = {
|
|
23567
|
+
id: v4(),
|
|
23568
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
23569
|
+
summary: params.summary,
|
|
23570
|
+
rationale: params.rationale,
|
|
23571
|
+
alternatives: params.alternatives,
|
|
23572
|
+
context: params.context
|
|
23573
|
+
};
|
|
23574
|
+
store.decisions.push(decision);
|
|
23575
|
+
if (store.onUpdate) store.onUpdate(store.decisions);
|
|
23576
|
+
return `Decision logged (#${store.decisions.length}): ${decision.summary}`;
|
|
23577
|
+
},
|
|
23578
|
+
toolSchema: {
|
|
23579
|
+
name: "log_decision",
|
|
23580
|
+
description: `Record a significant decision with its rationale for audit trail and session continuity.
|
|
23581
|
+
|
|
23582
|
+
**When to use:**
|
|
23583
|
+
- Architecture or design choices (e.g., "chose Zustand over Redux because...")
|
|
23584
|
+
- Scope narrowing or direction changes in research
|
|
23585
|
+
- Trade-off decisions between viable alternatives
|
|
23586
|
+
- Interpretation of ambiguous requirements
|
|
23587
|
+
|
|
23588
|
+
**When NOT to use:**
|
|
23589
|
+
- Routine operations (reading files, running tests)
|
|
23590
|
+
- Trivial choices that wouldn't matter to someone resuming this work
|
|
23591
|
+
- Implementation details that are obvious from the code
|
|
23592
|
+
|
|
23593
|
+
Log decisions that would matter if someone needed to understand WHY you did something.`,
|
|
23594
|
+
parameters: {
|
|
23595
|
+
type: "object",
|
|
23596
|
+
properties: {
|
|
23597
|
+
summary: {
|
|
23598
|
+
type: "string",
|
|
23599
|
+
description: "What was decided — a clear, concise statement"
|
|
23600
|
+
},
|
|
23601
|
+
rationale: {
|
|
23602
|
+
type: "string",
|
|
23603
|
+
description: "Why this decision was made — the reasoning behind it"
|
|
23604
|
+
},
|
|
23605
|
+
alternatives: {
|
|
23606
|
+
type: "array",
|
|
23607
|
+
items: { type: "string" },
|
|
23608
|
+
description: "What alternatives were considered (optional)"
|
|
23609
|
+
},
|
|
23610
|
+
context: {
|
|
23611
|
+
type: "string",
|
|
23612
|
+
description: "What triggered this decision — the situation or constraint (optional)"
|
|
23613
|
+
}
|
|
23614
|
+
},
|
|
23615
|
+
required: ["summary", "rationale"]
|
|
23616
|
+
}
|
|
23617
|
+
}
|
|
23618
|
+
};
|
|
23619
|
+
}
|
|
23620
|
+
/**
|
|
23621
|
+
* Create a new empty DecisionStore
|
|
23622
|
+
*/
|
|
23623
|
+
function createDecisionStore(onUpdate) {
|
|
23624
|
+
return {
|
|
23625
|
+
decisions: [],
|
|
23626
|
+
onUpdate
|
|
23627
|
+
};
|
|
23628
|
+
}
|
|
23629
|
+
//#endregion
|
|
23630
|
+
//#region src/tools/blockerTool.ts
|
|
23631
|
+
/**
|
|
23632
|
+
* Format blockers for display output
|
|
23633
|
+
*/
|
|
23634
|
+
function formatBlockersOutput(blockers) {
|
|
23635
|
+
if (blockers.length === 0) return "No blockers tracked in this session.";
|
|
23636
|
+
const open = blockers.filter((b) => b.status === "open");
|
|
23637
|
+
const resolved = blockers.filter((b) => b.status === "resolved");
|
|
23638
|
+
const lines = [];
|
|
23639
|
+
if (open.length > 0) {
|
|
23640
|
+
lines.push(`**Open blockers (${open.length}):**`);
|
|
23641
|
+
for (const blocker of open) lines.push(` - [${blocker.id.slice(0, 8)}] ${blocker.description}`);
|
|
23642
|
+
}
|
|
23643
|
+
if (resolved.length > 0) {
|
|
23644
|
+
if (open.length > 0) lines.push("");
|
|
23645
|
+
lines.push(`**Resolved blockers (${resolved.length}):**`);
|
|
23646
|
+
for (const blocker of resolved) {
|
|
23647
|
+
lines.push(` - [${blocker.id.slice(0, 8)}] ${blocker.description}`);
|
|
23648
|
+
lines.push(` Resolution: ${blocker.resolution ?? "(no resolution recorded)"}`);
|
|
23649
|
+
}
|
|
23650
|
+
}
|
|
23651
|
+
return lines.join("\n");
|
|
23652
|
+
}
|
|
23653
|
+
/**
|
|
23654
|
+
* Create the track_blocker and resolve_blocker tools.
|
|
23655
|
+
*
|
|
23656
|
+
* Allows the AI to track what's blocking progress and record resolutions.
|
|
23657
|
+
* Blockers are persisted in the session's workflow state for audit trail
|
|
23658
|
+
* and cross-session continuity.
|
|
23659
|
+
*/
|
|
23660
|
+
function createBlockerTools(store) {
|
|
23661
|
+
return [{
|
|
23662
|
+
toolFn: async (args) => {
|
|
23663
|
+
const params = args;
|
|
23664
|
+
if (typeof params.description !== "string" || params.description.trim() === "") throw new Error("track_blocker: description must be a non-empty string");
|
|
23665
|
+
const blocker = {
|
|
23666
|
+
id: v4(),
|
|
23667
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
23668
|
+
description: params.description.trim(),
|
|
23669
|
+
status: "open"
|
|
23670
|
+
};
|
|
23671
|
+
store.blockers.push(blocker);
|
|
23672
|
+
if (store.onUpdate) store.onUpdate(store.blockers);
|
|
23673
|
+
const openCount = store.blockers.filter((b) => b.status === "open").length;
|
|
23674
|
+
return `Blocker tracked [${blocker.id.slice(0, 8)}]: ${blocker.description}\n(${openCount} open blocker${openCount === 1 ? "" : "s"})`;
|
|
23675
|
+
},
|
|
23676
|
+
toolSchema: {
|
|
23677
|
+
name: "track_blocker",
|
|
23678
|
+
description: `Track something that is blocking progress.
|
|
23679
|
+
|
|
23680
|
+
**When to use:**
|
|
23681
|
+
- Missing information or unclear requirements
|
|
23682
|
+
- External dependencies (waiting on API access, credentials, data)
|
|
23683
|
+
- Technical constraints discovered during work
|
|
23684
|
+
- Ambiguous requirements that need human clarification
|
|
23685
|
+
|
|
23686
|
+
**When NOT to use:**
|
|
23687
|
+
- Normal challenges that are part of the work
|
|
23688
|
+
- Things you can resolve immediately`,
|
|
23689
|
+
parameters: {
|
|
23690
|
+
type: "object",
|
|
23691
|
+
properties: { description: {
|
|
23692
|
+
type: "string",
|
|
23693
|
+
description: "What is blocking progress — be specific about what is needed to unblock"
|
|
23694
|
+
} },
|
|
23695
|
+
required: ["description"]
|
|
23696
|
+
}
|
|
23697
|
+
}
|
|
23698
|
+
}, {
|
|
23699
|
+
toolFn: async (args) => {
|
|
23700
|
+
const params = args;
|
|
23701
|
+
if (typeof params.blocker_id !== "string" || params.blocker_id.trim() === "") throw new Error("resolve_blocker: blocker_id must be a non-empty string");
|
|
23702
|
+
if (typeof params.resolution !== "string" || params.resolution.trim() === "") throw new Error("resolve_blocker: resolution must be a non-empty string");
|
|
23703
|
+
const blockerId = params.blocker_id.trim();
|
|
23704
|
+
const blocker = store.blockers.find((b) => b.id === blockerId || b.id.startsWith(blockerId));
|
|
23705
|
+
if (!blocker) {
|
|
23706
|
+
const openBlockers = store.blockers.filter((b) => b.status === "open");
|
|
23707
|
+
if (openBlockers.length === 0) return "No open blockers to resolve.";
|
|
23708
|
+
return `Blocker not found. Open blockers:\n${openBlockers.map((b) => ` [${b.id.slice(0, 8)}] ${b.description}`).join("\n")}`;
|
|
23709
|
+
}
|
|
23710
|
+
if (blocker.status === "resolved") return `Blocker [${blocker.id.slice(0, 8)}] is already resolved.`;
|
|
23711
|
+
blocker.status = "resolved";
|
|
23712
|
+
blocker.resolvedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
23713
|
+
blocker.resolution = params.resolution.trim();
|
|
23714
|
+
if (store.onUpdate) store.onUpdate(store.blockers);
|
|
23715
|
+
const openCount = store.blockers.filter((b) => b.status === "open").length;
|
|
23716
|
+
return `Blocker resolved [${blocker.id.slice(0, 8)}]: ${blocker.resolution}\n(${openCount} open blocker${openCount === 1 ? "" : "s"} remaining)`;
|
|
23717
|
+
},
|
|
23718
|
+
toolSchema: {
|
|
23719
|
+
name: "resolve_blocker",
|
|
23720
|
+
description: `Mark a blocker as resolved with a description of how it was resolved.
|
|
23721
|
+
|
|
23722
|
+
Use the blocker ID (or its first 8 characters) from the track_blocker output.`,
|
|
23723
|
+
parameters: {
|
|
23724
|
+
type: "object",
|
|
23725
|
+
properties: {
|
|
23726
|
+
blocker_id: {
|
|
23727
|
+
type: "string",
|
|
23728
|
+
description: "The ID of the blocker to resolve (full ID or first 8 characters)"
|
|
23729
|
+
},
|
|
23730
|
+
resolution: {
|
|
23731
|
+
type: "string",
|
|
23732
|
+
description: "How the blocker was resolved"
|
|
23733
|
+
}
|
|
23734
|
+
},
|
|
23735
|
+
required: ["blocker_id", "resolution"]
|
|
23736
|
+
}
|
|
23737
|
+
}
|
|
23738
|
+
}];
|
|
23739
|
+
}
|
|
23740
|
+
/**
|
|
23741
|
+
* Create a new empty BlockerStore
|
|
23742
|
+
*/
|
|
23743
|
+
function createBlockerStore(onUpdate) {
|
|
23744
|
+
return {
|
|
23745
|
+
blockers: [],
|
|
23746
|
+
onUpdate
|
|
23747
|
+
};
|
|
23748
|
+
}
|
|
23749
|
+
//#endregion
|
|
23750
|
+
export { processFileReferences as $, getApiUrl as A, registerFeatureModuleTools as B, WebSocketLlmBackend as C, formatStep as D, substituteArguments as E, DEFAULT_AGENT_MODEL as F, isReadOnlyTool as G, OllamaBackend as H, DEFAULT_MAX_ITERATIONS as I, CheckpointStore as J, ReActAgent as K, DEFAULT_RETRY_CONFIG as L, PermissionManager as M, generateCliTools as N, extractCompactInstructions as O, ALWAYS_DENIED_FOR_AGENTS as P, hasFileReferences as Q, DEFAULT_THOROUGHNESS as R, FallbackLlmBackend as S, McpManager as T, buildCoreSystemPrompt as U, setWebSocketToolExecutor as V, buildSkillsPromptSection as W, SessionStore as X, CommandHistoryStore as Y, OAuthClient as Z, createSkillTool as _, createDecisionStore as a, WebSocketToolExecutor as b, createFindDefinitionTool as c, createCoordinateTaskTool as d, searchCommands as et, createBackgroundAgentTools as f, SubagentOrchestrator as g, AgentStore as h, createDecisionLogTool as i, warmFileCache as it, getEnvironmentName as j, loadContextFiles as k, createTodoStore as l, createAgentDelegateTool as m, createBlockerTools as n, formatFileSize$1 as nt, formatDecisionsOutput as o, BackgroundAgentManager as p, CustomCommandStore as q, formatBlockersOutput as r, searchFiles as rt, createGetFileStructureTool as s, createBlockerStore as t, mergeCommands as tt, createWriteTodosTool as u, parseAgentConfig as v, ServerLlmBackend as w, WebSocketConnectionManager as x, ApiClient as y, clearFeatureModuleTools as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bike4mind/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -118,11 +118,11 @@
|
|
|
118
118
|
"tsx": "^4.21.0",
|
|
119
119
|
"typescript": "^5.9.3",
|
|
120
120
|
"vitest": "^4.1.2",
|
|
121
|
-
"@bike4mind/agents": "0.5.
|
|
122
|
-
"@bike4mind/common": "2.
|
|
123
|
-
"@bike4mind/mcp": "1.
|
|
124
|
-
"@bike4mind/services": "2.
|
|
125
|
-
"@bike4mind/utils": "2.18.
|
|
121
|
+
"@bike4mind/agents": "0.5.3",
|
|
122
|
+
"@bike4mind/common": "2.89.0",
|
|
123
|
+
"@bike4mind/mcp": "1.36.0",
|
|
124
|
+
"@bike4mind/services": "2.77.0",
|
|
125
|
+
"@bike4mind/utils": "2.18.10"
|
|
126
126
|
},
|
|
127
127
|
"optionalDependencies": {
|
|
128
128
|
"@vscode/ripgrep": "^1.17.1"
|