@rubytech/taskmaster 1.17.6 → 1.17.7

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.
@@ -38,6 +38,8 @@ import { createBrandSettingsTool } from "./tools/brand-settings-tool.js";
38
38
  import { createChannelSettingsTool } from "./tools/channel-settings-tool.js";
39
39
  import { createImageGenerateTool } from "./tools/image-generate-tool.js";
40
40
  import { createLogsReadTool } from "./tools/logs-read-tool.js";
41
+ import { createNetworkSettingsTool } from "./tools/network-settings-tool.js";
42
+ import { createWifiSettingsTool } from "./tools/wifi-settings-tool.js";
41
43
  import { createOpeningHoursTool } from "./tools/opening-hours-tool.js";
42
44
  import { createPublicChatSettingsTool } from "./tools/public-chat-settings-tool.js";
43
45
  import { createSkillManageTool } from "./tools/skill-manage-tool.js";
@@ -172,6 +174,8 @@ export function createTaskmasterTools(options) {
172
174
  createPublicChatSettingsTool(),
173
175
  createSkillManageTool(),
174
176
  createLogsReadTool(),
177
+ createNetworkSettingsTool(),
178
+ createWifiSettingsTool(),
175
179
  createFileDeleteTool({
176
180
  config: options?.config,
177
181
  agentSessionKey: options?.agentSessionKey,
@@ -56,6 +56,8 @@ export const TOOL_GROUPS = {
56
56
  "public_chat_settings",
57
57
  "skill_manage",
58
58
  "logs_read",
59
+ "network_settings",
60
+ "wifi_settings",
59
61
  ],
60
62
  // All Taskmaster native tools (excludes provider plugins).
61
63
  "group:taskmaster": [
@@ -100,6 +102,8 @@ export const TOOL_GROUPS = {
100
102
  "public_chat_settings",
101
103
  "skill_manage",
102
104
  "logs_read",
105
+ "network_settings",
106
+ "wifi_settings",
103
107
  ],
104
108
  };
105
109
  // Tools that are never granted by profiles — must be explicitly added to the
@@ -16,6 +16,9 @@ const CHANNEL_SETTINGS_ACTIONS = [
16
16
  "set_thinking",
17
17
  "set_dm_policy",
18
18
  "set_group_policy",
19
+ "set_mention_required",
20
+ "logout",
21
+ "set_imessage_owner",
19
22
  ];
20
23
  const DM_POLICY_VALUES = ["open", "closed"];
21
24
  const GROUP_POLICY_VALUES = ["open", "disabled", "allowlist"];
@@ -25,7 +28,10 @@ const ChannelSettingsSchema = Type.Object({
25
28
  '"set_model" changes the AI model for a WhatsApp account. ' +
26
29
  '"set_thinking" changes the thinking level. ' +
27
30
  '"set_dm_policy" sets whether public DMs are handled (open/closed). ' +
28
- '"set_group_policy" sets group chat mode (open/disabled/allowlist).',
31
+ '"set_group_policy" sets group chat mode (open/disabled/allowlist). ' +
32
+ '"set_mention_required" sets whether @mention is required in group chats. ' +
33
+ '"logout" unlinks/logs out a WhatsApp account. ' +
34
+ '"set_imessage_owner" assigns iMessage channel ownership to an account.',
29
35
  }),
30
36
  accountId: Type.Optional(Type.String({
31
37
  description: "WhatsApp account ID (required for set_* actions). Use status action to discover account IDs.",
@@ -42,6 +48,12 @@ const ChannelSettingsSchema = Type.Object({
42
48
  groupPolicy: optionalStringEnum(GROUP_POLICY_VALUES, {
43
49
  description: 'Group chat policy: "open", "disabled", or "allowlist". Required for set_group_policy.',
44
50
  }),
51
+ mentionRequired: Type.Optional(Type.Boolean({
52
+ description: "Whether bot requires @mention in group chats. Required for set_mention_required.",
53
+ })),
54
+ imessageOwner: Type.Optional(Type.String({
55
+ description: "Account ID to assign iMessage ownership to. Required for set_imessage_owner.",
56
+ })),
45
57
  });
46
58
  export function createChannelSettingsTool() {
47
59
  return {
@@ -49,7 +61,9 @@ export function createChannelSettingsTool() {
49
61
  name: "channel_settings",
50
62
  description: "Read and update channel settings (WhatsApp, iMessage). " +
51
63
  '"status" shows connection state and account list. ' +
52
- "set_model/set_thinking/set_dm_policy/set_group_policy update per-account WhatsApp settings. " +
64
+ "set_model/set_thinking/set_dm_policy/set_group_policy/set_mention_required update per-account WhatsApp settings. " +
65
+ '"logout" unlinks a WhatsApp account. ' +
66
+ '"set_imessage_owner" assigns iMessage ownership to an account. ' +
53
67
  "Use status first to discover available account IDs.",
54
68
  parameters: ChannelSettingsSchema,
55
69
  execute: async (_toolCallId, args) => {
@@ -60,7 +74,24 @@ export function createChannelSettingsTool() {
60
74
  const result = await callGatewayTool("channels.status", gatewayOpts, {});
61
75
  return jsonResult(result);
62
76
  }
63
- // All set_* actions require accountId and use config.patch
77
+ // set_imessage_owner is global (no accountId needed)
78
+ if (action === "set_imessage_owner") {
79
+ const imessageOwner = readStringParam(params, "imessageOwner", {
80
+ required: true,
81
+ label: "imessageOwner",
82
+ });
83
+ const snapshot = await callGatewayTool("config.get", gatewayOpts, {});
84
+ const baseHash = typeof snapshot?.hash === "string" ? snapshot.hash : undefined;
85
+ const result = await callGatewayTool("config.patch", gatewayOpts, {
86
+ raw: JSON.stringify({
87
+ channels: { imessage: { owner: imessageOwner } },
88
+ }),
89
+ baseHash,
90
+ note: `agent: set iMessage owner to ${imessageOwner}`,
91
+ });
92
+ return jsonResult({ ok: true, imessageOwner, result });
93
+ }
94
+ // Remaining actions require accountId
64
95
  const accountId = readStringParam(params, "accountId", {
65
96
  required: true,
66
97
  label: "accountId",
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Agent tool for managing network and Tailscale settings.
3
+ *
4
+ * Exposes Tailscale status, enable/disable controls for Tailscale Serve and
5
+ * Funnel, plus general network status and hostname configuration — everything
6
+ * a user would normally manage from the Network section of the control panel.
7
+ */
8
+ import { Type } from "@sinclair/typebox";
9
+ import { stringEnum } from "../schema/typebox.js";
10
+ import { jsonResult, readStringParam } from "./common.js";
11
+ import { callGatewayTool } from "./gateway.js";
12
+ const ACTIONS = [
13
+ "tailscale_status",
14
+ "tailscale_enable",
15
+ "serve_enable",
16
+ "serve_disable",
17
+ "funnel_enable",
18
+ "funnel_disable",
19
+ "network_status",
20
+ "set_hostname",
21
+ ];
22
+ const NetworkSettingsSchema = Type.Object({
23
+ action: stringEnum(ACTIONS, {
24
+ description: '"tailscale_status" returns Tailscale connection state and public URL. ' +
25
+ '"tailscale_enable" starts Tailscale. ' +
26
+ '"serve_enable" / "serve_disable" toggle Tailscale Serve (HTTPS proxy). ' +
27
+ '"funnel_enable" / "funnel_disable" toggle Tailscale Funnel (public internet access). ' +
28
+ '"network_status" returns general network info (IP, hostname, interfaces). ' +
29
+ '"set_hostname" changes the device hostname (requires hostname param).',
30
+ }),
31
+ hostname: Type.Optional(Type.String({ description: "New hostname — required for set_hostname action." })),
32
+ });
33
+ export function createNetworkSettingsTool() {
34
+ return {
35
+ label: "Network Settings",
36
+ name: "network_settings",
37
+ description: "Manage network and Tailscale configuration. " +
38
+ "Actions: " +
39
+ '"tailscale_status" (connection state and public URL), ' +
40
+ '"tailscale_enable" (start Tailscale), ' +
41
+ '"serve_enable" / "serve_disable" (toggle Tailscale Serve), ' +
42
+ '"funnel_enable" / "funnel_disable" (toggle Tailscale Funnel), ' +
43
+ '"network_status" (general network info), ' +
44
+ '"set_hostname" (change device hostname — pass hostname param).',
45
+ parameters: NetworkSettingsSchema,
46
+ execute: async (_toolCallId, args) => {
47
+ const params = args;
48
+ const action = readStringParam(params, "action", { required: true });
49
+ const methodMap = {
50
+ tailscale_status: "tailscale.status",
51
+ tailscale_enable: "tailscale.enable",
52
+ serve_enable: "tailscale.serve.enable",
53
+ serve_disable: "tailscale.serve.disable",
54
+ funnel_enable: "tailscale.funnel.enable",
55
+ funnel_disable: "tailscale.funnel.disable",
56
+ network_status: "network.status",
57
+ set_hostname: "network.setHostname",
58
+ };
59
+ const method = methodMap[action];
60
+ if (!method)
61
+ throw new Error(`Unknown action: ${action}`);
62
+ const callParams = {};
63
+ if (action === "set_hostname") {
64
+ const hostname = readStringParam(params, "hostname", { required: true });
65
+ callParams.hostname = hostname;
66
+ }
67
+ const result = await callGatewayTool(method, {}, callParams);
68
+ return jsonResult(result);
69
+ },
70
+ };
71
+ }
@@ -17,6 +17,8 @@ const SYSTEM_STATUS_ACTIONS = [
17
17
  "channels",
18
18
  "models",
19
19
  "update",
20
+ "tailscale",
21
+ "network",
20
22
  ];
21
23
  const SystemStatusSchema = Type.Object({
22
24
  action: stringEnum(SYSTEM_STATUS_ACTIONS, {
@@ -32,19 +34,22 @@ export function createSystemStatusTool() {
32
34
  "Use specific actions for detail: " +
33
35
  '"health" (gateway health), "auth" (Claude API auth), "license" (license info), ' +
34
36
  '"channels" (WhatsApp/iMessage connections), "models" (available LLM models), ' +
35
- '"update" (software version and update availability).',
37
+ '"update" (software version and update availability), ' +
38
+ '"tailscale" (Tailscale connection + public URL), "network" (hostname + port).',
36
39
  parameters: SystemStatusSchema,
37
40
  execute: async (_toolCallId, args) => {
38
41
  const params = args;
39
42
  const action = readStringParam(params, "action", { required: true });
40
43
  if (action === "overview") {
41
44
  // Fetch all subsystems in parallel for a unified snapshot
42
- const [health, auth, license, channels, update] = await Promise.allSettled([
45
+ const [health, auth, license, channels, update, tailscale, network] = await Promise.allSettled([
43
46
  callGatewayTool("health", {}, {}),
44
47
  callGatewayTool("auth.status", {}, {}),
45
48
  callGatewayTool("license.status", {}, {}),
46
49
  callGatewayTool("channels.status", {}, {}),
47
50
  callGatewayTool("update.status", {}, {}),
51
+ callGatewayTool("tailscale.status", {}, {}),
52
+ callGatewayTool("network.status", {}, {}),
48
53
  ]);
49
54
  return jsonResult({
50
55
  health: health.status === "fulfilled"
@@ -62,6 +67,12 @@ export function createSystemStatusTool() {
62
67
  update: update.status === "fulfilled"
63
68
  ? update.value
64
69
  : { error: String(update.reason) },
70
+ tailscale: tailscale.status === "fulfilled"
71
+ ? tailscale.value
72
+ : { error: String(tailscale.reason) },
73
+ network: network.status === "fulfilled"
74
+ ? network.value
75
+ : { error: String(network.reason) },
65
76
  });
66
77
  }
67
78
  const methodMap = {
@@ -71,6 +82,8 @@ export function createSystemStatusTool() {
71
82
  channels: "channels.status",
72
83
  models: "models.list",
73
84
  update: "update.status",
85
+ tailscale: "tailscale.status",
86
+ network: "network.status",
74
87
  };
75
88
  const method = methodMap[action];
76
89
  if (!method)
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Agent tool for managing WiFi settings.
3
+ *
4
+ * Exposes WiFi status, scanning, connect/disconnect/reconnect/forget —
5
+ * everything a user would normally manage from the WiFi section of the
6
+ * control panel. Linux/Raspberry Pi only.
7
+ */
8
+ import { Type } from "@sinclair/typebox";
9
+ import { stringEnum } from "../schema/typebox.js";
10
+ import { jsonResult, readStringParam } from "./common.js";
11
+ import { callGatewayTool } from "./gateway.js";
12
+ const ACTIONS = ["status", "scan", "connect", "disconnect", "reconnect", "forget"];
13
+ const WifiSettingsSchema = Type.Object({
14
+ action: stringEnum(ACTIONS, {
15
+ description: '"status" returns current WiFi connection state. ' +
16
+ '"scan" lists available WiFi networks. ' +
17
+ '"connect" joins a network (requires ssid param, optional password). ' +
18
+ '"disconnect" drops the current WiFi connection. ' +
19
+ '"reconnect" drops and re-establishes the current WiFi connection. ' +
20
+ '"forget" removes the saved WiFi network.',
21
+ }),
22
+ ssid: Type.Optional(Type.String({ description: "Network name — required for connect action." })),
23
+ password: Type.Optional(Type.String({ description: "Network password — optional, for connect action only." })),
24
+ });
25
+ export function createWifiSettingsTool() {
26
+ return {
27
+ label: "WiFi Settings",
28
+ name: "wifi_settings",
29
+ description: "Manage WiFi configuration (Linux/Raspberry Pi only). " +
30
+ "Actions: " +
31
+ '"status" (current connection state), ' +
32
+ '"scan" (list available networks), ' +
33
+ '"connect" (join a network — pass ssid, optionally password), ' +
34
+ '"disconnect" (drop current connection), ' +
35
+ '"reconnect" (drop and re-establish connection), ' +
36
+ '"forget" (remove saved network).',
37
+ parameters: WifiSettingsSchema,
38
+ execute: async (_toolCallId, args) => {
39
+ const params = args;
40
+ const action = readStringParam(params, "action", { required: true });
41
+ const methodMap = {
42
+ status: "wifi.status",
43
+ scan: "wifi.scan",
44
+ connect: "wifi.connect",
45
+ disconnect: "wifi.disconnect",
46
+ reconnect: "wifi.reconnect",
47
+ forget: "wifi.forget",
48
+ };
49
+ const method = methodMap[action];
50
+ if (!method)
51
+ throw new Error(`Unknown action: ${action}`);
52
+ const callParams = {};
53
+ if (action === "connect") {
54
+ const ssid = readStringParam(params, "ssid", { required: true });
55
+ callParams.ssid = ssid;
56
+ const password = readStringParam(params, "password");
57
+ if (password)
58
+ callParams.password = password;
59
+ }
60
+ const result = await callGatewayTool(method, {}, callParams);
61
+ return jsonResult(result);
62
+ },
63
+ };
64
+ }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.17.6",
3
- "commit": "1f22ab0820d5ef0b02e53127897859386e2454a2",
4
- "builtAt": "2026-03-05T15:08:07.106Z"
2
+ "version": "1.17.7",
3
+ "commit": "5816363bb6d544f98555ba995bf5bda72f5c7a17",
4
+ "builtAt": "2026-03-05T15:37:55.754Z"
5
5
  }