@bike4mind/cli 0.2.3-feat-questmaster-gpt5-function-calling.17057 → 0.2.3-feat-cli-clear-command.17058

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.
@@ -7,7 +7,7 @@ import {
7
7
  getSettingsMap,
8
8
  getSettingsValue,
9
9
  secureParameters
10
- } from "./chunk-LYNNVNEC.js";
10
+ } from "./chunk-NZADYDFG.js";
11
11
  import {
12
12
  KnowledgeType,
13
13
  SupportedFabFileMimeTypes
@@ -6,7 +6,7 @@ import {
6
6
  getSettingsByNames,
7
7
  obfuscateApiKey,
8
8
  secureParameters
9
- } from "./chunk-LYNNVNEC.js";
9
+ } from "./chunk-NZADYDFG.js";
10
10
  import {
11
11
  ApiKeyType,
12
12
  MementoTier,
@@ -4112,12 +4112,6 @@ var OpenAIBackend = class {
4112
4112
  }
4113
4113
  if (options.tools?.length) {
4114
4114
  parameters.tools = this.formatTools(options.tools);
4115
- if (options.tool_choice) {
4116
- parameters.tool_choice = options.tool_choice;
4117
- }
4118
- if (options.parallel_tool_calls !== void 0) {
4119
- parameters.parallel_tool_calls = options.parallel_tool_calls;
4120
- }
4121
4115
  }
4122
4116
  const response = await this._api.chat.completions.create(parameters, {
4123
4117
  signal: options.abortSignal
@@ -7984,200 +7978,9 @@ function extractQuestMasterData(reply, options = {}) {
7984
7978
  return questMasterData;
7985
7979
  }
7986
7980
 
7987
- // ../../b4m-core/packages/utils/dist/src/questMasterToolSchema.js
7988
- var MAX_GOAL_LENGTH = 500;
7989
- var MAX_TITLE_LENGTH = 200;
7990
- var MAX_DESCRIPTION_LENGTH = 2e3;
7991
- var MAX_TAG_LENGTH = 50;
7992
- var MAX_QUESTS = 20;
7993
- var MAX_SUBQUESTS_PER_QUEST = 20;
7994
- var MAX_TAGS = 10;
7995
- var GPT5_MODELS_WITH_TOOL_SUPPORT = [
7996
- ChatModels.GPT5,
7997
- ChatModels.GPT5_MINI,
7998
- ChatModels.GPT5_NANO,
7999
- ChatModels.GPT5_1,
8000
- ChatModels.GPT5_2
8001
- ];
8002
- function isGPT5ModelWithToolSupport(model) {
8003
- return GPT5_MODELS_WITH_TOOL_SUPPORT.includes(model);
8004
- }
8005
- var createQuestPlanToolSchema = {
8006
- name: "create_quest_plan",
8007
- description: `Break down a user request into a structured quest plan with actionable tasks.
8008
-
8009
- GUIDELINES:
8010
- - Analyze the user's request and create 3-7 main quests
8011
- - Each quest must have 2-5 specific, actionable subquests
8012
- - Quest titles should be clear and action-oriented (e.g., "Set up database schema" not "Step 1")
8013
- - Provide detailed descriptions for each quest
8014
- - Assess complexity accurately: Easy (< 1 hour), Medium (1-4 hours), Hard (> 4 hours)
8015
- - Generate 2-5 relevant tags categorizing the work (e.g., "web-development", "database", "api")
8016
-
8017
- ALWAYS call this function to respond. Do NOT respond with plain text.`,
8018
- parameters: {
8019
- type: "object",
8020
- properties: {
8021
- goal: {
8022
- type: "string",
8023
- description: "The overall objective the user wants to achieve"
8024
- },
8025
- tags: {
8026
- type: "array",
8027
- items: { type: "string" },
8028
- description: 'Categories for this quest (e.g., "web-development", "api", "database")'
8029
- },
8030
- quests: {
8031
- type: "array",
8032
- description: "The main quests (3-7) that break down the goal",
8033
- items: {
8034
- type: "object",
8035
- properties: {
8036
- id: {
8037
- type: "string",
8038
- description: 'Unique identifier (e.g., "quest-1", "setup-database")'
8039
- },
8040
- title: {
8041
- type: "string",
8042
- description: 'Clear, action-oriented title (e.g., "Configure authentication middleware")'
8043
- },
8044
- description: {
8045
- type: "string",
8046
- description: "Detailed explanation of what needs to be done and why"
8047
- },
8048
- complexity: {
8049
- type: "string",
8050
- enum: ["Easy", "Medium", "Hard"],
8051
- description: "Difficulty assessment based on effort required"
8052
- },
8053
- subQuests: {
8054
- type: "array",
8055
- description: "Concrete subtasks (2-5) within this quest",
8056
- items: {
8057
- type: "object",
8058
- properties: {
8059
- id: {
8060
- type: "string",
8061
- description: "Unique identifier for the subquest"
8062
- },
8063
- title: {
8064
- type: "string",
8065
- description: "Specific, actionable subtask title"
8066
- }
8067
- },
8068
- required: ["id", "title"]
8069
- }
8070
- }
8071
- },
8072
- required: ["id", "title", "description", "complexity", "subQuests"]
8073
- }
8074
- }
8075
- },
8076
- required: ["goal", "quests"]
8077
- }
8078
- };
8079
- function parseQuestPlanFunctionCall(args) {
8080
- if (!args || typeof args !== "string" || args.trim() === "") {
8081
- throw new Error("Function call arguments are empty or invalid");
8082
- }
8083
- let parsed;
8084
- try {
8085
- parsed = JSON.parse(args);
8086
- } catch (e) {
8087
- throw new Error(`Failed to parse function call arguments as JSON: ${e}`);
8088
- }
8089
- if (!parsed || typeof parsed !== "object") {
8090
- throw new Error("Function call arguments must be an object");
8091
- }
8092
- const result = parsed;
8093
- if (!result.goal || typeof result.goal !== "string" || result.goal.trim() === "") {
8094
- throw new Error("Function call missing required field: goal (must be non-empty string)");
8095
- }
8096
- if (result.goal.length > MAX_GOAL_LENGTH) {
8097
- throw new Error(`Goal exceeds maximum length of ${MAX_GOAL_LENGTH} characters`);
8098
- }
8099
- if (!Array.isArray(result.quests)) {
8100
- throw new Error("Function call missing required field: quests (must be an array)");
8101
- }
8102
- if (result.quests.length === 0) {
8103
- throw new Error("Function call returned empty quests array");
8104
- }
8105
- if (result.quests.length > MAX_QUESTS) {
8106
- throw new Error(`Too many quests: ${result.quests.length} (max ${MAX_QUESTS})`);
8107
- }
8108
- for (let i = 0; i < result.quests.length; i++) {
8109
- const quest = result.quests[i];
8110
- if (!quest || typeof quest !== "object") {
8111
- throw new Error(`Quest ${i} is not a valid object`);
8112
- }
8113
- const questObj = quest;
8114
- if (!questObj.id || typeof questObj.id !== "string" || questObj.id.trim() === "") {
8115
- throw new Error(`Quest ${i} missing required field: id (must be non-empty string)`);
8116
- }
8117
- if (!questObj.title || typeof questObj.title !== "string" || questObj.title.trim() === "") {
8118
- throw new Error(`Quest ${i} missing required field: title (must be non-empty string)`);
8119
- }
8120
- if (questObj.title.length > MAX_TITLE_LENGTH) {
8121
- throw new Error(`Quest ${i} title exceeds maximum length of ${MAX_TITLE_LENGTH} characters`);
8122
- }
8123
- if (!questObj.description || typeof questObj.description !== "string" || questObj.description.trim() === "") {
8124
- throw new Error(`Quest ${i} missing required field: description (must be non-empty string)`);
8125
- }
8126
- if (questObj.description.length > MAX_DESCRIPTION_LENGTH) {
8127
- throw new Error(`Quest ${i} description exceeds maximum length of ${MAX_DESCRIPTION_LENGTH} characters`);
8128
- }
8129
- if (!questObj.complexity || !["Easy", "Medium", "Hard"].includes(questObj.complexity)) {
8130
- throw new Error(`Quest ${i} has invalid complexity: ${questObj.complexity} (must be Easy, Medium, or Hard)`);
8131
- }
8132
- if (!Array.isArray(questObj.subQuests)) {
8133
- throw new Error(`Quest "${questObj.id}" missing required field: subQuests (must be an array)`);
8134
- }
8135
- if (questObj.subQuests.length === 0) {
8136
- throw new Error(`Quest "${questObj.id}" has no subQuests (minimum 2 required)`);
8137
- }
8138
- if (questObj.subQuests.length > MAX_SUBQUESTS_PER_QUEST) {
8139
- throw new Error(`Quest "${questObj.id}" has too many subQuests: ${questObj.subQuests.length} (max ${MAX_SUBQUESTS_PER_QUEST})`);
8140
- }
8141
- for (let j = 0; j < questObj.subQuests.length; j++) {
8142
- const subQuest = questObj.subQuests[j];
8143
- if (!subQuest || typeof subQuest !== "object") {
8144
- throw new Error(`Quest "${questObj.id}" subQuest ${j} is not a valid object`);
8145
- }
8146
- const subQuestObj = subQuest;
8147
- if (!subQuestObj.id || typeof subQuestObj.id !== "string" || subQuestObj.id.trim() === "") {
8148
- throw new Error(`Quest "${questObj.id}" subQuest ${j} missing required field: id (must be non-empty string)`);
8149
- }
8150
- if (!subQuestObj.title || typeof subQuestObj.title !== "string" || subQuestObj.title.trim() === "") {
8151
- throw new Error(`Quest "${questObj.id}" subQuest ${j} missing required field: title (must be non-empty string)`);
8152
- }
8153
- if (subQuestObj.title.length > MAX_TITLE_LENGTH) {
8154
- throw new Error(`Quest "${questObj.id}" subQuest ${j} title exceeds maximum length of ${MAX_TITLE_LENGTH} characters`);
8155
- }
8156
- }
8157
- }
8158
- if (result.tags !== void 0) {
8159
- if (!Array.isArray(result.tags)) {
8160
- throw new Error("Function call field tags must be an array if provided");
8161
- }
8162
- if (result.tags.length > MAX_TAGS) {
8163
- throw new Error(`Too many tags: ${result.tags.length} (max ${MAX_TAGS})`);
8164
- }
8165
- for (let i = 0; i < result.tags.length; i++) {
8166
- if (typeof result.tags[i] !== "string") {
8167
- throw new Error(`Function call field tags[${i}] must be a string`);
8168
- }
8169
- if (result.tags[i].length > MAX_TAG_LENGTH) {
8170
- throw new Error(`Tag ${i} exceeds maximum length of ${MAX_TAG_LENGTH} characters`);
8171
- }
8172
- }
8173
- }
8174
- return result;
8175
- }
8176
-
8177
7981
  // ../../b4m-core/packages/utils/dist/src/questMaster.js
8178
- var sanitizeId = (id, fallback) => {
8179
- const sanitized = id.replace(/\s+/g, "-").replace(/[^a-zA-Z0-9_.-]/g, "").replace(/-+/g, "-").replace(/^-|-$/g, "");
8180
- return sanitized || fallback;
7982
+ var sanitizeId = (id) => {
7983
+ return id.replace(/\s+/g, "-").replace(/[^a-zA-Z0-9_.-]/g, "").replace(/-+/g, "-").replace(/^-|-$/g, "");
8181
7984
  };
8182
7985
  var QuestMaster = class {
8183
7986
  llm;
@@ -8205,12 +8008,10 @@ var QuestMaster = class {
8205
8008
  }
8206
8009
  return "Easy";
8207
8010
  }
8208
- async processQuestPlan(input) {
8011
+ async processQuestPlan(questPlanText) {
8209
8012
  try {
8210
- if (!this.quest) {
8211
- throw new Error("No quest context available");
8212
- }
8213
8013
  await this.onStatusUpdate(this.quest, "Processing quest plan...");
8014
+ this.logger.log("Processing quest plan:", questPlanText);
8214
8015
  const defaultResponse = {
8215
8016
  type: "narrative",
8216
8017
  meta: {
@@ -8227,158 +8028,135 @@ var QuestMaster = class {
8227
8028
  }
8228
8029
  ]
8229
8030
  };
8031
+ if (!questPlanText || typeof questPlanText !== "string") {
8032
+ this.logger.warn("Invalid questPlanText received:", questPlanText);
8033
+ if (this.quest) {
8034
+ this.quest.questMasterReply = JSON.stringify(defaultResponse);
8035
+ await this.db.quests.update({
8036
+ id: this.quest.id,
8037
+ questMasterReply: this.quest.questMasterReply,
8038
+ reply: null,
8039
+ replies: [],
8040
+ status: "done",
8041
+ type: "message"
8042
+ });
8043
+ }
8044
+ return;
8045
+ }
8046
+ if (!this.quest) {
8047
+ throw new Error("No quest context available");
8048
+ }
8049
+ const extracted = extractQuestMasterData(questPlanText, { logger: this.logger });
8050
+ const metaStartTag = "<!--QuestMasterMeta";
8051
+ const metaEndTag = "-->";
8052
+ const metaStartIndex = questPlanText.indexOf(metaStartTag);
8053
+ let goal = "Quest Plan";
8054
+ let tags = [];
8230
8055
  let questResponse;
8231
- if (input !== null && typeof input === "object") {
8232
- this.logger.log("Processing quest plan from function calling result");
8056
+ if (metaStartIndex !== -1) {
8057
+ const metaEndIndex = questPlanText.indexOf(metaEndTag, metaStartIndex);
8058
+ if (metaEndIndex !== -1) {
8059
+ const metaContent = questPlanText.slice(metaStartIndex + metaStartTag.length, metaEndIndex).trim();
8060
+ try {
8061
+ const jsonStartIndex = metaContent.indexOf("{");
8062
+ if (jsonStartIndex !== -1) {
8063
+ const metaData = JSON.parse(metaContent.slice(jsonStartIndex));
8064
+ goal = metaData.goal || goal;
8065
+ tags = Array.isArray(metaData.tags) ? metaData.tags : [];
8066
+ }
8067
+ } catch (err) {
8068
+ this.logger.error("Error parsing meta data:", err);
8069
+ }
8070
+ }
8071
+ }
8072
+ if (extracted.length > 0) {
8073
+ this.logger.log("Successfully extracted QuestMaster data:", extracted);
8074
+ await this.onStatusUpdate(this.quest, "Extracted QuestMaster data");
8075
+ const validQuests = extracted.filter((quest) => quest !== null && typeof quest === "object" && quest.id && quest.title && quest.title !== "Step 1" && // Explicitly filter out generic Step 1
8076
+ quest.description && quest.description !== "No description available");
8077
+ if (validQuests.length === 0) {
8078
+ throw new Error("No valid quests found after filtering");
8079
+ }
8233
8080
  questResponse = {
8234
8081
  type: "quest_plan",
8235
8082
  meta: {
8236
- goal: input.goal,
8237
- totalSteps: input.quests.length,
8238
- tags: input.tags
8083
+ goal,
8084
+ totalSteps: validQuests.length,
8085
+ tags
8239
8086
  },
8240
- quests: input.quests.map((quest) => ({
8087
+ quests: validQuests.map((quest) => ({
8241
8088
  id: quest.id,
8089
+ // No fallback - we filtered for valid IDs
8242
8090
  title: quest.title,
8091
+ // No fallback - we filtered for valid titles
8243
8092
  description: quest.description,
8244
- complexity: quest.complexity,
8093
+ // No fallback - we filtered for valid descriptions
8094
+ complexity: quest.complexity || "Medium",
8245
8095
  status: "not_started",
8246
- subQuests: quest.subQuests.map((sub) => ({
8096
+ subQuests: Array.isArray(quest.subQuests) ? quest.subQuests.filter((sub) => sub && sub.id && sub.title && !sub.title.startsWith("Subtask")).map((sub) => ({
8247
8097
  id: sub.id,
8248
8098
  title: sub.title,
8249
8099
  status: "not_started"
8250
- }))
8100
+ })) : []
8251
8101
  }))
8252
8102
  };
8253
- } else {
8254
- const questPlanText = input;
8255
- this.logger.log("Processing quest plan:", questPlanText);
8256
- if (!questPlanText || typeof questPlanText !== "string") {
8257
- this.logger.warn("Invalid questPlanText received:", questPlanText);
8258
- if (this.quest) {
8259
- this.quest.questMasterReply = JSON.stringify(defaultResponse);
8260
- await this.db.quests.update({
8261
- id: this.quest.id,
8262
- questMasterReply: this.quest.questMasterReply,
8263
- reply: null,
8264
- replies: [],
8265
- status: "done",
8266
- type: "message"
8267
- });
8268
- }
8269
- return;
8103
+ if (questResponse.quests.some((quest) => quest.subQuests.length === 0)) {
8104
+ throw new Error("Some quests have no valid subquests after filtering");
8270
8105
  }
8271
- const extracted = extractQuestMasterData(questPlanText, { logger: this.logger });
8272
- const metaStartTag = "<!--QuestMasterMeta";
8273
- const metaEndTag = "-->";
8274
- const metaStartIndex = questPlanText.indexOf(metaStartTag);
8275
- let goal = "Quest Plan";
8276
- let tags = [];
8277
- if (metaStartIndex !== -1) {
8278
- const metaEndIndex = questPlanText.indexOf(metaEndTag, metaStartIndex);
8279
- if (metaEndIndex !== -1) {
8280
- const metaContent = questPlanText.slice(metaStartIndex + metaStartTag.length, metaEndIndex).trim();
8281
- try {
8282
- const jsonStartIndex = metaContent.indexOf("{");
8283
- if (jsonStartIndex !== -1) {
8284
- const metaData = JSON.parse(metaContent.slice(jsonStartIndex));
8285
- goal = metaData.goal || goal;
8286
- tags = Array.isArray(metaData.tags) ? metaData.tags : [];
8287
- }
8288
- } catch (err) {
8289
- this.logger.error("Error parsing meta data:", err);
8106
+ } else {
8107
+ try {
8108
+ const questPlan = JSON.parse(questPlanText);
8109
+ if (questPlan && questPlan.questChain && Array.isArray(questPlan.questChain)) {
8110
+ const validQuestChain = questPlan.questChain.filter((item) => item && item.quest && item.quest !== "Step 1" && item.details && item.details !== "No description available");
8111
+ if (validQuestChain.length === 0) {
8112
+ throw new Error("No valid quests found in quest chain");
8290
8113
  }
8291
- }
8292
- }
8293
- if (extracted.length > 0) {
8294
- this.logger.log("Successfully extracted QuestMaster data:", extracted);
8295
- await this.onStatusUpdate(this.quest, "Extracted QuestMaster data");
8296
- const validQuests = extracted.filter((quest) => quest !== null && typeof quest === "object" && quest.id && quest.title && quest.title !== "Step 1" && // Explicitly filter out generic Step 1
8297
- quest.description && quest.description !== "No description available");
8298
- if (validQuests.length === 0) {
8299
- throw new Error("No valid quests found after filtering");
8300
- }
8301
- questResponse = {
8302
- type: "quest_plan",
8303
- meta: {
8304
- goal,
8305
- totalSteps: validQuests.length,
8306
- tags
8307
- },
8308
- quests: validQuests.map((quest) => ({
8309
- id: quest.id,
8310
- // No fallback - we filtered for valid IDs
8311
- title: quest.title,
8312
- // No fallback - we filtered for valid titles
8313
- description: quest.description,
8314
- // No fallback - we filtered for valid descriptions
8315
- complexity: quest.complexity || "Medium",
8316
- status: "not_started",
8317
- subQuests: Array.isArray(quest.subQuests) ? quest.subQuests.filter((sub) => sub && sub.id && sub.title && !sub.title.startsWith("Subtask")).map((sub) => ({
8318
- id: sub.id,
8319
- title: sub.title,
8320
- status: "not_started"
8321
- })) : []
8322
- }))
8323
- };
8324
- if (questResponse.quests.some((quest) => quest.subQuests.length === 0)) {
8325
- throw new Error("Some quests have no valid subquests after filtering");
8326
- }
8327
- } else {
8328
- try {
8329
- const questPlan = JSON.parse(questPlanText);
8330
- if (questPlan && questPlan.questChain && Array.isArray(questPlan.questChain)) {
8331
- const validQuestChain = questPlan.questChain.filter((item) => item && item.quest && item.quest !== "Step 1" && item.details && item.details !== "No description available");
8332
- if (validQuestChain.length === 0) {
8333
- throw new Error("No valid quests found in quest chain");
8334
- }
8335
- questResponse = {
8336
- type: "quest_plan",
8337
- meta: {
8338
- goal: questPlan.abstractObjective || "Process Request",
8339
- totalSteps: validQuestChain.length
8340
- },
8341
- quests: validQuestChain.map((item, index) => ({
8342
- id: `quest-${index + 1}`,
8343
- title: item.quest,
8344
- description: item.details,
8345
- complexity: this.determineComplexity(item.details),
8346
- status: "not_started",
8347
- subQuests: []
8348
- // This will trigger a retry since we require subquests
8349
- }))
8350
- };
8351
- } else {
8352
- if (!questPlanText.trim() || questPlanText.trim() === "Step 1") {
8353
- throw new Error("Empty or invalid response received");
8354
- }
8355
- questResponse = {
8356
- type: "narrative",
8357
- meta: {
8358
- goal: "Direct Response",
8359
- totalSteps: 1
8360
- },
8361
- quests: [
8362
- {
8363
- id: "narrative-1",
8364
- title: "Process Response",
8365
- description: questPlanText.trim(),
8366
- complexity: "Medium",
8367
- subQuests: [
8368
- {
8369
- id: "narrative-1-1",
8370
- title: "Review Response",
8371
- status: "not_started"
8372
- }
8373
- ]
8374
- }
8375
- ]
8376
- };
8114
+ questResponse = {
8115
+ type: "quest_plan",
8116
+ meta: {
8117
+ goal: questPlan.abstractObjective || "Process Request",
8118
+ totalSteps: validQuestChain.length
8119
+ },
8120
+ quests: validQuestChain.map((item, index) => ({
8121
+ id: `quest-${index + 1}`,
8122
+ title: item.quest,
8123
+ description: item.details,
8124
+ complexity: this.determineComplexity(item.details),
8125
+ status: "Not Started",
8126
+ subQuests: []
8127
+ // This will trigger a retry since we require subquests
8128
+ }))
8129
+ };
8130
+ } else {
8131
+ if (!questPlanText.trim() || questPlanText.trim() === "Step 1") {
8132
+ throw new Error("Empty or invalid response received");
8377
8133
  }
8378
- } catch (parseError) {
8379
- this.logger.error("Error parsing quest plan JSON:", parseError);
8380
- questResponse = defaultResponse;
8134
+ questResponse = {
8135
+ type: "narrative",
8136
+ meta: {
8137
+ goal: "Direct Response",
8138
+ totalSteps: 1
8139
+ },
8140
+ quests: [
8141
+ {
8142
+ id: "narrative-1",
8143
+ title: "Process Response",
8144
+ description: questPlanText.trim(),
8145
+ complexity: "Medium",
8146
+ subQuests: [
8147
+ {
8148
+ id: "narrative-1-1",
8149
+ title: "Review Response",
8150
+ status: "not_started"
8151
+ }
8152
+ ]
8153
+ }
8154
+ ]
8155
+ };
8381
8156
  }
8157
+ } catch (parseError) {
8158
+ this.logger.error("Error parsing quest plan JSON:", parseError);
8159
+ questResponse = defaultResponse;
8382
8160
  }
8383
8161
  }
8384
8162
  if (!this.validateQuestResponse(questResponse)) {
@@ -8392,21 +8170,18 @@ var QuestMaster = class {
8392
8170
  goal: questResponse.meta.goal,
8393
8171
  userId: this.userId,
8394
8172
  tags: questResponse.meta.tags || [],
8395
- quests: questResponse.quests.map((quest, questIndex) => {
8396
- const questId = sanitizeId(quest.id, `quest-${questIndex + 1}`);
8397
- return {
8398
- id: questId,
8399
- title: quest.title,
8400
- description: quest.description,
8401
- complexity: quest.complexity,
8402
- subQuests: quest.subQuests.map((sub, subIndex) => ({
8403
- id: sanitizeId(sub.id, `${questId}-sub-${subIndex + 1}`),
8404
- title: sub.title,
8405
- status: sub.status
8406
- // questId intentionally omitted - will be set when task is started and linked to a chat message
8407
- }))
8408
- };
8409
- })
8173
+ quests: questResponse.quests.map((quest) => ({
8174
+ id: sanitizeId(quest.id),
8175
+ title: quest.title,
8176
+ description: quest.description,
8177
+ complexity: quest.complexity,
8178
+ subQuests: quest.subQuests.map((sub) => ({
8179
+ id: sanitizeId(sub.id),
8180
+ title: sub.title,
8181
+ status: sub.status
8182
+ // questId intentionally omitted - will be set when task is started and linked to a chat message
8183
+ }))
8184
+ }))
8410
8185
  });
8411
8186
  this.quest.questMasterPlanId = questMasterPlan.id;
8412
8187
  this.quest.reply = null;
@@ -8457,9 +8232,7 @@ var QuestMaster = class {
8457
8232
  }
8458
8233
  throw error;
8459
8234
  } finally {
8460
- if (this.quest) {
8461
- await this.onStatusUpdate(this.quest, null);
8462
- }
8235
+ await this.onStatusUpdate(this.quest, null);
8463
8236
  }
8464
8237
  }
8465
8238
  validateQuestResponse(response) {
@@ -8583,114 +8356,9 @@ var QuestMaster = class {
8583
8356
  }
8584
8357
  -->`;
8585
8358
  }
8586
- /**
8587
- * Create a quest plan using GPT-5's function calling feature.
8588
- * This method is used when the model is a GPT-5 variant that supports tools
8589
- * but doesn't reliably follow HTML comment formatting.
8590
- *
8591
- * @param model - The GPT-5 model to use
8592
- * @param prompt - The user's request to break down into quests
8593
- * @returns The parsed quest plan result
8594
- */
8595
- async createQuestPlanWithFunctionCalling(model, prompt, retryCount = 0) {
8596
- const MAX_RETRIES = 2;
8597
- const messages = [
8598
- {
8599
- role: "system",
8600
- content: `You are the QuestMaster, an AI agent that breaks down complex tasks into manageable quests.
8601
-
8602
- When given a user request, you MUST call the create_quest_plan function to structure your response.
8603
- Do NOT respond with plain text - ALWAYS use the function call.
8604
-
8605
- Guidelines:
8606
- - Break down complex tasks into 3-7 main quests
8607
- - Each quest needs 2-5 specific, actionable subquests
8608
- - Make titles clear and action-oriented (e.g., "Set up database schema" not "Step 1")
8609
- - Provide detailed descriptions explaining what needs to be done
8610
- - Assess complexity accurately: Easy (< 1 hour), Medium (1-4 hours), Hard (> 4 hours)
8611
- - Generate 2-5 relevant tags categorizing the work`
8612
- },
8613
- { role: "user", content: prompt }
8614
- ];
8615
- const toolDef = {
8616
- toolFn: async (params) => JSON.stringify(params),
8617
- // Not executed, just captured
8618
- toolSchema: createQuestPlanToolSchema
8619
- };
8620
- const options = {
8621
- temperature: retryCount > 0 ? 0.5 : 0.7,
8622
- // Lower temperature for structured JSON outputs; even lower on retries
8623
- n: 1,
8624
- stream: false,
8625
- tools: [toolDef],
8626
- executeTools: false,
8627
- // Don't execute, just capture the function call
8628
- tool_choice: { type: "function", function: { name: "create_quest_plan" } },
8629
- // Force function call
8630
- parallel_tool_calls: false
8631
- // Required for structured outputs
8632
- };
8633
- let functionResult = null;
8634
- let lastError = null;
8635
- try {
8636
- await this.llm.complete(model, messages, options, async (text, completionInfo) => {
8637
- if (completionInfo?.toolsUsed?.length) {
8638
- const toolCall = completionInfo.toolsUsed[0];
8639
- if (toolCall.name === "create_quest_plan" && toolCall.arguments) {
8640
- this.logger.log("GPT-5 function call received, parsing arguments...");
8641
- try {
8642
- functionResult = parseQuestPlanFunctionCall(toolCall.arguments);
8643
- } catch (parseError) {
8644
- lastError = parseError instanceof Error ? parseError : new Error(String(parseError));
8645
- this.logger.error("Failed to parse function call arguments:", parseError);
8646
- }
8647
- }
8648
- }
8649
- });
8650
- } catch (error) {
8651
- lastError = error instanceof Error ? error : new Error(String(error));
8652
- this.logger.error("Error in GPT-5 function calling:", lastError);
8653
- }
8654
- if (!functionResult) {
8655
- if (retryCount < MAX_RETRIES) {
8656
- this.logger.warn(`GPT-5 did not return function call, retrying (attempt ${retryCount + 1}/${MAX_RETRIES})...`);
8657
- return this.createQuestPlanWithFunctionCalling(model, prompt, retryCount + 1);
8658
- }
8659
- throw lastError || new Error("GPT-5 did not call create_quest_plan function after retries");
8660
- }
8661
- const result = functionResult;
8662
- const questsWithoutSubquests = result.quests.filter((q) => !q.subQuests || q.subQuests.length === 0);
8663
- if (questsWithoutSubquests.length > 0) {
8664
- if (retryCount < MAX_RETRIES) {
8665
- this.logger.warn(`Some quests missing subquests: ${questsWithoutSubquests.map((q) => q.id).join(", ")}, retrying...`);
8666
- return this.createQuestPlanWithFunctionCalling(model, prompt, retryCount + 1);
8667
- } else {
8668
- this.logger.warn(`Returning quest plan with ${questsWithoutSubquests.length} quests missing subquests after max retries (${MAX_RETRIES}): ${questsWithoutSubquests.map((q) => q.id).join(", ")}`);
8669
- }
8670
- }
8671
- this.logger.log("Successfully received GPT-5 function call result:", {
8672
- goal: result.goal,
8673
- questCount: result.quests.length,
8674
- tags: result.tags
8675
- });
8676
- return result;
8677
- }
8678
8359
  async createQuestPlan(model, prompt) {
8679
8360
  try {
8680
- if (!this.quest) {
8681
- throw new Error("No quest context available");
8682
- }
8683
8361
  await this.onStatusUpdate(this.quest, "Creating quest plan...");
8684
- if (isGPT5ModelWithToolSupport(model)) {
8685
- this.logger.log(`Using function calling approach for GPT-5 model: ${model}`);
8686
- try {
8687
- const result = await this.createQuestPlanWithFunctionCalling(model, prompt);
8688
- await this.processQuestPlan(result);
8689
- return;
8690
- } catch (functionCallError) {
8691
- this.logger.error("Function calling failed, falling back to HTML approach:", functionCallError);
8692
- }
8693
- }
8694
8362
  const messages = [
8695
8363
  {
8696
8364
  role: "system",
@@ -10784,9 +10452,6 @@ export {
10784
10452
  sendToConnection,
10785
10453
  ClientMessageSender,
10786
10454
  OpenaiModerationsService,
10787
- isGPT5ModelWithToolSupport,
10788
- createQuestPlanToolSchema,
10789
- parseQuestPlanFunctionCall,
10790
10455
  QuestMaster,
10791
10456
  OpenAIImageService,
10792
10457
  TestImageService,
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  BadRequestError,
4
4
  secureParameters
5
- } from "./chunk-LYNNVNEC.js";
5
+ } from "./chunk-NZADYDFG.js";
6
6
  import {
7
7
  GenericCreditDeductTransaction,
8
8
  ImageEditUsageTransaction,
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  createFabFile,
4
4
  createFabFileSchema
5
- } from "./chunk-6AJODFPC.js";
6
- import "./chunk-LYNNVNEC.js";
5
+ } from "./chunk-5N4PG5EH.js";
6
+ import "./chunk-NZADYDFG.js";
7
7
  import "./chunk-AMDXHL6S.js";
8
8
  import "./chunk-WR6YZRQV.js";
9
9
  import "./chunk-PDX44BCA.js";
package/dist/index.js CHANGED
@@ -4,9 +4,9 @@ import {
4
4
  getEffectiveApiKey,
5
5
  getOpenWeatherKey,
6
6
  getSerperKey
7
- } from "./chunk-WNBKV4FX.js";
8
- import "./chunk-LEG2UM5Q.js";
9
- import "./chunk-6AJODFPC.js";
7
+ } from "./chunk-GZTILMGE.js";
8
+ import "./chunk-Y4HMTEDH.js";
9
+ import "./chunk-5N4PG5EH.js";
10
10
  import {
11
11
  BFLImageService,
12
12
  BaseStorage,
@@ -15,7 +15,7 @@ import {
15
15
  OpenAIBackend,
16
16
  OpenAIImageService,
17
17
  XAIImageService
18
- } from "./chunk-LYNNVNEC.js";
18
+ } from "./chunk-NZADYDFG.js";
19
19
  import {
20
20
  Logger
21
21
  } from "./chunk-AMDXHL6S.js";
@@ -384,6 +384,11 @@ var COMMANDS = [
384
384
  {
385
385
  name: "usage",
386
386
  description: "Show credit usage and balance"
387
+ },
388
+ {
389
+ name: "clear",
390
+ description: "Start a new session",
391
+ aliases: ["new"]
387
392
  }
388
393
  ];
389
394
 
@@ -9178,7 +9183,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
9178
9183
  // package.json
9179
9184
  var package_default = {
9180
9185
  name: "@bike4mind/cli",
9181
- version: "0.2.3-feat-questmaster-gpt5-function-calling.17057+6a6bd60d2",
9186
+ version: "0.2.3-feat-cli-clear-command.17058+9fe45e4bf",
9182
9187
  type: "module",
9183
9188
  description: "Interactive CLI tool for Bike4Mind with ReAct agents",
9184
9189
  license: "UNLICENSED",
@@ -9280,10 +9285,10 @@ var package_default = {
9280
9285
  },
9281
9286
  devDependencies: {
9282
9287
  "@bike4mind/agents": "0.1.0",
9283
- "@bike4mind/common": "2.37.1-feat-questmaster-gpt5-function-calling.17057+6a6bd60d2",
9284
- "@bike4mind/mcp": "1.19.5-feat-questmaster-gpt5-function-calling.17057+6a6bd60d2",
9285
- "@bike4mind/services": "2.31.1-feat-questmaster-gpt5-function-calling.17057+6a6bd60d2",
9286
- "@bike4mind/utils": "2.0.4-feat-questmaster-gpt5-function-calling.17057+6a6bd60d2",
9288
+ "@bike4mind/common": "2.37.1-feat-cli-clear-command.17058+9fe45e4bf",
9289
+ "@bike4mind/mcp": "1.19.5-feat-cli-clear-command.17058+9fe45e4bf",
9290
+ "@bike4mind/services": "2.31.1-feat-cli-clear-command.17058+9fe45e4bf",
9291
+ "@bike4mind/utils": "2.0.4-feat-cli-clear-command.17058+9fe45e4bf",
9287
9292
  "@types/diff": "^5.0.9",
9288
9293
  "@types/jsonwebtoken": "^9.0.4",
9289
9294
  "@types/node": "^22.9.0",
@@ -9295,7 +9300,7 @@ var package_default = {
9295
9300
  typescript: "^5.9.3",
9296
9301
  vitest: "^3.2.4"
9297
9302
  },
9298
- gitHead: "6a6bd60d237fe79e8af9694dfa94421fbc0e438c"
9303
+ gitHead: "9fe45e4bfb34840cd5b5cb738bb276b0520e89c6"
9299
9304
  };
9300
9305
 
9301
9306
  // src/config/constants.ts
@@ -9675,6 +9680,7 @@ Remember: Use context from previous messages to understand follow-up questions.`
9675
9680
  Available commands:
9676
9681
  /help - Show this help message
9677
9682
  /exit - Exit the CLI
9683
+ /clear - Start a new session
9678
9684
  /login - Authenticate with your B4M account
9679
9685
  /logout - Clear authentication and sign out
9680
9686
  /whoami - Show current authenticated user
@@ -9849,6 +9855,35 @@ Tool Permissions:
9849
9855
  console.log(`Expires: ${new Date(authTokens.expiresAt).toLocaleString()}`);
9850
9856
  console.log("");
9851
9857
  break;
9858
+ case "clear":
9859
+ case "new": {
9860
+ console.clear();
9861
+ const model = state.session?.model || state.config?.defaultModel || "claude-sonnet";
9862
+ const newSession = {
9863
+ id: uuidv49(),
9864
+ name: `Session ${(/* @__PURE__ */ new Date()).toLocaleString()}`,
9865
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
9866
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
9867
+ model,
9868
+ messages: [],
9869
+ metadata: {
9870
+ totalTokens: 0,
9871
+ totalCost: 0,
9872
+ toolCallCount: 0
9873
+ }
9874
+ };
9875
+ await logger.initialize(newSession.id);
9876
+ logger.debug("=== New Session Started via /clear ===");
9877
+ setState((prev) => ({ ...prev, session: newSession }));
9878
+ setStoreSession(newSession);
9879
+ useCliStore.getState().clearAgentSteps();
9880
+ usageCache = null;
9881
+ console.log("New session started.");
9882
+ console.log(`
9883
+ \u{1F4DD} Session: ${newSession.name} | \u{1F916} Model: ${newSession.model} | \u{1F4CA} Tokens: 0
9884
+ `);
9885
+ break;
9886
+ }
9852
9887
  case "usage": {
9853
9888
  const usageAuthTokens = await state.configStore.getAuthTokens();
9854
9889
  if (!usageAuthTokens || new Date(usageAuthTokens.expiresAt) <= /* @__PURE__ */ new Date()) {
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  findMostSimilarMemento,
4
4
  getRelevantMementos
5
- } from "./chunk-WNBKV4FX.js";
6
- import "./chunk-LYNNVNEC.js";
5
+ } from "./chunk-GZTILMGE.js";
6
+ import "./chunk-NZADYDFG.js";
7
7
  import "./chunk-AMDXHL6S.js";
8
8
  import "./chunk-WR6YZRQV.js";
9
9
  import "./chunk-PDX44BCA.js";
@@ -65,7 +65,6 @@ import {
65
65
  cleanMermaidSyntax,
66
66
  computeCosineSimilarity,
67
67
  convertCodeBlocksToArtifacts,
68
- createQuestPlanToolSchema,
69
68
  createTokenizer,
70
69
  decodeBase64DataUrl,
71
70
  detectURLs,
@@ -98,7 +97,6 @@ import {
98
97
  includeImagePromptSystemMessage,
99
98
  initializeConfig,
100
99
  invalidateSettingsCache,
101
- isGPT5ModelWithToolSupport,
102
100
  isMermaidSyntax,
103
101
  isModelAccessible,
104
102
  isPlainText,
@@ -107,7 +105,6 @@ import {
107
105
  isZodError,
108
106
  obfuscateApiKey,
109
107
  parseArtifacts,
110
- parseQuestPlanFunctionCall,
111
108
  processFabFilesServer,
112
109
  processUrlsFromPrompt,
113
110
  secureParameters,
@@ -120,7 +117,7 @@ import {
120
117
  validateMermaidSyntax,
121
118
  warmUpSettingsCache,
122
119
  withRetry
123
- } from "./chunk-LYNNVNEC.js";
120
+ } from "./chunk-NZADYDFG.js";
124
121
  import {
125
122
  Logger,
126
123
  NotificationDeduplicator,
@@ -199,7 +196,6 @@ export {
199
196
  cleanMermaidSyntax,
200
197
  computeCosineSimilarity,
201
198
  convertCodeBlocksToArtifacts,
202
- createQuestPlanToolSchema,
203
199
  createTokenizer,
204
200
  decodeBase64DataUrl,
205
201
  detectURLs,
@@ -232,7 +228,6 @@ export {
232
228
  includeImagePromptSystemMessage,
233
229
  initializeConfig,
234
230
  invalidateSettingsCache,
235
- isGPT5ModelWithToolSupport,
236
231
  isMermaidSyntax,
237
232
  isModelAccessible,
238
233
  isPlainText,
@@ -243,7 +238,6 @@ export {
243
238
  notifyEventLogsToSlack,
244
239
  obfuscateApiKey,
245
240
  parseArtifacts,
246
- parseQuestPlanFunctionCall,
247
241
  postLowCreditsNotificationToSlack,
248
242
  postMessageToSlack,
249
243
  processFabFilesServer,
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  SubtractCreditsSchema,
4
4
  subtractCredits
5
- } from "./chunk-LEG2UM5Q.js";
6
- import "./chunk-LYNNVNEC.js";
5
+ } from "./chunk-Y4HMTEDH.js";
6
+ import "./chunk-NZADYDFG.js";
7
7
  import "./chunk-AMDXHL6S.js";
8
8
  import "./chunk-WR6YZRQV.js";
9
9
  import "./chunk-PDX44BCA.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.2.3-feat-questmaster-gpt5-function-calling.17057+6a6bd60d2",
3
+ "version": "0.2.3-feat-cli-clear-command.17058+9fe45e4bf",
4
4
  "type": "module",
5
5
  "description": "Interactive CLI tool for Bike4Mind with ReAct agents",
6
6
  "license": "UNLICENSED",
@@ -102,10 +102,10 @@
102
102
  },
103
103
  "devDependencies": {
104
104
  "@bike4mind/agents": "0.1.0",
105
- "@bike4mind/common": "2.37.1-feat-questmaster-gpt5-function-calling.17057+6a6bd60d2",
106
- "@bike4mind/mcp": "1.19.5-feat-questmaster-gpt5-function-calling.17057+6a6bd60d2",
107
- "@bike4mind/services": "2.31.1-feat-questmaster-gpt5-function-calling.17057+6a6bd60d2",
108
- "@bike4mind/utils": "2.0.4-feat-questmaster-gpt5-function-calling.17057+6a6bd60d2",
105
+ "@bike4mind/common": "2.37.1-feat-cli-clear-command.17058+9fe45e4bf",
106
+ "@bike4mind/mcp": "1.19.5-feat-cli-clear-command.17058+9fe45e4bf",
107
+ "@bike4mind/services": "2.31.1-feat-cli-clear-command.17058+9fe45e4bf",
108
+ "@bike4mind/utils": "2.0.4-feat-cli-clear-command.17058+9fe45e4bf",
109
109
  "@types/diff": "^5.0.9",
110
110
  "@types/jsonwebtoken": "^9.0.4",
111
111
  "@types/node": "^22.9.0",
@@ -117,5 +117,5 @@
117
117
  "typescript": "^5.9.3",
118
118
  "vitest": "^3.2.4"
119
119
  },
120
- "gitHead": "6a6bd60d237fe79e8af9694dfa94421fbc0e438c"
120
+ "gitHead": "9fe45e4bfb34840cd5b5cb738bb276b0520e89c6"
121
121
  }