@canonmsg/agent-sdk 9.0.0 → 9.1.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/README.md +2 -1
- package/dist/canon-agent.js +106 -2
- package/dist/index.d.ts +2 -2
- package/dist/types.d.ts +18 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -200,6 +200,7 @@ The `message` event handler receives a context object with:
|
|
|
200
200
|
| `turnVerbosity` | `'verbose' \| 'quiet'` | Resolved emission mode for this turn — see [Turn verbosity](#turn-verbosity). Fixed for the whole turn |
|
|
201
201
|
| `requestApproval` | `(request) => Promise<ApprovalResult>` | Render a Canon approval card and wait for the decision. Fail-closed: returns `{ decision: 'deny' }` on any non-abort failure instead of throwing |
|
|
202
202
|
| `requestRuntimeInput` | `(request) => Promise<RuntimeInputResult>` | Render a Canon input card for clarification, sudo, or secret values |
|
|
203
|
+
| `requestPlanReview` | `(request) => Promise<RuntimePlanReviewResult>` | Render Canon's native plan-review card and wait for approve, revise, reject, cancellation, or timeout |
|
|
203
204
|
| `requestCard` / `sendCard` | functions | Render a generic `canon.card.v1` rich card. `requestCard` blocks only on cards that carry an `actions` block; `sendCard` posts a display card |
|
|
204
205
|
| `media` | `{ materialize, uploadFile, replyWithFile }` | Canon-managed access to real media bytes via `~/.canon/media-cache` plus local-file uploads back into Canon |
|
|
205
206
|
| `session` | `SessionInfo \| undefined` | Per-conversation queue/session state when sessions are enabled |
|
|
@@ -246,7 +247,7 @@ Reaction update events are interaction state, not new chat turns. They do not ca
|
|
|
246
247
|
|
|
247
248
|
### Human-in-the-loop cards
|
|
248
249
|
|
|
249
|
-
Use `ctx.requestRuntimeInput(...)` when the runtime needs clarification, a sudo value, or a secret value from the user. Use `ctx.requestApproval(...)` when the runtime needs an allow/deny decision before taking an action. Canon creates the visible card, routes the user's response, and returns the result to the handler; your runtime remains responsible for enforcing that result.
|
|
250
|
+
Use `ctx.requestRuntimeInput(...)` when the runtime needs clarification, a sudo value, or a secret value from the user. Use `ctx.requestPlanReview(...)` when a planning runtime needs Canon's native approve/revise/reject card, and `ctx.requestApproval(...)` when the runtime needs an allow/deny decision before taking an action. Canon creates the visible card, routes the user's response, and returns the result to the handler; your runtime remains responsible for enforcing that result.
|
|
250
251
|
|
|
251
252
|
`requestApproval` is fail-closed and never throws: it returns `{ decision: 'deny' }` when no approval manager can be built (no resolved agent identity or owner) and on any non-abort error. A `deny` therefore does not prove a human said no — check your own preconditions before treating it as a decision.
|
|
252
253
|
|
package/dist/canon-agent.js
CHANGED
|
@@ -245,6 +245,33 @@ function isAbortLikeError(error) {
|
|
|
245
245
|
return true;
|
|
246
246
|
return typeof record.message === 'string' && /\babort(?:ed)?\b/i.test(record.message);
|
|
247
247
|
}
|
|
248
|
+
function linkAbortSignals(turnSignal, requestSignal) {
|
|
249
|
+
if (!requestSignal || requestSignal === turnSignal) {
|
|
250
|
+
return { signal: turnSignal, dispose: () => { } };
|
|
251
|
+
}
|
|
252
|
+
const controller = new AbortController();
|
|
253
|
+
const abortFrom = (source) => {
|
|
254
|
+
if (!controller.signal.aborted)
|
|
255
|
+
controller.abort(source.reason);
|
|
256
|
+
};
|
|
257
|
+
const onTurnAbort = () => abortFrom(turnSignal);
|
|
258
|
+
const onRequestAbort = () => abortFrom(requestSignal);
|
|
259
|
+
if (turnSignal.aborted)
|
|
260
|
+
abortFrom(turnSignal);
|
|
261
|
+
else
|
|
262
|
+
turnSignal.addEventListener('abort', onTurnAbort, { once: true });
|
|
263
|
+
if (requestSignal.aborted)
|
|
264
|
+
abortFrom(requestSignal);
|
|
265
|
+
else
|
|
266
|
+
requestSignal.addEventListener('abort', onRequestAbort, { once: true });
|
|
267
|
+
return {
|
|
268
|
+
signal: controller.signal,
|
|
269
|
+
dispose: () => {
|
|
270
|
+
turnSignal.removeEventListener('abort', onTurnAbort);
|
|
271
|
+
requestSignal.removeEventListener('abort', onRequestAbort);
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
}
|
|
248
275
|
export class CanonAgent {
|
|
249
276
|
options;
|
|
250
277
|
runtimeConnection;
|
|
@@ -1706,6 +1733,7 @@ export class CanonAgent {
|
|
|
1706
1733
|
};
|
|
1707
1734
|
const requestRuntimeInput = async (request) => {
|
|
1708
1735
|
throwIfAborted();
|
|
1736
|
+
const linkedSignal = linkAbortSignals(abortController.signal, request.signal);
|
|
1709
1737
|
const inputId = safeRuntimeInputId(request.inputId, request.kind);
|
|
1710
1738
|
const timeoutMs = Math.max(1_000, request.timeoutMs ?? DEFAULT_RUNTIME_INPUT_TIMEOUT_MS);
|
|
1711
1739
|
const expiresAtMs = Date.now() + timeoutMs;
|
|
@@ -1761,7 +1789,7 @@ export class CanonAgent {
|
|
|
1761
1789
|
result = await this.ensureRuntimeRequestManager().request('input', conversationId, { kind: request.kind }, {
|
|
1762
1790
|
requestId: inputId,
|
|
1763
1791
|
expiresAt: expiresAtMs,
|
|
1764
|
-
signal:
|
|
1792
|
+
signal: linkedSignal.signal,
|
|
1765
1793
|
});
|
|
1766
1794
|
const outcome = buildRuntimeInputOutcome(inputId, result.status, {
|
|
1767
1795
|
kind: request.kind,
|
|
@@ -1787,7 +1815,7 @@ export class CanonAgent {
|
|
|
1787
1815
|
return result;
|
|
1788
1816
|
}
|
|
1789
1817
|
catch (error) {
|
|
1790
|
-
if (abortController.signal.aborted || isAbortLikeError(error)) {
|
|
1818
|
+
if (abortController.signal.aborted || request.signal?.aborted || isAbortLikeError(error)) {
|
|
1791
1819
|
if (requestCreated) {
|
|
1792
1820
|
// Abort landing before the manager wired its cancel (e.g. during
|
|
1793
1821
|
// the pre-request writeTurn/typing round-trips) leaves the
|
|
@@ -1810,6 +1838,81 @@ export class CanonAgent {
|
|
|
1810
1838
|
await resumeTurnFromWaiting();
|
|
1811
1839
|
return result;
|
|
1812
1840
|
}
|
|
1841
|
+
finally {
|
|
1842
|
+
linkedSignal.dispose();
|
|
1843
|
+
}
|
|
1844
|
+
};
|
|
1845
|
+
const requestPlanReview = async (request) => {
|
|
1846
|
+
throwIfAborted();
|
|
1847
|
+
const linkedSignal = linkAbortSignals(abortController.signal, request.signal);
|
|
1848
|
+
const planId = request.planId && RUNTIME_INPUT_ID_PATTERN.test(request.planId)
|
|
1849
|
+
? request.planId
|
|
1850
|
+
: randomUUID();
|
|
1851
|
+
const timeoutMs = Math.max(1_000, request.timeoutMs ?? DEFAULT_RUNTIME_INPUT_TIMEOUT_MS);
|
|
1852
|
+
const expiresAtMs = Date.now() + timeoutMs;
|
|
1853
|
+
const responseUserId = normalizeResponseUserId(request.responseUserId)
|
|
1854
|
+
?? triggeringHumanId
|
|
1855
|
+
?? normalizeResponseUserId(agent.ownerId);
|
|
1856
|
+
let created = false;
|
|
1857
|
+
let result = { status: 'timeout', planId };
|
|
1858
|
+
shouldPersistTurnState = true;
|
|
1859
|
+
try {
|
|
1860
|
+
result = await this.ensureRuntimeRequestManager().request('plan', conversationId, {
|
|
1861
|
+
...(request.title ? { title: request.title } : {}),
|
|
1862
|
+
...(request.summary ? { summary: request.summary } : {}),
|
|
1863
|
+
...(request.body ? { body: request.body } : {}),
|
|
1864
|
+
...(request.allowedPrompts ? { allowedPrompts: request.allowedPrompts } : {}),
|
|
1865
|
+
...(responseUserId ? { responseUserId } : {}),
|
|
1866
|
+
turnId: request.turnId ?? turnId,
|
|
1867
|
+
}, {
|
|
1868
|
+
requestId: planId,
|
|
1869
|
+
expiresAt: expiresAtMs,
|
|
1870
|
+
responderPolicy: 'infer',
|
|
1871
|
+
signal: linkedSignal.signal,
|
|
1872
|
+
onCreated: async () => {
|
|
1873
|
+
created = true;
|
|
1874
|
+
try {
|
|
1875
|
+
await turnOutput.addBlock({
|
|
1876
|
+
id: `plan:${planId}`,
|
|
1877
|
+
kind: 'input',
|
|
1878
|
+
status: 'pending',
|
|
1879
|
+
title: request.title ?? 'Plan review',
|
|
1880
|
+
summary: request.summary ?? 'Review requested',
|
|
1881
|
+
});
|
|
1882
|
+
await turnOutput.waitingInput();
|
|
1883
|
+
}
|
|
1884
|
+
catch { }
|
|
1885
|
+
await writeTurn('waiting_input');
|
|
1886
|
+
try {
|
|
1887
|
+
await this.typingSignals.clear(conversationId);
|
|
1888
|
+
}
|
|
1889
|
+
catch { }
|
|
1890
|
+
},
|
|
1891
|
+
});
|
|
1892
|
+
throwIfAborted();
|
|
1893
|
+
shouldPersistTurnState = false;
|
|
1894
|
+
try {
|
|
1895
|
+
await turnOutput.completeBlock(`plan:${planId}`, {
|
|
1896
|
+
summary: `Plan ${result.status}`,
|
|
1897
|
+
});
|
|
1898
|
+
}
|
|
1899
|
+
catch { }
|
|
1900
|
+
await resumeTurnFromWaiting();
|
|
1901
|
+
return result;
|
|
1902
|
+
}
|
|
1903
|
+
catch (error) {
|
|
1904
|
+
if (abortController.signal.aborted || request.signal?.aborted || isAbortLikeError(error)) {
|
|
1905
|
+
throw error;
|
|
1906
|
+
}
|
|
1907
|
+
shouldPersistTurnState = false;
|
|
1908
|
+
if (!created)
|
|
1909
|
+
throw error;
|
|
1910
|
+
await resumeTurnFromWaiting();
|
|
1911
|
+
return result;
|
|
1912
|
+
}
|
|
1913
|
+
finally {
|
|
1914
|
+
linkedSignal.dispose();
|
|
1915
|
+
}
|
|
1813
1916
|
};
|
|
1814
1917
|
const sendCard = async (request) => {
|
|
1815
1918
|
throwIfAborted();
|
|
@@ -2020,6 +2123,7 @@ export class CanonAgent {
|
|
|
2020
2123
|
turnVerbosity,
|
|
2021
2124
|
requestApproval,
|
|
2022
2125
|
requestRuntimeInput,
|
|
2126
|
+
requestPlanReview,
|
|
2023
2127
|
requestCard,
|
|
2024
2128
|
sendCard,
|
|
2025
2129
|
abortSignal: abortController.signal,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export { CanonAgent } from './canon-agent.js';
|
|
2
2
|
export type { AgentContactsAPI, AgentConversationsAPI, AgentUsersAPI } from './canon-agent.js';
|
|
3
3
|
export { ApprovalManager, buildApprovalOutcome, buildApprovalReply, buildApprovalRequest, CanonApiError, DEFAULT_APPROVAL_CONFIG, generateApprovalId, HOST_ADMISSION_ACTION_CAPABILITIES, HOST_ADMISSION_ACTIONS_DISABLED, parseApprovalReplyMetadata, parseApprovalRequestMetadata, parseSessionRule, redactSecrets, } from '@canonmsg/core';
|
|
4
|
-
export type { ApprovalConfig, ApprovalNativeRequestMetadata, ApprovalOutcomeMetadata, ApprovalReplyMetadata, ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRequestMetadata, ApprovalResult, ApprovalRisk, CanonContact, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeTurnModeActivation, CanonRuntimeTurnModeDescriptor, CanonRuntimeTurnModeScope, CanonRuntimeFact, CanonRuntimeFactGroup, CanonResolveAdmissionResult, ContactAddedPayload, ContactCardPayload, ContactRemovedPayload, ContactSource, HostAdmissionActionCapabilities, ParticipationSuppressedPayload, ResolveAdmissionTargetInput, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, ResumableMediaUploadResult, MediaAttachment, VideoProcessingStatus, VideoProcessingErrorCode, RuntimeInputAnswers, RuntimeInputChoice, RuntimeInputKind, RuntimeInputNativeMetadata, RuntimeInputQuestion, SessionRule, } from '@canonmsg/core';
|
|
4
|
+
export type { ApprovalConfig, ApprovalNativeRequestMetadata, ApprovalOutcomeMetadata, ApprovalReplyMetadata, ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRequestMetadata, ApprovalResult, ApprovalRisk, CanonContact, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeTurnModeActivation, CanonRuntimeTurnModeDescriptor, CanonRuntimeTurnModeScope, CanonRuntimeFact, CanonRuntimeFactGroup, CanonResolveAdmissionResult, ContactAddedPayload, ContactCardPayload, ContactRemovedPayload, ContactSource, HostAdmissionActionCapabilities, ParticipationSuppressedPayload, ResolveAdmissionTargetInput, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, ResumableMediaUploadResult, MediaAttachment, VideoProcessingStatus, VideoProcessingErrorCode, RuntimeInputAnswers, RuntimeInputChoice, RuntimeInputKind, RuntimeInputNativeMetadata, RuntimeInputQuestion, RuntimePlanRequestPayload, RuntimePlanRequestResult, SessionRule, } from '@canonmsg/core';
|
|
5
5
|
export { SessionManager } from './session-manager.js';
|
|
6
6
|
export { DEFAULT_ANTHROPIC_REQUEST_HEADROOM_BYTES, DEFAULT_MEDIA_CACHE_DIR, DEFAULT_MEDIA_MATERIALIZATION_BYTES, MAX_ANTHROPIC_IMAGE_RAW_BYTES, MAX_ANTHROPIC_REQUEST_BYTES, MAX_CANON_MEDIA_BYTES, getCodexImagePath, getMessageAttachments, inferUploadMimeType, isAnthropicImageAttachment, materializeAttachment, materializeMessageMedia, materializeReplyContextMedia, resolveAttachmentMimeType, sendMediaFileMessage, toAnthropicImageBlock, toAnthropicImageBlocksWithinBudget, uploadMediaFile, } from './media.js';
|
|
7
7
|
export type { AnthropicImageBlock, AnthropicImageBudgetOptions, AnthropicImageMimeType, MaterializeMediaOptions, MaterializedCanonAttachment, MaterializedCanonReplyContext, ReplyWithFileOptions, UploadMediaFileOptions, } from './media.js';
|
|
8
8
|
export type { SessionConfig, Session } from './session-manager.js';
|
|
9
9
|
export type { CanonAgentTurnVerbosityOption } from './turn-verbosity-option.js';
|
|
10
10
|
export type { AgentContext, CanonGroupContext, CanonKnownRecentParticipant, CanonMembershipChange, CanonContactRequest, GroupInviteRequirements, CanonMessage, CanonConversation, CommunicateInput, CommunicateResult, DirectConversationSelection, CanonConversationsPage, CanonConversationsPageOptions, CanonReplyContext, CanonSelfContext, CanonTurnContextV2, CanonRuntimeDescriptor, MessageUpdatedPayload, SendMessageOptions, CreateGroupOptions, CreateGroupResult, TurnVerbosity, TurnVerbosityConfig, } from '@canonmsg/core';
|
|
11
|
-
export type { CanonAgentConnectionOptions, CanonAgentOptions, ContactAddedHandler, ContactRemovedHandler, ContactRequestHandler, FinalMessageResult, MessageHandler, MessageHandlerContext, MessageUpdatedHandler, ParticipationSuppressedHandler, ProgressMessageOptions, ProgressMessageResult, RuntimeApprovalRequest, RuntimeInputRequest, RuntimeInputResult, RuntimeControlSurface, RuntimePrimitiveContext, RuntimePrimitiveHandler, RuntimePrimitiveHandlers, SessionInfo, SessionOptions, DeliveryMode, } from './types.js';
|
|
11
|
+
export type { CanonAgentConnectionOptions, CanonAgentOptions, ContactAddedHandler, ContactRemovedHandler, ContactRequestHandler, FinalMessageResult, MessageHandler, MessageHandlerContext, MessageUpdatedHandler, ParticipationSuppressedHandler, ProgressMessageOptions, ProgressMessageResult, RuntimeApprovalRequest, RuntimeInputRequest, RuntimeInputResult, RuntimePlanReviewRequest, RuntimePlanReviewResult, RuntimeControlSurface, RuntimePrimitiveContext, RuntimePrimitiveHandler, RuntimePrimitiveHandlers, SessionInfo, SessionOptions, DeliveryMode, } from './types.js';
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export type { AddMemberResult, GroupInviteRequirements, AgentClientType, CanonGroupContext, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeDescriptor, CanonRuntimeFact, CanonRuntimeFactGroup, CanonRuntimePrimitiveId, CanonRuntimeProvenance, CanonTurnContextV2, CanonMessage, CanonConversation, CommunicateInput, CommunicateResult, CanonReplyContext, CanonContact, CanonContactRequest, CanonResolveAdmissionResult, ContactAddedPayload, ContactRemovedPayload, ContactSource, AgentContext, ResolveAdmissionTargetInput, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, CanonSelfContext, CreateGroupOptions, CreateGroupResult, SendMessageOptions, SessionConfig, TurnLifecycleState, TurnOutputBlock, TurnOutputBlockInput, ApprovalNativeRequestMetadata, ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRequestMetadata, ApprovalRisk, ApprovalReplyMetadata, ApprovalOutcomeMetadata, RuntimeInputChoice, RuntimeInputAnswers, RuntimeInputKind, RuntimeInputNativeMetadata, RuntimeInputQuestion, RuntimeCardNativeMetadata, RuntimeCardV1, ResumableMediaUploadResult, MediaAttachment, VideoProcessingStatus, VideoProcessingErrorCode, SessionRule, ApprovalResult, } from '@canonmsg/core';
|
|
2
|
-
import type { AddMemberResult, CanonGroupContext, CanonMessage, CanonConversation, CommunicateInput, CommunicateResult, CanonReplyContext, CanonRuntimeActionDispatch, CanonRuntimePrimitiveId, CanonRuntimeProvenance, CanonTurnContextV2, ApprovalNativeRequestMetadata, ApprovalRequestCategory, ApprovalRequestDetail, ApprovalResult, ApprovalRisk, RuntimeInputChoice, RuntimeInputAnswers, RuntimeInputKind, RuntimeInputNativeMetadata, RuntimeInputQuestion, RuntimeCardNativeMetadata, RuntimeCardV1, ResumableMediaUploadResult, SendMessageOptions, TurnOutputBlock, TurnOutputBlockInput } from '@canonmsg/core';
|
|
1
|
+
export type { AddMemberResult, GroupInviteRequirements, AgentClientType, CanonGroupContext, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeDescriptor, CanonRuntimeFact, CanonRuntimeFactGroup, CanonRuntimePrimitiveId, CanonRuntimeProvenance, CanonTurnContextV2, CanonMessage, CanonConversation, CommunicateInput, CommunicateResult, CanonReplyContext, CanonContact, CanonContactRequest, CanonResolveAdmissionResult, ContactAddedPayload, ContactRemovedPayload, ContactSource, AgentContext, ResolveAdmissionTargetInput, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, CanonSelfContext, CreateGroupOptions, CreateGroupResult, SendMessageOptions, SessionConfig, TurnLifecycleState, TurnOutputBlock, TurnOutputBlockInput, ApprovalNativeRequestMetadata, ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRequestMetadata, ApprovalRisk, ApprovalReplyMetadata, ApprovalOutcomeMetadata, RuntimeInputChoice, RuntimeInputAnswers, RuntimeInputKind, RuntimeInputNativeMetadata, RuntimeInputQuestion, RuntimePlanRequestPayload, RuntimePlanRequestResult, RuntimeCardNativeMetadata, RuntimeCardV1, ResumableMediaUploadResult, MediaAttachment, VideoProcessingStatus, VideoProcessingErrorCode, SessionRule, ApprovalResult, } from '@canonmsg/core';
|
|
2
|
+
import type { AddMemberResult, CanonGroupContext, CanonMessage, CanonConversation, CommunicateInput, CommunicateResult, CanonReplyContext, CanonRuntimeActionDispatch, CanonRuntimePrimitiveId, CanonRuntimeProvenance, CanonTurnContextV2, ApprovalNativeRequestMetadata, ApprovalRequestCategory, ApprovalRequestDetail, ApprovalResult, ApprovalRisk, RuntimeInputChoice, RuntimeInputAnswers, RuntimeInputKind, RuntimeInputNativeMetadata, RuntimeInputQuestion, RuntimePlanRequestPayload, RuntimePlanRequestResult, RuntimeCardNativeMetadata, RuntimeCardV1, ResumableMediaUploadResult, SendMessageOptions, TurnOutputBlock, TurnOutputBlockInput } from '@canonmsg/core';
|
|
3
3
|
import type { MaterializeMediaOptions, MaterializedCanonAttachment, ReplyWithFileOptions, UploadMediaFileOptions } from './media.js';
|
|
4
4
|
export interface ProgressMessageOptions extends SendMessageOptions {
|
|
5
5
|
/**
|
|
@@ -119,6 +119,8 @@ export interface RuntimeInputRequest {
|
|
|
119
119
|
native?: RuntimeInputNativeMetadata;
|
|
120
120
|
inputId?: string;
|
|
121
121
|
timeoutMs?: number;
|
|
122
|
+
/** Aborts the pending input request without waiting for the enclosing turn to stop. */
|
|
123
|
+
signal?: AbortSignal;
|
|
122
124
|
/** Human conversation member who should answer. Secret and sudo prompts remain owner-only. */
|
|
123
125
|
responseUserId?: string;
|
|
124
126
|
}
|
|
@@ -128,6 +130,14 @@ export interface RuntimeInputResult {
|
|
|
128
130
|
answers?: RuntimeInputAnswers;
|
|
129
131
|
inputId: string;
|
|
130
132
|
}
|
|
133
|
+
/** Native Canon plan-review card backed by Core's existing runtime-plan interaction. */
|
|
134
|
+
export interface RuntimePlanReviewRequest extends RuntimePlanRequestPayload {
|
|
135
|
+
planId?: string;
|
|
136
|
+
timeoutMs?: number;
|
|
137
|
+
/** Aborts the pending plan review without waiting for the enclosing turn to stop. */
|
|
138
|
+
signal?: AbortSignal;
|
|
139
|
+
}
|
|
140
|
+
export type RuntimePlanReviewResult = RuntimePlanRequestResult;
|
|
131
141
|
export interface RuntimeCardRequest {
|
|
132
142
|
card: RuntimeCardV1;
|
|
133
143
|
cardId?: string;
|
|
@@ -210,6 +220,12 @@ export interface MessageHandlerContext {
|
|
|
210
220
|
* are never persisted in Canon message metadata.
|
|
211
221
|
*/
|
|
212
222
|
requestRuntimeInput: (request: RuntimeInputRequest) => Promise<RuntimeInputResult>;
|
|
223
|
+
/**
|
|
224
|
+
* Present a native Canon plan-review card and wait for approve, revise,
|
|
225
|
+
* reject, cancellation, or timeout. Canon owns presentation and response
|
|
226
|
+
* routing; the runtime remains responsible for enforcing the decision.
|
|
227
|
+
*/
|
|
228
|
+
requestPlanReview: (request: RuntimePlanReviewRequest) => Promise<RuntimePlanReviewResult>;
|
|
213
229
|
/**
|
|
214
230
|
* Ask the triggering human to review/respond to a generic rich card. The
|
|
215
231
|
* visible card document is redacted for presentation; raw response values
|