@rubytech/taskmaster 1.0.51 → 1.0.53

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.
@@ -248,46 +248,60 @@ export const sessionsTranscriptHandlers = {
248
248
  continue;
249
249
  const agentId = extractAgentId(sessionKey);
250
250
  agentIds.add(agentId);
251
- const candidates = resolveSessionTranscriptCandidates(sessionId, storePath, sessionEntry.sessionFile, agentId);
252
- // Find first existing file
253
- let filePath;
254
- for (const candidate of candidates) {
255
- try {
256
- await fs.stat(candidate);
257
- filePath = candidate;
258
- break;
259
- }
260
- catch {
261
- // not found, try next
251
+ const sources = [{ sid: sessionId, file: sessionEntry.sessionFile }];
252
+ const prev = sessionEntry.previousSessions;
253
+ if (Array.isArray(prev)) {
254
+ // Include recent previous sessions (newest first, limit 3 to bound IO)
255
+ for (const p of prev.slice(-3).reverse()) {
256
+ if (p.sessionId)
257
+ sources.push({ sid: p.sessionId, file: p.sessionFile });
262
258
  }
263
259
  }
264
- if (!filePath)
265
- continue;
266
- const cursor = inputCursors[sessionKey];
267
- let result;
268
- try {
269
- result = await readTranscriptTail({
270
- filePath,
271
- cursor,
272
- maxBytes: maxBytesPerFile,
273
- });
274
- }
275
- catch {
276
- continue;
277
- }
278
- cursors[sessionKey] = result.newCursor;
279
- for (const line of result.lines) {
280
- if (!line.trim())
260
+ for (const source of sources) {
261
+ const cursorKey = sources.length > 1 && source.sid !== sessionId
262
+ ? `${sessionKey}:${source.sid}`
263
+ : sessionKey;
264
+ const candidates = resolveSessionTranscriptCandidates(source.sid, storePath, source.file, agentId);
265
+ // Find first existing file
266
+ let filePath;
267
+ for (const candidate of candidates) {
268
+ try {
269
+ await fs.stat(candidate);
270
+ filePath = candidate;
271
+ break;
272
+ }
273
+ catch {
274
+ // not found, try next
275
+ }
276
+ }
277
+ if (!filePath)
281
278
  continue;
282
- let parsed;
279
+ const cursor = inputCursors[cursorKey];
280
+ let result;
283
281
  try {
284
- parsed = JSON.parse(line);
282
+ result = await readTranscriptTail({
283
+ filePath,
284
+ cursor,
285
+ maxBytes: maxBytesPerFile,
286
+ });
285
287
  }
286
288
  catch {
287
289
  continue;
288
290
  }
289
- const expanded = expandLineToEntries(parsed, sessionId, sessionKey, agentId, result.fileMtimeMs, contentMaxChars);
290
- allEntries.push(...expanded);
291
+ cursors[cursorKey] = result.newCursor;
292
+ for (const line of result.lines) {
293
+ if (!line.trim())
294
+ continue;
295
+ let parsed;
296
+ try {
297
+ parsed = JSON.parse(line);
298
+ }
299
+ catch {
300
+ continue;
301
+ }
302
+ const expanded = expandLineToEntries(parsed, source.sid, sessionKey, agentId, result.fileMtimeMs, contentMaxChars);
303
+ allEntries.push(...expanded);
304
+ }
291
305
  }
292
306
  }
293
307
  // Sort by timestamp descending and truncate to limit
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/taskmaster",
3
- "version": "1.0.51",
3
+ "version": "1.0.53",
4
4
  "description": "AI-powered business assistant for small businesses",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -53,11 +53,13 @@ If they have additional phone numbers they want to authorize (e.g., a business p
53
53
 
54
54
  ## Step 6: Help with API Keys
55
55
 
56
- Two free API keys unlock important capabilities. Offer to walk the admin through getting them — you can use the browser to guide them through signup and show screenshots so they can follow along.
56
+ Two free API keys unlock important capabilities. Offer to set them up — you can do it yourself using the browser tool while the admin watches your progress on the **Browser page** of the Control UI.
57
57
 
58
58
  - **Google AI** (voice notes + video) — load the `google-ai` skill's `references/browser-setup.md` and follow its steps
59
59
  - **Tavily** (web search) — load the `tavily` skill's `references/browser-setup.md` and follow its steps. The admin can use the same Google email they just set up to register.
60
60
 
61
+ Explain that they can watch what you're doing in real-time by opening the **Browser** page from the navigation menu and clicking **Start** — this shows a live view of the browser you're controlling. They can also toggle **Input: ON** if they need to interact directly (e.g., to enter a password or complete a CAPTCHA).
62
+
61
63
  If the admin prefers to do it themselves later, they can manage API keys through the **Setup page** (API Keys section) — this requires logging in with the **admin PIN**, not an account PIN. Direct them to [app.tavily.com](https://app.tavily.com) for Tavily and [aistudio.google.com](https://aistudio.google.com) for Google AI.
62
64
 
63
65
  These keys are optional — the assistant works without them. Don't pressure. If the admin wants to skip this and come back later, that's fine.