@bike4mind/cli 0.2.3-feat-questmaster-gpt5-function-calling.17055 → 0.2.3-feat-questmaster-gpt5-function-calling.17057

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-NH74I6GX.js";
10
+ } from "./chunk-LYNNVNEC.js";
11
11
  import {
12
12
  KnowledgeType,
13
13
  SupportedFabFileMimeTypes
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  BadRequestError,
4
4
  secureParameters
5
- } from "./chunk-NH74I6GX.js";
5
+ } from "./chunk-LYNNVNEC.js";
6
6
  import {
7
7
  GenericCreditDeductTransaction,
8
8
  ImageEditUsageTransaction,
@@ -7985,6 +7985,13 @@ function extractQuestMasterData(reply, options = {}) {
7985
7985
  }
7986
7986
 
7987
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;
7988
7995
  var GPT5_MODELS_WITH_TOOL_SUPPORT = [
7989
7996
  ChatModels.GPT5,
7990
7997
  ChatModels.GPT5_MINI,
@@ -8070,6 +8077,9 @@ ALWAYS call this function to respond. Do NOT respond with plain text.`,
8070
8077
  }
8071
8078
  };
8072
8079
  function parseQuestPlanFunctionCall(args) {
8080
+ if (!args || typeof args !== "string" || args.trim() === "") {
8081
+ throw new Error("Function call arguments are empty or invalid");
8082
+ }
8073
8083
  let parsed;
8074
8084
  try {
8075
8085
  parsed = JSON.parse(args);
@@ -8080,8 +8090,11 @@ function parseQuestPlanFunctionCall(args) {
8080
8090
  throw new Error("Function call arguments must be an object");
8081
8091
  }
8082
8092
  const result = parsed;
8083
- if (!result.goal || typeof result.goal !== "string") {
8084
- throw new Error("Function call missing required field: goal");
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`);
8085
8098
  }
