@canonmsg/core 0.19.1 → 0.19.3

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.
@@ -1,3 +1,4 @@
1
+ import { redactAgentSessionSnapshotForConversation } from './runtime-presentation.js';
1
2
  function listDescriptorControls(runtime) {
2
3
  const descriptor = runtime?.runtimeDescriptor;
3
4
  return [
@@ -104,7 +105,7 @@ export function buildAgentSessionSnapshot(input) {
104
105
  const executionMode = input.sessionState?.executionMode
105
106
  ?? input.sessionConfig?.executionMode;
106
107
  const controlState = buildControlState(input);
107
- return {
108
+ const snapshot = {
108
109
  conversationId: input.conversationId,
109
110
  agentId: input.agentId,
110
111
  clientType: input.sessionConfig?.clientType
@@ -132,7 +133,7 @@ export function buildAgentSessionSnapshot(input) {
132
133
  executionFallbackReason: input.sessionState?.executionFallbackReason,
133
134
  turnState: input.turnState?.state,
134
135
  supportsQueue: input.turnState?.capabilities?.supportsQueue,
135
- supportsInputInterrupt: input.turnState?.capabilities?.supportsInterrupt,
136
+ supportsInputInterrupt: input.turnState?.capabilities?.supportsInputInterrupt,
136
137
  queueDepth: input.turnState?.queueDepth ?? 0,
137
138
  waitingForInput: input.turnState?.state === 'waiting_input',
138
139
  contextUsage: input.sessionState?.contextUsage,
@@ -146,4 +147,5 @@ export function buildAgentSessionSnapshot(input) {
146
147
  ?? input.sessionConfig?.updatedAt
147
148
  ?? input.runtime?.updatedAt,
148
149
  };
150
+ return redactAgentSessionSnapshotForConversation(input.runtime?.runtimeDescriptor, snapshot);
149
151
  }
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, 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';
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, CanonRuntimePresentationField, CanonRuntimePresentationHint, CanonRuntimePresentationPolicy, CanonRuntimePresentationPreset, CanonRuntimeVisibility, 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 { DEFAULT_FIRST_PARTY_RUNTIME_PRESENTATION, RUNTIME_PRESENTATION_FIELDS, buildRuntimePresentationPolicy, getRuntimePresentationHint, isRuntimePresentationField, isRuntimePresentationFieldHidden, redactAgentSessionSnapshotForConversation, redactExecutionMetadataForConversation, redactRuntimeDescriptorForConversation, redactRuntimeInfoForConversation, } from './runtime-presentation.js';
5
6
  export { buildRuntimeProvenance, resolveRuntimeProvenance, } from './provenance.js';
6
7
  export { EXECUTION_ENVIRONMENT_MODES, isExecutionEnvironmentMode, } from './execution-environment-mode.js';
7
8
  export type { ExecutionEnvironmentMode } from './execution-environment-mode.js';
@@ -16,5 +17,5 @@ export type { DeliveryIntent, InboundDisposition, RuntimeCapabilities, TriggerDe
16
17
  export { buildApprovalReply, buildApprovalRequest, buildApprovalOutcome, generateApprovalId, parseTextApprovalReply, redactSecrets, } from './approval-format.js';
17
18
  export type { ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRequestMetadata, ApprovalNativeRequestMetadata, ApprovalRisk, ApprovalReplyMetadata, ApprovalOutcomeMetadata, SessionRule, ApprovalResult, ApprovalConfig, } from './approval-types.js';
18
19
  export { DEFAULT_APPROVAL_CONFIG, parseApprovalRequestMetadata, parseApprovalReplyMetadata, parseSessionRule, } from './approval-types.js';
19
- export { buildPlanApprovalReply, buildPlanApprovalRequest, buildQuestionReply, buildQuestionRequest, } from './runtime-cards.js';
20
- export type { ClaudeQuestionMetadata, ClaudeQuestionReplyMetadata, PlanApprovalMetadata, PlanApprovalReplyMetadata, RuntimeQuestionDefinition, RuntimeQuestionOption, } from './runtime-cards.js';
20
+ export { buildRuntimeInputOutcome, buildRuntimeInputReply, buildRuntimeInputRequest, buildPlanApprovalReply, buildPlanApprovalRequest, buildQuestionReply, buildQuestionRequest, parseRuntimeInputOutcomeMetadata, parseRuntimeInputReplyMetadata, parseRuntimeInputRequestMetadata, } from './runtime-cards.js';
21
+ export type { ClaudeQuestionMetadata, ClaudeQuestionReplyMetadata, PlanApprovalMetadata, PlanApprovalReplyMetadata, RuntimeInputChoice, RuntimeInputKind, RuntimeInputNativeMetadata, RuntimeInputOutcomeMetadata, RuntimeInputReplyMetadata, RuntimeInputReplyStatus, RuntimeInputRequestMetadata, RuntimeInputResolutionStatus, 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 { DEFAULT_FIRST_PARTY_RUNTIME_PRESENTATION, RUNTIME_PRESENTATION_FIELDS, buildRuntimePresentationPolicy, getRuntimePresentationHint, isRuntimePresentationField, isRuntimePresentationFieldHidden, redactAgentSessionSnapshotForConversation, redactExecutionMetadataForConversation, redactRuntimeDescriptorForConversation, redactRuntimeInfoForConversation, } from './runtime-presentation.js';
4
5
  export { buildRuntimeProvenance, resolveRuntimeProvenance, } from './provenance.js';
5
6
  export { EXECUTION_ENVIRONMENT_MODES, isExecutionEnvironmentMode, } from './execution-environment-mode.js';
6
7
  export { buildSelfContextPromptLines, normalizeSelfContexts, } from './self-context.js';
@@ -10,4 +11,4 @@ export { buildParticipationHistorySnapshot, buildParticipationHistorySnapshots,
10
11
  export { DEFAULT_RUNTIME_CAPABILITIES, FINAL_MESSAGE_HANDOFF_MS, isTurnOpen, normalizeTurnMetadata, normalizeTurnState, resolveTurnMessageSemantics, shouldPromoteConversationMessage, shouldTriggerAgentTurn, } from './turn-protocol.js';
11
12
  export { buildApprovalReply, buildApprovalRequest, buildApprovalOutcome, generateApprovalId, parseTextApprovalReply, redactSecrets, } from './approval-format.js';
12
13
  export { DEFAULT_APPROVAL_CONFIG, parseApprovalRequestMetadata, parseApprovalReplyMetadata, parseSessionRule, } from './approval-types.js';
13
- export { buildPlanApprovalReply, buildPlanApprovalRequest, buildQuestionReply, buildQuestionRequest, } from './runtime-cards.js';
14
+ export { buildRuntimeInputOutcome, buildRuntimeInputReply, buildRuntimeInputRequest, buildPlanApprovalReply, buildPlanApprovalRequest, buildQuestionReply, buildQuestionRequest, parseRuntimeInputOutcomeMetadata, parseRuntimeInputReplyMetadata, parseRuntimeInputRequestMetadata, } from './runtime-cards.js';
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, 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';
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';
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';
3
4
  export { buildRuntimeProvenance, resolveRuntimeProvenance, } from './provenance.js';
4
5
  export type { CanonSelfContext, CanonSelfContextType, SelfContextPromptRenderOptions, SendContextualMessageOptions, SendContextualMessageResult, SendContextualSelfContextInput, } from './self-context.js';
5
6
  export { buildSelfContextPromptLines, normalizeSelfContexts, resolveMessageActiveSelfContextId, selectActiveSelfContexts, } from './self-context.js';
@@ -19,8 +20,8 @@ export { ApprovalManager } from './approval-manager.js';
19
20
  export { generateApprovalId, buildApprovalRequest, buildApprovalReply, buildApprovalOutcome, parseTextApprovalReply, redactSecrets, } from './approval-format.js';
20
21
  export { DEFAULT_APPROVAL_CONFIG, parseApprovalRequestMetadata, parseApprovalReplyMetadata, parseSessionRule, } from './approval-types.js';
21
22
  export type { ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRequestMetadata, ApprovalNativeRequestMetadata, ApprovalRisk, ApprovalReplyMetadata, ApprovalOutcomeMetadata, SessionRule, ApprovalResult, ApprovalConfig, } from './approval-types.js';
22
- export { buildPlanApprovalReply, buildPlanApprovalRequest, buildQuestionReply, buildQuestionRequest, } from './runtime-cards.js';
23
- export type { ClaudeQuestionMetadata, ClaudeQuestionReplyMetadata, PlanApprovalMetadata, PlanApprovalReplyMetadata, RuntimeQuestionDefinition, RuntimeQuestionOption, } from './runtime-cards.js';
23
+ export { buildRuntimeInputOutcome, buildRuntimeInputReply, buildRuntimeInputRequest, buildPlanApprovalReply, buildPlanApprovalRequest, buildQuestionReply, buildQuestionRequest, parseRuntimeInputOutcomeMetadata, parseRuntimeInputReplyMetadata, parseRuntimeInputRequestMetadata, } from './runtime-cards.js';
24
+ export type { ClaudeQuestionMetadata, ClaudeQuestionReplyMetadata, PlanApprovalMetadata, PlanApprovalReplyMetadata, RuntimeInputChoice, RuntimeInputKind, RuntimeInputNativeMetadata, RuntimeInputOutcomeMetadata, RuntimeInputReplyMetadata, RuntimeInputReplyStatus, RuntimeInputRequestMetadata, RuntimeInputResolutionStatus, RuntimeQuestionDefinition, RuntimeQuestionOption, } from './runtime-cards.js';
24
25
  export { createStreamingHelper } from './streaming.js';
25
26
  export type { RTDBHandle, RTDBRef, ServerTimestamp, StreamingHelperOptions, StreamingNode } from './streaming.js';
26
27
  export { clearPendingRegistration, getOrCreatePendingRegistration, loadPendingRegistrations, loadProfiles, savePendingRegistrations, saveProfiles, updatePendingRegistration, upsertAgentProfile, isProfileLocked, acquireLock, releaseLock, isProcessAlive, CANON_DIR, AGENTS_PATH, LOCKS_DIR, } from './agent-profiles.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 { DEFAULT_FIRST_PARTY_RUNTIME_PRESENTATION, RUNTIME_PRESENTATION_FIELDS, buildRuntimePresentationPolicy, getRuntimePresentationHint, isRuntimePresentationField, isRuntimePresentationFieldHidden, redactAgentRuntimeForConversation, redactAgentSessionSnapshotForConversation, redactExecutionMetadataForConversation, redactRuntimeActivityItemForConversation, redactRuntimeDescriptorForConversation, redactRuntimeInfoForConversation, redactSessionStateForConversation, } from './runtime-presentation.js';
3
4
  export { buildRuntimeProvenance, resolveRuntimeProvenance, } from './provenance.js';
4
5
  export { buildSelfContextPromptLines, normalizeSelfContexts, resolveMessageActiveSelfContextId, selectActiveSelfContexts, } from './self-context.js';
5
6
  export { buildConfiguredWorkspaceOptionsWithRoots, buildPublicWorkspaceRoots, buildWorkspaceRootId, discoverWorkspaceProjects, } from './workspace-discovery.js';
@@ -18,7 +19,7 @@ export { ackRegistrationApproval, registerAndWaitForApproval, submitRegistration
18
19
  export { ApprovalManager } from './approval-manager.js';
19
20
  export { generateApprovalId, buildApprovalRequest, buildApprovalReply, buildApprovalOutcome, parseTextApprovalReply, redactSecrets, } from './approval-format.js';
20
21
  export { DEFAULT_APPROVAL_CONFIG, parseApprovalRequestMetadata, parseApprovalReplyMetadata, parseSessionRule, } from './approval-types.js';
21
- export { buildPlanApprovalReply, buildPlanApprovalRequest, buildQuestionReply, buildQuestionRequest, } from './runtime-cards.js';
22
+ export { buildRuntimeInputOutcome, buildRuntimeInputReply, buildRuntimeInputRequest, buildPlanApprovalReply, buildPlanApprovalRequest, buildQuestionReply, buildQuestionRequest, parseRuntimeInputOutcomeMetadata, parseRuntimeInputReplyMetadata, parseRuntimeInputRequestMetadata, } from './runtime-cards.js';
22
23
  // Streaming (RTDB helpers)
23
24
  export { createStreamingHelper } from './streaming.js';
24
25
  // Agent profiles (loading, locking, resolution)
@@ -10,6 +10,7 @@ export interface LocalRuntimeSessionState {
10
10
  codexPolicyFingerprint?: string;
11
11
  threadId?: string;
12
12
  claudeSessionId?: string;
13
+ hermesSessionId?: string;
13
14
  lastInboundMessageId?: string;
14
15
  updatedAt: string;
15
16
  }
package/dist/rtdb-rest.js CHANGED
@@ -208,8 +208,8 @@ function createRTDBClientHandle(client, options) {
208
208
  ...(state.capabilities?.supportsQueue !== undefined
209
209
  ? { supportsQueue: state.capabilities.supportsQueue }
210
210
  : {}),
211
- ...(state.capabilities?.supportsInterrupt !== undefined
212
- ? { supportsInputInterrupt: state.capabilities.supportsInterrupt }
211
+ ...(state.capabilities?.supportsInputInterrupt !== undefined
212
+ ? { supportsInputInterrupt: state.capabilities.supportsInputInterrupt }
213
213
  : {}),
214
214
  queueDepth: state.queueDepth,
215
215
  waitingForInput: state.state === 'waiting_input',
@@ -35,6 +35,49 @@ export interface PlanApprovalReplyMetadata {
35
35
  decision: 'approve' | 'revise';
36
36
  feedback?: string;
37
37
  }
38
+ export type RuntimeInputKind = 'clarify' | 'sudo' | 'secret';
39
+ export type RuntimeInputReplyStatus = 'submitted' | 'cancelled';
40
+ export type RuntimeInputResolutionStatus = RuntimeInputReplyStatus | 'timeout';
41
+ export interface RuntimeInputChoice {
42
+ label: string;
43
+ value?: string;
44
+ description?: string;
45
+ }
46
+ export interface RuntimeInputNativeMetadata {
47
+ runtime?: string;
48
+ method?: string;
49
+ requestId?: string;
50
+ sessionKey?: string;
51
+ turnId?: string;
52
+ handles?: Record<string, string>;
53
+ }
54
+ export interface RuntimeInputRequestMetadata {
55
+ type: 'runtime_input_request';
56
+ inputId: string;
57
+ kind: RuntimeInputKind;
58
+ prompt: string;
59
+ title?: string;
60
+ choices?: RuntimeInputChoice[];
61
+ secretName?: string;
62
+ native?: RuntimeInputNativeMetadata;
63
+ expiresAt: string;
64
+ sensitive?: boolean;
65
+ }
66
+ export interface RuntimeInputReplyMetadata {
67
+ type: 'runtime_input_reply';
68
+ inputId: string;
69
+ kind?: RuntimeInputKind;
70
+ status: RuntimeInputReplyStatus;
71
+ answerSummary?: string;
72
+ sensitive?: boolean;
73
+ }
74
+ export interface RuntimeInputOutcomeMetadata {
75
+ type: 'runtime_input_outcome';
76
+ inputId: string;
77
+ kind?: RuntimeInputKind;
78
+ status: RuntimeInputResolutionStatus;
79
+ reason?: 'submitted' | 'cancelled' | 'timeout' | 'expired' | 'interrupted';
80
+ }
38
81
  export declare function buildQuestionRequest(questionId: string, questions: RuntimeQuestionDefinition[]): {
39
82
  text: string;
40
83
  metadata: ClaudeQuestionMetadata;
@@ -51,3 +94,25 @@ export declare function buildPlanApprovalReply(planId: string, decision: 'approv
51
94
  text: string;
52
95
  metadata: PlanApprovalReplyMetadata;
53
96
  };
97
+ export declare function buildRuntimeInputRequest(inputId: string, input: Omit<RuntimeInputRequestMetadata, 'type' | 'inputId'>): {
98
+ text: string;
99
+ metadata: RuntimeInputRequestMetadata;
100
+ };
101
+ export declare function buildRuntimeInputReply(inputId: string, status: RuntimeInputReplyStatus, details?: {
102
+ kind?: RuntimeInputKind;
103
+ answerSummary?: string;
104
+ sensitive?: boolean;
105
+ }): {
106
+ text: string;
107
+ metadata: RuntimeInputReplyMetadata;
108
+ };
109
+ export declare function buildRuntimeInputOutcome(inputId: string, status: RuntimeInputResolutionStatus, details?: {
110
+ kind?: RuntimeInputKind;
111
+ reason?: RuntimeInputOutcomeMetadata['reason'];
112
+ }): {
113
+ text: string;
114
+ metadata: RuntimeInputOutcomeMetadata;
115
+ };
116
+ export declare function parseRuntimeInputRequestMetadata(value: unknown): RuntimeInputRequestMetadata | null;
117
+ export declare function parseRuntimeInputReplyMetadata(value: unknown): RuntimeInputReplyMetadata | null;
118
+ export declare function parseRuntimeInputOutcomeMetadata(value: unknown): RuntimeInputOutcomeMetadata | null;
@@ -1,3 +1,73 @@
1
+ function isRecord(value) {
2
+ return Boolean(value && typeof value === 'object' && !Array.isArray(value));
3
+ }
4
+ function normalizeString(value, maxLength) {
5
+ if (typeof value !== 'string')
6
+ return null;
7
+ const trimmed = value.trim();
8
+ if (!trimmed || trimmed.length > maxLength)
9
+ return null;
10
+ return trimmed;
11
+ }
12
+ function normalizeRuntimeInputKind(value) {
13
+ return value === 'clarify' || value === 'sudo' || value === 'secret' ? value : null;
14
+ }
15
+ function normalizeRuntimeInputReplyStatus(value) {
16
+ return value === 'submitted' || value === 'cancelled' ? value : null;
17
+ }
18
+ function normalizeRuntimeInputResolutionStatus(value) {
19
+ return value === 'submitted' || value === 'cancelled' || value === 'timeout' ? value : null;
20
+ }
21
+ function normalizeRuntimeInputChoices(value) {
22
+ if (!Array.isArray(value))
23
+ return undefined;
24
+ const choices = value.slice(0, 12).flatMap((entry) => {
25
+ if (!isRecord(entry))
26
+ return [];
27
+ const label = normalizeString(entry.label, 120);
28
+ if (!label)
29
+ return [];
30
+ const choice = { label };
31
+ const choiceValue = normalizeString(entry.value, 200);
32
+ const description = normalizeString(entry.description, 300);
33
+ if (choiceValue)
34
+ choice.value = choiceValue;
35
+ if (description)
36
+ choice.description = description;
37
+ return [choice];
38
+ });
39
+ return choices.length > 0 ? choices : undefined;
40
+ }
41
+ function normalizeRuntimeInputNative(value) {
42
+ if (!isRecord(value))
43
+ return undefined;
44
+ const native = {};
45
+ for (const key of ['runtime', 'method', 'requestId', 'sessionKey', 'turnId']) {
46
+ const normalized = normalizeString(value[key], 256);
47
+ if (normalized)
48
+ native[key] = normalized;
49
+ }
50
+ if (isRecord(value.handles)) {
51
+ const handles = {};
52
+ for (const [key, raw] of Object.entries(value.handles).slice(0, 16)) {
53
+ if (!/^[a-zA-Z0-9_.:-]{1,80}$/.test(key))
54
+ continue;
55
+ const normalized = normalizeString(raw, 256);
56
+ if (normalized)
57
+ handles[key] = normalized;
58
+ }
59
+ if (Object.keys(handles).length > 0)
60
+ native.handles = handles;
61
+ }
62
+ return Object.keys(native).length > 0 ? native : undefined;
63
+ }
64
+ function assertNoSensitiveRuntimeInputPayload(value) {
65
+ return !('value' in value)
66
+ && !('answer' in value)
67
+ && !('password' in value)
68
+ && !('secret' in value)
69
+ && !('rawValue' in value);
70
+ }
1
71
  export function buildQuestionRequest(questionId, questions) {
2
72
  const text = questions.length === 1
3
73
  ? questions[0]?.question || 'Question'
@@ -43,3 +113,131 @@ export function buildPlanApprovalReply(planId, decision, feedback) {
43
113
  },
44
114
  };
45
115
  }
116
+ export function buildRuntimeInputRequest(inputId, input) {
117
+ const title = input.title?.trim() || (input.kind === 'sudo'
118
+ ? 'Sudo password required'
119
+ : input.kind === 'secret'
120
+ ? 'Secret required'
121
+ : 'Input required');
122
+ return {
123
+ text: title,
124
+ metadata: {
125
+ type: 'runtime_input_request',
126
+ inputId,
127
+ kind: input.kind,
128
+ prompt: input.prompt.slice(0, 1000),
129
+ title: title.slice(0, 120),
130
+ ...(input.choices?.length ? { choices: input.choices.slice(0, 12) } : {}),
131
+ ...(input.secretName ? { secretName: input.secretName.slice(0, 120) } : {}),
132
+ ...(input.native ? { native: input.native } : {}),
133
+ expiresAt: input.expiresAt,
134
+ ...(input.sensitive ? { sensitive: true } : {}),
135
+ },
136
+ };
137
+ }
138
+ export function buildRuntimeInputReply(inputId, status, details) {
139
+ const answerSummary = details?.sensitive ? undefined : details?.answerSummary?.trim().slice(0, 500);
140
+ return {
141
+ text: status === 'submitted' ? 'Submitted' : 'Cancelled',
142
+ metadata: {
143
+ type: 'runtime_input_reply',
144
+ inputId,
145
+ ...(details?.kind ? { kind: details.kind } : {}),
146
+ status,
147
+ ...(answerSummary ? { answerSummary } : {}),
148
+ ...(details?.sensitive ? { sensitive: true } : {}),
149
+ },
150
+ };
151
+ }
152
+ export function buildRuntimeInputOutcome(inputId, status, details) {
153
+ return {
154
+ text: status === 'timeout'
155
+ ? 'Input request expired'
156
+ : status === 'cancelled'
157
+ ? 'Input request cancelled'
158
+ : 'Input request resolved',
159
+ metadata: {
160
+ type: 'runtime_input_outcome',
161
+ inputId,
162
+ ...(details?.kind ? { kind: details.kind } : {}),
163
+ status,
164
+ ...(details?.reason ? { reason: details.reason } : {}),
165
+ },
166
+ };
167
+ }
168
+ export function parseRuntimeInputRequestMetadata(value) {
169
+ if (!isRecord(value) || value.type !== 'runtime_input_request')
170
+ return null;
171
+ if (!assertNoSensitiveRuntimeInputPayload(value))
172
+ return null;
173
+ const inputId = normalizeString(value.inputId, 128);
174
+ const kind = normalizeRuntimeInputKind(value.kind);
175
+ const prompt = normalizeString(value.prompt, 1000);
176
+ const expiresAt = normalizeString(value.expiresAt, 128);
177
+ if (!inputId || !kind || !prompt || !expiresAt)
178
+ return null;
179
+ const expiresMs = Date.parse(expiresAt);
180
+ if (!Number.isFinite(expiresMs))
181
+ return null;
182
+ const title = normalizeString(value.title, 120) ?? undefined;
183
+ const choices = normalizeRuntimeInputChoices(value.choices);
184
+ const secretName = normalizeString(value.secretName, 120) ?? undefined;
185
+ const native = normalizeRuntimeInputNative(value.native);
186
+ return {
187
+ type: 'runtime_input_request',
188
+ inputId,
189
+ kind,
190
+ prompt,
191
+ ...(title ? { title } : {}),
192
+ ...(choices ? { choices } : {}),
193
+ ...(secretName ? { secretName } : {}),
194
+ ...(native ? { native } : {}),
195
+ expiresAt: new Date(expiresMs).toISOString(),
196
+ ...(value.sensitive === true ? { sensitive: true } : {}),
197
+ };
198
+ }
199
+ export function parseRuntimeInputReplyMetadata(value) {
200
+ if (!isRecord(value) || value.type !== 'runtime_input_reply')
201
+ return null;
202
+ if (!assertNoSensitiveRuntimeInputPayload(value))
203
+ return null;
204
+ const inputId = normalizeString(value.inputId, 128);
205
+ const status = normalizeRuntimeInputReplyStatus(value.status);
206
+ if (!inputId || !status)
207
+ return null;
208
+ const kind = normalizeRuntimeInputKind(value.kind) ?? undefined;
209
+ const answerSummary = value.sensitive === true ? undefined : normalizeString(value.answerSummary, 500) ?? undefined;
210
+ return {
211
+ type: 'runtime_input_reply',
212
+ inputId,
213
+ ...(kind ? { kind } : {}),
214
+ status,
215
+ ...(answerSummary ? { answerSummary } : {}),
216
+ ...(value.sensitive === true ? { sensitive: true } : {}),
217
+ };
218
+ }
219
+ export function parseRuntimeInputOutcomeMetadata(value) {
220
+ if (!isRecord(value) || value.type !== 'runtime_input_outcome')
221
+ return null;
222
+ if (!assertNoSensitiveRuntimeInputPayload(value))
223
+ return null;
224
+ const inputId = normalizeString(value.inputId, 128);
225
+ const status = normalizeRuntimeInputResolutionStatus(value.status);
226
+ if (!inputId || !status)
227
+ return null;
228
+ const kind = normalizeRuntimeInputKind(value.kind) ?? undefined;
229
+ const reason = value.reason === 'submitted'
230
+ || value.reason === 'cancelled'
231
+ || value.reason === 'timeout'
232
+ || value.reason === 'expired'
233
+ || value.reason === 'interrupted'
234
+ ? value.reason
235
+ : undefined;
236
+ return {
237
+ type: 'runtime_input_outcome',
238
+ inputId,
239
+ ...(kind ? { kind } : {}),
240
+ status,
241
+ ...(reason ? { reason } : {}),
242
+ };
243
+ }
@@ -1,5 +1,6 @@
1
1
  import type { ExecutionEnvironmentMode } from './execution-environment-mode.js';
2
2
  import { type AgentClientType, type CanonControlDescriptor, type CanonRuntimeActionDescriptor, type CanonRuntimeCommandDescriptor, type CanonRuntimeDescriptor, type CanonRuntimeStreamingMode, type CanonWorkspaceRootMetadata, type ModelOption, type PermissionModeOption, type WorkspaceOption } from './types.js';
3
+ import type { CanonRuntimePresentationPolicy } from './types.js';
3
4
  import type { HostAdmissionActionCapabilities } from './turn-protocol.js';
4
5
  export declare const CLAUDE_EFFORT_OPTIONS: readonly [{
5
6
  readonly value: "low";
@@ -51,4 +52,5 @@ export declare function buildFirstPartyCodingRuntimeDescriptor(input: {
51
52
  commands?: ReadonlyArray<CanonRuntimeCommandDescriptor>;
52
53
  streamingTextMode: CanonRuntimeStreamingMode;
53
54
  admissionActions?: HostAdmissionActionCapabilities;
55
+ presentation?: CanonRuntimePresentationPolicy;
54
56
  }): CanonRuntimeDescriptor;
@@ -1,4 +1,5 @@
1
1
  import { CLAUDE_PERMISSION_MODE_OPTIONS, } from './types.js';
2
+ import { DEFAULT_FIRST_PARTY_RUNTIME_PRESENTATION } from './runtime-presentation.js';
2
3
  export const CLAUDE_EFFORT_OPTIONS = [
3
4
  { value: 'low', label: 'Low' },
4
5
  { value: 'medium', label: 'Medium' },
@@ -155,6 +156,7 @@ export function buildFirstPartyCodingRuntimeDescriptor(input) {
155
156
  supportsInterrupt: true,
156
157
  supportsInputInterrupt: true,
157
158
  streamingTextMode: input.streamingTextMode,
159
+ presentation: input.presentation ?? DEFAULT_FIRST_PARTY_RUNTIME_PRESENTATION,
158
160
  admissionActions: input.admissionActions,
159
161
  };
160
162
  }
@@ -0,0 +1,38 @@
1
+ import type { AgentRuntime, AgentSessionSnapshot, CanonRuntimeActivityItem, CanonRuntimeDescriptor, CanonRuntimeExecutionMetadata, CanonRuntimePresentationField, CanonRuntimePresentationPolicy, RuntimeInfoPayload } from './types.js';
2
+ export declare const RUNTIME_PRESENTATION_FIELDS: readonly ["model", "permissionMode", "effort", "workspace", "executionMode", "contextUsage", "cwd", "branch", "worktreePath", "workspaceRoot", "workspaceRelativePath", "fallbackReason"];
3
+ export declare const DEFAULT_FIRST_PARTY_RUNTIME_PRESENTATION: CanonRuntimePresentationPolicy;
4
+ export declare function isRuntimePresentationField(value: string): value is CanonRuntimePresentationField;
5
+ export declare function buildRuntimePresentationPolicy(input?: {
6
+ preset?: CanonRuntimePresentationPolicy['preset'];
7
+ show?: ReadonlyArray<string>;
8
+ hide?: ReadonlyArray<string>;
9
+ base?: CanonRuntimePresentationPolicy;
10
+ }): CanonRuntimePresentationPolicy;
11
+ export declare function getRuntimePresentationHint(descriptor: CanonRuntimeDescriptor | null | undefined, field: CanonRuntimePresentationField): import("./types.js").CanonRuntimePresentationHint | null;
12
+ export declare function isRuntimePresentationFieldHidden(descriptor: CanonRuntimeDescriptor | null | undefined, field: CanonRuntimePresentationField): boolean;
13
+ export declare function redactRuntimeDescriptorForConversation(descriptor: CanonRuntimeDescriptor): CanonRuntimeDescriptor;
14
+ export declare function redactRuntimeActivityItemForConversation(item: CanonRuntimeActivityItem): CanonRuntimeActivityItem | null;
15
+ export declare function redactExecutionMetadataForConversation(descriptor: CanonRuntimeDescriptor | null | undefined, execution: CanonRuntimeExecutionMetadata | null | undefined): CanonRuntimeExecutionMetadata | null;
16
+ export declare function redactRuntimeInfoForConversation<T extends Partial<Omit<RuntimeInfoPayload, 'updatedAt'>> | RuntimeInfoPayload>(payload: T, options?: {
17
+ descriptor?: CanonRuntimeDescriptor | null;
18
+ }): T;
19
+ export declare function redactAgentRuntimeForConversation(runtime: AgentRuntime): AgentRuntime;
20
+ type SessionStatePresentationLike = {
21
+ model?: unknown;
22
+ permissionMode?: unknown;
23
+ effort?: unknown;
24
+ cwd?: unknown;
25
+ executionMode?: unknown;
26
+ executionBranch?: unknown;
27
+ worktreePath?: unknown;
28
+ executionFallbackReason?: unknown;
29
+ contextUsage?: unknown;
30
+ availableModels?: unknown;
31
+ runtimeControlValues?: Record<string, unknown>;
32
+ controlState?: Record<string, unknown>;
33
+ };
34
+ export declare function redactSessionStateForConversation<T extends SessionStatePresentationLike>(descriptor: CanonRuntimeDescriptor | null | undefined, state: T): T;
35
+ export declare function redactAgentSessionSnapshotForConversation(descriptor: CanonRuntimeDescriptor | null | undefined, snapshot: Partial<AgentSessionSnapshot> & Record<string, unknown>, options?: {
36
+ patch?: boolean;
37
+ }): Partial<AgentSessionSnapshot> & Record<string, unknown>;
38
+ export {};
@@ -0,0 +1,441 @@
1
+ const MINIMAL_HIDDEN_FIELDS = new Set([
2
+ 'model',
3
+ 'permissionMode',
4
+ 'effort',
5
+ 'workspace',
6
+ 'contextUsage',
7
+ 'cwd',
8
+ 'branch',
9
+ 'worktreePath',
10
+ 'workspaceRoot',
11
+ 'workspaceRelativePath',
12
+ 'fallbackReason',
13
+ ]);
14
+ export const RUNTIME_PRESENTATION_FIELDS = [
15
+ 'model',
16
+ 'permissionMode',
17
+ 'effort',
18
+ 'workspace',
19
+ 'executionMode',
20
+ 'contextUsage',
21
+ 'cwd',
22
+ 'branch',
23
+ 'worktreePath',
24
+ 'workspaceRoot',
25
+ 'workspaceRelativePath',
26
+ 'fallbackReason',
27
+ ];
28
+ export const DEFAULT_FIRST_PARTY_RUNTIME_PRESENTATION = {
29
+ preset: 'normal',
30
+ fields: {
31
+ cwd: { visibility: 'hidden' },
32
+ worktreePath: { visibility: 'hidden' },
33
+ workspaceRoot: { visibility: 'hidden' },
34
+ },
35
+ };
36
+ export function isRuntimePresentationField(value) {
37
+ return RUNTIME_PRESENTATION_FIELDS.includes(value);
38
+ }
39
+ export function buildRuntimePresentationPolicy(input = {}) {
40
+ const preset = input.preset ?? input.base?.preset ?? 'normal';
41
+ const fields = {
42
+ ...(preset === 'full' ? {} : input.base?.fields ?? {}),
43
+ };
44
+ for (const field of input.show ?? []) {
45
+ if (!isRuntimePresentationField(field))
46
+ continue;
47
+ fields[field] = {
48
+ ...(fields[field] ?? {}),
49
+ visibility: 'conversation',
50
+ };
51
+ }
52
+ for (const field of input.hide ?? []) {
53
+ if (!isRuntimePresentationField(field))
54
+ continue;
55
+ fields[field] = {
56
+ ...(fields[field] ?? {}),
57
+ visibility: 'hidden',
58
+ };
59
+ }
60
+ return {
61
+ preset,
62
+ fields,
63
+ };
64
+ }
65
+ function hasOwn(value, key) {
66
+ return Object.prototype.hasOwnProperty.call(value, key);
67
+ }
68
+ function cloneDefined(value) {
69
+ return Object.fromEntries(Object.entries(value).filter(([, entryValue]) => entryValue !== undefined));
70
+ }
71
+ export function getRuntimePresentationHint(descriptor, field) {
72
+ return descriptor?.presentation?.fields?.[field] ?? null;
73
+ }
74
+ export function isRuntimePresentationFieldHidden(descriptor, field) {
75
+ const policy = descriptor?.presentation;
76
+ const hint = policy?.fields?.[field];
77
+ if (hint?.visibility === 'conversation')
78
+ return false;
79
+ if (hint?.visibility === 'hidden')
80
+ return true;
81
+ return policy?.preset === 'minimal' && MINIMAL_HIDDEN_FIELDS.has(field);
82
+ }
83
+ function isRuntimeItemHidden(item) {
84
+ return item?.visibility === 'hidden';
85
+ }
86
+ function isRequiredSetupControl(control) {
87
+ return control.selectionPolicy === 'required_explicit'
88
+ && (control.availability === 'setup' || control.availability === 'setup_and_live');
89
+ }
90
+ function shouldHideControlValue(descriptor, control) {
91
+ if (isRuntimeItemHidden(control) || control.sensitive)
92
+ return true;
93
+ const field = control.id;
94
+ const hidden = isRuntimePresentationFieldHidden(descriptor, field);
95
+ return hidden && !isRequiredSetupControl(control);
96
+ }
97
+ function hiddenControlValueIds(descriptor) {
98
+ const controls = [
99
+ ...(descriptor?.coreControls ?? []),
100
+ ...(descriptor?.runtimeControls ?? []),
101
+ ];
102
+ return new Set(controls
103
+ .filter((control) => shouldHideControlValue(descriptor, control))
104
+ .map((control) => control.id));
105
+ }
106
+ function redactControlValueMap(descriptor, values, options = {}) {
107
+ if (!values)
108
+ return values;
109
+ const hiddenIds = hiddenControlValueIds(descriptor);
110
+ if (hiddenIds.size === 0)
111
+ return values;
112
+ const redacted = { ...values };
113
+ for (const id of hiddenIds) {
114
+ if (!hasOwn(redacted, id))
115
+ continue;
116
+ if (options.patch) {
117
+ redacted[id] = null;
118
+ }
119
+ else {
120
+ delete redacted[id];
121
+ }
122
+ }
123
+ return redacted;
124
+ }
125
+ function redactSensitiveValue(value) {
126
+ void value;
127
+ return 'Hidden';
128
+ }
129
+ function redactControl(descriptor, control) {
130
+ if (isRuntimeItemHidden(control))
131
+ return null;
132
+ const field = control.id;
133
+ const hidden = isRuntimePresentationFieldHidden(descriptor, field);
134
+ if (hidden && !isRequiredSetupControl(control))
135
+ return null;
136
+ if (!control.sensitive)
137
+ return control;
138
+ return cloneDefined({
139
+ ...control,
140
+ defaultValue: null,
141
+ options: control.options?.map((option) => ({
142
+ value: option.value,
143
+ label: redactSensitiveValue(option.label),
144
+ })),
145
+ });
146
+ }
147
+ function redactAction(action) {
148
+ if (isRuntimeItemHidden(action))
149
+ return null;
150
+ if (!action.sensitive)
151
+ return action;
152
+ return cloneDefined({
153
+ ...action,
154
+ description: action.description ? redactSensitiveValue(action.description) : undefined,
155
+ });
156
+ }
157
+ function redactWorkspaceOption(descriptor, option) {
158
+ const hideRoot = isRuntimePresentationFieldHidden(descriptor, 'workspaceRoot');
159
+ const hideRelative = isRuntimePresentationFieldHidden(descriptor, 'workspaceRelativePath');
160
+ return cloneDefined({
161
+ ...option,
162
+ ...(hideRoot ? { workspaceRootId: undefined } : {}),
163
+ ...(hideRelative ? { workspaceRelativePath: undefined } : {}),
164
+ });
165
+ }
166
+ export function redactRuntimeDescriptorForConversation(descriptor) {
167
+ const coreControls = (descriptor.coreControls ?? [])
168
+ .map((control) => redactControl(descriptor, control))
169
+ .filter((control) => Boolean(control))
170
+ .map((control) => control.id === 'workspace'
171
+ ? {
172
+ ...control,
173
+ options: control.options?.map((option) => redactWorkspaceOption(descriptor, option)),
174
+ }
175
+ : control);
176
+ const runtimeControls = descriptor.runtimeControls?.map((control) => redactControl(descriptor, control))
177
+ .filter((control) => Boolean(control));
178
+ const commands = descriptor.commands?.map((command) => redactAction(command))
179
+ .filter((command) => Boolean(command));
180
+ const actions = descriptor.actions?.map((action) => redactAction(action))
181
+ .filter((action) => Boolean(action));
182
+ return cloneDefined({
183
+ ...descriptor,
184
+ coreControls,
185
+ runtimeControls,
186
+ commands,
187
+ actions,
188
+ workspaceRoots: isRuntimePresentationFieldHidden(descriptor, 'workspaceRoot')
189
+ ? []
190
+ : descriptor.workspaceRoots,
191
+ writableRoots: isRuntimePresentationFieldHidden(descriptor, 'workspaceRoot')
192
+ ? []
193
+ : descriptor.writableRoots,
194
+ });
195
+ }
196
+ function redactStatusItem(item) {
197
+ if (isRuntimeItemHidden(item))
198
+ return null;
199
+ if (!item.sensitive)
200
+ return item;
201
+ return {
202
+ ...item,
203
+ value: redactSensitiveValue(item.value),
204
+ tone: item.tone ?? 'warning',
205
+ };
206
+ }
207
+ function redactFact(item) {
208
+ if (isRuntimeItemHidden(item))
209
+ return null;
210
+ if (!item.sensitive)
211
+ return item;
212
+ return {
213
+ ...item,
214
+ value: redactSensitiveValue(item.value),
215
+ tone: item.tone ?? 'warning',
216
+ copyable: false,
217
+ };
218
+ }
219
+ function redactInventoryEntry(entry) {
220
+ if (isRuntimeItemHidden(entry))
221
+ return null;
222
+ if (!entry.sensitive)
223
+ return entry;
224
+ return cloneDefined({
225
+ ...entry,
226
+ label: redactSensitiveValue(entry.label),
227
+ description: entry.description ? redactSensitiveValue(entry.description) : undefined,
228
+ });
229
+ }
230
+ function redactInventory(inventory) {
231
+ if (isRuntimeItemHidden(inventory))
232
+ return null;
233
+ const entries = (inventory.entries ?? [])
234
+ .map(redactInventoryEntry)
235
+ .filter((entry) => Boolean(entry));
236
+ if (!inventory.sensitive) {
237
+ return {
238
+ ...inventory,
239
+ entries,
240
+ };
241
+ }
242
+ return {
243
+ ...inventory,
244
+ entries: [],
245
+ label: redactSensitiveValue(inventory.label),
246
+ };
247
+ }
248
+ export function redactRuntimeActivityItemForConversation(item) {
249
+ if (isRuntimeItemHidden(item))
250
+ return null;
251
+ const actions = item.actions
252
+ ?.map((action) => redactAction(action))
253
+ .filter((action) => Boolean(action));
254
+ if (!item.sensitive) {
255
+ return cloneDefined({
256
+ ...item,
257
+ actions,
258
+ });
259
+ }
260
+ return cloneDefined({
261
+ ...item,
262
+ title: redactSensitiveValue(item.title),
263
+ summary: item.summary ? redactSensitiveValue(item.summary) : undefined,
264
+ detail: item.detail ? redactSensitiveValue(item.detail) : undefined,
265
+ progressText: item.progressText ? redactSensitiveValue(item.progressText) : undefined,
266
+ actions,
267
+ });
268
+ }
269
+ export function redactExecutionMetadataForConversation(descriptor, execution) {
270
+ if (!execution)
271
+ return null;
272
+ const redacted = cloneDefined({
273
+ ...execution,
274
+ resolvedWorkspaceLabel: isRuntimePresentationFieldHidden(descriptor, 'workspace')
275
+ ? undefined
276
+ : execution.resolvedWorkspaceLabel,
277
+ resolvedCwd: isRuntimePresentationFieldHidden(descriptor, 'cwd')
278
+ ? undefined
279
+ : execution.resolvedCwd,
280
+ workspaceRootId: isRuntimePresentationFieldHidden(descriptor, 'workspaceRoot')
281
+ ? undefined
282
+ : execution.workspaceRootId,
283
+ workspaceRelativePath: isRuntimePresentationFieldHidden(descriptor, 'workspaceRelativePath')
284
+ ? undefined
285
+ : execution.workspaceRelativePath,
286
+ executionMode: isRuntimePresentationFieldHidden(descriptor, 'executionMode')
287
+ ? undefined
288
+ : execution.executionMode,
289
+ executionBranch: isRuntimePresentationFieldHidden(descriptor, 'branch')
290
+ ? undefined
291
+ : execution.executionBranch,
292
+ worktreePath: isRuntimePresentationFieldHidden(descriptor, 'worktreePath')
293
+ ? undefined
294
+ : execution.worktreePath,
295
+ fallbackReason: isRuntimePresentationFieldHidden(descriptor, 'fallbackReason')
296
+ ? undefined
297
+ : execution.fallbackReason,
298
+ });
299
+ return Object.keys(redacted).length > 0 ? redacted : null;
300
+ }
301
+ export function redactRuntimeInfoForConversation(payload, options = {}) {
302
+ const descriptor = payload.descriptor
303
+ ? redactRuntimeDescriptorForConversation(payload.descriptor)
304
+ : payload.descriptor;
305
+ const policyDescriptor = options.descriptor ?? payload.descriptor ?? descriptor;
306
+ return cloneDefined({
307
+ ...payload,
308
+ descriptor,
309
+ facts: payload.facts
310
+ ?.map(redactFact)
311
+ .filter((fact) => Boolean(fact)),
312
+ statusItems: payload.statusItems
313
+ ?.map(redactStatusItem)
314
+ .filter((item) => Boolean(item)),
315
+ inventories: payload.inventories
316
+ ?.map(redactInventory)
317
+ .filter((inventory) => Boolean(inventory)),
318
+ ...(hasOwn(payload, 'execution')
319
+ ? { execution: redactExecutionMetadataForConversation(policyDescriptor, payload.execution) }
320
+ : {}),
321
+ });
322
+ }
323
+ export function redactAgentRuntimeForConversation(runtime) {
324
+ const descriptor = runtime.runtimeDescriptor;
325
+ const redactedDescriptor = descriptor
326
+ ? redactRuntimeDescriptorForConversation(descriptor)
327
+ : descriptor;
328
+ return cloneDefined({
329
+ ...runtime,
330
+ runtimeDescriptor: redactedDescriptor,
331
+ defaultModel: isRuntimePresentationFieldHidden(descriptor, 'model')
332
+ ? undefined
333
+ : runtime.defaultModel,
334
+ availableModels: isRuntimePresentationFieldHidden(descriptor, 'model')
335
+ ? undefined
336
+ : runtime.availableModels,
337
+ defaultPermissionMode: isRuntimePresentationFieldHidden(descriptor, 'permissionMode')
338
+ ? undefined
339
+ : runtime.defaultPermissionMode,
340
+ availablePermissionModes: isRuntimePresentationFieldHidden(descriptor, 'permissionMode')
341
+ ? undefined
342
+ : runtime.availablePermissionModes,
343
+ defaultWorkspaceId: isRuntimePresentationFieldHidden(descriptor, 'workspace')
344
+ ? undefined
345
+ : runtime.defaultWorkspaceId,
346
+ availableWorkspaces: isRuntimePresentationFieldHidden(descriptor, 'workspace')
347
+ ? undefined
348
+ : runtime.availableWorkspaces,
349
+ defaultExecutionMode: isRuntimePresentationFieldHidden(descriptor, 'executionMode')
350
+ ? undefined
351
+ : runtime.defaultExecutionMode,
352
+ availableExecutionModes: isRuntimePresentationFieldHidden(descriptor, 'executionMode')
353
+ ? undefined
354
+ : runtime.availableExecutionModes,
355
+ });
356
+ }
357
+ export function redactSessionStateForConversation(descriptor, state) {
358
+ return cloneDefined({
359
+ ...state,
360
+ model: isRuntimePresentationFieldHidden(descriptor, 'model') ? undefined : state.model,
361
+ permissionMode: isRuntimePresentationFieldHidden(descriptor, 'permissionMode')
362
+ ? undefined
363
+ : state.permissionMode,
364
+ effort: isRuntimePresentationFieldHidden(descriptor, 'effort') ? undefined : state.effort,
365
+ cwd: isRuntimePresentationFieldHidden(descriptor, 'cwd') ? undefined : state.cwd,
366
+ executionMode: isRuntimePresentationFieldHidden(descriptor, 'executionMode')
367
+ ? undefined
368
+ : state.executionMode,
369
+ executionBranch: isRuntimePresentationFieldHidden(descriptor, 'branch')
370
+ ? undefined
371
+ : state.executionBranch,
372
+ worktreePath: isRuntimePresentationFieldHidden(descriptor, 'worktreePath')
373
+ ? undefined
374
+ : state.worktreePath,
375
+ executionFallbackReason: isRuntimePresentationFieldHidden(descriptor, 'fallbackReason')
376
+ ? undefined
377
+ : state.executionFallbackReason,
378
+ contextUsage: isRuntimePresentationFieldHidden(descriptor, 'contextUsage')
379
+ ? undefined
380
+ : state.contextUsage,
381
+ availableModels: isRuntimePresentationFieldHidden(descriptor, 'model')
382
+ ? undefined
383
+ : state.availableModels,
384
+ runtimeControlValues: redactControlValueMap(descriptor, state.runtimeControlValues),
385
+ controlState: redactControlValueMap(descriptor, state.controlState),
386
+ });
387
+ }
388
+ export function redactAgentSessionSnapshotForConversation(descriptor, snapshot, options = {}) {
389
+ const hiddenValue = options.patch ? null : undefined;
390
+ const redacted = {
391
+ ...snapshot,
392
+ model: isRuntimePresentationFieldHidden(descriptor, 'model') ? hiddenValue : snapshot.model,
393
+ modelOptions: isRuntimePresentationFieldHidden(descriptor, 'model') ? hiddenValue : snapshot.modelOptions,
394
+ permissionMode: isRuntimePresentationFieldHidden(descriptor, 'permissionMode') ? hiddenValue : snapshot.permissionMode,
395
+ permissionModeOptions: isRuntimePresentationFieldHidden(descriptor, 'permissionMode') ? hiddenValue : snapshot.permissionModeOptions,
396
+ effort: isRuntimePresentationFieldHidden(descriptor, 'effort') ? hiddenValue : snapshot.effort,
397
+ workspaceId: isRuntimePresentationFieldHidden(descriptor, 'workspace') ? hiddenValue : snapshot.workspaceId,
398
+ workspaceOptions: isRuntimePresentationFieldHidden(descriptor, 'workspace') ? hiddenValue : snapshot.workspaceOptions,
399
+ executionMode: isRuntimePresentationFieldHidden(descriptor, 'executionMode') ? hiddenValue : snapshot.executionMode,
400
+ availableExecutionModes: isRuntimePresentationFieldHidden(descriptor, 'executionMode') ? hiddenValue : snapshot.availableExecutionModes,
401
+ executionBranch: isRuntimePresentationFieldHidden(descriptor, 'branch') ? hiddenValue : snapshot.executionBranch,
402
+ resolvedWorkspaceLabel: isRuntimePresentationFieldHidden(descriptor, 'workspace') ? hiddenValue : snapshot.resolvedWorkspaceLabel,
403
+ resolvedCwd: isRuntimePresentationFieldHidden(descriptor, 'cwd') ? hiddenValue : snapshot.resolvedCwd,
404
+ worktreePath: isRuntimePresentationFieldHidden(descriptor, 'worktreePath') ? hiddenValue : snapshot.worktreePath,
405
+ executionFallbackReason: isRuntimePresentationFieldHidden(descriptor, 'fallbackReason') ? hiddenValue : snapshot.executionFallbackReason,
406
+ contextUsage: isRuntimePresentationFieldHidden(descriptor, 'contextUsage') ? hiddenValue : snapshot.contextUsage,
407
+ runtimeControlValues: redactControlValueMap(descriptor, snapshot.runtimeControlValues, options),
408
+ };
409
+ if (redacted.runtimeDescriptor) {
410
+ redacted.runtimeDescriptor = redactRuntimeDescriptorForConversation(redacted.runtimeDescriptor);
411
+ }
412
+ if (redacted.runtimeInfo) {
413
+ redacted.runtimeInfo = redactRuntimeInfoForConversation(redacted.runtimeInfo);
414
+ }
415
+ if (!redacted.controlState)
416
+ return cloneDefined(redacted);
417
+ const controlState = { ...redacted.controlState };
418
+ const hiddenIds = hiddenControlValueIds(descriptor);
419
+ for (const field of ['model', 'permissionMode', 'effort', 'workspace', 'executionMode']) {
420
+ if (isRuntimePresentationFieldHidden(descriptor, field) && hasOwn(controlState, field)) {
421
+ if (options.patch) {
422
+ controlState[field] = null;
423
+ }
424
+ else {
425
+ delete controlState[field];
426
+ }
427
+ }
428
+ }
429
+ for (const id of hiddenIds) {
430
+ if (!hasOwn(controlState, id))
431
+ continue;
432
+ if (options.patch) {
433
+ controlState[id] = null;
434
+ }
435
+ else {
436
+ delete controlState[id];
437
+ }
438
+ }
439
+ redacted.controlState = controlState;
440
+ return cloneDefined(redacted);
441
+ }
@@ -1,3 +1,4 @@
1
+ import { redactAgentRuntimeForConversation, redactAgentSessionSnapshotForConversation, isRuntimePresentationFieldHidden, redactRuntimeActivityItemForConversation, redactRuntimeInfoForConversation, redactSessionStateForConversation, } from './runtime-presentation.js';
1
2
  import { clearRuntimeInfo, clearRuntimeActivity, clearSessionState, clearTurnState, patchAgentSessionSnapshot, patchRuntimeInfo, readRuntimeActivity, removeRuntimeActivityItem, rtdbRead, rtdbWrite, writeRuntimeActivity, writeRuntimeInfo, writeSessionState, writeTurnState, } from './rtdb-rest.js';
2
3
  const SERVER_TIMESTAMP = { '.sv': 'timestamp' };
3
4
  const MAX_RUNTIME_ACTIVITY_ITEMS = 50;
@@ -35,7 +36,31 @@ export function createRuntimeStatePublisher(options) {
35
36
  const { agentId, clientType, hostMode, rtdb } = options;
36
37
  const writePath = (path, data) => (rtdb ? rtdb.write(path, data) : rtdbWrite(path, data));
37
38
  const readPath = (path) => (rtdb ? rtdb.read(path) : rtdbRead(path));
38
- let lastPublishedRuntime = null;
39
+ let lastRawRuntime = null;
40
+ let lastPublicRuntime = null;
41
+ function currentDescriptor() {
42
+ return lastRawRuntime?.runtimeDescriptor ?? null;
43
+ }
44
+ function hasHiddenSessionStateField(descriptor) {
45
+ if (!descriptor)
46
+ return false;
47
+ const controls = [
48
+ ...(descriptor.coreControls ?? []),
49
+ ...(descriptor.runtimeControls ?? []),
50
+ ];
51
+ return [
52
+ 'model',
53
+ 'permissionMode',
54
+ 'effort',
55
+ 'cwd',
56
+ 'executionMode',
57
+ 'branch',
58
+ 'worktreePath',
59
+ 'fallbackReason',
60
+ 'contextUsage',
61
+ ].some((field) => isRuntimePresentationFieldHidden(descriptor, field))
62
+ || controls.some((control) => control.visibility === 'hidden' || control.sensitive === true);
63
+ }
39
64
  const readRuntimeActivityPath = (conversationId) => (rtdb
40
65
  ? rtdb.readRuntimeActivity(conversationId, agentId)
41
66
  : readRuntimeActivity(conversationId, agentId));
@@ -63,18 +88,22 @@ export function createRuntimeStatePublisher(options) {
63
88
  }
64
89
  return {
65
90
  async publishAgentRuntime(runtime) {
66
- const payload = {
91
+ const rawRuntime = {
67
92
  clientType,
68
93
  hostMode,
69
94
  ...runtime,
95
+ };
96
+ const publicPayload = {
97
+ ...redactAgentRuntimeForConversation(rawRuntime),
70
98
  updatedAt: SERVER_TIMESTAMP,
71
99
  };
72
- lastPublishedRuntime = payload;
73
- await writePath(`/agent-runtime/${agentId}`, payload);
100
+ lastRawRuntime = rawRuntime;
101
+ lastPublicRuntime = publicPayload;
102
+ await writePath(`/agent-runtime/${agentId}`, publicPayload);
74
103
  },
75
104
  async clearAgentRuntime() {
76
105
  const path = `/agent-runtime/${agentId}`;
77
- const current = lastPublishedRuntime ?? await readPath(path).catch(() => null);
106
+ const current = lastPublicRuntime ?? await readPath(path).catch(() => null);
78
107
  if (hasPreservableRuntimeState(current)) {
79
108
  await writePath(path, {
80
109
  ...current,
@@ -85,9 +114,30 @@ export function createRuntimeStatePublisher(options) {
85
114
  await writePath(path, null);
86
115
  },
87
116
  async writeSessionState(conversationId, state) {
117
+ const descriptor = currentDescriptor();
118
+ const publicState = redactSessionStateForConversation(descriptor, state);
88
119
  await (rtdb
89
- ? rtdb.writeSessionState(conversationId, agentId, state)
90
- : writeSessionState(conversationId, agentId, state));
120
+ ? rtdb.writeSessionState(conversationId, agentId, publicState)
121
+ : writeSessionState(conversationId, agentId, publicState));
122
+ if (hasHiddenSessionStateField(descriptor)) {
123
+ const clearingPatch = redactAgentSessionSnapshotForConversation(descriptor, {
124
+ model: state.model,
125
+ modelOptions: state.availableModels,
126
+ permissionMode: state.permissionMode,
127
+ effort: state.effort,
128
+ resolvedCwd: state.cwd,
129
+ executionMode: state.executionMode,
130
+ executionBranch: state.executionBranch,
131
+ worktreePath: state.worktreePath,
132
+ executionFallbackReason: state.executionFallbackReason,
133
+ contextUsage: state.contextUsage,
134
+ runtimeControlValues: state.runtimeControlValues,
135
+ controlState: state.controlState,
136
+ }, { patch: true });
137
+ await (rtdb
138
+ ? rtdb.patchAgentSessionSnapshot(conversationId, agentId, clearingPatch)
139
+ : patchAgentSessionSnapshot(conversationId, agentId, clearingPatch));
140
+ }
91
141
  },
92
142
  async clearSessionState(conversationId) {
93
143
  await (rtdb
@@ -105,19 +155,22 @@ export function createRuntimeStatePublisher(options) {
105
155
  : clearTurnState(conversationId, agentId));
106
156
  },
107
157
  async patchAgentSessionSnapshot(conversationId, snapshot) {
158
+ const publicSnapshot = redactAgentSessionSnapshotForConversation(currentDescriptor(), snapshot, { patch: true });
108
159
  await (rtdb
109
- ? rtdb.patchAgentSessionSnapshot(conversationId, agentId, snapshot)
110
- : patchAgentSessionSnapshot(conversationId, agentId, snapshot));
160
+ ? rtdb.patchAgentSessionSnapshot(conversationId, agentId, publicSnapshot)
161
+ : patchAgentSessionSnapshot(conversationId, agentId, publicSnapshot));
111
162
  },
112
163
  async writeRuntimeInfo(conversationId, payload) {
164
+ const publicPayload = redactRuntimeInfoForConversation(payload, { descriptor: currentDescriptor() });
113
165
  await (rtdb
114
- ? rtdb.writeRuntimeInfo(conversationId, agentId, payload)
115
- : writeRuntimeInfo(conversationId, agentId, payload));
166
+ ? rtdb.writeRuntimeInfo(conversationId, agentId, publicPayload)
167
+ : writeRuntimeInfo(conversationId, agentId, publicPayload));
116
168
  },
117
169
  async patchRuntimeInfo(conversationId, payload) {
170
+ const publicPayload = redactRuntimeInfoForConversation(payload, { descriptor: currentDescriptor() });
118
171
  await (rtdb
119
- ? rtdb.patchRuntimeInfo(conversationId, agentId, payload)
120
- : patchRuntimeInfo(conversationId, agentId, payload));
172
+ ? rtdb.patchRuntimeInfo(conversationId, agentId, publicPayload)
173
+ : patchRuntimeInfo(conversationId, agentId, publicPayload));
121
174
  },
122
175
  async clearRuntimeInfo(conversationId) {
123
176
  await (rtdb
@@ -125,9 +178,12 @@ export function createRuntimeStatePublisher(options) {
125
178
  : clearRuntimeInfo(conversationId, agentId));
126
179
  },
127
180
  async writeRuntimeActivity(conversationId, item) {
181
+ const publicItem = redactRuntimeActivityItemForConversation(item);
182
+ if (!publicItem)
183
+ return;
128
184
  const normalized = {
129
- ...item,
130
- updatedAt: item.updatedAt || Date.now(),
185
+ ...publicItem,
186
+ updatedAt: publicItem.updatedAt || Date.now(),
131
187
  };
132
188
  await (rtdb
133
189
  ? rtdb.writeRuntimeActivity(conversationId, agentId, normalized)
@@ -1,9 +1,10 @@
1
1
  export type DeliveryIntent = 'queue' | 'interrupt' | 'interleave' | 'stop';
2
2
  export type TurnMessageSemantics = 'progress' | 'turn_complete' | 'control';
3
- export type InboundDisposition = 'queued' | 'accepted_now' | 'interleaved' | 'trigger_suppressed' | 'rejected';
3
+ export type InboundDisposition = 'queued' | 'accepted_now' | 'interleaved' | 'trigger_suppressed' | 'rejected' | 'cancelled';
4
4
  export type TurnLifecycleState = 'idle' | 'thinking' | 'streaming' | 'tool' | 'waiting_input' | 'completed' | 'interrupted';
5
5
  export interface RuntimeCapabilities {
6
6
  supportsInterrupt: boolean;
7
+ supportsInputInterrupt: boolean;
7
8
  supportsQueue: boolean;
8
9
  supportsInterleave: boolean;
9
10
  supportsRequiresAction: boolean;
@@ -21,6 +21,7 @@ const DELIVERY_INTENTS = [
21
21
  ];
22
22
  export const DEFAULT_RUNTIME_CAPABILITIES = {
23
23
  supportsInterrupt: false,
24
+ supportsInputInterrupt: false,
24
25
  supportsQueue: true,
25
26
  supportsInterleave: false,
26
27
  supportsRequiresAction: false,
@@ -43,6 +44,16 @@ export const HOST_ADMISSION_ACTIONS_DISABLED = {
43
44
  function isRecord(value) {
44
45
  return typeof value === 'object' && value !== null && !Array.isArray(value);
45
46
  }
47
+ function isHiddenRuntimeCardMetadata(metadata) {
48
+ if (!isRecord(metadata) || typeof metadata.type !== 'string')
49
+ return false;
50
+ return metadata.type === 'approval_reply'
51
+ || metadata.type === 'approval_outcome'
52
+ || metadata.type === 'question_reply'
53
+ || metadata.type === 'plan_approval_reply'
54
+ || metadata.type === 'runtime_input_reply'
55
+ || metadata.type === 'runtime_input_outcome';
56
+ }
46
57
  export function normalizeTurnMetadata(metadata) {
47
58
  if (!isRecord(metadata))
48
59
  return null;
@@ -63,6 +74,7 @@ export function normalizeTurnMetadata(metadata) {
63
74
  || metadata.inboundDisposition === 'interleaved'
64
75
  || metadata.inboundDisposition === 'trigger_suppressed'
65
76
  || metadata.inboundDisposition === 'rejected'
77
+ || metadata.inboundDisposition === 'cancelled'
66
78
  ? metadata.inboundDisposition
67
79
  : undefined;
68
80
  if (!turnId && !turnSemantics && !deliveryIntent && typeof metadata.turnComplete !== 'boolean'
@@ -100,6 +112,7 @@ export function normalizeTurnState(value) {
100
112
  capabilities: isRecord(value.capabilities)
101
113
  ? {
102
114
  supportsInterrupt: Boolean(value.capabilities.supportsInterrupt),
115
+ supportsInputInterrupt: Boolean(value.capabilities.supportsInputInterrupt),
103
116
  supportsQueue: value.capabilities.supportsQueue !== false,
104
117
  supportsInterleave: Boolean(value.capabilities.supportsInterleave),
105
118
  supportsRequiresAction: Boolean(value.capabilities.supportsRequiresAction),
@@ -132,6 +145,9 @@ export function resolveTurnMessageSemantics(input) {
132
145
  return isTurnOpen(input.senderTurnState) ? 'progress' : 'turn_complete';
133
146
  }
134
147
  export function shouldPromoteConversationMessage(input) {
148
+ if (isHiddenRuntimeCardMetadata(input.metadata)) {
149
+ return false;
150
+ }
135
151
  return resolveTurnMessageSemantics(input) !== 'progress';
136
152
  }
137
153
  export function shouldTriggerAgentTurn(input) {
package/dist/types.d.ts CHANGED
@@ -190,7 +190,7 @@ export interface CanonResolveAdmissionResult {
190
190
  target: ResolvedAdmissionTargetSummary | null;
191
191
  admission: ResolvedTargetAdmissionPayload;
192
192
  }
193
- export type AgentClientType = 'claude-code' | 'openclaw' | 'codex' | 'generic';
193
+ export type AgentClientType = 'claude-code' | 'openclaw' | 'codex' | 'hermes' | 'generic';
194
194
  export interface ResolvedAdmission {
195
195
  discoverable: boolean;
196
196
  inboundPolicy: 'open' | 'approval-required' | 'owner-only';
@@ -250,6 +250,18 @@ export type CanonControlSelectionPolicy = 'inherit' | 'required_explicit';
250
250
  export type CanonRuntimeStreamingMode = 'none' | 'status' | 'snapshot' | 'block' | 'delta';
251
251
  export type CanonRuntimeSurfaceMode = 'host' | 'channel' | 'limited_channel' | 'operator';
252
252
  export type CanonRuntimeDetailTier = 'primary' | 'detail' | 'diagnostic';
253
+ export type CanonRuntimeVisibility = 'conversation' | 'hidden';
254
+ export type CanonRuntimePresentationPreset = 'normal' | 'minimal' | 'full';
255
+ export type CanonRuntimePresentationField = 'model' | 'permissionMode' | 'effort' | 'workspace' | 'executionMode' | 'contextUsage' | 'cwd' | 'branch' | 'worktreePath' | 'workspaceRoot' | 'workspaceRelativePath' | 'fallbackReason';
256
+ export interface CanonRuntimePresentationHint {
257
+ visibility?: CanonRuntimeVisibility;
258
+ tier?: CanonRuntimeDetailTier;
259
+ sensitive?: boolean;
260
+ }
261
+ export interface CanonRuntimePresentationPolicy {
262
+ preset?: CanonRuntimePresentationPreset;
263
+ fields?: Partial<Record<CanonRuntimePresentationField, CanonRuntimePresentationHint>>;
264
+ }
253
265
  export type CanonRuntimeFactGroup = 'connection' | 'route' | 'runtime' | 'model' | 'session' | 'account' | 'limits';
254
266
  export type CanonRuntimeInventoryStatus = 'ready' | 'auth_needed' | 'unknown' | 'configured' | 'running' | 'error';
255
267
  export type CanonRuntimeStatusTone = 'default' | 'success' | 'warning' | 'danger';
@@ -295,6 +307,9 @@ export interface CanonRuntimeActionDescriptor {
295
307
  id: string;
296
308
  label: string;
297
309
  description?: string;
310
+ visibility?: CanonRuntimeVisibility;
311
+ tier?: CanonRuntimeDetailTier;
312
+ sensitive?: boolean;
298
313
  primitive?: CanonRuntimePrimitiveId;
299
314
  aliases?: ReadonlyArray<string>;
300
315
  category?: CanonRuntimeActionCategory;
@@ -319,6 +334,9 @@ export interface CanonControlDescriptor {
319
334
  liveBehavior: CanonControlLiveBehavior;
320
335
  selectionPolicy: CanonControlSelectionPolicy;
321
336
  description?: string;
337
+ visibility?: CanonRuntimeVisibility;
338
+ tier?: CanonRuntimeDetailTier;
339
+ sensitive?: boolean;
322
340
  }
323
341
  export interface CanonRuntimeDescriptor {
324
342
  coreControls: ReadonlyArray<CanonControlDescriptor>;
@@ -341,6 +359,12 @@ export interface CanonRuntimeDescriptor {
341
359
  * means activity/tool state without live assistant text.
342
360
  */
343
361
  streamingTextMode?: CanonRuntimeStreamingMode;
362
+ /**
363
+ * Runtime-owned presentation policy for built-in Canon detail fields.
364
+ * Hidden fields are redacted before public/member-readable runtime payloads
365
+ * are published; clients only render what remains.
366
+ */
367
+ presentation?: CanonRuntimePresentationPolicy;
344
368
  /**
345
369
  * Contact-graph and admission actions this runtime exposes through the
346
370
  * agent SDK. Plugins set this to advertise which tools they will surface
@@ -366,6 +390,7 @@ export interface CanonRuntimeStatusItem {
366
390
  tone?: CanonRuntimeStatusTone;
367
391
  tier?: CanonRuntimeDetailTier;
368
392
  sensitive?: boolean;
393
+ visibility?: CanonRuntimeVisibility;
369
394
  source?: RuntimeControlValueSource;
370
395
  }
371
396
  export interface CanonRuntimeFact {
@@ -374,6 +399,8 @@ export interface CanonRuntimeFact {
374
399
  value: string;
375
400
  group: CanonRuntimeFactGroup;
376
401
  tier?: CanonRuntimeDetailTier;
402
+ sensitive?: boolean;
403
+ visibility?: CanonRuntimeVisibility;
377
404
  tone?: 'neutral' | 'good' | 'warning' | 'danger';
378
405
  copyable?: boolean;
379
406
  updatedAt?: number;
@@ -392,6 +419,9 @@ export interface CanonRuntimeActivityItem {
392
419
  startedAt?: number;
393
420
  updatedAt: number;
394
421
  endedAt?: number;
422
+ visibility?: CanonRuntimeVisibility;
423
+ tier?: CanonRuntimeDetailTier;
424
+ sensitive?: boolean;
395
425
  actions?: ReadonlyArray<CanonRuntimeCommandDescriptor>;
396
426
  }
397
427
  export interface CanonRuntimeInventoryEntry {
@@ -399,12 +429,17 @@ export interface CanonRuntimeInventoryEntry {
399
429
  label: string;
400
430
  status?: CanonRuntimeInventoryStatus;
401
431
  description?: string;
432
+ tier?: CanonRuntimeDetailTier;
433
+ sensitive?: boolean;
434
+ visibility?: CanonRuntimeVisibility;
402
435
  }
403
436
  export interface CanonRuntimeInventory {
404
437
  id: string;
405
438
  label: string;
406
439
  entries: ReadonlyArray<CanonRuntimeInventoryEntry>;
407
440
  tier?: CanonRuntimeDetailTier;
441
+ sensitive?: boolean;
442
+ visibility?: CanonRuntimeVisibility;
408
443
  }
409
444
  export interface RuntimeInfoPayload {
410
445
  descriptor: CanonRuntimeDescriptor;
package/dist/types.js CHANGED
@@ -29,6 +29,15 @@ export const AGENT_CAPABILITIES = {
29
29
  supportsQueue: true,
30
30
  supportsInterleave: false,
31
31
  },
32
+ 'hermes': {
33
+ supportsModelSwitch: false,
34
+ supportsPermissionMode: false,
35
+ supportsEffort: false,
36
+ supportsSessionState: true,
37
+ supportsInterrupt: true,
38
+ supportsQueue: true,
39
+ supportsInterleave: false,
40
+ },
32
41
  'openclaw': { ...DEFAULT_CAPABILITIES },
33
42
  'generic': { ...DEFAULT_CAPABILITIES },
34
43
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonmsg/core",
3
- "version": "0.19.1",
3
+ "version": "0.19.3",
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",