@canonmsg/codex-plugin 0.7.0 → 0.9.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 +13 -3
- package/dist/host.js +103 -13
- package/dist/setup.js +2 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -37,7 +37,15 @@ You do not need a git repo for host mode. The plugin passes `--skip-git-repo-che
|
|
|
37
37
|
|
|
38
38
|
## Current limitation
|
|
39
39
|
|
|
40
|
-
The stable `codex exec --json` surface exposes thinking state, tool activity, and completed assistant-message previews, but not token-by-token text deltas. v1 therefore publishes live progress and message snapshots without claiming true token streaming.
|
|
40
|
+
The stable `codex exec --json` surface exposes thinking state, tool activity, and completed assistant-message previews, but not token-by-token text deltas. v1 therefore publishes live progress and assistant-message snapshots without claiming true token streaming.
|
|
41
|
+
|
|
42
|
+
Current Canon control truth for Codex host mode:
|
|
43
|
+
|
|
44
|
+
- model is live-visible, but current changes apply on the next turn rather than mid-turn
|
|
45
|
+
- workspace selection is setup-only
|
|
46
|
+
- execution mode selection is setup-only
|
|
47
|
+
- the current `Execution policy`/permission choice is setup-only
|
|
48
|
+
- advanced Codex-only controls such as effort, sandbox policy, approval reviewer, or apps/plugins inventory are not exposed on the current transport unless the runtime can actually report them
|
|
41
49
|
|
|
42
50
|
## Working directory
|
|
43
51
|
|
|
@@ -48,10 +56,12 @@ canon-codex --cwd /path/to/project
|
|
|
48
56
|
Advertise multiple project choices to the Canon app:
|
|
49
57
|
|
|
50
58
|
```bash
|
|
51
|
-
canon-codex --cwd ~/dev --workspace ~/dev
|
|
59
|
+
canon-codex --cwd ~/dev --workspace-root ~/dev
|
|
52
60
|
```
|
|
53
61
|
|
|
54
|
-
`--cwd` is the default workspace. Each `--workspace` value
|
|
62
|
+
`--cwd` is the default workspace. Each `--workspace-root` value is an approved local root; the host discovers immediate child projects with common markers such as `.git`, `package.json`, `pyproject.toml`, `Cargo.toml`, or `go.mod` and publishes them as selectable projects during session creation. Use repeated `--workspace /path/to/project` entries to advertise specific projects outside those roots. Worktree mode creates a per-conversation git worktree under `~/.canon/conversation-worktrees`; shared-project mode runs directly in the selected directory.
|
|
63
|
+
|
|
64
|
+
If worktree isolation is requested for a project that cannot support it, Canon may fall back to shared-project execution and surface the fallback reason in session details instead of failing the session outright.
|
|
55
65
|
|
|
56
66
|
Useful flags:
|
|
57
67
|
|
package/dist/host.js
CHANGED
|
@@ -3,7 +3,7 @@ import { setDefaultResultOrder } from 'node:dns';
|
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
4
|
import { parseArgs } from 'node:util';
|
|
5
5
|
import { getCodexImagePath, materializeMessageMedia, } from '@canonmsg/agent-sdk';
|
|
6
|
-
import {
|
|
6
|
+
import { buildConfiguredWorkspaceOptionsWithRoots, buildPublicWorkspaceRoots, buildPublicWorkspaceOptions, EXECUTION_ENVIRONMENT_MODES, ExecutionEnvironmentError, CanonClient, CanonStream, clearSessionState, clearTurnState, DEFAULT_PARTICIPATION_HISTORY_FETCH_LIMIT, DEFAULT_RUNTIME_CAPABILITIES, FINAL_MESSAGE_HANDOFF_MS, getActiveProfile, initRTDBAuth, normalizeTurnMetadata, normalizeTurnState, prepareConversationEnvironment, releaseLock, releaseConversationEnvironment, resolveCanonAgent, rtdbRead, rtdbWrite, writeRuntimeInfo, shouldTriggerAgentTurn, writeSessionState, writeTurnState, } from '@canonmsg/core';
|
|
7
7
|
import { buildCanonHostPrompt, buildHydratedInboundContext, createConversationMetadataLoader, loadHostSessionConfig, publishHostAgentRuntime, publishHostSessionSnapshots, renderCanonHostInboundContent, resolveHostWorkspaceCwd, } from './host-runtime.js';
|
|
8
8
|
import { buildInboundContextLines, decideAutoReply, } from './inbound-policy.js';
|
|
9
9
|
import { CodexConversationAdapter, } from './adapter.js';
|
|
@@ -23,6 +23,8 @@ const CODEX_RUNTIME_CAPABILITIES = {
|
|
|
23
23
|
};
|
|
24
24
|
let workingDir = process.cwd();
|
|
25
25
|
let workspaceOptions = [];
|
|
26
|
+
let workspaceRoots = [];
|
|
27
|
+
let workspaceRootMetadata = [];
|
|
26
28
|
function buildCodexRuntimeDescriptor(input) {
|
|
27
29
|
return {
|
|
28
30
|
coreControls: [
|
|
@@ -37,25 +39,32 @@ function buildCodexRuntimeDescriptor(input) {
|
|
|
37
39
|
},
|
|
38
40
|
{
|
|
39
41
|
id: 'workspace',
|
|
40
|
-
label: '
|
|
42
|
+
label: 'Project',
|
|
41
43
|
options: input.workspaces.map((workspace) => ({
|
|
42
44
|
value: workspace.id,
|
|
43
45
|
label: workspace.label,
|
|
46
|
+
...(workspace.description ? { description: workspace.description } : {}),
|
|
47
|
+
...(workspace.workspaceRootId ? { workspaceRootId: workspace.workspaceRootId } : {}),
|
|
48
|
+
...(workspace.workspaceRelativePath ? { workspaceRelativePath: workspace.workspaceRelativePath } : {}),
|
|
49
|
+
...(workspace.source ? { source: workspace.source } : {}),
|
|
44
50
|
})),
|
|
45
51
|
defaultValue: input.workspaces[0]?.id ?? null,
|
|
46
52
|
availability: 'setup',
|
|
47
53
|
liveBehavior: 'none',
|
|
48
54
|
selectionPolicy: 'inherit',
|
|
55
|
+
description: input.workspaceRoots?.length
|
|
56
|
+
? 'Choose one of the projects discovered inside the approved local roots for this host.'
|
|
57
|
+
: 'Choose one of the local projects advertised by this host.',
|
|
49
58
|
},
|
|
50
59
|
{
|
|
51
60
|
id: 'executionMode',
|
|
52
61
|
label: 'Execution mode',
|
|
53
62
|
options: input.executionModes.map((mode) => ({
|
|
54
63
|
value: mode,
|
|
55
|
-
label: mode === 'worktree' ? 'Isolated worktree' : 'Use shared
|
|
64
|
+
label: mode === 'worktree' ? 'Isolated worktree' : 'Use shared project',
|
|
56
65
|
description: mode === 'worktree'
|
|
57
|
-
? 'Creates or reuses a per-conversation git worktree under ~/.canon/conversation-worktrees when the selected
|
|
58
|
-
: 'Runs directly in the selected
|
|
66
|
+
? 'Creates or reuses a per-conversation git worktree under ~/.canon/conversation-worktrees when the selected project is a git repo.'
|
|
67
|
+
: 'Runs directly in the selected project folder. Changes happen there.',
|
|
59
68
|
})),
|
|
60
69
|
defaultValue: null,
|
|
61
70
|
availability: 'setup',
|
|
@@ -74,6 +83,29 @@ function buildCodexRuntimeDescriptor(input) {
|
|
|
74
83
|
selectionPolicy: 'inherit',
|
|
75
84
|
},
|
|
76
85
|
],
|
|
86
|
+
actions: [
|
|
87
|
+
{
|
|
88
|
+
id: 'stop',
|
|
89
|
+
label: 'Stop',
|
|
90
|
+
description: 'Interrupt the current Codex exec turn.',
|
|
91
|
+
aliases: ['stop'],
|
|
92
|
+
category: 'turn',
|
|
93
|
+
placements: ['composer_slash', 'command_palette'],
|
|
94
|
+
availability: ['busy'],
|
|
95
|
+
dispatch: { kind: 'signal', signal: 'interrupt' },
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
id: 'stop-and-clear-queue',
|
|
99
|
+
label: 'Stop & clear queue',
|
|
100
|
+
description: 'Interrupt the current Codex exec turn and drop queued Canon messages.',
|
|
101
|
+
aliases: ['stop-clear', 'clear-queue'],
|
|
102
|
+
category: 'turn',
|
|
103
|
+
placements: ['composer_slash', 'command_palette', 'session_strip'],
|
|
104
|
+
availability: ['busy_with_queue'],
|
|
105
|
+
dispatch: { kind: 'signal', signal: 'stop_and_drop' },
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
workspaceRoots: input.workspaceRoots,
|
|
77
109
|
supportsInterrupt: true,
|
|
78
110
|
streamingTextMode: 'snapshot',
|
|
79
111
|
};
|
|
@@ -104,11 +136,10 @@ async function loadSessionConfig(conversationId, agentId) {
|
|
|
104
136
|
extraStringFields: ['permissionMode'],
|
|
105
137
|
});
|
|
106
138
|
}
|
|
107
|
-
// Default to 'locked' (shared workspace) when no mode has been picked. The
|
|
108
|
-
// UI still lets owners flip to 'worktree'; this just stops sessions from
|
|
109
|
-
// failing closed when the mode has never been written.
|
|
110
139
|
function resolveSessionExecutionMode(config) {
|
|
111
|
-
|
|
140
|
+
if (config?.executionMode)
|
|
141
|
+
return config.executionMode;
|
|
142
|
+
throw new ExecutionEnvironmentError('Session config is missing an execution mode.', 'Choose Isolated worktree or Use shared project before starting this coding session.');
|
|
112
143
|
}
|
|
113
144
|
function resolveWorkspaceCwd(config) {
|
|
114
145
|
return resolveHostWorkspaceCwd({
|
|
@@ -164,6 +195,7 @@ export async function main() {
|
|
|
164
195
|
'codex-profile': { type: 'string' },
|
|
165
196
|
'add-dir': { type: 'string', multiple: true },
|
|
166
197
|
workspace: { type: 'string', multiple: true },
|
|
198
|
+
'workspace-root': { type: 'string', multiple: true },
|
|
167
199
|
config: { type: 'string', multiple: true },
|
|
168
200
|
'codex-bin': { type: 'string' },
|
|
169
201
|
'full-auto': { type: 'boolean' },
|
|
@@ -172,7 +204,17 @@ export async function main() {
|
|
|
172
204
|
strict: true,
|
|
173
205
|
});
|
|
174
206
|
workingDir = (typeof args.cwd === 'string' ? args.cwd : null) || process.cwd();
|
|
175
|
-
|
|
207
|
+
const workspaceDiscovery = buildConfiguredWorkspaceOptionsWithRoots({
|
|
208
|
+
primaryCwd: workingDir,
|
|
209
|
+
configuredWorkspaces: args.workspace ?? [],
|
|
210
|
+
workspaceRoots: args['workspace-root'] ?? [],
|
|
211
|
+
});
|
|
212
|
+
workspaceOptions = workspaceDiscovery.workspaceOptions;
|
|
213
|
+
workspaceRoots = workspaceDiscovery.workspaceRoots;
|
|
214
|
+
workspaceRootMetadata = buildPublicWorkspaceRoots(workspaceRoots);
|
|
215
|
+
for (const warning of workspaceDiscovery.warnings) {
|
|
216
|
+
console.error(`[canon-codex] ${warning}`);
|
|
217
|
+
}
|
|
176
218
|
if (typeof args['ask-for-approval'] === 'string') {
|
|
177
219
|
console.error('[canon-codex] Note: newer Codex CLI releases do not accept --ask-for-approval for `codex exec`; Canon will translate compatible legacy usage when possible.');
|
|
178
220
|
}
|
|
@@ -258,6 +300,9 @@ export async function main() {
|
|
|
258
300
|
executionMode: session.environment.mode,
|
|
259
301
|
...(session.environment.branch ? { executionBranch: session.environment.branch } : {}),
|
|
260
302
|
...(session.environment.worktreePath ? { worktreePath: session.environment.worktreePath } : {}),
|
|
303
|
+
...(resolveExecutionFallbackReason(session.environment)
|
|
304
|
+
? { executionFallbackReason: resolveExecutionFallbackReason(session.environment) ?? undefined }
|
|
305
|
+
: {}),
|
|
261
306
|
hostMode: true,
|
|
262
307
|
clientType: 'codex',
|
|
263
308
|
state: session.state.state,
|
|
@@ -291,11 +336,33 @@ export async function main() {
|
|
|
291
336
|
clearStreaming(conversationId);
|
|
292
337
|
client.setTyping(conversationId, false).catch(() => { });
|
|
293
338
|
}
|
|
339
|
+
function refreshVisibleWorkSignal(session) {
|
|
340
|
+
if (!session.running || session.closed)
|
|
341
|
+
return;
|
|
342
|
+
if (session.turnState !== 'thinking' && session.turnState !== 'tool')
|
|
343
|
+
return;
|
|
344
|
+
client.setTyping(session.conversationId, true, 'thinking').catch(() => { });
|
|
345
|
+
}
|
|
346
|
+
function startVisibleWorkSignal(session) {
|
|
347
|
+
refreshVisibleWorkSignal(session);
|
|
348
|
+
if (session.typingKeepaliveTimer)
|
|
349
|
+
return;
|
|
350
|
+
session.typingKeepaliveTimer = setInterval(() => {
|
|
351
|
+
refreshVisibleWorkSignal(session);
|
|
352
|
+
}, 3500);
|
|
353
|
+
}
|
|
354
|
+
function stopVisibleWorkSignal(session) {
|
|
355
|
+
if (session.typingKeepaliveTimer) {
|
|
356
|
+
clearInterval(session.typingKeepaliveTimer);
|
|
357
|
+
session.typingKeepaliveTimer = null;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
294
360
|
function closeSession(conversationId) {
|
|
295
361
|
const session = sessions.get(conversationId);
|
|
296
362
|
if (!session)
|
|
297
363
|
return;
|
|
298
364
|
session.closed = true;
|
|
365
|
+
stopVisibleWorkSignal(session);
|
|
299
366
|
releaseConversationEnvironment(session.environment);
|
|
300
367
|
clearStreaming(conversationId);
|
|
301
368
|
clearSessionState(conversationId, agentId).catch(() => { });
|
|
@@ -383,6 +450,7 @@ export async function main() {
|
|
|
383
450
|
currentTurnOpenedAt: null,
|
|
384
451
|
lastAcceptedIntent: null,
|
|
385
452
|
lastActivity: Date.now(),
|
|
453
|
+
typingKeepaliveTimer: null,
|
|
386
454
|
closed: false,
|
|
387
455
|
};
|
|
388
456
|
sessions.set(conversationId, session);
|
|
@@ -462,7 +530,12 @@ export async function main() {
|
|
|
462
530
|
const message = error instanceof Error ? error.message : String(error);
|
|
463
531
|
const userMessage = error instanceof ExecutionEnvironmentError ? error.userMessage : message;
|
|
464
532
|
console.error(`[canon-codex] [${input.conversationId.slice(0, 8)}] Failed to create session: ${message}`);
|
|
465
|
-
await client.sendMessage(input.conversationId, `I couldn't start a coding session for this workspace: ${userMessage}
|
|
533
|
+
await client.sendMessage(input.conversationId, `I couldn't start a coding session for this workspace: ${userMessage}`, {
|
|
534
|
+
metadata: {
|
|
535
|
+
turnSemantics: 'turn_complete',
|
|
536
|
+
turnComplete: true,
|
|
537
|
+
},
|
|
538
|
+
}).catch(() => { });
|
|
466
539
|
return;
|
|
467
540
|
}
|
|
468
541
|
const turnMetadata = normalizeTurnMetadata(input.message.metadata);
|
|
@@ -503,7 +576,7 @@ export async function main() {
|
|
|
503
576
|
await markQueuedMessageAccepted(session.conversationId, nextTurn.sourceMessageId, nextTurn.markAccepted);
|
|
504
577
|
writeState(session);
|
|
505
578
|
writeTurn(session);
|
|
506
|
-
|
|
579
|
+
startVisibleWorkSignal(session);
|
|
507
580
|
rtdbWrite(`/streaming/${session.conversationId}/${agentId}`, {
|
|
508
581
|
text: 'Thinking…',
|
|
509
582
|
status: 'thinking',
|
|
@@ -521,6 +594,8 @@ export async function main() {
|
|
|
521
594
|
if (event.type === 'message') {
|
|
522
595
|
session.turnState = 'streaming';
|
|
523
596
|
writeTurn(session);
|
|
597
|
+
stopVisibleWorkSignal(session);
|
|
598
|
+
client.setTyping(session.conversationId, false).catch(() => { });
|
|
524
599
|
rtdbWrite(`/streaming/${session.conversationId}/${agentId}`, {
|
|
525
600
|
text: event.text,
|
|
526
601
|
status: 'streaming',
|
|
@@ -531,7 +606,7 @@ export async function main() {
|
|
|
531
606
|
if (event.type === 'command.started') {
|
|
532
607
|
session.turnState = 'tool';
|
|
533
608
|
writeTurn(session);
|
|
534
|
-
|
|
609
|
+
startVisibleWorkSignal(session);
|
|
535
610
|
rtdbWrite(`/streaming/${session.conversationId}/${agentId}`, {
|
|
536
611
|
text: summarizeCommand(event.command),
|
|
537
612
|
status: 'tool',
|
|
@@ -583,6 +658,7 @@ export async function main() {
|
|
|
583
658
|
else if (result.interrupted) {
|
|
584
659
|
session.turnState = 'interrupted';
|
|
585
660
|
writeTurn(session);
|
|
661
|
+
stopVisibleWorkSignal(session);
|
|
586
662
|
clearStreaming(session.conversationId);
|
|
587
663
|
client.setTyping(session.conversationId, false).catch(() => { });
|
|
588
664
|
console.error(`[canon-codex] [${session.conversationId.slice(0, 8)}] Turn interrupted`);
|
|
@@ -605,6 +681,7 @@ export async function main() {
|
|
|
605
681
|
console.error(`[canon-codex] [${session.conversationId.slice(0, 8)}] Turn failed:`, error);
|
|
606
682
|
}
|
|
607
683
|
finally {
|
|
684
|
+
stopVisibleWorkSignal(session);
|
|
608
685
|
session.running = false;
|
|
609
686
|
session.state.state = 'idle';
|
|
610
687
|
session.turnState = 'idle';
|
|
@@ -637,6 +714,7 @@ export async function main() {
|
|
|
637
714
|
runtimeDescriptor: buildCodexRuntimeDescriptor({
|
|
638
715
|
models: [],
|
|
639
716
|
workspaces: buildPublicWorkspaceOptions(workspaceOptions),
|
|
717
|
+
workspaceRoots: workspaceRootMetadata,
|
|
640
718
|
executionModes: hostAvailableExecutionModes,
|
|
641
719
|
permissionModes: [...codexPermissionEnvelope.availablePermissionModes],
|
|
642
720
|
defaultPermissionMode: codexPermissionEnvelope.defaultPermissionMode,
|
|
@@ -683,6 +761,7 @@ export async function main() {
|
|
|
683
761
|
descriptor: runtimeDescriptor.runtimeDescriptor ?? buildCodexRuntimeDescriptor({
|
|
684
762
|
models: runtimeDescriptor.availableModels ?? [],
|
|
685
763
|
workspaces: buildPublicWorkspaceOptions(workspaceOptions),
|
|
764
|
+
workspaceRoots: workspaceRootMetadata,
|
|
686
765
|
executionModes: hostAvailableExecutionModes,
|
|
687
766
|
permissionModes: [...codexPermissionEnvelope.availablePermissionModes],
|
|
688
767
|
defaultPermissionMode: codexPermissionEnvelope.defaultPermissionMode,
|
|
@@ -699,10 +778,18 @@ export async function main() {
|
|
|
699
778
|
label: 'Live output',
|
|
700
779
|
value: 'Thinking, tools, and completed-message previews',
|
|
701
780
|
},
|
|
781
|
+
{
|
|
782
|
+
id: 'nativeActions',
|
|
783
|
+
label: 'Native actions',
|
|
784
|
+
value: 'Limited until app-server transport',
|
|
785
|
+
tone: 'warning',
|
|
786
|
+
},
|
|
702
787
|
],
|
|
703
788
|
execution: {
|
|
704
789
|
resolvedWorkspaceLabel: workspace?.label ?? workspaceId ?? null,
|
|
705
790
|
resolvedCwd: session?.cwd ?? workspace?.cwd ?? workingDir,
|
|
791
|
+
workspaceRootId: workspace?.workspaceRootId ?? null,
|
|
792
|
+
workspaceRelativePath: workspace?.workspaceRelativePath ?? null,
|
|
706
793
|
executionMode: session?.environment.mode ?? null,
|
|
707
794
|
executionBranch: session?.environment.branch ?? null,
|
|
708
795
|
worktreePath: session?.environment.worktreePath ?? null,
|
|
@@ -710,6 +797,7 @@ export async function main() {
|
|
|
710
797
|
},
|
|
711
798
|
notes: [
|
|
712
799
|
'This Codex host uses the current exec --json transport, so Canon can show thinking, tool activity, and completed assistant-message previews, but not token-by-token text deltas.',
|
|
800
|
+
'Codex review, compact/rollback, live plan/diff/reasoning updates, PTY command execution, plugin/app/MCP inventory, and structured approvals require the future app-server transport.',
|
|
713
801
|
],
|
|
714
802
|
};
|
|
715
803
|
await writeRuntimeInfo(conversationId, agentId, payload);
|
|
@@ -760,6 +848,7 @@ export async function main() {
|
|
|
760
848
|
runtimeDescriptor: buildCodexRuntimeDescriptor({
|
|
761
849
|
models: [],
|
|
762
850
|
workspaces: buildPublicWorkspaceOptions(workspaceOptions),
|
|
851
|
+
workspaceRoots: workspaceRootMetadata,
|
|
763
852
|
executionModes: hostAvailableExecutionModes,
|
|
764
853
|
permissionModes: [...codexPermissionEnvelope.availablePermissionModes],
|
|
765
854
|
defaultPermissionMode: codexPermissionEnvelope.defaultPermissionMode,
|
|
@@ -778,6 +867,7 @@ export async function main() {
|
|
|
778
867
|
runtimeDescriptor: buildCodexRuntimeDescriptor({
|
|
779
868
|
models: [],
|
|
780
869
|
workspaces: buildPublicWorkspaceOptions(workspaceOptions),
|
|
870
|
+
workspaceRoots: workspaceRootMetadata,
|
|
781
871
|
executionModes: hostAvailableExecutionModes,
|
|
782
872
|
permissionModes: [...codexPermissionEnvelope.availablePermissionModes],
|
|
783
873
|
defaultPermissionMode: codexPermissionEnvelope.defaultPermissionMode,
|
package/dist/setup.js
CHANGED
|
@@ -21,8 +21,10 @@ export function main() {
|
|
|
21
21
|
console.log('');
|
|
22
22
|
console.log(' 2. Start the host in a project directory and keep it running');
|
|
23
23
|
console.log(' canon-codex --cwd /path/to/project');
|
|
24
|
+
console.log(' canon-codex --cwd ~/dev --workspace-root ~/dev');
|
|
24
25
|
console.log('');
|
|
25
26
|
console.log(' A git repo is not required; any readable directory works.');
|
|
27
|
+
console.log(' Use --workspace-root to let Canon offer discovered projects inside an approved root.');
|
|
26
28
|
console.log('');
|
|
27
29
|
console.log('Optional flags:');
|
|
28
30
|
console.log(' --model gpt-5.4');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonmsg/codex-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Canon host integration for Codex CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"prepack": "npm run build"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@canonmsg/agent-sdk": "^0.9.
|
|
33
|
-
"@canonmsg/core": "^0.
|
|
32
|
+
"@canonmsg/agent-sdk": "^0.9.2",
|
|
33
|
+
"@canonmsg/core": "^0.10.0"
|
|
34
34
|
},
|
|
35
35
|
"engines": {
|
|
36
36
|
"node": ">=18.0.0"
|