@canonmsg/codex-plugin 0.25.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.js +11 -5
- package/package.json +3 -3
|
@@ -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.js
CHANGED
|
@@ -9,7 +9,7 @@ import { buildTrailBlockId, buildUndeliverableFinalNotice, captureTurnArtifactSn
|
|
|
9
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';
|
|
@@ -1366,7 +1366,7 @@ export async function main() {
|
|
|
1366
1366
|
const args = isRecord(params.arguments) ? params.arguments : null;
|
|
1367
1367
|
return params.card ?? params.cardDocument ?? input?.card ?? args?.card ?? null;
|
|
1368
1368
|
}
|
|
1369
|
-
async function handleCodexServerRequest(session, request, requestingUserId) {
|
|
1369
|
+
async function handleCodexServerRequest(session, request, requestingUserId, sourceMessageId) {
|
|
1370
1370
|
const requestId = String(request.id);
|
|
1371
1371
|
const params = request.params;
|
|
1372
1372
|
const expiresAt = Date.now() + 30 * 60_000;
|
|
@@ -1379,10 +1379,16 @@ export async function main() {
|
|
|
1379
1379
|
canUseAppTools: session.currentTurnCanUseCodexAppTools,
|
|
1380
1380
|
});
|
|
1381
1381
|
if (disposition === 'no-reply') {
|
|
1382
|
-
|
|
1382
|
+
const result = answerCodexNoReply({
|
|
1383
|
+
client,
|
|
1384
|
+
conversationId: session.conversationId,
|
|
1385
|
+
sourceMessageId,
|
|
1386
|
+
params,
|
|
1387
|
+
markSilenced: () => { session.currentTurnSilenced = true; },
|
|
1388
|
+
});
|
|
1383
1389
|
console.error(`[canon-codex] [${session.conversationId.slice(0, 8)}] Turn chose no_reply`
|
|
1384
1390
|
+ ` (reason: ${readCodexNoReplyReason(params) ? 'given' : 'none'})`);
|
|
1385
|
-
return
|
|
1391
|
+
return result;
|
|
1386
1392
|
}
|
|
1387
1393
|
if (disposition === 'denied-non-owner') {
|
|
1388
1394
|
return deniedCodexAppToolResult('Only the Canon owner can use codex_app tools.');
|
|
@@ -1924,7 +1930,7 @@ export async function main() {
|
|
|
1924
1930
|
};
|
|
1925
1931
|
const runTurnOnce = () => session.adapter.runTurn(turnPrompt, handleCodexEvent, logCodexLine, turnImagePaths, turnMediaAddDirs, {
|
|
1926
1932
|
planMode: nextTurn.planMode,
|
|
1927
|
-
onServerRequest: (request) => handleCodexServerRequest(session, request, nextTurn.requestingUserId ?? null),
|
|
1933
|
+
onServerRequest: (request) => handleCodexServerRequest(session, request, nextTurn.requestingUserId ?? null, nextTurn.sourceMessageId ?? null),
|
|
1928
1934
|
});
|
|
1929
1935
|
let result = await runTurnOnce();
|
|
1930
1936
|
if (!result.interrupted
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonmsg/codex-plugin",
|
|
3
|
-
"version": "0.25.
|
|
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.
|
|
32
|
+
"@canonmsg/agent-sdk": "^8.3.0",
|
|
33
33
|
"@canonmsg/coding-agent-host": "^0.5.0",
|
|
34
|
-
"@canonmsg/core": "^10.
|
|
34
|
+
"@canonmsg/core": "^10.2.0"
|
|
35
35
|
},
|
|
36
36
|
"engines": {
|
|
37
37
|
"node": ">=18.0.0"
|