@rubytech/taskmaster 1.0.64 → 1.0.65

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.
Files changed (39) hide show
  1. package/dist/agents/pi-embedded-runner/history.js +19 -1
  2. package/dist/agents/pi-embedded-runner/run/attempt.js +23 -5
  3. package/dist/agents/pi-embedded-runner/run.js +6 -31
  4. package/dist/agents/pi-embedded-runner.js +1 -1
  5. package/dist/agents/system-prompt.js +20 -0
  6. package/dist/agents/taskmaster-tools.js +4 -0
  7. package/dist/agents/tool-policy.js +2 -0
  8. package/dist/agents/tools/message-history-tool.js +436 -0
  9. package/dist/agents/tools/sessions-history-tool.js +1 -0
  10. package/dist/build-info.json +3 -3
  11. package/dist/config/zod-schema.js +10 -0
  12. package/dist/control-ui/assets/index-DmifehTc.css +1 -0
  13. package/dist/control-ui/assets/index-o5Xs9S4u.js +3166 -0
  14. package/dist/control-ui/assets/index-o5Xs9S4u.js.map +1 -0
  15. package/dist/control-ui/index.html +2 -2
  16. package/dist/gateway/config-reload.js +1 -0
  17. package/dist/gateway/control-ui.js +173 -0
  18. package/dist/gateway/net.js +16 -0
  19. package/dist/gateway/protocol/client-info.js +1 -0
  20. package/dist/gateway/protocol/schema/logs-chat.js +3 -0
  21. package/dist/gateway/protocol/schema/sessions-transcript.js +1 -3
  22. package/dist/gateway/public-chat/deliver-otp.js +9 -0
  23. package/dist/gateway/public-chat/otp.js +60 -0
  24. package/dist/gateway/public-chat/session.js +45 -0
  25. package/dist/gateway/server/ws-connection/message-handler.js +17 -4
  26. package/dist/gateway/server-chat.js +22 -0
  27. package/dist/gateway/server-http.js +21 -3
  28. package/dist/gateway/server-methods/chat.js +38 -5
  29. package/dist/gateway/server-methods/public-chat.js +110 -0
  30. package/dist/gateway/server-methods/sessions-transcript.js +29 -46
  31. package/dist/gateway/server-methods.js +17 -0
  32. package/dist/hooks/bundled/conversation-archive/handler.js +23 -6
  33. package/dist/plugins/runtime/index.js +2 -0
  34. package/dist/utils/message-channel.js +3 -0
  35. package/package.json +1 -1
  36. package/taskmaster-docs/USER-GUIDE.md +185 -5
  37. package/dist/control-ui/assets/index-BPvR6pln.js +0 -3021
  38. package/dist/control-ui/assets/index-BPvR6pln.js.map +0 -1
  39. package/dist/control-ui/assets/index-mweBpmCT.css +0 -1
@@ -70,7 +70,7 @@ export function getDmHistoryLimitFromSessionKey(sessionKey, config) {
70
70
  }
71
71
  /**
72
72
  * Resolves the effective history turn limit for any session.
73
- * Priority: per-DM/channel config → agents.defaults.historyTurns → built-in default (50).
73
+ * Priority: per-DM/channel config → agents.defaults.historyTurns → built-in default (20).
74
74
  * This ensures ALL sessions have a rolling window, preventing context overflow and compaction.
75
75
  */
