@rubytech/taskmaster 1.2.1 → 1.4.0

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 (92) hide show
  1. package/dist/agents/auth-profiles/oauth.js +24 -0
  2. package/dist/agents/auth-profiles/profiles.js +37 -0
  3. package/dist/agents/auth-profiles.js +1 -1
  4. package/dist/agents/pi-tools.policy.js +4 -0
  5. package/dist/agents/taskmaster-tools.js +14 -0
  6. package/dist/agents/tool-policy.js +5 -2
  7. package/dist/agents/tools/apikeys-tool.js +16 -5
  8. package/dist/agents/tools/contact-create-tool.js +59 -0
  9. package/dist/agents/tools/contact-delete-tool.js +48 -0
  10. package/dist/agents/tools/contact-update-tool.js +17 -2
  11. package/dist/agents/tools/file-delete-tool.js +137 -0
  12. package/dist/agents/tools/file-list-tool.js +127 -0
  13. package/dist/agents/tools/message-history-tool.js +2 -3
  14. package/dist/auto-reply/media-note.js +11 -0
  15. package/dist/auto-reply/reply/commands-tts.js +7 -2
  16. package/dist/auto-reply/reply/get-reply.js +4 -0
  17. package/dist/build-info.json +3 -3
  18. package/dist/cli/provision-seed.js +1 -2
  19. package/dist/commands/doctor-config-flow.js +13 -0
  20. package/dist/config/agent-tools-reconcile.js +53 -0
  21. package/dist/config/defaults.js +10 -1
  22. package/dist/config/legacy.migrations.part-3.js +26 -0
  23. package/dist/config/zod-schema.core.js +9 -1
  24. package/dist/config/zod-schema.js +1 -0
  25. package/dist/control-ui/assets/{index-N8du4fwV.js → index-BDETQp97.js} +692 -600
  26. package/dist/control-ui/assets/index-BDETQp97.js.map +1 -0
  27. package/dist/control-ui/assets/index-CPawOl_z.css +1 -0
  28. package/dist/control-ui/index.html +2 -2
  29. package/dist/gateway/chat-sanitize.js +5 -1
  30. package/dist/gateway/config-reload.js +1 -0
  31. package/dist/gateway/media-http.js +28 -0
  32. package/dist/gateway/server/tls.js +2 -2
  33. package/dist/gateway/server-http.js +34 -4
  34. package/dist/gateway/server-methods/apikeys.js +56 -4
  35. package/dist/gateway/server-methods/chat.js +64 -25
  36. package/dist/gateway/server-methods/tts.js +11 -2
  37. package/dist/gateway/server.impl.js +38 -5
  38. package/dist/infra/tls/gateway.js +19 -3
  39. package/dist/media-understanding/apply.js +35 -0
  40. package/dist/media-understanding/providers/deepgram/audio.js +1 -1
  41. package/dist/media-understanding/providers/google/audio.js +1 -1
  42. package/dist/media-understanding/providers/google/video.js +1 -1
  43. package/dist/media-understanding/providers/index.js +2 -0
  44. package/dist/media-understanding/providers/openai/audio.js +1 -1
  45. package/dist/media-understanding/providers/sherpa-onnx/index.js +10 -0
  46. package/dist/media-understanding/runner.js +61 -72
  47. package/dist/media-understanding/sherpa-onnx-local.js +223 -0
  48. package/dist/memory/audit.js +9 -0
  49. package/dist/memory/manager.js +1 -1
  50. package/dist/records/records-manager.js +10 -0
  51. package/dist/tts/tts.js +98 -10
  52. package/dist/web/auto-reply/monitor/process-message.js +45 -17
  53. package/dist/web/inbound/monitor.js +9 -1
  54. package/extensions/diagnostics-otel/node_modules/.bin/acorn +0 -0
  55. package/extensions/googlechat/node_modules/.bin/taskmaster +2 -2
  56. package/extensions/googlechat/package.json +2 -2
  57. package/extensions/line/node_modules/.bin/taskmaster +2 -2
  58. package/extensions/line/package.json +1 -1
  59. package/extensions/matrix/node_modules/.bin/markdown-it +0 -0
  60. package/extensions/matrix/node_modules/.bin/taskmaster +2 -2
  61. package/extensions/matrix/package.json +1 -1
  62. package/extensions/memory-lancedb/node_modules/.bin/arrow2csv +0 -0
  63. package/extensions/memory-lancedb/node_modules/.bin/openai +0 -0
  64. package/extensions/msteams/node_modules/.bin/taskmaster +2 -2
  65. package/extensions/msteams/package.json +1 -1
  66. package/extensions/nostr/node_modules/.bin/taskmaster +2 -2
  67. package/extensions/nostr/node_modules/.bin/tsc +0 -0
  68. package/extensions/nostr/node_modules/.bin/tsserver +0 -0
  69. package/extensions/nostr/package.json +1 -1
  70. package/extensions/zalo/node_modules/.bin/taskmaster +2 -2
  71. package/extensions/zalo/package.json +1 -1
  72. package/extensions/zalouser/node_modules/.bin/taskmaster +2 -2
  73. package/extensions/zalouser/package.json +1 -1
  74. package/package.json +56 -65
  75. package/scripts/install.sh +0 -0
  76. package/scripts/postinstall.js +76 -0
  77. package/skills/business-assistant/references/crm.md +32 -8
  78. package/taskmaster-docs/USER-GUIDE.md +111 -6
  79. package/templates/.DS_Store +0 -0
  80. package/templates/beagle/agents/admin/AGENTS.md +4 -2
  81. package/templates/customer/.DS_Store +0 -0
  82. package/templates/customer/agents/.DS_Store +0 -0
  83. package/templates/maxy/.DS_Store +0 -0
  84. package/templates/maxy/.gitignore +1 -0
  85. package/templates/maxy/agents/.DS_Store +0 -0
  86. package/templates/maxy/agents/admin/.DS_Store +0 -0
  87. package/templates/maxy/memory/.DS_Store +0 -0
  88. package/templates/maxy/skills/.DS_Store +0 -0
  89. package/templates/taskmaster/.gitignore +1 -0
  90. package/templates/taskmaster/agents/admin/AGENTS.md +1 -0
  91. package/dist/control-ui/assets/index-DtQHRIVD.css +0 -1
  92. package/dist/control-ui/assets/index-N8du4fwV.js.map +0 -1