8086
8099
  if (!Array.isArray(result.quests)) {
8087
8100
  throw new Error("Function call missing required field: quests (must be an array)");
@@ -8089,45 +8102,82 @@ function parseQuestPlanFunctionCall(args) {
8089
8102
  if (result.quests.length === 0) {
8090
8103
  throw new Error("Function call returned empty quests array");
8091
8104
  }
8105
+ if (result.quests.length > MAX_QUESTS) {
8106
+ throw new Error(`Too many quests: ${result.quests.length} (max ${MAX_QUESTS})`);
8107
+ }
8092
8108
  for (let i = 0; i < result.quests.length; i++) {
8093
8109
  const quest = result.quests[i];
8094
- if (!quest.id || typeof quest.id !== "string") {
8095
- throw new Error(`Quest ${i} missing required field: id`);
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`);
8096
8122
  }
8097
- if (!quest.title || typeof quest.title !== "string") {
8098
- throw new Error(`Quest ${i} missing required field: title`);
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)`);
8099
8125
  }
8100
- if (!quest.description || typeof quest.description !== "string") {
8101
- throw new Error(`Quest ${i} missing required field: description`);
8126
+ if (questObj.description.length > MAX_DESCRIPTION_LENGTH) {
8127
+ throw new Error(`Quest ${i} description exceeds maximum length of ${MAX_DESCRIPTION_LENGTH} characters`);
8102
8128
  }
8103
- if (!quest.complexity || !["Easy", "Medium", "Hard"].includes(quest.complexity)) {
8104
- throw new Error(`Quest ${i} has invalid complexity: ${quest.complexity} (must be Easy, Medium, or Hard)`);
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)`);
8105
8131
  }
8106
- if (!Array.isArray(quest.subQuests)) {
8107
- throw new Error(`Quest "${quest.id}" missing required field: subQuests (must be an array)`);
8132
+ if (!Array.isArray(questObj.subQuests)) {
8133
+ throw new Error(`Quest "${questObj.id}" missing required field: subQuests (must be an array)`);
8108
8134
  }
8109
- if (quest.subQuests.length === 0) {
8110
- throw new Error(`Quest "${quest.id}" has no subQuests (minimum 2 required)`);
8135
+ if (questObj.subQuests.length === 0) {
8136
+ throw new Error(`Quest "${questObj.id}" has no subQuests (minimum 2 required)`);
8111
8137
  }
8112
- for (let j = 0; j < quest.subQuests.length; j++) {
8113
- const subQuest = quest.subQuests[j];
8114
- if (!subQuest.id || typeof subQuest.id !== "string") {
8115
- throw new Error(`Quest "${quest.id}" subQuest ${j} missing required field: id`);
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)`);
8116
8152
  }
8117
- if (!subQuest.title || typeof subQuest.title !== "string") {
8118
- throw new Error(`Quest "${quest.id}" subQuest ${j} missing required field: title`);
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`);
8119
8155
  }
8120
8156
  }
8121
8157
  }
8122
- if (result.tags !== void 0 && !Array.isArray(result.tags)) {
8123
- throw new Error("Function call field tags must be an array if provided");
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
+ }
8124
8173
  }
8125
8174
  return result;
8126
8175
  }
8127
8176
 
8128
8177
  // ../../b4m-core/packages/utils/dist/src/questMaster.js
8129
- var sanitizeId = (id) => {
8130
- return id.replace(/\s+/g, "-").replace(/[^a-zA-Z0-9_.-]/g, "").replace(/-+/g, "-").replace(/^-|-$/g, "");
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;
8131
8181
  };
8132
8182
  var QuestMaster = class {
8133
8183
  llm;
@@ -8157,6 +8207,9 @@ var QuestMaster = class {
8157
8207
  }
8158
8208
  async processQuestPlan(input) {
8159
8209
  try {
8210
+ if (!this.quest) {
8211
+ throw new Error("No quest context available");
8212
+ }
8160
8213
  await this.onStatusUpdate(this.quest, "Processing quest plan...");
8161
8214
  const defaultResponse = {
8162
8215
  type: "narrative",
@@ -8174,11 +8227,8 @@ var QuestMaster = class {
8174
8227
  }
8175
8228
  ]
8176
8229
  };
8177
- if (!this.quest) {
8178
- throw new Error("No quest context available");
8179
- }
8180
8230
  let questResponse;
8181
- if (typeof input === "object") {
8231
+ if (input !== null && typeof input === "object") {
8182
8232
  this.logger.log("Processing quest plan from function calling result");
8183
8233
  questResponse = {
8184
8234
  type: "quest_plan",
@@ -8293,7 +8343,7 @@ var QuestMaster = class {
8293
8343
  title: item.quest,
8294
8344
  description: item.details,
8295
8345
  complexity: this.determineComplexity(item.details),
8296
- status: "Not Started",
8346
+ status: "not_started",
8297
8347
  subQuests: []
8298
8348
  // This will trigger a retry since we require subquests
8299
8349
  }))
@@ -8342,18 +8392,21 @@ var QuestMaster = class {
8342
8392
  goal: questResponse.meta.goal,
8343
8393
  userId: this.userId,
8344
8394
  tags: questResponse.meta.tags || [],
8345
- quests: questResponse.quests.map((quest) => ({
8346
- id: sanitizeId(quest.id),
8347
- title: quest.title,
8348
- description: quest.description,
8349
- complexity: quest.complexity,
8350
- subQuests: quest.subQuests.map((sub) => ({
8351
- id: sanitizeId(sub.id),
8352
- title: sub.title,
8353
- status: sub.status
8354
- // questId intentionally omitted - will be set when task is started and linked to a chat message
8355
- }))
8356
- }))
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
+ })
8357
8410
  });
8358
8411
  this.quest.questMasterPlanId = questMasterPlan.id;
8359
8412
  this.quest.reply = null;
@@ -8404,7 +8457,9 @@ var QuestMaster = class {
8404
8457
  }
8405
8458
  throw error;
8406
8459
  } finally {
8407
- await this.onStatusUpdate(this.quest, null);
8460
+ if (this.quest) {
8461
+ await this.onStatusUpdate(this.quest, null);
8462
+ }
8408
8463
  }
8409
8464
  }
8410
8465
  validateQuestResponse(response) {
@@ -8563,8 +8618,8 @@ Guidelines:
8563
8618
  toolSchema: createQuestPlanToolSchema
8564
8619
  };
8565
8620
  const options = {
8566
- temperature: retryCount > 0 ? 0.7 : 0.9,
8567
- // Lower temperature on retries
8621
+ temperature: retryCount > 0 ? 0.5 : 0.7,
8622
+ // Lower temperature for structured JSON outputs; even lower on retries
8568
8623
  n: 1,
8569
8624
  stream: false,
8570
8625
  tools: [toolDef],
@@ -8583,7 +8638,12 @@ Guidelines:
8583
8638
  const toolCall = completionInfo.toolsUsed[0];
8584
8639
  if (toolCall.name === "create_quest_plan" && toolCall.arguments) {
8585
8640
  this.logger.log("GPT-5 function call received, parsing arguments...");
8586
- functionResult = parseQuestPlanFunctionCall(toolCall.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
+ }
8587
8647
  }
8588
8648
  }
8589
8649
  });
@@ -8600,9 +8660,13 @@ Guidelines:
8600
8660
  }
8601
8661
  const result = functionResult;
8602
8662
  const questsWithoutSubquests = result.quests.filter((q) => !q.subQuests || q.subQuests.length === 0);
8603
- if (questsWithoutSubquests.length > 0 && retryCount < MAX_RETRIES) {
8604
- this.logger.warn(`Some quests missing subquests: ${questsWithoutSubquests.map((q) => q.id).join(", ")}, retrying...`);
8605
- return this.createQuestPlanWithFunctionCalling(model, prompt, retryCount + 1);
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
+ }
8606
8670
  }
8607
8671
  this.logger.log("Successfully received GPT-5 function call result:", {
8608
8672
  goal: result.goal,
@@ -8613,6 +8677,9 @@ Guidelines:
8613
8677
  }
8614
8678
  async createQuestPlan(model, prompt) {
8615
8679
  try {
8680
+ if (!this.quest) {
8681
+ throw new Error("No quest context available");
8682
+ }
8616
8683
  await this.onStatusUpdate(this.quest, "Creating quest plan...");
8617
8684
  if (isGPT5ModelWithToolSupport(model)) {
8618
8685
  this.logger.log(`Using function calling approach for GPT-5 model: ${model}`);
@@ -6,7 +6,7 @@ import {
6
6
  getSettingsByNames,
7
7
  obfuscateApiKey,
8
8
  secureParameters
9
- } from "./chunk-NH74I6GX.js";
9
+ } from "./chunk-LYNNVNEC.js";
10
10
  import {
11
11
  ApiKeyType,
12
12
  MementoTier,
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  createFabFile,
4
4
  createFabFileSchema
5
- } from "./chunk-KDBSH6HC.js";
6
- import "./chunk-NH74I6GX.js";
5
+ } from "./chunk-6AJODFPC.js";
6
+ import "./chunk-LYNNVNEC.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-44WCHZA2.js";
8
- import "./chunk-O2622ACK.js";
9
- import "./chunk-KDBSH6HC.js";
7
+ } from "./chunk-WNBKV4FX.js";
8
+ import "./chunk-LEG2UM5Q.js";
9
+ import "./chunk-6AJODFPC.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-NH74I6GX.js";
18
+ } from "./chunk-LYNNVNEC.js";
19
19
  import {
20
20
  Logger
21
21
  } from "./chunk-AMDXHL6S.js";
@@ -9178,7 +9178,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
9178
9178
  // package.json
9179
9179
  var package_default = {
9180
9180
  name: "@bike4mind/cli",
9181
- version: "0.2.3-feat-questmaster-gpt5-function-calling.17055+efa3267ae",
9181
+ version: "0.2.3-feat-questmaster-gpt5-function-calling.17057+6a6bd60d2",
9182
9182
  type: "module",
9183
9183
  description: "Interactive CLI tool for Bike4Mind with ReAct agents",
9184
9184
  license: "UNLICENSED",
@@ -9280,10 +9280,10 @@ var package_default = {
9280
9280
  },
9281
9281
  devDependencies: {
9282
9282
  "@bike4mind/agents": "0.1.0",
9283
- "@bike4mind/common": "2.37.1-feat-questmaster-gpt5-function-calling.17055+efa3267ae",
9284
- "@bike4mind/mcp": "1.19.5-feat-questmaster-gpt5-function-calling.17055+efa3267ae",
9285
- "@bike4mind/services": "2.31.1-feat-questmaster-gpt5-function-calling.17055+efa3267ae",
9286
- "@bike4mind/utils": "2.0.4-feat-questmaster-gpt5-function-calling.17055+efa3267ae",
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",
9287
9287
  "@types/diff": "^5.0.9",
9288
9288
  "@types/jsonwebtoken": "^9.0.4",
9289
9289
  "@types/node": "^22.9.0",
@@ -9295,7 +9295,7 @@ var package_default = {
9295
9295
  typescript: "^5.9.3",
9296
9296
  vitest: "^3.2.4"
9297
9297
  },
9298
- gitHead: "efa3267ae1a98e505e89bb3b7e40caf68a8a1347"
9298
+ gitHead: "6a6bd60d237fe79e8af9694dfa94421fbc0e438c"
9299
9299
  };
9300
9300
 
9301
9301
  // src/config/constants.ts
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  findMostSimilarMemento,
4
4
  getRelevantMementos
5
- } from "./chunk-44WCHZA2.js";
6
- import "./chunk-NH74I6GX.js";
5
+ } from "./chunk-WNBKV4FX.js";
6
+ import "./chunk-LYNNVNEC.js";
7
7
  import "./chunk-AMDXHL6S.js";
8
8
  import "./chunk-WR6YZRQV.js";
9
9
  import "./chunk-PDX44BCA.js";
@@ -120,7 +120,7 @@ import {
120
120
  validateMermaidSyntax,
121
121
  warmUpSettingsCache,
122
122
  withRetry
123
- } from "./chunk-NH74I6GX.js";
123
+ } from "./chunk-LYNNVNEC.js";
124
124
  import {
125
125
  Logger,
126
126
  NotificationDeduplicator,
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  SubtractCreditsSchema,
4
4
  subtractCredits
5
- } from "./chunk-O2622ACK.js";
6
- import "./chunk-NH74I6GX.js";
5
+ } from "./chunk-LEG2UM5Q.js";
6
+ import "./chunk-LYNNVNEC.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.17055+efa3267ae",
3
+ "version": "0.2.3-feat-questmaster-gpt5-function-calling.17057+6a6bd60d2",
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.17055+efa3267ae",
106
- "@bike4mind/mcp": "1.19.5-feat-questmaster-gpt5-function-calling.17055+efa3267ae",
107
- "@bike4mind/services": "2.31.1-feat-questmaster-gpt5-function-calling.17055+efa3267ae",
108
- "@bike4mind/utils": "2.0.4-feat-questmaster-gpt5-function-calling.17055+efa3267ae",
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",
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": "efa3267ae1a98e505e89bb3b7e40caf68a8a1347"
120
+ "gitHead": "6a6bd60d237fe79e8af9694dfa94421fbc0e438c"
121
121
  }