@hasna/assistants 1.1.17 → 1.1.18

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.
@@ -0,0 +1,11 @@
1
+ {
2
+ "id": "605c7efa-fc58-4128-9473-e3886866c8aa",
3
+ "createdAt": "2026-02-08T11:04:19.259Z",
4
+ "type": "feedback",
5
+ "title": "good This is great",
6
+ "description": "good This is great",
7
+ "source": "command",
8
+ "metadata": {
9
+ "cwd": "/Users/hasna/Workspace/hasna/opensource/opensourcedev/opensource-assistants"
10
+ }
11
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "id": "0f585da2-b4e5-4967-8283-633ff8cefabb",
3
+ "createdAt": 1770548570379,
4
+ "updatedAt": 1770548660353,
5
+ "createdBy": "assistant",
6
+ "sessionId": "033405ed-b730-47b9-9d6d-ed2e77ff8e65",
7
+ "actionType": "command",
8
+ "command": "telegram me",
9
+ "description": "Telegram bot monitor - check bot status every minute",
10
+ "status": "active",
11
+ "schedule": {
12
+ "kind": "interval",
13
+ "unit": "minutes",
14
+ "interval": 1
15
+ },
16
+ "nextRunAt": 1770548720353,
17
+ "lastRunAt": 1770548660353,
18
+ "lastResult": {
19
+ "ok": true,
20
+ "summary": "**@hasna_assistant_bot** is online and healthy."
21
+ }
22
+ }
package/dist/index.js CHANGED
@@ -25784,6 +25784,60 @@ var init_executor3 = __esm(async () => {
25784
25784
  MAX_SHELL_OUTPUT_LENGTH = 64 * 1024;
25785
25785
  });
25786
25786
 
25787
+ // packages/core/src/channels/mentions.ts
25788
+ function parseMentions(content) {
25789
+ const mentions = [];
25790
+ const quotedRegex = /@"([^"]+)"/g;
25791
+ let match;
25792
+ while ((match = quotedRegex.exec(content)) !== null) {
25793
+ const name = match[1].trim();
25794
+ if (name && !mentions.includes(name)) {
25795
+ mentions.push(name);
25796
+ }
25797
+ }
25798
+ const simpleRegex = /@([a-zA-Z0-9_-]+)/g;
25799
+ while ((match = simpleRegex.exec(content)) !== null) {
25800
+ const name = match[1];
25801
+ if (!mentions.includes(name)) {
25802
+ mentions.push(name);
25803
+ }
25804
+ }
25805
+ return mentions;
25806
+ }
25807
+ function resolveNameToKnown(mentionName, knownNames) {
25808
+ const lower = mentionName.toLowerCase();
25809
+ const exact = knownNames.find((k) => k.name.toLowerCase() === lower);
25810
+ if (exact)
25811
+ return exact;
25812
+ const prefix = knownNames.find((k) => k.name.toLowerCase().startsWith(lower));
25813
+ if (prefix)
25814
+ return prefix;
25815
+ const word = knownNames.find((k) => k.name.toLowerCase().split(/\s+/).some((w) => w === lower));
25816
+ if (word)
25817
+ return word;
25818
+ return null;
25819
+ }
25820
+ function resolveMentions(names, members) {
25821
+ const resolved = [];
25822
+ for (const name of names) {
25823
+ const lower = name.toLowerCase();
25824
+ const member = members.find((m) => m.assistantName.toLowerCase() === lower);
25825
+ if (member) {
25826
+ resolved.push({
25827
+ name,
25828
+ memberId: member.assistantId,
25829
+ memberType: member.memberType
25830
+ });
25831
+ }
25832
+ }
25833
+ return resolved;
25834
+ }
25835
+ function getMentionedMemberIds(content, members) {
25836
+ const names = parseMentions(content);
25837
+ const resolved = resolveMentions(names, members);
25838
+ return resolved.map((r) => r.memberId);
25839
+ }
25840
+
25787
25841
  // packages/core/src/scheduler/format.ts