package/dist/tts/tts.js CHANGED
@@ -5,11 +5,13 @@ import { completeSimple } from "@mariozechner/pi-ai";
5
5
  import { EdgeTTS } from "node-edge-tts";
6
6
  import { normalizeChannelId } from "../channels/plugins/index.js";
7
7
  import { logVerbose } from "../globals.js";
8
+ import { createSubsystemLogger } from "../logging/subsystem.js";
8
9
  import { isVoiceCompatibleAudio } from "../media/audio.js";
9
10
  import { CONFIG_DIR, resolveUserPath } from "../utils.js";
10
- import { getApiKeyForModel, requireApiKey } from "../agents/model-auth.js";
11
+ import { getApiKeyForModel, requireApiKey, resolveApiKeyForProvider, } from "../agents/model-auth.js";
11
12
  import { buildModelAliasIndex, resolveDefaultModelForAgent, resolveModelRefFromString, } from "../agents/model-selection.js";
12
13
  import { resolveModel } from "../agents/pi-embedded-runner/model.js";
14
+ const log = createSubsystemLogger("gateway/tts");
13
15
  const DEFAULT_TIMEOUT_MS = 30_000;
14
16
  const DEFAULT_TTS_MAX_LENGTH = 1500;
15
17
  const DEFAULT_TTS_SUMMARIZE = true;