76
76
  export function getEffectiveHistoryLimit(sessionKey, config) {
@@ -108,6 +108,24 @@ function stripToolCallBlocks(msg) {
108
108
  return null; // assistant message was tool-calls only
109
109
  return { ...msg, content: textBlocks };
110
110
  }
111
+ /**
112
+ * Strips an array of agent messages down to conversational content only.
113
+ * Keeps user messages and assistant text responses; drops tool calls,
114
+ * tool results, and other operational message types.
115
+ * Used to ensure the rolling window operates on clean conversational text,
116
+ * preventing tool-result bloat from inflating token counts.
117
+ */
118
+ export function stripToConversationMessages(messages) {
119
+ const result = [];
120
+ for (const msg of messages) {
121
+ if (!msg?.role || !CONVERSATION_ROLES.has(msg.role))
122
+ continue;
123
+ const cleaned = stripToolCallBlocks(msg);
124
+ if (cleaned)
125
+ result.push(cleaned);
126
+ }
127
+ return result;
128
+ }
111
129
  /**
112
130
  * Loads conversation messages from all previous sessions for a given session key.
113
131
  * Returns user + assistant text messages in chronological order (oldest first).
@@ -38,7 +38,7 @@ import { buildEmbeddedExtensionPaths } from "../extensions.js";
38
38
  import { applyExtraParamsToAgent } from "../extra-params.js";
39
39
  import { appendCacheTtlTimestamp, isCacheTtlEligibleProvider } from "../cache-ttl.js";
40
40
  import { logToolSchemasForGoogle, sanitizeSessionHistory, sanitizeToolsForGoogle, } from "../google.js";
41
- import { getEffectiveHistoryLimit, limitHistoryTurns, loadPreviousSessionMessages, } from "../history.js";
41
+ import { getEffectiveHistoryLimit, limitHistoryTurns, loadPreviousSessionMessages, stripToConversationMessages, } from "../history.js";
42
42
  import { log } from "../logger.js";
43
43
  import { buildModelAliasLines } from "../model.js";
44
44
  import { clearActiveEmbeddedRun, setActiveEmbeddedRun, } from "../runs.js";
@@ -360,6 +360,18 @@ export async function runEmbeddedAttempt(params) {
360
360
  settingsManager,
361
361
  minReserveTokens: resolveCompactionReserveTokensFloor(params.config),
362
362
  });
363
+ // Disable auto-compaction entirely. The rolling history window
364
+ // (limitHistoryTurns + stripToConversationMessages) prevents context
365
+ // overflow by sending only clean conversational text to the model.
366
+ // Auto-compaction replaces history with a thin summary the agent cannot
367
+ // use, causing complete context loss. Manual /compact is unaffected
368
+ // (it creates its own session and SettingsManager).
369
+ settingsManager.setCompactionEnabled(false);
370
+ // Disable auto-compaction entirely. The rolling history window
371
+ // (limitHistoryTurns) prevents context overflow between runs.
372
+ // Auto-compaction replaces conversation history with a thin summary,
373
+ // causing the agent to lose all context. Manual /compact is unaffected.
374
+ settingsManager.setCompactionEnabled(false);
363
375
  const additionalExtensionPaths = buildEmbeddedExtensionPaths({
364
376
  cfg: params.config,
365
377
  sessionManager,
@@ -409,6 +421,7 @@ export async function runEmbeddedAttempt(params) {
409
421
  throw new Error("Embedded agent session missing");
410
422
  }
411
423
  const activeSession = session;
424
+ activeSession.setAutoCompactionEnabled(false);
412
425
  const cacheTrace = createCacheTrace({
413
426
  cfg: params.config,
414
427
  env: process.env,
@@ -445,12 +458,17 @@ export async function runEmbeddedAttempt(params) {
445
458
  activeSession.agent.streamFn = anthropicPayloadLogger.wrapStreamFn(activeSession.agent.streamFn);
446
459
  }
447
460
  try {
448
- // Load messages from previous sessions to create one continuous conversation.
449
- // The rolling window then keeps only the last N turns for context.
461
+ // Build a clean conversational history for the rolling window.
462
+ // Both previous-session and current-session messages are stripped
463
+ // to user + assistant text only — tool calls and tool results are
464
+ // operational artifacts that bloat token counts without adding
465
+ // conversational value. This ensures the 20-turn window stays
466
+ // within context limits regardless of how many tools were used.
450
467
  const previousMessages = loadPreviousSessionMessages(params.sessionFile, params.sessionKey);
468
+ const currentConversation = stripToConversationMessages(activeSession.messages);
451
469
  const combinedMessages = previousMessages.length > 0
452
- ? [...previousMessages, ...activeSession.messages]
453
- : activeSession.messages;
470
+ ? [...previousMessages, ...currentConversation]
471
+ : currentConversation;
454
472
  const prior = await sanitizeSessionHistory({
455
473
  messages: combinedMessages,
456
474
  modelApi: params.model.api,
@@ -12,7 +12,6 @@ import { normalizeProviderId } from "../model-selection.js";
12
12
  import { ensureTaskmasterModelsJson } from "../models-config.js";
13
13
  import { classifyFailoverReason, formatAssistantErrorText, isAuthAssistantError, isCompactionFailureError, isContextOverflowError, isFailoverAssistantError, isFailoverErrorMessage, parseImageDimensionError, isRateLimitAssistantError, isTimeoutErrorMessage, pickFallbackThinkingLevel, } from "../pi-embedded-helpers.js";
14
14
  import { normalizeUsage } from "../usage.js";
15
- import { compactEmbeddedPiSessionDirect } from "./compact.js";
16
15
  import { resolveGlobalLane, resolveSessionLane } from "./lanes.js";
17
16
  import { log } from "./logger.js";
18
17
  import { resolveModel } from "./model.js";
@@ -213,7 +212,6 @@ export async function runEmbeddedPiAgent(params) {
213
212
  throwAuthProfileFailover({ allInCooldown: false, error: err });
214
213
  }
215
214
  }
216
- let overflowCompactionAttempted = false;
217
215
  try {
218
216
  while (true) {
219
217
  attemptedThinking.add(thinkLevel);
@@ -280,35 +278,12 @@ export async function runEmbeddedPiAgent(params) {
280
278
  const errorText = describeUnknownError(promptError);
281
279
  if (isContextOverflowError(errorText)) {
282
280
  const isCompactionFailure = isCompactionFailureError(errorText);
283
- // Attempt auto-compaction on context overflow (not compaction_failure)
284
- if (!isCompactionFailure && !overflowCompactionAttempted) {
285
- log.warn(`context overflow detected; attempting auto-compaction for ${provider}/${modelId}`);
286
- overflowCompactionAttempted = true;
287
- const compactResult = await compactEmbeddedPiSessionDirect({
288
- sessionId: params.sessionId,
289
- sessionKey: params.sessionKey,
290
- messageChannel: params.messageChannel,
291
- messageProvider: params.messageProvider,
292
- agentAccountId: params.agentAccountId,
293
- authProfileId: lastProfileId,
294
- sessionFile: params.sessionFile,
295
- workspaceDir: params.workspaceDir,
296
- agentDir,
297
- config: params.config,
298
- skillsSnapshot: params.skillsSnapshot,
299
- provider,
300
- model: modelId,
301
- thinkLevel,
302
- reasoningLevel: params.reasoningLevel,
303
- bashElevated: params.bashElevated,
304
- extraSystemPrompt: params.extraSystemPrompt,
305
- ownerNumbers: params.ownerNumbers,
306
- });
307
- if (compactResult.compacted) {
308
- log.info(`auto-compaction succeeded for ${provider}/${modelId}; retrying prompt`);
309
- continue;
310
- }
311
- log.warn(`auto-compaction failed for ${provider}/${modelId}: ${compactResult.reason ?? "nothing to compact"}`);
281
+ // No auto-compaction. The rolling window strips tool calls and
282
+ // limits to 20 conversational turns, so overflow should not occur.
283
+ // If it does (e.g. extremely large single message), return the
284
+ // error and let the user /reset to start a new session.
285
+ if (!isCompactionFailure) {
286
+ log.warn(`context overflow despite rolling window for ${provider}/${modelId}; user should /reset`);
312
287
  }
313
288
  const kind = isCompactionFailure ? "compaction_failure" : "context_overflow";
314
289
  return {
@@ -1,7 +1,7 @@
1
1
  export { compactEmbeddedPiSession } from "./pi-embedded-runner/compact.js";
2
2
  export { applyExtraParamsToAgent, resolveExtraParams } from "./pi-embedded-runner/extra-params.js";
3
3
  export { applyGoogleTurnOrderingFix } from "./pi-embedded-runner/google.js";
4
- export { getDmHistoryLimitFromSessionKey, getEffectiveHistoryLimit, limitHistoryTurns, loadPreviousSessionMessages, } from "./pi-embedded-runner/history.js";
4
+ export { getDmHistoryLimitFromSessionKey, getEffectiveHistoryLimit, limitHistoryTurns, loadPreviousSessionMessages, stripToConversationMessages, } from "./pi-embedded-runner/history.js";
5
5
  export { resolveEmbeddedSessionLane } from "./pi-embedded-runner/lanes.js";
6
6
  export { runEmbeddedPiAgent } from "./pi-embedded-runner/run.js";
7
7
  export { abortEmbeddedPiRun, isEmbeddedPiRunActive, isEmbeddedPiRunStreaming, queueEmbeddedPiMessage, waitForEmbeddedPiRunEnd, } from "./pi-embedded-runner/runs.js";
@@ -29,6 +29,24 @@ function buildMemorySection(params) {
29
29
  "",
30
30
  ];
31
31
  }
32
+ function buildMessageHistorySection(params) {
33
+ if (params.isMinimal)
34
+ return [];
35
+ if (!params.availableTools.has("message_history"))
36
+ return [];
37
+ return [
38
+ "## Message History",
39
+ "When asked about recent messages, what was said, or conversation history from any channel (WhatsApp, webchat, groups):",
40
+ '- Use `message_history` — it reads the conversation archive directly and returns messages with accurate timestamps. Pass source="current" for this conversation, "admin" for admin/webchat, a phone number for a WhatsApp DM, or a group JID for group chat.',
41
+ '- Pass source="discover" to list all available conversations (with type and last-activity date) when you need to find which conversations exist.',
42
+ '- Pass source="all" to retrieve recent messages across all conversations at once — each message includes its source identifier.',
43
+ "- Filter with: search (text substring), date (YYYY-MM-DD), after/before (HH:MM time range within a date), channel (whatsapp/webchat/imessage).",
44
+ "- Do NOT use memory_search for recent message retrieval — it is semantic search and cannot reliably return the most recent messages or accurate timestamps.",
45
+ "- Do NOT use sessions_history for message retrieval — use it only for session management. message_history is the correct tool for looking up what was said.",
46
+ "- Never guess, fabricate, or infer message content or timestamps. If message_history returns no results, say so.",
47
+ "",
48
+ ];
49
+ }
32
50
  function buildUserIdentitySection(ownerLine, isMinimal) {
33
51
  if (!ownerLine || isMinimal)
34
52
  return [];
@@ -244,6 +262,7 @@ export function buildAgentSystemPrompt(params) {
244
262
  readToolName: skillReadToolName,
245
263
  });
246
264
  const memorySection = buildMemorySection({ isMinimal, availableTools });
265
+ const messageHistorySection = buildMessageHistorySection({ isMinimal, availableTools });
247
266
  const docsSection = buildDocsSection({
248
267
  docsPath: params.docsPath,
249
268
  isMinimal,
@@ -299,6 +318,7 @@ export function buildAgentSystemPrompt(params) {
299
318
  "",
300
319
  ...skillsSection,
301
320
  ...memorySection,
321
+ ...messageHistorySection,
302
322
  // Skip self-update for subagent/none modes
303
323
  hasGateway && !isMinimal ? "## Taskmaster Self-Update" : "",
304
324
  hasGateway && !isMinimal
@@ -8,6 +8,7 @@ import { createDocumentTool } from "./tools/document-tool.js";
8
8
  import { createGatewayTool } from "./tools/gateway-tool.js";
9
9
  import { createImageTool } from "./tools/image-tool.js";
10
10
  import { createMemoryGetTool, createMemorySaveMediaTool, createMemorySearchTool, createMemoryWriteTool, } from "./tools/memory-tool.js";
11
+ import { createMessageHistoryTool } from "./tools/message-history-tool.js";
11
12
  import { createMemoryReindexTool } from "./tools/memory-reindex-tool.js";
12
13
  import { createMessageTool } from "./tools/message-tool.js";
13
14
  import { createNodesTool } from "./tools/nodes-tool.js";
@@ -144,6 +145,7 @@ export function createTaskmasterTools(options) {
144
145
  const memoryWriteTool = createMemoryWriteTool(memoryToolOptions);
145
146
  const memorySaveMediaTool = createMemorySaveMediaTool(memoryToolOptions);
146
147
  const memoryReindexTool = createMemoryReindexTool(memoryToolOptions);
148
+ const messageHistoryTool = createMessageHistoryTool(memoryToolOptions);
147
149
  if (memorySearchTool)
148
150
  tools.push(memorySearchTool);
149
151
  if (memoryGetTool)
@@ -154,6 +156,8 @@ export function createTaskmasterTools(options) {
154
156
  tools.push(memorySaveMediaTool);
155
157
  if (memoryReindexTool)
156
158
  tools.push(memoryReindexTool);
159
+ if (messageHistoryTool)
160
+ tools.push(messageHistoryTool);
157
161
  const pluginTools = resolvePluginTools({
158
162
  context: {
159
163
  config: options?.config,
@@ -10,6 +10,7 @@ export const TOOL_GROUPS = {
10
10
  "memory_write",
11
11
  "memory_save_media",
12
12
  "memory_reindex",
13
+ "message_history",
13
14
  "document_read",
14
15
  ],
15
16
  "group:web": ["web_search", "web_fetch"],
@@ -54,6 +55,7 @@ export const TOOL_GROUPS = {
54
55
  "memory_search",
55
56
  "memory_get",
56
57
  "memory_write",
58
+ "message_history",
57
59
  "document_read",
58
60
  "web_search",
59
61
  "web_fetch",