@canonmsg/agent-sdk 3.2.5 → 3.3.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.
- package/dist/canon-agent.js +51 -14
- package/dist/types.d.ts +2 -0
- package/package.json +2 -2
package/dist/canon-agent.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ApprovalManager, CanonClient, ControlChannelPoller, buildCanonTurnContextV2, buildCanonGroupContext, buildParticipationHistorySnapshot, createTurnOutputController, createRuntimeStatePublisher, createTypingStatusPublisher, diffCanonMemberIds, FINAL_MESSAGE_HANDOFF_MS, RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildRuntimeCardOutcome, buildRuntimeInputOutcome, initRTDBAuth, normalizeTurnMetadata, reachOutToCanonContact, resolveCanonReplyContext, resolveMessageActiveSelfContextId, resolveRuntimeProvenance, selectActiveSelfContexts, renderCanonHostInboundContent, } from '@canonmsg/core';
|
|
2
|
-
import { randomUUID } from 'node:crypto';
|
|
1
|
+
import { ApprovalManager, CanonClient, ControlChannelPoller, buildCanonTurnContextV2, buildCanonGroupContext, buildParticipationHistorySnapshot, createTurnOutputController, createRuntimeStatePublisher, createTypingStatusPublisher, diffCanonMemberIds, FINAL_MESSAGE_HANDOFF_MS, RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildRuntimeCardOutcome, buildRuntimeInputOutcome, initRTDBAuth, normalizeTurnMetadata, reachOutToCanonContact, resolveCanonReplyContext, resolveMessageActiveSelfContextId, resolveRuntimeProvenance, selectActiveSelfContexts, renderCanonHostInboundContent, sendMessageWithRetry, } from '@canonmsg/core';
|
|
2
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
3
3
|
import { AuthManager } from './auth.js';
|
|
4
4
|
import { Debouncer } from './debouncer.js';
|
|
5
5
|
import { buildRuntimeCardCreateArgs } from './runtime-card.js';
|
|
@@ -12,6 +12,7 @@ const RUNTIME_PRIMITIVE_DEDUPE_MAX = 1_000;
|
|
|
12
12
|
const DEFAULT_RUNTIME_INPUT_TIMEOUT_MS = 5 * 60_000;
|
|
13
13
|
const RUNTIME_INPUT_POLL_MS = 1_000;
|
|
14
14
|
const RUNTIME_INPUT_ID_PATTERN = /^[A-Za-z0-9_.:-]{1,160}$/;
|
|
15
|
+
const SDK_MESSAGE_ID_READABLE_MAX = 120;
|
|
15
16
|
const SDK_RUNTIME_CAPABILITIES = {
|
|
16
17
|
supportsInterrupt: false,
|
|
17
18
|
supportsInputInterrupt: false,
|
|
@@ -32,8 +33,8 @@ const DEFAULT_SDK_RUNTIME_DESCRIPTOR = {
|
|
|
32
33
|
responder: 'agent_owner',
|
|
33
34
|
result: 'action_or_values',
|
|
34
35
|
maxTimeoutMs: 30 * 60_000,
|
|
35
|
-
blockKinds: ['summary', 'metricGrid', 'chart', 'table', 'list', 'callout', 'actions'],
|
|
36
|
-
actionFieldTypes: ['text', 'textarea', 'select', 'multiSelect', 'boolean'],
|
|
36
|
+
blockKinds: ['summary', 'metricGrid', 'chart', 'table', 'list', 'callout', 'actions', 'mediaPreview', 'details'],
|
|
37
|
+
actionFieldTypes: ['text', 'textarea', 'select', 'multiSelect', 'boolean', 'date', 'number', 'currency', 'searchSelect', 'lineItems'],
|
|
37
38
|
native: true,
|
|
38
39
|
},
|
|
39
40
|
},
|
|
@@ -167,6 +168,19 @@ function safeRuntimeCardId(value) {
|
|
|
167
168
|
? normalized
|
|
168
169
|
: `card_${randomUUID()}`;
|
|
169
170
|
}
|
|
171
|
+
function buildSdkMessageId(parts) {
|
|
172
|
+
const raw = parts
|
|
173
|
+
.map((part) => part == null ? '' : String(part))
|
|
174
|
+
.filter(Boolean)
|
|
175
|
+
.join(':');
|
|
176
|
+
const hash = createHash('sha256').update(raw || 'sdk-message').digest('hex').slice(0, 16);
|
|
177
|
+
const readable = (raw || 'sdk-message')
|
|
178
|
+
.replace(/[^A-Za-z0-9_.:-]+/g, '_')
|
|
179
|
+
.replace(/_+/g, '_')
|
|
180
|
+
.replace(/^[:_.-]+|[:_.-]+$/g, '')
|
|
181
|
+
.slice(0, SDK_MESSAGE_ID_READABLE_MAX);
|
|
182
|
+
return `${readable || 'sdk-message'}:${hash}`;
|
|
183
|
+
}
|
|
170
184
|
function isRuntimePrimitiveId(value) {
|
|
171
185
|
return value === 'runtime.status'
|
|
172
186
|
|| value === 'runtime.reasoning.set'
|
|
@@ -1101,6 +1115,7 @@ export class CanonAgent {
|
|
|
1101
1115
|
const turnOpenedAt = Date.now();
|
|
1102
1116
|
let turnState = 'thinking';
|
|
1103
1117
|
let shouldPersistTurnState = false;
|
|
1118
|
+
let durableMessageSequence = 0;
|
|
1104
1119
|
const agentId = this.agentId;
|
|
1105
1120
|
const runtimeState = this.createRuntimeStatePublisher();
|
|
1106
1121
|
const queueDepth = () => this.sessionManager?.getQueueDepth(conversationId) ?? 0;
|
|
@@ -1208,7 +1223,7 @@ export class CanonAgent {
|
|
|
1208
1223
|
throwIfAborted();
|
|
1209
1224
|
const sendOptions = withActiveSelfContext(options);
|
|
1210
1225
|
const turnTrail = turnOutput.getFinalTrail();
|
|
1211
|
-
const result = await
|
|
1226
|
+
const result = await sendDurableMessage(text, {
|
|
1212
1227
|
...sendOptions,
|
|
1213
1228
|
metadata: {
|
|
1214
1229
|
...(sendOptions.metadata ?? {}),
|
|
@@ -1216,7 +1231,7 @@ export class CanonAgent {
|
|
|
1216
1231
|
turnSemantics: 'turn_complete',
|
|
1217
1232
|
...(turnTrail.length > 0 ? { turnTrail } : {}),
|
|
1218
1233
|
},
|
|
1219
|
-
});
|
|
1234
|
+
}, ['sdk', 'final', conversationId, turnId]);
|
|
1220
1235
|
await sleep(FINAL_MESSAGE_HANDOFF_MS);
|
|
1221
1236
|
try {
|
|
1222
1237
|
await this.typingSignals.clear(conversationId);
|
|
@@ -1266,6 +1281,16 @@ export class CanonAgent {
|
|
|
1266
1281
|
return base;
|
|
1267
1282
|
return activeSelfContextId ? { ...base, selfContextId: activeSelfContextId } : base;
|
|
1268
1283
|
};
|
|
1284
|
+
const sendDurableMessage = (text, options, fallbackMessageIdParts) => {
|
|
1285
|
+
const messageId = options?.messageId
|
|
1286
|
+
?? buildSdkMessageId([...fallbackMessageIdParts, durableMessageSequence += 1]);
|
|
1287
|
+
return sendMessageWithRetry(this.apiClient, conversationId, text, {
|
|
1288
|
+
...(options ?? {}),
|
|
1289
|
+
messageId,
|
|
1290
|
+
}, {
|
|
1291
|
+
sleep: (ms) => sleepWithAbort(ms, abortController.signal),
|
|
1292
|
+
});
|
|
1293
|
+
};
|
|
1269
1294
|
// Build agent context (fallback to minimal if not yet received)
|
|
1270
1295
|
const agent = this.agentContext ?? {
|
|
1271
1296
|
agentId: this.agentId,
|
|
@@ -1549,14 +1574,14 @@ export class CanonAgent {
|
|
|
1549
1574
|
kind: request.kind,
|
|
1550
1575
|
reason: result.status,
|
|
1551
1576
|
});
|
|
1552
|
-
await
|
|
1577
|
+
await sendDurableMessage(outcome.text, {
|
|
1553
1578
|
metadata: {
|
|
1554
1579
|
...outcome.metadata,
|
|
1555
1580
|
turnId: request.turnId ?? turnId,
|
|
1556
1581
|
turnSemantics: 'control',
|
|
1557
1582
|
replyBehavior: 'suppress_auto_reply',
|
|
1558
1583
|
},
|
|
1559
|
-
});
|
|
1584
|
+
}, ['sdk', 'runtime-input-outcome', conversationId, request.turnId ?? turnId, inputId, result.status]);
|
|
1560
1585
|
throwIfAborted();
|
|
1561
1586
|
shouldPersistTurnState = false;
|
|
1562
1587
|
try {
|
|
@@ -1725,14 +1750,14 @@ export class CanonAgent {
|
|
|
1725
1750
|
const outcome = buildRuntimeCardOutcome(cardId, resolutionStatus, {
|
|
1726
1751
|
reason: resolutionStatus,
|
|
1727
1752
|
});
|
|
1728
|
-
await
|
|
1753
|
+
await sendDurableMessage(outcome.text, {
|
|
1729
1754
|
metadata: {
|
|
1730
1755
|
...outcome.metadata,
|
|
1731
1756
|
turnId: request.turnId ?? turnId,
|
|
1732
1757
|
turnSemantics: 'control',
|
|
1733
1758
|
replyBehavior: 'suppress_auto_reply',
|
|
1734
1759
|
},
|
|
1735
|
-
});
|
|
1760
|
+
}, ['sdk', 'runtime-card-outcome', conversationId, request.turnId ?? turnId, cardId, resolutionStatus]);
|
|
1736
1761
|
throwIfAborted();
|
|
1737
1762
|
shouldPersistTurnState = false;
|
|
1738
1763
|
try {
|
|
@@ -1754,14 +1779,14 @@ export class CanonAgent {
|
|
|
1754
1779
|
if (abortController.signal.aborted || isAbortLikeError(error)) {
|
|
1755
1780
|
if (shouldSendInterruptedOutcome) {
|
|
1756
1781
|
const outcome = buildRuntimeCardOutcome(cardId, 'cancelled', { reason: 'interrupted' });
|
|
1757
|
-
await
|
|
1782
|
+
await sendDurableMessage(outcome.text, {
|
|
1758
1783
|
metadata: {
|
|
1759
1784
|
...outcome.metadata,
|
|
1760
1785
|
turnId: request.turnId ?? turnId,
|
|
1761
1786
|
turnSemantics: 'control',
|
|
1762
1787
|
replyBehavior: 'suppress_auto_reply',
|
|
1763
1788
|
},
|
|
1764
|
-
}).catch(() => { });
|
|
1789
|
+
}, ['sdk', 'runtime-card-outcome', conversationId, request.turnId ?? turnId, cardId, 'interrupted']).catch(() => { });
|
|
1765
1790
|
}
|
|
1766
1791
|
throw error;
|
|
1767
1792
|
}
|
|
@@ -1886,6 +1911,18 @@ export class CanonAgent {
|
|
|
1886
1911
|
turnOutput.appendBlock(block);
|
|
1887
1912
|
void writeTurn('streaming');
|
|
1888
1913
|
},
|
|
1914
|
+
appendTextSegmentDelta: (id, delta) => {
|
|
1915
|
+
throwIfAborted();
|
|
1916
|
+
turnState = 'streaming';
|
|
1917
|
+
turnOutput.appendTextSegmentDelta(id, delta);
|
|
1918
|
+
void writeTurn('streaming');
|
|
1919
|
+
},
|
|
1920
|
+
replaceTextSegmentSnapshot: (id, text) => {
|
|
1921
|
+
throwIfAborted();
|
|
1922
|
+
turnState = 'streaming';
|
|
1923
|
+
turnOutput.replaceTextSegmentSnapshot(id, text);
|
|
1924
|
+
void writeTurn('streaming');
|
|
1925
|
+
},
|
|
1889
1926
|
addBlock: async (block) => {
|
|
1890
1927
|
throwIfAborted();
|
|
1891
1928
|
return turnOutput.addBlock(block);
|
|
@@ -1933,13 +1970,13 @@ export class CanonAgent {
|
|
|
1933
1970
|
}
|
|
1934
1971
|
catch { }
|
|
1935
1972
|
if (text) {
|
|
1936
|
-
await
|
|
1973
|
+
await sendDurableMessage(text, {
|
|
1937
1974
|
metadata: {
|
|
1938
1975
|
turnId,
|
|
1939
1976
|
turnSemantics: 'control',
|
|
1940
1977
|
replyBehavior: 'suppress_auto_reply',
|
|
1941
1978
|
},
|
|
1942
|
-
});
|
|
1979
|
+
}, ['sdk', 'waiting-input-note', conversationId, turnId]);
|
|
1943
1980
|
}
|
|
1944
1981
|
},
|
|
1945
1982
|
},
|
package/dist/types.d.ts
CHANGED
|
@@ -33,6 +33,8 @@ export interface TurnController {
|
|
|
33
33
|
setStreaming: (text: string) => Promise<void>;
|
|
34
34
|
appendDelta: (delta: string) => void;
|
|
35
35
|
appendBlock: (block: string) => void;
|
|
36
|
+
appendTextSegmentDelta: (id: string, delta: string) => void;
|
|
37
|
+
replaceTextSegmentSnapshot: (id: string, text: string) => void;
|
|
36
38
|
addBlock: (block: TurnOutputBlockInput) => Promise<TurnOutputBlock>;
|
|
37
39
|
updateBlock: (id: string, patch: Partial<Omit<TurnOutputBlockInput, 'id' | 'sequence'>>) => Promise<TurnOutputBlock | null>;
|
|
38
40
|
completeBlock: (id: string, patch?: Partial<Omit<TurnOutputBlockInput, 'id' | 'sequence' | 'status'>>) => Promise<TurnOutputBlock | null>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonmsg/agent-sdk",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.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": "^2.
|
|
31
|
+
"@canonmsg/core": "^2.8.1"
|
|
32
32
|
},
|
|
33
33
|
"publishConfig": {
|
|
34
34
|
"access": "public"
|