@rubytech/taskmaster 1.0.92 → 1.0.95
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/taskmaster-tools.js +4 -4
- package/dist/agents/tool-policy.js +2 -2
- package/dist/agents/tools/contact-lookup-tool.js +45 -0
- package/dist/agents/tools/contact-update-tool.js +68 -0
- package/dist/agents/tools/memory-tool.js +10 -3
- package/dist/build-info.json +3 -3
- package/dist/cli/provision-seed.js +2 -2
- package/dist/control-ui/assets/{index-B7exVNNa.css → index-BWth4bv5.css} +1 -1
- package/dist/control-ui/assets/{index-hWMGux19.js → index-Bem0-Ojd.js} +220 -220
- package/dist/control-ui/assets/index-Bem0-Ojd.js.map +1 -0
- package/dist/control-ui/index.html +2 -2
- package/dist/gateway/chat-sanitize.js +121 -5
- package/dist/gateway/media-http.js +120 -0
- package/dist/gateway/public-chat-api.js +5 -3
- package/dist/gateway/server-http.js +3 -0
- package/dist/gateway/server-methods/chat.js +5 -3
- package/dist/infra/heartbeat-infra-alert.js +143 -0
- package/dist/infra/heartbeat-runner.js +13 -0
- package/dist/memory/manager.js +25 -8
- package/package.json +1 -1
- package/taskmaster-docs/USER-GUIDE.md +5 -5
- package/dist/control-ui/assets/index-hWMGux19.js.map +0 -1
|
@@ -22,8 +22,8 @@ import { createTtsTool } from "./tools/tts-tool.js";
|
|
|
22
22
|
import { createCurrentTimeTool } from "./tools/current-time.js";
|
|
23
23
|
import { createAuthorizeAdminTool, createListAdminsTool, createRevokeAdminTool, } from "./tools/authorize-admin-tool.js";
|
|
24
24
|
import { createLicenseGenerateTool } from "./tools/license-tool.js";
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
25
|
+
import { createContactLookupTool } from "./tools/contact-lookup-tool.js";
|
|
26
|
+
import { createContactUpdateTool } from "./tools/contact-update-tool.js";
|
|
27
27
|
import { createRelayMessageTool } from "./tools/relay-message-tool.js";
|
|
28
28
|
import { createSkillReadTool } from "./tools/skill-read-tool.js";
|
|
29
29
|
import { createApiKeysTool } from "./tools/apikeys-tool.js";
|
|
@@ -127,8 +127,8 @@ export function createTaskmasterTools(options) {
|
|
|
127
127
|
createRevokeAdminTool(),
|
|
128
128
|
createListAdminsTool(),
|
|
129
129
|
createLicenseGenerateTool(),
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
createContactLookupTool(),
|
|
131
|
+
createContactUpdateTool(),
|
|
132
132
|
createRelayMessageTool(),
|
|
133
133
|
createApiKeysTool(),
|
|
134
134
|
];
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { getRecord, listRecords, searchRecords } from "../../records/records-manager.js";
|
|
3
|
+
import { jsonResult } from "./common.js";
|
|
4
|
+
const ContactLookupSchema = Type.Object({
|
|
5
|
+
phone: Type.Optional(Type.String({
|
|
6
|
+
description: "Phone number to look up (e.g. '+447490553305'). Exact match.",
|
|
7
|
+
})),
|
|
8
|
+
name: Type.Optional(Type.String({
|
|
9
|
+
description: "Name to search for (partial match).",
|
|
10
|
+
})),
|
|
11
|
+
});
|
|
12
|
+
export function createContactLookupTool() {
|
|
13
|
+
return {
|
|
14
|
+
label: "Contact Lookup",
|
|
15
|
+
name: "contact_lookup",
|
|
16
|
+
description: "Look up a contact's verified record (payment status, account details). " +
|
|
17
|
+
"These records are managed by the business owner and cannot be modified by agents. " +
|
|
18
|
+
"Provide a phone number for exact lookup, a name for search, or no parameters to list all records.",
|
|
19
|
+
parameters: ContactLookupSchema,
|
|
20
|
+
execute: async (_toolCallId, args) => {
|
|
21
|
+
const params = args;
|
|
22
|
+
const phone = typeof params.phone === "string" ? params.phone.trim() : undefined;
|
|
23
|
+
const name = typeof params.name === "string" ? params.name.trim() : undefined;
|
|
24
|
+
if (!phone && !name) {
|
|
25
|
+
const all = listRecords();
|
|
26
|
+
if (all.length === 0) {
|
|
27
|
+
return jsonResult({ found: false, message: "No contact records exist yet." });
|
|
28
|
+
}
|
|
29
|
+
return jsonResult({ found: true, count: all.length, records: all });
|
|
30
|
+
}
|
|
31
|
+
if (phone) {
|
|
32
|
+
const record = getRecord(phone);
|
|
33
|
+
if (!record) {
|
|
34
|
+
return jsonResult({ found: false, message: `No record found for ${phone}.` });
|
|
35
|
+
}
|
|
36
|
+
return jsonResult({ found: true, record });
|
|
37
|
+
}
|
|
38
|
+
const results = searchRecords(name);
|
|
39
|
+
if (results.length === 0) {
|
|
40
|
+
return jsonResult({ found: false, message: `No records matching "${name}".` });
|
|
41
|
+
}
|
|
42
|
+
return jsonResult({ found: true, count: results.length, records: results });
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { getRecord, setRecordField, deleteRecordField } from "../../records/records-manager.js";
|
|
3
|
+
import { jsonResult } from "./common.js";
|
|
4
|
+
const ContactUpdateSchema = Type.Object({
|
|
5
|
+
phone: Type.String({
|
|
6
|
+
description: "Phone number (record ID) of the contact to update (e.g. '+447490553305').",
|
|
7
|
+
}),
|
|
8
|
+
field: Type.String({
|
|
9
|
+
description: "Field name to set or delete (e.g. 'license_key', 'notes').",
|
|
10
|
+
}),
|
|
11
|
+
value: Type.Optional(Type.String({
|
|
12
|
+
description: "Value to set. Omit to delete the field.",
|
|
13
|
+
})),
|
|
14
|
+
});
|
|
15
|
+
/**
|
|
16
|
+
* Contact record update tool — admin agent only.
|
|
17
|
+
*
|
|
18
|
+
* Allows the admin agent to write individual fields on contact records.
|
|
19
|
+
* The public agent does NOT have access to this tool (same gating as
|
|
20
|
+
* license_generate — not in any profile allow list).
|
|
21
|
+
*/
|
|
22
|
+
export function createContactUpdateTool() {
|
|
23
|
+
return {
|
|
24
|
+
label: "Contact Update",
|
|
25
|
+
name: "contact_update",
|
|
26
|
+
description: "Update a field on a contact's verified record. " +
|
|
27
|
+
"Use this to store license keys, notes, or other admin data against a contact. " +
|
|
28
|
+
"The contact must already exist (created via the Contacts admin page).",
|
|
29
|
+
parameters: ContactUpdateSchema,
|
|
30
|
+
execute: async (_toolCallId, args) => {
|
|
31
|
+
const params = args;
|
|
32
|
+
const phone = typeof params.phone === "string" ? params.phone.trim() : "";
|
|
33
|
+
const field = typeof params.field === "string" ? params.field.trim() : "";
|
|
34
|
+
const value = typeof params.value === "string" ? params.value : undefined;
|
|
35
|
+
if (!phone) {
|
|
36
|
+
return jsonResult({ error: "Phone number is required." });
|
|
37
|
+
}
|
|
38
|
+
if (!field) {
|
|
39
|
+
return jsonResult({ error: "Field name is required." });
|
|
40
|
+
}
|
|
41
|
+
const existing = getRecord(phone);
|
|
42
|
+
if (!existing) {
|
|
43
|
+
return jsonResult({
|
|
44
|
+
error: `No contact record found for ${phone}. Create one via the Contacts admin page first.`,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
if (value === undefined) {
|
|
48
|
+
const updated = deleteRecordField(phone, field);
|
|
49
|
+
return jsonResult({
|
|
50
|
+
ok: true,
|
|
51
|
+
action: "deleted",
|
|
52
|
+
phone,
|
|
53
|
+
field,
|
|
54
|
+
record: updated,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
const updated = setRecordField(phone, field, value);
|
|
58
|
+
return jsonResult({
|
|
59
|
+
ok: true,
|
|
60
|
+
action: "set",
|
|
61
|
+
phone,
|
|
62
|
+
field,
|
|
63
|
+
value,
|
|
64
|
+
record: updated,
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
@@ -25,6 +25,10 @@ const MemorySaveMediaSchema = Type.Object({
|
|
|
25
25
|
filename: Type.String({
|
|
26
26
|
description: "Destination filename with extension (e.g., 'leak-photo-2026-01-29.jpg')",
|
|
27
27
|
}),
|
|
28
|
+
destFolder: Type.Optional(Type.String({
|
|
29
|
+
description: "Destination folder relative to workspace (e.g., 'memory/admin/media'). " +
|
|
30
|
+
"Defaults to 'memory/users/{phone}/media' when omitted.",
|
|
31
|
+
})),
|
|
28
32
|
});
|
|
29
33
|
export function createMemorySearchTool(options) {
|
|
30
34
|
const cfg = options.config;
|
|
@@ -194,14 +198,16 @@ export function createMemorySaveMediaTool(options) {
|
|
|
194
198
|
return {
|
|
195
199
|
label: "Memory Save Media",
|
|
196
200
|
name: "memory_save_media",
|
|
197
|
-
description: "Save a media file (photo, document)
|
|
198
|
-
"Use this to preserve important
|
|
199
|
-
"
|
|
201
|
+
description: "Save a media file (photo, document) to persistent storage. " +
|
|
202
|
+
"Use this to preserve important photos (job sites, faults, completed work) for future reference. " +
|
|
203
|
+
"By default the file is stored in memory/users/{phone}/media/{filename}. " +
|
|
204
|
+
"Set destFolder to save elsewhere (e.g., 'memory/admin/media' for admin-scoped files). " +
|
|
200
205
|
"Provide a descriptive filename (e.g., 'boiler-fault-2026-01-29.jpg').",
|
|
201
206
|
parameters: MemorySaveMediaSchema,
|
|
202
207
|
execute: async (_toolCallId, params) => {
|
|
203
208
|
const sourcePath = readStringParam(params, "sourcePath", { required: true });
|
|
204
209
|
const filename = readStringParam(params, "filename", { required: true });
|
|
210
|
+
const destFolder = readStringParam(params, "destFolder");
|
|
205
211
|
const { manager, error } = await getMemorySearchManager({
|
|
206
212
|
cfg,
|
|
207
213
|
agentId,
|
|
@@ -213,6 +219,7 @@ export function createMemorySaveMediaTool(options) {
|
|
|
213
219
|
const result = await manager.writeMedia({
|
|
214
220
|
sourcePath,
|
|
215
221
|
destFilename: filename,
|
|
222
|
+
destFolder: destFolder || undefined,
|
|
216
223
|
sessionKey: options.agentSessionKey,
|
|
217
224
|
});
|
|
218
225
|
return jsonResult({ ...result, success: true });
|
package/dist/build-info.json
CHANGED
|
@@ -137,8 +137,8 @@ export function buildDefaultAgentList(workspaceRoot) {
|
|
|
137
137
|
"session_status",
|
|
138
138
|
"cron",
|
|
139
139
|
"license_generate",
|
|
140
|
-
"
|
|
141
|
-
"
|
|
140
|
+
"contact_lookup",
|
|
141
|
+
"contact_update",
|
|
142
142
|
"authorize_admin",
|
|
143
143
|
"revoke_admin",
|
|
144
144
|
"list_admins",
|