@canonmsg/claude-code-plugin 0.22.0 → 0.24.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/.claude-plugin/plugin.json +25 -0
- package/README.md +18 -2
- package/dist/approval-diff.d.ts +1 -1
- package/dist/approval-diff.js +1 -1
- package/dist/approval-server.d.ts +33 -0
- package/dist/approval-server.js +200 -0
- package/dist/cli-entry.d.ts +2 -2
- package/dist/cli-entry.js +1 -1
- package/dist/host.d.ts +1 -1
- package/dist/host.js +1079 -678
- package/dist/inbound-policy.d.ts +22 -0
- package/dist/inbound-policy.js +46 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/mcp-args.d.ts +45 -0
- package/dist/mcp-args.js +179 -0
- package/dist/register.js +25 -73
- package/dist/server.d.ts +2 -0
- package/dist/server.js +699 -0
- package/dist/session-state.d.ts +47 -54
- package/dist/session-state.js +88 -166
- package/dist/setup.d.ts +3 -2
- package/dist/setup.js +29 -5
- package/dist/startup-recovery.d.ts +46 -0
- package/dist/startup-recovery.js +59 -0
- package/dist/streaming-buffer.d.ts +16 -0
- package/dist/streaming-buffer.js +52 -0
- package/dist/tool-policy.d.ts +1 -2
- package/package.json +11 -11
- package/skills/configure/SKILL.md +10 -4
- package/dist/bridge-bin.d.ts +0 -14
- package/dist/bridge-bin.js +0 -27
- package/dist/session-defaults.d.ts +0 -35
- package/dist/session-defaults.js +0 -124
- package/dist/subagent-activity.d.ts +0 -11
- package/dist/subagent-activity.js +0 -51
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonmsg/claude-code-plugin",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Canon
|
|
3
|
+
"version": "0.24.0",
|
|
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",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -12,16 +12,18 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"bin": {
|
|
15
|
+
"canon-channel-server": "dist/server.js",
|
|
15
16
|
"canon-claude": "dist/host.js",
|
|
16
17
|
"canon-register": "dist/register.js",
|
|
17
18
|
"canon-setup": "dist/setup.js"
|
|
18
19
|
},
|
|
19
20
|
"files": [
|
|
20
21
|
"dist",
|
|
21
|
-
"skills"
|
|
22
|
+
"skills",
|
|
23
|
+
".claude-plugin"
|
|
22
24
|
],
|
|
23
25
|
"scripts": {
|
|
24
|
-
"prepare:workspace-deps": "node ../../scripts/run-workspace-prep.mjs
|
|
26
|
+
"prepare:workspace-deps": "node ../../scripts/run-workspace-prep.mjs ../core ../agent-sdk ../coding-agent-host",
|
|
25
27
|
"build": "npm run prepare:workspace-deps && node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc",
|
|
26
28
|
"dev": "npm run prepare:workspace-deps && tsc --watch",
|
|
27
29
|
"prepack": "npm run build",
|
|
@@ -29,11 +31,9 @@
|
|
|
29
31
|
},
|
|
30
32
|
"dependencies": {
|
|
31
33
|
"@anthropic-ai/claude-agent-sdk": "^0.3.200",
|
|
32
|
-
"@canonmsg/agent-
|
|
33
|
-
"@canonmsg/agent-
|
|
34
|
-
"@canonmsg/
|
|
35
|
-
"@canonmsg/core": "^3.3.0",
|
|
36
|
-
"@canonmsg/framework": "^0.3.0",
|
|
34
|
+
"@canonmsg/agent-sdk": "^5.0.0",
|
|
35
|
+
"@canonmsg/coding-agent-host": "^0.2.2",
|
|
36
|
+
"@canonmsg/core": "^4.1.0",
|
|
37
37
|
"@modelcontextprotocol/sdk": "^1.29.0"
|
|
38
38
|
},
|
|
39
39
|
"engines": {
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
"repository": {
|
|
51
51
|
"type": "git",
|
|
52
52
|
"url": "https://github.com/HeyBobChan/canon",
|
|
53
|
-
"directory": "
|
|
53
|
+
"directory": "packages/claude-code-plugin"
|
|
54
54
|
},
|
|
55
|
-
"homepage": "https://github.com/HeyBobChan/canon/tree/main/
|
|
55
|
+
"homepage": "https://github.com/HeyBobChan/canon/tree/main/packages/claude-code-plugin",
|
|
56
56
|
"publishConfig": {
|
|
57
57
|
"access": "public"
|
|
58
58
|
},
|
|
@@ -36,9 +36,15 @@ Add an existing Canon agent API key as a named profile.
|
|
|
36
36
|
|
|
37
37
|
5. Write the updated profiles to `~/.canon/agents.json`.
|
|
38
38
|
|
|
39
|
-
6. Tell the user: **"API key saved as profile '<profile>'.
|
|
39
|
+
6. Tell the user: **"API key saved as profile '<profile>'. Restart Claude Code to connect."**
|
|
40
40
|
|
|
41
|
-
If they have multiple agents and want to pin one,
|
|
42
|
-
```
|
|
43
|
-
|
|
41
|
+
If they have multiple agents and want to pin one, add to `.mcp.json`:
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"mcpServers": {
|
|
45
|
+
"canon-channel": {
|
|
46
|
+
"env": { "CANON_AGENT": "<profile>" }
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
44
50
|
```
|
package/dist/bridge-bin.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Packaged canon-bridge daemon resolution (bridge plan Phase 6, §F3).
|
|
3
|
-
*
|
|
4
|
-
* On a fresh npm install nothing has populated ~/.canon/bin yet, so
|
|
5
|
-
* connectBridge()'s fallback chain (explicit binPath → $CANON_BRIDGE_BIN →
|
|
6
|
-
* the shared install) has nothing to spawn. The plugin therefore ships the
|
|
7
|
-
* daemon as its own @canonmsg/bridge dependency and passes the packaged
|
|
8
|
-
* dist entry as binPath.
|
|
9
|
-
*
|
|
10
|
-
* $CANON_BRIDGE_BIN still wins: when the env override is set we return
|
|
11
|
-
* undefined and let connectBridge()'s own env resolution take it (an
|
|
12
|
-
* options.binPath would out-rank the env var otherwise).
|
|
13
|
-
*/
|
|
14
|
-
export declare function resolvePackagedBridgeBin(env?: NodeJS.ProcessEnv): string | undefined;
|
package/dist/bridge-bin.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Packaged canon-bridge daemon resolution (bridge plan Phase 6, §F3).
|
|
3
|
-
*
|
|
4
|
-
* On a fresh npm install nothing has populated ~/.canon/bin yet, so
|
|
5
|
-
* connectBridge()'s fallback chain (explicit binPath → $CANON_BRIDGE_BIN →
|
|
6
|
-
* the shared install) has nothing to spawn. The plugin therefore ships the
|
|
7
|
-
* daemon as its own @canonmsg/bridge dependency and passes the packaged
|
|
8
|
-
* dist entry as binPath.
|
|
9
|
-
*
|
|
10
|
-
* $CANON_BRIDGE_BIN still wins: when the env override is set we return
|
|
11
|
-
* undefined and let connectBridge()'s own env resolution take it (an
|
|
12
|
-
* options.binPath would out-rank the env var otherwise).
|
|
13
|
-
*/
|
|
14
|
-
import { createRequire } from 'node:module';
|
|
15
|
-
import { dirname, join as joinPath } from 'node:path';
|
|
16
|
-
export function resolvePackagedBridgeBin(env = process.env) {
|
|
17
|
-
if (env.CANON_BRIDGE_BIN)
|
|
18
|
-
return undefined;
|
|
19
|
-
try {
|
|
20
|
-
const require = createRequire(import.meta.url);
|
|
21
|
-
const manifestPath = require.resolve('@canonmsg/bridge/package.json');
|
|
22
|
-
return joinPath(dirname(manifestPath), 'dist', 'main.js');
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
return undefined;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import type { AgentDefinition, EffortLevel, ThinkingConfig } from '@anthropic-ai/claude-agent-sdk';
|
|
2
|
-
export type ClaudeThinkingMode = 'adaptive' | 'off';
|
|
3
|
-
export type ClaudeUltracodeMode = 'on' | 'off';
|
|
4
|
-
export type ClaudeEffortLevel = Extract<EffortLevel, 'low' | 'medium' | 'high' | 'xhigh' | 'max'>;
|
|
5
|
-
export interface ClaudeSessionDefaults {
|
|
6
|
-
model?: string;
|
|
7
|
-
effort?: ClaudeEffortLevel;
|
|
8
|
-
thinking?: ClaudeThinkingMode;
|
|
9
|
-
ultracode?: ClaudeUltracodeMode;
|
|
10
|
-
fallbackModel?: string;
|
|
11
|
-
agentProgressSummaries?: boolean;
|
|
12
|
-
agents?: Record<string, AgentDefinition>;
|
|
13
|
-
}
|
|
14
|
-
export interface ClaudeSessionControlValues {
|
|
15
|
-
thinking?: ClaudeThinkingMode;
|
|
16
|
-
ultracode?: ClaudeUltracodeMode;
|
|
17
|
-
}
|
|
18
|
-
export interface ClaudeEffectiveSessionSettings extends ClaudeSessionDefaults {
|
|
19
|
-
runtimeControlValues: Record<string, string>;
|
|
20
|
-
}
|
|
21
|
-
export declare const CLAUDE_EFFORT_LEVELS: readonly ClaudeEffortLevel[];
|
|
22
|
-
export declare function parseClaudeThinkingMode(value: unknown): ClaudeThinkingMode | undefined;
|
|
23
|
-
export declare function parseClaudeUltracodeMode(value: unknown): ClaudeUltracodeMode | undefined;
|
|
24
|
-
export declare function parseClaudeSessionDefaults(raw: unknown): ClaudeSessionDefaults;
|
|
25
|
-
export declare function parseClaudeSessionControlValues(values: Record<string, string> | null | undefined): ClaudeSessionControlValues;
|
|
26
|
-
export declare function claudeThinkingToConfig(mode: ClaudeThinkingMode | undefined): ThinkingConfig | undefined;
|
|
27
|
-
export declare function claudeThinkingToFlagValue(mode: ClaudeThinkingMode): boolean;
|
|
28
|
-
export declare function resolveEffectiveSessionSettings(input: {
|
|
29
|
-
profileDefaults?: ClaudeSessionDefaults;
|
|
30
|
-
sessionConfig?: {
|
|
31
|
-
model?: string;
|
|
32
|
-
effort?: ClaudeEffortLevel;
|
|
33
|
-
runtimeControlValues?: Record<string, string>;
|
|
34
|
-
} | null;
|
|
35
|
-
}): ClaudeEffectiveSessionSettings;
|
package/dist/session-defaults.js
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
export const CLAUDE_EFFORT_LEVELS = ['low', 'medium', 'high', 'xhigh', 'max'];
|
|
2
|
-
const CLAUDE_EFFORT_VALUES = new Set(CLAUDE_EFFORT_LEVELS);
|
|
3
|
-
function optionalString(value) {
|
|
4
|
-
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
5
|
-
}
|
|
6
|
-
function optionalBoolean(value) {
|
|
7
|
-
return typeof value === 'boolean' ? value : undefined;
|
|
8
|
-
}
|
|
9
|
-
export function parseClaudeThinkingMode(value) {
|
|
10
|
-
if (value === false || value === 'off' || value === 'disabled')
|
|
11
|
-
return 'off';
|
|
12
|
-
if (value === true || value === 'on' || value === 'adaptive' || value === 'enabled')
|
|
13
|
-
return 'adaptive';
|
|
14
|
-
return undefined;
|
|
15
|
-
}
|
|
16
|
-
export function parseClaudeUltracodeMode(value) {
|
|
17
|
-
if (value === true || value === 'on' || value === 'enabled')
|
|
18
|
-
return 'on';
|
|
19
|
-
if (value === false || value === 'off' || value === 'disabled')
|
|
20
|
-
return 'off';
|
|
21
|
-
return undefined;
|
|
22
|
-
}
|
|
23
|
-
function parseEffort(value) {
|
|
24
|
-
const normalized = optionalString(value);
|
|
25
|
-
if (!normalized)
|
|
26
|
-
return undefined;
|
|
27
|
-
return CLAUDE_EFFORT_VALUES.has(normalized)
|
|
28
|
-
? normalized
|
|
29
|
-
: undefined;
|
|
30
|
-
}
|
|
31
|
-
function parseStringArray(value) {
|
|
32
|
-
if (!Array.isArray(value))
|
|
33
|
-
return undefined;
|
|
34
|
-
const out = value
|
|
35
|
-
.map((entry) => optionalString(entry))
|
|
36
|
-
.filter((entry) => Boolean(entry));
|
|
37
|
-
return out.length > 0 ? out : undefined;
|
|
38
|
-
}
|
|
39
|
-
function parseAgentDefinition(value) {
|
|
40
|
-
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
41
|
-
return null;
|
|
42
|
-
const data = value;
|
|
43
|
-
const description = optionalString(data.description);
|
|
44
|
-
const prompt = optionalString(data.prompt);
|
|
45
|
-
if (!description || !prompt)
|
|
46
|
-
return null;
|
|
47
|
-
return {
|
|
48
|
-
description,
|
|
49
|
-
prompt,
|
|
50
|
-
...(parseStringArray(data.tools) ? { tools: parseStringArray(data.tools) } : {}),
|
|
51
|
-
...(parseStringArray(data.disallowedTools) ? { disallowedTools: parseStringArray(data.disallowedTools) } : {}),
|
|
52
|
-
...(optionalString(data.model) ? { model: optionalString(data.model) } : {}),
|
|
53
|
-
...(parseStringArray(data.skills) ? { skills: parseStringArray(data.skills) } : {}),
|
|
54
|
-
...(typeof data.maxTurns === 'number' && Number.isFinite(data.maxTurns) && data.maxTurns > 0
|
|
55
|
-
? { maxTurns: Math.floor(data.maxTurns) }
|
|
56
|
-
: {}),
|
|
57
|
-
...(typeof data.background === 'boolean' ? { background: data.background } : {}),
|
|
58
|
-
...(parseEffort(data.effort) ? { effort: parseEffort(data.effort) } : {}),
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
function parseAgents(value) {
|
|
62
|
-
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
63
|
-
return undefined;
|
|
64
|
-
const out = {};
|
|
65
|
-
for (const [rawName, rawAgent] of Object.entries(value)) {
|
|
66
|
-
const name = rawName.trim();
|
|
67
|
-
if (!name)
|
|
68
|
-
continue;
|
|
69
|
-
const agent = parseAgentDefinition(rawAgent);
|
|
70
|
-
if (agent)
|
|
71
|
-
out[name] = agent;
|
|
72
|
-
}
|
|
73
|
-
return Object.keys(out).length > 0 ? out : undefined;
|
|
74
|
-
}
|
|
75
|
-
export function parseClaudeSessionDefaults(raw) {
|
|
76
|
-
if (!raw || typeof raw !== 'object' || Array.isArray(raw))
|
|
77
|
-
return {};
|
|
78
|
-
const data = raw;
|
|
79
|
-
return {
|
|
80
|
-
...(optionalString(data.model) ? { model: optionalString(data.model) } : {}),
|
|
81
|
-
...(parseEffort(data.effort) ? { effort: parseEffort(data.effort) } : {}),
|
|
82
|
-
...(parseClaudeThinkingMode(data.thinking) ? { thinking: parseClaudeThinkingMode(data.thinking) } : {}),
|
|
83
|
-
...(parseClaudeUltracodeMode(data.ultracode) ? { ultracode: parseClaudeUltracodeMode(data.ultracode) } : {}),
|
|
84
|
-
...(optionalString(data.fallbackModel) ? { fallbackModel: optionalString(data.fallbackModel) } : {}),
|
|
85
|
-
...(optionalBoolean(data.agentProgressSummaries) !== undefined
|
|
86
|
-
? { agentProgressSummaries: optionalBoolean(data.agentProgressSummaries) }
|
|
87
|
-
: {}),
|
|
88
|
-
...(parseAgents(data.agents) ? { agents: parseAgents(data.agents) } : {}),
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
export function parseClaudeSessionControlValues(values) {
|
|
92
|
-
return {
|
|
93
|
-
...(parseClaudeThinkingMode(values?.thinking) ? { thinking: parseClaudeThinkingMode(values?.thinking) } : {}),
|
|
94
|
-
...(parseClaudeUltracodeMode(values?.ultracode) ? { ultracode: parseClaudeUltracodeMode(values?.ultracode) } : {}),
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
export function claudeThinkingToConfig(mode) {
|
|
98
|
-
if (mode === 'adaptive')
|
|
99
|
-
return { type: 'adaptive' };
|
|
100
|
-
if (mode === 'off')
|
|
101
|
-
return { type: 'disabled' };
|
|
102
|
-
return undefined;
|
|
103
|
-
}
|
|
104
|
-
export function claudeThinkingToFlagValue(mode) {
|
|
105
|
-
return mode !== 'off';
|
|
106
|
-
}
|
|
107
|
-
export function resolveEffectiveSessionSettings(input) {
|
|
108
|
-
const controlValues = parseClaudeSessionControlValues(input.sessionConfig?.runtimeControlValues);
|
|
109
|
-
const runtimeControlValues = {
|
|
110
|
-
...(input.profileDefaults?.thinking ? { thinking: input.profileDefaults.thinking } : {}),
|
|
111
|
-
...(input.profileDefaults?.ultracode ? { ultracode: input.profileDefaults.ultracode } : {}),
|
|
112
|
-
...(input.sessionConfig?.runtimeControlValues ?? {}),
|
|
113
|
-
...(controlValues.thinking ? { thinking: controlValues.thinking } : {}),
|
|
114
|
-
...(controlValues.ultracode ? { ultracode: controlValues.ultracode } : {}),
|
|
115
|
-
};
|
|
116
|
-
return {
|
|
117
|
-
...(input.profileDefaults ?? {}),
|
|
118
|
-
...(input.sessionConfig?.model ? { model: input.sessionConfig.model } : {}),
|
|
119
|
-
...(input.sessionConfig?.effort ? { effort: input.sessionConfig.effort } : {}),
|
|
120
|
-
...(controlValues.thinking ? { thinking: controlValues.thinking } : {}),
|
|
121
|
-
...(controlValues.ultracode ? { ultracode: controlValues.ultracode } : {}),
|
|
122
|
-
runtimeControlValues,
|
|
123
|
-
};
|
|
124
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { SDKTaskNotificationMessage, SDKTaskProgressMessage, SDKTaskStartedMessage, SDKTaskUpdatedMessage } from '@anthropic-ai/claude-agent-sdk';
|
|
2
|
-
type ClaudeTaskMessage = SDKTaskNotificationMessage | SDKTaskProgressMessage | SDKTaskStartedMessage | SDKTaskUpdatedMessage;
|
|
3
|
-
export interface ClaudeSubagentActivityBlock {
|
|
4
|
-
id: string;
|
|
5
|
-
kind: 'status';
|
|
6
|
-
status: 'running' | 'completed' | 'failed';
|
|
7
|
-
title: string;
|
|
8
|
-
text?: string;
|
|
9
|
-
}
|
|
10
|
-
export declare function mapClaudeSubagentActivity(message: ClaudeTaskMessage): ClaudeSubagentActivityBlock | null;
|
|
11
|
-
export {};
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
function titleForMessage(message) {
|
|
2
|
-
const subtype = message.subtype;
|
|
3
|
-
if (subtype === 'task_started') {
|
|
4
|
-
return message.subagent_type
|
|
5
|
-
? `Subagent started: ${message.subagent_type}`
|
|
6
|
-
: 'Subagent started';
|
|
7
|
-
}
|
|
8
|
-
if (subtype === 'task_progress') {
|
|
9
|
-
return message.subagent_type
|
|
10
|
-
? `Subagent progress: ${message.subagent_type}`
|
|
11
|
-
: 'Subagent progress';
|
|
12
|
-
}
|
|
13
|
-
if (subtype === 'task_updated')
|
|
14
|
-
return 'Subagent updated';
|
|
15
|
-
return `Subagent ${message.status}`;
|
|
16
|
-
}
|
|
17
|
-
function textForMessage(message) {
|
|
18
|
-
if (message.subtype === 'task_started')
|
|
19
|
-
return message.description;
|
|
20
|
-
if (message.subtype === 'task_progress')
|
|
21
|
-
return message.summary ?? message.description;
|
|
22
|
-
if (message.subtype === 'task_updated')
|
|
23
|
-
return message.patch.description ?? message.patch.error;
|
|
24
|
-
return message.summary;
|
|
25
|
-
}
|
|
26
|
-
function statusForMessage(message) {
|
|
27
|
-
if (message.subtype === 'task_notification') {
|
|
28
|
-
if (message.status === 'completed')
|
|
29
|
-
return 'completed';
|
|
30
|
-
return 'failed';
|
|
31
|
-
}
|
|
32
|
-
if (message.subtype === 'task_updated') {
|
|
33
|
-
if (message.patch.status === 'completed')
|
|
34
|
-
return 'completed';
|
|
35
|
-
if (message.patch.status === 'failed' || message.patch.status === 'killed')
|
|
36
|
-
return 'failed';
|
|
37
|
-
}
|
|
38
|
-
return 'running';
|
|
39
|
-
}
|
|
40
|
-
export function mapClaudeSubagentActivity(message) {
|
|
41
|
-
if ('skip_transcript' in message && message.skip_transcript)
|
|
42
|
-
return null;
|
|
43
|
-
const text = textForMessage(message);
|
|
44
|
-
return {
|
|
45
|
-
id: `task:${message.task_id}`,
|
|
46
|
-
kind: 'status',
|
|
47
|
-
status: statusForMessage(message),
|
|
48
|
-
title: titleForMessage(message),
|
|
49
|
-
...(text ? { text } : {}),
|
|
50
|
-
};
|
|
51
|
-
}
|