@canonmsg/core 0.18.1 → 0.19.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.
- package/dist/approval-format.d.ts +8 -1
- package/dist/approval-format.js +28 -6
- package/dist/approval-manager.d.ts +11 -2
- package/dist/approval-manager.js +51 -27
- package/dist/approval-types.d.ts +40 -0
- package/dist/approval-types.js +189 -0
- package/dist/browser.d.ts +4 -2
- package/dist/browser.js +2 -0
- package/dist/host-runtime.d.ts +4 -1
- package/dist/host-runtime.js +18 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +2 -1
- package/dist/provenance.d.ts +31 -0
- package/dist/provenance.js +71 -0
- package/dist/types.d.ts +23 -0
- package/package.json +1 -1
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
import type { ApprovalRequestMetadata, ApprovalReplyMetadata, SessionRule } from './approval-types.js';
|
|
1
|
+
import type { ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRequestMetadata, ApprovalNativeRequestMetadata, ApprovalRisk, ApprovalReplyMetadata, SessionRule } from './approval-types.js';
|
|
2
2
|
export declare function generateApprovalId(): string;
|
|
3
3
|
export declare function redactSecrets(text: string, patterns: string[]): string;
|
|
4
4
|
export declare function buildApprovalRequest(approvalId: string, toolName: string, toolInput: Record<string, unknown>, opts: {
|
|
5
5
|
riskLevel?: 'normal' | 'destructive';
|
|
6
|
+
risk?: ApprovalRisk;
|
|
7
|
+
category?: ApprovalRequestCategory;
|
|
8
|
+
runtimeId?: string;
|
|
9
|
+
turnId?: string;
|
|
10
|
+
native?: ApprovalNativeRequestMetadata;
|
|
11
|
+
toolSummary?: string;
|
|
12
|
+
details?: ApprovalRequestDetail[];
|
|
6
13
|
expiresAt: string;
|
|
7
14
|
redactPatterns?: string[];
|
|
8
15
|
}): {
|
package/dist/approval-format.js
CHANGED
|
@@ -27,22 +27,37 @@ export function redactSecrets(text, patterns) {
|
|
|
27
27
|
}
|
|
28
28
|
return result;
|
|
29
29
|
}
|
|
30
|
+
function redactApprovalDetails(details, patterns) {
|
|
31
|
+
if (!details?.length)
|
|
32
|
+
return undefined;
|
|
33
|
+
return details.slice(0, 8).map((detail) => ({
|
|
34
|
+
...detail,
|
|
35
|
+
label: detail.label.slice(0, 80),
|
|
36
|
+
value: patterns?.length
|
|
37
|
+
? redactSecrets(detail.value.slice(0, 500), patterns)
|
|
38
|
+
: detail.value.slice(0, 500),
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
30
41
|
// ── Build approval request message ──────────────────────────────────
|
|
31
42
|
export function buildApprovalRequest(approvalId, toolName, toolInput, opts) {
|
|
32
|
-
let summary = summarizeToolInput(toolName, toolInput);
|
|
43
|
+
let summary = opts.toolSummary ?? summarizeToolInput(toolName, toolInput);
|
|
33
44
|
if (opts.redactPatterns?.length) {
|
|
34
45
|
summary = redactSecrets(summary, opts.redactPatterns);
|
|
35
46
|
}
|
|
47
|
+
summary = summary.slice(0, 1000);
|
|
48
|
+
const risk = opts.risk ?? opts.riskLevel ?? 'normal';
|
|
49
|
+
const riskLevel = risk === 'destructive' ? 'destructive' : (opts.riskLevel ?? 'normal');
|
|
50
|
+
const details = redactApprovalDetails(opts.details, opts.redactPatterns);
|
|
36
51
|
const timeoutMin = Math.round((new Date(opts.expiresAt).getTime() - Date.now()) / 60_000);
|
|
37
52
|
const lines = [
|
|
38
|
-
`
|
|
53
|
+
`Action Approval Required [${approvalId}]`,
|
|
39
54
|
'',
|
|
40
55
|
`Tool: ${toolName}`,
|
|
41
56
|
summary,
|
|
42
57
|
'',
|
|
43
58
|
];
|
|
44
|
-
if (
|
|
45
|
-
lines.push('This is a destructive operation');
|
|
59
|
+
if (risk === 'high' || risk === 'destructive') {
|
|
60
|
+
lines.push(risk === 'destructive' ? 'This is a destructive operation' : 'This is a high-risk operation');
|
|
46
61
|
lines.push('');
|
|
47
62
|
}
|
|
48
63
|
lines.push(`Reply "approve" or "deny" (expires in ${timeoutMin}m)`);
|
|
@@ -51,7 +66,13 @@ export function buildApprovalRequest(approvalId, toolName, toolInput, opts) {
|
|
|
51
66
|
approvalId,
|
|
52
67
|
toolName,
|
|
53
68
|
toolSummary: summary,
|
|
54
|
-
|
|
69
|
+
...(opts.category ? { category: opts.category } : {}),
|
|
70
|
+
risk,
|
|
71
|
+
riskLevel,
|
|
72
|
+
...(opts.runtimeId ? { runtimeId: opts.runtimeId } : {}),
|
|
73
|
+
...(opts.turnId ? { turnId: opts.turnId } : {}),
|
|
74
|
+
...(opts.native ? { native: opts.native } : {}),
|
|
75
|
+
...(details ? { details } : {}),
|
|
55
76
|
expiresAt: opts.expiresAt,
|
|
56
77
|
};
|
|
57
78
|
return { text: lines.join('\n'), metadata };
|
|
@@ -77,7 +98,8 @@ export function buildApprovalOutcome(approvalId, toolName, toolSummary, decision
|
|
|
77
98
|
return `Expired [${approvalId}] -- ${toolName}: ${short} (auto-denied)`;
|
|
78
99
|
}
|
|
79
100
|
if (reason === 'session-rule') {
|
|
80
|
-
|
|
101
|
+
const label = decision === 'allow' ? 'Auto-approved' : 'Auto-denied';
|
|
102
|
+
return `${label} (session rule) -- ${toolName}: ${short}`;
|
|
81
103
|
}
|
|
82
104
|
return `${icon} [${approvalId}] -- ${toolName}: ${short}`;
|
|
83
105
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CanonClient } from './client.js';
|
|
2
|
-
import type { ApprovalConfig, ApprovalResult, SessionRule } from './approval-types.js';
|
|
2
|
+
import type { ApprovalConfig, ApprovalNativeRequestMetadata, ApprovalResult, ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRisk, SessionRule } from './approval-types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Platform-agnostic approval protocol for Canon.
|
|
5
5
|
*
|
|
@@ -27,6 +27,15 @@ export declare class ApprovalManager {
|
|
|
27
27
|
*/
|
|
28
28
|
requestApproval(conversationId: string, toolName: string, toolInput: Record<string, unknown>, opts?: {
|
|
29
29
|
riskLevel?: 'normal' | 'destructive';
|
|
30
|
+
risk?: ApprovalRisk;
|
|
31
|
+
category?: ApprovalRequestCategory;
|
|
32
|
+
runtimeId?: string;
|
|
33
|
+
turnId?: string;
|
|
34
|
+
native?: ApprovalNativeRequestMetadata;
|
|
35
|
+
toolSummary?: string;
|
|
36
|
+
details?: ApprovalRequestDetail[];
|
|
37
|
+
ignoreSessionRules?: boolean;
|
|
38
|
+
allowSessionRule?: boolean;
|
|
30
39
|
}): Promise<ApprovalResult>;
|
|
31
40
|
/**
|
|
32
41
|
* Feed an inbound message to the approval manager.
|
|
@@ -38,7 +47,7 @@ export declare class ApprovalManager {
|
|
|
38
47
|
metadata?: Record<string, unknown>;
|
|
39
48
|
}): boolean;
|
|
40
49
|
/** Check if a tool would be auto-resolved by a session rule */
|
|
41
|
-
checkSessionRules(toolName: string): SessionRule | null;
|
|
50
|
+
checkSessionRules(toolName: string, conversationId?: string): SessionRule | null;
|
|
42
51
|
getSessionRules(): SessionRule[];
|
|
43
52
|
clearSessionRules(): void;
|
|
44
53
|
get pendingCount(): number;
|
package/dist/approval-manager.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { DEFAULT_APPROVAL_CONFIG } from './approval-types.js';
|
|
2
|
-
import { generateApprovalId, buildApprovalRequest, buildApprovalOutcome, parseTextApprovalReply, } from './approval-format.js';
|
|
1
|
+
import { DEFAULT_APPROVAL_CONFIG, parseApprovalReplyMetadata } from './approval-types.js';
|
|
2
|
+
import { generateApprovalId, buildApprovalRequest, buildApprovalOutcome, parseTextApprovalReply, redactSecrets, } from './approval-format.js';
|
|
3
3
|
// ── ApprovalManager ─────────────────────────────────────────────────
|
|
4
4
|
/**
|
|
5
5
|
* Platform-agnostic approval protocol for Canon.
|
|
@@ -34,11 +34,14 @@ export class ApprovalManager {
|
|
|
34
34
|
*/
|
|
35
35
|
async requestApproval(conversationId, toolName, toolInput, opts) {
|
|
36
36
|
// Check session rules first
|
|
37
|
-
const matchingRule = this.checkSessionRules(toolName);
|
|
37
|
+
const matchingRule = opts?.ignoreSessionRules ? null : this.checkSessionRules(toolName, conversationId);
|
|
38
38
|
if (matchingRule) {
|
|
39
39
|
const decision = matchingRule.type === 'deny-tool' ? 'deny' : 'allow';
|
|
40
40
|
// Send silent log (fire-and-forget)
|
|
41
|
-
const
|
|
41
|
+
const rawSummary = opts?.toolSummary ?? this.summarizeTool(toolName, toolInput);
|
|
42
|
+
const summary = this.config.redactPatterns.length
|
|
43
|
+
? redactSecrets(rawSummary, this.config.redactPatterns)
|
|
44
|
+
: rawSummary;
|
|
42
45
|
const logMsg = buildApprovalOutcome('', toolName, summary, decision, 'session-rule');
|
|
43
46
|
this.client.sendMessage(conversationId, logMsg, {
|
|
44
47
|
metadata: { type: 'approval_outcome', decision, reason: 'session-rule' },
|
|
@@ -49,6 +52,13 @@ export class ApprovalManager {
|
|
|
49
52
|
const expiresAt = new Date(Date.now() + this.config.timeoutSeconds * 1000).toISOString();
|
|
50
53
|
const { text, metadata } = buildApprovalRequest(approvalId, toolName, toolInput, {
|
|
51
54
|
riskLevel: opts?.riskLevel,
|
|
55
|
+
risk: opts?.risk,
|
|
56
|
+
category: opts?.category,
|
|
57
|
+
runtimeId: opts?.runtimeId,
|
|
58
|
+
turnId: opts?.turnId,
|
|
59
|
+
native: opts?.native,
|
|
60
|
+
toolSummary: opts?.toolSummary,
|
|
61
|
+
details: opts?.details,
|
|
52
62
|
expiresAt,
|
|
53
63
|
redactPatterns: this.config.redactPatterns,
|
|
54
64
|
});
|
|
@@ -61,8 +71,7 @@ export class ApprovalManager {
|
|
|
61
71
|
return new Promise((resolve) => {
|
|
62
72
|
const timer = setTimeout(() => {
|
|
63
73
|
this.pending.delete(approvalId);
|
|
64
|
-
const
|
|
65
|
-
const msg = buildApprovalOutcome(approvalId, toolName, summary, 'deny', 'timeout');
|
|
74
|
+
const msg = buildApprovalOutcome(approvalId, toolName, metadata.toolSummary, 'deny', 'timeout');
|
|
66
75
|
this.client.sendMessage(conversationId, msg, {
|
|
67
76
|
metadata: {
|
|
68
77
|
type: 'approval_outcome',
|
|
@@ -77,7 +86,8 @@ export class ApprovalManager {
|
|
|
77
86
|
approvalId,
|
|
78
87
|
conversationId,
|
|
79
88
|
toolName,
|
|
80
|
-
toolSummary:
|
|
89
|
+
toolSummary: metadata.toolSummary,
|
|
90
|
+
allowSessionRule: opts?.allowSessionRule !== false,
|
|
81
91
|
resolve,
|
|
82
92
|
timer,
|
|
83
93
|
});
|
|
@@ -95,11 +105,10 @@ export class ApprovalManager {
|
|
|
95
105
|
return false;
|
|
96
106
|
// Try structured metadata first (from card UI)
|
|
97
107
|
if (message.metadata?.type === 'approval_reply') {
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
return this.resolveApproval(approvalId, decision, sessionRule, conversationId);
|
|
108
|
+
const parsed = parseApprovalReplyMetadata(message.metadata);
|
|
109
|
+
if (!parsed)
|
|
110
|
+
return false;
|
|
111
|
+
return this.resolveApproval(parsed.approvalId, parsed.decision, parsed.sessionRule, conversationId);
|
|
103
112
|
}
|
|
104
113
|
// Fall back to text parsing
|
|
105
114
|
if (message.text) {
|
|
@@ -119,23 +128,31 @@ export class ApprovalManager {
|
|
|
119
128
|
return false;
|
|
120
129
|
}
|
|
121
130
|
/** Check if a tool would be auto-resolved by a session rule */
|
|
122
|
-
checkSessionRules(toolName) {
|
|
131
|
+
checkSessionRules(toolName, conversationId) {
|
|
123
132
|
this.pruneExpiredRules();
|
|
124
|
-
for (const
|
|
133
|
+
for (const stored of this.rules) {
|
|
134
|
+
if (conversationId && stored.conversationId !== conversationId)
|
|
135
|
+
continue;
|
|
136
|
+
const { rule } = stored;
|
|
125
137
|
if (rule.type === 'approve-all')
|
|
126
138
|
return rule;
|
|
127
139
|
if ((rule.type === 'approve-tool' || rule.type === 'deny-tool') &&
|
|
128
140
|
rule.toolPattern) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
141
|
+
try {
|
|
142
|
+
const re = new RegExp(`^${rule.toolPattern}$`, 'i');
|
|
143
|
+
if (re.test(toolName))
|
|
144
|
+
return rule;
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
132
149
|
}
|
|
133
150
|
}
|
|
134
151
|
return null;
|
|
135
152
|
}
|
|
136
153
|
getSessionRules() {
|
|
137
154
|
this.pruneExpiredRules();
|
|
138
|
-
return
|
|
155
|
+
return this.rules.map((stored) => stored.rule);
|
|
139
156
|
}
|
|
140
157
|
clearSessionRules() {
|
|
141
158
|
this.rules = [];
|
|
@@ -160,11 +177,18 @@ export class ApprovalManager {
|
|
|
160
177
|
}
|
|
161
178
|
return false;
|
|
162
179
|
}
|
|
180
|
+
if (entry.conversationId !== conversationId) {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
163
183
|
clearTimeout(entry.timer);
|
|
164
184
|
this.pending.delete(approvalId);
|
|
165
|
-
|
|
166
|
-
if
|
|
167
|
-
|
|
185
|
+
const acceptedSessionRule = entry.allowSessionRule ? sessionRule : undefined;
|
|
186
|
+
// Store session rule if provided and allowed for this request
|
|
187
|
+
if (acceptedSessionRule) {
|
|
188
|
+
this.rules.push({
|
|
189
|
+
conversationId: entry.conversationId,
|
|
190
|
+
rule: acceptedSessionRule,
|
|
191
|
+
});
|
|
168
192
|
}
|
|
169
193
|
// Send confirmation (fire-and-forget)
|
|
170
194
|
const msg = buildApprovalOutcome(approvalId, entry.toolName, entry.toolSummary, decision, 'replied');
|
|
@@ -177,15 +201,15 @@ export class ApprovalManager {
|
|
|
177
201
|
},
|
|
178
202
|
}).catch(() => { });
|
|
179
203
|
// If session rule was set, log that too
|
|
180
|
-
if (
|
|
181
|
-
const ruleDesc = this.describeRule(
|
|
204
|
+
if (acceptedSessionRule) {
|
|
205
|
+
const ruleDesc = this.describeRule(acceptedSessionRule);
|
|
182
206
|
this.client
|
|
183
207
|
.sendMessage(conversationId, `Session rule set: ${ruleDesc}`, {
|
|
184
208
|
metadata: { type: 'approval_outcome', decision, reason: 'session-rule' },
|
|
185
209
|
})
|
|
186
210
|
.catch(() => { });
|
|
187
211
|
}
|
|
188
|
-
entry.resolve({ decision, sessionRule });
|
|
212
|
+
entry.resolve({ decision, ...(acceptedSessionRule ? { sessionRule: acceptedSessionRule } : {}) });
|
|
189
213
|
return true;
|
|
190
214
|
}
|
|
191
215
|
findMostRecentPending(conversationId) {
|
|
@@ -199,10 +223,10 @@ export class ApprovalManager {
|
|
|
199
223
|
}
|
|
200
224
|
pruneExpiredRules() {
|
|
201
225
|
const now = Date.now();
|
|
202
|
-
this.rules = this.rules.filter((
|
|
203
|
-
if (!
|
|
226
|
+
this.rules = this.rules.filter(({ rule }) => {
|
|
227
|
+
if (!rule.expiresAt)
|
|
204
228
|
return true;
|
|
205
|
-
return new Date(
|
|
229
|
+
return new Date(rule.expiresAt).getTime() > now;
|
|
206
230
|
});
|
|
207
231
|
}
|
|
208
232
|
summarizeTool(toolName, toolInput) {
|
package/dist/approval-types.d.ts
CHANGED
|
@@ -4,7 +4,17 @@ export interface ApprovalRequestMetadata {
|
|
|
4
4
|
toolName: string;
|
|
5
5
|
/** Pre-computed, redacted summary — raw toolInput is never stored */
|
|
6
6
|
toolSummary: string;
|
|
7
|
+
/** Broad action family for richer Canon approval cards. */
|
|
8
|
+
category?: ApprovalRequestCategory;
|
|
9
|
+
/** Preferred v2 risk signal. `riskLevel` remains for older clients. */
|
|
10
|
+
risk?: ApprovalRisk;
|
|
7
11
|
riskLevel?: 'normal' | 'destructive';
|
|
12
|
+
runtimeId?: string;
|
|
13
|
+
turnId?: string;
|
|
14
|
+
/** Native runtime correlation handle. Canon stores this opaquely for plugins/SDK bridges. */
|
|
15
|
+
native?: ApprovalNativeRequestMetadata;
|
|
16
|
+
/** Redacted, normalized details. Raw tool input must not be stored here. */
|
|
17
|
+
details?: ApprovalRequestDetail[];
|
|
8
18
|
expiresAt: string;
|
|
9
19
|
}
|
|
10
20
|
export interface ApprovalOutcomeMetadata {
|
|
@@ -19,6 +29,33 @@ export interface ApprovalReplyMetadata {
|
|
|
19
29
|
decision: 'allow' | 'deny';
|
|
20
30
|
sessionRule?: SessionRule;
|
|
21
31
|
}
|
|
32
|
+
export type ApprovalRequestCategory = 'command' | 'file' | 'network' | 'browser' | 'mcp' | 'plugin' | 'canon' | 'tool';
|
|
33
|
+
export type ApprovalRisk = 'low' | 'normal' | 'high' | 'destructive';
|
|
34
|
+
export interface ApprovalRequestDetail {
|
|
35
|
+
label: string;
|
|
36
|
+
value: string;
|
|
37
|
+
monospace?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export interface ApprovalNativeRequestMetadata {
|
|
40
|
+
runtime?: string;
|
|
41
|
+
method?: string;
|
|
42
|
+
requestId?: string;
|
|
43
|
+
provider?: string;
|
|
44
|
+
origin?: string;
|
|
45
|
+
surface?: string;
|
|
46
|
+
threadId?: string;
|
|
47
|
+
turnId?: string;
|
|
48
|
+
runId?: string;
|
|
49
|
+
itemId?: string;
|
|
50
|
+
toolCallId?: string;
|
|
51
|
+
approvalId?: string;
|
|
52
|
+
pluginId?: string;
|
|
53
|
+
sessionKey?: string;
|
|
54
|
+
cwd?: string;
|
|
55
|
+
model?: string;
|
|
56
|
+
nodeId?: string;
|
|
57
|
+
handles?: Record<string, string>;
|
|
58
|
+
}
|
|
22
59
|
export interface SessionRule {
|
|
23
60
|
type: 'approve-all' | 'approve-tool' | 'deny-tool';
|
|
24
61
|
/** Tool name pattern (regex) — only for approve-tool/deny-tool */
|
|
@@ -37,3 +74,6 @@ export interface ApprovalConfig {
|
|
|
37
74
|
redactPatterns: string[];
|
|
38
75
|
}
|
|
39
76
|
export declare const DEFAULT_APPROVAL_CONFIG: ApprovalConfig;
|
|
77
|
+
export declare function parseSessionRule(value: unknown): SessionRule | null;
|
|
78
|
+
export declare function parseApprovalReplyMetadata(value: unknown): ApprovalReplyMetadata | null;
|
|
79
|
+
export declare function parseApprovalRequestMetadata(value: unknown): ApprovalRequestMetadata | null;
|
package/dist/approval-types.js
CHANGED
|
@@ -7,3 +7,192 @@ export const DEFAULT_APPROVAL_CONFIG = {
|
|
|
7
7
|
'(?:api[_-]?key|token|secret|password)\\s*[:=]\\s*\\S+',
|
|
8
8
|
],
|
|
9
9
|
};
|
|
10
|
+
function isRecord(value) {
|
|
11
|
+
return Boolean(value && typeof value === 'object' && !Array.isArray(value));
|
|
12
|
+
}
|
|
13
|
+
function normalizeString(value, maxLength) {
|
|
14
|
+
if (typeof value !== 'string')
|
|
15
|
+
return null;
|
|
16
|
+
const trimmed = value.trim();
|
|
17
|
+
if (!trimmed || trimmed.length > maxLength)
|
|
18
|
+
return null;
|
|
19
|
+
return trimmed;
|
|
20
|
+
}
|
|
21
|
+
function normalizeCategory(value) {
|
|
22
|
+
return value === 'command'
|
|
23
|
+
|| value === 'file'
|
|
24
|
+
|| value === 'network'
|
|
25
|
+
|| value === 'browser'
|
|
26
|
+
|| value === 'mcp'
|
|
27
|
+
|| value === 'plugin'
|
|
28
|
+
|| value === 'canon'
|
|
29
|
+
|| value === 'tool'
|
|
30
|
+
? value
|
|
31
|
+
: undefined;
|
|
32
|
+
}
|
|
33
|
+
function normalizeRisk(value) {
|
|
34
|
+
return value === 'low'
|
|
35
|
+
|| value === 'normal'
|
|
36
|
+
|| value === 'high'
|
|
37
|
+
|| value === 'destructive'
|
|
38
|
+
? value
|
|
39
|
+
: undefined;
|
|
40
|
+
}
|
|
41
|
+
function normalizeDetails(value) {
|
|
42
|
+
if (!Array.isArray(value))
|
|
43
|
+
return undefined;
|
|
44
|
+
const details = value.slice(0, 8).flatMap((entry) => {
|
|
45
|
+
if (!isRecord(entry))
|
|
46
|
+
return [];
|
|
47
|
+
const label = normalizeString(entry.label, 80);
|
|
48
|
+
const detailValue = normalizeString(entry.value, 500);
|
|
49
|
+
if (!label || !detailValue)
|
|
50
|
+
return [];
|
|
51
|
+
return [{
|
|
52
|
+
label,
|
|
53
|
+
value: detailValue,
|
|
54
|
+
...(entry.monospace === true ? { monospace: true } : {}),
|
|
55
|
+
}];
|
|
56
|
+
});
|
|
57
|
+
return details.length > 0 ? details : undefined;
|
|
58
|
+
}
|
|
59
|
+
function normalizeNativeRequest(value) {
|
|
60
|
+
if (!isRecord(value))
|
|
61
|
+
return undefined;
|
|
62
|
+
const native = {};
|
|
63
|
+
for (const key of [
|
|
64
|
+
'runtime',
|
|
65
|
+
'method',
|
|
66
|
+
'requestId',
|
|
67
|
+
'provider',
|
|
68
|
+
'origin',
|
|
69
|
+
'surface',
|
|
70
|
+
'threadId',
|
|
71
|
+
'turnId',
|
|
72
|
+
'runId',
|
|
73
|
+
'itemId',
|
|
74
|
+
'toolCallId',
|
|
75
|
+
'approvalId',
|
|
76
|
+
'pluginId',
|
|
77
|
+
'sessionKey',
|
|
78
|
+
'cwd',
|
|
79
|
+
'model',
|
|
80
|
+
'nodeId',
|
|
81
|
+
]) {
|
|
82
|
+
const normalized = normalizeString(value[key], 256);
|
|
83
|
+
if (normalized)
|
|
84
|
+
native[key] = normalized;
|
|
85
|
+
}
|
|
86
|
+
const handles = isRecord(value.handles) ? value.handles : null;
|
|
87
|
+
if (handles) {
|
|
88
|
+
const normalizedHandles = {};
|
|
89
|
+
for (const [key, raw] of Object.entries(handles).slice(0, 16)) {
|
|
90
|
+
const normalizedKey = /^[a-zA-Z0-9_.:-]{1,80}$/.test(key) ? key : null;
|
|
91
|
+
const normalizedValue = normalizeString(raw, 256);
|
|
92
|
+
if (normalizedKey && normalizedValue) {
|
|
93
|
+
normalizedHandles[normalizedKey] = normalizedValue;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (Object.keys(normalizedHandles).length > 0) {
|
|
97
|
+
native.handles = normalizedHandles;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return Object.keys(native).length > 0 ? native : undefined;
|
|
101
|
+
}
|
|
102
|
+
export function parseSessionRule(value) {
|
|
103
|
+
if (!isRecord(value))
|
|
104
|
+
return null;
|
|
105
|
+
const type = value.type;
|
|
106
|
+
if (type !== 'approve-all' && type !== 'approve-tool' && type !== 'deny-tool') {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
let expiresAt;
|
|
110
|
+
if (value.expiresAt !== undefined) {
|
|
111
|
+
if (value.expiresAt === null) {
|
|
112
|
+
expiresAt = null;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
const normalizedExpiresAt = normalizeString(value.expiresAt, 128);
|
|
116
|
+
if (!normalizedExpiresAt)
|
|
117
|
+
return null;
|
|
118
|
+
const expiresMs = Date.parse(normalizedExpiresAt);
|
|
119
|
+
if (!Number.isFinite(expiresMs) || expiresMs <= Date.now())
|
|
120
|
+
return null;
|
|
121
|
+
expiresAt = new Date(expiresMs).toISOString();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (type === 'approve-all') {
|
|
125
|
+
return {
|
|
126
|
+
type,
|
|
127
|
+
...(expiresAt !== undefined ? { expiresAt } : {}),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
const toolPattern = normalizeString(value.toolPattern, 128);
|
|
131
|
+
if (!toolPattern || !/^[\w.*:-]+$/.test(toolPattern)) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
type,
|
|
136
|
+
toolPattern,
|
|
137
|
+
...(expiresAt !== undefined ? { expiresAt } : {}),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
export function parseApprovalReplyMetadata(value) {
|
|
141
|
+
if (!isRecord(value) || value.type !== 'approval_reply')
|
|
142
|
+
return null;
|
|
143
|
+
const approvalId = normalizeString(value.approvalId, 128);
|
|
144
|
+
if (!approvalId)
|
|
145
|
+
return null;
|
|
146
|
+
const decision = value.decision;
|
|
147
|
+
if (decision !== 'allow' && decision !== 'deny')
|
|
148
|
+
return null;
|
|
149
|
+
let sessionRule;
|
|
150
|
+
if (value.sessionRule !== undefined) {
|
|
151
|
+
const parsed = parseSessionRule(value.sessionRule);
|
|
152
|
+
if (!parsed)
|
|
153
|
+
return null;
|
|
154
|
+
sessionRule = parsed;
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
type: 'approval_reply',
|
|
158
|
+
approvalId,
|
|
159
|
+
decision,
|
|
160
|
+
...(sessionRule ? { sessionRule } : {}),
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
export function parseApprovalRequestMetadata(value) {
|
|
164
|
+
if (!isRecord(value) || value.type !== 'approval_request')
|
|
165
|
+
return null;
|
|
166
|
+
const approvalId = normalizeString(value.approvalId, 128);
|
|
167
|
+
const toolName = normalizeString(value.toolName, 128);
|
|
168
|
+
const toolSummary = normalizeString(value.toolSummary, 1000);
|
|
169
|
+
const expiresAt = normalizeString(value.expiresAt, 128);
|
|
170
|
+
if (!approvalId || !toolName || !toolSummary || !expiresAt)
|
|
171
|
+
return null;
|
|
172
|
+
const expiresMs = Date.parse(expiresAt);
|
|
173
|
+
if (!Number.isFinite(expiresMs))
|
|
174
|
+
return null;
|
|
175
|
+
const riskLevel = value.riskLevel === 'destructive' || value.riskLevel === 'normal'
|
|
176
|
+
? value.riskLevel
|
|
177
|
+
: undefined;
|
|
178
|
+
const risk = normalizeRisk(value.risk) ?? (riskLevel === 'destructive' ? 'destructive' : undefined);
|
|
179
|
+
const category = normalizeCategory(value.category);
|
|
180
|
+
const runtimeId = normalizeString(value.runtimeId, 128) ?? undefined;
|
|
181
|
+
const turnId = normalizeString(value.turnId, 128) ?? undefined;
|
|
182
|
+
const native = normalizeNativeRequest(value.native);
|
|
183
|
+
const details = normalizeDetails(value.details);
|
|
184
|
+
return {
|
|
185
|
+
type: 'approval_request',
|
|
186
|
+
approvalId,
|
|
187
|
+
toolName,
|
|
188
|
+
toolSummary,
|
|
189
|
+
...(category ? { category } : {}),
|
|
190
|
+
...(risk ? { risk } : {}),
|
|
191
|
+
...(riskLevel ? { riskLevel } : {}),
|
|
192
|
+
...(runtimeId ? { runtimeId } : {}),
|
|
193
|
+
...(turnId ? { turnId } : {}),
|
|
194
|
+
...(native ? { native } : {}),
|
|
195
|
+
...(details ? { details } : {}),
|
|
196
|
+
expiresAt: new Date(expiresMs).toISOString(),
|
|
197
|
+
};
|
|
198
|
+
}
|
package/dist/browser.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export { AGENT_CAPABILITIES, CLAUDE_PERMISSION_MODE_OPTIONS, } from './types.js';
|
|
2
2
|
export { resolveCanonBaseUrl } from './base-url.js';
|
|
3
3
|
export { DEFAULT_BASE_URL, DEFAULT_STREAM_URL, DEFAULT_RTDB_URL, FIREBASE_WEB_API_KEY } from './constants.js';
|
|
4
|
-
export type { AddMemberResult, AgentCapabilities, AgentClientType, AgentSessionSnapshot, AgentRuntime, CanonControlAvailability, CanonControlDescriptor, CanonControlLiveBehavior, CanonControlSelectionPolicy, CanonControlValue, CanonContact, CanonContactRequest, CanonContactRequestStatus, CanonResolveAdmissionResult, ContactAddedPayload, ContactApprovedPayload, ContactRemovedPayload, ContactRequestPayload, ContactSource, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, CanonStreamEvent, CreateContactRequestResult, MediaAttachment, MediaAttachmentKind, ModelOption, PermissionModeOption, CanonRuntimeDescriptor, CanonRuntimeActionAvailability, CanonRuntimeActionCategory, CanonRuntimeActionDescriptor, CanonRuntimeActionDispatch, CanonRuntimeActionPlacement, CanonRuntimeCommandArgumentChoice, CanonRuntimeCommandArgumentDescriptor, CanonRuntimeCommandArgumentKind, CanonRuntimeCommandDescriptor, CanonRuntimeDetailTier, CanonRuntimeExecutionMetadata, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeFact, CanonRuntimeFactGroup, CanonRuntimeInventory, CanonRuntimeInventoryEntry, CanonRuntimePrimitiveId, CanonRuntimeStreamingMode, CanonRuntimeStatusItem, CanonRuntimeSurfaceMode, CanonWorkspaceRootMetadata, RuntimeUpdatedPayload, RuntimeInfoPayload, RuntimeControlError, RuntimeControlState, RuntimeControlValueSource, ResolvedAdmission, SessionConfig, TurnUpdatedPayload, WorkspaceOption, WorkspaceOptionSource, } from './types.js';
|
|
4
|
+
export type { AddMemberResult, AgentCapabilities, AgentClientType, AgentSessionSnapshot, AgentRuntime, CanonControlAvailability, CanonControlDescriptor, CanonControlLiveBehavior, CanonControlSelectionPolicy, CanonControlValue, CanonContact, CanonContactRequest, CanonContactRequestStatus, CanonResolveAdmissionResult, ContactAddedPayload, ContactApprovedPayload, ContactRemovedPayload, ContactRequestPayload, ContactSource, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, CanonStreamEvent, CreateContactRequestResult, MediaAttachment, MediaAttachmentKind, ModelOption, PermissionModeOption, CanonRuntimeDescriptor, CanonRuntimeActionAvailability, CanonRuntimeActionCategory, CanonRuntimeActionDescriptor, CanonRuntimeActionDispatch, CanonRuntimeActionPlacement, CanonRuntimeCommandArgumentChoice, CanonRuntimeCommandArgumentDescriptor, CanonRuntimeCommandArgumentKind, CanonRuntimeCommandDescriptor, CanonRuntimeDetailTier, CanonRuntimeExecutionMetadata, CanonRuntimeProvenance, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeFact, CanonRuntimeFactGroup, CanonRuntimeInventory, CanonRuntimeInventoryEntry, CanonRuntimePrimitiveId, CanonRuntimeStreamingMode, CanonRuntimeStatusItem, CanonRuntimeSurfaceMode, CanonWorkspaceRootMetadata, RuntimeUpdatedPayload, RuntimeInfoPayload, RuntimeControlError, RuntimeControlState, RuntimeControlValueSource, ResolvedAdmission, SessionConfig, TurnUpdatedPayload, WorkspaceOption, WorkspaceOptionSource, } from './types.js';
|
|
5
|
+
export { buildRuntimeProvenance, resolveRuntimeProvenance, } from './provenance.js';
|
|
5
6
|
export { EXECUTION_ENVIRONMENT_MODES, isExecutionEnvironmentMode, } from './execution-environment-mode.js';
|
|
6
7
|
export type { ExecutionEnvironmentMode } from './execution-environment-mode.js';
|
|
7
8
|
export type { CanonSelfContext, CanonSelfContextType, SelfContextPromptRenderOptions, SendContextualMessageOptions, SendContextualMessageResult, SendContextualSelfContextInput, } from './self-context.js';
|
|
@@ -13,6 +14,7 @@ export { buildParticipationHistorySnapshot, buildParticipationHistorySnapshots,
|
|
|
13
14
|
export { DEFAULT_RUNTIME_CAPABILITIES, FINAL_MESSAGE_HANDOFF_MS, isTurnOpen, normalizeTurnMetadata, normalizeTurnState, resolveTurnMessageSemantics, shouldPromoteConversationMessage, shouldTriggerAgentTurn, } from './turn-protocol.js';
|
|
14
15
|
export type { DeliveryIntent, InboundDisposition, RuntimeCapabilities, TriggerDecision, TurnLifecycleState, TurnMessageSemantics, TurnMetadata, TurnState, } from './turn-protocol.js';
|
|
15
16
|
export { buildApprovalReply, buildApprovalRequest, buildApprovalOutcome, generateApprovalId, parseTextApprovalReply, redactSecrets, } from './approval-format.js';
|
|
16
|
-
export type { ApprovalRequestMetadata, ApprovalReplyMetadata, ApprovalOutcomeMetadata, SessionRule, ApprovalResult, ApprovalConfig, } from './approval-types.js';
|
|
17
|
+
export type { ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRequestMetadata, ApprovalNativeRequestMetadata, ApprovalRisk, ApprovalReplyMetadata, ApprovalOutcomeMetadata, SessionRule, ApprovalResult, ApprovalConfig, } from './approval-types.js';
|
|
18
|
+
export { DEFAULT_APPROVAL_CONFIG, parseApprovalRequestMetadata, parseApprovalReplyMetadata, parseSessionRule, } from './approval-types.js';
|
|
17
19
|
export { buildPlanApprovalReply, buildPlanApprovalRequest, buildQuestionReply, buildQuestionRequest, } from './runtime-cards.js';
|
|
18
20
|
export type { ClaudeQuestionMetadata, ClaudeQuestionReplyMetadata, PlanApprovalMetadata, PlanApprovalReplyMetadata, RuntimeQuestionDefinition, RuntimeQuestionOption, } from './runtime-cards.js';
|
package/dist/browser.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { AGENT_CAPABILITIES, CLAUDE_PERMISSION_MODE_OPTIONS, } from './types.js';
|
|
2
2
|
export { resolveCanonBaseUrl } from './base-url.js';
|
|
3
3
|
export { DEFAULT_BASE_URL, DEFAULT_STREAM_URL, DEFAULT_RTDB_URL, FIREBASE_WEB_API_KEY } from './constants.js';
|
|
4
|
+
export { buildRuntimeProvenance, resolveRuntimeProvenance, } from './provenance.js';
|
|
4
5
|
export { EXECUTION_ENVIRONMENT_MODES, isExecutionEnvironmentMode, } from './execution-environment-mode.js';
|
|
5
6
|
export { buildSelfContextPromptLines, normalizeSelfContexts, } from './self-context.js';
|
|
6
7
|
export { buildAgentSessionSnapshot } from './agent-session.js';
|
|
@@ -8,4 +9,5 @@ export { CLAUDE_EFFORT_OPTIONS, EXECUTION_MODE_CONTROL_OPTIONS, RUNTIME_NEW_SESS
|
|
|
8
9
|
export { buildParticipationHistorySnapshot, buildParticipationHistorySnapshots, buildBehaviorPolicyLines, DEFAULT_PARTICIPATION_HISTORY_FETCH_LIMIT, evaluateParticipationPolicy, getDefaultParticipationPolicy, resolveAgentBehaviorPolicy, } from './policy.js';
|
|
9
10
|
export { DEFAULT_RUNTIME_CAPABILITIES, FINAL_MESSAGE_HANDOFF_MS, isTurnOpen, normalizeTurnMetadata, normalizeTurnState, resolveTurnMessageSemantics, shouldPromoteConversationMessage, shouldTriggerAgentTurn, } from './turn-protocol.js';
|
|
10
11
|
export { buildApprovalReply, buildApprovalRequest, buildApprovalOutcome, generateApprovalId, parseTextApprovalReply, redactSecrets, } from './approval-format.js';
|
|
12
|
+
export { DEFAULT_APPROVAL_CONFIG, parseApprovalRequestMetadata, parseApprovalReplyMetadata, parseSessionRule, } from './approval-types.js';
|
|
11
13
|
export { buildPlanApprovalReply, buildPlanApprovalRequest, buildQuestionReply, buildQuestionRequest, } from './runtime-cards.js';
|
package/dist/host-runtime.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AgentClientType, type AgentRuntime, type CanonConversation, type CanonGroupContext, type CanonGroupContextMode, type CanonMembershipChange, type CanonMessage, type CanonMessagesPage, type MessageCreatedPayload } from './types.js';
|
|
1
|
+
import { type AgentClientType, type AgentRuntime, type CanonConversation, type CanonGroupContext, type CanonGroupContextMode, type CanonMembershipChange, type CanonMessage, type CanonMessagesPage, type CanonRuntimeProvenance, type MessageCreatedPayload } from './types.js';
|
|
2
2
|
import { type CanonClient } from './client.js';
|
|
3
3
|
import { type SessionWorkspaceConfig } from './execution-environment.js';
|
|
4
4
|
import { type ResolvedAgentBehaviorPolicy } from './policy.js';
|
|
@@ -86,10 +86,12 @@ export declare function resolveCanonReplyContext(input: {
|
|
|
86
86
|
}): CanonReplyContext | null;
|
|
87
87
|
export declare function buildHydratedInboundContext(input: {
|
|
88
88
|
agentId: string;
|
|
89
|
+
conversationId: string;
|
|
89
90
|
conversation: CanonConversation | null;
|
|
90
91
|
page?: CanonMessagesPage | null;
|
|
91
92
|
activeSelfContextId?: string | null;
|
|
92
93
|
selfContexts?: MessageCreatedPayload['selfContexts'];
|
|
94
|
+
provenance?: MessageCreatedPayload['provenance'];
|
|
93
95
|
message: HostInboundMessage;
|
|
94
96
|
senderName: string;
|
|
95
97
|
isOwner: boolean;
|
|
@@ -102,6 +104,7 @@ export declare function buildHydratedInboundContext(input: {
|
|
|
102
104
|
behavior?: ResolvedAgentBehaviorPolicy | null;
|
|
103
105
|
activeSelfContextId: string | null;
|
|
104
106
|
selfContexts: NonNullable<MessageCreatedPayload['selfContexts']>;
|
|
107
|
+
provenance: CanonRuntimeProvenance;
|
|
105
108
|
replyContext: CanonReplyContext | null;
|
|
106
109
|
hydratedFromPage: boolean;
|
|
107
110
|
};
|
package/dist/host-runtime.js
CHANGED
|
@@ -3,6 +3,7 @@ import { buildAgentSessionSnapshot } from './agent-session.js';
|
|
|
3
3
|
import { buildConversationWorktreeSpec, normalizeOptionalString, readSessionWorkspaceConfig, resolveConfiguredWorkspaceCwd, } from './execution-environment.js';
|
|
4
4
|
import { buildBehaviorPolicyLines, buildParticipationHistorySnapshot, } from './policy.js';
|
|
5
5
|
import { buildSelfContextPromptLines, normalizeSelfContexts, resolveMessageActiveSelfContextId, selectActiveSelfContexts, } from './self-context.js';
|
|
6
|
+
import { resolveRuntimeProvenance } from './provenance.js';
|
|
6
7
|
import { rtdbRead } from './rtdb-rest.js';
|
|
7
8
|
import { createRuntimeStatePublisher } from './runtime-state-publisher.js';
|
|
8
9
|
const HOST_INBOUND_CONTACT_CARD_ACTION_CAPABILITIES = Object.freeze({
|
|
@@ -173,6 +174,21 @@ export function buildHydratedInboundContext(input) {
|
|
|
173
174
|
...(input.page?.selfContexts ?? []),
|
|
174
175
|
...(input.selfContexts ?? []),
|
|
175
176
|
], activeSelfContextId);
|
|
177
|
+
const resolvedActiveSelfContextId = activeSelfContexts.length > 0 ? activeSelfContextId : null;
|
|
178
|
+
const provenance = resolveRuntimeProvenance({
|
|
179
|
+
provenance: input.provenance,
|
|
180
|
+
conversationId: input.conversationId,
|
|
181
|
+
conversationType: input.conversation?.type ?? 'unknown',
|
|
182
|
+
memberCount: input.conversation?.memberIds?.length ?? null,
|
|
183
|
+
senderId: input.message.senderId ?? '',
|
|
184
|
+
senderName: input.senderName,
|
|
185
|
+
senderType: input.message.senderType ?? 'human',
|
|
186
|
+
isOwner: input.isOwner,
|
|
187
|
+
agentId: input.agentId,
|
|
188
|
+
mentions: input.message.mentions ?? [],
|
|
189
|
+
activeSelfContextId: resolvedActiveSelfContextId,
|
|
190
|
+
selfContexts: activeSelfContexts,
|
|
191
|
+
});
|
|
176
192
|
const groupContext = buildCanonGroupContext({
|
|
177
193
|
conversation: input.conversation,
|
|
178
194
|
messages: [
|
|
@@ -201,8 +217,9 @@ export function buildHydratedInboundContext(input) {
|
|
|
201
217
|
currentAgentStreakStartedByHuman: history.currentAgentStreakStartedByHuman,
|
|
202
218
|
},
|
|
203
219
|
behavior: input.page?.behavior ?? input.conversation?.behavior,
|
|
204
|
-
activeSelfContextId:
|
|
220
|
+
activeSelfContextId: resolvedActiveSelfContextId,
|
|
205
221
|
selfContexts: activeSelfContexts,
|
|
222
|
+
provenance,
|
|
206
223
|
replyContext: resolveCanonReplyContext({
|
|
207
224
|
message: input.message,
|
|
208
225
|
messages: input.page?.messages ?? [],
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { AGENT_CAPABILITIES, CLAUDE_PERMISSION_MODE_OPTIONS, } from './types.js';
|
|
2
|
-
export type { AddMemberResult, AgentCapabilities, AgentClientType, CanonControlAvailability, CanonControlDescriptor, CanonControlLiveBehavior, CanonControlSelectionPolicy, CanonControlValue, CanonContact, CanonContactRequest, CanonContactRequestStatus, CanonGroupContext, CanonGroupContextMode, CanonKnownRecentParticipant, CanonMembershipChange, CanonResolveAdmissionResult, ConversationUpdatedPayload, ContactAddedPayload, ContactApprovedPayload, ContactCardPayload, ContactRemovedPayload, ContactRequestPayload, ContactSource, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, CanonMessage, CanonConversation, CanonMessagesPage, CreateContactRequestResult, AgentContext, CanonStreamEvent, AgentSessionSnapshot, ResolvedAdmission, MediaAttachment, MediaAttachmentKind, MessageCreatedPayload, TypingPayload, PresencePayload, RuntimeUpdatedPayload, TurnUpdatedPayload, SendMessageOptions, CreateConversationOptions, RegistrationInput, RegistrationResult, RegistrationStatus, StreamingStatus, SetStreamingOptions, SessionControl, SessionState, SessionConfig, AgentRuntime, CanonRuntimeDescriptor, CanonRuntimeActionAvailability, CanonRuntimeActionCategory, CanonRuntimeActionDescriptor, CanonRuntimeActionDispatch, CanonRuntimeActionPlacement, CanonRuntimeCommandArgumentChoice, CanonRuntimeCommandArgumentDescriptor, CanonRuntimeCommandArgumentKind, CanonRuntimeCommandDescriptor, CanonRuntimeDetailTier, CanonRuntimeExecutionMetadata, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeFact, CanonRuntimeFactGroup, CanonRuntimeInventory, CanonRuntimeInventoryEntry, CanonRuntimePrimitiveId, CanonRuntimeStreamingMode, CanonRuntimeStatusItem, CanonRuntimeSurfaceMode, CanonWorkspaceRootMetadata, ModelOption, PermissionModeOption, RuntimeInfoPayload, RuntimeControlError, RuntimeControlState, RuntimeControlValueSource, WorkspaceOption, WorkspaceOptionSource, } from './types.js';
|
|
2
|
+
export type { AddMemberResult, AgentCapabilities, AgentClientType, CanonControlAvailability, CanonControlDescriptor, CanonControlLiveBehavior, CanonControlSelectionPolicy, CanonControlValue, CanonContact, CanonContactRequest, CanonContactRequestStatus, CanonGroupContext, CanonGroupContextMode, CanonKnownRecentParticipant, CanonMembershipChange, CanonResolveAdmissionResult, ConversationUpdatedPayload, ContactAddedPayload, ContactApprovedPayload, ContactCardPayload, ContactRemovedPayload, ContactRequestPayload, ContactSource, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, CanonMessage, CanonRuntimeProvenance, CanonConversation, CanonMessagesPage, CreateContactRequestResult, AgentContext, CanonStreamEvent, AgentSessionSnapshot, ResolvedAdmission, MediaAttachment, MediaAttachmentKind, MessageCreatedPayload, TypingPayload, PresencePayload, RuntimeUpdatedPayload, TurnUpdatedPayload, SendMessageOptions, CreateConversationOptions, RegistrationInput, RegistrationResult, RegistrationStatus, StreamingStatus, SetStreamingOptions, SessionControl, SessionState, SessionConfig, AgentRuntime, CanonRuntimeDescriptor, CanonRuntimeActionAvailability, CanonRuntimeActionCategory, CanonRuntimeActionDescriptor, CanonRuntimeActionDispatch, CanonRuntimeActionPlacement, CanonRuntimeCommandArgumentChoice, CanonRuntimeCommandArgumentDescriptor, CanonRuntimeCommandArgumentKind, CanonRuntimeCommandDescriptor, CanonRuntimeDetailTier, CanonRuntimeExecutionMetadata, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeFact, CanonRuntimeFactGroup, CanonRuntimeInventory, CanonRuntimeInventoryEntry, CanonRuntimePrimitiveId, CanonRuntimeStreamingMode, CanonRuntimeStatusItem, CanonRuntimeSurfaceMode, CanonWorkspaceRootMetadata, ModelOption, PermissionModeOption, RuntimeInfoPayload, RuntimeControlError, RuntimeControlState, RuntimeControlValueSource, WorkspaceOption, WorkspaceOptionSource, } from './types.js';
|
|
3
|
+
export { buildRuntimeProvenance, resolveRuntimeProvenance, } from './provenance.js';
|
|
3
4
|
export type { CanonSelfContext, CanonSelfContextType, SelfContextPromptRenderOptions, SendContextualMessageOptions, SendContextualMessageResult, SendContextualSelfContextInput, } from './self-context.js';
|
|
4
5
|
export { buildSelfContextPromptLines, normalizeSelfContexts, resolveMessageActiveSelfContextId, selectActiveSelfContexts, } from './self-context.js';
|
|
5
6
|
export { buildConfiguredWorkspaceOptionsWithRoots, buildPublicWorkspaceRoots, buildWorkspaceRootId, discoverWorkspaceProjects, } from './workspace-discovery.js';
|
|
@@ -16,8 +17,8 @@ export type { DeliveryIntent, TurnMessageSemantics, InboundDisposition, TurnLife
|
|
|
16
17
|
export { ackRegistrationApproval, registerAndWaitForApproval, submitRegistrationRequest, waitForRegistrationApproval, } from './registration.js';
|
|
17
18
|
export { ApprovalManager } from './approval-manager.js';
|
|
18
19
|
export { generateApprovalId, buildApprovalRequest, buildApprovalReply, buildApprovalOutcome, parseTextApprovalReply, redactSecrets, } from './approval-format.js';
|
|
19
|
-
export { DEFAULT_APPROVAL_CONFIG, } from './approval-types.js';
|
|
20
|
-
export type { ApprovalRequestMetadata, ApprovalReplyMetadata, ApprovalOutcomeMetadata, SessionRule, ApprovalResult, ApprovalConfig, } from './approval-types.js';
|
|
20
|
+
export { DEFAULT_APPROVAL_CONFIG, parseApprovalRequestMetadata, parseApprovalReplyMetadata, parseSessionRule, } from './approval-types.js';
|
|
21
|
+
export type { ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRequestMetadata, ApprovalNativeRequestMetadata, ApprovalRisk, ApprovalReplyMetadata, ApprovalOutcomeMetadata, SessionRule, ApprovalResult, ApprovalConfig, } from './approval-types.js';
|
|
21
22
|
export { buildPlanApprovalReply, buildPlanApprovalRequest, buildQuestionReply, buildQuestionRequest, } from './runtime-cards.js';
|
|
22
23
|
export type { ClaudeQuestionMetadata, ClaudeQuestionReplyMetadata, PlanApprovalMetadata, PlanApprovalReplyMetadata, RuntimeQuestionDefinition, RuntimeQuestionOption, } from './runtime-cards.js';
|
|
23
24
|
export { createStreamingHelper } from './streaming.js';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Types
|
|
2
2
|
export { AGENT_CAPABILITIES, CLAUDE_PERMISSION_MODE_OPTIONS, } from './types.js';
|
|
3
|
+
export { buildRuntimeProvenance, resolveRuntimeProvenance, } from './provenance.js';
|
|
3
4
|
export { buildSelfContextPromptLines, normalizeSelfContexts, resolveMessageActiveSelfContextId, selectActiveSelfContexts, } from './self-context.js';
|
|
4
5
|
export { buildConfiguredWorkspaceOptionsWithRoots, buildPublicWorkspaceRoots, buildWorkspaceRootId, discoverWorkspaceProjects, } from './workspace-discovery.js';
|
|
5
6
|
// Client
|
|
@@ -16,7 +17,7 @@ export { ackRegistrationApproval, registerAndWaitForApproval, submitRegistration
|
|
|
16
17
|
// Approval
|
|
17
18
|
export { ApprovalManager } from './approval-manager.js';
|
|
18
19
|
export { generateApprovalId, buildApprovalRequest, buildApprovalReply, buildApprovalOutcome, parseTextApprovalReply, redactSecrets, } from './approval-format.js';
|
|
19
|
-
export { DEFAULT_APPROVAL_CONFIG, } from './approval-types.js';
|
|
20
|
+
export { DEFAULT_APPROVAL_CONFIG, parseApprovalRequestMetadata, parseApprovalReplyMetadata, parseSessionRule, } from './approval-types.js';
|
|
20
21
|
export { buildPlanApprovalReply, buildPlanApprovalRequest, buildQuestionReply, buildQuestionRequest, } from './runtime-cards.js';
|
|
21
22
|
// Streaming (RTDB helpers)
|
|
22
23
|
export { createStreamingHelper } from './streaming.js';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { CanonConversation, CanonMessage, CanonRuntimeProvenance } from './types.js';
|
|
2
|
+
import type { CanonSelfContext } from './self-context.js';
|
|
3
|
+
export declare function buildRuntimeProvenance(input: {
|
|
4
|
+
conversationId: string;
|
|
5
|
+
conversationType?: CanonConversation['type'] | 'unknown' | string | null;
|
|
6
|
+
memberCount?: number | null;
|
|
7
|
+
senderId: string;
|
|
8
|
+
senderName?: string | null;
|
|
9
|
+
senderType?: CanonMessage['senderType'] | string | null;
|
|
10
|
+
isOwner?: boolean | null;
|
|
11
|
+
agentId?: string | null;
|
|
12
|
+
mentions?: readonly string[] | null;
|
|
13
|
+
mentionedAgent?: boolean | null;
|
|
14
|
+
activeSelfContextId?: string | null;
|
|
15
|
+
selfContexts?: readonly CanonSelfContext[] | null;
|
|
16
|
+
}): CanonRuntimeProvenance;
|
|
17
|
+
export declare function resolveRuntimeProvenance(input: {
|
|
18
|
+
provenance?: CanonRuntimeProvenance | null;
|
|
19
|
+
conversationId: string;
|
|
20
|
+
conversationType?: CanonConversation['type'] | 'unknown' | string | null;
|
|
21
|
+
memberCount?: number | null;
|
|
22
|
+
senderId: string;
|
|
23
|
+
senderName?: string | null;
|
|
24
|
+
senderType?: CanonMessage['senderType'] | string | null;
|
|
25
|
+
isOwner?: boolean | null;
|
|
26
|
+
agentId?: string | null;
|
|
27
|
+
mentions?: readonly string[] | null;
|
|
28
|
+
mentionedAgent?: boolean | null;
|
|
29
|
+
activeSelfContextId?: string | null;
|
|
30
|
+
selfContexts?: readonly CanonSelfContext[] | null;
|
|
31
|
+
}): CanonRuntimeProvenance;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
function normalizeConversationType(value) {
|
|
2
|
+
return value === 'direct' || value === 'group' ? value : 'unknown';
|
|
3
|
+
}
|
|
4
|
+
function normalizeSenderType(value) {
|
|
5
|
+
return value === 'ai_agent' ? 'ai_agent' : 'human';
|
|
6
|
+
}
|
|
7
|
+
function normalizeMemberCount(value) {
|
|
8
|
+
if (value == null)
|
|
9
|
+
return value;
|
|
10
|
+
return Number.isFinite(value) && value >= 0 ? Math.floor(value) : null;
|
|
11
|
+
}
|
|
12
|
+
function normalizeName(value) {
|
|
13
|
+
if (typeof value !== 'string')
|
|
14
|
+
return value == null ? value : undefined;
|
|
15
|
+
const trimmed = value.trim();
|
|
16
|
+
return trimmed ? trimmed : null;
|
|
17
|
+
}
|
|
18
|
+
function findSelfContextType(selfContexts, activeSelfContextId) {
|
|
19
|
+
if (!activeSelfContextId)
|
|
20
|
+
return null;
|
|
21
|
+
return selfContexts?.find((entry) => entry.id === activeSelfContextId)?.type ?? null;
|
|
22
|
+
}
|
|
23
|
+
export function buildRuntimeProvenance(input) {
|
|
24
|
+
const activeSelfContextId = typeof input.activeSelfContextId === 'string' && input.activeSelfContextId.trim()
|
|
25
|
+
? input.activeSelfContextId.trim()
|
|
26
|
+
: null;
|
|
27
|
+
const mentionedAgent = typeof input.mentionedAgent === 'boolean'
|
|
28
|
+
? input.mentionedAgent
|
|
29
|
+
: Boolean(input.agentId && input.mentions?.includes(input.agentId));
|
|
30
|
+
return {
|
|
31
|
+
conversation: {
|
|
32
|
+
id: input.conversationId,
|
|
33
|
+
type: normalizeConversationType(input.conversationType),
|
|
34
|
+
...(input.memberCount !== undefined
|
|
35
|
+
? { memberCount: normalizeMemberCount(input.memberCount) }
|
|
36
|
+
: {}),
|
|
37
|
+
},
|
|
38
|
+
sender: {
|
|
39
|
+
id: input.senderId,
|
|
40
|
+
...(input.senderName !== undefined ? { name: normalizeName(input.senderName) } : {}),
|
|
41
|
+
type: normalizeSenderType(input.senderType),
|
|
42
|
+
isOwner: input.isOwner === true,
|
|
43
|
+
},
|
|
44
|
+
mentionedAgent,
|
|
45
|
+
activeSelfContext: activeSelfContextId
|
|
46
|
+
? {
|
|
47
|
+
id: activeSelfContextId,
|
|
48
|
+
type: findSelfContextType(input.selfContexts, activeSelfContextId),
|
|
49
|
+
}
|
|
50
|
+
: null,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export function resolveRuntimeProvenance(input) {
|
|
54
|
+
if (!input.provenance) {
|
|
55
|
+
return buildRuntimeProvenance(input);
|
|
56
|
+
}
|
|
57
|
+
return buildRuntimeProvenance({
|
|
58
|
+
conversationId: input.provenance.conversation?.id || input.conversationId,
|
|
59
|
+
conversationType: input.provenance.conversation?.type ?? input.conversationType,
|
|
60
|
+
memberCount: input.provenance.conversation?.memberCount ?? input.memberCount,
|
|
61
|
+
senderId: input.provenance.sender?.id || input.senderId,
|
|
62
|
+
senderName: input.provenance.sender?.name ?? input.senderName,
|
|
63
|
+
senderType: input.provenance.sender?.type ?? input.senderType,
|
|
64
|
+
isOwner: input.provenance.sender?.isOwner ?? input.isOwner,
|
|
65
|
+
agentId: input.agentId,
|
|
66
|
+
mentions: input.mentions,
|
|
67
|
+
mentionedAgent: input.provenance.mentionedAgent ?? input.mentionedAgent,
|
|
68
|
+
activeSelfContextId: input.provenance.activeSelfContext?.id ?? input.activeSelfContextId,
|
|
69
|
+
selfContexts: input.selfContexts,
|
|
70
|
+
});
|
|
71
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -81,6 +81,24 @@ export interface CanonMessagesPage {
|
|
|
81
81
|
activeSelfContextIdByMessageId?: Record<string, string>;
|
|
82
82
|
selfContexts?: CanonSelfContext[];
|
|
83
83
|
}
|
|
84
|
+
export interface CanonRuntimeProvenance {
|
|
85
|
+
conversation: {
|
|
86
|
+
id: string;
|
|
87
|
+
type: CanonConversation['type'] | 'unknown';
|
|
88
|
+
memberCount?: number | null;
|
|
89
|
+
};
|
|
90
|
+
sender: {
|
|
91
|
+
id: string;
|
|
92
|
+
name?: string | null;
|
|
93
|
+
type: CanonMessage['senderType'];
|
|
94
|
+
isOwner: boolean;
|
|
95
|
+
};
|
|
96
|
+
mentionedAgent: boolean;
|
|
97
|
+
activeSelfContext?: {
|
|
98
|
+
id: string;
|
|
99
|
+
type?: CanonSelfContext['type'] | string | null;
|
|
100
|
+
} | null;
|
|
101
|
+
}
|
|
84
102
|
export type CanonContactRequestStatus = 'pending' | 'approved' | 'rejected' | 'expired';
|
|
85
103
|
export interface CanonContactRequest {
|
|
86
104
|
id: string;
|
|
@@ -88,6 +106,10 @@ export interface CanonContactRequest {
|
|
|
88
106
|
requesterName: string;
|
|
89
107
|
requesterAvatarUrl: string | null;
|
|
90
108
|
targetId: string;
|
|
109
|
+
targetName?: string | null;
|
|
110
|
+
targetAvatarUrl?: string | null;
|
|
111
|
+
targetUserType?: 'human' | 'ai_agent' | null;
|
|
112
|
+
targetOwnerId?: string | null;
|
|
91
113
|
approverId: string;
|
|
92
114
|
message: string | null;
|
|
93
115
|
status: CanonContactRequestStatus;
|
|
@@ -415,6 +437,7 @@ export interface MessageCreatedPayload {
|
|
|
415
437
|
behavior?: ResolvedAgentBehaviorPolicy;
|
|
416
438
|
activeSelfContextId?: string | null;
|
|
417
439
|
selfContexts?: CanonSelfContext[];
|
|
440
|
+
provenance?: CanonRuntimeProvenance;
|
|
418
441
|
message: {
|
|
419
442
|
id: string;
|
|
420
443
|
senderId: string;
|