@@ -133,6 +135,11 @@ export function resolveTtsConfig(cfg) {
133
135
  proxy: raw.edge?.proxy?.trim() || undefined,
134
136
  timeoutMs: raw.edge?.timeoutMs,
135
137
  },
138
+ hume: {
139
+ apiKey: raw.hume?.apiKey,
140
+ voice: raw.hume?.voice?.trim() || "KORA",
141
+ description: raw.hume?.description?.trim() || undefined,
142
+ },
136
143
  prefsPath: raw.prefsPath,
137
144
  maxTextLength: raw.maxTextLength ?? DEFAULT_MAX_TEXT_LENGTH,
138
145
  timeoutMs: raw.timeoutMs ?? DEFAULT_TIMEOUT_MS,
@@ -173,15 +180,15 @@ export function buildTtsSystemPromptHint(cfg) {
173
180
  const maxLength = getTtsMaxLength(prefsPath);
174
181
  const summarize = isSummarizationEnabled(prefsPath) ? "on" : "off";
175
182
  const autoHint = autoMode === "inbound"
176
- ? "Only use TTS when the user's last message includes audio/voice."
183
+ ? "Your replies are automatically converted to voice notes when the user sends audio/voice."
177
184
  : autoMode === "tagged"
178
- ? "Only use TTS when you include [[tts]] or [[tts:text]] tags."
179
- : undefined;
185
+ ? "Your replies are converted to voice notes when you include [[tts]] or [[tts:text]] tags."
186
+ : "Your replies are automatically converted to voice notes and sent as audio messages.";
180
187
  return [
181
- "Voice (TTS) is enabled.",
188
+ "Voice replies are enabled — you CAN send voice notes.",
182
189
  autoHint,
190
+ "Write naturally as if speaking. Do not tell the user you cannot send voice messages — you can.",
183
191
  `Keep spoken text ≤${maxLength} chars to avoid auto-summary (summary ${summarize}).`,
184
- "Use [[tts:...]] and optional [[tts:text]]...[[/tts:text]] to control voice/expressiveness.",
185
192
  ]
186
193
  .filter(Boolean)
187
194
  .join("\n");
@@ -291,15 +298,20 @@ export function resolveTtsApiKey(config, provider) {
291
298
  if (provider === "openai") {
292
299
  return config.openai.apiKey || process.env.OPENAI_API_KEY;
293
300
  }
301
+ if (provider === "hume") {
302
+ return config.hume.apiKey || process.env.HUME_API_KEY;
303
+ }
294
304
  return undefined;
295
305
  }
296
- export const TTS_PROVIDERS = ["openai", "elevenlabs", "edge"];
306
+ export const TTS_PROVIDERS = ["openai", "elevenlabs", "hume", "edge"];
297
307
  export function resolveTtsProviderOrder(primary) {
298
308
  return [primary, ...TTS_PROVIDERS.filter((provider) => provider !== primary)];
299
309
  }
300
310
  export function isTtsProviderConfigured(config, provider) {
301
311
  if (provider === "edge")
302
312
  return config.edge.enabled;
313
+ if (provider === "hume")
314
+ return Boolean(resolveTtsApiKey(config, provider));
303
315
  return Boolean(resolveTtsApiKey(config, provider));
304
316
  }
305
317
  function isValidVoiceId(voiceId) {
@@ -350,6 +362,14 @@ function normalizeSeed(seed) {
350
362
  }
351
363
  return next;
352
364
  }
365
+ /** Strip emoji characters so TTS engines don't read them aloud by name. */
366
+ function stripEmoji(text) {
367
+ // Unicode emoji ranges: emoticons, dingbats, symbols, flags, components
368
+ return text
369
+ .replace(/[\p{Emoji_Presentation}\p{Extended_Pictographic}]/gu, "")
370
+ .replace(/ +/g, " ")
371
+ .trim();
372
+ }
353
373
  function parseBooleanValue(value) {
354
374
  const normalized = value.trim().toLowerCase();
355
375
  if (["true", "1", "yes", "on"].includes(normalized))
@@ -777,6 +797,50 @@ async function openaiTTS(params) {
777
797
  clearTimeout(timeout);
778
798
  }
779
799
  }
800
+ // ---------------------------------------------------------------------------
801
+ // Hume Octave TTS — REST API
802
+ // POST https://api.hume.ai/v0/tts
803
+ // ---------------------------------------------------------------------------
804
+ const HUME_TTS_BASE_URL = "https://api.hume.ai/v0/tts";
805
+ async function humeTTS(params) {
806
+ const { text, apiKey, voice, description, timeoutMs } = params;
807
+ const controller = new AbortController();
808
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
809
+ try {
810
+ const isUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(voice);
811
+ const voiceSpec = isUuid ? { id: voice } : { name: voice, provider: "HUME_AI" };
812
+ const utterance = { text, voice: voiceSpec };
813
+ if (description) {
814
+ utterance.description = description;
815
+ }
816
+ const response = await fetch(HUME_TTS_BASE_URL, {
817
+ method: "POST",
818
+ headers: {
819
+ "X-Hume-Api-Key": apiKey,
820
+ "Content-Type": "application/json",
821
+ },
822
+ body: JSON.stringify({
823
+ utterances: [utterance],
824
+ format: { type: "mp3" },
825
+ strip_headers: true,
826
+ }),
827
+ signal: controller.signal,
828
+ });
829
+ if (!response.ok) {
830
+ const body = await response.text().catch(() => "");
831
+ throw new Error(`Hume TTS API error (${response.status}): ${body.slice(0, 200)}`);
832
+ }
833
+ const json = (await response.json());
834
+ const audio64 = json.generations?.[0]?.audio;
835
+ if (!audio64) {
836
+ throw new Error("Hume TTS: no audio in response");
837
+ }
838
+ return Buffer.from(audio64, "base64");
839
+ }
840
+ finally {
841
+ clearTimeout(timeout);
842
+ }
843
+ }
780
844
  function inferEdgeExtension(outputFormat) {
781
845
  const normalized = outputFormat.toLowerCase();
782
846
  if (normalized.includes("webm"))
@@ -888,7 +952,17 @@ export async function textToSpeech(params) {
888
952
  voiceCompatible,
889
953
  };
890
954
  }
891
- const apiKey = resolveTtsApiKey(config, provider);
955
+ let apiKey = resolveTtsApiKey(config, provider);
956
+ // Hume keys are stored in auth profiles (API Keys UI). Fall back to async lookup.
957
+ if (!apiKey && provider === "hume") {
958
+ try {
959
+ const auth = await resolveApiKeyForProvider({ provider: "hume", cfg: params.cfg });
960
+ apiKey = auth.apiKey?.trim() || undefined;
961
+ }
962
+ catch {
963
+ // No auth profile key available
964
+ }
965
+ }
892
966
  if (!apiKey) {
893
967
  lastError = `No API key for ${provider}`;
894
968
  continue;
@@ -918,6 +992,15 @@ export async function textToSpeech(params) {
918
992
  timeoutMs: config.timeoutMs,
919
993
  });
920
994
  }
