@bike4mind/cli 0.2.4-feat-questmaster-external-integrations.17091 → 0.2.4-feat-questmaster-external-integrations.17092
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/index.js +392 -9
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -90,8 +90,10 @@ import { Box as Box9, Text as Text8, Static } from "ink";
|
|
|
90
90
|
// src/components/StatusBar.tsx
|
|
91
91
|
import React from "react";
|
|
92
92
|
import { Box, Text } from "ink";
|
|
93
|
-
var StatusBar = React.memo(function StatusBar2({ sessionName, model, tokenUsage }) {
|
|
94
|
-
|
|
93
|
+
var StatusBar = React.memo(function StatusBar2({ sessionName, model, tokenUsage, quest }) {
|
|
94
|
+
const questDisplay = quest ? `${quest.questTitle || quest.questPlanName} (${quest.progress.completed}/${quest.progress.total})` : null;
|
|
95
|
+
const syncIndicator = quest?.syncStatus === "offline" ? " \u26A0\uFE0F" : quest?.syncStatus === "pending" ? " \u23F3" : "";
|
|
96
|
+
return /* @__PURE__ */ React.createElement(Box, { borderStyle: "single", borderColor: "green", paddingX: 1 }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React.createElement(Box, { gap: 2 }, /* @__PURE__ */ React.createElement(Text, { color: "green", bold: true }, "\u{1F4DD} Session:"), /* @__PURE__ */ React.createElement(Text, null, sessionName)), /* @__PURE__ */ React.createElement(Box, { gap: 2 }, /* @__PURE__ */ React.createElement(Text, { color: "blue", bold: true }, "\u{1F916} Model:"), /* @__PURE__ */ React.createElement(Text, null, model)), /* @__PURE__ */ React.createElement(Box, { gap: 2 }, /* @__PURE__ */ React.createElement(Text, { color: "yellow", bold: true }, "\u{1F4CA} Tokens:"), /* @__PURE__ */ React.createElement(Text, null, tokenUsage.toLocaleString())), questDisplay && /* @__PURE__ */ React.createElement(Box, { gap: 2 }, /* @__PURE__ */ React.createElement(Text, { color: "magenta", bold: true }, "\u{1F3AF} Quest:"), /* @__PURE__ */ React.createElement(Text, null, questDisplay, syncIndicator))));
|
|
95
97
|
});
|
|
96
98
|
|
|
97
99
|
// src/components/InputPrompt.tsx
|
|
@@ -389,6 +391,25 @@ var COMMANDS = [
|
|
|
389
391
|
name: "clear",
|
|
390
392
|
description: "Start a new session",
|
|
391
393
|
aliases: ["new"]
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
name: "quest",
|
|
397
|
+
description: "Load a quest into current session",
|
|
398
|
+
args: "<quest-id>",
|
|
399
|
+
aliases: ["q"]
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
name: "quest-status",
|
|
403
|
+
description: "Show current quest progress",
|
|
404
|
+
aliases: ["qs"]
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
name: "quest-unlink",
|
|
408
|
+
description: "Unlink quest from current session"
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
name: "plan",
|
|
412
|
+
description: "Create a QuestMaster plan from current context"
|
|
392
413
|
}
|
|
393
414
|
];
|
|
394
415
|
|
|
@@ -998,6 +1019,7 @@ function App({
|
|
|
998
1019
|
const sessionName = useCliStore((state) => state.session?.name || "New Session");
|
|
999
1020
|
const currentModel = useCliStore((state) => state.session?.model || "claude-sonnet-4-5-20250929");
|
|
1000
1021
|
const totalTokens = useCliStore((state) => state.session?.metadata.totalTokens || 0);
|
|
1022
|
+
const quest = useCliStore((state) => state.session?.quest);
|
|
1001
1023
|
const isThinking = useCliStore((state) => state.isThinking);
|
|
1002
1024
|
const permissionPrompt = useCliStore((state) => state.permissionPrompt);
|
|
1003
1025
|
const showConfigEditor = useCliStore((state) => state.showConfigEditor);
|
|
@@ -1033,7 +1055,7 @@ ${errorBlock}`;
|
|
|
1033
1055
|
},
|
|
1034
1056
|
[onMessage, onCommand, setIsThinking]
|
|
1035
1057
|
);
|
|
1036
|
-
return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column" }, /* @__PURE__ */ React9.createElement(StatusBar, { sessionName, model: currentModel, tokenUsage: totalTokens }), showConfigEditor && config && onSaveConfig ? /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React9.createElement(ConfigEditor, { config, onSave: onSaveConfig, onClose: () => setShowConfigEditor(false) })) : permissionPrompt ? /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React9.createElement(
|
|
1058
|
+
return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column" }, /* @__PURE__ */ React9.createElement(StatusBar, { sessionName, model: currentModel, tokenUsage: totalTokens, quest }), showConfigEditor && config && onSaveConfig ? /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React9.createElement(ConfigEditor, { config, onSave: onSaveConfig, onClose: () => setShowConfigEditor(false) })) : permissionPrompt ? /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React9.createElement(
|
|
1037
1059
|
PermissionPrompt,
|
|
1038
1060
|
{
|
|
1039
1061
|
toolName: permissionPrompt.toolName,
|
|
@@ -9026,6 +9048,197 @@ var McpManager = class {
|
|
|
9026
9048
|
}
|
|
9027
9049
|
};
|
|
9028
9050
|
|
|
9051
|
+
// src/utils/QuestTracker.ts
|
|
9052
|
+
var QuestTracker = class {
|
|
9053
|
+
constructor(apiClient) {
|
|
9054
|
+
this.apiClient = apiClient;
|
|
9055
|
+
this.pendingUpdates = [];
|
|
9056
|
+
this.cachedQuests = /* @__PURE__ */ new Map();
|
|
9057
|
+
}
|
|
9058
|
+
/**
|
|
9059
|
+
* Fetch a quest plan from the API
|
|
9060
|
+
*/
|
|
9061
|
+
async fetchQuestPlan(questPlanId) {
|
|
9062
|
+
try {
|
|
9063
|
+
const response = await this.apiClient.get(
|
|
9064
|
+
`/api/quest-plans/${questPlanId}`
|
|
9065
|
+
);
|
|
9066
|
+
if (response.success && response.questPlan) {
|
|
9067
|
+
this.cachedQuests.set(questPlanId, response.questPlan);
|
|
9068
|
+
return response.questPlan;
|
|
9069
|
+
}
|
|
9070
|
+
return null;
|
|
9071
|
+
} catch (error) {
|
|
9072
|
+
const cached = this.cachedQuests.get(questPlanId);
|
|
9073
|
+
if (cached) {
|
|
9074
|
+
console.log("\u26A0\uFE0F Using cached quest data (offline mode)");
|
|
9075
|
+
return cached;
|
|
9076
|
+
}
|
|
9077
|
+
throw error;
|
|
9078
|
+
}
|
|
9079
|
+
}
|
|
9080
|
+
/**
|
|
9081
|
+
* Create a SessionQuestLink from quest plan data
|
|
9082
|
+
*/
|
|
9083
|
+
createQuestLink(questPlan, questId) {
|
|
9084
|
+
const quest = questId ? questPlan.quests.find((q) => q.id === questId) : null;
|
|
9085
|
+
let total = 0;
|
|
9086
|
+
let completed = 0;
|
|
9087
|
+
if (quest) {
|
|
9088
|
+
total = quest.subQuests.length || 1;
|
|
9089
|
+
completed = quest.subQuests.filter((sq) => sq.status === "completed").length;
|
|
9090
|
+
if (quest.subQuests.length === 0 && quest.status === "completed") {
|
|
9091
|
+
completed = 1;
|
|
9092
|
+
}
|
|
9093
|
+
} else {
|
|
9094
|
+
total = questPlan.quests.length;
|
|
9095
|
+
completed = questPlan.quests.filter((q) => q.status === "completed").length;
|
|
9096
|
+
}
|
|
9097
|
+
return {
|
|
9098
|
+
questPlanId: questPlan.id,
|
|
9099
|
+
questPlanName: questPlan.goal.length > 40 ? questPlan.goal.substring(0, 37) + "..." : questPlan.goal,
|
|
9100
|
+
questId,
|
|
9101
|
+
questTitle: quest?.title,
|
|
9102
|
+
linkedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9103
|
+
progress: { total, completed },
|
|
9104
|
+
syncStatus: "synced",
|
|
9105
|
+
lastSyncedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
9106
|
+
};
|
|
9107
|
+
}
|
|
9108
|
+
/**
|
|
9109
|
+
* Update quest status (queues for sync if offline)
|
|
9110
|
+
*/
|
|
9111
|
+
async updateQuestStatus(questPlanId, status, questId, subQuestId) {
|
|
9112
|
+
const update3 = {
|
|
9113
|
+
questPlanId,
|
|
9114
|
+
questId,
|
|
9115
|
+
subQuestId,
|
|
9116
|
+
newStatus: status,
|
|
9117
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
9118
|
+
};
|
|
9119
|
+
try {
|
|
9120
|
+
await this.syncUpdate(update3);
|
|
9121
|
+
return true;
|
|
9122
|
+
} catch (error) {
|
|
9123
|
+
this.pendingUpdates.push(update3);
|
|
9124
|
+
console.log("\u26A0\uFE0F Update queued for sync when online");
|
|
9125
|
+
return false;
|
|
9126
|
+
}
|
|
9127
|
+
}
|
|
9128
|
+
/**
|
|
9129
|
+
* Sync a single update to the server
|
|
9130
|
+
*/
|
|
9131
|
+
async syncUpdate(update3) {
|
|
9132
|
+
const endpoint = update3.subQuestId ? `/api/quest-plans/${update3.questPlanId}/quests/${update3.questId}/sub-quests/${update3.subQuestId}/status` : update3.questId ? `/api/quest-plans/${update3.questPlanId}/quests/${update3.questId}/status` : `/api/quest-plans/${update3.questPlanId}/status`;
|
|
9133
|
+
await this.apiClient.put(endpoint, { status: update3.newStatus });
|
|
9134
|
+
}
|
|
9135
|
+
/**
|
|
9136
|
+
* Sync all pending updates
|
|
9137
|
+
*/
|
|
9138
|
+
async syncPendingUpdates() {
|
|
9139
|
+
let synced = 0;
|
|
9140
|
+
let failed = 0;
|
|
9141
|
+
const remaining = [];
|
|
9142
|
+
for (const update3 of this.pendingUpdates) {
|
|
9143
|
+
try {
|
|
9144
|
+
await this.syncUpdate(update3);
|
|
9145
|
+
synced++;
|
|
9146
|
+
} catch {
|
|
9147
|
+
remaining.push(update3);
|
|
9148
|
+
failed++;
|
|
9149
|
+
}
|
|
9150
|
+
}
|
|
9151
|
+
this.pendingUpdates = remaining;
|
|
9152
|
+
return { synced, failed };
|
|
9153
|
+
}
|
|
9154
|
+
/**
|
|
9155
|
+
* Get pending update count
|
|
9156
|
+
*/
|
|
9157
|
+
getPendingCount() {
|
|
9158
|
+
return this.pendingUpdates.length;
|
|
9159
|
+
}
|
|
9160
|
+
/**
|
|
9161
|
+
* Check if there are pending updates
|
|
9162
|
+
*/
|
|
9163
|
+
hasPendingUpdates() {
|
|
9164
|
+
return this.pendingUpdates.length > 0;
|
|
9165
|
+
}
|
|
9166
|
+
/**
|
|
9167
|
+
* Update progress in a SessionQuestLink
|
|
9168
|
+
*/
|
|
9169
|
+
updateProgress(link, questPlan) {
|
|
9170
|
+
const quest = link.questId ? questPlan.quests.find((q) => q.id === link.questId) : null;
|
|
9171
|
+
let total = 0;
|
|
9172
|
+
let completed = 0;
|
|
9173
|
+
if (quest) {
|
|
9174
|
+
total = quest.subQuests.length || 1;
|
|
9175
|
+
completed = quest.subQuests.filter((sq) => sq.status === "completed").length;
|
|
9176
|
+
if (quest.subQuests.length === 0 && quest.status === "completed") {
|
|
9177
|
+
completed = 1;
|
|
9178
|
+
}
|
|
9179
|
+
} else {
|
|
9180
|
+
total = questPlan.quests.length;
|
|
9181
|
+
completed = questPlan.quests.filter((q) => q.status === "completed").length;
|
|
9182
|
+
}
|
|
9183
|
+
return {
|
|
9184
|
+
...link,
|
|
9185
|
+
progress: { total, completed },
|
|
9186
|
+
syncStatus: this.hasPendingUpdates() ? "pending" : "synced",
|
|
9187
|
+
lastSyncedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
9188
|
+
};
|
|
9189
|
+
}
|
|
9190
|
+
/**
|
|
9191
|
+
* Format quest plan for display
|
|
9192
|
+
*/
|
|
9193
|
+
formatQuestPlan(questPlan) {
|
|
9194
|
+
const lines = [];
|
|
9195
|
+
lines.push(`
|
|
9196
|
+
\u{1F3AF} Quest Plan: ${questPlan.goal}`);
|
|
9197
|
+
lines.push(` Status: ${this.formatStatus(questPlan.status)}`);
|
|
9198
|
+
lines.push("");
|
|
9199
|
+
questPlan.quests.forEach((quest, i) => {
|
|
9200
|
+
const statusIcon = this.getStatusIcon(quest.status);
|
|
9201
|
+
lines.push(` ${i + 1}. ${statusIcon} ${quest.title}`);
|
|
9202
|
+
if (quest.subQuests.length > 0) {
|
|
9203
|
+
quest.subQuests.forEach((sq) => {
|
|
9204
|
+
const sqIcon = this.getStatusIcon(sq.status);
|
|
9205
|
+
lines.push(` ${sqIcon} ${sq.title}`);
|
|
9206
|
+
});
|
|
9207
|
+
}
|
|
9208
|
+
});
|
|
9209
|
+
lines.push("");
|
|
9210
|
+
return lines.join("\n");
|
|
9211
|
+
}
|
|
9212
|
+
formatStatus(status) {
|
|
9213
|
+
switch (status) {
|
|
9214
|
+
case "planning":
|
|
9215
|
+
return "\u{1F4CB} Planning";
|
|
9216
|
+
case "in_progress":
|
|
9217
|
+
return "\u{1F504} In Progress";
|
|
9218
|
+
case "completed":
|
|
9219
|
+
return "\u2705 Completed";
|
|
9220
|
+
case "cancelled":
|
|
9221
|
+
return "\u274C Cancelled";
|
|
9222
|
+
default:
|
|
9223
|
+
return status;
|
|
9224
|
+
}
|
|
9225
|
+
}
|
|
9226
|
+
getStatusIcon(status) {
|
|
9227
|
+
switch (status) {
|
|
9228
|
+
case "pending":
|
|
9229
|
+
return "\u2B1C";
|
|
9230
|
+
case "in_progress":
|
|
9231
|
+
return "\u{1F504}";
|
|
9232
|
+
case "completed":
|
|
9233
|
+
return "\u2705";
|
|
9234
|
+
case "skipped":
|
|
9235
|
+
return "\u23ED\uFE0F";
|
|
9236
|
+
default:
|
|
9237
|
+
return "\u2B1C";
|
|
9238
|
+
}
|
|
9239
|
+
}
|
|
9240
|
+
};
|
|
9241
|
+
|
|
9029
9242
|
// src/llm/ServerLlmBackend.ts
|
|
9030
9243
|
import { createParser } from "eventsource-parser";
|
|
9031
9244
|
import { isAxiosError } from "axios";
|
|
@@ -9412,7 +9625,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
|
|
|
9412
9625
|
// package.json
|
|
9413
9626
|
var package_default = {
|
|
9414
9627
|
name: "@bike4mind/cli",
|
|
9415
|
-
version: "0.2.4-feat-questmaster-external-integrations.
|
|
9628
|
+
version: "0.2.4-feat-questmaster-external-integrations.17092+a4c38b013",
|
|
9416
9629
|
type: "module",
|
|
9417
9630
|
description: "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
9418
9631
|
license: "UNLICENSED",
|
|
@@ -9514,10 +9727,10 @@ var package_default = {
|
|
|
9514
9727
|
},
|
|
9515
9728
|
devDependencies: {
|
|
9516
9729
|
"@bike4mind/agents": "0.1.0",
|
|
9517
|
-
"@bike4mind/common": "2.37.1-feat-questmaster-external-integrations.
|
|
9518
|
-
"@bike4mind/mcp": "1.19.5-feat-questmaster-external-integrations.
|
|
9519
|
-
"@bike4mind/services": "2.32.1-feat-questmaster-external-integrations.
|
|
9520
|
-
"@bike4mind/utils": "2.1.1-feat-questmaster-external-integrations.
|
|
9730
|
+
"@bike4mind/common": "2.37.1-feat-questmaster-external-integrations.17092+a4c38b013",
|
|
9731
|
+
"@bike4mind/mcp": "1.19.5-feat-questmaster-external-integrations.17092+a4c38b013",
|
|
9732
|
+
"@bike4mind/services": "2.32.1-feat-questmaster-external-integrations.17092+a4c38b013",
|
|
9733
|
+
"@bike4mind/utils": "2.1.1-feat-questmaster-external-integrations.17092+a4c38b013",
|
|
9521
9734
|
"@types/diff": "^5.0.9",
|
|
9522
9735
|
"@types/jsonwebtoken": "^9.0.4",
|
|
9523
9736
|
"@types/node": "^22.9.0",
|
|
@@ -9529,7 +9742,7 @@ var package_default = {
|
|
|
9529
9742
|
typescript: "^5.9.3",
|
|
9530
9743
|
vitest: "^3.2.4"
|
|
9531
9744
|
},
|
|
9532
|
-
gitHead: "
|
|
9745
|
+
gitHead: "a4c38b0137e98ea3c491cbfe670c42e277ac6afe"
|
|
9533
9746
|
};
|
|
9534
9747
|
|
|
9535
9748
|
// src/config/constants.ts
|
|
@@ -10203,6 +10416,176 @@ No usage data available for the last ${USAGE_DAYS} days.`);
|
|
|
10203
10416
|
console.log("");
|
|
10204
10417
|
break;
|
|
10205
10418
|
}
|
|
10419
|
+
case "quest":
|
|
10420
|
+
case "q": {
|
|
10421
|
+
const questPlanId = args[0];
|
|
10422
|
+
if (!questPlanId) {
|
|
10423
|
+
console.log("\nUsage: /quest <quest-plan-id>");
|
|
10424
|
+
console.log("Example: /quest abc123");
|
|
10425
|
+
console.log("\nThis will load a quest plan into your current session.\n");
|
|
10426
|
+
break;
|
|
10427
|
+
}
|
|
10428
|
+
const questAuthTokens = await state.configStore.getAuthTokens();
|
|
10429
|
+
if (!questAuthTokens || new Date(questAuthTokens.expiresAt) <= /* @__PURE__ */ new Date()) {
|
|
10430
|
+
console.log("\n\u274C Authentication required. Run /login first.\n");
|
|
10431
|
+
break;
|
|
10432
|
+
}
|
|
10433
|
+
console.log("\nLoading quest plan...");
|
|
10434
|
+
try {
|
|
10435
|
+
const config = await state.configStore.get();
|
|
10436
|
+
const apiBaseURL = getApiUrl(config.apiConfig);
|
|
10437
|
+
const apiClient = new ApiClient(apiBaseURL, state.configStore);
|
|
10438
|
+
const questTracker = new QuestTracker(apiClient);
|
|
10439
|
+
const questPlan = await questTracker.fetchQuestPlan(questPlanId);
|
|
10440
|
+
if (!questPlan) {
|
|
10441
|
+
console.log("\n\u274C Quest plan not found.\n");
|
|
10442
|
+
break;
|
|
10443
|
+
}
|
|
10444
|
+
const questLink = questTracker.createQuestLink(questPlan);
|
|
10445
|
+
const updatedSession = {
|
|
10446
|
+
...state.session,
|
|
10447
|
+
quest: questLink,
|
|
10448
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
10449
|
+
};
|
|
10450
|
+
setState((prev) => ({ ...prev, session: updatedSession }));
|
|
10451
|
+
setStoreSession(updatedSession);
|
|
10452
|
+
await state.sessionStore.save(updatedSession);
|
|
10453
|
+
console.log(`
|
|
10454
|
+
\u2705 Quest loaded: ${questPlan.goal}`);
|
|
10455
|
+
console.log(questTracker.formatQuestPlan(questPlan));
|
|
10456
|
+
} catch (error) {
|
|
10457
|
+
if (isAxiosError2(error)) {
|
|
10458
|
+
if (error.response?.status === 404) {
|
|
10459
|
+
console.log("\n\u274C Quest plan not found.\n");
|
|
10460
|
+
} else if (error.response?.status === 403) {
|
|
10461
|
+
console.log("\n\u274C Access denied to this quest plan.\n");
|
|
10462
|
+
} else {
|
|
10463
|
+
console.log(`
|
|
10464
|
+
\u274C Error loading quest: ${error.message}
|
|
10465
|
+
`);
|
|
10466
|
+
}
|
|
10467
|
+
} else if (error instanceof Error) {
|
|
10468
|
+
console.log(`
|
|
10469
|
+
\u274C Error: ${error.message}
|
|
10470
|
+
`);
|
|
10471
|
+
}
|
|
10472
|
+
}
|
|
10473
|
+
break;
|
|
10474
|
+
}
|
|
10475
|
+
case "quest-status":
|
|
10476
|
+
case "qs": {
|
|
10477
|
+
if (!state.session?.quest) {
|
|
10478
|
+
console.log("\n\u26A0\uFE0F No quest linked to this session.");
|
|
10479
|
+
console.log("Use /quest <quest-id> to load a quest.\n");
|
|
10480
|
+
break;
|
|
10481
|
+
}
|
|
10482
|
+
const questLink = state.session.quest;
|
|
10483
|
+
console.log("\n\u{1F3AF} Current Quest Status:");
|
|
10484
|
+
console.log(` Plan: ${questLink.questPlanName}`);
|
|
10485
|
+
if (questLink.questTitle) {
|
|
10486
|
+
console.log(` Quest: ${questLink.questTitle}`);
|
|
10487
|
+
}
|
|
10488
|
+
console.log(` Progress: ${questLink.progress.completed}/${questLink.progress.total}`);
|
|
10489
|
+
console.log(
|
|
10490
|
+
` Sync: ${questLink.syncStatus === "synced" ? "\u2705 Synced" : questLink.syncStatus === "pending" ? "\u23F3 Pending" : "\u26A0\uFE0F Offline"}`
|
|
10491
|
+
);
|
|
10492
|
+
if (questLink.lastSyncedAt) {
|
|
10493
|
+
console.log(` Last Synced: ${new Date(questLink.lastSyncedAt).toLocaleString()}`);
|
|
10494
|
+
}
|
|
10495
|
+
try {
|
|
10496
|
+
const config = await state.configStore.get();
|
|
10497
|
+
const apiBaseURL = getApiUrl(config.apiConfig);
|
|
10498
|
+
const apiClient = new ApiClient(apiBaseURL, state.configStore);
|
|
10499
|
+
const questTracker = new QuestTracker(apiClient);
|
|
10500
|
+
const questPlan = await questTracker.fetchQuestPlan(questLink.questPlanId);
|
|
10501
|
+
if (questPlan) {
|
|
10502
|
+
console.log(questTracker.formatQuestPlan(questPlan));
|
|
10503
|
+
const updatedLink = questTracker.updateProgress(questLink, questPlan);
|
|
10504
|
+
if (updatedLink.progress.completed !== questLink.progress.completed || updatedLink.progress.total !== questLink.progress.total) {
|
|
10505
|
+
const updatedSession = {
|
|
10506
|
+
...state.session,
|
|
10507
|
+
quest: updatedLink,
|
|
10508
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
10509
|
+
};
|
|
10510
|
+
setState((prev) => ({ ...prev, session: updatedSession }));
|
|
10511
|
+
setStoreSession(updatedSession);
|
|
10512
|
+
await state.sessionStore.save(updatedSession);
|
|
10513
|
+
}
|
|
10514
|
+
}
|
|
10515
|
+
} catch {
|
|
10516
|
+
console.log("\n\u26A0\uFE0F Could not fetch latest quest data (showing cached info).\n");
|
|
10517
|
+
}
|
|
10518
|
+
break;
|
|
10519
|
+
}
|
|
10520
|
+
case "quest-unlink": {
|
|
10521
|
+
if (!state.session?.quest) {
|
|
10522
|
+
console.log("\n\u26A0\uFE0F No quest linked to this session.\n");
|
|
10523
|
+
break;
|
|
10524
|
+
}
|
|
10525
|
+
const questName = state.session.quest.questPlanName;
|
|
10526
|
+
const updatedSession = {
|
|
10527
|
+
...state.session,
|
|
10528
|
+
quest: void 0,
|
|
10529
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
10530
|
+
};
|
|
10531
|
+
setState((prev) => ({ ...prev, session: updatedSession }));
|
|
10532
|
+
setStoreSession(updatedSession);
|
|
10533
|
+
await state.sessionStore.save(updatedSession);
|
|
10534
|
+
console.log(`
|
|
10535
|
+
\u2705 Unlinked quest: ${questName}
|
|
10536
|
+
`);
|
|
10537
|
+
break;
|
|
10538
|
+
}
|
|
10539
|
+
case "plan": {
|
|
10540
|
+
const planAuthTokens = await state.configStore.getAuthTokens();
|
|
10541
|
+
if (!planAuthTokens || new Date(planAuthTokens.expiresAt) <= /* @__PURE__ */ new Date()) {
|
|
10542
|
+
console.log("\n\u274C Authentication required. Run /login first.\n");
|
|
10543
|
+
break;
|
|
10544
|
+
}
|
|
10545
|
+
if (!state.session || state.session.messages.length === 0) {
|
|
10546
|
+
console.log("\n\u26A0\uFE0F No conversation context to create a plan from.");
|
|
10547
|
+
console.log("Start a conversation first, then use /plan to generate a QuestMaster plan.\n");
|
|
10548
|
+
break;
|
|
10549
|
+
}
|
|
10550
|
+
console.log("\n\u{1F3AF} Creating QuestMaster plan from conversation context...");
|
|
10551
|
+
console.log("\u{1F4A1} This will analyze your conversation and create a structured plan.\n");
|
|
10552
|
+
try {
|
|
10553
|
+
const config = await state.configStore.get();
|
|
10554
|
+
const apiBaseURL = getApiUrl(config.apiConfig);
|
|
10555
|
+
const apiClient = new ApiClient(apiBaseURL, state.configStore);
|
|
10556
|
+
const contextMessages = state.session.messages.slice(-10).map((m) => ({
|
|
10557
|
+
role: m.role,
|
|
10558
|
+
content: m.content
|
|
10559
|
+
}));
|
|
10560
|
+
const response = await apiClient.post("/api/quest-plans", {
|
|
10561
|
+
context: contextMessages,
|
|
10562
|
+
sessionId: state.session.id
|
|
10563
|
+
});
|
|
10564
|
+
if (!response.success) {
|
|
10565
|
+
console.log(`
|
|
10566
|
+
\u274C Failed to create plan: ${response.error}
|
|
10567
|
+
`);
|
|
10568
|
+
break;
|
|
10569
|
+
}
|
|
10570
|
+
console.log(`
|
|
10571
|
+
\u2705 Quest plan created: ${response.questPlan.goal}`);
|
|
10572
|
+
console.log(` Plan ID: ${response.questPlan.id}`);
|
|
10573
|
+
console.log(`
|
|
10574
|
+
\u{1F4A1} Use /quest ${response.questPlan.id} to load this plan into your session.
|
|
10575
|
+
`);
|
|
10576
|
+
} catch (error) {
|
|
10577
|
+
if (isAxiosError2(error)) {
|
|
10578
|
+
console.log(`
|
|
10579
|
+
\u274C Error creating plan: ${error.response?.data?.error || error.message}
|
|
10580
|
+
`);
|
|
10581
|
+
} else if (error instanceof Error) {
|
|
10582
|
+
console.log(`
|
|
10583
|
+
\u274C Error: ${error.message}
|
|
10584
|
+
`);
|
|
10585
|
+
}
|
|
10586
|
+
}
|
|
10587
|
+
break;
|
|
10588
|
+
}
|
|
10206
10589
|
default:
|
|
10207
10590
|
console.log(`Unknown command: /${command}`);
|
|
10208
10591
|
console.log("Type /help for available commands");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bike4mind/cli",
|
|
3
|
-
"version": "0.2.4-feat-questmaster-external-integrations.
|
|
3
|
+
"version": "0.2.4-feat-questmaster-external-integrations.17092+a4c38b013",
|
|
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-external-integrations.
|
|
106
|
-
"@bike4mind/mcp": "1.19.5-feat-questmaster-external-integrations.
|
|
107
|
-
"@bike4mind/services": "2.32.1-feat-questmaster-external-integrations.
|
|
108
|
-
"@bike4mind/utils": "2.1.1-feat-questmaster-external-integrations.
|
|
105
|
+
"@bike4mind/common": "2.37.1-feat-questmaster-external-integrations.17092+a4c38b013",
|
|
106
|
+
"@bike4mind/mcp": "1.19.5-feat-questmaster-external-integrations.17092+a4c38b013",
|
|
107
|
+
"@bike4mind/services": "2.32.1-feat-questmaster-external-integrations.17092+a4c38b013",
|
|
108
|
+
"@bike4mind/utils": "2.1.1-feat-questmaster-external-integrations.17092+a4c38b013",
|
|
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": "
|
|
120
|
+
"gitHead": "a4c38b0137e98ea3c491cbfe670c42e277ac6afe"
|
|
121
121
|
}
|