@canonmsg/core 0.15.0 → 0.15.2

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.
@@ -14,7 +14,7 @@ function descriptorOptions(runtime, controlId) {
14
14
  function descriptorDefaultValue(runtime, controlId) {
15
15
  const control = listDescriptorControls(runtime)
16
16
  .find((candidate) => candidate.id === controlId);
17
- return control?.defaultValue ?? control?.options?.[0]?.value ?? undefined;
17
+ return control?.defaultValue ?? undefined;
18
18
  }
19
19
  function buildWorkSessionSummary(workSession, workSessions) {
20
20
  const merged = mergeWorkSessionContexts(workSession, workSessions);
@@ -30,13 +30,95 @@ function buildWorkSessionSummary(workSession, workSessions) {
30
30
  status: primary.status ?? null,
31
31
  };
32
32
  }
33
+ function setControlState(controlState, id, value, source, appliedAt) {
34
+ if (value === undefined)
35
+ return;
36
+ controlState[id] = {
37
+ value,
38
+ source,
39
+ ...(source === 'applied' && appliedAt ? { appliedAt } : {}),
40
+ };
41
+ }
42
+ function buildControlState(input) {
43
+ const controlState = {};
44
+ const appliedAt = input.sessionState?.updatedAt ?? input.lastHeartbeatAt ?? input.updatedAt ?? undefined;
45
+ const modelDefault = descriptorDefaultValue(input.runtime, 'model');
46
+ if (input.sessionState?.model !== undefined) {
47
+ setControlState(controlState, 'model', input.sessionState.model, 'applied', appliedAt);
48
+ }
49
+ else if (input.sessionConfig?.model !== undefined) {
50
+ setControlState(controlState, 'model', input.sessionConfig.model, 'requested');
51
+ }
52
+ else if (modelDefault !== undefined) {
53
+ setControlState(controlState, 'model', modelDefault, 'host-default');
54
+ }
55
+ const permissionDefault = descriptorDefaultValue(input.runtime, 'permissionMode');
56
+ if (input.sessionState?.permissionMode !== undefined) {
57
+ setControlState(controlState, 'permissionMode', input.sessionState.permissionMode, 'applied', appliedAt);
58
+ }
59
+ else if (input.sessionConfig?.permissionMode !== undefined) {
60
+ setControlState(controlState, 'permissionMode', input.sessionConfig.permissionMode, 'requested');
61
+ }
62
+ else if (permissionDefault !== undefined) {
63
+ setControlState(controlState, 'permissionMode', permissionDefault, 'host-default');
64
+ }
65
+ const effortDefault = descriptorDefaultValue(input.runtime, 'effort');
66
+ if (input.sessionState?.effort !== undefined) {
67
+ setControlState(controlState, 'effort', input.sessionState.effort, 'applied', appliedAt);
68
+ }
69
+ else if (input.sessionConfig?.effort !== undefined) {
70
+ setControlState(controlState, 'effort', input.sessionConfig.effort, 'requested');
71
+ }
72
+ else if (effortDefault !== undefined) {
73
+ setControlState(controlState, 'effort', effortDefault, 'host-default');
74
+ }
75
+ const workspaceDefault = descriptorDefaultValue(input.runtime, 'workspace');
76
+ if (input.sessionConfig?.workspaceId !== undefined) {
77
+ setControlState(controlState, 'workspace', input.sessionConfig.workspaceId, 'requested');
78
+ }
79
+ else if (workspaceDefault !== undefined) {
80
+ setControlState(controlState, 'workspace', workspaceDefault, 'host-default');
81
+ }
82
+ if (input.sessionState?.executionMode !== undefined) {
83
+ setControlState(controlState, 'executionMode', input.sessionState.executionMode, 'applied', appliedAt);
84
+ }
85
+ else if (input.sessionConfig?.executionMode !== undefined) {
86
+ setControlState(controlState, 'executionMode', input.sessionConfig.executionMode, 'requested');
87
+ }
88
+ for (const [id, value] of Object.entries(input.sessionConfig?.runtimeControlValues ?? {})) {
89
+ setControlState(controlState, id, value, 'requested');
90
+ }
91
+ for (const [id, value] of Object.entries(input.sessionState?.runtimeControlValues ?? {})) {
92
+ setControlState(controlState, id, value, 'applied', appliedAt);
93
+ }
94
+ Object.assign(controlState, input.sessionState?.controlState ?? {});
95
+ return Object.keys(controlState).length > 0 ? controlState : undefined;
96
+ }
33
97
  export function buildAgentSessionSnapshot(input) {
34
- const modelOptions = descriptorOptions(input.runtime, 'model');
98
+ const modelOptions = input.sessionState?.availableModels?.length
99
+ ? input.sessionState.availableModels
100
+ : descriptorOptions(input.runtime, 'model');
35
101
  const workspaceOptions = descriptorOptions(input.runtime, 'workspace')
36
102
  .map((option) => ({ id: option.value, label: option.label }));
37
103
  const availableExecutionModes = descriptorOptions(input.runtime, 'executionMode')
38
104
  .map((option) => option.value)
39
105
  .filter((value) => value === 'worktree' || value === 'locked');
106
+ const model = input.sessionState?.model
107
+ ?? input.sessionConfig?.model
108
+ ?? descriptorDefaultValue(input.runtime, 'model');
109
+ const permissionMode = input.sessionState?.permissionMode
110
+ ?? input.sessionConfig?.permissionMode
111
+ ?? descriptorDefaultValue(input.runtime, 'permissionMode');
112
+ const effort = input.sessionState?.effort
113
+ ?? input.sessionConfig?.effort
114
+ ?? descriptorDefaultValue(input.runtime, 'effort');
115
+ const runtimeControlValues = input.sessionState?.runtimeControlValues
116
+ ?? input.sessionConfig?.runtimeControlValues;
117
+ const workspaceId = input.sessionConfig?.workspaceId
118
+ ?? descriptorDefaultValue(input.runtime, 'workspace');
119
+ const executionMode = input.sessionState?.executionMode
120
+ ?? input.sessionConfig?.executionMode;
121
+ const controlState = buildControlState(input);
40
122
  return {
41
123
  conversationId: input.conversationId,
42
124
  agentId: input.agentId,
@@ -46,22 +128,17 @@ export function buildAgentSessionSnapshot(input) {
46
128
  hostMode: Boolean(input.sessionState?.hostMode
47
129
  ?? input.sessionConfig?.hostMode
48
130
  ?? input.runtime?.hostMode),
49
- model: input.sessionState?.model
50
- ?? input.sessionConfig?.model
51
- ?? descriptorDefaultValue(input.runtime, 'model'),
131
+ model,
52
132
  modelOptions,
53
- permissionMode: input.sessionState?.permissionMode
54
- ?? input.sessionConfig?.permissionMode
55
- ?? descriptorDefaultValue(input.runtime, 'permissionMode'),
133
+ permissionMode,
56
134
  permissionModeOptions: descriptorOptions(input.runtime, 'permissionMode'),
57
- effort: input.sessionState?.effort ?? input.sessionConfig?.effort,
58
- runtimeControlValues: input.sessionState?.runtimeControlValues
59
- ?? input.sessionConfig?.runtimeControlValues,
60
- workspaceId: input.sessionConfig?.workspaceId
61
- ?? descriptorDefaultValue(input.runtime, 'workspace'),
135
+ effort,
136
+ runtimeControlValues,
137
+ controlState,
138
+ runtimeControlErrors: input.sessionState?.runtimeControlErrors ?? undefined,
139
+ workspaceId,
62
140
  workspaceOptions,
63
- executionMode: input.sessionState?.executionMode
64
- ?? input.sessionConfig?.executionMode,
141
+ executionMode,
65
142
  availableExecutionModes,
66
143
  executionBranch: input.sessionState?.executionBranch,
67
144
  resolvedWorkspaceLabel: undefined,
package/dist/browser.d.ts CHANGED
@@ -1,7 +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 type { AddMemberResult, AgentCapabilities, AgentClientType, AgentSessionSnapshot, AgentSessionWorkSessionSummary, 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, CanonRuntimeExecutionMetadata, CanonRuntimeInventory, CanonRuntimeInventoryEntry, CanonRuntimeStreamingMode, CanonRuntimeStatusItem, CanonRuntimeSurfaceMode, CanonWorkspaceRootMetadata, RuntimeUpdatedPayload, RuntimeInfoPayload, ResolvedAdmission, SessionConfig, TurnUpdatedPayload, WorkspaceOption, WorkspaceOptionSource, } from './types.js';
4
+ export type { AddMemberResult, AgentCapabilities, AgentClientType, AgentSessionSnapshot, AgentSessionWorkSessionSummary, 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, CanonRuntimeDetailTier, CanonRuntimeExecutionMetadata, CanonRuntimeInventory, CanonRuntimeInventoryEntry, CanonRuntimeStreamingMode, CanonRuntimeStatusItem, CanonRuntimeSurfaceMode, CanonWorkspaceRootMetadata, RuntimeUpdatedPayload, RuntimeInfoPayload, RuntimeControlError, RuntimeControlState, RuntimeControlValueSource, ResolvedAdmission, SessionConfig, TurnUpdatedPayload, WorkspaceOption, WorkspaceOptionSource, } from './types.js';
5
5
  export { EXECUTION_ENVIRONMENT_MODES, isExecutionEnvironmentMode, } from './execution-environment-mode.js';
6
6
  export type { ExecutionEnvironmentMode } from './execution-environment-mode.js';
7
7
  export type { CanonResolvedWorkSession, CanonWorkSession, CanonWorkSessionContext, CanonWorkSessionConversationRole, CanonWorkSessionDisclosureMode, CanonWorkSessionParticipant, CanonWorkSessionStatus, CreateWorkSessionOptions, SendLinkedMessageOptions, SendLinkedMessageResult, UpdateWorkSessionConversationOptions, WorkSessionPromptRenderOptions, } from './work-session.js';
@@ -0,0 +1,13 @@
1
+ export interface CliMetadata {
2
+ name: string;
3
+ description?: string;
4
+ help: string;
5
+ version?: string;
6
+ }
7
+ export interface RunCliMetadataOptions extends CliMetadata {
8
+ argv?: string[];
9
+ }
10
+ export declare function isDirectExecution(moduleUrl: string): boolean;
11
+ export declare function readCliPackageVersion(moduleUrl: string): string | null;
12
+ export declare function handleCliMetadataRequest(moduleUrl: string, metadata: RunCliMetadataOptions): boolean;
13
+ export declare function runCli(moduleUrl: string, main: () => void | Promise<void>, onError: (error: unknown) => void, metadata?: RunCliMetadataOptions): void;
@@ -0,0 +1,60 @@
1
+ import { readFileSync, realpathSync } from 'node:fs';
2
+ import { dirname, resolve } from 'node:path';
3
+ import { fileURLToPath, pathToFileURL } from 'node:url';
4
+ export function isDirectExecution(moduleUrl) {
5
+ const entry = process.argv[1];
6
+ if (!entry)
7
+ return false;
8
+ const abs = resolve(entry);
9
+ let real = abs;
10
+ try {
11
+ real = realpathSync(abs);
12
+ }
13
+ catch {
14
+ // argv[1] may not exist on disk in rare harnesses; fall back to abs.
15
+ }
16
+ return (pathToFileURL(real).href === moduleUrl
17
+ || pathToFileURL(abs).href === moduleUrl);
18
+ }
19
+ export function readCliPackageVersion(moduleUrl) {
20
+ let current = dirname(fileURLToPath(moduleUrl));
21
+ while (true) {
22
+ try {
23
+ const manifest = JSON.parse(readFileSync(resolve(current, 'package.json'), 'utf8'));
24
+ return typeof manifest.version === 'string' ? manifest.version : null;
25
+ }
26
+ catch {
27
+ const parent = dirname(current);
28
+ if (parent === current)
29
+ return null;
30
+ current = parent;
31
+ }
32
+ }
33
+ }
34
+ function hasArg(argv, long, short) {
35
+ return argv.includes(long) || argv.includes(short);
36
+ }
37
+ export function handleCliMetadataRequest(moduleUrl, metadata) {
38
+ const argv = metadata.argv ?? process.argv.slice(2);
39
+ if (hasArg(argv, '--help', '-h')) {
40
+ process.stdout.write(`${metadata.help.trimEnd()}\n`);
41
+ return true;
42
+ }
43
+ if (hasArg(argv, '--version', '-V')) {
44
+ const version = metadata.version ?? readCliPackageVersion(moduleUrl) ?? 'unknown';
45
+ process.stdout.write(`${metadata.name} ${version}\n`);
46
+ return true;
47
+ }
48
+ return false;
49
+ }
50
+ export function runCli(moduleUrl, main, onError, metadata) {
51
+ if (!isDirectExecution(moduleUrl)) {
52
+ return;
53
+ }
54
+ if (metadata && handleCliMetadataRequest(moduleUrl, metadata)) {
55
+ return;
56
+ }
57
+ Promise.resolve()
58
+ .then(() => main())
59
+ .catch(onError);
60
+ }
@@ -36,6 +36,7 @@ export declare function buildCanonHostPrompt(input: {
36
36
  workSession?: MessageCreatedPayload['message']['workSession'];
37
37
  workSessions?: MessageCreatedPayload['workSessions'];
38
38
  buildInboundContextLines: (context: HostInboundParticipantContext) => string[];
39
+ sessionContextLines?: string[];
39
40
  }): string;
40
41
  /**
41
42
  * Render the **text portion** of an inbound Canon message. Images are
@@ -24,6 +24,9 @@ export function buildCanonHostPrompt(input) {
24
24
  ...(resolvedWorkSessions.length > 0
25
25
  ? ['Honor the Canon work-session context above within its stated disclosure limits.']
26
26
  : []),
27
+ ...(input.sessionContextLines?.length
28
+ ? ['Canon session state:', ...input.sessionContextLines]
29
+ : []),
27
30
  `Conversation ID: ${input.conversationId}`,
28
31
  '',
29
32
  'New Canon message:',
@@ -180,6 +183,7 @@ export async function publishHostSessionSnapshots(input) {
180
183
  permissionMode: snapshot.permissionMode ?? null,
181
184
  effort: snapshot.effort ?? null,
182
185
  runtimeControlValues: snapshot.runtimeControlValues ?? null,
186
+ controlState: snapshot.controlState ?? null,
183
187
  workspaceId: snapshot.workspaceId ?? null,
184
188
  executionMode: snapshot.executionMode ?? null,
185
189
  executionBranch,
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, CanonResolveAdmissionResult, ContactAddedPayload, ContactApprovedPayload, ContactCardPayload, ContactRemovedPayload, ContactRequestPayload, ContactSource, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, CanonMessage, CanonConversation, CanonMessagesPage, CreateContactRequestResult, AgentContext, CanonStreamEvent, AgentSessionSnapshot, AgentSessionWorkSessionSummary, 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, CanonRuntimeExecutionMetadata, CanonRuntimeInventory, CanonRuntimeInventoryEntry, CanonRuntimeStreamingMode, CanonRuntimeStatusItem, CanonRuntimeSurfaceMode, CanonWorkspaceRootMetadata, ModelOption, PermissionModeOption, RuntimeInfoPayload, WorkspaceOption, WorkspaceOptionSource, } from './types.js';
2
+ export type { AddMemberResult, AgentCapabilities, AgentClientType, CanonControlAvailability, CanonControlDescriptor, CanonControlLiveBehavior, CanonControlSelectionPolicy, CanonControlValue, CanonContact, CanonContactRequest, CanonContactRequestStatus, CanonResolveAdmissionResult, ContactAddedPayload, ContactApprovedPayload, ContactCardPayload, ContactRemovedPayload, ContactRequestPayload, ContactSource, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, CanonMessage, CanonConversation, CanonMessagesPage, CreateContactRequestResult, AgentContext, CanonStreamEvent, AgentSessionSnapshot, AgentSessionWorkSessionSummary, 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, CanonRuntimeDetailTier, CanonRuntimeExecutionMetadata, CanonRuntimeInventory, CanonRuntimeInventoryEntry, CanonRuntimeStreamingMode, CanonRuntimeStatusItem, CanonRuntimeSurfaceMode, CanonWorkspaceRootMetadata, ModelOption, PermissionModeOption, RuntimeInfoPayload, RuntimeControlError, RuntimeControlState, RuntimeControlValueSource, WorkspaceOption, WorkspaceOptionSource, } from './types.js';
3
3
  export type { CanonResolvedWorkSession, CanonWorkSession, CanonWorkSessionContext, CanonWorkSessionConversationRole, CreateWorkSessionOptions, CanonWorkSessionDisclosureMode, CanonWorkSessionParticipant, CanonWorkSessionStatus, SendLinkedMessageOptions, SendLinkedMessageResult, UpdateWorkSessionConversationOptions, WorkSessionPromptRenderOptions, } from './work-session.js';
4
4
  export { buildWorkSessionPromptLines, buildWorkSessionsPromptLines, mergeWorkSessionContexts, } from './work-session.js';
5
5
  export { buildConfiguredWorkspaceOptionsWithRoots, buildPublicWorkspaceRoots, buildWorkspaceRootId, discoverWorkspaceProjects, } from './workspace-discovery.js';
@@ -39,3 +39,5 @@ export type { RuntimeStatePublisher, RuntimeStatePublisherOptions, RuntimeStream
39
39
  export { formatCanonMessageAsText } from './message-format.js';
40
40
  export { DEFAULT_BASE_URL, DEFAULT_STREAM_URL, DEFAULT_RTDB_URL, FIREBASE_WEB_API_KEY } from './constants.js';
41
41
  export { resolveCanonBaseUrl } from './base-url.js';
42
+ export { handleCliMetadataRequest, isDirectExecution, readCliPackageVersion, runCli, } from './cli-metadata.js';
43
+ export type { CliMetadata, RunCliMetadataOptions, } from './cli-metadata.js';
package/dist/index.js CHANGED
@@ -39,3 +39,5 @@ export { formatCanonMessageAsText } from './message-format.js';
39
39
  export { DEFAULT_BASE_URL, DEFAULT_STREAM_URL, DEFAULT_RTDB_URL, FIREBASE_WEB_API_KEY } from './constants.js';
40
40
  // Base URL resolver
41
41
  export { resolveCanonBaseUrl } from './base-url.js';
42
+ // CLI metadata helpers for Node entrypoints
43
+ export { handleCliMetadataRequest, isDirectExecution, readCliPackageVersion, runCli, } from './cli-metadata.js';
@@ -7,6 +7,7 @@ export interface LocalRuntimeSessionState {
7
7
  workspaceId?: string;
8
8
  baseCwd: string;
9
9
  executionMode?: ExecutionEnvironmentMode;
10
+ codexPolicyFingerprint?: string;
10
11
  threadId?: string;
11
12
  claudeSessionId?: string;
12
13
  lastInboundMessageId?: string;
@@ -165,7 +165,7 @@ export function clearRuntimeSessionState(runtimeId, input) {
165
165
  delete sessions[key];
166
166
  }
167
167
  }
168
- upsertLocalRuntimeEntry({ ...entry, sessions });
168
+ writeJsonAtomic(runtimePath(entry.id), { ...entry, sessions });
169
169
  }
170
170
  function migrateLegacyCodexSessions(runtimeId) {
171
171
  if (!existsSync(LEGACY_CODEX_SESSIONS_PATH))
@@ -7,13 +7,15 @@
7
7
  */
8
8
  import type { CanonClient } from './client.js';
9
9
  import type { DeliveryIntent, RuntimeCapabilities, TurnLifecycleState } from './turn-protocol.js';
10
- import type { CanonControlValue, RuntimeInfoPayload } from './types.js';
10
+ import type { CanonControlValue, ModelOption, RuntimeControlError, RuntimeControlState, RuntimeInfoPayload } from './types.js';
11
11
  export interface SessionStatePayload {
12
12
  lastError?: string;
13
13
  model?: string;
14
14
  permissionMode?: string;
15
15
  effort?: string;
16
16
  runtimeControlValues?: Record<string, CanonControlValue>;
17
+ controlState?: Record<string, RuntimeControlState>;
18
+ runtimeControlErrors?: Record<string, RuntimeControlError> | null;
17
19
  cwd?: string;
18
20
  executionMode?: 'worktree' | 'locked';
19
21
  executionBranch?: string;
@@ -27,6 +29,7 @@ export interface SessionStatePayload {
27
29
  totalTokens: number;
28
30
  maxTokens: number;
29
31
  };
32
+ availableModels?: ModelOption[];
30
33
  updatedAt: {
31
34
  '.sv': 'timestamp';
32
35
  };
@@ -53,10 +56,7 @@ export interface AgentSessionSnapshotPatch {
53
56
  clientType?: string;
54
57
  hostMode?: boolean;
55
58
  model?: string | null;
56
- modelOptions?: Array<{
57
- value: string;
58
- label: string;
59
- }> | null;
59
+ modelOptions?: ModelOption[] | null;
60
60
  permissionMode?: string | null;
61
61
  permissionModeOptions?: Array<{
62
62
  value: string;
@@ -64,6 +64,8 @@ export interface AgentSessionSnapshotPatch {
64
64
  }> | null;
65
65
  effort?: string | null;
66
66
  runtimeControlValues?: Record<string, CanonControlValue> | null;
67
+ controlState?: Record<string, RuntimeControlState> | null;
68
+ runtimeControlErrors?: Record<string, RuntimeControlError> | null;
67
69
  workspaceId?: string | null;
68
70
  workspaceOptions?: Array<{
69
71
  id: string;
package/dist/rtdb-rest.js CHANGED
@@ -144,6 +144,12 @@ function createRTDBClientHandle(client, options) {
144
144
  ...(state.runtimeControlValues !== undefined
145
145
  ? { runtimeControlValues: state.runtimeControlValues }
146
146
  : {}),
147
+ ...(state.controlState !== undefined
148
+ ? { controlState: state.controlState }
149
+ : {}),
150
+ ...(state.runtimeControlErrors !== undefined
151
+ ? { runtimeControlErrors: state.runtimeControlErrors }
152
+ : {}),
147
153
  ...(state.cwd !== undefined ? { resolvedCwd: state.cwd } : {}),
148
154
  ...(state.executionMode !== undefined ? { executionMode: state.executionMode } : {}),
149
155
  ...(state.executionBranch !== undefined ? { executionBranch: state.executionBranch } : {}),
@@ -154,6 +160,7 @@ function createRTDBClientHandle(client, options) {
154
160
  state: null,
155
161
  waitingForInput: false,
156
162
  ...(state.contextUsage !== undefined ? { contextUsage: state.contextUsage } : {}),
163
+ ...(state.availableModels !== undefined ? { modelOptions: state.availableModels } : {}),
157
164
  ...(state.lastError !== undefined ? { lastError: state.lastError } : {}),
158
165
  lastHeartbeatAt: { '.sv': 'timestamp' },
159
166
  updatedAt: { '.sv': 'timestamp' },
@@ -169,6 +176,7 @@ function createRTDBClientHandle(client, options) {
169
176
  state: null,
170
177
  waitingForInput: false,
171
178
  lastError: null,
179
+ controlState: null,
172
180
  executionBranch: null,
173
181
  contextUsage: null,
174
182
  worktreePath: null,
package/dist/types.d.ts CHANGED
@@ -212,11 +212,18 @@ export interface CanonWorkspaceRootMetadata {
212
212
  defaultRelativePath?: string | null;
213
213
  }
214
214
  export type CanonControlValue = string;
215
+ export type RuntimeControlValueSource = 'applied' | 'requested' | 'host-default' | 'route-default' | 'unknown';
216
+ export interface RuntimeControlState {
217
+ value: CanonControlValue | null;
218
+ source: RuntimeControlValueSource;
219
+ appliedAt?: number;
220
+ }
215
221
  export type CanonControlAvailability = 'setup' | 'live' | 'setup_and_live';
216
222
  export type CanonControlLiveBehavior = 'immediate' | 'next_turn' | 'none';
217
223
  export type CanonControlSelectionPolicy = 'inherit' | 'required_explicit';
218
224
  export type CanonRuntimeStreamingMode = 'none' | 'status' | 'snapshot' | 'block' | 'delta';
219
225
  export type CanonRuntimeSurfaceMode = 'host' | 'channel' | 'limited_channel' | 'operator';
226
+ export type CanonRuntimeDetailTier = 'primary' | 'detail' | 'diagnostic';
220
227
  export type CanonRuntimeInventoryStatus = 'ready' | 'auth_needed' | 'unknown' | 'configured' | 'running' | 'error';
221
228
  export type CanonRuntimeStatusTone = 'default' | 'success' | 'warning' | 'danger';
222
229
  export type CanonRuntimeActionAvailability = 'idle' | 'busy' | 'busy_with_queue' | 'waiting_input' | 'always';
@@ -301,6 +308,9 @@ export interface CanonRuntimeStatusItem {
301
308
  label: string;
302
309
  value: string;
303
310
  tone?: CanonRuntimeStatusTone;
311
+ tier?: CanonRuntimeDetailTier;
312
+ sensitive?: boolean;
313
+ source?: RuntimeControlValueSource;
304
314
  }
305
315
  export interface CanonRuntimeInventoryEntry {
306
316
  id: string;
@@ -312,6 +322,7 @@ export interface CanonRuntimeInventory {
312
322
  id: string;
313
323
  label: string;
314
324
  entries: ReadonlyArray<CanonRuntimeInventoryEntry>;
325
+ tier?: CanonRuntimeDetailTier;
315
326
  }
316
327
  export interface RuntimeInfoPayload {
317
328
  descriptor: CanonRuntimeDescriptor;
@@ -434,6 +445,7 @@ export type CanonStreamEvent = {
434
445
  };
435
446
  };
436
447
  export interface SendMessageOptions {
448
+ messageId?: string;
437
449
  contentType?: 'text' | 'audio' | 'image' | 'file' | 'contact_card';
438
450
  replyTo?: string;
439
451
  replyToPosition?: number;
@@ -466,6 +478,11 @@ export interface SessionControl {
466
478
  updatedAt: number;
467
479
  updatedBy: string;
468
480
  }
481
+ export interface RuntimeControlError {
482
+ value: string;
483
+ message: string;
484
+ updatedAt: number;
485
+ }
469
486
  /** Written by agent to /session-state/{convoId}/{agentId} in RTDB */
470
487
  export interface SessionState {
471
488
  lastError?: string;
@@ -473,6 +490,8 @@ export interface SessionState {
473
490
  permissionMode?: string;
474
491
  effort?: string;
475
492
  runtimeControlValues?: Record<string, CanonControlValue>;
493
+ controlState?: Record<string, RuntimeControlState>;
494
+ runtimeControlErrors?: Record<string, RuntimeControlError> | null;
476
495
  cwd?: string;
477
496
  executionMode?: 'worktree' | 'locked';
478
497
  executionBranch?: string;
@@ -573,6 +592,8 @@ export interface AgentSessionSnapshot {
573
592
  permissionModeOptions?: PermissionModeOption[];
574
593
  effort?: string;
575
594
  runtimeControlValues?: Record<string, CanonControlValue>;
595
+ controlState?: Record<string, RuntimeControlState>;
596
+ runtimeControlErrors?: Record<string, RuntimeControlError> | null;
576
597
  runtimeDescriptor?: CanonRuntimeDescriptor | null;
577
598
  runtimeInfo?: RuntimeInfoPayload | null;
578
599
  workspaceId?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonmsg/core",
3
- "version": "0.15.0",
3
+ "version": "0.15.2",
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",