maka-agent 0.2.0-dev.46.20260922 → 0.2.0-dev.48.20260923
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/DISCLAIMER-WIP +6 -1
- package/README.md +6 -1
- package/dist/acp/maka-acp-agent.js +1 -1
- package/dist/acp/session-mcp.js +212 -0
- package/dist/acp/session-registry.js +52 -8
- package/dist/acp/stdio-server.js +3 -0
- package/dist/cli-core.js +1 -1
- package/dist/mcp-capability-provider.js +6 -1
- package/dist/mcp-capability-publication.js +139 -0
- package/dist/pi-tui-layout.js +46 -17
- package/dist/pi-tui-pickers.js +25 -14
- package/dist/pi-tui-runner.js +24 -15
- package/dist/runtime-host-capability-provider-command.js +25 -6
- package/dist/runtime-host-service-manager.js +26 -2
- package/dist/tui-context-refresh.js +15 -26
- package/dist/tui-mcp-control.js +66 -112
- package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
- package/node_modules/@maka/acp-executor-plugin/dist/acp-errors.js +26 -0
- package/node_modules/@maka/acp-executor-plugin/dist/acp-filesystem.js +103 -0
- package/node_modules/@maka/acp-executor-plugin/dist/acp-process.js +119 -0
- package/node_modules/@maka/acp-executor-plugin/dist/acp-projection.js +146 -0
- package/node_modules/@maka/acp-executor-plugin/dist/index.js +653 -0
- package/node_modules/@maka/acp-executor-plugin/dist/plugin.mjs +24446 -0
- package/node_modules/@maka/acp-executor-plugin/package.json +15 -0
- package/node_modules/@maka/antigravity-acp-plugin/dist/index.js +88 -0
- package/node_modules/@maka/antigravity-acp-plugin/dist/model-presentation.js +53 -0
- package/node_modules/@maka/antigravity-acp-plugin/dist/plugin.mjs +115 -0
- package/node_modules/@maka/antigravity-acp-plugin/package.json +15 -0
- package/node_modules/@maka/core/dist/client-capability-grant.js +2 -2
- package/node_modules/@maka/core/dist/executor-catalog.js +106 -0
- package/node_modules/@maka/core/dist/mcp.js +4 -1
- package/node_modules/@maka/core/dist/model-metadata.js +28 -1
- package/node_modules/@maka/core/dist/model-thinking.js +36 -1
- package/node_modules/@maka/core/dist/provider-registry.js +0 -1
- package/node_modules/@maka/core/dist/refresh-read-coordinator.js +62 -0
- package/node_modules/@maka/core/dist/runtime-event-store.js +25 -0
- package/node_modules/@maka/core/dist/runtime-invocation.js +5 -0
- package/node_modules/@maka/core/dist/runtime-policy/connection-catalog-codec.js +4 -0
- package/node_modules/@maka/core/dist/runtime-policy/credential-vault-codec.js +6 -0
- package/node_modules/@maka/core/dist/runtime-policy/policy-codec.js +21 -0
- package/node_modules/@maka/core/dist/session.js +19 -1
- package/node_modules/@maka/core/dist/settings.js +3 -0
- package/node_modules/@maka/core/dist/tool-ledger-scanner.js +365 -104
- package/node_modules/@maka/core/dist/turn-origin.js +14 -0
- package/node_modules/@maka/core/package.json +3 -0
- package/node_modules/@maka/mcp/dist/credential-coordinator.js +6 -1
- package/node_modules/@maka/mcp/dist/index.js +31 -5
- package/node_modules/@maka/mcp/dist/oauth.js +54 -6
- package/node_modules/@maka/runtime/dist/agent-run-inspect.js +1 -1
- package/node_modules/@maka/runtime/dist/ai-sdk-message-projection.js +15 -60
- package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +18 -0
- package/node_modules/@maka/runtime/dist/apply-patch-profile.js +64 -14
- package/node_modules/@maka/runtime/dist/builtin-tools.js +3 -2
- package/node_modules/@maka/runtime/dist/codex-v4a-patch.js +18 -0
- package/node_modules/@maka/runtime/dist/conversation-copy.js +56 -1
- package/node_modules/@maka/runtime/dist/mcp-tools.js +9 -2
- package/node_modules/@maka/runtime/dist/model-adapter.js +80 -3
- package/node_modules/@maka/runtime/dist/model-runtime.js +6 -0
- package/node_modules/@maka/runtime/dist/openai-apply-patch.js +5 -0
- package/node_modules/@maka/runtime/dist/plugin-executor-backend.js +122 -3
- package/node_modules/@maka/runtime/dist/plugin-executor-service.js +212 -16
- package/node_modules/@maka/runtime/dist/runtime-ledger-repair.js +2 -2
- package/node_modules/@maka/runtime/dist/session-event-runtime-mapper.js +3 -0
- package/node_modules/@maka/runtime/dist/session-manager.js +184 -126
- package/node_modules/@maka/runtime/dist/shell-run-manager.js +3 -0
- package/node_modules/@maka/runtime/dist/stream-graph-coordinator.js +29 -4
- package/node_modules/@maka/runtime-host/dist/candidate-entry.js +8 -5
- package/node_modules/@maka/runtime-host/dist/client/capability-provider-service.js +2 -0
- package/node_modules/@maka/runtime-host/dist/client/client-capability-channel.js +59 -20
- package/node_modules/@maka/runtime-host/dist/client/connection.js +6 -4
- package/node_modules/@maka/runtime-host/dist/client/index.js +1 -1
- package/node_modules/@maka/runtime-host/dist/client/reconnect-lifecycle.js +8 -1
- package/node_modules/@maka/runtime-host/dist/client/reconnecting-connection.js +4 -4
- package/node_modules/@maka/runtime-host/dist/client/session-catalog-summary.js +6 -1
- package/node_modules/@maka/runtime-host/dist/composition-identity.js +19 -0
- package/node_modules/@maka/runtime-host/dist/protocol/client-capability.js +20 -3
- package/node_modules/@maka/runtime-host/dist/protocol/external-session.js +8 -5
- package/node_modules/@maka/runtime-host/dist/protocol/index.js +20 -2
- package/node_modules/@maka/runtime-host/dist/protocol/plugin-platform.js +34 -0
- package/node_modules/@maka/runtime-host/dist/protocol/session-catalog.js +75 -5
- package/node_modules/@maka/runtime-host/dist/protocol/workhub-coordination.js +1 -5
- package/node_modules/@maka/runtime-host/dist/server/builtin-external-agent-plugins.js +188 -0
- package/node_modules/@maka/runtime-host/dist/server/candidate.js +12 -7
- package/node_modules/@maka/runtime-host/dist/server/client-capability-coordinator.js +234 -70
- package/node_modules/@maka/runtime-host/dist/server/client-capability-invocation-broker.js +14 -8
- package/node_modules/@maka/runtime-host/dist/server/client-capability-recovery.js +44 -46
- package/node_modules/@maka/runtime-host/dist/server/context-coordinator.js +2 -0
- package/node_modules/@maka/runtime-host/dist/server/execution-composition-factory.js +1 -1
- package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +188 -21
- package/node_modules/@maka/runtime-host/dist/server/execution-model-authority.js +6 -0
- package/node_modules/@maka/runtime-host/dist/server/extension-bundle.js +4 -0
- package/node_modules/@maka/runtime-host/dist/server/external-session-coordinator.js +29 -7
- package/node_modules/@maka/runtime-host/dist/server/host-composition-source.js +47 -0
- package/node_modules/@maka/runtime-host/dist/server/host-composition.js +1 -29
- package/node_modules/@maka/runtime-host/dist/server/host-kernel.js +2 -9
- package/node_modules/@maka/runtime-host/dist/server/hosted-execution-recovery.js +75 -9
- package/node_modules/@maka/runtime-host/dist/server/hosted-execution-tool-profile.js +5 -1
- package/node_modules/@maka/runtime-host/dist/server/interaction-coordinator.js +45 -0
- package/node_modules/@maka/runtime-host/dist/server/jev-routing-model.js +157 -0
- package/node_modules/@maka/runtime-host/dist/server/listener-set.js +2 -2
- package/node_modules/@maka/runtime-host/dist/server/message-coordinator.js +4 -0
- package/node_modules/@maka/runtime-host/dist/server/plugin-platform-coordinator.js +11 -1
- package/node_modules/@maka/runtime-host/dist/server/process-lifecycle.js +1 -1
- package/node_modules/@maka/runtime-host/dist/server/process-termination-error.js +27 -0
- package/node_modules/@maka/runtime-host/dist/server/root-turn-coordinator.js +91 -12
- package/node_modules/@maka/runtime-host/dist/server/runtime-policy-coordinator.js +2 -0
- package/node_modules/@maka/runtime-host/dist/server/session-bundle-coordinator.js +4 -1
- package/node_modules/@maka/runtime-host/dist/server/session-catalog-coordinator.js +128 -13
- package/node_modules/@maka/runtime-host/dist/server/session-effect-coordinator.js +12 -6
- package/node_modules/@maka/runtime-host/dist/server/session-retirement-coordinator.js +2 -2
- package/node_modules/@maka/runtime-host/dist/server/session-transcript-reader.js +33 -0
- package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-coordinator.js +4 -0
- package/node_modules/@maka/runtime-host/dist/server/workhub-result-coordinator.js +173 -0
- package/node_modules/@maka/runtime-host/dist/server/workhub-result-runtime.js +293 -0
- package/node_modules/@maka/runtime-host/package.json +2 -0
- package/node_modules/@maka/storage/dist/agent-run-store-contract.js +8 -0
- package/node_modules/@maka/storage/dist/execution-stores.js +15 -3
- package/node_modules/@maka/storage/dist/mcp-config-store.js +91 -2
- package/node_modules/@maka/storage/dist/operational-state-store.js +15 -1
- package/node_modules/@maka/storage/dist/plan-authority.js +2 -0
- package/node_modules/@maka/storage/dist/plan-store.js +30 -0
- package/node_modules/@maka/storage/dist/runtime-event-persistence.js +1 -0
- package/node_modules/@maka/storage/dist/runtime-policy/credential-vault-document.js +4 -1
- package/node_modules/@maka/storage/dist/runtime-policy/policy-document.js +2 -0
- package/node_modules/@maka/storage/dist/session-store-values.js +16 -4
- package/node_modules/@maka/storage/dist/shell-run-authority.js +1 -0
- package/node_modules/@maka/storage/dist/shell-run-store.js +15 -0
- package/node_modules/@maka/storage/dist/sqlite-runtime-schema.js +74 -1
- package/node_modules/@maka/storage/dist/sqlite-runtime-store.js +724 -84
- package/node_modules/@maka/storage/dist/sqlite-session-metadata-store.js +16 -0
- package/package.json +1 -1
|
@@ -23,6 +23,7 @@ import { decodePersistedToolResultContent } from '@maka/core/tool-result-record-
|
|
|
23
23
|
import { isEmittedAgentRunEventType } from '@maka/core/agent-run';
|
|
24
24
|
import { decodeModelCallAttempt, MODEL_CALL_ATTEMPT_EVENT_TYPE, } from '@maka/core/model-call-attempt';
|
|
25
25
|
import { TOOL_RECOVERY_DECISION_FACT_KIND } from '@maka/core/tool-recovery-fact';
|
|
26
|
+
import { canonicalToolArgsHash } from '@maka/core/tool-args-identity';
|
|
26
27
|
import { buildHistoryCompactCheckpoint, historyCompactSourceDigest, matchHistoryCompactCheckpointPrefix, validateHistoryCompactCheckpointShape, } from './history-compact-checkpoint.js';
|
|
27
28
|
import { findCheckpointSummaryDefect } from './history-compact-summary-validation.js';
|
|
28
29
|
import { isHistoryCompactContentEvent } from './history-compaction.js';
|
|
@@ -281,6 +282,20 @@ function assertConversationRuntimeLedgerCopySupported(run, runtimeEvents) {
|
|
|
281
282
|
error.code = 'branch_runtime_fact_rewrite_unsupported';
|
|
282
283
|
throw error;
|
|
283
284
|
}
|
|
285
|
+
/**
|
|
286
|
+
* Mirrors the T1 scanner's identity semantics: a call whose args are not
|
|
287
|
+
* strict JSON cannot authenticate, which the scanner surfaces as a
|
|
288
|
+
* `canonical_args_hash_conflict` rather than an exception — so the copy pass
|
|
289
|
+
* must see `undefined` there, not a thrown error.
|
|
290
|
+
*/
|
|
291
|
+
const tryCanonicalToolArgsHash = (toolName, args) => {
|
|
292
|
+
try {
|
|
293
|
+
return canonicalToolArgsHash(toolName, args);
|
|
294
|
+
}
|
|
295
|
+
catch {
|
|
296
|
+
return undefined;
|
|
297
|
+
}
|
|
298
|
+
};
|
|
284
299
|
export async function cloneConversationRuntimeLedger(input) {
|
|
285
300
|
if (input.plan.sourceSessionId !== input.referenceMap.sourceSessionId) {
|
|
286
301
|
throw new Error('Conversation copy plan does not belong to the source Session');
|
|
@@ -386,10 +401,22 @@ export async function cloneConversationRuntimeLedger(input) {
|
|
|
386
401
|
};
|
|
387
402
|
for (const sourceId of clonedEventBySourceId.keys())
|
|
388
403
|
finishTarget(sourceId);
|
|
404
|
+
// The identity rewrite changes a copied call's canonical args, so the paired
|
|
405
|
+
// dispatch's recorded hash stops authenticating them and the copied ledger
|
|
406
|
+
// fails its own T1 re-scan. Collect the source and rewritten identities per
|
|
407
|
+
// (invocation, tool call) and re-authenticate the dispatches after the
|
|
408
|
+
// rewrite pass — but only when the source dispatch actually authenticated
|
|
409
|
+
// the source call. Stamping the rewritten identity over a mismatched hash
|
|
410
|
+
// would launder an already-corrupt source ledger into a valid-looking copy
|
|
411
|
+
// instead of preserving the corruption for the re-scan to reject (#5466
|
|
412
|
+
// review). Identity derivation mirrors the scanner's semantics: args that
|
|
413
|
+
// are not strict JSON cannot authenticate at all.
|
|
414
|
+
const rewrittenArgsIdentities = new Map();
|
|
389
415
|
for (const event of clonedEventBySourceId.values()) {
|
|
390
416
|
if (event.content?.kind === 'function_call' && event.content.name === 'Read') {
|
|
391
417
|
const args = event.content.args;
|
|
392
|
-
if (args && typeof args === 'object' && 'path' in args && typeof args.path === 'string')
|
|
418
|
+
if (args && typeof args === 'object' && 'path' in args && typeof args.path === 'string') {
|
|
419
|
+
const sourceArgsHash = tryCanonicalToolArgsHash(event.content.name, args);
|
|
393
420
|
event.content = {
|
|
394
421
|
...event.content,
|
|
395
422
|
args: {
|
|
@@ -397,19 +424,47 @@ export async function cloneConversationRuntimeLedger(input) {
|
|
|
397
424
|
...rewriteReadInput(args, references, clonedEventBySourceId),
|
|
398
425
|
},
|
|
399
426
|
};
|
|
427
|
+
rewrittenArgsIdentities.set(`${event.invocationId}\u0000${event.content.id}`, {
|
|
428
|
+
sourceArgsHash,
|
|
429
|
+
rewrittenArgsHash: tryCanonicalToolArgsHash(event.content.name, event.content.args),
|
|
430
|
+
});
|
|
431
|
+
}
|
|
400
432
|
}
|
|
401
433
|
if (event.content?.kind === 'text')
|
|
402
434
|
event.content.text = rewriteCopiedText(event.content.text, references, clonedEventBySourceId);
|
|
403
435
|
if (event.content?.kind === 'function_call' && event.content.name === 'ArchiveRead') {
|
|
404
436
|
const args = event.content.args;
|
|
405
437
|
if (args && typeof args === 'object' && 'ref' in args && typeof args.ref === 'string') {
|
|
438
|
+
const sourceArgsHash = tryCanonicalToolArgsHash(event.content.name, args);
|
|
406
439
|
event.content = {
|
|
407
440
|
...event.content,
|
|
408
441
|
args: { ...args, ref: rewriteLedgerArchiveText(args.ref, references) },
|
|
409
442
|
};
|
|
443
|
+
rewrittenArgsIdentities.set(`${event.invocationId}\u0000${event.content.id}`, {
|
|
444
|
+
sourceArgsHash,
|
|
445
|
+
rewrittenArgsHash: tryCanonicalToolArgsHash(event.content.name, event.content.args),
|
|
446
|
+
});
|
|
410
447
|
}
|
|
411
448
|
}
|
|
412
449
|
}
|
|
450
|
+
if (rewrittenArgsIdentities.size > 0) {
|
|
451
|
+
for (const event of clonedEventBySourceId.values()) {
|
|
452
|
+
const dispatch = event.actions?.toolDispatch;
|
|
453
|
+
if (dispatch?.canonicalArgsHash === undefined)
|
|
454
|
+
continue;
|
|
455
|
+
const identity = rewrittenArgsIdentities.get(`${event.invocationId}\u0000${dispatch.providerToolCallId}`);
|
|
456
|
+
if (identity === undefined)
|
|
457
|
+
continue;
|
|
458
|
+
if (identity.sourceArgsHash !== dispatch.canonicalArgsHash)
|
|
459
|
+
continue;
|
|
460
|
+
if (identity.rewrittenArgsHash === undefined)
|
|
461
|
+
continue;
|
|
462
|
+
event.actions = {
|
|
463
|
+
...event.actions,
|
|
464
|
+
toolDispatch: { ...dispatch, canonicalArgsHash: identity.rewrittenArgsHash },
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
}
|
|
413
468
|
const preparedPlans = flattenedPlans.map((plan) => {
|
|
414
469
|
const runId = runIds.get(plan.run.runId);
|
|
415
470
|
const clonedOperationalEvents = plan.operationalEvents.flatMap((event) => {
|
|
@@ -136,13 +136,20 @@ function mcpToolDescription(descriptor) {
|
|
|
136
136
|
}
|
|
137
137
|
export function mcpProxyToolName(serverId, toolName) {
|
|
138
138
|
const raw = `mcp__${sanitizeNamePart(serverId)}__${sanitizeNamePart(toolName)}`;
|
|
139
|
-
|
|
139
|
+
// Preserve existing simple names; hash identities whose spelling or separators are ambiguous.
|
|
140
|
+
if (raw.length <= MAX_PROVIDER_TOOL_NAME &&
|
|
141
|
+
sanitizeNamePart(serverId) === serverId &&
|
|
142
|
+
sanitizeNamePart(toolName) === toolName &&
|
|
143
|
+
!serverId.includes('__') &&
|
|
144
|
+
!toolName.includes('__'))
|
|
140
145
|
return raw;
|
|
141
146
|
const hash = createHash('sha256')
|
|
142
147
|
.update(`${serverId}\0${toolName}`)
|
|
143
148
|
.digest('hex')
|
|
144
149
|
.slice(0, HASH_CHARS);
|
|
145
|
-
|
|
150
|
+
// A truncated name must not become another identity's unmodified name.
|
|
151
|
+
const hashed = `mcp_h__${sanitizeNamePart(serverId)}__${sanitizeNamePart(toolName)}`;
|
|
152
|
+
return `${hashed.slice(0, MAX_PROVIDER_TOOL_NAME - HASH_CHARS - 2)}__${hash}`;
|
|
146
153
|
}
|
|
147
154
|
function sanitizeNamePart(value) {
|
|
148
155
|
const sanitized = value
|
|
@@ -22,13 +22,14 @@ import { providerAuthRequiresSecret, } from '@maka/core/llm-connections';
|
|
|
22
22
|
import { lookupModelMetadata } from '@maka/core/model-metadata';
|
|
23
23
|
import { rawFinishReasonString } from './model-protocol.js';
|
|
24
24
|
import { resolveModelRuntime } from './model-runtime.js';
|
|
25
|
+
import { resolveSelectedModelContextWindow } from './context-budget-policy.js';
|
|
25
26
|
import { plaintextResponsesReasoningProviderOptions, withoutMakaResponsesState, safePlaintextResponsesReasoningItemId, } from './responses-reasoning-state.js';
|
|
26
27
|
import { classifyError, providerModelFailure } from './provider-error-classification.js';
|
|
27
28
|
import { withProviderStreamTracking, } from './provider-request-telemetry.js';
|
|
28
29
|
import { createOpenAiChatReasoningTransportState, openAiChatReasoningFieldProviderOptions, restoreOpenAiChatEmptyReasoning, } from './openai-chat-reasoning-transport.js';
|
|
29
30
|
import { mergeOpenAiResponsesProviderOptions, planOpenAiResponsesContinuation, } from './openai-responses-continuation.js';
|
|
30
31
|
import { createOpenAiResponsesTransportState, OPENAI_RESPONSES_LANE_HEADER, } from './openai-responses-websocket.js';
|
|
31
|
-
import { openAiApplyPatchProviderTool } from './openai-apply-patch.js';
|
|
32
|
+
import { openAiApplyPatchProviderTool, codexApplyPatchProviderTool } from './openai-apply-patch.js';
|
|
32
33
|
import { TOOL_SEARCH_NAME, TOOL_SEARCH_PROVIDER_NAME } from './tool-availability.js';
|
|
33
34
|
export class ModelAdapter {
|
|
34
35
|
input;
|
|
@@ -97,12 +98,40 @@ export class ModelAdapter {
|
|
|
97
98
|
maxOutputTokens() {
|
|
98
99
|
return selectedModelMaxOutputTokens(this.input.connection, this.input.modelId, this.input.providerOptions, this.runtime);
|
|
99
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Keep a provider-derived output limit from making a resumed request
|
|
103
|
+
* impossible. The token count is the last request the provider accepted, so
|
|
104
|
+
* it is a conservative lower bound for the next request. Leave a small
|
|
105
|
+
* amount of room for newly appended user/tool content because Runtime does
|
|
106
|
+
* not estimate the final prompt locally.
|
|
107
|
+
*/
|
|
108
|
+
maxOutputTokensForInput(knownInputTokens) {
|
|
109
|
+
const outputLimit = this.maxOutputTokens();
|
|
110
|
+
if (outputLimit === undefined ||
|
|
111
|
+
knownInputTokens === undefined ||
|
|
112
|
+
!Number.isFinite(knownInputTokens) ||
|
|
113
|
+
knownInputTokens < 0) {
|
|
114
|
+
return outputLimit;
|
|
115
|
+
}
|
|
116
|
+
const contextWindow = resolveSelectedModelContextWindow(this.input.connection, this.input.modelId);
|
|
117
|
+
if (contextWindow === undefined)
|
|
118
|
+
return outputLimit;
|
|
119
|
+
const thinkingBudget = this.runtime.wire === 'anthropic-messages'
|
|
120
|
+
? fixedAnthropicThinkingBudget(this.input.providerOptions)
|
|
121
|
+
: 0;
|
|
122
|
+
const available = contextWindow - Math.ceil(knownInputTokens) - CONTEXT_INPUT_GROWTH_HEADROOM - thinkingBudget;
|
|
123
|
+
// Do not turn a near-window request into a one-token success. A useful
|
|
124
|
+
// floor deliberately lets the provider reject the request, which keeps
|
|
125
|
+
// the existing reactive compaction path in control of recovery.
|
|
126
|
+
return Math.max(Math.min(outputLimit, CONTEXT_RECOVERY_OUTPUT_FLOOR), Math.min(outputLimit, available));
|
|
127
|
+
}
|
|
100
128
|
async startStream(input) {
|
|
101
129
|
const ai = await import('ai').catch((err) => {
|
|
102
130
|
throw new Error(`Failed to load 'ai' package. Run \`npm install ai\`. Inner: ${err.message}`);
|
|
103
131
|
});
|
|
104
132
|
const { streamText, wrapLanguageModel } = ai;
|
|
105
|
-
const maxOutputTokens =
|
|
133
|
+
const maxOutputTokens = input.maxOutputTokens ??
|
|
134
|
+
selectedModelMaxOutputTokens(this.input.connection, this.input.modelId, this.input.providerOptions, this.runtime);
|
|
106
135
|
let settleAccounting;
|
|
107
136
|
const terminalModel = withProviderFinishBoundary(input.model, wrapLanguageModel);
|
|
108
137
|
const trackedModel = input.providerRequestTracker
|
|
@@ -127,7 +156,7 @@ export class ModelAdapter {
|
|
|
127
156
|
sdkTools[TOOL_SEARCH_PROVIDER_NAME] = sdkTools[TOOL_SEARCH_NAME];
|
|
128
157
|
delete sdkTools[TOOL_SEARCH_NAME];
|
|
129
158
|
}
|
|
130
|
-
const fullMessages = input.messages;
|
|
159
|
+
const fullMessages = this.runtime.wire === 'openai-chat' ? lowerChatToolImages(input.messages) : input.messages;
|
|
131
160
|
const responsesLane = input.continuationKey && usesNativeOpenAiResponses(this.input.connection, this.runtime)
|
|
132
161
|
? input.continuationKey
|
|
133
162
|
: undefined;
|
|
@@ -441,6 +470,12 @@ function failedStepOutcome(failure, usage) {
|
|
|
441
470
|
continuation: 'none',
|
|
442
471
|
};
|
|
443
472
|
}
|
|
473
|
+
/**
|
|
474
|
+
* A persisted provider count describes the preceding request, not the new
|
|
475
|
+
* user message or tool result that may be appended after a restart.
|
|
476
|
+
*/
|
|
477
|
+
const CONTEXT_INPUT_GROWTH_HEADROOM = 8_000;
|
|
478
|
+
const CONTEXT_RECOVERY_OUTPUT_FLOOR = 8_000;
|
|
444
479
|
function selectedModelMaxOutputTokens(connection, modelId, providerOptions, runtime) {
|
|
445
480
|
const anthropicMessages = runtime.wire === 'anthropic-messages';
|
|
446
481
|
const kimiOpenAiChat = connection.providerType === 'kimi-coding-plan' && runtime.wire === 'openai-chat';
|
|
@@ -835,6 +870,46 @@ function translateChunk(chunk, openAiChatReasoningTransportState, runtime, runti
|
|
|
835
870
|
return [];
|
|
836
871
|
}
|
|
837
872
|
}
|
|
873
|
+
function lowerChatToolImages(messages) {
|
|
874
|
+
const result = [];
|
|
875
|
+
let images = [];
|
|
876
|
+
const flush = () => {
|
|
877
|
+
if (images.length === 0)
|
|
878
|
+
return;
|
|
879
|
+
result.push({ role: 'user', content: images });
|
|
880
|
+
images = [];
|
|
881
|
+
};
|
|
882
|
+
for (const message of messages) {
|
|
883
|
+
if (message.role !== 'tool') {
|
|
884
|
+
flush();
|
|
885
|
+
result.push(message);
|
|
886
|
+
continue;
|
|
887
|
+
}
|
|
888
|
+
result.push({
|
|
889
|
+
...message,
|
|
890
|
+
content: message.content.map((part) => {
|
|
891
|
+
if (part.type !== 'tool-result' || part.output.type !== 'content')
|
|
892
|
+
return part;
|
|
893
|
+
return {
|
|
894
|
+
...part,
|
|
895
|
+
output: {
|
|
896
|
+
...part.output,
|
|
897
|
+
value: part.output.value.map((content) => {
|
|
898
|
+
if (content.type !== 'file' || !content.mediaType.startsWith('image/'))
|
|
899
|
+
return content;
|
|
900
|
+
images.push({ type: 'text', text: `Image from tool ${part.toolName} (${part.toolCallId}):` }, content);
|
|
901
|
+
return { type: 'text', text: 'Image supplied below.' };
|
|
902
|
+
}),
|
|
903
|
+
},
|
|
904
|
+
};
|
|
905
|
+
}),
|
|
906
|
+
});
|
|
907
|
+
}
|
|
908
|
+
// Chat tool messages are text-only; attach images after the whole result group
|
|
909
|
+
// so an assistant's parallel tool calls stay paired before the next user message.
|
|
910
|
+
flush();
|
|
911
|
+
return result;
|
|
912
|
+
}
|
|
838
913
|
/**
|
|
839
914
|
* OpenAI Responses reserves the provider name `tool_search`. Keep Maka's
|
|
840
915
|
* persisted/history name intact and translate only the provider-bound copy.
|
|
@@ -898,6 +973,8 @@ function compileProviderTool(tool) {
|
|
|
898
973
|
switch (tool.kind) {
|
|
899
974
|
case 'openai-apply-patch':
|
|
900
975
|
return openAiApplyPatchProviderTool;
|
|
976
|
+
case 'codex-apply-patch':
|
|
977
|
+
return codexApplyPatchProviderTool;
|
|
901
978
|
case 'openai-web-search':
|
|
902
979
|
return openai.tools.webSearch({
|
|
903
980
|
...(tool.searchContextSize ? { searchContextSize: tool.searchContextSize } : {}),
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
import { PROVIDER_REGISTRY, effectiveBaseUrl, } from '@maka/core/llm-connections';
|
|
20
20
|
import { lookupModelMetadata, lookupModelRuntimeOverride, openAiAdapterApiProtocol, } from '@maka/core/model-metadata';
|
|
21
21
|
import { isRetiredProvider } from '@maka/core/provider-registry';
|
|
22
|
+
import { modelOverride } from '@maka/core/model-thinking';
|
|
22
23
|
import { anthropicV1BaseUrl, googleV1BetaBaseUrl, openAiResponsesBaseUrl, } from './provider-urls.js';
|
|
23
24
|
import { resolveApplyPatchProfile } from './apply-patch-profile.js';
|
|
24
25
|
export function resolveModelRuntime(connection, modelId) {
|
|
@@ -76,6 +77,11 @@ export function resolveModelRuntime(connection, modelId) {
|
|
|
76
77
|
applyPatchProfile: resolveApplyPatchProfile({
|
|
77
78
|
wire,
|
|
78
79
|
applyPatchProtocol: adapter.applyPatchProtocol,
|
|
80
|
+
enabled: modelOverride(connection, modelId)?.applyPatch,
|
|
81
|
+
customTools: wire === 'openai-responses' &&
|
|
82
|
+
(connection.providerType === 'openai' || connection.providerType === 'openai-codex') &&
|
|
83
|
+
replay.kind === 'responses' &&
|
|
84
|
+
replay.contract.adapter === 'openai',
|
|
79
85
|
}, modelId),
|
|
80
86
|
};
|
|
81
87
|
}
|
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
19
|
import { openai } from '@ai-sdk/openai';
|
|
20
|
+
import { CODEX_PATCH_DESCRIPTION, CODEX_PATCH_GRAMMAR } from './codex-v4a-patch.js';
|
|
21
|
+
export const codexApplyPatchProviderTool = openai.tools.customTool({
|
|
22
|
+
description: `${CODEX_PATCH_DESCRIPTION}\nPass raw patch text, not JSON.`,
|
|
23
|
+
format: { type: 'grammar', syntax: 'lark', definition: CODEX_PATCH_GRAMMAR },
|
|
24
|
+
});
|
|
20
25
|
export const openAiApplyPatchProviderTool = openai.tools.applyPatch({});
|
|
21
26
|
const inputSchema = openAiApplyPatchProviderTool.inputSchema;
|
|
22
27
|
export const openAiApplyPatchInputSchema = typeof inputSchema === 'function' ? inputSchema() : inputSchema;
|
|
@@ -17,13 +17,17 @@
|
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
19
|
import { randomUUID } from 'node:crypto';
|
|
20
|
+
import { redactSecrets } from '@maka/core/redaction';
|
|
20
21
|
import { AsyncEventQueue } from './async-queue.js';
|
|
21
22
|
/** Converts a small plugin executor contract into Maka's existing Run event stream. */
|
|
22
23
|
export class PluginExecutorBackend {
|
|
23
24
|
kind = 'plugin-executor';
|
|
24
25
|
sessionId;
|
|
25
26
|
#cwd;
|
|
27
|
+
#configuration;
|
|
26
28
|
#instructions;
|
|
29
|
+
#model;
|
|
30
|
+
#thinkingLevel;
|
|
27
31
|
#binding;
|
|
28
32
|
#newId;
|
|
29
33
|
#now;
|
|
@@ -32,7 +36,10 @@ export class PluginExecutorBackend {
|
|
|
32
36
|
constructor(input) {
|
|
33
37
|
this.sessionId = input.sessionId;
|
|
34
38
|
this.#cwd = input.cwd;
|
|
39
|
+
this.#configuration = input.configuration;
|
|
35
40
|
this.#instructions = input.instructions;
|
|
41
|
+
this.#model = input.model;
|
|
42
|
+
this.#thinkingLevel = input.thinkingLevel;
|
|
36
43
|
this.#binding = input.binding;
|
|
37
44
|
this.#newId = input.newId ?? randomUUID;
|
|
38
45
|
this.#now = input.now ?? Date.now;
|
|
@@ -82,6 +89,7 @@ export class PluginExecutorBackend {
|
|
|
82
89
|
const turnId = input.turnId;
|
|
83
90
|
let thinkingText = '';
|
|
84
91
|
const toolUseIds = new Map();
|
|
92
|
+
const toolOutputSequences = new Map();
|
|
85
93
|
let result;
|
|
86
94
|
let failure;
|
|
87
95
|
let failed = false;
|
|
@@ -93,6 +101,9 @@ export class PluginExecutorBackend {
|
|
|
93
101
|
conversationKey: this.sessionId,
|
|
94
102
|
text: input.text,
|
|
95
103
|
cwd: this.#cwd,
|
|
104
|
+
...(this.#model ? { model: this.#model } : {}),
|
|
105
|
+
reasoningEffort: this.#thinkingLevel ?? null,
|
|
106
|
+
...(this.#configuration ? { configuration: this.#configuration } : {}),
|
|
96
107
|
...(this.#instructions ? { instructions: this.#instructions } : {}),
|
|
97
108
|
...(input.attachments ? { attachments: input.attachments } : {}),
|
|
98
109
|
...(input.directoryReferences ? { directoryReferences: input.directoryReferences } : {}),
|
|
@@ -102,8 +113,9 @@ export class PluginExecutorBackend {
|
|
|
102
113
|
onEvent: (event) => {
|
|
103
114
|
if (event.type === 'thinking_delta')
|
|
104
115
|
thinkingText += event.text;
|
|
105
|
-
this.#publishOutputEvent(turnId, messageId, event, toolUseIds, queue);
|
|
116
|
+
this.#publishOutputEvent(turnId, messageId, event, toolUseIds, toolOutputSequences, queue);
|
|
106
117
|
},
|
|
118
|
+
onPermissionRequest: (request) => this.#requestPermission(input, request, signal, toolUseIds, queue),
|
|
107
119
|
});
|
|
108
120
|
}
|
|
109
121
|
catch (error) {
|
|
@@ -124,6 +136,81 @@ export class PluginExecutorBackend {
|
|
|
124
136
|
}
|
|
125
137
|
this.#publishResult(turnId, messageId, result, queue);
|
|
126
138
|
}
|
|
139
|
+
async #requestPermission(input, request, signal, toolUseIds, queue) {
|
|
140
|
+
const hosted = input.hostedInteraction;
|
|
141
|
+
if (!hosted || signal.aborted)
|
|
142
|
+
return { outcome: 'cancelled' };
|
|
143
|
+
const requestId = this.#newId();
|
|
144
|
+
const event = {
|
|
145
|
+
type: 'form_request',
|
|
146
|
+
id: this.#newId(),
|
|
147
|
+
turnId: input.turnId,
|
|
148
|
+
ts: this.#now(),
|
|
149
|
+
requestId,
|
|
150
|
+
toolUseId: toolUseIds.get(request.toolCallId) ?? request.toolCallId,
|
|
151
|
+
message: request.title,
|
|
152
|
+
requester: {
|
|
153
|
+
name: this.#binding.identity.displayName,
|
|
154
|
+
source: this.#binding.identity.extensionId,
|
|
155
|
+
},
|
|
156
|
+
fields: [
|
|
157
|
+
{
|
|
158
|
+
kind: 'single_select',
|
|
159
|
+
name: 'optionId',
|
|
160
|
+
label: request.kind === 'question' ? 'Question' : 'Permission',
|
|
161
|
+
required: true,
|
|
162
|
+
options: request.options.map((option) => ({
|
|
163
|
+
value: option.optionId,
|
|
164
|
+
label: option.name,
|
|
165
|
+
})),
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
};
|
|
169
|
+
let settle;
|
|
170
|
+
const answer = new Promise((resolve) => {
|
|
171
|
+
settle = resolve;
|
|
172
|
+
});
|
|
173
|
+
let settled = false;
|
|
174
|
+
const finish = (result) => {
|
|
175
|
+
if (settled)
|
|
176
|
+
return;
|
|
177
|
+
settled = true;
|
|
178
|
+
settle(result);
|
|
179
|
+
};
|
|
180
|
+
const settlement = {
|
|
181
|
+
applyAnswer: async (result) => {
|
|
182
|
+
if (result.action !== 'accept')
|
|
183
|
+
return finish({ outcome: 'cancelled' });
|
|
184
|
+
const selected = result.values.optionId;
|
|
185
|
+
if (typeof selected !== 'string' ||
|
|
186
|
+
!request.options.some((option) => option.optionId === selected)) {
|
|
187
|
+
return finish({ outcome: 'cancelled' });
|
|
188
|
+
}
|
|
189
|
+
finish({ outcome: 'selected', optionId: selected });
|
|
190
|
+
},
|
|
191
|
+
applyClosure: async () => finish({ outcome: 'cancelled' }),
|
|
192
|
+
};
|
|
193
|
+
let admission;
|
|
194
|
+
const onAbort = () => {
|
|
195
|
+
finish({ outcome: 'cancelled' });
|
|
196
|
+
void Promise.resolve().then(async () => {
|
|
197
|
+
await admission?.catch(() => undefined);
|
|
198
|
+
await hosted.withdrawFormRequest(requestId).catch(() => undefined);
|
|
199
|
+
});
|
|
200
|
+
};
|
|
201
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
202
|
+
try {
|
|
203
|
+
admission = hosted.admitFormRequest({ request: event, settlement });
|
|
204
|
+
await admission;
|
|
205
|
+
if (signal.aborted)
|
|
206
|
+
return { outcome: 'cancelled' };
|
|
207
|
+
queue.push(event);
|
|
208
|
+
return await answer;
|
|
209
|
+
}
|
|
210
|
+
finally {
|
|
211
|
+
signal.removeEventListener('abort', onAbort);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
127
214
|
#closeOptionalOutput(turnId, messageId, thinkingText, toolUseIds, queue) {
|
|
128
215
|
if (thinkingText) {
|
|
129
216
|
queue.push({
|
|
@@ -188,9 +275,10 @@ export class PluginExecutorBackend {
|
|
|
188
275
|
turnId,
|
|
189
276
|
ts: this.#now(),
|
|
190
277
|
stopReason: 'user_stop',
|
|
278
|
+
...(result.providerStopReason ? { providerStopReason: result.providerStopReason } : {}),
|
|
191
279
|
});
|
|
192
280
|
}
|
|
193
|
-
#publishOutputEvent(turnId, messageId, event, toolUseIds, queue) {
|
|
281
|
+
#publishOutputEvent(turnId, messageId, event, toolUseIds, toolOutputSequences, queue) {
|
|
194
282
|
if (event.type === 'output_delta') {
|
|
195
283
|
if (!event.text)
|
|
196
284
|
return;
|
|
@@ -233,6 +321,7 @@ export class PluginExecutorBackend {
|
|
|
233
321
|
}
|
|
234
322
|
const toolUseId = this.#newId();
|
|
235
323
|
toolUseIds.set(event.toolCallId, toolUseId);
|
|
324
|
+
toolOutputSequences.set(event.toolCallId, 0);
|
|
236
325
|
queue.push({
|
|
237
326
|
type: 'tool_start',
|
|
238
327
|
id: this.#newId(),
|
|
@@ -251,6 +340,31 @@ export class PluginExecutorBackend {
|
|
|
251
340
|
const toolUseId = toolUseIds.get(event.toolCallId);
|
|
252
341
|
if (!toolUseId)
|
|
253
342
|
return;
|
|
343
|
+
if (event.type === 'tool_output_delta') {
|
|
344
|
+
if (!event.text)
|
|
345
|
+
return;
|
|
346
|
+
const chunk = redactSecrets(event.text);
|
|
347
|
+
if (!chunk)
|
|
348
|
+
return;
|
|
349
|
+
const now = this.#now();
|
|
350
|
+
const seq = (toolOutputSequences.get(event.toolCallId) ?? 0) + 1;
|
|
351
|
+
toolOutputSequences.set(event.toolCallId, seq);
|
|
352
|
+
queue.push({
|
|
353
|
+
type: 'tool_output_delta',
|
|
354
|
+
id: this.#newId(),
|
|
355
|
+
sessionId: this.sessionId,
|
|
356
|
+
turnId,
|
|
357
|
+
ts: now,
|
|
358
|
+
toolCallId: toolUseId,
|
|
359
|
+
toolUseId,
|
|
360
|
+
seq,
|
|
361
|
+
stream: event.stream ?? 'stdout',
|
|
362
|
+
chunk,
|
|
363
|
+
redacted: chunk !== event.text,
|
|
364
|
+
createdAt: now,
|
|
365
|
+
});
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
254
368
|
if (event.type === 'tool_progress') {
|
|
255
369
|
if (!event.text)
|
|
256
370
|
return;
|
|
@@ -265,6 +379,7 @@ export class PluginExecutorBackend {
|
|
|
265
379
|
return;
|
|
266
380
|
}
|
|
267
381
|
toolUseIds.delete(event.toolCallId);
|
|
382
|
+
toolOutputSequences.delete(event.toolCallId);
|
|
268
383
|
queue.push({
|
|
269
384
|
type: 'tool_result',
|
|
270
385
|
id: this.#newId(),
|
|
@@ -273,7 +388,9 @@ export class PluginExecutorBackend {
|
|
|
273
388
|
toolUseId,
|
|
274
389
|
providerExecuted: true,
|
|
275
390
|
isError: event.isError ?? false,
|
|
276
|
-
content:
|
|
391
|
+
content: event.content.kind === 'text'
|
|
392
|
+
? event.content
|
|
393
|
+
: { kind: 'file_diff', paths: [...event.content.paths], diff: event.content.diff },
|
|
277
394
|
});
|
|
278
395
|
}
|
|
279
396
|
#publishFailure(turnId, message, code, recoverable, queue) {
|
|
@@ -305,6 +422,8 @@ function cancellationEventReason(result) {
|
|
|
305
422
|
return 'redirect';
|
|
306
423
|
if (result.reason === 'timeout')
|
|
307
424
|
return 'timeout';
|
|
425
|
+
if (result.reason === 'crash')
|
|
426
|
+
return 'crash';
|
|
308
427
|
if (result.source === 'executor_retired')
|
|
309
428
|
return 'crash';
|
|
310
429
|
return 'user_stop';
|