@canonmsg/core 0.19.0 → 0.19.1

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,4 +1,4 @@
1
- import { clearRuntimeInfo, clearRuntimeActivity, clearSessionState, clearTurnState, patchAgentSessionSnapshot, patchRuntimeInfo, readRuntimeActivity, removeRuntimeActivityItem, rtdbWrite, writeRuntimeActivity, writeRuntimeInfo, writeSessionState, writeTurnState, } from './rtdb-rest.js';
1
+ import { clearRuntimeInfo, clearRuntimeActivity, clearSessionState, clearTurnState, patchAgentSessionSnapshot, patchRuntimeInfo, readRuntimeActivity, removeRuntimeActivityItem, rtdbRead, rtdbWrite, writeRuntimeActivity, writeRuntimeInfo, writeSessionState, writeTurnState, } from './rtdb-rest.js';
2
2
  const SERVER_TIMESTAMP = { '.sv': 'timestamp' };
3
3
  const MAX_RUNTIME_ACTIVITY_ITEMS = 50;
4
4
  const TERMINAL_RUNTIME_ACTIVITY_CLEAR_MS = 60_000;
@@ -6,9 +6,36 @@ const TERMINAL_RUNTIME_ACTIVITY_STATUSES = new Set(['completed', 'failed', 'bloc
6
6
  function isTerminalRuntimeActivity(item) {
7
7
  return TERMINAL_RUNTIME_ACTIVITY_STATUSES.has(item.status);
8
8
  }
9
+ function hasNonEmptyArray(value) {
10
+ return Array.isArray(value) && value.length > 0;
11
+ }
12
+ function hasEnabledAdmissionActions(value) {
13
+ if (!value || typeof value !== 'object' || Array.isArray(value))
14
+ return false;
15
+ return Object.values(value).some((enabled) => enabled === true);
16
+ }
17
+ function hasPreservableRuntimeState(value) {
18
+ if (!value || typeof value !== 'object' || Array.isArray(value))
19
+ return false;
20
+ const descriptor = value.runtimeDescriptor;
21
+ if (!descriptor || typeof descriptor !== 'object' || Array.isArray(descriptor))
22
+ return false;
23
+ const runtimeDescriptor = descriptor;
24
+ return hasNonEmptyArray(runtimeDescriptor.coreControls)
25
+ || hasNonEmptyArray(runtimeDescriptor.runtimeControls)
26
+ || hasNonEmptyArray(runtimeDescriptor.commands)
27
+ || hasNonEmptyArray(runtimeDescriptor.actions)
28
+ || hasNonEmptyArray(runtimeDescriptor.workspaceRoots)
29
+ || hasNonEmptyArray(runtimeDescriptor.writableRoots)
30
+ || hasEnabledAdmissionActions(runtimeDescriptor.admissionActions)
31
+ || runtimeDescriptor.streamingTextMode === 'delta'
32
+ || runtimeDescriptor.streamingTextMode === 'block';
33
+ }
9
34
  export function createRuntimeStatePublisher(options) {
10
35
  const { agentId, clientType, hostMode, rtdb } = options;
11
36
  const writePath = (path, data) => (rtdb ? rtdb.write(path, data) : rtdbWrite(path, data));
37
+ const readPath = (path) => (rtdb ? rtdb.read(path) : rtdbRead(path));
38
+ let lastPublishedRuntime = null;
12
39
  const readRuntimeActivityPath = (conversationId) => (rtdb
13
40
  ? rtdb.readRuntimeActivity(conversationId, agentId)
14
41
  : readRuntimeActivity(conversationId, agentId));
@@ -36,15 +63,26 @@ export function createRuntimeStatePublisher(options) {
36
63
  }
37
64
  return {
38
65
  async publishAgentRuntime(runtime) {
39
- await writePath(`/agent-runtime/${agentId}`, {
66
+ const payload = {
40
67
  clientType,
41
68
  hostMode,
42
69
  ...runtime,
43
70
  updatedAt: SERVER_TIMESTAMP,
44
- });
71
+ };
72
+ lastPublishedRuntime = payload;
73
+ await writePath(`/agent-runtime/${agentId}`, payload);
45
74
  },
46
75
  async clearAgentRuntime() {
47
- await writePath(`/agent-runtime/${agentId}`, null);
76
+ const path = `/agent-runtime/${agentId}`;
77
+ const current = lastPublishedRuntime ?? await readPath(path).catch(() => null);
78
+ if (hasPreservableRuntimeState(current)) {
79
+ await writePath(path, {
80
+ ...current,
81
+ updatedAt: 0,
82
+ });
83
+ return;
84
+ }
85
+ await writePath(path, null);
48
86
  },
49
87
  async writeSessionState(conversationId, state) {
50
88
  await (rtdb
package/dist/types.d.ts CHANGED
@@ -216,6 +216,8 @@ export interface ModelOption {
216
216
  value: string;
217
217
  label: string;
218
218
  description?: string;
219
+ /** This option may only be selected by the agent owner or the agent itself. */
220
+ ownerOnly?: boolean;
219
221
  workspaceRootId?: string;
220
222
  workspaceRelativePath?: string;
221
223
  source?: WorkspaceOptionSource;
@@ -640,6 +642,8 @@ export interface PermissionModeOption {
640
642
  value: string;
641
643
  label: string;
642
644
  description?: string;
645
+ /** Runtime-owned risk marker; Canon enforces owner-only selection generically. */
646
+ ownerOnly?: boolean;
643
647
  }
644
648
  export declare const CLAUDE_PERMISSION_MODE_OPTIONS: readonly [{
645
649
  readonly value: "default";
@@ -653,12 +657,15 @@ export declare const CLAUDE_PERMISSION_MODE_OPTIONS: readonly [{
653
657
  }, {
654
658
  readonly value: "dontAsk";
655
659
  readonly label: "Don't ask";
660
+ readonly ownerOnly: true;
656
661
  }, {
657
662
  readonly value: "bypassPermissions";
658
663
  readonly label: "Bypass";
664
+ readonly ownerOnly: true;
659
665
  }, {
660
666
  readonly value: "auto";
661
667
  readonly label: "Auto";
668
+ readonly ownerOnly: true;
662
669
  }];
663
670
  export interface AgentRuntime {
664
671
  clientType?: AgentClientType;
package/dist/types.js CHANGED
@@ -36,7 +36,7 @@ export const CLAUDE_PERMISSION_MODE_OPTIONS = [
36
36
  { value: 'default', label: 'Default' },
37
37
  { value: 'acceptEdits', label: 'Auto-edit' },
38
38
  { value: 'plan', label: 'Plan' },
39
- { value: 'dontAsk', label: "Don't ask" },
40
- { value: 'bypassPermissions', label: 'Bypass' },
41
- { value: 'auto', label: 'Auto' },
39
+ { value: 'dontAsk', label: "Don't ask", ownerOnly: true },
40
+ { value: 'bypassPermissions', label: 'Bypass', ownerOnly: true },
41
+ { value: 'auto', label: 'Auto', ownerOnly: true },
42
42
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonmsg/core",
3
- "version": "0.19.0",
3
+ "version": "0.19.1",
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",