@canonmsg/backend-contracts 0.2.2 → 0.2.4
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/cjs/message.js +1 -0
- package/dist/cjs/turnProtocol.js +49 -2
- package/dist/message.d.ts +1 -1
- package/dist/message.js +1 -0
- package/dist/turnProtocol.d.ts +7 -0
- package/dist/turnProtocol.js +46 -2
- package/package.json +1 -1
package/dist/cjs/message.js
CHANGED
package/dist/cjs/turnProtocol.js
CHANGED
|
@@ -1,14 +1,29 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WAITING_INPUT_STALE_THRESHOLD_MS = exports.ACTIVE_TURN_STALE_THRESHOLD_MS = void 0;
|
|
3
4
|
exports.normalizeTurnMetadata = normalizeTurnMetadata;
|
|
4
5
|
exports.isTurnOpen = isTurnOpen;
|
|
6
|
+
exports.getTurnStateStaleThresholdMs = getTurnStateStaleThresholdMs;
|
|
7
|
+
exports.isTurnStateStale = isTurnStateStale;
|
|
5
8
|
exports.resolveTurnMessageSemantics = resolveTurnMessageSemantics;
|
|
6
9
|
exports.shouldPromoteConversationMessage = shouldPromoteConversationMessage;
|
|
7
10
|
exports.shouldTriggerAgentTurn = shouldTriggerAgentTurn;
|
|
8
11
|
exports.normalizeRuntimeTurnState = normalizeRuntimeTurnState;
|
|
12
|
+
exports.ACTIVE_TURN_STALE_THRESHOLD_MS = 30 * 60 * 1000;
|
|
13
|
+
exports.WAITING_INPUT_STALE_THRESHOLD_MS = 12 * 60 * 60 * 1000;
|
|
9
14
|
function isRecord(value) {
|
|
10
15
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
11
16
|
}
|
|
17
|
+
function isHiddenRuntimeCardMetadata(metadata) {
|
|
18
|
+
if (!isRecord(metadata) || typeof metadata.type !== 'string')
|
|
19
|
+
return false;
|
|
20
|
+
return metadata.type === 'approval_reply'
|
|
21
|
+
|| metadata.type === 'approval_outcome'
|
|
22
|
+
|| metadata.type === 'question_reply'
|
|
23
|
+
|| metadata.type === 'plan_approval_reply'
|
|
24
|
+
|| metadata.type === 'runtime_input_reply'
|
|
25
|
+
|| metadata.type === 'runtime_input_outcome';
|
|
26
|
+
}
|
|
12
27
|
function normalizeTurnMetadata(metadata) {
|
|
13
28
|
if (!isRecord(metadata))
|
|
14
29
|
return null;
|
|
@@ -33,9 +48,33 @@ function normalizeTurnMetadata(metadata) {
|
|
|
33
48
|
function isTurnOpen(turnState) {
|
|
34
49
|
if (!turnState)
|
|
35
50
|
return false;
|
|
36
|
-
|
|
51
|
+
const open = turnState.state !== 'idle'
|
|
37
52
|
&& turnState.state !== 'completed'
|
|
38
53
|
&& turnState.state !== 'interrupted';
|
|
54
|
+
if (!open)
|
|
55
|
+
return false;
|
|
56
|
+
return !isTurnStateStale(turnState);
|
|
57
|
+
}
|
|
58
|
+
function getTurnStateStaleThresholdMs(state) {
|
|
59
|
+
return state === 'waiting_input'
|
|
60
|
+
? exports.WAITING_INPUT_STALE_THRESHOLD_MS
|
|
61
|
+
: exports.ACTIVE_TURN_STALE_THRESHOLD_MS;
|
|
62
|
+
}
|
|
63
|
+
function isTurnStateStale(turnState) {
|
|
64
|
+
if (!turnState)
|
|
65
|
+
return false;
|
|
66
|
+
if (turnState.state !== 'thinking'
|
|
67
|
+
&& turnState.state !== 'streaming'
|
|
68
|
+
&& turnState.state !== 'tool'
|
|
69
|
+
&& turnState.state !== 'waiting_input') {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
const updatedAt = turnState.turnUpdatedAt
|
|
73
|
+
?? turnState.updatedAt
|
|
74
|
+
?? turnState.openedAt;
|
|
75
|
+
if (updatedAt == null)
|
|
76
|
+
return false;
|
|
77
|
+
return Date.now() - updatedAt >= getTurnStateStaleThresholdMs(turnState.state);
|
|
39
78
|
}
|
|
40
79
|
function resolveTurnMessageSemantics(input) {
|
|
41
80
|
const turnMetadata = normalizeTurnMetadata(input.metadata);
|
|
@@ -48,6 +87,9 @@ function resolveTurnMessageSemantics(input) {
|
|
|
48
87
|
return isTurnOpen(input.senderTurnState) ? 'progress' : 'turn_complete';
|
|
49
88
|
}
|
|
50
89
|
function shouldPromoteConversationMessage(input) {
|
|
90
|
+
if (isHiddenRuntimeCardMetadata(input.metadata)) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
51
93
|
return resolveTurnMessageSemantics(input) !== 'progress';
|
|
52
94
|
}
|
|
53
95
|
function shouldTriggerAgentTurn(input) {
|
|
@@ -71,7 +113,12 @@ function normalizeRuntimeTurnState(value) {
|
|
|
71
113
|
|| value.state === 'waiting_input'
|
|
72
114
|
|| value.state === 'completed'
|
|
73
115
|
|| value.state === 'interrupted') {
|
|
74
|
-
return {
|
|
116
|
+
return {
|
|
117
|
+
state: value.state,
|
|
118
|
+
...(typeof value.openedAt === 'number' ? { openedAt: value.openedAt } : {}),
|
|
119
|
+
...(typeof value.updatedAt === 'number' ? { updatedAt: value.updatedAt } : {}),
|
|
120
|
+
...(typeof value.turnUpdatedAt === 'number' ? { turnUpdatedAt: value.turnUpdatedAt } : {}),
|
|
121
|
+
};
|
|
75
122
|
}
|
|
76
123
|
return null;
|
|
77
124
|
}
|
package/dist/message.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MediaAttachment } from './media.js';
|
|
2
2
|
export type SerializedSenderType = 'human' | 'ai_agent';
|
|
3
|
-
export type SerializedAgentClientType = 'claude-code' | 'openclaw' | 'codex' | 'generic';
|
|
3
|
+
export type SerializedAgentClientType = 'claude-code' | 'openclaw' | 'codex' | 'hermes' | 'generic';
|
|
4
4
|
export type SerializedContentType = 'text' | 'image' | 'audio' | 'file' | 'contact_card';
|
|
5
5
|
export interface ForwardedFrom {
|
|
6
6
|
sourceConversationId: string;
|
package/dist/message.js
CHANGED
package/dist/turnProtocol.d.ts
CHANGED
|
@@ -8,9 +8,16 @@ export interface TurnMetadata {
|
|
|
8
8
|
}
|
|
9
9
|
export interface TurnStateLike {
|
|
10
10
|
state: TurnLifecycleState;
|
|
11
|
+
openedAt?: number;
|
|
12
|
+
updatedAt?: number;
|
|
13
|
+
turnUpdatedAt?: number | null;
|
|
11
14
|
}
|
|
15
|
+
export declare const ACTIVE_TURN_STALE_THRESHOLD_MS: number;
|
|
16
|
+
export declare const WAITING_INPUT_STALE_THRESHOLD_MS: number;
|
|
12
17
|
export declare function normalizeTurnMetadata(metadata: unknown): TurnMetadata | null;
|
|
13
18
|
export declare function isTurnOpen(turnState: TurnStateLike | null | undefined): boolean;
|
|
19
|
+
export declare function getTurnStateStaleThresholdMs(state: TurnLifecycleState): number;
|
|
20
|
+
export declare function isTurnStateStale(turnState: TurnStateLike | null | undefined): boolean;
|
|
14
21
|
export declare function resolveTurnMessageSemantics(input: {
|
|
15
22
|
senderType: SenderType;
|
|
16
23
|
metadata?: unknown;
|
package/dist/turnProtocol.js
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
|
+
export const ACTIVE_TURN_STALE_THRESHOLD_MS = 30 * 60 * 1000;
|
|
2
|
+
export const WAITING_INPUT_STALE_THRESHOLD_MS = 12 * 60 * 60 * 1000;
|
|
1
3
|
function isRecord(value) {
|
|
2
4
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
3
5
|
}
|
|
6
|
+
function isHiddenRuntimeCardMetadata(metadata) {
|
|
7
|
+
if (!isRecord(metadata) || typeof metadata.type !== 'string')
|
|
8
|
+
return false;
|
|
9
|
+
return metadata.type === 'approval_reply'
|
|
10
|
+
|| metadata.type === 'approval_outcome'
|
|
11
|
+
|| metadata.type === 'question_reply'
|
|
12
|
+
|| metadata.type === 'plan_approval_reply'
|
|
13
|
+
|| metadata.type === 'runtime_input_reply'
|
|
14
|
+
|| metadata.type === 'runtime_input_outcome';
|
|
15
|
+
}
|
|
4
16
|
export function normalizeTurnMetadata(metadata) {
|
|
5
17
|
if (!isRecord(metadata))
|
|
6
18
|
return null;
|
|
@@ -25,9 +37,33 @@ export function normalizeTurnMetadata(metadata) {
|
|
|
25
37
|
export function isTurnOpen(turnState) {
|
|
26
38
|
if (!turnState)
|
|
27
39
|
return false;
|
|
28
|
-
|
|
40
|
+
const open = turnState.state !== 'idle'
|
|
29
41
|
&& turnState.state !== 'completed'
|
|
30
42
|
&& turnState.state !== 'interrupted';
|
|
43
|
+
if (!open)
|
|
44
|
+
return false;
|
|
45
|
+
return !isTurnStateStale(turnState);
|
|
46
|
+
}
|
|
47
|
+
export function getTurnStateStaleThresholdMs(state) {
|
|
48
|
+
return state === 'waiting_input'
|
|
49
|
+
? WAITING_INPUT_STALE_THRESHOLD_MS
|
|
50
|
+
: ACTIVE_TURN_STALE_THRESHOLD_MS;
|
|
51
|
+
}
|
|
52
|
+
export function isTurnStateStale(turnState) {
|
|
53
|
+
if (!turnState)
|
|
54
|
+
return false;
|
|
55
|
+
if (turnState.state !== 'thinking'
|
|
56
|
+
&& turnState.state !== 'streaming'
|
|
57
|
+
&& turnState.state !== 'tool'
|
|
58
|
+
&& turnState.state !== 'waiting_input') {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
const updatedAt = turnState.turnUpdatedAt
|
|
62
|
+
?? turnState.updatedAt
|
|
63
|
+
?? turnState.openedAt;
|
|
64
|
+
if (updatedAt == null)
|
|
65
|
+
return false;
|
|
66
|
+
return Date.now() - updatedAt >= getTurnStateStaleThresholdMs(turnState.state);
|
|
31
67
|
}
|
|
32
68
|
export function resolveTurnMessageSemantics(input) {
|
|
33
69
|
const turnMetadata = normalizeTurnMetadata(input.metadata);
|
|
@@ -40,6 +76,9 @@ export function resolveTurnMessageSemantics(input) {
|
|
|
40
76
|
return isTurnOpen(input.senderTurnState) ? 'progress' : 'turn_complete';
|
|
41
77
|
}
|
|
42
78
|
export function shouldPromoteConversationMessage(input) {
|
|
79
|
+
if (isHiddenRuntimeCardMetadata(input.metadata)) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
43
82
|
return resolveTurnMessageSemantics(input) !== 'progress';
|
|
44
83
|
}
|
|
45
84
|
export function shouldTriggerAgentTurn(input) {
|
|
@@ -63,7 +102,12 @@ export function normalizeRuntimeTurnState(value) {
|
|
|
63
102
|
|| value.state === 'waiting_input'
|
|
64
103
|
|| value.state === 'completed'
|
|
65
104
|
|| value.state === 'interrupted') {
|
|
66
|
-
return {
|
|
105
|
+
return {
|
|
106
|
+
state: value.state,
|
|
107
|
+
...(typeof value.openedAt === 'number' ? { openedAt: value.openedAt } : {}),
|
|
108
|
+
...(typeof value.updatedAt === 'number' ? { updatedAt: value.updatedAt } : {}),
|
|
109
|
+
...(typeof value.turnUpdatedAt === 'number' ? { turnUpdatedAt: value.turnUpdatedAt } : {}),
|
|
110
|
+
};
|
|
67
111
|
}
|
|
68
112
|
return null;
|
|
69
113
|
}
|