@canonmsg/agent-sdk 2.1.0 → 2.1.1

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.
@@ -55,6 +55,7 @@ export declare class CanonAgent {
55
55
  private readonly activeTurns;
56
56
  private readonly conversationMemberIds;
57
57
  private readonly pendingMembershipChanges;
58
+ private readonly typingSignals;
58
59
  private sseConnectedLogged;
59
60
  constructor(options: CanonAgentOptions);
60
61
  private ensureApprovalManager;
@@ -1,4 +1,4 @@
1
- import { ApprovalManager, CanonClient, buildCanonGroupContext, createTurnOutputController, createRuntimeStatePublisher, diffCanonMemberIds, FINAL_MESSAGE_HANDOFF_MS, RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildRuntimeCardOutcome, buildRuntimeInputOutcome, initRTDBAuth, rtdbRead, rtdbWrite, normalizeTurnMetadata, reachOutToCanonContact, resolveCanonReplyContext, resolveMessageActiveSelfContextId, resolveRuntimeProvenance, selectActiveSelfContexts, } from '@canonmsg/core';
1
+ import { ApprovalManager, CanonClient, buildCanonGroupContext, createTurnOutputController, createRuntimeStatePublisher, createTypingStatusPublisher, diffCanonMemberIds, FINAL_MESSAGE_HANDOFF_MS, RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildRuntimeCardOutcome, buildRuntimeInputOutcome, initRTDBAuth, rtdbRead, rtdbWrite, normalizeTurnMetadata, reachOutToCanonContact, resolveCanonReplyContext, resolveMessageActiveSelfContextId, resolveRuntimeProvenance, selectActiveSelfContexts, } from '@canonmsg/core';
2
2
  import { randomUUID } from 'node:crypto';
3
3
  import { AuthManager } from './auth.js';
4
4
  import { Debouncer } from './debouncer.js';
@@ -259,6 +259,7 @@ export class CanonAgent {
259
259
  activeTurns = new Map();
260
260
  conversationMemberIds = new Map();
261
261
  pendingMembershipChanges = new Map();
262
+ typingSignals;
262
263
  sseConnectedLogged = false;
263
264
  constructor(options) {
264
265
  this.options = {
@@ -271,6 +272,11 @@ export class CanonAgent {
271
272
  ...options,
272
273
  };
273
274
  this.apiClient = new CanonClient(this.options.apiKey, this.options.baseUrl);
275
+ this.typingSignals = createTypingStatusPublisher({
276
+ setTyping: (conversationId, typing, status) => status
277
+ ? this.apiClient.setTyping(conversationId, typing, status)
278
+ : this.apiClient.setTyping(conversationId, typing),
279
+ });
274
280
  this.authManager = new AuthManager(this.apiClient);
275
281
  this.debouncer = new Debouncer(this.options.debounceMs);
276
282
  const apiClient = this.apiClient;
@@ -1002,7 +1008,7 @@ export class CanonAgent {
1002
1008
  }
1003
1009
  await Promise.all([
1004
1010
  this.apiClient.clearStreaming(conversationId).catch(() => { }),
1005
- this.apiClient.setTyping(conversationId, false).catch(() => { }),
1011
+ this.typingSignals.clear(conversationId).catch(() => { }),
1006
1012
  ]);
1007
1013
  }
1008
1014
  abortActiveTurns(conversationId) {
@@ -1149,14 +1155,13 @@ export class CanonAgent {
1149
1155
  };
1150
1156
  // Show thinking indicator and keep it alive (5s client-side expiry)
1151
1157
  try {
1152
- await this.apiClient.setTyping(conversationId, true, 'thinking');
1158
+ await this.typingSignals.start(conversationId, 'thinking');
1153
1159
  }
1154
1160
  catch {
1155
1161
  // Non-critical
1156
1162
  }
1157
1163
  await setLiveState('thinking', 'Thinking...', 'thinking');
1158
1164
  const thinkingKeepalive = setInterval(() => {
1159
- this.apiClient.setTyping(conversationId, true, 'thinking').catch(() => { });
1160
1165
  if (turnState === 'thinking') {
1161
1166
  turnOutput.setStatus('thinking', 'Thinking...').catch(() => { });
1162
1167
  }
@@ -1189,7 +1194,7 @@ export class CanonAgent {
1189
1194
  const replyFinal = async (text, options) => {
1190
1195
  throwIfAborted();
1191
1196
  try {
1192
- await this.apiClient.setTyping(conversationId, true, 'typing');
1197
+ await this.typingSignals.start(conversationId, 'typing');
1193
1198
  }
1194
1199
  catch { }
1195
1200
  throwIfAborted();
@@ -1206,7 +1211,7 @@ export class CanonAgent {
1206
1211
  });
1207
1212
  await sleep(FINAL_MESSAGE_HANDOFF_MS);
1208
1213
  try {
1209
- await this.apiClient.setTyping(conversationId, false);
1214
+ await this.typingSignals.clear(conversationId);
1210
1215
  }
1211
1216
  catch { }
1212
1217
  return result;
@@ -1355,7 +1360,7 @@ export class CanonAgent {
1355
1360
  catch { }
1356
1361
  await writeTurn('waiting_input');
1357
1362
  try {
1358
- await this.apiClient.setTyping(conversationId, false);
1363
+ await this.typingSignals.clear(conversationId);
1359
1364
  }
1360
1365
  catch { }
1361
1366
  const result = await manager.requestApproval(conversationId, request.toolName, request.toolInput ?? {}, {
@@ -1379,7 +1384,7 @@ export class CanonAgent {
1379
1384
  }
1380
1385
  catch { }
1381
1386
  try {
1382
- await this.apiClient.setTyping(conversationId, true, 'thinking');
1387
+ await this.typingSignals.start(conversationId, 'thinking');
1383
1388
  }
1384
1389
  catch { }
1385
1390
  await setLiveState('thinking', 'Thinking...', 'thinking');
@@ -1446,7 +1451,7 @@ export class CanonAgent {
1446
1451
  catch { }
1447
1452
  await writeTurn('waiting_input');
1448
1453
  try {
1449
- await this.apiClient.setTyping(conversationId, false);
1454
+ await this.typingSignals.clear(conversationId);
1450
1455
  }
1451
1456
  catch { }
1452
1457
  while (Date.now() < expiresAtMs) {
@@ -1520,7 +1525,7 @@ export class CanonAgent {
1520
1525
  }
1521
1526
  catch { }
1522
1527
  try {
1523
- await this.apiClient.setTyping(conversationId, true, 'thinking');
1528
+ await this.typingSignals.start(conversationId, 'thinking');
1524
1529
  }
1525
1530
  catch { }
1526
1531
  await setLiveState('thinking', 'Thinking...', 'thinking');
@@ -1619,7 +1624,7 @@ export class CanonAgent {
1619
1624
  catch { }
1620
1625
  await writeTurn('waiting_input');
1621
1626
  try {
1622
- await this.apiClient.setTyping(conversationId, false);
1627
+ await this.typingSignals.clear(conversationId);
1623
1628
  }
1624
1629
  catch { }
1625
1630
  while (Date.now() < expiresAtMs) {
@@ -1695,7 +1700,7 @@ export class CanonAgent {
1695
1700
  }
1696
1701
  catch { }
1697
1702
  try {
1698
- await this.apiClient.setTyping(conversationId, true, 'thinking');
1703
+ await this.typingSignals.start(conversationId, 'thinking');
1699
1704
  }
1700
1705
  catch { }
1701
1706
  await setLiveState('thinking', 'Thinking...', 'thinking');
@@ -1726,7 +1731,7 @@ export class CanonAgent {
1726
1731
  const replyWithFile = async (filePath, text = '', options) => {
1727
1732
  throwIfAborted();
1728
1733
  try {
1729
- await this.apiClient.setTyping(conversationId, true, 'typing');
1734
+ await this.typingSignals.start(conversationId, 'typing');
1730
1735
  }
1731
1736
  catch { }
1732
1737
  throwIfAborted();
@@ -1756,7 +1761,7 @@ export class CanonAgent {
1756
1761
  }
1757
1762
  finally {
1758
1763
  try {
1759
- await this.apiClient.setTyping(conversationId, false);
1764
+ await this.typingSignals.clear(conversationId);
1760
1765
  }
1761
1766
  catch { }
1762
1767
  }
@@ -1876,7 +1881,7 @@ export class CanonAgent {
1876
1881
  catch { }
1877
1882
  await writeTurn('waiting_input');
1878
1883
  try {
1879
- await this.apiClient.setTyping(conversationId, false);
1884
+ await this.typingSignals.clear(conversationId);
1880
1885
  }
1881
1886
  catch { }
1882
1887
  if (text) {
@@ -1923,7 +1928,7 @@ export class CanonAgent {
1923
1928
  clearInterval(thinkingKeepalive);
1924
1929
  // Always clear typing when done
1925
1930
  try {
1926
- await this.apiClient.setTyping(conversationId, false);
1931
+ await this.typingSignals.clear(conversationId);
1927
1932
  }
1928
1933
  catch { }
1929
1934
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonmsg/agent-sdk",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "Canon Agent SDK — build AI agents that participate in Canon conversations",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -28,7 +28,7 @@
28
28
  "node": ">=18.0.0"
29
29
  },
30
30
  "dependencies": {
31
- "@canonmsg/core": "^1.2.0"
31
+ "@canonmsg/core": "^1.3.0"
32
32
  },
33
33
  "publishConfig": {
34
34
  "access": "public"