@canonmsg/claude-code-plugin 0.34.1 → 0.34.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.
- package/.claude-plugin/plugin.json +1 -1
- package/dist/host.js +38 -190
- package/package.json +3 -3
package/dist/host.js
CHANGED
|
@@ -29,7 +29,7 @@ import { query, } from '@anthropic-ai/claude-agent-sdk';
|
|
|
29
29
|
import { materializeMessageMedia, materializeReplyContextMedia, sendMediaFileMessage, } from '@canonmsg/agent-sdk';
|
|
30
30
|
import { captureTurnArtifactSnapshot, createTurnArtifactRouter, IDLE_TIMEOUT_MS, collectMissedInboundMessages, createRecoveryCheckpointTracker, createReconnectRecoveryCoordinator, STARTUP_RECOVERY_PAGE_SIZE, } from '@canonmsg/coding-agent-host';
|
|
31
31
|
import { buildCanonUserContent, renderClaudeInboundContent, withClaudeReplyContextMediaReferences, } from './canon-user-content.js';
|
|
32
|
-
import { EFFORT_OPTIONS, CLAUDE_PERMISSION_MODE_OPTIONS, RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildCanonInboundFrameV1, buildCanonTurnContextV2, buildConfiguredWorkspaceOptionsWithRoots, buildConversationEnvironmentKey, buildFirstPartyCodingRuntimeDescriptor, buildHydratedInboundContext, diffCanonMemberIds, buildPublicWorkspaceRoots, buildPublicWorkspaceOptions, buildRuntimePresentationPolicy, normalizeRuntimeCommandDescriptors, DEFAULT_FIRST_PARTY_RUNTIME_PRESENTATION, createConversationMetadataLoader, createTurnOutputController, createRuntimeStatePublisher, createTypingStatusPublisher, EXECUTION_ENVIRONMENT_MODES, ExecutionEnvironmentError, CanonClient, CanonStream, ControlChannelPoller, DEFAULT_PARTICIPATION_HISTORY_FETCH_LIMIT, DEFAULT_RUNTIME_CAPABILITIES, HOST_ADMISSION_ACTIONS_DISABLED, ApprovalManager, RuntimeRequestManager, FINAL_MESSAGE_HANDOFF_MS, buildLocalRuntimeId, getActiveProfileLock, heartbeatLocalRuntimeEntry, normalizeTurnMetadata, parseTurnVerbosityConfig, prepareConversationEnvironment, resolveCanonAgent, verifyResolvedAgentEnvironment, decideAutoReply, initRTDBAuth, isChunkedSendMessageError, sendMessageWithRetry, sendMessageWithRetryChunked, loadRuntimeSessionState, markLocalRuntimeStopped, releaseConversationEnvironment, resolveLocalRuntimeSessionState, saveRuntimeSessionState, clearRuntimeSessionState,
|
|
32
|
+
import { EFFORT_OPTIONS, CLAUDE_PERMISSION_MODE_OPTIONS, RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildCanonInboundFrameV1, buildCanonTurnContextV2, buildConfiguredWorkspaceOptionsWithRoots, buildConversationEnvironmentKey, buildFirstPartyCodingRuntimeDescriptor, buildHydratedInboundContext, diffCanonMemberIds, buildPublicWorkspaceRoots, buildPublicWorkspaceOptions, buildRuntimePresentationPolicy, normalizeRuntimeCommandDescriptors, DEFAULT_FIRST_PARTY_RUNTIME_PRESENTATION, createConversationMetadataLoader, createTurnOutputController, createRuntimeStatePublisher, createRuntimeHeartbeat, createTypingStatusPublisher, EXECUTION_ENVIRONMENT_MODES, ExecutionEnvironmentError, CanonClient, CanonStream, ControlChannelPoller, DEFAULT_PARTICIPATION_HISTORY_FETCH_LIMIT, DEFAULT_RUNTIME_CAPABILITIES, HOST_ADMISSION_ACTIONS_DISABLED, ApprovalManager, RuntimeRequestManager, FINAL_MESSAGE_HANDOFF_MS, buildLocalRuntimeId, getActiveProfileLock, heartbeatLocalRuntimeEntry, normalizeTurnMetadata, parseTurnVerbosityConfig, prepareConversationEnvironment, resolveCanonAgent, verifyResolvedAgentEnvironment, decideAutoReply, initRTDBAuth, isChunkedSendMessageError, sendMessageWithRetry, sendMessageWithRetryChunked, loadRuntimeSessionState, markLocalRuntimeStopped, releaseConversationEnvironment, resolveLocalRuntimeSessionState, saveRuntimeSessionState, clearRuntimeSessionState, publishHostSessionSnapshots, renderCodingHostInboundPrompt, resolveConfiguredWorkspaceCwd, resolveTurnVerbosity, shouldTriggerAgentTurn, upsertLocalRuntimeEntry, } from '@canonmsg/core';
|
|
33
33
|
import { runCli } from '@canonmsg/core';
|
|
34
34
|
import { CANON_VERB_MCP_SERVER_NAME, createCanonVerbMcpServer } from '@canonmsg/agent-tools';
|
|
35
35
|
import { synthesizeClaudeApprovalDiff } from './approval-diff.js';
|
|
@@ -414,9 +414,6 @@ function acceptClaudeCli(source, cliPath) {
|
|
|
414
414
|
function toModelOptions(models) {
|
|
415
415
|
return models.map(claudeModelInfoToOption);
|
|
416
416
|
}
|
|
417
|
-
async function publishAgentRuntime(agentId, runtime, rtdb) {
|
|
418
|
-
await publishHostAgentRuntime(agentId, 'claude-code', runtime, rtdb);
|
|
419
|
-
}
|
|
420
417
|
export function resolveSessionExecutionMode(defaultExecutionMode = 'worktree') {
|
|
421
418
|
return defaultExecutionMode;
|
|
422
419
|
}
|
|
@@ -434,14 +431,6 @@ function resolveWorkspaceCwd() {
|
|
|
434
431
|
defaultCwd: workingDir,
|
|
435
432
|
});
|
|
436
433
|
}
|
|
437
|
-
function resolveExecutionFallbackReason(environment) {
|
|
438
|
-
if (!environment?.reason || environment.mode !== 'locked') {
|
|
439
|
-
return null;
|
|
440
|
-
}
|
|
441
|
-
return environment.reason === 'Sharing the base workspace (locked mode)'
|
|
442
|
-
? null
|
|
443
|
-
: environment.reason;
|
|
444
|
-
}
|
|
445
434
|
async function detectRuntimeModels(cwd) {
|
|
446
435
|
const discovered = await detectRuntimeModelsForSelection(cwd, 'default');
|
|
447
436
|
const supplemental = await detectSupplementalRuntimeModels(cwd, deriveClaudeSupplementalModelProbes(discovered));
|
|
@@ -562,147 +551,6 @@ async function readApprovalDiffPreImage(filePath) {
|
|
|
562
551
|
throw error;
|
|
563
552
|
}
|
|
564
553
|
}
|
|
565
|
-
function mapClaudeMcpStatus(status) {
|
|
566
|
-
switch (status) {
|
|
567
|
-
case 'connected':
|
|
568
|
-
return 'ready';
|
|
569
|
-
case 'needs-auth':
|
|
570
|
-
return 'auth_needed';
|
|
571
|
-
case 'disabled':
|
|
572
|
-
return 'configured';
|
|
573
|
-
case 'failed':
|
|
574
|
-
return 'error';
|
|
575
|
-
default:
|
|
576
|
-
return 'unknown';
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
function buildClaudeRuntimeInfo(input) {
|
|
580
|
-
const { descriptor, metadata } = input;
|
|
581
|
-
const statusItems = [
|
|
582
|
-
metadata.account?.email
|
|
583
|
-
? {
|
|
584
|
-
id: 'account',
|
|
585
|
-
label: 'Account',
|
|
586
|
-
value: 'Connected',
|
|
587
|
-
tone: 'success',
|
|
588
|
-
tier: 'diagnostic',
|
|
589
|
-
}
|
|
590
|
-
: null,
|
|
591
|
-
metadata.account?.subscriptionType
|
|
592
|
-
? {
|
|
593
|
-
id: 'subscription',
|
|
594
|
-
label: 'Plan',
|
|
595
|
-
value: metadata.account.subscriptionType,
|
|
596
|
-
}
|
|
597
|
-
: null,
|
|
598
|
-
metadata.account?.apiProvider
|
|
599
|
-
? {
|
|
600
|
-
id: 'provider',
|
|
601
|
-
label: 'Provider',
|
|
602
|
-
value: metadata.account.apiProvider,
|
|
603
|
-
}
|
|
604
|
-
: null,
|
|
605
|
-
metadata.account?.tokenSource || metadata.account?.apiKeySource
|
|
606
|
-
? {
|
|
607
|
-
id: 'auth',
|
|
608
|
-
label: 'Auth',
|
|
609
|
-
value: metadata.account.tokenSource ?? metadata.account?.apiKeySource ?? 'connected',
|
|
610
|
-
tier: 'diagnostic',
|
|
611
|
-
}
|
|
612
|
-
: null,
|
|
613
|
-
runtimeModels[0]
|
|
614
|
-
? {
|
|
615
|
-
id: 'fallbackModel',
|
|
616
|
-
label: 'Fallback model',
|
|
617
|
-
value: runtimeModels[0].label,
|
|
618
|
-
tier: 'diagnostic',
|
|
619
|
-
source: 'host-default',
|
|
620
|
-
}
|
|
621
|
-
: null,
|
|
622
|
-
{
|
|
623
|
-
id: 'toolPolicy',
|
|
624
|
-
label: 'Tool policy',
|
|
625
|
-
value: 'Claude Code preset',
|
|
626
|
-
tier: 'detail',
|
|
627
|
-
},
|
|
628
|
-
{
|
|
629
|
-
id: 'browser',
|
|
630
|
-
label: 'Browser tools',
|
|
631
|
-
value: 'Runtime policy',
|
|
632
|
-
tier: 'detail',
|
|
633
|
-
},
|
|
634
|
-
{
|
|
635
|
-
id: 'mediaOut',
|
|
636
|
-
label: 'Media out',
|
|
637
|
-
value: 'Generated media artifacts',
|
|
638
|
-
tier: 'detail',
|
|
639
|
-
},
|
|
640
|
-
].filter((item) => Boolean(item));
|
|
641
|
-
return {
|
|
642
|
-
descriptor,
|
|
643
|
-
surfaceMode: 'host',
|
|
644
|
-
statusItems,
|
|
645
|
-
inventories: [
|
|
646
|
-
{
|
|
647
|
-
id: 'mcp',
|
|
648
|
-
label: 'MCP',
|
|
649
|
-
entries: metadata.mcpServers.map((server) => ({
|
|
650
|
-
id: server.name,
|
|
651
|
-
label: server.name,
|
|
652
|
-
status: mapClaudeMcpStatus(server.status),
|
|
653
|
-
description: server.error
|
|
654
|
-
?? server.serverInfo?.version
|
|
655
|
-
?? server.scope
|
|
656
|
-
?? undefined,
|
|
657
|
-
})),
|
|
658
|
-
tier: 'diagnostic',
|
|
659
|
-
},
|
|
660
|
-
{
|
|
661
|
-
id: 'plugins',
|
|
662
|
-
label: 'Plugins',
|
|
663
|
-
entries: metadata.plugins.map((plugin) => ({
|
|
664
|
-
id: plugin.name,
|
|
665
|
-
label: plugin.name,
|
|
666
|
-
status: 'configured',
|
|
667
|
-
description: plugin.source ?? plugin.path,
|
|
668
|
-
})),
|
|
669
|
-
tier: 'diagnostic',
|
|
670
|
-
},
|
|
671
|
-
{
|
|
672
|
-
id: 'commands',
|
|
673
|
-
label: 'Commands',
|
|
674
|
-
entries: metadata.commands.map((command) => ({
|
|
675
|
-
id: command.name,
|
|
676
|
-
label: command.name.startsWith('/') ? command.name : `/${command.name}`,
|
|
677
|
-
status: 'configured',
|
|
678
|
-
description: command.description ?? command.argumentHint ?? undefined,
|
|
679
|
-
})),
|
|
680
|
-
tier: 'diagnostic',
|
|
681
|
-
},
|
|
682
|
-
{
|
|
683
|
-
id: 'agents',
|
|
684
|
-
label: 'Agents',
|
|
685
|
-
entries: metadata.agents.map((agent) => ({
|
|
686
|
-
id: agent.name,
|
|
687
|
-
label: agent.name,
|
|
688
|
-
status: 'configured',
|
|
689
|
-
description: agent.description ?? agent.model ?? undefined,
|
|
690
|
-
})),
|
|
691
|
-
tier: 'diagnostic',
|
|
692
|
-
},
|
|
693
|
-
],
|
|
694
|
-
execution: {
|
|
695
|
-
resolvedWorkspaceLabel: input.workspaceLabel,
|
|
696
|
-
resolvedCwd: input.resolvedCwd,
|
|
697
|
-
workspaceRootId: input.workspaceRootId ?? null,
|
|
698
|
-
workspaceRelativePath: input.workspaceRelativePath ?? null,
|
|
699
|
-
executionMode: input.executionMode,
|
|
700
|
-
executionBranch: input.executionBranch,
|
|
701
|
-
worktreePath: input.worktreePath,
|
|
702
|
-
fallbackReason: input.fallbackReason,
|
|
703
|
-
},
|
|
704
|
-
};
|
|
705
|
-
}
|
|
706
554
|
// ── Constants ───────────────────────────────────────────────────────
|
|
707
555
|
const MAX_SESSIONS = 5;
|
|
708
556
|
// IDLE_TIMEOUT_MS (30 minutes) is shared with the other coding-agent hosts.
|
|
@@ -2529,29 +2377,29 @@ export async function main() {
|
|
|
2529
2377
|
console.error('[canon-host] Failed to publish session snapshots:', error);
|
|
2530
2378
|
});
|
|
2531
2379
|
}
|
|
2532
|
-
const
|
|
2380
|
+
const publishLocalHeartbeat = () => {
|
|
2533
2381
|
heartbeatLocalRuntimeEntry(runtimeId, {
|
|
2534
2382
|
agentId,
|
|
2535
2383
|
agentName: profileAgentName,
|
|
2536
2384
|
cwd: workingDir,
|
|
2537
2385
|
baseCwd: workingDir,
|
|
2538
2386
|
});
|
|
2539
|
-
|
|
2540
|
-
|
|
2387
|
+
};
|
|
2388
|
+
const refreshRuntimeDetails = async (signal) => {
|
|
2541
2389
|
await refreshKnownConversationIds().catch((error) => {
|
|
2542
2390
|
console.error('[canon-host] Failed to refresh known conversations:', error);
|
|
2543
2391
|
});
|
|
2392
|
+
if (signal.aborted)
|
|
2393
|
+
return;
|
|
2544
2394
|
const activeSessionQuery = sessions.values().next().value?.query ?? null;
|
|
2545
|
-
|
|
2395
|
+
await refreshClaudeRuntimeMetadata({
|
|
2546
2396
|
cwd: workingDir,
|
|
2547
2397
|
activeQuery: activeSessionQuery,
|
|
2548
2398
|
}).catch((error) => {
|
|
2549
2399
|
console.error('[canon-host] Failed to refresh Claude runtime metadata:', error);
|
|
2550
|
-
return runtimeMetadata;
|
|
2551
|
-
});
|
|
2552
|
-
await publishAgentRuntime(agentId, runtimeDescriptor, rtdb).catch((error) => {
|
|
2553
|
-
console.error('[canon-host] Failed to publish agent runtime:', error);
|
|
2554
2400
|
});
|
|
2401
|
+
if (signal.aborted)
|
|
2402
|
+
return;
|
|
2555
2403
|
await publishSessionSnapshots(Array.from(knownConversationIds));
|
|
2556
2404
|
// Rebuild so the descriptor picks up native slash commands from the
|
|
2557
2405
|
// metadata refresh above — the initial descriptor is built before the
|
|
@@ -2569,32 +2417,34 @@ export async function main() {
|
|
|
2569
2417
|
}),
|
|
2570
2418
|
};
|
|
2571
2419
|
}
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
? resolveWorkspaceIdForBaseCwd(session.environment.baseCwd)
|
|
2576
|
-
: runtimeDescriptor.defaultWorkspaceId;
|
|
2577
|
-
const workspace = workspaceOptions.find((option) => option.id === workspaceId) ?? null;
|
|
2420
|
+
if (signal.aborted)
|
|
2421
|
+
return;
|
|
2422
|
+
const results = await Promise.allSettled(Array.from(knownConversationIds).map(async (conversationId) => {
|
|
2578
2423
|
const descriptor = runtimeDescriptor.runtimeDescriptor;
|
|
2579
2424
|
if (!descriptor)
|
|
2580
2425
|
return;
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
executionBranch: session?.environment.branch ?? null,
|
|
2590
|
-
worktreePath: session?.environment.worktreePath ?? null,
|
|
2591
|
-
fallbackReason: resolveExecutionFallbackReason(session?.environment),
|
|
2426
|
+
await runtimeState.writeRuntimeInfo(conversationId, {
|
|
2427
|
+
surfaceMode: 'host',
|
|
2428
|
+
descriptor: {
|
|
2429
|
+
coreControls: [],
|
|
2430
|
+
supportsInterrupt: descriptor.supportsInterrupt,
|
|
2431
|
+
supportsInputInterrupt: descriptor.supportsInputInterrupt,
|
|
2432
|
+
streamingTextMode: descriptor.streamingTextMode,
|
|
2433
|
+
},
|
|
2592
2434
|
});
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2435
|
+
}));
|
|
2436
|
+
const failure = results.find((result) => result.status === 'rejected');
|
|
2437
|
+
if (failure?.status === 'rejected')
|
|
2438
|
+
throw failure.reason;
|
|
2597
2439
|
};
|
|
2440
|
+
const runtimeHeartbeat = createRuntimeHeartbeat({
|
|
2441
|
+
publisher: runtimeState,
|
|
2442
|
+
getRuntime: () => runtimeDescriptor,
|
|
2443
|
+
refreshDetails: refreshRuntimeDetails,
|
|
2444
|
+
onError: (error, operation) => {
|
|
2445
|
+
console.error(`[canon-host] Runtime ${operation} failed:`, error);
|
|
2446
|
+
},
|
|
2447
|
+
});
|
|
2598
2448
|
// ── Load conversations (informational — sessions created on demand) ──
|
|
2599
2449
|
try {
|
|
2600
2450
|
runtimeModels = await detectRuntimeModels(workingDir);
|
|
@@ -2706,9 +2556,6 @@ export async function main() {
|
|
|
2706
2556
|
client,
|
|
2707
2557
|
conversationCache,
|
|
2708
2558
|
});
|
|
2709
|
-
function resolveWorkspaceIdForBaseCwd(baseCwd) {
|
|
2710
|
-
return workspaceOptions.find((option) => option.cwd === baseCwd)?.id;
|
|
2711
|
-
}
|
|
2712
2559
|
async function refreshKnownConversationIds(force = false) {
|
|
2713
2560
|
if (!force && Date.now() - lastKnownConversationRefreshAt < HEARTBEAT_MS) {
|
|
2714
2561
|
return;
|
|
@@ -3004,7 +2851,7 @@ export async function main() {
|
|
|
3004
2851
|
runtimeState.clearTurnState(convoId).catch(() => { });
|
|
3005
2852
|
}, (descriptor) => {
|
|
3006
2853
|
runtimeDescriptor = descriptor;
|
|
3007
|
-
|
|
2854
|
+
runtimeHeartbeat.refresh();
|
|
3008
2855
|
}, {
|
|
3009
2856
|
model: runtimeModels[0]?.value,
|
|
3010
2857
|
permissionMode: 'default',
|
|
@@ -3460,7 +3307,8 @@ export async function main() {
|
|
|
3460
3307
|
},
|
|
3461
3308
|
onConnected: () => {
|
|
3462
3309
|
streamConnected = true;
|
|
3463
|
-
|
|
3310
|
+
publishLocalHeartbeat();
|
|
3311
|
+
runtimeHeartbeat.connect();
|
|
3464
3312
|
const recovery = reconnectRecovery.onConnected();
|
|
3465
3313
|
if (recovery) {
|
|
3466
3314
|
void recovery.catch((error) => {
|
|
@@ -3471,7 +3319,7 @@ export async function main() {
|
|
|
3471
3319
|
},
|
|
3472
3320
|
onDisconnected: () => {
|
|
3473
3321
|
streamConnected = false;
|
|
3474
|
-
|
|
3322
|
+
void runtimeHeartbeat.disconnect();
|
|
3475
3323
|
console.error('[canon-host] SSE disconnected');
|
|
3476
3324
|
},
|
|
3477
3325
|
onError: (err) => console.error(`[canon-host] SSE error: ${err.message}`),
|
|
@@ -3571,7 +3419,7 @@ export async function main() {
|
|
|
3571
3419
|
session.writeTurn();
|
|
3572
3420
|
}
|
|
3573
3421
|
}
|
|
3574
|
-
|
|
3422
|
+
publishLocalHeartbeat();
|
|
3575
3423
|
}, HEARTBEAT_MS);
|
|
3576
3424
|
// ── Idle session cleanup ──
|
|
3577
3425
|
const idleCheck = setInterval(() => {
|
|
@@ -3595,7 +3443,7 @@ export async function main() {
|
|
|
3595
3443
|
stream.stop();
|
|
3596
3444
|
approvalManager?.dispose();
|
|
3597
3445
|
runtimeInputManager.dispose();
|
|
3598
|
-
await
|
|
3446
|
+
await runtimeHeartbeat.dispose();
|
|
3599
3447
|
for (const convoId of [...sessions.keys()]) {
|
|
3600
3448
|
closeSession(convoId);
|
|
3601
3449
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonmsg/claude-code-plugin",
|
|
3
|
-
"version": "0.34.
|
|
3
|
+
"version": "0.34.3",
|
|
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,10 +31,10 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@anthropic-ai/claude-agent-sdk": "0.3.228",
|
|
34
|
-
"@canonmsg/agent-sdk": "^10.1
|
|
34
|
+
"@canonmsg/agent-sdk": "^10.2.1",
|
|
35
35
|
"@canonmsg/agent-tools": "^0.9.0",
|
|
36
36
|
"@canonmsg/coding-agent-host": "^0.7.0",
|
|
37
|
-
"@canonmsg/core": "^12.
|
|
37
|
+
"@canonmsg/core": "^12.3.0",
|
|
38
38
|
"@canonmsg/rich-cards": "^0.10.4",
|
|
39
39
|
"@modelcontextprotocol/sdk": "^1.30.0"
|
|
40
40
|
},
|