@canonmsg/claude-code-plugin 0.25.4 → 0.25.6
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.d.ts +2 -1
- package/dist/host.js +30 -53
- package/package.json +2 -2
package/dist/host.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { type SDKControlReloadPluginsResponse } from '@anthropic-ai/claude-agent-sdk';
|
|
2
|
+
import { type PermissionResult, type SDKControlReloadPluginsResponse } from '@anthropic-ai/claude-agent-sdk';
|
|
3
3
|
import { type CanonRuntimeCommandDescriptor } from '@canonmsg/core';
|
|
4
|
+
export declare function buildClaudePlanAllowResult(input: Record<string, unknown>): PermissionResult;
|
|
4
5
|
/**
|
|
5
6
|
* Claude Code's own slash commands (built-ins, plugins, project .claude/
|
|
6
7
|
* commands) are executable when sent as prompt text, so the runtime's command
|
package/dist/host.js
CHANGED
|
@@ -92,6 +92,9 @@ let runtimeMetadata = {
|
|
|
92
92
|
let runtimeMetadataRefresh = null;
|
|
93
93
|
/** Bound on native slash commands exposed to the composer palette. */
|
|
94
94
|
const MAX_NATIVE_SLASH_COMMANDS = 50;
|
|
95
|
+
export function buildClaudePlanAllowResult(input) {
|
|
96
|
+
return { behavior: 'allow', updatedInput: input };
|
|
97
|
+
}
|
|
95
98
|
/**
|
|
96
99
|
* Claude Code's own slash commands (built-ins, plugins, project .claude/
|
|
97
100
|
* commands) are executable when sent as prompt text, so the runtime's command
|
|
@@ -841,25 +844,6 @@ function createSession(conversationId, environment, agentId, client, typingSigna
|
|
|
841
844
|
}
|
|
842
845
|
});
|
|
843
846
|
}
|
|
844
|
-
function waitForReply(type, requestId, responseUserId) {
|
|
845
|
-
// Keep session alive while waiting for user input
|
|
846
|
-
session.lastActivity = Date.now();
|
|
847
|
-
return new Promise((resolve, reject) => {
|
|
848
|
-
const timer = setTimeout(() => {
|
|
849
|
-
session.pendingReply = null;
|
|
850
|
-
reject(new Error('Timed out waiting for user reply'));
|
|
851
|
-
}, REPLY_TIMEOUT_MS);
|
|
852
|
-
session.pendingReply = {
|
|
853
|
-
type,
|
|
854
|
-
requestId,
|
|
855
|
-
responseUserId,
|
|
856
|
-
resolve: (metadata) => {
|
|
857
|
-
clearTimeout(timer);
|
|
858
|
-
resolve(metadata);
|
|
859
|
-
},
|
|
860
|
-
};
|
|
861
|
-
});
|
|
862
|
-
}
|
|
863
847
|
function buildArtifactMediaMetadata() {
|
|
864
848
|
return {
|
|
865
849
|
...(session.currentTurnId ? { turnId: session.currentTurnId } : {}),
|
|
@@ -939,24 +923,24 @@ function createSession(conversationId, environment, agentId, client, typingSigna
|
|
|
939
923
|
const planBody = typeof input.plan === 'string' && input.plan.trim()
|
|
940
924
|
? input.plan.trim()
|
|
941
925
|
: undefined;
|
|
942
|
-
|
|
943
|
-
// seeds the server-owned pending node/attention/state and authors the
|
|
944
|
-
// `plan_approval` card. Resolution is UNCHANGED — the gate still blocks
|
|
945
|
-
// on the server-authored `plan_approval_reply` below.
|
|
946
|
-
await client.createRuntimePlanRequest({
|
|
947
|
-
conversationId,
|
|
948
|
-
planId,
|
|
926
|
+
const reply = await config.runtimeInputManager.request('plan', conversationId, {
|
|
949
927
|
title: 'Plan ready for review.',
|
|
950
928
|
summary: 'Claude has prepared a plan and is asking permission to continue.',
|
|
951
929
|
...(planBody ? { body: planBody } : {}),
|
|
952
930
|
responseUserId: turnResponseRouting.responseUserId,
|
|
953
931
|
...(allowedPrompts.length > 0 ? { allowedPrompts } : {}),
|
|
954
932
|
...(session.currentTurnId ? { turnId: session.currentTurnId } : {}),
|
|
933
|
+
}, {
|
|
934
|
+
requestId: planId,
|
|
955
935
|
expiresAt: Date.now() + REPLY_TIMEOUT_MS,
|
|
936
|
+
responderPolicy: 'infer',
|
|
937
|
+
signal: options.signal,
|
|
938
|
+
onCreated: () => {
|
|
939
|
+
session.lastActivity = Date.now();
|
|
940
|
+
console.error(`[canon-host] [${conversationId.slice(0, 8)}] Plan approval sent (${planId.slice(0, 8)})`);
|
|
941
|
+
},
|
|
956
942
|
});
|
|
957
|
-
|
|
958
|
-
const reply = await waitForReply('plan_approval_reply', planId, turnResponseRouting.responseUserId);
|
|
959
|
-
if (reply.decision === 'approve') {
|
|
943
|
+
if (reply.status === 'approve') {
|
|
960
944
|
// Honor opt-in selective grants: when the card sent an explicit
|
|
961
945
|
// granted subset, pre-approve those tools as session rules so they
|
|
962
946
|
// do not re-prompt. Owner-turn only; absent grants preserve the
|
|
@@ -998,15 +982,23 @@ function createSession(conversationId, environment, agentId, client, typingSigna
|
|
|
998
982
|
// instead of waiting for the next 30s heartbeat (lag fix).
|
|
999
983
|
config.publishSessionSnapshots?.([conversationId]);
|
|
1000
984
|
}
|
|
1001
|
-
return
|
|
985
|
+
return buildClaudePlanAllowResult(input);
|
|
1002
986
|
}
|
|
1003
|
-
if (reply.
|
|
987
|
+
if (reply.status === 'reject') {
|
|
1004
988
|
return {
|
|
1005
989
|
behavior: 'deny',
|
|
1006
990
|
message: reply.feedback?.trim()
|
|
1007
991
|
|| 'Plan declined — keep planning and wait for guidance before proceeding.',
|
|
1008
992
|
};
|
|
1009
993
|
}
|
|
994
|
+
if (reply.status === 'cancelled' || reply.status === 'timeout') {
|
|
995
|
+
return {
|
|
996
|
+
behavior: 'deny',
|
|
997
|
+
message: reply.status === 'timeout'
|
|
998
|
+
? 'No reply received (timed out)'
|
|
999
|
+
: 'The plan review was cancelled.',
|
|
1000
|
+
};
|
|
1001
|
+
}
|
|
1010
1002
|
return {
|
|
1011
1003
|
behavior: 'deny',
|
|
1012
1004
|
message: reply.feedback?.trim() || 'User requested changes to the plan.',
|
|
@@ -1093,7 +1085,6 @@ function createSession(conversationId, environment, agentId, client, typingSigna
|
|
|
1093
1085
|
controlInterruptPending: false,
|
|
1094
1086
|
closed: false,
|
|
1095
1087
|
sdkSessionId: resumeSessionId || null,
|
|
1096
|
-
pendingReply: null,
|
|
1097
1088
|
writeState: () => writeState(),
|
|
1098
1089
|
writeTurn: () => writeTurn(),
|
|
1099
1090
|
clearStreaming: () => clearStreaming(),
|
|
@@ -2559,28 +2550,14 @@ export async function main() {
|
|
|
2559
2550
|
return true;
|
|
2560
2551
|
}
|
|
2561
2552
|
}
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
console.error(`[canon-host] [${conversationId.slice(0, 8)}] Ignoring stale ${message.metadata.type} with no pending request`);
|
|
2569
|
-
return true;
|
|
2570
|
-
}
|
|
2571
|
-
if (message.senderId !== pendingReply.responseUserId) {
|
|
2572
|
-
console.error(`[canon-host] [${conversationId.slice(0, 8)}] Ignoring ${message.metadata.type} from unexpected responder ${message.senderId}`);
|
|
2573
|
-
return true;
|
|
2574
|
-
}
|
|
2575
|
-
if (pendingReply.type !== message.metadata.type || pendingReply.requestId !== replyRequestId) {
|
|
2576
|
-
console.error(`[canon-host] [${conversationId.slice(0, 8)}] Ignoring mismatched ${message.metadata.type} (${String(replyRequestId ?? 'missing-id')})`);
|
|
2577
|
-
return true;
|
|
2553
|
+
const consumed = runtimeInputManager.handleMessage(conversationId, {
|
|
2554
|
+
senderId: message.senderId,
|
|
2555
|
+
metadata: message.metadata,
|
|
2556
|
+
});
|
|
2557
|
+
if (consumed) {
|
|
2558
|
+
console.error(`[canon-host] [${conversationId.slice(0, 8)}] Runtime response receipt woke canonical polling`);
|
|
2578
2559
|
}
|
|
2579
|
-
|
|
2580
|
-
existingSession.lastActivity = Date.now();
|
|
2581
|
-
pendingReply.resolve(message.metadata);
|
|
2582
|
-
console.error(`[canon-host] [${conversationId.slice(0, 8)}] Reply received (${message.metadata.type}:${pendingReply.requestId.slice(0, 8)})`);
|
|
2583
|
-
return true;
|
|
2560
|
+
return consumed;
|
|
2584
2561
|
}
|
|
2585
2562
|
function persistedConversationCursors(conversationId) {
|
|
2586
2563
|
const canonicalCursor = loadRuntimeSessionState(runtimeId, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonmsg/claude-code-plugin",
|
|
3
|
-
"version": "0.25.
|
|
3
|
+
"version": "0.25.6",
|
|
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",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"@anthropic-ai/claude-agent-sdk": "0.3.204",
|
|
34
34
|
"@canonmsg/agent-sdk": "^5.1.1",
|
|
35
35
|
"@canonmsg/coding-agent-host": "^0.2.2",
|
|
36
|
-
"@canonmsg/core": "^4.2.
|
|
36
|
+
"@canonmsg/core": "^4.2.3",
|
|
37
37
|
"@modelcontextprotocol/sdk": "^1.29.0"
|
|
38
38
|
},
|
|
39
39
|
"engines": {
|