995
+ else if (provider === "hume") {
996
+ audioBuffer = await humeTTS({
997
+ text: params.text,
998
+ apiKey,
999
+ voice: config.hume.voice,
1000
+ description: config.hume.description,
1001
+ timeoutMs: config.timeoutMs,
1002
+ });
1003
+ }
921
1004
  else {
922
1005
  const openaiModelOverride = params.overrides?.openai?.model;
923
1006
  const openaiVoiceOverride = params.overrides?.openai?.voice;
@@ -931,6 +1014,7 @@ export async function textToSpeech(params) {
931
1014
  });
932
1015
  }
933
1016
  const latencyMs = Date.now() - providerStart;
1017
+ log.info(`success via ${provider} (${latencyMs}ms, ${audioBuffer.length} bytes)`);
934
1018
  const tempDir = mkdtempSync(path.join(tmpdir(), "tts-"));
935
1019
  const audioPath = path.join(tempDir, `voice-${Date.now()}${output.extension}`);
936
1020
  writeFileSync(audioPath, audioBuffer);
@@ -940,7 +1024,7 @@ export async function textToSpeech(params) {
940
1024
  audioPath,
941
1025
  latencyMs,
942
1026
  provider,
943
- outputFormat: provider === "openai" ? output.openai : output.elevenlabs,
1027
+ outputFormat: provider === "openai" ? output.openai : provider === "hume" ? "mp3" : output.elevenlabs,
944
1028
  voiceCompatible: output.voiceCompatible,
945
1029
  };
