@canonmsg/claude-code-plugin 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -3
- package/dist/host.js +82 -13
- package/dist/inbound-policy.d.ts +3 -1
- package/dist/inbound-policy.js +4 -1
- package/dist/register.js +3 -1
- package/dist/server.js +3 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ canon-register --name "My Claude" --description "My Claude Code agent" --phone "
|
|
|
15
15
|
canon-claude
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
Send a message to your agent in the Canon app. Claude Code responds with full capabilities (file read/write, bash, etc.).
|
|
18
|
+
Send a message to your agent in the Canon app. Claude Code responds with full capabilities (file read/write, bash, etc.). `canon-claude` is the local agent process. Keep that terminal open while you want Canon to reach the agent. Closing it, logging out, rebooting, or sleeping long enough to stop the process takes this local agent offline until you revive it.
|
|
19
19
|
|
|
20
20
|
After a restart or closed terminal, use the shared local manager to list and revive all recorded local agents:
|
|
21
21
|
|
|
@@ -25,6 +25,8 @@ canon-necromance
|
|
|
25
25
|
canon-necromance revive frontend
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
+
Public docs: <https://canonmail.com/agents/integrations>. Coding-host concepts: <https://canonmail.com/agents/coding-agents>.
|
|
29
|
+
|
|
28
30
|
## Features
|
|
29
31
|
|
|
30
32
|
- **Two-way messaging** — Messages from Canon flow to Claude Code and back
|
|
@@ -66,9 +68,19 @@ CANON_AGENT=frontend canon-claude --cwd ~/projects/frontend
|
|
|
66
68
|
|
|
67
69
|
## Channel mode (alternative)
|
|
68
70
|
|
|
69
|
-
For a lighter integration without session controls, run Canon as a channel plugin inside your own Claude Code session.
|
|
71
|
+
For a lighter integration without session controls, run Canon as a channel plugin inside your own Claude Code session. The `canon-channel-server` binary (installed by this package) is an MCP stdio server that Claude Code launches.
|
|
72
|
+
|
|
73
|
+
Register the channel server with Claude Code's MCP config and provide your Canon API key via the `CANON_API_KEY` environment variable:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Register once per Claude Code project
|
|
77
|
+
claude mcp add canon-channel canon-channel-server
|
|
78
|
+
|
|
79
|
+
# Then start Claude Code with your Canon key in the environment
|
|
80
|
+
CANON_API_KEY=agk_live_... claude
|
|
81
|
+
```
|
|
70
82
|
|
|
71
|
-
Channel mode
|
|
83
|
+
Channel mode forwards messages between Canon conversations and the embedded Claude Code session without managing session lifecycle. It is shown as non-revivable by `canon-necromance`. Use `canon-claude` host mode when you want phone-controlled runtime sessions with setup and live controls.
|
|
72
84
|
|
|
73
85
|
## Development
|
|
74
86
|
|
package/dist/host.js
CHANGED
|
@@ -26,7 +26,7 @@ import { execFileSync } from 'node:child_process';
|
|
|
26
26
|
import { existsSync } from 'node:fs';
|
|
27
27
|
import { query, } from '@anthropic-ai/claude-agent-sdk';
|
|
28
28
|
import { isAnthropicImageAttachment, materializeMessageMedia, toAnthropicImageBlock, } from '@canonmsg/agent-sdk';
|
|
29
|
-
import { CLAUDE_PERMISSION_MODE_OPTIONS, RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildCanonHostPrompt, buildConfiguredWorkspaceOptionsWithRoots, buildConversationEnvironmentKey, buildFirstPartyCodingRuntimeDescriptor, buildHydratedInboundContext, buildPlanApprovalRequest, buildQuestionRequest, buildPublicWorkspaceRoots, buildPublicWorkspaceOptions, createConversationMetadataLoader, createRuntimeStatePublisher, EXECUTION_ENVIRONMENT_MODES, CanonClient, CanonStream, DEFAULT_PARTICIPATION_HISTORY_FETCH_LIMIT, DEFAULT_RUNTIME_CAPABILITIES, HOST_ADMISSION_ACTIONS_DISABLED, ExecutionEnvironmentError, FINAL_MESSAGE_HANDOFF_MS, buildLocalRuntimeId, getActiveProfileLock, heartbeatLocalRuntimeEntry, normalizeTurnMetadata, prepareConversationEnvironment, resolveCanonAgent, initRTDBAuth, rtdbRead, rtdbWrite, loadHostSessionConfig, loadRuntimeSessionState, markLocalRuntimeStopped, releaseConversationEnvironment, saveRuntimeSessionState, clearRuntimeSessionState, publishHostAgentRuntime, publishHostSessionSnapshots, renderCanonHostInboundContent, resolveHostWorkspaceCwd, upsertLocalRuntimeEntry, } from '@canonmsg/core';
|
|
29
|
+
import { CLAUDE_PERMISSION_MODE_OPTIONS, RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildCanonHostPrompt, buildConfiguredWorkspaceOptionsWithRoots, buildConversationEnvironmentKey, buildFirstPartyCodingRuntimeDescriptor, buildHydratedInboundContext, diffCanonMemberIds, buildPlanApprovalRequest, buildQuestionRequest, buildPublicWorkspaceRoots, buildPublicWorkspaceOptions, createConversationMetadataLoader, createRuntimeStatePublisher, EXECUTION_ENVIRONMENT_MODES, CanonClient, CanonStream, DEFAULT_PARTICIPATION_HISTORY_FETCH_LIMIT, DEFAULT_RUNTIME_CAPABILITIES, HOST_ADMISSION_ACTIONS_DISABLED, ExecutionEnvironmentError, FINAL_MESSAGE_HANDOFF_MS, buildLocalRuntimeId, getActiveProfileLock, heartbeatLocalRuntimeEntry, normalizeTurnMetadata, prepareConversationEnvironment, resolveCanonAgent, initRTDBAuth, rtdbRead, rtdbWrite, loadHostSessionConfig, loadRuntimeSessionState, markLocalRuntimeStopped, releaseConversationEnvironment, saveRuntimeSessionState, clearRuntimeSessionState, publishHostAgentRuntime, publishHostSessionSnapshots, renderCanonHostInboundContent, resolveHostWorkspaceCwd, upsertLocalRuntimeEntry, } from '@canonmsg/core';
|
|
30
30
|
import { buildInboundContextLines, decideAutoReply, } from './inbound-policy.js';
|
|
31
31
|
import { createStreamingBuffer } from './streaming-buffer.js';
|
|
32
32
|
import { runCli } from './cli-entry.js';
|
|
@@ -51,7 +51,10 @@ EXAMPLES
|
|
|
51
51
|
canon-claude --cwd ~/dev/canon
|
|
52
52
|
canon-claude --cwd ~/dev/canon --workspace-root ~/dev
|
|
53
53
|
|
|
54
|
-
Keep this terminal open while you want Canon to reach the agent
|
|
54
|
+
Keep this terminal open while you want Canon to reach the agent. Closing it,
|
|
55
|
+
logging out, rebooting, or sleeping long enough to stop the process takes the
|
|
56
|
+
local agent offline until you revive it. Docs:
|
|
57
|
+
https://canonmail.com/agents/integrations`;
|
|
55
58
|
let workingDir = process.cwd();
|
|
56
59
|
let workspaceOptions = [];
|
|
57
60
|
let workspaceRoots = [];
|
|
@@ -785,6 +788,10 @@ function createSession(conversationId, environment, agentId, client, runtimeStat
|
|
|
785
788
|
function onStreamDelta(text) {
|
|
786
789
|
streamingBuffer.append(text);
|
|
787
790
|
}
|
|
791
|
+
function isActiveTurnInterrupted() {
|
|
792
|
+
const turnKey = session.activeInput?.turnKey;
|
|
793
|
+
return Boolean(turnKey && session.interruptedTurnKeys.has(turnKey));
|
|
794
|
+
}
|
|
788
795
|
function clearStreaming() {
|
|
789
796
|
streamingBuffer.clear();
|
|
790
797
|
runtimeState.clearStreaming(conversationId).catch(() => { });
|
|
@@ -1077,6 +1084,11 @@ function createSession(conversationId, environment, agentId, client, runtimeStat
|
|
|
1077
1084
|
}
|
|
1078
1085
|
case 'stream_event': {
|
|
1079
1086
|
const event = msg.event;
|
|
1087
|
+
if (isActiveTurnInterrupted()) {
|
|
1088
|
+
stopVisibleWorkSignal();
|
|
1089
|
+
client.setTyping(conversationId, false).catch(() => { });
|
|
1090
|
+
break;
|
|
1091
|
+
}
|
|
1080
1092
|
if (event?.type === 'content_block_start' && event.content_block?.type === 'tool_use') {
|
|
1081
1093
|
session.toolInProgress = true;
|
|
1082
1094
|
session.turnState = 'tool';
|
|
@@ -1313,10 +1325,12 @@ export async function main() {
|
|
|
1313
1325
|
initRTDBAuth(client);
|
|
1314
1326
|
let agentId;
|
|
1315
1327
|
let ownerId = null;
|
|
1328
|
+
let ownerName = null;
|
|
1316
1329
|
try {
|
|
1317
1330
|
const ctx = await client.getAgentMe();
|
|
1318
1331
|
agentId = ctx.agentId;
|
|
1319
1332
|
ownerId = ctx.ownerId;
|
|
1333
|
+
ownerName = ctx.ownerName;
|
|
1320
1334
|
console.error(`[canon-host] Connected as ${ctx.displayName || agentId}`);
|
|
1321
1335
|
}
|
|
1322
1336
|
catch {
|
|
@@ -1381,6 +1395,8 @@ export async function main() {
|
|
|
1381
1395
|
};
|
|
1382
1396
|
const conversationCache = new Map();
|
|
1383
1397
|
const knownConversationIds = new Set();
|
|
1398
|
+
const promptedGroupContextConversationIds = new Set();
|
|
1399
|
+
const pendingMembershipChanges = new Map();
|
|
1384
1400
|
let lastKnownConversationRefreshAt = 0;
|
|
1385
1401
|
const publishRuntimeHeartbeat = async () => {
|
|
1386
1402
|
heartbeatLocalRuntimeEntry(runtimeId, {
|
|
@@ -1533,18 +1549,65 @@ export async function main() {
|
|
|
1533
1549
|
}
|
|
1534
1550
|
lastKnownConversationRefreshAt = Date.now();
|
|
1535
1551
|
}
|
|
1552
|
+
function handleConversationUpdated(payload) {
|
|
1553
|
+
const rawMemberIds = payload.changes.memberIds;
|
|
1554
|
+
if (!Array.isArray(rawMemberIds))
|
|
1555
|
+
return;
|
|
1556
|
+
const memberIds = rawMemberIds.filter((id) => typeof id === 'string');
|
|
1557
|
+
const cached = conversationCache.get(payload.conversationId);
|
|
1558
|
+
const membershipChange = payload.membershipChange
|
|
1559
|
+
?? (cached ? diffCanonMemberIds(cached.memberIds, memberIds) : null);
|
|
1560
|
+
if (cached) {
|
|
1561
|
+
conversationCache.set(payload.conversationId, {
|
|
1562
|
+
...cached,
|
|
1563
|
+
memberIds,
|
|
1564
|
+
});
|
|
1565
|
+
}
|
|
1566
|
+
if (membershipChange) {
|
|
1567
|
+
pendingMembershipChanges.set(payload.conversationId, membershipChange);
|
|
1568
|
+
}
|
|
1569
|
+
if (!memberIds.includes(agentId)) {
|
|
1570
|
+
knownConversationIds.delete(payload.conversationId);
|
|
1571
|
+
conversationCache.delete(payload.conversationId);
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
function getGroupContextMode(conversationId, conversation) {
|
|
1575
|
+
if (conversation?.type !== 'group')
|
|
1576
|
+
return undefined;
|
|
1577
|
+
if (pendingMembershipChanges.has(conversationId))
|
|
1578
|
+
return 'membership_change';
|
|
1579
|
+
if (!promptedGroupContextConversationIds.has(conversationId))
|
|
1580
|
+
return 'initial';
|
|
1581
|
+
return undefined;
|
|
1582
|
+
}
|
|
1583
|
+
function markGroupContextModeUsed(conversationId, mode) {
|
|
1584
|
+
if (!mode)
|
|
1585
|
+
return;
|
|
1586
|
+
promptedGroupContextConversationIds.add(conversationId);
|
|
1587
|
+
if (mode === 'membership_change') {
|
|
1588
|
+
pendingMembershipChanges.delete(conversationId);
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1536
1591
|
async function loadHydratedInboundContext(input) {
|
|
1537
1592
|
const [conversation, page] = await Promise.all([
|
|
1538
1593
|
getConversationMeta(input.conversationId),
|
|
1539
|
-
|
|
1594
|
+
input.hydratedPage
|
|
1595
|
+
? Promise.resolve(input.hydratedPage)
|
|
1596
|
+
: client.getMessagesPage(input.conversationId, DEFAULT_PARTICIPATION_HISTORY_FETCH_LIMIT).catch(() => null),
|
|
1540
1597
|
]);
|
|
1541
1598
|
return buildHydratedInboundContext({
|
|
1542
1599
|
agentId,
|
|
1543
1600
|
conversation,
|
|
1544
1601
|
page,
|
|
1602
|
+
activeSelfContextId: input.activeSelfContextId,
|
|
1603
|
+
selfContexts: input.selfContexts,
|
|
1545
1604
|
message: input.message,
|
|
1546
1605
|
senderName: input.senderName,
|
|
1547
1606
|
isOwner: input.isOwner,
|
|
1607
|
+
ownerId,
|
|
1608
|
+
ownerName,
|
|
1609
|
+
membershipChange: pendingMembershipChanges.get(input.conversationId) ?? null,
|
|
1610
|
+
groupContextMode: getGroupContextMode(input.conversationId, conversation),
|
|
1548
1611
|
});
|
|
1549
1612
|
}
|
|
1550
1613
|
function closeSession(conversationId, options = {}) {
|
|
@@ -1779,15 +1842,18 @@ export async function main() {
|
|
|
1779
1842
|
message: m,
|
|
1780
1843
|
senderName: sender,
|
|
1781
1844
|
isOwner,
|
|
1845
|
+
hydratedPage: input.hydratedPage,
|
|
1782
1846
|
});
|
|
1783
1847
|
const behavior = input.hydratedPage?.behavior ?? hydrated.behavior;
|
|
1784
|
-
const
|
|
1848
|
+
const activeSelfContextId = hydrated.activeSelfContextId;
|
|
1849
|
+
const selfContexts = hydrated.selfContexts;
|
|
1785
1850
|
const participantContext = hydrated.participantContext;
|
|
1786
1851
|
const autoReply = decideAutoReply(participantContext, behavior);
|
|
1787
1852
|
if (!autoReply.allow) {
|
|
1788
1853
|
console.error(`[canon-host] [${input.conversationId.slice(0, 8)}] Suppressed recovered auto-reply: ${autoReply.reason}`);
|
|
1789
1854
|
return;
|
|
1790
1855
|
}
|
|
1856
|
+
markGroupContextModeUsed(input.conversationId, participantContext.groupContextMode);
|
|
1791
1857
|
let session;
|
|
1792
1858
|
try {
|
|
1793
1859
|
session = await getOrCreateSession(input.conversationId);
|
|
@@ -1797,7 +1863,7 @@ export async function main() {
|
|
|
1797
1863
|
const userMessage = error instanceof ExecutionEnvironmentError ? error.userMessage : message;
|
|
1798
1864
|
console.error(`[canon-host] [${input.conversationId.slice(0, 8)}] Failed to create recovered session: ${message}`);
|
|
1799
1865
|
await client.sendMessage(input.conversationId, `I couldn't start a coding session for this workspace: ${userMessage}`, {
|
|
1800
|
-
...(
|
|
1866
|
+
...(activeSelfContextId ? { selfContextId: activeSelfContextId } : {}),
|
|
1801
1867
|
metadata: {
|
|
1802
1868
|
turnSemantics: 'turn_complete',
|
|
1803
1869
|
turnComplete: true,
|
|
@@ -1807,7 +1873,7 @@ export async function main() {
|
|
|
1807
1873
|
return;
|
|
1808
1874
|
}
|
|
1809
1875
|
const turnMetadata = normalizeTurnMetadata(m.metadata);
|
|
1810
|
-
session.activeSelfContextId =
|
|
1876
|
+
session.activeSelfContextId = activeSelfContextId;
|
|
1811
1877
|
const deliveryIntent = turnMetadata?.deliveryIntent ?? 'queue';
|
|
1812
1878
|
const shouldMarkAccepted = turnMetadata?.inboundDisposition === 'queued';
|
|
1813
1879
|
const promptText = buildCanonPrompt({
|
|
@@ -1925,19 +1991,19 @@ export async function main() {
|
|
|
1925
1991
|
message: m,
|
|
1926
1992
|
senderName: sender,
|
|
1927
1993
|
isOwner,
|
|
1994
|
+
activeSelfContextId: payload.activeSelfContextId,
|
|
1995
|
+
selfContexts: payload.selfContexts,
|
|
1928
1996
|
});
|
|
1929
1997
|
const behavior = payload.behavior ?? hydrated.behavior;
|
|
1930
|
-
const
|
|
1931
|
-
|
|
1932
|
-
: Array.isArray(payload.selfContexts)
|
|
1933
|
-
? payload.selfContexts
|
|
1934
|
-
: hydrated.selfContexts;
|
|
1998
|
+
const activeSelfContextId = hydrated.activeSelfContextId;
|
|
1999
|
+
const selfContexts = hydrated.selfContexts;
|
|
1935
2000
|
const participantContext = hydrated.participantContext;
|
|
1936
2001
|
const autoReply = decideAutoReply(participantContext, behavior);
|
|
1937
2002
|
if (!autoReply.allow) {
|
|
1938
2003
|
console.error(`[canon-host] [${convoId.slice(0, 8)}] Suppressed auto-reply: ${autoReply.reason}`);
|
|
1939
2004
|
return;
|
|
1940
2005
|
}
|
|
2006
|
+
markGroupContextModeUsed(convoId, participantContext.groupContextMode);
|
|
1941
2007
|
console.error(`[canon-host] [${convoId.slice(0, 8)}] Message from ${sender}: "${content.slice(0, 80)}" (${autoReply.reason})`);
|
|
1942
2008
|
let session;
|
|
1943
2009
|
try {
|
|
@@ -1948,7 +2014,7 @@ export async function main() {
|
|
|
1948
2014
|
const userMessage = error instanceof ExecutionEnvironmentError ? error.userMessage : message;
|
|
1949
2015
|
console.error(`[canon-host] [${convoId.slice(0, 8)}] Failed to create session: ${message}`);
|
|
1950
2016
|
await client.sendMessage(convoId, `I couldn't start a coding session for this workspace: ${userMessage}`, {
|
|
1951
|
-
...(
|
|
2017
|
+
...(activeSelfContextId ? { selfContextId: activeSelfContextId } : {}),
|
|
1952
2018
|
metadata: {
|
|
1953
2019
|
turnSemantics: 'turn_complete',
|
|
1954
2020
|
turnComplete: true,
|
|
@@ -1958,7 +2024,7 @@ export async function main() {
|
|
|
1958
2024
|
return;
|
|
1959
2025
|
}
|
|
1960
2026
|
const turnMetadata = normalizeTurnMetadata(m.metadata);
|
|
1961
|
-
session.activeSelfContextId =
|
|
2027
|
+
session.activeSelfContextId = activeSelfContextId;
|
|
1962
2028
|
const deliveryIntent = turnMetadata?.deliveryIntent ?? 'queue';
|
|
1963
2029
|
const shouldMarkAccepted = turnMetadata?.inboundDisposition === 'queued';
|
|
1964
2030
|
const promptText = buildCanonPrompt({
|
|
@@ -1987,6 +2053,9 @@ export async function main() {
|
|
|
1987
2053
|
}
|
|
1988
2054
|
})();
|
|
1989
2055
|
},
|
|
2056
|
+
onConversationUpdated: (payload) => {
|
|
2057
|
+
handleConversationUpdated(payload);
|
|
2058
|
+
},
|
|
1990
2059
|
onConnected: () => {
|
|
1991
2060
|
streamConnected = true;
|
|
1992
2061
|
void publishRuntimeHeartbeat();
|
package/dist/inbound-policy.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type CanonConversation, type ResolvedAgentBehaviorPolicy } from '@canonmsg/core';
|
|
1
|
+
import { type CanonGroupContext, type CanonGroupContextMode, type CanonConversation, type ResolvedAgentBehaviorPolicy } from '@canonmsg/core';
|
|
2
2
|
export interface InboundParticipantContext {
|
|
3
3
|
conversationType: CanonConversation['type'] | 'unknown';
|
|
4
4
|
memberCount: number | null;
|
|
@@ -6,6 +6,8 @@ export interface InboundParticipantContext {
|
|
|
6
6
|
senderName: string;
|
|
7
7
|
isOwner: boolean;
|
|
8
8
|
mentionedAgent: boolean;
|
|
9
|
+
groupContext?: CanonGroupContext;
|
|
10
|
+
groupContextMode?: CanonGroupContextMode;
|
|
9
11
|
recentSenderTypes: Array<'human' | 'ai_agent'>;
|
|
10
12
|
recentHumanCount: number;
|
|
11
13
|
recentAgentCount: number;
|
package/dist/inbound-policy.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { evaluateParticipationPolicy, resolveAgentBehaviorPolicy, } from '@canonmsg/core';
|
|
1
|
+
import { buildCompactGroupContextLines, evaluateParticipationPolicy, resolveAgentBehaviorPolicy, } from '@canonmsg/core';
|
|
2
2
|
function formatRecentSenders(senderTypes) {
|
|
3
3
|
if (senderTypes.length === 0)
|
|
4
4
|
return 'none';
|
|
@@ -18,6 +18,9 @@ export function buildInboundContextLines(context) {
|
|
|
18
18
|
`Latest sender name: ${context.senderName}`,
|
|
19
19
|
`Latest sender type: ${context.senderType}`,
|
|
20
20
|
`Conversation type: ${conversationTypeLabel}`,
|
|
21
|
+
...(context.groupContext && context.groupContextMode
|
|
22
|
+
? buildCompactGroupContextLines(context.groupContext, context.groupContextMode)
|
|
23
|
+
: []),
|
|
21
24
|
`Directly addressed to this agent: ${context.mentionedAgent ? 'yes' : 'no'}`,
|
|
22
25
|
`Recent sender pattern: ${formatRecentSenders(context.recentSenderTypes)}`,
|
|
23
26
|
`Recent human messages: ${context.recentHumanCount}`,
|
package/dist/register.js
CHANGED
|
@@ -107,7 +107,9 @@ export async function main() {
|
|
|
107
107
|
console.log(`Approved! Agent: ${result.agentName} (${result.agentId})`);
|
|
108
108
|
console.log(`Saved as profile "${profileName}" in ~/.canon/agents.json`);
|
|
109
109
|
console.log('Start it with: CANON_AGENT=' + profileName + ' canon-claude --cwd /path/to/project');
|
|
110
|
-
console.log('Keep that terminal open
|
|
110
|
+
console.log('Keep that terminal open while you want Canon to reach the agent.');
|
|
111
|
+
console.log('Closing it, logging out, rebooting, or sleeping long enough to stop the process takes this local agent offline until you revive it.');
|
|
112
|
+
console.log('Docs: https://canonmail.com/agents/integrations');
|
|
111
113
|
break;
|
|
112
114
|
}
|
|
113
115
|
case 'rejected':
|
package/dist/server.js
CHANGED
|
@@ -447,6 +447,9 @@ async function handleInboundMessage(payload) {
|
|
|
447
447
|
}
|
|
448
448
|
}
|
|
449
449
|
if (Array.isArray(payload.selfContexts) && payload.selfContexts.length > 0) {
|
|
450
|
+
if (payload.activeSelfContextId) {
|
|
451
|
+
meta.active_self_context_id = payload.activeSelfContextId;
|
|
452
|
+
}
|
|
450
453
|
meta.self_context_ids = payload.selfContexts
|
|
451
454
|
.map((selfContext) => selfContext.id)
|
|
452
455
|
.join('\n');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonmsg/claude-code-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.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/index.js",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@anthropic-ai/claude-agent-sdk": "^0.2.101",
|
|
34
|
-
"@canonmsg/agent-sdk": "^1.
|
|
35
|
-
"@canonmsg/core": "^0.
|
|
34
|
+
"@canonmsg/agent-sdk": "^1.3.0",
|
|
35
|
+
"@canonmsg/core": "^0.17.0",
|
|
36
36
|
"@modelcontextprotocol/sdk": "^1.12.0"
|
|
37
37
|
},
|
|
38
38
|
"engines": {
|