@canonmsg/core 0.21.0 → 0.23.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-manager.js +62 -21
- package/dist/client.d.ts +59 -1
- package/dist/client.js +38 -0
- package/dist/index.d.ts +1 -1
- package/dist/types.d.ts +17 -1
- package/package.json +3 -2
package/dist/approval-manager.js
CHANGED
|
@@ -50,7 +50,7 @@ export class ApprovalManager {
|
|
|
50
50
|
}
|
|
51
51
|
const approvalId = generateApprovalId();
|
|
52
52
|
const expiresAt = new Date(Date.now() + this.config.timeoutSeconds * 1000).toISOString();
|
|
53
|
-
const {
|
|
53
|
+
const { metadata } = buildApprovalRequest(approvalId, toolName, toolInput, {
|
|
54
54
|
riskLevel: opts?.riskLevel,
|
|
55
55
|
risk: opts?.risk,
|
|
56
56
|
category: opts?.category,
|
|
@@ -63,29 +63,47 @@ export class ApprovalManager {
|
|
|
63
63
|
expiresAt,
|
|
64
64
|
redactPatterns: this.config.redactPatterns,
|
|
65
65
|
});
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
},
|
|
66
|
+
await this.client.createRuntimeApprovalRequest({
|
|
67
|
+
conversationId,
|
|
68
|
+
approvalId,
|
|
69
|
+
toolName,
|
|
70
|
+
toolSummary: metadata.toolSummary,
|
|
71
|
+
expiresAt: Date.parse(expiresAt),
|
|
72
|
+
responseUserId: this.ownerId,
|
|
73
|
+
...(opts?.riskLevel ? { riskLevel: opts.riskLevel } : {}),
|
|
74
|
+
...(opts?.risk ? { risk: opts.risk } : {}),
|
|
75
|
+
...(opts?.category ? { category: opts.category } : {}),
|
|
76
|
+
...(opts?.runtimeId ? { runtimeId: opts.runtimeId } : {}),
|
|
77
|
+
...(opts?.turnId ? { turnId: opts.turnId } : {}),
|
|
78
|
+
...(metadata.native ? { native: metadata.native } : {}),
|
|
79
|
+
...(metadata.details ? { details: metadata.details } : {}),
|
|
80
|
+
...(opts?.allowSessionRule === false ? { allowSessionRule: false } : {}),
|
|
74
81
|
});
|
|
75
82
|
// Wait for reply or timeout
|
|
76
83
|
return new Promise((resolve) => {
|
|
77
|
-
|
|
84
|
+
let settled = false;
|
|
85
|
+
let timer;
|
|
86
|
+
const finish = (result, reason) => {
|
|
87
|
+
if (settled)
|
|
88
|
+
return;
|
|
89
|
+
settled = true;
|
|
90
|
+
clearTimeout(timer);
|
|
78
91
|
this.pending.delete(approvalId);
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
92
|
+
if (reason === 'timeout') {
|
|
93
|
+
const msg = buildApprovalOutcome(approvalId, toolName, metadata.toolSummary, 'deny', 'timeout');
|
|
94
|
+
this.client.sendMessage(conversationId, msg, {
|
|
95
|
+
metadata: {
|
|
96
|
+
type: 'approval_outcome',
|
|
97
|
+
approvalId,
|
|
98
|
+
decision: 'deny',
|
|
99
|
+
reason: 'timeout',
|
|
100
|
+
},
|
|
101
|
+
}).catch(() => { });
|
|
102
|
+
}
|
|
103
|
+
resolve(result);
|
|
104
|
+
};
|
|
105
|
+
timer = setTimeout(() => {
|
|
106
|
+
finish({ decision: 'deny' }, 'timeout');
|
|
89
107
|
}, this.config.timeoutSeconds * 1000);
|
|
90
108
|
this.pending.set(approvalId, {
|
|
91
109
|
approvalId,
|
|
@@ -93,9 +111,32 @@ export class ApprovalManager {
|
|
|
93
111
|
toolName,
|
|
94
112
|
toolSummary: metadata.toolSummary,
|
|
95
113
|
allowSessionRule: opts?.allowSessionRule !== false,
|
|
96
|
-
resolve,
|
|
114
|
+
resolve: (result) => finish(result, 'replied'),
|
|
97
115
|
timer,
|
|
98
116
|
});
|
|
117
|
+
const poll = async () => {
|
|
118
|
+
while (this.pending.has(approvalId)) {
|
|
119
|
+
try {
|
|
120
|
+
const response = await this.client.consumeRuntimeApprovalResponse({
|
|
121
|
+
conversationId,
|
|
122
|
+
approvalId,
|
|
123
|
+
});
|
|
124
|
+
if (response.status === 'allow' || response.status === 'deny') {
|
|
125
|
+
this.resolveApproval(approvalId, response.status, response.sessionRule, conversationId);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (response.status === 'timeout') {
|
|
129
|
+
finish({ decision: 'deny' }, 'timeout');
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// Keep polling through transient API errors until the local timeout.
|
|
135
|
+
}
|
|
136
|
+
await new Promise((resume) => setTimeout(resume, 1000));
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
void poll();
|
|
99
140
|
});
|
|
100
141
|
}
|
|
101
142
|
/**
|
package/dist/client.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { type CanonMessage, type CanonConversation, type CanonContact, type CanonContactRequest, type CanonMessagesPage, type CanonResolveAdmissionResult, type AgentContext, type AddMemberResult, type CreateContactRequestResult, type MediaAttachment, type SendMessageOptions, type CreateConversationOptions, type RegistrationStatus, type SetStreamingOptions } from './types.js';
|
|
1
|
+
import { type CanonMessage, type CanonConversation, type CanonContact, type CanonContactRequest, type CanonMessagesPage, type CanonResolveAdmissionResult, type AgentContext, type AddMemberResult, type CreateContactRequestResult, type MediaAttachment, type SendMessageOptions, type CreateConversationOptions, type RegistrationStatus, type SetRuntimeTurnOptions, type SetStreamingOptions } from './types.js';
|
|
2
2
|
import type { RuntimeInputKind } from './runtime-cards.js';
|
|
3
|
+
import type { ApprovalNativeRequestMetadata, ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRisk, SessionRule } from './approval-types.js';
|
|
4
|
+
import type { RuntimeInputChoice, RuntimeInputNativeMetadata } from './runtime-cards.js';
|
|
3
5
|
import type { SendContextualMessageOptions, SendContextualMessageResult } from './self-context.js';
|
|
4
6
|
import type { InboundDisposition } from './turn-protocol.js';
|
|
5
7
|
/**
|
|
@@ -53,16 +55,26 @@ export declare class CanonClient {
|
|
|
53
55
|
removeMember(conversationId: string, userId: string): Promise<void>;
|
|
54
56
|
setStreaming(options: SetStreamingOptions): Promise<void>;
|
|
55
57
|
clearStreaming(conversationId: string): Promise<void>;
|
|
58
|
+
setRuntimeTurn(options: SetRuntimeTurnOptions): Promise<void>;
|
|
56
59
|
setTyping(conversationId: string, typing: boolean, status?: 'thinking' | 'typing'): Promise<void>;
|
|
57
60
|
createRuntimeInputRequest(options: {
|
|
58
61
|
conversationId: string;
|
|
59
62
|
inputId: string;
|
|
60
63
|
kind: RuntimeInputKind;
|
|
61
64
|
expiresAt: number;
|
|
65
|
+
title?: string;
|
|
66
|
+
prompt?: string;
|
|
67
|
+
choices?: RuntimeInputChoice[];
|
|
68
|
+
secretName?: string;
|
|
69
|
+
native?: RuntimeInputNativeMetadata;
|
|
70
|
+
sensitive?: boolean;
|
|
71
|
+
responseUserId?: string;
|
|
72
|
+
turnId?: string;
|
|
62
73
|
}): Promise<{
|
|
63
74
|
success: true;
|
|
64
75
|
inputId: string;
|
|
65
76
|
expiresAt: number;
|
|
77
|
+
messageId?: string;
|
|
66
78
|
}>;
|
|
67
79
|
consumeRuntimeInputResponse(options: {
|
|
68
80
|
conversationId: string;
|
|
@@ -86,6 +98,52 @@ export declare class CanonClient {
|
|
|
86
98
|
inputId: string;
|
|
87
99
|
kind: RuntimeInputKind;
|
|
88
100
|
}>;
|
|
101
|
+
createRuntimeApprovalRequest(options: {
|
|
102
|
+
conversationId: string;
|
|
103
|
+
approvalId?: string;
|
|
104
|
+
toolName: string;
|
|
105
|
+
toolSummary: string;
|
|
106
|
+
expiresAt: number;
|
|
107
|
+
responseUserId?: string;
|
|
108
|
+
riskLevel?: 'normal' | 'destructive';
|
|
109
|
+
risk?: ApprovalRisk;
|
|
110
|
+
category?: ApprovalRequestCategory;
|
|
111
|
+
runtimeId?: string;
|
|
112
|
+
turnId?: string;
|
|
113
|
+
native?: ApprovalNativeRequestMetadata;
|
|
114
|
+
details?: ApprovalRequestDetail[];
|
|
115
|
+
allowSessionRule?: boolean;
|
|
116
|
+
}): Promise<{
|
|
117
|
+
success: true;
|
|
118
|
+
approvalId: string;
|
|
119
|
+
expiresAt: number;
|
|
120
|
+
messageId?: string;
|
|
121
|
+
}>;
|
|
122
|
+
consumeRuntimeApprovalResponse(options: {
|
|
123
|
+
conversationId: string;
|
|
124
|
+
approvalId: string;
|
|
125
|
+
cancel?: boolean;
|
|
126
|
+
}): Promise<{
|
|
127
|
+
status: 'pending';
|
|
128
|
+
approvalId: string;
|
|
129
|
+
expiresAt?: number;
|
|
130
|
+
} | {
|
|
131
|
+
status: 'allow';
|
|
132
|
+
approvalId: string;
|
|
133
|
+
sessionRule?: SessionRule;
|
|
134
|
+
} | {
|
|
135
|
+
status: 'deny';
|
|
136
|
+
approvalId: string;
|
|
137
|
+
sessionRule?: SessionRule;
|
|
138
|
+
} | {
|
|
139
|
+
status: 'timeout';
|
|
140
|
+
approvalId: string;
|
|
141
|
+
}>;
|
|
142
|
+
updateRuntimeStatus(options: {
|
|
143
|
+
runtime: string;
|
|
144
|
+
hostMode?: boolean;
|
|
145
|
+
runtimeDescriptor?: Record<string, unknown>;
|
|
146
|
+
}): Promise<void>;
|
|
89
147
|
static register(baseUrl: string | undefined, body: {
|
|
90
148
|
name: string;
|
|
91
149
|
description: string;
|
package/dist/client.js
CHANGED
|
@@ -310,6 +310,15 @@ export class CanonClient {
|
|
|
310
310
|
if (!res.ok)
|
|
311
311
|
throw new CanonApiError(res.status, await res.text());
|
|
312
312
|
}
|
|
313
|
+
async setRuntimeTurn(options) {
|
|
314
|
+
const res = await fetch(`${this.baseUrl}/runtime/turn`, {
|
|
315
|
+
method: 'POST',
|
|
316
|
+
headers: this.authHeaders(),
|
|
317
|
+
body: JSON.stringify(options),
|
|
318
|
+
});
|
|
319
|
+
if (!res.ok)
|
|
320
|
+
throw new CanonApiError(res.status, await res.text());
|
|
321
|
+
}
|
|
313
322
|
async setTyping(conversationId, typing, status) {
|
|
314
323
|
const res = await fetch(`${this.baseUrl}/typing`, {
|
|
315
324
|
method: 'POST',
|
|
@@ -339,6 +348,35 @@ export class CanonClient {
|
|
|
339
348
|
throw new CanonApiError(res.status, await res.text());
|
|
340
349
|
return res.json();
|
|
341
350
|
}
|
|
351
|
+
async createRuntimeApprovalRequest(options) {
|
|
352
|
+
const res = await fetch(`${this.baseUrl}/runtime-approval/request`, {
|
|
353
|
+
method: 'POST',
|
|
354
|
+
headers: this.authHeaders(),
|
|
355
|
+
body: JSON.stringify(options),
|
|
356
|
+
});
|
|
357
|
+
if (!res.ok)
|
|
358
|
+
throw new CanonApiError(res.status, await res.text());
|
|
359
|
+
return res.json();
|
|
360
|
+
}
|
|
361
|
+
async consumeRuntimeApprovalResponse(options) {
|
|
362
|
+
const res = await fetch(`${this.baseUrl}/runtime-approval/consume`, {
|
|
363
|
+
method: 'POST',
|
|
364
|
+
headers: this.authHeaders(),
|
|
365
|
+
body: JSON.stringify(options),
|
|
366
|
+
});
|
|
367
|
+
if (!res.ok)
|
|
368
|
+
throw new CanonApiError(res.status, await res.text());
|
|
369
|
+
return res.json();
|
|
370
|
+
}
|
|
371
|
+
async updateRuntimeStatus(options) {
|
|
372
|
+
const res = await fetch(`${this.baseUrl}/runtime/status`, {
|
|
373
|
+
method: 'POST',
|
|
374
|
+
headers: this.authHeaders(),
|
|
375
|
+
body: JSON.stringify(options),
|
|
376
|
+
});
|
|
377
|
+
if (!res.ok)
|
|
378
|
+
throw new CanonApiError(res.status, await res.text());
|
|
379
|
+
}
|
|
342
380
|
// ── Static unauthenticated registration endpoints ────────────────────
|
|
343
381
|
static async register(baseUrl, body) {
|
|
344
382
|
const url = baseUrl || DEFAULT_BASE_URL;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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, 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, CanonRuntimePresentationField, CanonRuntimePresentationHint, CanonRuntimePresentationPolicy, CanonRuntimePresentationPreset, CanonRuntimeVisibility, 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, SetRuntimeTurnOptions, StreamingStatus, SetStreamingOptions, SessionControl, SessionState, SessionConfig, AgentRuntime, CanonRuntimeDescriptor, CanonRuntimeActionAvailability, CanonRuntimeActionCategory, CanonRuntimeActionDescriptor, CanonRuntimeActionDispatch, CanonRuntimeActionPlacement, CanonRuntimeCommandArgumentChoice, CanonRuntimeCommandArgumentDescriptor, CanonRuntimeCommandArgumentKind, CanonRuntimeCommandDescriptor, CanonRuntimeDetailTier, CanonRuntimeExecutionMetadata, CanonRuntimePresentationField, CanonRuntimePresentationHint, CanonRuntimePresentationPolicy, CanonRuntimePresentationPreset, CanonRuntimeVisibility, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeFact, CanonRuntimeFactGroup, CanonRuntimeInventory, CanonRuntimeInventoryEntry, CanonRuntimePrimitiveId, CanonRuntimeStreamingMode, CanonRuntimeStatusItem, CanonRuntimeSurfaceMode, CanonWorkspaceRootMetadata, ModelOption, PermissionModeOption, RuntimeInfoPayload, RuntimeControlError, RuntimeControlState, RuntimeControlValueSource, WorkspaceOption, WorkspaceOptionSource, } from './types.js';
|
|
3
3
|
export { DEFAULT_FIRST_PARTY_RUNTIME_PRESENTATION, RUNTIME_PRESENTATION_FIELDS, buildRuntimePresentationPolicy, getRuntimePresentationHint, isRuntimePresentationField, isRuntimePresentationFieldHidden, redactAgentRuntimeForConversation, redactAgentSessionSnapshotForConversation, redactExecutionMetadataForConversation, redactRuntimeActivityItemForConversation, redactRuntimeDescriptorForConversation, redactRuntimeInfoForConversation, redactSessionStateForConversation, } from './runtime-presentation.js';
|
|
4
4
|
export { buildRuntimeProvenance, resolveRuntimeProvenance, } from './provenance.js';
|
|
5
5
|
export type { CanonSelfContext, CanonSelfContextType, SelfContextPromptRenderOptions, SendContextualMessageOptions, SendContextualMessageResult, SendContextualSelfContextInput, } from './self-context.js';
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ExecutionEnvironmentMode } from './execution-environment-mode.js';
|
|
2
2
|
import type { ResolvedAgentBehaviorPolicy } from './policy.js';
|
|
3
|
-
import type { TurnLifecycleState } from './turn-protocol.js';
|
|
3
|
+
import type { DeliveryIntent, RuntimeCapabilities, TurnLifecycleState } from './turn-protocol.js';
|
|
4
4
|
import type { CanonSelfContext } from './self-context.js';
|
|
5
5
|
export type { ExecutionEnvironmentMode };
|
|
6
6
|
export type MediaAttachmentKind = 'image' | 'audio' | 'file';
|
|
@@ -614,6 +614,22 @@ export interface SetStreamingOptions {
|
|
|
614
614
|
status: StreamingStatus;
|
|
615
615
|
messageId: string;
|
|
616
616
|
}
|
|
617
|
+
export interface SetRuntimeTurnOptions {
|
|
618
|
+
conversationId: string;
|
|
619
|
+
state: TurnLifecycleState;
|
|
620
|
+
turnId?: string | null;
|
|
621
|
+
queueDepth?: number;
|
|
622
|
+
currentSpeakerId?: string | null;
|
|
623
|
+
lastAcceptedIntent?: DeliveryIntent | null;
|
|
624
|
+
activeMessageIds?: string[];
|
|
625
|
+
capabilities?: Partial<RuntimeCapabilities>;
|
|
626
|
+
openedAt?: number | null;
|
|
627
|
+
/**
|
|
628
|
+
* Set when this publish represents real turn progress. Omit for heartbeat or
|
|
629
|
+
* status-only refreshes so Canon can preserve stale-turn recovery semantics.
|
|
630
|
+
*/
|
|
631
|
+
turnUpdatedAt?: number | null;
|
|
632
|
+
}
|
|
617
633
|
/** Written by Canon app to /control/{convoId}/{agentId}/session in RTDB */
|
|
618
634
|
export interface SessionControl {
|
|
619
635
|
model?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonmsg/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "Canon core — shared types, REST client, SSE stream, and registration for Canon messaging",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -47,7 +47,8 @@
|
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/node": "^22.0.0",
|
|
50
|
-
"typescript": "~5.7.0"
|
|
50
|
+
"typescript": "~5.7.0",
|
|
51
|
+
"vitest": "^3.0.0"
|
|
51
52
|
},
|
|
52
53
|
"license": "MIT"
|
|
53
54
|
}
|