946
1030
  }
@@ -952,8 +1036,10 @@ export async function textToSpeech(params) {
952
1036
  else {
953
1037
  lastError = `${provider}: ${error.message}`;
954
1038
  }
1039
+ log.error(`${provider} failed: ${lastError}`);
955
1040
  }
956
1041
  }
1042
+ log.error(`all providers failed: ${lastError || "none available"}`);
957
1043
  return {
958
1044
  success: false,
959
1045
  error: `TTS conversion failed: ${lastError || "no providers available"}`,
@@ -1033,8 +1119,10 @@ export async function textToSpeechTelephony(params) {
1033
1119
  else {
1034
1120
  lastError = `${provider}: ${error.message}`;
1035
1121
  }
1122
+ log.error(`telephony: ${provider} failed: ${lastError}`);
1036
1123
  }
1037
1124
  }
1125
+ log.error(`telephony: all providers failed: ${lastError || "none available"}`);
1038
1126
  return {
1039
1127
  success: false,
1040
1128
  error: `TTS conversion failed: ${lastError || "no providers available"}`,
@@ -1081,7 +1169,7 @@ export async function maybeApplyTtsToPayload(params) {
1081
1169
  if (ttsText.trim().length < 10)
1082
1170
  return nextPayload;
1083
1171
  const maxLength = getTtsMaxLength(prefsPath);
1084
- let textForAudio = ttsText.trim();
1172
+ let textForAudio = stripEmoji(ttsText.trim());
1085
1173
  let wasSummarized = false;
1086
1174
  if (textForAudio.length > maxLength) {
1087
1175
  if (!isSummarizationEnabled(prefsPath)) {
@@ -130,23 +130,32 @@ export async function processMessage(params) {
130
130
  params.echoForget(combinedEchoKey);
131
131
  return false;
132
132
  }
133
- // Fire message:inbound hook for conversation archiving
134
- const inboundHookEvent = createInternalHookEvent("message", "inbound", params.route.sessionKey, {
135
- from: params.msg.senderE164 ?? params.msg.from,
136
- to: params.msg.to,
137
- text: params.msg.body,
138
- timestamp: params.msg.timestamp ?? Date.now(),
139
- chatType: params.msg.chatType,
140
- agentId: params.route.agentId,
141
- channel: "whatsapp",
142
- mediaType: params.msg.mediaType,
143
- senderName: params.msg.senderName,
144
- senderE164: params.msg.senderE164,
145
- groupSubject: params.msg.groupSubject,
146
- conversationId,
147
- cfg: params.cfg,
148
- });
149
- void triggerInternalHook(inboundHookEvent);
133
+ // Fire message:inbound hook for conversation archiving.
134
+ // For media messages (audio, image, video) the raw body is a placeholder like
135
+ // `<media:audio>`. Defer the hook until after media understanding resolves so
136
+ // the archive records the transcript / description instead of the dead link.
137
+ // Text-only messages fire immediately (unchanged behaviour).
138
+ const hasMediaAttachment = Boolean(params.msg.mediaType);
139
+ const fireInboundArchiveHook = (text) => {
140
+ void triggerInternalHook(createInternalHookEvent("message", "inbound", params.route.sessionKey, {
141
+ from: params.msg.senderE164 ?? params.msg.from,
142
+ to: params.msg.to,
143
+ text,
144
+ timestamp: params.msg.timestamp ?? Date.now(),
145
+ chatType: params.msg.chatType,
146
+ agentId: params.route.agentId,
147
+ channel: "whatsapp",
148
+ mediaType: params.msg.mediaType,
149
+ senderName: params.msg.senderName,
150
+ senderE164: params.msg.senderE164,
151
+ groupSubject: params.msg.groupSubject,
152
+ conversationId,
153
+ cfg: params.cfg,
154
+ }));
155
+ };
156
+ if (!hasMediaAttachment) {
157
+ fireInboundArchiveHook(params.msg.body);
158
+ }
150
159
  // Send ack reaction immediately upon message receipt (post-gating).
151
160
  // Suppress when running silently on un-mentioned group messages.
152
161
  if (params.suppressDelivery) {
@@ -233,6 +242,7 @@ export async function processMessage(params) {
233
242
  MediaPath: params.msg.mediaPath,
234
243
  MediaUrl: params.msg.mediaUrl,
235
244
  MediaType: params.msg.mediaType,
245
+ MediaDownloadFailed: params.msg.mediaDownloadFailed,
236
246
  ChatType: params.msg.chatType,
237
247
  ConversationLabel: params.msg.chatType === "group" ? conversationId : params.msg.from,
238
248
  GroupSubject: params.msg.groupSubject,
@@ -363,6 +373,24 @@ export async function processMessage(params) {
363
373
  ? !params.cfg.channels.whatsapp.blockStreaming
364
374
  : undefined,
365
375
  onModelSelected: prefixContext.onModelSelected,
376
+ // For media messages the inbound archive hook was deferred until after
377
+ // media understanding resolves. Fire it now with the resolved text.
378
+ ...(hasMediaAttachment
379
+ ? {
380
+ onMediaResolved: () => {
381
+ const raw = params.msg.body ?? "";
382
+ // Prefer the raw transcript for audio. For other media or failed
383
+ // transcription fall back to the resolved Body (which contains the
384
+ // description or a human-readable failure reason). The regex guard
385
+ // prevents using the envelope-formatted Body for plain text messages.
386
+ const resolvedText = ctxPayload.Transcript ??
387
+ (/^<media:[^>]+>/i.test(raw.trim())
388
+ ? String(ctxPayload.Body ?? raw)
389
+ : raw);
390
+ fireInboundArchiveHook(String(resolvedText));
391
+ },
392
+ }
393
+ : {}),
366
394
  },
367
395
  });
368
396
  if (!queuedFinal) {
@@ -230,6 +230,7 @@ export async function monitorWebInbox(options) {
230
230
  const replyContext = describeReplyContext(msg.message);
231
231
  let mediaPath;
232
232
  let mediaType;
233
+ let mediaDownloadFailed = false;
233
234
  try {
234
235
  const inboundMedia = await downloadInboundMedia(msg, sock);
235
236
  if (inboundMedia) {
@@ -241,9 +242,15 @@ export async function monitorWebInbox(options) {
241
242
  mediaPath = saved.path;
242
243
  mediaType = inboundMedia.mimetype;
243
244
  }
245
+ else if (body.includes("<media:")) {
246
+ // downloadInboundMedia returned undefined — media was expected but unavailable
247
+ mediaDownloadFailed = true;
248
+ inboundLogger.warn({ id, from, body }, "media download returned empty");
249
+ }
244
250
  }
245
251
  catch (err) {
246
- logVerbose(`Inbound media download failed: ${String(err)}`);
252
+ mediaDownloadFailed = body.includes("<media:");
253
+ inboundLogger.warn({ id, from, error: String(err) }, "media download failed");
247
254
  }
248
255
  const chatJid = remoteJid;
249
256
  const sendComposing = async () => {
@@ -294,6 +301,7 @@ export async function monitorWebInbox(options) {
294
301
  sendMedia,
295
302
  mediaPath,
296
303
  mediaType,
304
+ mediaDownloadFailed,
297
305
  };
298
306
  try {
299
307
  const task = Promise.resolve(debouncer.enqueue(inboundMessage));
@@ -15,7 +15,7 @@ else
15
15
  export NODE_PATH="/Users/neo/taskmaster-dev/dist/node_modules:/Users/neo/taskmaster-dev/node_modules:/Users/neo/node_modules:/Users/node_modules:/node_modules:/Users/neo/taskmaster-dev/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
- exec "$basedir/node" "$basedir/../taskmaster/dist/entry.js" "$@"
18
+ exec "$basedir/node" "$basedir/../@rubytech/taskmaster/dist/entry.js" "$@"
19
19
  else
20
- exec node "$basedir/../taskmaster/dist/entry.js" "$@"
20
+ exec node "$basedir/../@rubytech/taskmaster/dist/entry.js" "$@"
21
21
  fi
@@ -31,9 +31,9 @@
31
31
  "google-auth-library": "^10.5.0"
32
32
  },
33
33
  "devDependencies": {
34
- "taskmaster": "workspace:*"
34
+ "@rubytech/taskmaster": "workspace:*"
35
35
  },
36
36
  "peerDependencies": {
37
- "taskmaster": "workspace:*"
37
+ "@rubytech/taskmaster": "workspace:*"
38
38
  }
39
39
  }
@@ -15,7 +15,7 @@ else
15
15
  export NODE_PATH="/Users/neo/taskmaster-dev/dist/node_modules:/Users/neo/taskmaster-dev/node_modules:/Users/neo/node_modules:/Users/node_modules:/node_modules:/Users/neo/taskmaster-dev/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
- exec "$basedir/node" "$basedir/../taskmaster/dist/entry.js" "$@"
18
+ exec "$basedir/node" "$basedir/../@rubytech/taskmaster/dist/entry.js" "$@"
19
19
  else
20
- exec node "$basedir/../taskmaster/dist/entry.js" "$@"
20
+ exec node "$basedir/../@rubytech/taskmaster/dist/entry.js" "$@"
21
21
  fi
@@ -24,6 +24,6 @@
24
24
  }
25
25
  },
26
26
  "devDependencies": {
27
- "taskmaster": "workspace:*"
27
+ "@rubytech/taskmaster": "workspace:*"
28
28
  }
29
29
  }
File without changes
@@ -15,7 +15,7 @@ else
15
15
  export NODE_PATH="/Users/neo/taskmaster-dev/dist/node_modules:/Users/neo/taskmaster-dev/node_modules:/Users/neo/node_modules:/Users/node_modules:/node_modules:/Users/neo/taskmaster-dev/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
- exec "$basedir/node" "$basedir/../taskmaster/dist/entry.js" "$@"
18
+ exec "$basedir/node" "$basedir/../@rubytech/taskmaster/dist/entry.js" "$@"
19
19
  else
20
- exec node "$basedir/../taskmaster/dist/entry.js" "$@"
20
+ exec node "$basedir/../@rubytech/taskmaster/dist/entry.js" "$@"
21
21
  fi
@@ -31,6 +31,6 @@
31
31
  "zod": "^4.3.6"
32
32
  },
33
33
  "devDependencies": {
34
- "taskmaster": "workspace:*"
34
+ "@rubytech/taskmaster": "workspace:*"
35
35
  }
36
36
  }
@@ -15,7 +15,7 @@ else
15
15
  export NODE_PATH="/Users/neo/taskmaster-dev/dist/node_modules:/Users/neo/taskmaster-dev/node_modules:/Users/neo/node_modules:/Users/node_modules:/node_modules:/Users/neo/taskmaster-dev/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
- exec "$basedir/node" "$basedir/../taskmaster/dist/entry.js" "$@"
18
+ exec "$basedir/node" "$basedir/../@rubytech/taskmaster/dist/entry.js" "$@"
19
19
  else
20
- exec node "$basedir/../taskmaster/dist/entry.js" "$@"
20
+ exec node "$basedir/../@rubytech/taskmaster/dist/entry.js" "$@"
21
21
  fi
@@ -29,7 +29,7 @@
29
29
  "@microsoft/agents-hosting": "^1.2.2",
30
30
  "@microsoft/agents-hosting-express": "^1.2.2",
31
31
  "@microsoft/agents-hosting-extensions-teams": "^1.2.2",
32
- "taskmaster": "workspace:*",
32
+ "@rubytech/taskmaster": "workspace:*",
33
33
  "express": "^5.2.1",
34
34
  "proper-lockfile": "^4.1.2"
35
35
  }
@@ -15,7 +15,7 @@ else
15
15
  export NODE_PATH="/Users/neo/taskmaster-dev/dist/node_modules:/Users/neo/taskmaster-dev/node_modules:/Users/neo/node_modules:/Users/node_modules:/node_modules:/Users/neo/taskmaster-dev/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
- exec "$basedir/node" "$basedir/../taskmaster/dist/entry.js" "$@"
18
+ exec "$basedir/node" "$basedir/../@rubytech/taskmaster/dist/entry.js" "$@"
19
19
  else
20
- exec node "$basedir/../taskmaster/dist/entry.js" "$@"
20
+ exec node "$basedir/../@rubytech/taskmaster/dist/entry.js" "$@"
21
21
  fi
File without changes
File without changes
@@ -24,7 +24,7 @@
24
24
  }
