@canonmsg/claude-code-plugin 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/host.js CHANGED
@@ -152,7 +152,7 @@ function renderInboundContent(message) {
152
152
  return content || '[Empty message]';
153
153
  }
154
154
  // ── Session factory ─────────────────────────────────────────────────
155
- function createSession(conversationId, environment, agentId, client, onSessionEnd, config, resumeSessionId) {
155
+ function createSession(conversationId, environment, agentId, client, onSessionEnd, onRuntimeDescriptorUpdate, config, resumeSessionId) {
156
156
  const { cwd } = environment;
157
157
  // Per-session input stream with message queue
158
158
  let resolveInput = null;
@@ -649,13 +649,13 @@ function createSession(conversationId, environment, agentId, client, onSessionEn
649
649
  const modelList = toModelOptions(models);
650
650
  session.availableModels = modelList;
651
651
  runtimeModels = modelList;
652
- await publishAgentRuntime(agentId, {
652
+ onRuntimeDescriptorUpdate({
653
653
  defaultWorkspaceId: workspaceOptions[0]?.id,
654
654
  defaultModel: session.state.model ?? modelList[0]?.value,
655
655
  defaultPermissionMode: 'default',
656
656
  availableModels: modelList,
657
657
  availableWorkspaces: buildPublicWorkspaceOptions(workspaceOptions),
658
- }).catch(() => { });
658
+ });
659
659
  writeSessionState(conversationId, agentId, {
660
660
  ...session.state,
661
661
  availableModels: modelList,
@@ -716,19 +716,36 @@ async function main() {
716
716
  }
717
717
  console.error(`[canon-host] Authenticated as ${agentId}`);
718
718
  }
719
+ let streamConnected = false;
720
+ let runtimeDescriptor = {
721
+ defaultWorkspaceId: workspaceOptions[0]?.id,
722
+ defaultPermissionMode: 'default',
723
+ availableWorkspaces: buildPublicWorkspaceOptions(workspaceOptions),
724
+ };
725
+ const publishRuntimeHeartbeat = async () => {
726
+ if (!streamConnected)
727
+ return;
728
+ await publishAgentRuntime(agentId, runtimeDescriptor).catch((error) => {
729
+ console.error('[canon-host] Failed to publish agent runtime:', error);
730
+ });
731
+ };
719
732
  // ── Load conversations (informational — sessions created on demand) ──
720
733
  try {
721
734
  runtimeModels = await detectRuntimeModels(workingDir);
722
- await publishAgentRuntime(agentId, {
735
+ runtimeDescriptor = {
723
736
  defaultWorkspaceId: workspaceOptions[0]?.id,
724
737
  defaultModel: runtimeModels[0]?.value,
725
738
  defaultPermissionMode: 'default',
726
739
  availableModels: runtimeModels,
727
740
  availableWorkspaces: buildPublicWorkspaceOptions(workspaceOptions),
728
- });
741
+ };
729
742
  }
730
- catch (error) {
731
- console.error('[canon-host] Failed to publish agent runtime:', error);
743
+ catch {
744
+ runtimeDescriptor = {
745
+ defaultWorkspaceId: workspaceOptions[0]?.id,
746
+ defaultPermissionMode: 'default',
747
+ availableWorkspaces: buildPublicWorkspaceOptions(workspaceOptions),
748
+ };
732
749
  }
733
750
  try {
734
751
  const convos = await client.getConversations();
@@ -869,6 +886,9 @@ async function main() {
869
886
  sessions.delete(convoId);
870
887
  clearSessionState(convoId, agentId).catch(() => { });
871
888
  clearTurnState(convoId, agentId).catch(() => { });
889
+ }, (descriptor) => {
890
+ runtimeDescriptor = descriptor;
891
+ void publishRuntimeHeartbeat();
872
892
  }, {
873
893
  model: config?.model ?? runtimeModels[0]?.value,
874
894
  permissionMode: config?.permissionMode ?? 'default',
@@ -959,8 +979,16 @@ async function main() {
959
979
  }, deliveryIntent, m.id ?? null, shouldMarkAccepted);
960
980
  })();
961
981
  },
962
- onConnected: () => console.error('[canon-host] SSE connected'),
963
- onDisconnected: () => console.error('[canon-host] SSE disconnected'),
982
+ onConnected: () => {
983
+ streamConnected = true;
984
+ void publishRuntimeHeartbeat();
985
+ console.error('[canon-host] SSE connected');
986
+ },
987
+ onDisconnected: () => {
988
+ streamConnected = false;
989
+ rtdbWrite(`/agent-runtime/${agentId}`, null).catch(() => { });
990
+ console.error('[canon-host] SSE disconnected');
991
+ },
964
992
  onError: (err) => console.error(`[canon-host] SSE error: ${err.message}`),
965
993
  },
966
994
  });
@@ -1095,6 +1123,7 @@ async function main() {
1095
1123
  : {}),
1096
1124
  }).catch(() => { });
1097
1125
  }
1126
+ void publishRuntimeHeartbeat();
1098
1127
  }, HEARTBEAT_MS);
1099
1128
  // ── Idle session cleanup ──
1100
1129
  const idleCheck = setInterval(() => {
@@ -1116,6 +1145,7 @@ async function main() {
1116
1145
  clearInterval(heartbeat);
1117
1146
  clearInterval(idleCheck);
1118
1147
  stream.stop();
1148
+ await rtdbWrite(`/agent-runtime/${agentId}`, null).catch(() => { });
1119
1149
  for (const convoId of [...sessions.keys()]) {
1120
1150
  closeSession(convoId);
1121
1151
  }
package/dist/register.js CHANGED
@@ -33,6 +33,14 @@ if (!values.name || !values.description || !values.phone) {
33
33
  }
34
34
  // Default profile name: sanitized agent name
35
35
  const profileName = values.profile || values.name.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-');
36
+ let existingAgentId;
37
+ try {
38
+ const profiles = JSON.parse(readFileSync(AGENTS_PATH, 'utf-8'));
39
+ existingAgentId = profiles[profileName]?.agentId;
40
+ }
41
+ catch {
42
+ // File doesn't exist yet
43
+ }
36
44
  console.log(`Registering agent "${values.name}" (profile: ${profileName})...`);
37
45
  const result = await registerAndWaitForApproval({
38
46
  name: values.name,
@@ -41,6 +49,7 @@ const result = await registerAndWaitForApproval({
41
49
  developerInfo: 'Claude Code plugin',
42
50
  clientType: 'claude-code',
43
51
  baseUrl: values['base-url'],
52
+ requestedAgentId: existingAgentId,
44
53
  }, {
45
54
  onSubmitted: (requestId) => {
46
55
  console.log(`Registration submitted (request ID: ${requestId}).`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonmsg/claude-code-plugin",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Canon channel plugin for Claude Code — messaging where AI agents are first-class citizens",
5
5
  "type": "module",
6
6
  "main": "dist/server.js",
@@ -22,7 +22,7 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "@anthropic-ai/claude-agent-sdk": "^0.2.101",
25
- "@canonmsg/core": "^0.4.0",
25
+ "@canonmsg/core": "^0.5.0",
26
26
  "@modelcontextprotocol/sdk": "^1.12.0"
27
27
  },
28
28
  "engines": {