@rubytech/taskmaster 1.0.10 → 1.0.12
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/agents/pi-embedded-helpers/errors.js +6 -7
- package/dist/agents/pi-embedded-runner/compact.js +5 -0
- package/dist/agents/pi-embedded-runner/run/attempt.js +5 -0
- package/dist/agents/pi-embedded-runner/run/payloads.js +4 -4
- package/dist/agents/pi-embedded-runner/run.js +4 -4
- package/dist/agents/pi-tools.js +1 -0
- package/dist/agents/skills/workspace.js +40 -3
- package/dist/agents/system-prompt.js +12 -6
- package/dist/agents/taskmaster-tools.js +10 -0
- package/dist/agents/tool-display.json +5 -0
- package/dist/agents/tool-policy.js +1 -0
- package/dist/agents/tools/memory-reindex-tool.js +67 -0
- package/dist/agents/tools/skill-read-tool.js +75 -0
- package/dist/agents/workspace.js +2 -2
- package/dist/auto-reply/reply/agent-runner-execution.js +17 -40
- package/dist/auto-reply/reply/agent-runner.js +14 -24
- package/dist/auto-reply/reply/session.js +1 -1
- package/dist/build-info.json +3 -3
- package/dist/cli/gateway-cli/dev.js +1 -1
- package/dist/cli/provision-seed.js +1 -0
- package/dist/control-ui/assets/{index-Dcwiyz6o.js → index-D8ayJUWC.js} +205 -195
- package/dist/control-ui/assets/index-D8ayJUWC.js.map +1 -0
- package/dist/control-ui/assets/{index-DE-53MKi.css → index-dMMqL7A5.css} +1 -1
- package/dist/control-ui/index.html +2 -2
- package/dist/gateway/protocol/schema/sessions-transcript.js +1 -0
- package/dist/gateway/server-methods/memory.js +62 -0
- package/dist/gateway/server-methods/sessions-transcript.js +10 -9
- package/dist/gateway/server-methods.js +5 -1
- package/dist/memory/manager.js +17 -1
- package/dist/memory/memory-schema.js +23 -1
- package/dist/web/auto-reply/monitor.js +1 -1
- package/package.json +1 -1
- package/taskmaster-docs/USER-GUIDE.md +43 -12
- package/templates/customer/agents/admin/AGENTS.md +6 -5
- package/templates/customer/agents/admin/TOOLS.md +36 -0
- package/templates/taskmaster/agents/admin/AGENTS.md +7 -5
- package/templates/tradesupport/agents/admin/AGENTS.md +6 -5
- package/dist/control-ui/assets/index-Dcwiyz6o.js.map +0 -1
|
@@ -39,7 +39,7 @@ function extractTextFromContentBlocks(blocks) {
|
|
|
39
39
|
}
|
|
40
40
|
return parts.join("\n");
|
|
41
41
|
}
|
|
42
|
-
function expandLineToEntries(line, sessionId, sessionKey, agentId, fileMtimeMs) {
|
|
42
|
+
function expandLineToEntries(line, sessionId, sessionKey, agentId, fileMtimeMs, maxChars = CONTENT_MAX_CHARS) {
|
|
43
43
|
const entries = [];
|
|
44
44
|
const ts = resolveTimestamp(line, fileMtimeMs);
|
|
45
45
|
const model = line.message?.model;
|
|
@@ -57,7 +57,7 @@ function expandLineToEntries(line, sessionId, sessionKey, agentId, fileMtimeMs)
|
|
|
57
57
|
agentId,
|
|
58
58
|
timestamp: ts,
|
|
59
59
|
type: "error",
|
|
60
|
-
content: truncate(content,
|
|
60
|
+
content: truncate(content, maxChars),
|
|
61
61
|
...(model ? { model } : {}),
|
|
62
62
|
});
|
|
63
63
|
return entries;
|
|
@@ -74,7 +74,7 @@ function expandLineToEntries(line, sessionId, sessionKey, agentId, fileMtimeMs)
|
|
|
74
74
|
agentId,
|
|
75
75
|
timestamp: ts,
|
|
76
76
|
type: "tool",
|
|
77
|
-
content: truncate(content,
|
|
77
|
+
content: truncate(content, maxChars),
|
|
78
78
|
...(line.toolName ? { toolName: line.toolName } : {}),
|
|
79
79
|
...(model ? { model } : {}),
|
|
80
80
|
});
|
|
@@ -93,7 +93,7 @@ function expandLineToEntries(line, sessionId, sessionKey, agentId, fileMtimeMs)
|
|
|
93
93
|
agentId,
|
|
94
94
|
timestamp: ts,
|
|
95
95
|
type: entryType,
|
|
96
|
-
content: truncate(msg.content,
|
|
96
|
+
content: truncate(msg.content, maxChars),
|
|
97
97
|
...(model ? { model } : {}),
|
|
98
98
|
});
|
|
99
99
|
return entries;
|
|
@@ -113,7 +113,7 @@ function expandLineToEntries(line, sessionId, sessionKey, agentId, fileMtimeMs)
|
|
|
113
113
|
agentId,
|
|
114
114
|
timestamp: ts,
|
|
115
115
|
type: "thinking",
|
|
116
|
-
content: truncate(text,
|
|
116
|
+
content: truncate(text, maxChars),
|
|
117
117
|
...(model ? { model } : {}),
|
|
118
118
|
});
|
|
119
119
|
}
|
|
@@ -127,7 +127,7 @@ function expandLineToEntries(line, sessionId, sessionKey, agentId, fileMtimeMs)
|
|
|
127
127
|
agentId,
|
|
128
128
|
timestamp: ts,
|
|
129
129
|
type: "tool",
|
|
130
|
-
content: truncate(content,
|
|
130
|
+
content: truncate(content, maxChars),
|
|
131
131
|
...(toolName ? { toolName } : {}),
|
|
132
132
|
...(model ? { model } : {}),
|
|
133
133
|
});
|
|
@@ -143,7 +143,7 @@ function expandLineToEntries(line, sessionId, sessionKey, agentId, fileMtimeMs)
|
|
|
143
143
|
agentId,
|
|
144
144
|
timestamp: ts,
|
|
145
145
|
type: entryType,
|
|
146
|
-
content: truncate(text,
|
|
146
|
+
content: truncate(text, maxChars),
|
|
147
147
|
...(model ? { model } : {}),
|
|
148
148
|
});
|
|
149
149
|
}
|
|
@@ -161,7 +161,7 @@ function expandLineToEntries(line, sessionId, sessionKey, agentId, fileMtimeMs)
|
|
|
161
161
|
agentId,
|
|
162
162
|
timestamp: ts,
|
|
163
163
|
type: entryType,
|
|
164
|
-
content: truncate(text,
|
|
164
|
+
content: truncate(text, maxChars),
|
|
165
165
|
...(model ? { model } : {}),
|
|
166
166
|
});
|
|
167
167
|
}
|
|
@@ -217,6 +217,7 @@ export const sessionsTranscriptHandlers = {
|
|
|
217
217
|
const limit = p.limit ?? DEFAULT_LIMIT;
|
|
218
218
|
const maxBytesPerFile = p.maxBytesPerFile ?? DEFAULT_MAX_BYTES_PER_FILE;
|
|
219
219
|
const inputCursors = p.cursors ?? {};
|
|
220
|
+
const contentMaxChars = p.full ? Infinity : CONTENT_MAX_CHARS;
|
|
220
221
|
const agentFilter = p.agents && p.agents.length > 0 ? new Set(p.agents) : null;
|
|
221
222
|
try {
|
|
222
223
|
const cfg = loadConfig();
|
|
@@ -285,7 +286,7 @@ export const sessionsTranscriptHandlers = {
|
|
|
285
286
|
catch {
|
|
286
287
|
continue;
|
|
287
288
|
}
|
|
288
|
-
const expanded = expandLineToEntries(parsed, sessionId, sessionKey, agentId, result.fileMtimeMs);
|
|
289
|
+
const expanded = expandLineToEntries(parsed, sessionId, sessionKey, agentId, result.fileMtimeMs, contentMaxChars);
|
|
289
290
|
allEntries.push(...expanded);
|
|
290
291
|
}
|
|
291
292
|
}
|
|
@@ -16,6 +16,7 @@ import { filesHandlers } from "./server-methods/files.js";
|
|
|
16
16
|
import { healthHandlers } from "./server-methods/health.js";
|
|
17
17
|
import { licenseHandlers } from "./server-methods/license.js";
|
|
18
18
|
import { logsHandlers } from "./server-methods/logs.js";
|
|
19
|
+
import { memoryHandlers } from "./server-methods/memory.js";
|
|
19
20
|
import { recordsHandlers } from "./server-methods/records.js";
|
|
20
21
|
import { modelsHandlers } from "./server-methods/models.js";
|
|
21
22
|
import { nodeHandlers } from "./server-methods/nodes.js";
|
|
@@ -88,6 +89,7 @@ const READ_METHODS = new Set([
|
|
|
88
89
|
"records.search",
|
|
89
90
|
"workspaces.list",
|
|
90
91
|
"workspaces.scan",
|
|
92
|
+
"memory.status",
|
|
91
93
|
]);
|
|
92
94
|
const WRITE_METHODS = new Set([
|
|
93
95
|
"send",
|
|
@@ -172,7 +174,8 @@ function authorizeGatewayMethod(method, client) {
|
|
|
172
174
|
method === "records.setField" ||
|
|
173
175
|
method === "records.deleteField" ||
|
|
174
176
|
method === "workspaces.create" ||
|
|
175
|
-
method === "workspaces.remove"
|
|
177
|
+
method === "workspaces.remove" ||
|
|
178
|
+
method === "memory.reindex") {
|
|
176
179
|
return errorShape(ErrorCodes.INVALID_REQUEST, "missing scope: operator.admin");
|
|
177
180
|
}
|
|
178
181
|
return errorShape(ErrorCodes.INVALID_REQUEST, "missing scope: operator.admin");
|
|
@@ -209,6 +212,7 @@ export const coreGatewayHandlers = {
|
|
|
209
212
|
...filesHandlers,
|
|
210
213
|
...browserScreencastHandlers,
|
|
211
214
|
...licenseHandlers,
|
|
215
|
+
...memoryHandlers,
|
|
212
216
|
...recordsHandlers,
|
|
213
217
|
...workspacesHandlers,
|
|
214
218
|
};
|
package/dist/memory/manager.js
CHANGED
|
@@ -1297,6 +1297,8 @@ export class MemoryIndexManager {
|
|
|
1297
1297
|
}
|
|
1298
1298
|
const vectorReady = await this.ensureVectorReady();
|
|
1299
1299
|
const meta = this.readMeta();
|
|
1300
|
+
const sourcesChanged = meta?.sources != null &&
|
|
1301
|
+
JSON.stringify([...meta.sources].sort()) !== JSON.stringify([...this.sources].sort());
|
|
1300
1302
|
const needsFullReindex = params?.force ||
|
|
1301
1303
|
!meta ||
|
|
1302
1304
|
meta.model !== this.provider.model ||
|
|
@@ -1304,7 +1306,16 @@ export class MemoryIndexManager {
|
|
|
1304
1306
|
meta.providerKey !== this.providerKey ||
|
|
1305
1307
|
meta.chunkTokens !== this.settings.chunking.tokens ||
|
|
1306
1308
|
meta.chunkOverlap !== this.settings.chunking.overlap ||
|
|
1307
|
-
(vectorReady && !meta?.vectorDims)
|
|
1309
|
+
(vectorReady && !meta?.vectorDims) ||
|
|
1310
|
+
sourcesChanged;
|
|
1311
|
+
// Detect missing memory index: source enabled but no files indexed (legacy DB or failed initial sync)
|
|
1312
|
+
if (!needsFullReindex && this.sources.has("memory") && !this.dirty) {
|
|
1313
|
+
const memoryFileCount = this.db.prepare("SELECT COUNT(*) as c FROM files WHERE source = ?").get("memory").c;
|
|
1314
|
+
if (memoryFileCount === 0) {
|
|
1315
|
+
log.info("memory source enabled but no memory files indexed — marking dirty");
|
|
1316
|
+
this.dirty = true;
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1308
1319
|
try {
|
|
1309
1320
|
if (needsFullReindex) {
|
|
1310
1321
|
await this.runSafeReindex({
|
|
@@ -1331,6 +1342,10 @@ export class MemoryIndexManager {
|
|
|
1331
1342
|
else {
|
|
1332
1343
|
this.sessionsDirty = false;
|
|
1333
1344
|
}
|
|
1345
|
+
// Persist sources to meta if missing (backfill for legacy databases)
|
|
1346
|
+
if (meta && !meta.sources) {
|
|
1347
|
+
this.writeMeta({ ...meta, sources: Array.from(this.sources) });
|
|
1348
|
+
}
|
|
1334
1349
|
}
|
|
1335
1350
|
catch (err) {
|
|
1336
1351
|
const reason = err instanceof Error ? err.message : String(err);
|
|
@@ -1455,6 +1470,7 @@ export class MemoryIndexManager {
|
|
|
1455
1470
|
providerKey: this.providerKey,
|
|
1456
1471
|
chunkTokens: this.settings.chunking.tokens,
|
|
1457
1472
|
chunkOverlap: this.settings.chunking.overlap,
|
|
1473
|
+
sources: Array.from(this.sources),
|
|
1458
1474
|
};
|
|
1459
1475
|
if (this.vector.available && this.vector.dims) {
|
|
1460
1476
|
nextMeta.vectorDims = this.vector.dims;
|
|
@@ -60,6 +60,10 @@ export function ensureMemoryIndexSchema(params) {
|
|
|
60
60
|
const message = err instanceof Error ? err.message : String(err);
|
|
61
61
|
ftsAvailable = false;
|
|
62
62
|
ftsError = message;
|
|
63
|
+
// Drop orphaned FTS shadow tables when the fts5 module is unavailable.
|
|
64
|
+
// Leaving them in the DB can cause "no such module: fts5" errors on
|
|
65
|
+
// unrelated operations if SQLite touches the virtual table machinery.
|
|
66
|
+
dropOrphanedFtsTables(params.db, params.ftsTable);
|
|
63
67
|
}
|
|
64
68
|
}
|
|
65
69
|
ensureColumn(params.db, "files", "source", "TEXT NOT NULL DEFAULT 'memory'");
|
|
@@ -68,9 +72,27 @@ export function ensureMemoryIndexSchema(params) {
|
|
|
68
72
|
params.db.exec(`CREATE INDEX IF NOT EXISTS idx_chunks_source ON chunks(source);`);
|
|
69
73
|
return { ftsAvailable, ...(ftsError ? { ftsError } : {}) };
|
|
70
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* When fts5 module is unavailable but the virtual table and its shadow tables
|
|
77
|
+
* exist from a previous run, drop them to prevent "no such module" errors.
|
|
78
|
+
* Shadow tables follow the pattern: {ftsTable}_config, _content, _data, _docsize, _idx.
|
|
79
|
+
*/
|
|
80
|
+
function dropOrphanedFtsTables(db, ftsTable) {
|
|
81
|
+
const shadowSuffixes = ["_config", "_content", "_data", "_docsize", "_idx"];
|
|
82
|
+
for (const suffix of shadowSuffixes) {
|
|
83
|
+
try {
|
|
84
|
+
db.prepare(`DROP TABLE IF EXISTS ${ftsTable}${suffix}`).run();
|
|
85
|
+
}
|
|
86
|
+
catch { }
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
db.prepare(`DROP TABLE IF EXISTS ${ftsTable}`).run();
|
|
90
|
+
}
|
|
91
|
+
catch { }
|
|
92
|
+
}
|
|
71
93
|
function ensureColumn(db, table, column, definition) {
|
|
72
94
|
const rows = db.prepare(`PRAGMA table_info(${table})`).all();
|
|
73
95
|
if (rows.some((row) => row.name === column))
|
|
74
96
|
return;
|
|
75
|
-
db.
|
|
97
|
+
db.prepare(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`).run();
|
|
76
98
|
}
|
|
@@ -230,7 +230,7 @@ export async function monitorWebChannel(verbose, listenerFactory = monitorWebInb
|
|
|
230
230
|
heartbeatLogger.warn(logData, "⚠️ web gateway heartbeat - no messages in 30+ minutes");
|
|
231
231
|
}
|
|
232
232
|
else {
|
|
233
|
-
heartbeatLogger.
|
|
233
|
+
heartbeatLogger.debug(logData, "web gateway heartbeat");
|
|
234
234
|
}
|
|
235
235
|
}, heartbeatSeconds * 1000);
|
|
236
236
|
watchdogTimer = setInterval(() => {
|
package/package.json
CHANGED
|
@@ -38,7 +38,7 @@ You'll need a monitor, keyboard, and mouse connected to the Pi.
|
|
|
38
38
|
1. Open **Terminal** from the desktop taskbar (or press Ctrl+Alt+T)
|
|
39
39
|
2. Run:
|
|
40
40
|
|
|
41
|
-
```
|
|
41
|
+
```bash
|
|
42
42
|
curl -fsSL https://taskmaster.bot/install.sh | sudo bash
|
|
43
43
|
```
|
|
44
44
|
|
|
@@ -51,7 +51,7 @@ curl -fsSL https://taskmaster.bot/install.sh | sudo bash
|
|
|
51
51
|
|
|
52
52
|
Open **Terminal** (search for "Terminal" in Spotlight) and run:
|
|
53
53
|
|
|
54
|
-
```
|
|
54
|
+
```bash
|
|
55
55
|
curl -fsSL https://taskmaster.bot/install.sh | sudo bash
|
|
56
56
|
```
|
|
57
57
|
|
|
@@ -59,10 +59,12 @@ This installs Node.js (if needed), Taskmaster, and sets up the background servic
|
|
|
59
59
|
|
|
60
60
|
**Custom port:** If you're running multiple Taskmaster instances (e.g., one on a Pi and one on a Mac), give each a different port:
|
|
61
61
|
|
|
62
|
-
```
|
|
62
|
+
```bash
|
|
63
63
|
curl -fsSL https://taskmaster.bot/install.sh | sudo bash -s -- --port 19000
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
When using a custom port, the hostname includes the port to avoid conflicts. The setup URL becomes `http://taskmaster-19000.local:19000/setup`.
|
|
67
|
+
|
|
66
68
|
### Option D: Install from a package file
|
|
67
69
|
|
|
68
70
|
If you received a `.tgz` package file (for offline install or when the install script isn't available):
|
|
@@ -70,7 +72,7 @@ If you received a `.tgz` package file (for offline install or when the install s
|
|
|
70
72
|
1. **Install Node.js** (version 22 or later) from [nodejs.org](https://nodejs.org) if you don't have it
|
|
71
73
|
2. Open a terminal and run:
|
|
72
74
|
|
|
73
|
-
```
|
|
75
|
+
```bash
|
|
74
76
|
npm install -g ~/Downloads/rubytech-taskmaster-2026.2.14.tgz
|
|
75
77
|
taskmaster provision
|
|
76
78
|
```
|
|
@@ -263,6 +265,8 @@ Your assistant can send messages, images, and reactions on your behalf — and r
|
|
|
263
265
|
|
|
264
266
|
Your assistant can search, read, and update your business knowledge. It has full file access within your account workspace — it can create, read, update, and organise files. Files uploaded or dragged onto the Files page are automatically indexed for search.
|
|
265
267
|
|
|
268
|
+
The Files page shows a **status indicator** next to the Re-index button — a green light means the index is up to date, red means files have changed since the last index. The indicator also shows the number of indexed files and chunks. If the light is red or search results seem stale, click **Re-index** to rebuild the search index.
|
|
269
|
+
|
|
266
270
|
| Capability | Description |
|
|
267
271
|
|------------|-------------|
|
|
268
272
|
| Search knowledge | Find information across all your business files and notes |
|
|
@@ -345,6 +349,32 @@ Your assistant can manage recurring tasks, reminders, and automated routines. Yo
|
|
|
345
349
|
- "Set up a daily briefing at 7am every weekday"
|
|
346
350
|
- "Create a weekly reminder to check stock levels every Monday"
|
|
347
351
|
|
|
352
|
+
### Proactive Outreach
|
|
353
|
+
|
|
354
|
+
Your assistant doesn't just respond to incoming messages — it reaches out on your behalf to win work, chase payments, and keep customers engaged.
|
|
355
|
+
|
|
356
|
+
| Capability | Description |
|
|
357
|
+
|------------|-------------|
|
|
358
|
+
| Quote follow-up | Automatically nudges customers who haven't responded to a quote (default: 3 days) |
|
|
359
|
+
| Invoice reminders | Sends friendly payment reminders when invoices are overdue |
|
|
360
|
+
| Service reminders | Contacts past customers when it's time for a repeat service or annual check |
|
|
361
|
+
| Morning briefings | Sends you a daily schedule summary with jobs, pending quotes, and overdue invoices |
|
|
362
|
+
| ETA updates | Proactively tells customers when you're running late, before they call to ask |
|
|
363
|
+
| Re-engagement | Follows up on old enquiries to see if a customer is still interested |
|
|
364
|
+
|
|
365
|
+
**How it works:**
|
|
366
|
+
|
|
367
|
+
Your assistant learns your customers, their service history, and your pricing through normal conversations. It then uses scheduled events (visible under **Events** on the Advanced page) to trigger outreach at the right time. You don't need to configure anything manually — the assistant sets up follow-ups as part of its normal workflow.
|
|
368
|
+
|
|
369
|
+
**What you can customise:**
|
|
370
|
+
|
|
371
|
+
- Quote follow-up timing — tell your assistant "follow up on quotes after 5 days instead of 3"
|
|
372
|
+
- Invoice reminder timing — "send invoice reminders after 7 days"
|
|
373
|
+
- Morning briefing time — "send my briefing at 6:30am instead of 7am"
|
|
374
|
+
- Service reminder intervals — "remind customers about annual services 11 months after their last visit"
|
|
375
|
+
|
|
376
|
+
All outreach messages are sent as your assistant — customers reply normally and the conversation continues.
|
|
377
|
+
|
|
348
378
|
### Conversations & Sessions
|
|
349
379
|
|
|
350
380
|
Your assistant can review conversation history and check what customers have been asking about.
|
|
@@ -451,7 +481,7 @@ The **Files** page shows your assistant's knowledge — everything it knows abou
|
|
|
451
481
|
|
|
452
482
|
All files are markdown (`.md`) — plain text with simple formatting. You can upload new files by dragging them onto the Files page.
|
|
453
483
|
|
|
454
|
-
When you add or change a file, your assistant picks it up automatically — no restart needed.
|
|
484
|
+
When you add or change a file, your assistant picks it up automatically — no restart needed. The status light on the Files page turns red when files have changed since the last index, so you can see at a glance whether a re-index is needed.
|
|
455
485
|
|
|
456
486
|
---
|
|
457
487
|
|
|
@@ -664,7 +694,7 @@ iMessage support requires two things on your Mac **before** running Taskmaster s
|
|
|
664
694
|
Homebrew needs a current version of Xcode to compile the iMessage helper. Check which situation applies to you:
|
|
665
695
|
|
|
666
696
|
- **If you don't have Xcode at all** — open Terminal and run:
|
|
667
|
-
```
|
|
697
|
+
```bash
|
|
668
698
|
xcode-select --install
|
|
669
699
|
```
|
|
670
700
|
A dialog will appear — click **Install** and wait for it to finish.
|
|
@@ -672,13 +702,13 @@ iMessage support requires two things on your Mac **before** running Taskmaster s
|
|
|
672
702
|
- **If you have Xcode from the App Store but it's outdated** — open the **App Store**, find Xcode, and click **Update**. This is the most common issue.
|
|
673
703
|
|
|
674
704
|
- **If you don't want to update Xcode** — you can tell your Mac to use the standalone Command Line Tools instead (faster, no large download). Open Terminal and run:
|
|
675
|
-
```
|
|
705
|
+
```bash
|
|
676
706
|
sudo xcode-select --switch /Library/Developer/CommandLineTools
|
|
677
707
|
```
|
|
678
708
|
Enter your password when prompted. This leaves Xcode.app untouched but tells Homebrew to use the lightweight tools.
|
|
679
709
|
|
|
680
710
|
2. **Homebrew** — if you don't already have it, open Terminal and run:
|
|
681
|
-
```
|
|
711
|
+
```bash
|
|
682
712
|
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
683
713
|
```
|
|
684
714
|
|
|
@@ -700,7 +730,7 @@ Taskmaster's iMessage helper needs permission to read the Messages database. mac
|
|
|
700
730
|
|
|
701
731
|
Some Homebrew-installed binaries are unsigned. macOS Full Disk Access silently rejects unsigned binaries — they won't appear in the list even after you add them. Open Terminal and run:
|
|
702
732
|
|
|
703
|
-
```
|
|
733
|
+
```bash
|
|
704
734
|
sudo codesign --force --sign - $(realpath $(which imsg))
|
|
705
735
|
sudo codesign --force --sign - $(realpath $(which node))
|
|
706
736
|
```
|
|
@@ -722,7 +752,7 @@ You can verify it worked by running `imsg chats --limit 5` in Terminal — if yo
|
|
|
722
752
|
The gateway runs as a background service using Node.js. Terminal's access doesn't apply to background services, so Node.js needs its own entry.
|
|
723
753
|
|
|
724
754
|
1. Open Terminal and run:
|
|
725
|
-
```
|
|
755
|
+
```bash
|
|
726
756
|
realpath $(which node)
|
|
727
757
|
```
|
|
728
758
|
This prints the real path — something like `/usr/local/Cellar/node/23.3.0/bin/node` or `/Users/you/.nvm/versions/node/v22.22.0/bin/node`.
|
|
@@ -752,7 +782,7 @@ This means Homebrew found an outdated Xcode.app on your Mac. Three options:
|
|
|
752
782
|
|
|
753
783
|
1. **Update Xcode** — open the App Store and update Xcode
|
|
754
784
|
2. **Switch to Command Line Tools** (no download needed) — open Terminal and run:
|
|
755
|
-
```
|
|
785
|
+
```bash
|
|
756
786
|
sudo xcode-select --switch /Library/Developer/CommandLineTools
|
|
757
787
|
```
|
|
758
788
|
3. **Install Command Line Tools** (if you don't have them) — run `xcode-select --install`
|
|
@@ -805,7 +835,8 @@ You need the IP address to connect from another device on your network (e.g., SS
|
|
|
805
835
|
**From your Mac or PC** (without a monitor on the Pi):
|
|
806
836
|
|
|
807
837
|
- **Before install:** Run `ping -c 1 raspberrypi.local` — a fresh Pi advertises this hostname by default
|
|
808
|
-
- **After install:** Run `ping -c 1 taskmaster.local` — the install changes the hostname to `taskmaster`
|
|
838
|
+
- **After install (default port):** Run `ping -c 1 taskmaster.local` — the install changes the hostname to `taskmaster`
|
|
839
|
+
- **After install (custom port):** Run `ping -c 1 taskmaster-19000.local` — when using `--port 19000`, the hostname includes the port
|
|
809
840
|
- **Router:** Check your router's admin page (usually `192.168.1.1`) — look for a device called "taskmaster" or "raspberrypi" in the connected devices list
|
|
810
841
|
|
|
811
842
|
Once you have the IP, you can access the setup page at `http://<your-pi-ip>:18789/setup` or connect via SSH with `ssh pi@<your-pi-ip>`.
|
|
@@ -42,14 +42,15 @@ Use the owner's name naturally in conversation (you'll find it in USER.md).
|
|
|
42
42
|
|
|
43
43
|
---
|
|
44
44
|
|
|
45
|
-
## Activity
|
|
45
|
+
## Activity & Recent History
|
|
46
46
|
|
|
47
|
-
When asked about "activity", "what
|
|
47
|
+
When asked about "activity", "what happened", or similar:
|
|
48
48
|
|
|
49
|
-
1. **
|
|
50
|
-
2. **
|
|
49
|
+
1. **Your conversation log first** — `memory/admin/conversations/YYYY-MM.md` is your own record of what you said and did. This is the most complete source, especially when sessions have been reset.
|
|
50
|
+
2. **Sessions (current + previous)** — use `sessions_list` to see active sessions. Each entry may have a `previousSessions` array listing archived sessions. Pass a previous `sessionId` to `sessions_history` to read its transcript.
|
|
51
|
+
3. **Memory** — notes, decisions, and summaries you stored about what happened.
|
|
51
52
|
|
|
52
|
-
|
|
53
|
+
Do not rely solely on the current session. Sessions reset on `/new`, auto-recovery, and expiry — always check your conversation log and `previousSessions` for the full picture.
|
|
53
54
|
|
|
54
55
|
---
|
|
55
56
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# TOOLS.md - Local Notes
|
|
2
|
+
|
|
3
|
+
Skills define *how* tools work. This file is for *your* specifics — the stuff that's unique to your setup.
|
|
4
|
+
|
|
5
|
+
## What Goes Here
|
|
6
|
+
|
|
7
|
+
Things like:
|
|
8
|
+
- Camera names and locations
|
|
9
|
+
- SSH hosts and aliases
|
|
10
|
+
- Preferred voices for TTS
|
|
11
|
+
- Speaker/room names
|
|
12
|
+
- Device nicknames
|
|
13
|
+
- Anything environment-specific
|
|
14
|
+
|
|
15
|
+
## Examples
|
|
16
|
+
|
|
17
|
+
```markdown
|
|
18
|
+
### Cameras
|
|
19
|
+
- living-room → Main area, 180° wide angle
|
|
20
|
+
- front-door → Entrance, motion-triggered
|
|
21
|
+
|
|
22
|
+
### SSH
|
|
23
|
+
- home-server → 192.168.1.100, user: admin
|
|
24
|
+
|
|
25
|
+
### TTS
|
|
26
|
+
- Preferred voice: "Nova" (warm, slightly British)
|
|
27
|
+
- Default speaker: Kitchen HomePod
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Why Separate?
|
|
31
|
+
|
|
32
|
+
Skills are shared. Your setup is yours. Keeping them apart means you can update skills without losing your notes, and share skills without leaking your infrastructure.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
Add whatever helps you do your job. This is your cheat sheet.
|
|
@@ -11,14 +11,15 @@ Before doing anything else:
|
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
-
## Activity
|
|
14
|
+
## Activity & Recent History
|
|
15
15
|
|
|
16
|
-
When asked about "activity", "what
|
|
16
|
+
When asked about "activity", "what happened", or similar:
|
|
17
17
|
|
|
18
|
-
1. **
|
|
19
|
-
2. **
|
|
18
|
+
1. **Your conversation log first** — `memory/admin/conversations/YYYY-MM.md` is your own record of what you said and did. This is the most complete source, especially when sessions have been reset.
|
|
19
|
+
2. **Sessions (current + previous)** — use `sessions_list` to see active sessions. Each entry may have a `previousSessions` array listing archived sessions. Pass a previous `sessionId` to `sessions_history` to read its transcript.
|
|
20
|
+
3. **Memory** — notes, decisions, and summaries you stored about what happened.
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
Do not rely solely on the current session. Sessions reset on `/new`, auto-recovery, and expiry — always check your conversation log and `previousSessions` for the full picture.
|
|
22
23
|
|
|
23
24
|
## Multi-Channel
|
|
24
25
|
|
|
@@ -48,6 +49,7 @@ You have access to everything. Use it.
|
|
|
48
49
|
Full access to all memory:
|
|
49
50
|
- **Store:** Use `memory_write` freely
|
|
50
51
|
- **Retrieve:** Use `memory_search` for any context
|
|
52
|
+
- **Reindex:** Use `memory_reindex` with action `reindex` to rebuild the search index, or `status` to check index health
|
|
51
53
|
- **Cross-agent:** You can see the public agent's conversations
|
|
52
54
|
|
|
53
55
|
### Finding Other Conversations
|
|
@@ -42,14 +42,15 @@ Use the owner's name naturally in conversation (you'll find it in USER.md).
|
|
|
42
42
|
|
|
43
43
|
---
|
|
44
44
|
|
|
45
|
-
## Activity
|
|
45
|
+
## Activity & Recent History
|
|
46
46
|
|
|
47
|
-
When asked about "activity", "what
|
|
47
|
+
When asked about "activity", "what happened", or similar:
|
|
48
48
|
|
|
49
|
-
1. **
|
|
50
|
-
2. **
|
|
49
|
+
1. **Your conversation log first** — `memory/admin/conversations/YYYY-MM.md` is your own record of what you said and did. This is the most complete source, especially when sessions have been reset.
|
|
50
|
+
2. **Sessions (current + previous)** — use `sessions_list` to see active sessions. Each entry may have a `previousSessions` array listing archived sessions. Pass a previous `sessionId` to `sessions_history` to read its transcript.
|
|
51
|
+
3. **Memory** — notes, decisions, and summaries you stored about what happened.
|
|
51
52
|
|
|
52
|
-
|
|
53
|
+
Do not rely solely on the current session. Sessions reset on `/new`, auto-recovery, and expiry — always check your conversation log and `previousSessions` for the full picture.
|
|
53
54
|
|
|
54
55
|
---
|
|
55
56
|
|