25788
25842
  function formatRelativeTime(timestamp, now2 = Date.now()) {
25789
25843
  if (!timestamp)
@@ -74461,10 +74515,23 @@ Configure the external source with the URL and secret above.
74461
74515
  if (activePerson && result.success) {
74462
74516
  const agentPool = context.getChannelAgentPool?.();
74463
74517
  const members = manager.getMembers(channel);
74518
+ const currentAssistantId = context.getAssistantManager?.()?.getActive?.()?.id;
74464
74519
  if (agentPool && members.length > 0) {
74465
- const currentAssistantId = context.getAssistantManager?.()?.getActive?.()?.id;
74466
74520
  agentPool.triggerResponses(channel, activePerson.name, message, members, currentAssistantId || undefined);
74467
74521
  }
74522
+ const mentions = parseMentions(message);
74523
+ if (mentions.length > 0) {
74524
+ const assistantMembers = members.filter((m) => m.memberType === "assistant");
74525
+ const knownNames = assistantMembers.map((m) => ({ id: m.assistantId, name: m.assistantName }));
74526
+ const resolved = mentions.map((m) => resolveNameToKnown(m, knownNames)).filter(Boolean);
74527
+ if (resolved.length > 0) {
74528
+ if (!resolved.some((r) => r.id === currentAssistantId)) {
74529
+ return { handled: true };
74530
+ }
74531
+ } else {
74532
+ return { handled: true };
74533
+ }
74534
+ }
74468
74535
  return {
74469
74536
  handled: false,
74470
74537
  prompt: `[Channel Message] ${activePerson.name} posted in #${channel}: "${message}"
@@ -79324,7 +79391,7 @@ ${repoUrl}/issues/new
79324
79391
  context.setProjectContext(projectContext);
79325
79392
  }
79326
79393
  }
79327
- var VERSION = "1.1.17";
79394
+ var VERSION = "1.1.18";
79328
79395
  var init_builtin = __esm(async () => {
79329
79396
  init_src2();
79330
79397
  init_store();
@@ -173527,60 +173594,6 @@ var init_client4 = __esm(async () => {
173527
173594
  ]);
173528
173595
  });
173529
173596
 
173530
- // packages/core/src/channels/mentions.ts
173531
- function parseMentions(content) {
173532
- const mentions = [];
173533
- const quotedRegex = /@"([^"]+)"/g;
173534
- let match;
173535
- while ((match = quotedRegex.exec(content)) !== null) {
173536
- const name2 = match[1].trim();
173537
- if (name2 && !mentions.includes(name2)) {
173538
- mentions.push(name2);
173539
- }
173540
- }
173541
- const simpleRegex = /@([a-zA-Z0-9_-]+)/g;
173542
- while ((match = simpleRegex.exec(content)) !== null) {
173543
- const name2 = match[1];
173544
- if (!mentions.includes(name2)) {
173545
- mentions.push(name2);
173546
- }
173547
- }
173548
- return mentions;
173549
- }
173550
- function resolveNameToKnown(mentionName, knownNames) {
173551
- const lower = mentionName.toLowerCase();
173552
- const exact = knownNames.find((k7) => k7.name.toLowerCase() === lower);
173553
- if (exact)
173554
- return exact;
173555
- const prefix2 = knownNames.find((k7) => k7.name.toLowerCase().startsWith(lower));
173556
- if (prefix2)
173557
- return prefix2;
173558
- const word = knownNames.find((k7) => k7.name.toLowerCase().split(/\s+/).some((w6) => w6 === lower));
173559
- if (word)
173560
- return word;
173561
- return null;
173562
- }
173563
- function resolveMentions(names, members) {
173564
- const resolved = [];
173565
- for (const name2 of names) {
173566
- const lower = name2.toLowerCase();
173567
- const member = members.find((m5) => m5.assistantName.toLowerCase() === lower);
173568
- if (member) {
173569
- resolved.push({
173570
- name: name2,
173571
- memberId: member.assistantId,
173572
- memberType: member.memberType
173573
- });
173574
- }
173575
- }
173576
- return resolved;
173577
- }
173578
- function getMentionedMemberIds(content, members) {
173579
- const names = parseMentions(content);
173580
- const resolved = resolveMentions(names, members);
173581
- return resolved.map((r6) => r6.memberId);
173582
- }
173583
-
173584
173597
  // packages/core/src/channels/agent-pool.ts
173585
173598
  class ChannelAgentPool {
173586
173599
  agents = new Map;
@@ -173603,6 +173616,8 @@ class ChannelAgentPool {
173603
173616
  if (resolved.length > 0) {
173604
173617
  const resolvedIds = new Set(resolved.map((r6) => r6.id));
173605
173618
  targetMembers = assistantMembers.filter((m5) => resolvedIds.has(m5.assistantId));
173619
+ } else {
173620
+ return;
173606
173621
  }
173607
173622
  }
173608
173623
  if (excludeAssistantId) {
@@ -182645,6 +182660,7 @@ class AssistantLoop {
182645
182660
  isRunning = false;
182646
182661
  shouldStop = false;
182647
182662
  cumulativeTurns = 0;
182663
+ emittedTerminalChunk = false;
182648
182664
  toolAbortController = null;
182649
182665
  systemPrompt = null;
182650
182666
  connectorDiscovery = null;
@@ -183265,6 +183281,7 @@ You are running in **autonomous mode**. You manage your own wakeup schedule.
183265
183281
  throw new Error("Assistant not initialized. Call initialize() first.");
183266
183282
  }
183267
183283
  this.isRunning = true;
183284
+ this.emittedTerminalChunk = false;
183268
183285
  this.setHeartbeatState("processing");
183269
183286
  this.shouldStop = false;
183270
183287
  this.cumulativeTurns = 0;
@@ -183289,6 +183306,7 @@ You are running in **autonomous mode**. You manage your own wakeup schedule.
183289
183306
  if (explicitToolResult) {
183290
183307
  this.pendingMemoryContext = null;
183291
183308
  this.pendingContextInjection = null;
183309
+ this.ensureTerminalChunk();
183292
183310
  return explicitToolResult;
183293
183311
  }
183294
183312
  if (userMessage.startsWith("/")) {
@@ -183326,6 +183344,7 @@ You are running in **autonomous mode**. You manage your own wakeup schedule.
183326
183344
  panelValue: `session:${payload}`
183327
183345
  });
183328
183346
  }
183347
+ this.ensureTerminalChunk();
183329
183348
  return { ok: true, summary: `Handled ${userMessage}` };
183330
183349
  }
183331
183350
  if (commandResult.prompt) {
@@ -183336,6 +183355,7 @@ You are running in **autonomous mode**. You manage your own wakeup schedule.
183336
183355
  if (handled) {
183337
183356
  this.pendingMemoryContext = null;
183338
183357
  this.pendingContextInjection = null;
183358
+ this.ensureTerminalChunk();
183339
183359
  return { ok: true, summary: `Executed ${userMessage}` };
183340
183360
  }
183341
183361
  } else {
@@ -183350,6 +183370,7 @@ You are running in **autonomous mode**. You manage your own wakeup schedule.
183350
183370
  panelValue: commandResult.panelValue
183351
183371
  });
183352
183372
  }
183373
+ this.ensureTerminalChunk();
183353
183374
  return { ok: true, summary: `Handled ${userMessage}` };
183354
183375
  }
183355
183376
  if (commandResult.prompt) {
@@ -184196,7 +184217,15 @@ You are running in **autonomous mode**. You manage your own wakeup schedule.
184196
184217
  }
184197
184218
  return true;
184198
184219
  }
184220
+ ensureTerminalChunk() {
184221
+ if (!this.emittedTerminalChunk) {
184222
+ this.emit({ type: "done" });
184223
+ }
184224
+ }
184199
184225
  emit(chunk) {
184226
+ if (chunk.type === "done" || chunk.type === "error") {
184227
+ this.emittedTerminalChunk = true;
184228
+ }
184200
184229
  this.onChunk?.(chunk);
184201
184230
  }
184202
184231
  async emitNotification(params) {
@@ -206275,6 +206304,8 @@ await init_src3();
206275
206304
 
206276
206305
  // packages/terminal/src/hooks/useSafeInput.ts
206277
206306
  var import_react27 = __toESM(require_react(), 1);
206307
+ var rawModeUsers = 0;
206308
+ var rawModeEnabled = false;
206278
206309
  function parseKeypress2(s6) {
206279
206310
  const key = { name: "", ctrl: false, shift: false, meta: false, option: false, sequence: s6 };
206280
206311
  if (s6 === "\r" || s6 === `
@@ -206321,9 +206352,17 @@ function useSafeInput(handler, options = {}) {
206321
206352
  import_react27.useEffect(() => {
206322
206353
  if (!isRawModeSupported || !setRawMode)
206323
206354
  return;
206324
- setRawMode(true);
206355
+ rawModeUsers += 1;
206356
+ if (!rawModeEnabled) {
206357
+ setRawMode(true);
206358
+ rawModeEnabled = true;
206359
+ }
206325
206360
  return () => {
206326
- setRawMode(false);
206361
+ rawModeUsers = Math.max(0, rawModeUsers - 1);
206362
+ if (rawModeEnabled && rawModeUsers === 0) {
206363
+ setRawMode(false);
206364
+ rawModeEnabled = false;
206365
+ }
206327
206366
  };
206328
206367
  }, [isRawModeSupported, setRawMode]);
206329
206368
  import_react27.useEffect(() => {
@@ -219183,6 +219222,11 @@ function ChannelsPanel({ manager, onClose, activePersonId, activePersonName, onP
219183
219222
  const [createName, setCreateName] = import_react46.useState("");
219184
219223
  const [createDesc, setCreateDesc] = import_react46.useState("");
219185
219224
  const [chatInput, setChatInput] = import_react46.useState("");
219225
+ const lastSubmitTimeRef = import_react46.useRef(0);
219226
+ const [mentionActive, setMentionActive] = import_react46.useState(false);
219227
+ const [mentionQuery, setMentionQuery] = import_react46.useState("");
219228
+ const [mentionIndex, setMentionIndex] = import_react46.useState(0);
219229
+ const [chatMembers, setChatMembers] = import_react46.useState([]);
219186
219230
  const [inviteName, setInviteName] = import_react46.useState("");
219187
219231
  const loadChannels = () => {
219188
219232
  try {
@@ -219202,6 +219246,7 @@ function ChannelsPanel({ manager, onClose, activePersonId, activePersonName, onP
219202
219246
  setSelectedChannel(ch2);
219203
219247
  const result = manager.readMessages(ch2.id, 50);
219204
219248
  setMessages(result?.messages || []);
219249
+ setChatMembers(manager.getMembers(ch2.id));
219205
219250
  setMode("chat");
219206
219251
  }
219207
219252
  };
@@ -219213,7 +219258,68 @@ function ChannelsPanel({ manager, onClose, activePersonId, activePersonName, onP
219213
219258
  setMode("members");
219214
219259
  }
219215
219260
  };
219261
+ const mentionCandidates = import_react46.useMemo(() => {
219262
+ if (!mentionActive)
219263
+ return [];
219264
+ const q7 = mentionQuery.toLowerCase();
219265
+ return chatMembers.filter((m5) => m5.assistantName.toLowerCase().includes(q7));
219266
+ }, [mentionActive, mentionQuery, chatMembers]);
219267
+ const handleChatInputChange = (value) => {
219268
+ const prev = chatInput;
219269
+ setChatInput(value);
219270
+ if (value.length === prev.length + 1 && value[value.length - 1] === "@" && !mentionActive) {
219271
+ setMentionActive(true);
219272
+ setMentionQuery("");
219273
+ setMentionIndex(0);
219274
+ return;
219275
+ }
219276
+ if (mentionActive) {
219277
+ const lastAt = value.lastIndexOf("@");
219278
+ if (lastAt >= 0) {
219279
+ const afterAt = value.slice(lastAt + 1);
219280
+ if (lastAt > prev.lastIndexOf("@") + prev.slice(prev.lastIndexOf("@") + 1).length + 1) {
219281
+ setMentionActive(false);
219282
+ } else {
219283
+ setMentionQuery(afterAt);
219284
+ setMentionIndex(0);
219285
+ }
219286
+ } else {
219287
+ setMentionActive(false);
219288
+ }
219289
+ }
219290
+ };
219291
+ const insertMention = (memberName) => {
219292
+ const lastAt = chatInput.lastIndexOf("@");
219293
+ if (lastAt >= 0) {
219294
+ const before = chatInput.slice(0, lastAt);
219295
+ const needsQuotes = memberName.includes(" ");
219296
+ const mention = needsQuotes ? `@"${memberName}" ` : `@${memberName} `;
219297
+ setChatInput(before + mention);
219298
+ }
219299
+ setMentionActive(false);
219300
+ setMentionQuery("");
219301
+ setMentionIndex(0);
219302
+ };
219216
219303
  useSafeInput((input, key) => {
219304
+ if (mentionActive && mode === "chat") {
219305
+ if (key.escape) {
219306
+ setMentionActive(false);
219307
+ setMentionQuery("");
219308
+ return;
219309
+ }
219310
+ if (key.upArrow) {
219311
+ setMentionIndex((prev) => Math.max(0, prev - 1));
219312
+ return;
219313
+ }
219314
+ if (key.downArrow) {
219315
+ setMentionIndex((prev) => Math.min(mentionCandidates.length - 1, prev + 1));
219316
+ return;
219317
+ }
219318
+ if (key.tab && mentionCandidates.length > 0) {
219319
+ insertMention(mentionCandidates[mentionIndex].assistantName);
219320
+ return;
219321
+ }
219322
+ }
219217
219323
  const isTextEntry = mode === "create-name" || mode === "create-desc" || mode === "invite" || mode === "chat";
219218
219324
  if (key.escape || input === "q" && !isTextEntry) {
219219
219325
  if (key.escape && mode === "list" || input === "q" && mode === "list") {
@@ -219222,6 +219328,7 @@ function ChannelsPanel({ manager, onClose, activePersonId, activePersonName, onP
219222
219328
  setMode("list");
219223
219329
  setSelectedChannel(null);
219224
219330
  setStatusMessage(null);
219331
+ setMentionActive(false);
219225
219332
  }
219226
219333
  return;
219227
219334
  }
@@ -219307,7 +219414,7 @@ function ChannelsPanel({ manager, onClose, activePersonId, activePersonName, onP
219307
219414
  }, undefined, false, undefined, this),
219308
219415
  /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Text3, {
219309
219416
  color: "gray",
219310
- children: mode === "list" ? "q:close c:create enter:open m:members i:invite l:leave d:delete r:refresh" : mode === "chat" ? "esc:back (type to chat)" : mode === "members" ? "esc:back" : mode === "delete-confirm" ? "y:confirm n:cancel" : mode === "create-confirm" ? "y:confirm n:cancel" : "Enter to continue"
219417
+ children: mode === "list" ? "q:close c:create enter:open m:members i:invite l:leave d:delete r:refresh" : mode === "chat" ? "esc:back (type to chat, @ to mention)" : mode === "members" ? "esc:back" : mode === "delete-confirm" ? "y:confirm n:cancel" : mode === "create-confirm" ? "y:confirm n:cancel" : "Enter to continue"
219311
219418
  }, undefined, false, undefined, this)
219312
219419
  ]
219313
219420
  }, undefined, true, undefined, this);
@@ -219449,13 +219556,18 @@ function ChannelsPanel({ manager, onClose, activePersonId, activePersonName, onP
219449
219556
  }, undefined, false, undefined, this),
219450
219557
  /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(build_default2, {
219451
219558
  value: chatInput,
219452
- onChange: setChatInput,
219559
+ onChange: handleChatInputChange,
219453
219560
  onSubmit: () => {
219454
219561
  if (chatInput.trim()) {
219562
+ const now2 = Date.now();
219563
+ if (now2 - lastSubmitTimeRef.current < 500)
219564
+ return;
219565
+ lastSubmitTimeRef.current = now2;
219455
219566
  const msg = chatInput.trim();
219456
219567
  const result = activePersonId && activePersonName ? manager.sendAs(selectedChannel.id, msg, activePersonId, activePersonName) : manager.send(selectedChannel.id, msg);
219457
219568
  if (result.success) {
219458
219569
  setChatInput("");
219570
+ setMentionActive(false);
219459
219571
  const updated = manager.readMessages(selectedChannel.id, 50);
219460
219572
  setMessages(updated?.messages || []);
219461
219573
  if (activePersonId && activePersonName && onPersonMessage && selectedChannel) {
@@ -219485,9 +219597,40 @@ function ChannelsPanel({ manager, onClose, activePersonId, activePersonName, onP
219485
219597
  }
219486
219598
  }
219487
219599
  },
219488
- placeholder: "Type a message..."
219600
+ placeholder: "Type a message... (@ to mention)"
219489
219601
  }, undefined, false, undefined, this)
219490
219602
  ]
219603
+ }, undefined, true, undefined, this),
219604
+ mentionActive && mentionCandidates.length > 0 && /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Box_default, {
219605
+ flexDirection: "column",
219606
+ paddingX: 1,
219607
+ borderStyle: "single",
219608
+ borderColor: "yellow",
219609
+ marginTop: 0,
219610
+ children: [
219611
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Text3, {
219612
+ color: "yellow",
219613
+ bold: true,
219614
+ children: "Members (Tab to select, Esc to dismiss)"
219615
+ }, undefined, false, undefined, this),
219616
+ mentionCandidates.slice(0, 8).map((m5, i5) => /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Box_default, {
219617
+ children: [
219618
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Text3, {
219619
+ color: i5 === mentionIndex ? "blue" : undefined,
219620
+ children: i5 === mentionIndex ? "\u25B8 " : " "
219621
+ }, undefined, false, undefined, this),
219622
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Text3, {
219623
+ bold: i5 === mentionIndex,
219624
+ color: i5 === mentionIndex ? "blue" : undefined,
219625
+ children: m5.assistantName
219626
+ }, undefined, false, undefined, this),
219627
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Text3, {
219628
+ color: "gray",
219629
+ children: m5.memberType === "person" ? " [person]" : " [assistant]"
219630
+ }, undefined, false, undefined, this)
219631
+ ]
219632
+ }, m5.assistantId, true, undefined, this))
219633
+ ]
219491
219634
  }, undefined, true, undefined, this)
219492
219635
  ]
219493
219636
  }, undefined, true, undefined, this);
@@ -233699,12 +233842,14 @@ When done, report the result.`);
233699
233842
  const isActiveMember = activeAssistantId && members.some((m5) => m5.assistantId === activeAssistantId && m5.memberType === "assistant");
233700
233843
  const mentions = parseMentions(message);
233701
233844
  let activeAssistantTargeted = true;
233702
- if (mentions.length > 0 && isActiveMember) {
233845
+ if (mentions.length > 0) {
233703
233846
  const assistantMembers = members.filter((m5) => m5.memberType === "assistant");
233704
233847
  const knownNames = assistantMembers.map((m5) => ({ id: m5.assistantId, name: m5.assistantName }));
233705
233848
  const resolved = mentions.map((m5) => resolveNameToKnown(m5, knownNames)).filter(Boolean);
233706
233849
  if (resolved.length > 0) {
233707
233850
  activeAssistantTargeted = resolved.some((r6) => r6.id === activeAssistantId);
233851
+ } else {
233852
+ activeAssistantTargeted = false;
233708
233853
  }
233709
233854
  }
233710
233855
  if (isActiveMember && activeAssistantTargeted) {
@@ -234504,7 +234649,7 @@ Interactive Mode:
234504
234649
  // packages/terminal/src/index.tsx
234505
234650
  var jsx_dev_runtime44 = __toESM(require_jsx_dev_runtime(), 1);
234506
234651
  setRuntime(bunRuntime);
234507
- var VERSION4 = "1.1.17";
234652
+ var VERSION4 = "1.1.18";
234508
234653
  var SYNC_START = "\x1B[?2026h";
234509
234654
  var SYNC_END = "\x1B[?2026l";
234510
234655
  function enableSynchronizedOutput() {
@@ -234644,4 +234789,4 @@ export {
234644
234789
  main
234645
234790
  };
234646
234791
 
234647
- //# debugId=06504F1621F0D4C464756E2164756E21
234792
+ //# debugId=C8555F61FD8AD49264756E2164756E21