@canonmsg/codex-plugin 0.24.0 → 0.25.1
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/dist/codex-app-tools.d.ts +17 -0
- package/dist/codex-app-tools.js +19 -1
- package/dist/host.d.ts +29 -0
- package/dist/host.js +67 -44
- package/package.json +4 -4
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type NoReplyReportClient } from '@canonmsg/core';
|
|
1
2
|
type JsonRecord = Record<string, unknown>;
|
|
2
3
|
interface DynamicToolSpec {
|
|
3
4
|
[key: string]: unknown;
|
|
@@ -60,6 +61,22 @@ export declare function readCodexNoReplyReason(params: CodexAppToolCallParams):
|
|
|
60
61
|
* `no_reply` ack sends so the two can never drift.
|
|
61
62
|
*/
|
|
62
63
|
export declare function codexNoReplyToolResult(): DynamicToolCallResponse;
|
|
64
|
+
/**
|
|
65
|
+
* Answer a `no_reply` dynamic-tool call end to end: mark the turn silent
|
|
66
|
+
* FIRST, then report the outcome to the server (fire-and-forget telemetry,
|
|
67
|
+
* `reportNoReplyOutcome` swallows every failure), then ack the model. The
|
|
68
|
+
* report can never change the turn: a rejecting or unreachable server leaves
|
|
69
|
+
* the flag and the ack exactly as they were. `sourceMessageId` is the
|
|
70
|
+
* binding's own record of the message that started this turn — never
|
|
71
|
+
* model-supplied.
|
|
72
|
+
*/
|
|
73
|
+
export declare function answerCodexNoReply(input: {
|
|
74
|
+
client: NoReplyReportClient;
|
|
75
|
+
conversationId: string;
|
|
76
|
+
sourceMessageId: string | null;
|
|
77
|
+
params: CodexAppToolCallParams;
|
|
78
|
+
markSilenced: () => void;
|
|
79
|
+
}): DynamicToolCallResponse;
|
|
63
80
|
/** How the host should answer one `codex_app` dynamic-tool call. */
|
|
64
81
|
export type CodexAppToolDisposition = 'no-reply' | 'denied-transport' | 'denied-non-owner' | 'bridge';
|
|
65
82
|
/**
|
package/dist/codex-app-tools.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NO_REPLY_ACK_NOTE } from '@canonmsg/core';
|
|
1
|
+
import { NO_REPLY_ACK_NOTE, reportNoReplyOutcome } from '@canonmsg/core';
|
|
2
2
|
const emptyObjectSchema = {
|
|
3
3
|
type: 'object',
|
|
4
4
|
properties: {},
|
|
@@ -262,6 +262,24 @@ export function readCodexNoReplyReason(params) {
|
|
|
262
262
|
export function codexNoReplyToolResult() {
|
|
263
263
|
return toolResult(true, { status: 'acknowledged', note: NO_REPLY_ACK_NOTE });
|
|
264
264
|
}
|
|
265
|
+
/**
|
|
266
|
+
* Answer a `no_reply` dynamic-tool call end to end: mark the turn silent
|
|
267
|
+
* FIRST, then report the outcome to the server (fire-and-forget telemetry,
|
|
268
|
+
* `reportNoReplyOutcome` swallows every failure), then ack the model. The
|
|
269
|
+
* report can never change the turn: a rejecting or unreachable server leaves
|
|
270
|
+
* the flag and the ack exactly as they were. `sourceMessageId` is the
|
|
271
|
+
* binding's own record of the message that started this turn — never
|
|
272
|
+
* model-supplied.
|
|
273
|
+
*/
|
|
274
|
+
export function answerCodexNoReply(input) {
|
|
275
|
+
input.markSilenced();
|
|
276
|
+
reportNoReplyOutcome(input.client, {
|
|
277
|
+
conversationId: input.conversationId,
|
|
278
|
+
...(input.sourceMessageId ? { messageId: input.sourceMessageId } : {}),
|
|
279
|
+
reason: readCodexNoReplyReason(input.params),
|
|
280
|
+
});
|
|
281
|
+
return codexNoReplyToolResult();
|
|
282
|
+
}
|
|
265
283
|
/**
|
|
266
284
|
* The whole `codex_app` admission decision, as data.
|
|
267
285
|
*
|
package/dist/host.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { type TurnArtifactRoutingDecision, type TurnArtifactRoutingMode } from '@canonmsg/coding-agent-host';
|
|
2
3
|
import { type CanonRuntimeCommandDescriptor, type CanonRuntimeDescriptor, type CanonRuntimePresentationPolicy, type ExecutionEnvironmentMode, type WorkspaceOption, type CanonWorkspaceRootMetadata, type RuntimeStreamingPayload, type TurnLifecycleState, type TurnOutputBlock, type TurnVerbosity, type TurnVerbosityConfig } from '@canonmsg/core';
|
|
3
4
|
import { type CodexSkillMetadata } from './app-server-adapter.js';
|
|
4
5
|
import { type CodexControlOption } from './model-catalog.js';
|
|
@@ -136,5 +137,33 @@ export declare function planCodexStreamingWrite(input: {
|
|
|
136
137
|
* same decision at its `text_delta` handler.
|
|
137
138
|
*/
|
|
138
139
|
export declare function shouldStopTypingDotsOnStreamedText(turnVerbosity: TurnVerbosity): boolean;
|
|
140
|
+
/**
|
|
141
|
+
* Whether this turn may post the media it generated in the workspace.
|
|
142
|
+
*
|
|
143
|
+
* Where the shared ruling (`resolveTurnArtifactRouting`) meets this host's
|
|
144
|
+
* per-turn state, and the only place silence is resolved for Codex artifacts:
|
|
145
|
+
* `silenced` here is the RAW `no_reply` sentinel, and it is weighed against the
|
|
146
|
+
* turn's own final text by `isSilentTurnSuppressed` — the same switch the final
|
|
147
|
+
* delivery reads. Flipping `DEFAULT_SILENT_TURN_PRECEDENCE` to `advisory`
|
|
148
|
+
* therefore moves a turn's text and its files together; it cannot leave Codex
|
|
149
|
+
* talking about a chart it then withholds.
|
|
150
|
+
*
|
|
151
|
+
* `finalText` is the model's own reply, never Canon's failure notice: the
|
|
152
|
+
* notice is a host diagnostic and goes out whether the turn spoke or not.
|
|
153
|
+
*
|
|
154
|
+
* Interruption is not a parameter. Codex's `result.interrupted` branch is the
|
|
155
|
+
* one completion branch that never calls the funnel, so the axis is dead on
|
|
156
|
+
* the normal paths. The known gap is the catch branch, which routes
|
|
157
|
+
* unconditionally and IS reachable after an interrupt (a hard interrupt can
|
|
158
|
+
* make `runTurn` reject rather than resolve); an interrupted turn's artifacts
|
|
159
|
+
* can still be posted alongside the failure notice there, as they always
|
|
160
|
+
* could. Claude gates that case; matching it needs an interrupt signal Codex
|
|
161
|
+
* does not currently carry into the catch without a race.
|
|
162
|
+
*/
|
|
163
|
+
export declare function shouldRouteCodexTurnArtifacts(input: {
|
|
164
|
+
artifactRoutingMode: TurnArtifactRoutingMode | undefined;
|
|
165
|
+
silenced: boolean;
|
|
166
|
+
finalText: string | null | undefined;
|
|
167
|
+
}): TurnArtifactRoutingDecision;
|
|
139
168
|
export declare function main(): Promise<void>;
|
|
140
169
|
export {};
|
package/dist/host.js
CHANGED
|
@@ -5,11 +5,11 @@ import { spawnSync } from 'node:child_process';
|
|
|
5
5
|
import { dirname } from 'node:path';
|
|
6
6
|
import { parseArgs } from 'node:util';
|
|
7
7
|
import { getCodexImagePath, materializeMessageMedia, materializeReplyContextMedia, sendMediaFileMessage, } from '@canonmsg/agent-sdk';
|
|
8
|
-
import { buildTrailBlockId, buildUndeliverableFinalNotice, captureTurnArtifactSnapshot,
|
|
9
|
-
import { RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildRuntimeCardOutcome, resolveQuestionAllowOther, buildCanonTurnContextV2, buildConfiguredWorkspaceOptionsWithRoots, buildFirstPartyCodingRuntimeDescriptor, buildHydratedInboundContext, diffCanonMemberIds, buildPublicWorkspaceRoots, buildPublicWorkspaceOptions, buildRuntimePresentationPolicy, buildCanonInboundFrameV1, DEFAULT_FIRST_PARTY_RUNTIME_PRESENTATION, createConversationMetadataLoader, createRuntimeStatePublisher, createTypingStatusPublisher, EXECUTION_ENVIRONMENT_MODES, ExecutionEnvironmentError, CanonClient, CanonStream, DEFAULT_PARTICIPATION_HISTORY_FETCH_LIMIT, DEFAULT_RUNTIME_CAPABILITIES, FINAL_MESSAGE_HANDOFF_MS, getActiveProfileLock, decideAutoReply, initRTDBAuth, buildLocalRuntimeId, heartbeatLocalRuntimeEntry, markLocalRuntimeStopped, normalizeTurnMetadata, parseRuntimeCardV1, parseTurnVerbosityConfig, RuntimeRequestManager, prepareConversationEnvironment, loadHostSessionConfig, releaseConversationEnvironment, resolveCanonAgent, verifyResolvedAgentEnvironment, CanonApiError, loadRuntimeSessionState, sendMessageWithRetry, sendMessageWithRetryChunked, saveRuntimeSessionState, publishHostAgentRuntime, publishHostSessionSnapshots, renderCanonHostInboundContent, renderCodingHostInboundPrompt, resolveHostWorkspaceCwd, resolveSilentTurnDelivery, resolveTurnVerbosity, shouldTriggerAgentTurn, upsertLocalRuntimeEntry, } from '@canonmsg/core';
|
|
8
|
+
import { buildTrailBlockId, buildUndeliverableFinalNotice, captureTurnArtifactSnapshot, createTurnArtifactRouter, IDLE_TIMEOUT_MS, PLAN_BLOCK_TITLE, resolveTurnArtifactRouting, collectMissedInboundMessages, STARTUP_RECOVERY_MAX_MESSAGES, STARTUP_RECOVERY_PAGE_SIZE, } from '@canonmsg/coding-agent-host';
|
|
9
|
+
import { RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildRuntimeCardOutcome, resolveQuestionAllowOther, buildCanonTurnContextV2, buildConfiguredWorkspaceOptionsWithRoots, buildFirstPartyCodingRuntimeDescriptor, buildHydratedInboundContext, diffCanonMemberIds, buildPublicWorkspaceRoots, buildPublicWorkspaceOptions, buildRuntimePresentationPolicy, buildCanonInboundFrameV1, DEFAULT_FIRST_PARTY_RUNTIME_PRESENTATION, createConversationMetadataLoader, createRuntimeStatePublisher, createTypingStatusPublisher, EXECUTION_ENVIRONMENT_MODES, ExecutionEnvironmentError, CanonClient, CanonStream, DEFAULT_PARTICIPATION_HISTORY_FETCH_LIMIT, DEFAULT_RUNTIME_CAPABILITIES, FINAL_MESSAGE_HANDOFF_MS, getActiveProfileLock, decideAutoReply, initRTDBAuth, buildLocalRuntimeId, heartbeatLocalRuntimeEntry, markLocalRuntimeStopped, normalizeTurnMetadata, parseRuntimeCardV1, parseTurnVerbosityConfig, RuntimeRequestManager, prepareConversationEnvironment, loadHostSessionConfig, releaseConversationEnvironment, resolveCanonAgent, verifyResolvedAgentEnvironment, CanonApiError, loadRuntimeSessionState, sendMessageWithRetry, sendMessageWithRetryChunked, saveRuntimeSessionState, publishHostAgentRuntime, publishHostSessionSnapshots, renderCanonHostInboundContent, renderCodingHostInboundPrompt, resolveHostWorkspaceCwd, isSilentTurnSuppressed, resolveSilentTurnDelivery, resolveTurnVerbosity, shouldTriggerAgentTurn, upsertLocalRuntimeEntry, } from '@canonmsg/core';
|
|
10
10
|
import { CodexConversationAdapter, } from './adapter.js';
|
|
11
11
|
import { CodexAppServerAdapter, } from './app-server-adapter.js';
|
|
12
|
-
import { CODEX_APP_DYNAMIC_TOOLS, CODEX_NO_REPLY_MODEL_TOOL_NAME,
|
|
12
|
+
import { CODEX_APP_DYNAMIC_TOOLS, CODEX_NO_REPLY_MODEL_TOOL_NAME, answerCodexNoReply, classifyCodexAppToolRequest, deniedCodexAppToolResult, handleCodexAppToolCall, isCodexAppToolCall, readCodexNoReplyReason, } from './codex-app-tools.js';
|
|
13
13
|
import { mapCanonApprovalResultToCodexDecision, mapCodexAppServerApprovalRequest, } from './app-server-approval.js';
|
|
14
14
|
import { clearStoredThreadId, buildCodexThreadPolicyFingerprint, loadStoredThreadId, saveStoredThreadId, } from './session-store.js';
|
|
15
15
|
import { deriveCodexPermissionEnvelope, mapCanonPermissionToCodex, } from './permission-mode.js';
|
|
@@ -538,6 +538,35 @@ export function planCodexStreamingWrite(input) {
|
|
|
538
538
|
export function shouldStopTypingDotsOnStreamedText(turnVerbosity) {
|
|
539
539
|
return turnVerbosity !== 'quiet';
|
|
540
540
|
}
|
|
541
|
+
/**
|
|
542
|
+
* Whether this turn may post the media it generated in the workspace.
|
|
543
|
+
*
|
|
544
|
+
* Where the shared ruling (`resolveTurnArtifactRouting`) meets this host's
|
|
545
|
+
* per-turn state, and the only place silence is resolved for Codex artifacts:
|
|
546
|
+
* `silenced` here is the RAW `no_reply` sentinel, and it is weighed against the
|
|
547
|
+
* turn's own final text by `isSilentTurnSuppressed` — the same switch the final
|
|
548
|
+
* delivery reads. Flipping `DEFAULT_SILENT_TURN_PRECEDENCE` to `advisory`
|
|
549
|
+
* therefore moves a turn's text and its files together; it cannot leave Codex
|
|
550
|
+
* talking about a chart it then withholds.
|
|
551
|
+
*
|
|
552
|
+
* `finalText` is the model's own reply, never Canon's failure notice: the
|
|
553
|
+
* notice is a host diagnostic and goes out whether the turn spoke or not.
|
|
554
|
+
*
|
|
555
|
+
* Interruption is not a parameter. Codex's `result.interrupted` branch is the
|
|
556
|
+
* one completion branch that never calls the funnel, so the axis is dead on
|
|
557
|
+
* the normal paths. The known gap is the catch branch, which routes
|
|
558
|
+
* unconditionally and IS reachable after an interrupt (a hard interrupt can
|
|
559
|
+
* make `runTurn` reject rather than resolve); an interrupted turn's artifacts
|
|
560
|
+
* can still be posted alongside the failure notice there, as they always
|
|
561
|
+
* could. Claude gates that case; matching it needs an interrupt signal Codex
|
|
562
|
+
* does not currently carry into the catch without a race.
|
|
563
|
+
*/
|
|
564
|
+
export function shouldRouteCodexTurnArtifacts(input) {
|
|
565
|
+
return resolveTurnArtifactRouting({
|
|
566
|
+
artifactRoutingMode: input.artifactRoutingMode,
|
|
567
|
+
silenced: isSilentTurnSuppressed({ silenced: input.silenced, finalText: input.finalText }),
|
|
568
|
+
});
|
|
569
|
+
}
|
|
541
570
|
export async function main() {
|
|
542
571
|
setDefaultResultOrder('ipv4first');
|
|
543
572
|
const { values: args } = parseArgs({
|
|
@@ -1337,7 +1366,7 @@ export async function main() {
|
|
|
1337
1366
|
const args = isRecord(params.arguments) ? params.arguments : null;
|
|
1338
1367
|
return params.card ?? params.cardDocument ?? input?.card ?? args?.card ?? null;
|
|
1339
1368
|
}
|
|
1340
|
-
async function handleCodexServerRequest(session, request, requestingUserId) {
|
|
1369
|
+
async function handleCodexServerRequest(session, request, requestingUserId, sourceMessageId) {
|
|
1341
1370
|
const requestId = String(request.id);
|
|
1342
1371
|
const params = request.params;
|
|
1343
1372
|
const expiresAt = Date.now() + 30 * 60_000;
|
|
@@ -1350,10 +1379,16 @@ export async function main() {
|
|
|
1350
1379
|
canUseAppTools: session.currentTurnCanUseCodexAppTools,
|
|
1351
1380
|
});
|
|
1352
1381
|
if (disposition === 'no-reply') {
|
|
1353
|
-
|
|
1382
|
+
const result = answerCodexNoReply({
|
|
1383
|
+
client,
|
|
1384
|
+
conversationId: session.conversationId,
|
|
1385
|
+
sourceMessageId,
|
|
1386
|
+
params,
|
|
1387
|
+
markSilenced: () => { session.currentTurnSilenced = true; },
|
|
1388
|
+
});
|
|
1354
1389
|
console.error(`[canon-codex] [${session.conversationId.slice(0, 8)}] Turn chose no_reply`
|
|
1355
1390
|
+ ` (reason: ${readCodexNoReplyReason(params) ? 'given' : 'none'})`);
|
|
1356
|
-
return
|
|
1391
|
+
return result;
|
|
1357
1392
|
}
|
|
1358
1393
|
if (disposition === 'denied-non-owner') {
|
|
1359
1394
|
return deniedCodexAppToolResult('Only the Canon owner can use codex_app tools.');
|
|
@@ -1683,34 +1718,6 @@ export async function main() {
|
|
|
1683
1718
|
},
|
|
1684
1719
|
});
|
|
1685
1720
|
}
|
|
1686
|
-
async function routeWorkspaceGeneratedArtifacts(session, baseline) {
|
|
1687
|
-
if (!baseline)
|
|
1688
|
-
return;
|
|
1689
|
-
const logPrefix = `[canon-codex] [${session.conversationId.slice(0, 8)}]`;
|
|
1690
|
-
try {
|
|
1691
|
-
const result = await collectTurnArtifacts({
|
|
1692
|
-
cwd: session.cwd,
|
|
1693
|
-
baseline,
|
|
1694
|
-
});
|
|
1695
|
-
for (const file of result.files) {
|
|
1696
|
-
try {
|
|
1697
|
-
const { messageId } = await sendTurnArtifactFile(session, file);
|
|
1698
|
-
console.error(`${logPrefix} Routed generated artifact ${file.relativePath ?? file.fileName} (${messageId})`);
|
|
1699
|
-
}
|
|
1700
|
-
catch (error) {
|
|
1701
|
-
console.error(`${logPrefix} Artifact upload failed for ${file.relativePath ?? file.fileName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
1702
|
-
}
|
|
1703
|
-
}
|
|
1704
|
-
for (const skipped of result.skipped) {
|
|
1705
|
-
if (skipped.reason === 'too-large' || skipped.reason === 'file-cap' || skipped.reason === 'scan-limit') {
|
|
1706
|
-
console.error(`${logPrefix} Artifact skipped ${skipped.fileName} (${skipped.reason})`);
|
|
1707
|
-
}
|
|
1708
|
-
}
|
|
1709
|
-
}
|
|
1710
|
-
catch (error) {
|
|
1711
|
-
console.error(`${logPrefix} Artifact routing failed:`, error instanceof Error ? error.message : error);
|
|
1712
|
-
}
|
|
1713
|
-
}
|
|
1714
1721
|
async function runNextTurn(session) {
|
|
1715
1722
|
if (session.running || session.closed)
|
|
1716
1723
|
return;
|
|
@@ -1757,15 +1764,27 @@ export async function main() {
|
|
|
1757
1764
|
writeCodexStreaming(session, '', 'thinking');
|
|
1758
1765
|
}
|
|
1759
1766
|
let artifactBaseline = null;
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1767
|
+
// The model's own reply for this turn, once it is known. Read by the gate
|
|
1768
|
+
// below so silence is weighed against the SAME text the final delivery
|
|
1769
|
+
// weighs it against; null while the turn runs and after a throw, which is
|
|
1770
|
+
// the honest answer — no reply was produced.
|
|
1771
|
+
let turnFinalText = null;
|
|
1772
|
+
// Every completion branch below funnels through this router, and it owns
|
|
1773
|
+
// the collect-and-post loop, so there is no un-gated path left to the
|
|
1774
|
+
// workspace: the failure branches still send Canon's notice, and none of
|
|
1775
|
+
// them can post the artifacts of a turn that chose silence.
|
|
1776
|
+
const artifactRouter = createTurnArtifactRouter({
|
|
1777
|
+
decide: () => shouldRouteCodexTurnArtifacts({
|
|
1778
|
+
artifactRoutingMode: nextTurn.artifactRoutingMode,
|
|
1779
|
+
silenced: session.currentTurnSilenced,
|
|
1780
|
+
finalText: turnFinalText,
|
|
1781
|
+
}),
|
|
1782
|
+
baseline: () => artifactBaseline,
|
|
1783
|
+
cwd: () => session.cwd,
|
|
1784
|
+
send: (file) => sendTurnArtifactFile(session, file),
|
|
1785
|
+
log: (line) => console.error(`[canon-codex] [${session.conversationId.slice(0, 8)}] ${line}`),
|
|
1786
|
+
});
|
|
1787
|
+
const routeArtifactsOnce = artifactRouter.route;
|
|
1769
1788
|
try {
|
|
1770
1789
|
const turnId = session.currentTurnId ?? randomUUID();
|
|
1771
1790
|
session.currentTurnId = turnId;
|
|
@@ -1911,7 +1930,7 @@ export async function main() {
|
|
|
1911
1930
|
};
|
|
1912
1931
|
const runTurnOnce = () => session.adapter.runTurn(turnPrompt, handleCodexEvent, logCodexLine, turnImagePaths, turnMediaAddDirs, {
|
|
1913
1932
|
planMode: nextTurn.planMode,
|
|
1914
|
-
onServerRequest: (request) => handleCodexServerRequest(session, request, nextTurn.requestingUserId ?? null),
|
|
1933
|
+
onServerRequest: (request) => handleCodexServerRequest(session, request, nextTurn.requestingUserId ?? null, nextTurn.sourceMessageId ?? null),
|
|
1915
1934
|
});
|
|
1916
1935
|
let result = await runTurnOnce();
|
|
1917
1936
|
if (!result.interrupted
|
|
@@ -1928,6 +1947,10 @@ export async function main() {
|
|
|
1928
1947
|
session.currentTurnSilenced = false;
|
|
1929
1948
|
result = await runTurnOnce();
|
|
1930
1949
|
}
|
|
1950
|
+
// Both the artifact gate and the final delivery weigh silence against
|
|
1951
|
+
// this text, and they must weigh the same one — set it before any
|
|
1952
|
+
// completion branch runs, including the ones that route first.
|
|
1953
|
+
turnFinalText = result.finalMessage ?? null;
|
|
1931
1954
|
if (session.adapter instanceof CodexAppServerAdapter) {
|
|
1932
1955
|
const resolvedModel = session.adapter.getResolvedModel();
|
|
1933
1956
|
const resolvedEffort = session.adapter.getResolvedReasoningEffort();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonmsg/codex-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.1",
|
|
4
4
|
"description": "Canon host integration for Codex CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"prepack": "npm run build"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@canonmsg/agent-sdk": "^8.
|
|
33
|
-
"@canonmsg/coding-agent-host": "^0.
|
|
34
|
-
"@canonmsg/core": "^10.
|
|
32
|
+
"@canonmsg/agent-sdk": "^8.3.0",
|
|
33
|
+
"@canonmsg/coding-agent-host": "^0.5.0",
|
|
34
|
+
"@canonmsg/core": "^10.2.0"
|
|
35
35
|
},
|
|
36
36
|
"engines": {
|
|
37
37
|
"node": ">=18.0.0"
|