25
25
  },
26
26
  "dependencies": {
27
- "taskmaster": "workspace:*",
27
+ "@rubytech/taskmaster": "workspace:*",
28
28
  "nostr-tools": "^2.20.0",
29
29
  "zod": "^4.3.6"
30
30
  }
@@ -15,7 +15,7 @@ else
15
15
  export NODE_PATH="/Users/neo/taskmaster-dev/dist/node_modules:/Users/neo/taskmaster-dev/node_modules:/Users/neo/node_modules:/Users/node_modules:/node_modules:/Users/neo/taskmaster-dev/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
- exec "$basedir/node" "$basedir/../taskmaster/dist/entry.js" "$@"
18
+ exec "$basedir/node" "$basedir/../@rubytech/taskmaster/dist/entry.js" "$@"
19
19
  else
20
- exec node "$basedir/../taskmaster/dist/entry.js" "$@"
20
+ exec node "$basedir/../@rubytech/taskmaster/dist/entry.js" "$@"
21
21
  fi
@@ -27,7 +27,7 @@
27
27
  }
28
28
  },
29
29
  "dependencies": {
30
- "taskmaster": "workspace:*",
30
+ "@rubytech/taskmaster": "workspace:*",
31
31
  "undici": "7.19.0"
32
32
  }
33
33
  }
@@ -15,7 +15,7 @@ else
15
15
  export NODE_PATH="/Users/neo/taskmaster-dev/dist/node_modules:/Users/neo/taskmaster-dev/node_modules:/Users/neo/node_modules:/Users/node_modules:/node_modules:/Users/neo/taskmaster-dev/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
- exec "$basedir/node" "$basedir/../taskmaster/dist/entry.js" "$@"
18
+ exec "$basedir/node" "$basedir/../@rubytech/taskmaster/dist/entry.js" "$@"
19
19
  else
20
- exec node "$basedir/../taskmaster/dist/entry.js" "$@"
20
+ exec node "$basedir/../@rubytech/taskmaster/dist/entry.js" "$@"
21
21
  fi
@@ -4,7 +4,7 @@
4
4
  "type": "module",
5
5
  "description": "Taskmaster Zalo Personal Account plugin via zca-cli",
6
6
  "dependencies": {
7
- "taskmaster": "workspace:*",
7
+ "@rubytech/taskmaster": "workspace:*",
8
8
  "@sinclair/typebox": "0.34.47"
9
9
  },
10
10
  "taskmaster": {