maka-agent 0.2.0-dev.43.20260919 → 0.2.0-dev.45.20260921
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/LICENSE +12 -6
- package/dist/mcp-capability-provider.js +7 -0
- package/dist/runtime-host-service-manager.js +1 -6
- package/dist/runtime-host-tui-command.js +1 -1
- package/dist/runtime-host-update-command.js +39 -27
- package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
- package/node_modules/@maka/core/dist/artifacts.js +1 -0
- package/node_modules/@maka/core/dist/chat-model-choice.js +3 -0
- package/node_modules/@maka/core/dist/llm-connections.js +3 -21
- package/node_modules/@maka/core/dist/model-catalog.js +8 -20
- package/node_modules/@maka/core/dist/model-metadata.generated.js +304 -304
- package/node_modules/@maka/core/dist/model-metadata.js +1 -2
- package/node_modules/@maka/core/dist/model-thinking.js +16 -1
- package/node_modules/@maka/core/dist/models-dev-projection.js +0 -1
- package/node_modules/@maka/core/dist/provider-auth.js +1 -7
- package/node_modules/@maka/core/dist/provider-registry.js +20 -58
- package/node_modules/@maka/core/dist/recall.js +5 -1
- package/node_modules/@maka/core/dist/runtime-policy/connection-catalog-codec.js +7 -0
- package/node_modules/@maka/core/dist/runtime-policy/model-catalog-entry-codec.js +14 -1
- package/node_modules/@maka/core/dist/session-start-mode.js +2 -5
- package/node_modules/@maka/core/dist/session.js +0 -1
- package/node_modules/@maka/core/dist/settings.js +19 -3
- package/node_modules/@maka/core/dist/tool-quiet-preview.js +2 -16
- package/node_modules/@maka/core/dist/transcript-search.js +46 -0
- package/node_modules/@maka/core/package.json +1 -4
- package/node_modules/@maka/mcp/dist/index.js +22 -0
- package/node_modules/@maka/mcp/dist/oauth.js +4 -2
- package/node_modules/@maka/mcp/dist/tool-progress.js +45 -0
- package/node_modules/@maka/runtime/dist/model-factory.js +0 -16
- package/node_modules/@maka/runtime/dist/model-fetcher.js +1 -4
- package/node_modules/@maka/runtime/dist/model-runtime.js +0 -8
- package/node_modules/@maka/runtime/dist/opencode-session-header.js +2 -3
- package/node_modules/@maka/runtime/dist/recall-tools.js +4 -0
- package/node_modules/@maka/runtime/dist/session-manager.js +5 -57
- package/node_modules/@maka/runtime/dist/subagent-tools.js +69 -11
- package/node_modules/@maka/runtime/dist/test-connection.js +4 -114
- package/node_modules/@maka/runtime/package.json +0 -1
- package/node_modules/@maka/runtime-host/dist/client/client-capability-channel.js +44 -9
- package/node_modules/@maka/runtime-host/dist/client/host-handoff-copy.js +25 -18
- package/node_modules/@maka/runtime-host/dist/client/host-handoff.js +3 -1
- package/node_modules/@maka/runtime-host/dist/client/index.js +1 -1
- package/node_modules/@maka/runtime-host/dist/client/session-subscription.js +33 -3
- package/node_modules/@maka/runtime-host/dist/protocol/connection-effects.js +0 -108
- package/node_modules/@maka/runtime-host/dist/protocol/index.js +12 -1
- package/node_modules/@maka/runtime-host/dist/protocol/message.js +10 -0
- package/node_modules/@maka/runtime-host/dist/protocol/operations.js +4 -6
- package/node_modules/@maka/runtime-host/dist/protocol/recall.js +270 -0
- package/node_modules/@maka/runtime-host/dist/protocol/session-catalog.js +1 -1
- package/node_modules/@maka/runtime-host/dist/protocol/session-continuity.js +1 -7
- package/node_modules/@maka/runtime-host/dist/protocol/turn.js +0 -33
- package/node_modules/@maka/runtime-host/dist/protocol/usage-screen.js +12 -4
- package/node_modules/@maka/runtime-host/dist/server/access-credential-store.js +6 -0
- package/node_modules/@maka/runtime-host/dist/server/bootstrap-runtime-policy.js +31 -104
- package/node_modules/@maka/runtime-host/dist/server/connection-effect-coordinator.js +1 -57
- package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +11 -35
- package/node_modules/@maka/runtime-host/dist/server/interactive-run-composer.js +3 -20
- package/node_modules/@maka/runtime-host/dist/server/interactive-turn-coordinator.js +1 -16
- package/node_modules/@maka/runtime-host/dist/server/message-coordinator.js +46 -28
- package/node_modules/@maka/runtime-host/dist/server/recall-coordinator.js +117 -0
- package/node_modules/@maka/runtime-host/dist/server/root-turn-coordinator.js +5 -16
- package/node_modules/@maka/runtime-host/dist/server/session-catalog-coordinator.js +21 -12
- package/node_modules/@maka/runtime-host/dist/server/session-revision-coordinator.js +0 -4
- package/node_modules/@maka/runtime-host/dist/server/session-turn-access-request-coordinator.js +7 -17
- package/node_modules/@maka/storage/dist/artifact-metadata-codec.js +4 -3
- package/node_modules/@maka/storage/dist/artifact-store.js +1 -11
- package/node_modules/@maka/storage/dist/process-lifetime-file-update-lock.js +0 -41
- package/node_modules/@maka/storage/dist/runtime-policy/connection-catalog-document.js +0 -62
- package/node_modules/@maka/storage/dist/runtime-policy/coordinator.js +0 -31
- package/node_modules/@maka/storage/dist/runtime-policy-stores.js +0 -3
- package/node_modules/@maka/storage/dist/sqlite-usage-schema.js +29 -5
- package/node_modules/@maka/storage/dist/sqlite-workflow-schema.js +2 -0
- package/node_modules/@maka/storage/dist/storage-writer-composition.js +0 -3
- package/node_modules/@maka/storage/dist/telemetry-file-schema.js +5 -3
- package/node_modules/@maka/storage/dist/usage-screen.js +5 -6
- package/node_modules/@maka/storage/dist/usage-stores.js +14 -4
- package/node_modules/@maka/storage/package.json +0 -2
- package/package.json +1 -1
- package/node_modules/@maka/core/dist/connection-usage.js +0 -27
- package/node_modules/@maka/core/dist/deep-research-client-progress.js +0 -132
- package/node_modules/@maka/core/dist/deep-research-run.js +0 -625
- package/node_modules/@maka/core/dist/deep-research.js +0 -208
- package/node_modules/@maka/core/dist/thread-search.js +0 -498
- package/node_modules/@maka/runtime/dist/commandcode-cli-language-model.js +0 -837
- package/node_modules/@maka/runtime/dist/connection-usage.js +0 -232
- package/node_modules/@maka/runtime/dist/deep-research-tools.js +0 -732
- package/node_modules/@maka/runtime-host/dist/protocol/deep-research.js +0 -233
- package/node_modules/@maka/runtime-host/dist/server/deep-research-coordinator.js +0 -116
- package/node_modules/@maka/storage/dist/deep-research-authority.js +0 -129
- package/node_modules/@maka/storage/dist/deep-research-store.js +0 -343
|
@@ -107,35 +107,53 @@ export class HostMessageCoordinator {
|
|
|
107
107
|
}
|
|
108
108
|
return success({ cancelledMessageIds });
|
|
109
109
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
110
|
+
queryMessageExecutions(input) {
|
|
111
|
+
// Enter the Session admission the way every other admission reader does.
|
|
112
|
+
// `not_admitted` claims that no epoch ever admitted this identity, and it
|
|
113
|
+
// is only sound while no admission write can be in flight. WorkHub writes
|
|
114
|
+
// admission rows without an in-memory submit to observe, so the gate —
|
|
115
|
+
// not `#pendingSubmits` alone — is what makes the read atomic.
|
|
116
|
+
return this.#sessionAdmission.runOrJoin(input.sessionId, async () => {
|
|
117
|
+
const resolutions = [];
|
|
118
|
+
for (const messageId of input.messageIds) {
|
|
119
|
+
const disposition = await this.#resolveMessageExecution(input.sessionId, messageId);
|
|
120
|
+
if (disposition.kind === 'owned_root' || disposition.kind === 'shared_turn') {
|
|
121
|
+
// This read projects current execution, including safe-boundary
|
|
122
|
+
// continuations. The Message's durable admission ownership is unchanged.
|
|
123
|
+
const latest = await this.#root.readLatestRootTurnLineage({
|
|
124
|
+
sessionId: input.sessionId,
|
|
125
|
+
turnId: disposition.turnId,
|
|
126
|
+
runId: disposition.runId,
|
|
127
|
+
});
|
|
128
|
+
resolutions.push({
|
|
129
|
+
messageId,
|
|
130
|
+
state: 'owned',
|
|
131
|
+
turnId: latest.turnId,
|
|
132
|
+
runId: latest.runId,
|
|
133
|
+
});
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (disposition.kind === 'cancelled') {
|
|
137
|
+
resolutions.push({ messageId, state: 'cancelled' });
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
if (disposition.kind === 'pending') {
|
|
141
|
+
resolutions.push({ messageId, state: 'pending' });
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
// `recovering` means no durable receipt, steering proof, cancellation
|
|
145
|
+
// tombstone, or pending admission names this identity. Under the
|
|
146
|
+
// Session gate no admission write is in flight, so that silence is
|
|
147
|
+
// itself the proof: nothing in this epoch — or any prior one, since a
|
|
148
|
+
// stale epoch's submit can never commit here — ever admitted it.
|
|
149
|
+
// Report that fact positively instead of omitting the identity, so a
|
|
150
|
+
// missing entry stops meaning both "not admitted" and "cannot say yet".
|
|
151
|
+
if (this.#pendingSubmits.has(operationKey(input.sessionId, messageId)))
|
|
152
|
+
continue;
|
|
153
|
+
resolutions.push({ messageId, state: 'not_admitted' });
|
|
136
154
|
}
|
|
137
|
-
|
|
138
|
-
|
|
155
|
+
return success({ resolutions });
|
|
156
|
+
});
|
|
139
157
|
}
|
|
140
158
|
/**
|
|
141
159
|
* Cancels exactly one durable pending Message, or returns the Turn that has
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed to the Apache Software Foundation (ASF) under one
|
|
3
|
+
* or more contributor license agreements. See the NOTICE file
|
|
4
|
+
* distributed with this work for additional information
|
|
5
|
+
* regarding copyright ownership. The ASF licenses this file
|
|
6
|
+
* to you under the Apache License, Version 2.0 (the
|
|
7
|
+
* "License"); you may not use this file except in compliance
|
|
8
|
+
* with the License. You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing,
|
|
13
|
+
* software distributed under the License is distributed on an
|
|
14
|
+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
15
|
+
* KIND, either express or implied. See the License for the
|
|
16
|
+
* specific language governing permissions and limitations
|
|
17
|
+
* under the License.
|
|
18
|
+
*/
|
|
19
|
+
import { runRecall } from '@maka/core/recall';
|
|
20
|
+
/**
|
|
21
|
+
* Serves `recall.query` from the same dependency graph the model's `Recall`
|
|
22
|
+
* tool uses.
|
|
23
|
+
*
|
|
24
|
+
* The point of this coordinator is that it owns no retrieval logic: it hands
|
|
25
|
+
* the request to `runRecall` and projects the answer. Whatever recall can see —
|
|
26
|
+
* privacy gating, archived Sessions, the distilled-fact store — a Client
|
|
27
|
+
* asking over the wire sees the same thing, because there is one implementation
|
|
28
|
+
* and this is not a second one.
|
|
29
|
+
*
|
|
30
|
+
* Unlike the model's tool, no turn is excluded. A tool call runs inside a turn
|
|
31
|
+
* and must not surface that turn's own text back as corroboration; a Client
|
|
32
|
+
* search is not inside any turn, so there is nothing to exclude.
|
|
33
|
+
*/
|
|
34
|
+
export class HostRecallCoordinator {
|
|
35
|
+
deps;
|
|
36
|
+
handlers = {
|
|
37
|
+
'recall.query': (input) => this.#query(input),
|
|
38
|
+
};
|
|
39
|
+
constructor(deps) {
|
|
40
|
+
this.deps = deps;
|
|
41
|
+
}
|
|
42
|
+
async #query(input) {
|
|
43
|
+
try {
|
|
44
|
+
const result = await runRecall(input, this.deps, { includeArchived: true });
|
|
45
|
+
return { ok: true, result: projectRecallResult(result) };
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return {
|
|
49
|
+
ok: false,
|
|
50
|
+
error: { code: 'internal_failure', message: 'Recall query failed' },
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* `RecallQueryResult` is the core result with the Host's field vocabulary.
|
|
57
|
+
*
|
|
58
|
+
* Recall already returns exactly these fields; the projection exists to drop
|
|
59
|
+
* core-internal detail and to make the boundary explicit, so a change to the
|
|
60
|
+
* core shape shows up here rather than silently widening the wire.
|
|
61
|
+
*/
|
|
62
|
+
export function projectRecallResult(result) {
|
|
63
|
+
if (!result.ok) {
|
|
64
|
+
return { ok: false, reason: result.reason, message: result.message };
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
ok: true,
|
|
68
|
+
facts: result.facts.map((fact) => ({
|
|
69
|
+
content: fact.content,
|
|
70
|
+
kind: fact.kind,
|
|
71
|
+
observedAt: fact.observedAt,
|
|
72
|
+
})),
|
|
73
|
+
passages: result.passages.map((passage) => projectPassage(passage)),
|
|
74
|
+
gaps: result.gaps,
|
|
75
|
+
searchedEverySession: result.scannedFully,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function projectPassage(passage) {
|
|
79
|
+
return {
|
|
80
|
+
sessionId: passage.sessionId,
|
|
81
|
+
sessionTitle: passage.sessionTitle,
|
|
82
|
+
...(passage.turnId ? { turnId: passage.turnId } : {}),
|
|
83
|
+
anchorMessageId: passage.anchorMessageId,
|
|
84
|
+
sequence: passage.sequence,
|
|
85
|
+
messages: passage.messages.map((message) => ({
|
|
86
|
+
messageId: message.messageId,
|
|
87
|
+
role: message.role,
|
|
88
|
+
matchKind: message.matchKind,
|
|
89
|
+
text: message.text,
|
|
90
|
+
timestamp: message.timestamp,
|
|
91
|
+
isAnchor: message.isAnchor,
|
|
92
|
+
...(message.materials
|
|
93
|
+
? {
|
|
94
|
+
materials: message.materials.map((material) => ({
|
|
95
|
+
name: material.name,
|
|
96
|
+
kind: material.kind,
|
|
97
|
+
mimeType: material.mimeType,
|
|
98
|
+
bytes: material.bytes,
|
|
99
|
+
...(material.resource ? { resource: material.resource } : {}),
|
|
100
|
+
...(material.sourceSessionId && material.materialId
|
|
101
|
+
? {
|
|
102
|
+
sourceSessionId: material.sourceSessionId,
|
|
103
|
+
materialId: material.materialId,
|
|
104
|
+
}
|
|
105
|
+
: {}),
|
|
106
|
+
})),
|
|
107
|
+
}
|
|
108
|
+
: {}),
|
|
109
|
+
})),
|
|
110
|
+
matchedTerms: passage.matchedTerms,
|
|
111
|
+
score: passage.score,
|
|
112
|
+
...(passage.lastMessageAt !== undefined ? { lastMessageAt: passage.lastMessageAt } : {}),
|
|
113
|
+
hasMoreBefore: passage.hasMoreBefore,
|
|
114
|
+
hasMoreAfter: passage.hasMoreAfter,
|
|
115
|
+
...(passage.truncated ? { truncated: true } : {}),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
@@ -27,7 +27,7 @@ import { decodeSkillInvocationResult, } from '@maka/core/skill-invocation';
|
|
|
27
27
|
import { agentGraphIdForRootSession } from '@maka/runtime/stream-graph-coordinator';
|
|
28
28
|
import { RuntimeHostedRootConflictError, RuntimeHostedRootUnavailableError, RuntimeMessageAuthorityInvariantError, } from '@maka/runtime/message-authority';
|
|
29
29
|
import { isShutdownCancelledInteractionAdmission, RuntimeInteractionAdmissionRejectedError, RuntimeInteractionFailStopError, RuntimeInteractionInvariantError, } from '@maka/runtime/interaction-authority';
|
|
30
|
-
import { normalizeStopSessionSource,
|
|
30
|
+
import { normalizeStopSessionSource, } from '@maka/runtime/session-manager';
|
|
31
31
|
import { RuntimeOwnerCleanupError } from '@maka/runtime/runtime-kernel';
|
|
32
32
|
import { parseSkillInvocationTokens, } from '@maka/runtime/skill-invocation';
|
|
33
33
|
import { skillInvocationInlineReferences } from '@maka/runtime/skill-invocation-receipt';
|
|
@@ -1422,21 +1422,10 @@ export class RootTurnCoordinator {
|
|
|
1422
1422
|
return { kind: 'ready', content: request.content };
|
|
1423
1423
|
if ('prepareFreshContent' in request)
|
|
1424
1424
|
return request.prepareFreshContent(lease);
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
};
|
|
1430
|
-
}
|
|
1431
|
-
catch (error) {
|
|
1432
|
-
if (error instanceof RuntimeRegenerateTurnError) {
|
|
1433
|
-
return {
|
|
1434
|
-
kind: 'rejected',
|
|
1435
|
-
outcome: error.code === 'not_found' ? notFound(error.message) : operationConflict(error.message),
|
|
1436
|
-
};
|
|
1437
|
-
}
|
|
1438
|
-
throw error;
|
|
1439
|
-
}
|
|
1425
|
+
return {
|
|
1426
|
+
kind: 'ready',
|
|
1427
|
+
content: normalizeMessageContent(await request.prepareContent()),
|
|
1428
|
+
};
|
|
1440
1429
|
}
|
|
1441
1430
|
async queryTurnResume(input, context) {
|
|
1442
1431
|
if (isWorkHubCoordinationSessionId(input.sessionId)) {
|
|
@@ -21,7 +21,7 @@ import { RuntimeHostProtocolError } from '../protocol/errors.js';
|
|
|
21
21
|
import { createHash } from 'node:crypto';
|
|
22
22
|
import { authorizeConnectionModel, connectionEnabledModelIds } from '@maka/core/llm-connections';
|
|
23
23
|
import { isModelExplicitlyUnsupportedForChat } from '@maka/core/model-catalog';
|
|
24
|
-
import { thinkingVariantsForConnection } from '@maka/core/model-thinking';
|
|
24
|
+
import { defaultThinkingLevelForConnection, thinkingVariantsForConnection, } from '@maka/core/model-thinking';
|
|
25
25
|
import { executionBoundaryDisplayMode, } from '@maka/core/sandbox-boundary';
|
|
26
26
|
import { isExecutorId } from '@maka/core/executor-id';
|
|
27
27
|
import { DEFAULT_SESSION_NAME, normalizeUserSessionName } from '@maka/core/session-name';
|
|
@@ -184,7 +184,7 @@ export class HostSessionCatalogCoordinator {
|
|
|
184
184
|
*/
|
|
185
185
|
async resolveDefaultCreateTarget() {
|
|
186
186
|
try {
|
|
187
|
-
return await this.#composeCreateTarget(this.#resolveModel({ kind: 'default' }, undefined));
|
|
187
|
+
return await this.#composeCreateTarget(this.#resolveModel({ kind: 'default' }, undefined, true));
|
|
188
188
|
}
|
|
189
189
|
catch (error) {
|
|
190
190
|
if (error instanceof SessionOperationFailure &&
|
|
@@ -200,6 +200,7 @@ export class HostSessionCatalogCoordinator {
|
|
|
200
200
|
llmConnectionId: model.connectionId,
|
|
201
201
|
llmConnectionSlug: model.connectionSlug,
|
|
202
202
|
model: model.model,
|
|
203
|
+
...(model.thinkingLevel === undefined ? {} : { thinkingLevel: model.thinkingLevel }),
|
|
203
204
|
permissionMode: policy.policy.chatDefaults.permissionMode,
|
|
204
205
|
toolMode: policy.policy.chatDefaults.codeModeEnabled ? 'code_mode' : 'direct',
|
|
205
206
|
collaborationMode: 'agent',
|
|
@@ -235,7 +236,7 @@ export class HostSessionCatalogCoordinator {
|
|
|
235
236
|
...(model.connectionId ? { llmConnectionId: model.connectionId } : {}),
|
|
236
237
|
llmConnectionSlug: model.connectionSlug,
|
|
237
238
|
model: model.model,
|
|
238
|
-
...(
|
|
239
|
+
...(model.thinkingLevel === undefined ? {} : { thinkingLevel: model.thinkingLevel }),
|
|
239
240
|
...(input.toolProfile === undefined ? {} : { toolProfile: input.toolProfile }),
|
|
240
241
|
permissionMode: prepared.permissionMode ?? policy.policy.chatDefaults.permissionMode,
|
|
241
242
|
toolMode: policy.policy.chatDefaults.codeModeEnabled ? 'code_mode' : 'direct',
|
|
@@ -405,7 +406,7 @@ export class HostSessionCatalogCoordinator {
|
|
|
405
406
|
...(model.connectionId ? { llmConnectionId: model.connectionId } : {}),
|
|
406
407
|
llmConnectionSlug: model.connectionSlug,
|
|
407
408
|
model: model.model,
|
|
408
|
-
...(
|
|
409
|
+
...(model.thinkingLevel === undefined ? {} : { thinkingLevel: model.thinkingLevel }),
|
|
409
410
|
...(input.toolProfile === undefined ? {} : { toolProfile: input.toolProfile }),
|
|
410
411
|
permissionMode: prepared.permissionMode ?? policy.policy.chatDefaults.permissionMode,
|
|
411
412
|
toolMode: toolMode ?? (policy.policy.chatDefaults.codeModeEnabled ? 'code_mode' : 'direct'),
|
|
@@ -715,7 +716,7 @@ export class HostSessionCatalogCoordinator {
|
|
|
715
716
|
connectionId: candidate.connectionId,
|
|
716
717
|
connectionSlug: candidate.connectionSlug,
|
|
717
718
|
model: candidate.modelId,
|
|
718
|
-
}, undefined);
|
|
719
|
+
}, undefined, true);
|
|
719
720
|
}
|
|
720
721
|
catch (error) {
|
|
721
722
|
if (!(error instanceof SessionOperationFailure))
|
|
@@ -741,7 +742,7 @@ export class HostSessionCatalogCoordinator {
|
|
|
741
742
|
}
|
|
742
743
|
throw new NoUsableImportModelError('No usable Session model connection is available for import');
|
|
743
744
|
}
|
|
744
|
-
async #resolveModel(target, thinkingLevel) {
|
|
745
|
+
async #resolveModel(target, thinkingLevel, applyConfiguredDefault = false) {
|
|
745
746
|
const selected = await this.#selectModelTarget(target);
|
|
746
747
|
const readiness = await this.#runtimePolicy.operations.resolveExecutionConnection({
|
|
747
748
|
kind: 'bound',
|
|
@@ -788,17 +789,25 @@ export class HostSessionCatalogCoordinator {
|
|
|
788
789
|
// rejected — execution-model-authority rebuilds the runtime connection
|
|
789
790
|
// from the same table, so whatever passes here is exactly what the wire
|
|
790
791
|
// can send.
|
|
791
|
-
|
|
792
|
+
const resolvedThinkingLevel = thinkingLevel ??
|
|
793
|
+
(applyConfiguredDefault
|
|
794
|
+
? defaultThinkingLevelForConnection({
|
|
795
|
+
providerType: connection.providerType,
|
|
796
|
+
modelOverrides: connection.modelOverrides,
|
|
797
|
+
}, selected.modelId)
|
|
798
|
+
: undefined);
|
|
799
|
+
if (resolvedThinkingLevel !== undefined &&
|
|
792
800
|
!thinkingVariantsForConnection({
|
|
793
801
|
providerType: connection.providerType,
|
|
794
802
|
modelOverrides: connection.modelOverrides,
|
|
795
|
-
}, selected.modelId).includes(
|
|
796
|
-
throw new SessionOperationFailure('invalid_request', `Session model does not support thinking level ${
|
|
803
|
+
}, selected.modelId).includes(resolvedThinkingLevel)) {
|
|
804
|
+
throw new SessionOperationFailure('invalid_request', `Session model does not support thinking level ${resolvedThinkingLevel}`);
|
|
797
805
|
}
|
|
798
806
|
return {
|
|
799
807
|
connectionId: connection.connectionId,
|
|
800
808
|
connectionSlug: connection.slug,
|
|
801
809
|
model: selected.modelId,
|
|
810
|
+
thinkingLevel: resolvedThinkingLevel,
|
|
802
811
|
};
|
|
803
812
|
}
|
|
804
813
|
async #selectModelTarget(target) {
|
|
@@ -888,7 +897,7 @@ export class HostSessionCatalogCoordinator {
|
|
|
888
897
|
if (!input.modelTarget) {
|
|
889
898
|
throw new SessionOperationFailure('invalid_request', 'Session creation requires a model target or executor id');
|
|
890
899
|
}
|
|
891
|
-
return await this.#resolveModel(input.modelTarget, input.thinkingLevel);
|
|
900
|
+
return await this.#resolveModel(input.modelTarget, input.thinkingLevel ?? undefined, input.thinkingLevel !== null);
|
|
892
901
|
}
|
|
893
902
|
async #readRuntimePolicy() {
|
|
894
903
|
try {
|
|
@@ -943,7 +952,7 @@ async function prepareCreate(input) {
|
|
|
943
952
|
}
|
|
944
953
|
function createRequestFingerprint(input, prepared) {
|
|
945
954
|
const identity = [
|
|
946
|
-
'session.create.
|
|
955
|
+
'session.create.v5',
|
|
947
956
|
input.sessionId,
|
|
948
957
|
input.workspace.kind === 'project'
|
|
949
958
|
? ['project', input.workspace.projectId]
|
|
@@ -960,7 +969,7 @@ function createRequestFingerprint(input, prepared) {
|
|
|
960
969
|
input.modelTarget.connectionSlug,
|
|
961
970
|
input.modelTarget.model,
|
|
962
971
|
],
|
|
963
|
-
input.thinkingLevel
|
|
972
|
+
input.thinkingLevel === undefined ? ['model_default'] : input.thinkingLevel,
|
|
964
973
|
input.toolProfile ?? null,
|
|
965
974
|
prepared.permissionMode ?? ['runtime_default'],
|
|
966
975
|
input.collaborationMode ?? 'agent',
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
19
|
import { createHash, randomUUID } from 'node:crypto';
|
|
20
|
-
import { isDeepResearchSession } from '@maka/core/deep-research';
|
|
21
20
|
import { SIDE_CONVERSATION_SESSION_LABEL } from '@maka/core/side-conversation';
|
|
22
21
|
import { isWorkHubCoordinationSessionId, isWorkHubCoordinationSessionTarget, sessionRevisionFamilyId, } from '@maka/core/session';
|
|
23
22
|
import { runtimeHostConversationCopyUnavailableReason } from './host-session-availability.js';
|
|
@@ -204,9 +203,6 @@ export class HostSessionRevisionCoordinator {
|
|
|
204
203
|
if (sourceHeader.subagentParent) {
|
|
205
204
|
return copyFailure('operation_conflict', 'Linked child Sessions cannot be copied as ordinary conversations');
|
|
206
205
|
}
|
|
207
|
-
if (isDeepResearchSession(sourceHeader.labels)) {
|
|
208
|
-
return copyFailure('operation_unavailable', 'Deep Research Sessions cannot be copied without an exact research ledger boundary');
|
|
209
|
-
}
|
|
210
206
|
const copyUnavailableReason = runtimeHostConversationCopyUnavailableReason(sourceHeader);
|
|
211
207
|
if (copyUnavailableReason)
|
|
212
208
|
return copyFailure('operation_unavailable', copyUnavailableReason);
|
package/node_modules/@maka/runtime-host/dist/server/session-turn-access-request-coordinator.js
CHANGED
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
export class SessionTurnAccessRequestCoordinator {
|
|
20
20
|
#authority;
|
|
21
21
|
#startTurn;
|
|
22
|
-
#regenerateTurn;
|
|
23
22
|
#acquireResidency;
|
|
24
23
|
#requestDrain;
|
|
25
24
|
#whenIdle;
|
|
@@ -30,7 +29,6 @@ export class SessionTurnAccessRequestCoordinator {
|
|
|
30
29
|
constructor(input) {
|
|
31
30
|
this.#authority = input.authority;
|
|
32
31
|
this.#startTurn = input.startTurn;
|
|
33
|
-
this.#regenerateTurn = input.regenerateTurn;
|
|
34
32
|
this.#acquireResidency = input.acquireResidency;
|
|
35
33
|
this.#requestDrain = input.requestDrain;
|
|
36
34
|
this.#whenIdle = input.whenIdle;
|
|
@@ -98,21 +96,13 @@ export class SessionTurnAccessRequestCoordinator {
|
|
|
98
96
|
async #run(request, context) {
|
|
99
97
|
for (;;) {
|
|
100
98
|
try {
|
|
101
|
-
if ('content' in request.intent)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
const outcome = await this.#regenerateTurn(request.intent, context);
|
|
111
|
-
if (outcome.ok)
|
|
112
|
-
return 'started';
|
|
113
|
-
if (outcome.error.code !== 'session_busy') {
|
|
114
|
-
return this.#draining ? undefined : 'failed';
|
|
115
|
-
}
|
|
99
|
+
if (!('content' in request.intent))
|
|
100
|
+
return 'failed';
|
|
101
|
+
const outcome = await this.#startTurn(request.intent, context);
|
|
102
|
+
if (outcome.ok)
|
|
103
|
+
return outcome.result.kind;
|
|
104
|
+
if (outcome.error.code !== 'session_busy') {
|
|
105
|
+
return this.#draining ? undefined : 'failed';
|
|
116
106
|
}
|
|
117
107
|
}
|
|
118
108
|
catch {
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { isAbsolute } from 'node:path';
|
|
20
20
|
import { ARTIFACT_KINDS, ARTIFACT_SOURCES, isArtifactTurnKey, isCanonicalArtifactEntityId, } from '@maka/core/artifacts';
|
|
21
|
-
import { isDeepResearchArtifactRole } from '@maka/core/deep-research-run';
|
|
22
21
|
const ARTIFACT_KIND_SET = new Set(ARTIFACT_KINDS);
|
|
23
22
|
const ARTIFACT_SOURCE_SET = new Set(ARTIFACT_SOURCES);
|
|
24
23
|
const ARTIFACT_RECORD_KEYS = new Set([
|
|
@@ -104,7 +103,6 @@ function decodeArtifactRecord(value, index) {
|
|
|
104
103
|
value.sizeBytes < 0 ||
|
|
105
104
|
!isOptionalNonEmptyString(value.mimeType) ||
|
|
106
105
|
!isOptionalNonEmptyString(value.summary) ||
|
|
107
|
-
(value.deepResearchRole !== undefined && !isDeepResearchArtifactRole(value.deepResearchRole)) ||
|
|
108
106
|
typeof value.source !== 'string') {
|
|
109
107
|
throw invalidMetadataRecord(index);
|
|
110
108
|
}
|
|
@@ -114,7 +112,10 @@ function decodeArtifactRecord(value, index) {
|
|
|
114
112
|
if (value.relativePath !== `${value.sessionId}/${value.id}-${value.name}`) {
|
|
115
113
|
throw invalidMetadataRecord(index);
|
|
116
114
|
}
|
|
117
|
-
|
|
115
|
+
// Old reports carry a workflow role that no longer has a consumer.
|
|
116
|
+
const record = { ...value };
|
|
117
|
+
delete record.deepResearchRole;
|
|
118
|
+
return record;
|
|
118
119
|
}
|
|
119
120
|
function isCompatibleArtifactName(name) {
|
|
120
121
|
if (name.length === 0 || name.length > 120)
|
|
@@ -22,7 +22,6 @@ import { constants as fsConstants } from 'node:fs';
|
|
|
22
22
|
import { access, copyFile, lstat, mkdir, open, readFile, realpath, rm, stat, unlink, writeFile, } from 'node:fs/promises';
|
|
23
23
|
import { basename, dirname, join, relative, sep } from 'node:path';
|
|
24
24
|
import { ARTIFACT_ENTITY_ID_MAX_CHARS, ARTIFACT_KINDS, ARTIFACT_SOURCES, canUserDeleteArtifact, isArtifactTurnKey, isCanonicalArtifactEntityId, } from '@maka/core/artifacts';
|
|
25
|
-
import { isDeepResearchArtifactRole, } from '@maka/core/deep-research-run';
|
|
26
25
|
import { sniffAttachmentMimeType } from '@maka/core/attachments';
|
|
27
26
|
import { isSafeRelativeArtifactPath, validateRelativeArtifactPath, } from './artifact-metadata-codec.js';
|
|
28
27
|
import { withArtifactWriterLock, withLeaseBoundArtifactWriterLock, } from './artifact-writer-lock.js';
|
|
@@ -68,10 +67,6 @@ class SqliteArtifactStore {
|
|
|
68
67
|
if (!ARTIFACT_SOURCE_SET.has(acceptedInput.source)) {
|
|
69
68
|
throw new Error('Invalid Artifact source');
|
|
70
69
|
}
|
|
71
|
-
if (acceptedInput.deepResearchRole !== undefined &&
|
|
72
|
-
!isDeepResearchArtifactRole(acceptedInput.deepResearchRole)) {
|
|
73
|
-
throw new Error('Invalid Artifact deep-research role');
|
|
74
|
-
}
|
|
75
70
|
if (acceptedInput.now !== undefined &&
|
|
76
71
|
(!Number.isSafeInteger(acceptedInput.now) || acceptedInput.now < 0)) {
|
|
77
72
|
throw new Error('Invalid Artifact creation time');
|
|
@@ -103,9 +98,6 @@ class SqliteArtifactStore {
|
|
|
103
98
|
...(acceptedInput.mimeType ? { mimeType: acceptedInput.mimeType } : {}),
|
|
104
99
|
source: acceptedInput.source,
|
|
105
100
|
...(acceptedInput.summary ? { summary: acceptedInput.summary } : {}),
|
|
106
|
-
...(acceptedInput.deepResearchRole
|
|
107
|
-
? { deepResearchRole: acceptedInput.deepResearchRole }
|
|
108
|
-
: {}),
|
|
109
101
|
}, (targetPath) => writeFile(targetPath, acceptedInput.content, { flag: 'wx' }));
|
|
110
102
|
});
|
|
111
103
|
}
|
|
@@ -346,7 +338,6 @@ class SqliteArtifactStore {
|
|
|
346
338
|
existing.mimeType !== optionalCanonicalText(input.mimeType) ||
|
|
347
339
|
existing.source !== input.source ||
|
|
348
340
|
existing.summary !== optionalCanonicalText(input.summary) ||
|
|
349
|
-
existing.deepResearchRole !== input.deepResearchRole ||
|
|
350
341
|
(input.now !== undefined && existing.createdAt !== input.now)) {
|
|
351
342
|
throw artifactReplayConflict(canonical.id);
|
|
352
343
|
}
|
|
@@ -798,8 +789,7 @@ function sameArtifactRecord(a, b) {
|
|
|
798
789
|
a.sizeBytes === b.sizeBytes &&
|
|
799
790
|
a.mimeType === b.mimeType &&
|
|
800
791
|
a.source === b.source &&
|
|
801
|
-
a.summary === b.summary
|
|
802
|
-
a.deepResearchRole === b.deepResearchRole);
|
|
792
|
+
a.summary === b.summary);
|
|
803
793
|
}
|
|
804
794
|
function assertPageBound(value, allowZero, label) {
|
|
805
795
|
if (!Number.isSafeInteger(value) || value < (allowZero ? 0 : 1)) {
|
|
@@ -22,43 +22,6 @@ import { openStableNativeLockFile, releaseNativeFileLock, tryAcquireNativeFileLo
|
|
|
22
22
|
const LOCK_POLL_MS = 25;
|
|
23
23
|
const LOCK_TIMEOUT_MS = 10_000;
|
|
24
24
|
const lockGates = new Map();
|
|
25
|
-
export async function withLegacyFileUpdateLockLease(targetPath, operation, timeoutMs = LOCK_TIMEOUT_MS) {
|
|
26
|
-
const lockPath = `${targetPath}.lock`;
|
|
27
|
-
const leasePath = `${targetPath}.lease`;
|
|
28
|
-
const supervisionPath = `${targetPath}.supervised`;
|
|
29
|
-
const deadline = Date.now() + timeoutMs;
|
|
30
|
-
return runWithLockGate(leasePath, deadline, async () => {
|
|
31
|
-
const lease = await openStableNativeLockFile(leasePath);
|
|
32
|
-
let leased = false;
|
|
33
|
-
let supervised = false;
|
|
34
|
-
let completed = false;
|
|
35
|
-
try {
|
|
36
|
-
while (!(leased = tryAcquireNativeFileLock(lease))) {
|
|
37
|
-
await waitForLockTurn(lockPath, deadline);
|
|
38
|
-
}
|
|
39
|
-
// The inherited advisory lease follows the legacy child process. A surviving
|
|
40
|
-
// supervision marker therefore proves that its directory lock is ownerless
|
|
41
|
-
// once a later process can acquire this lease.
|
|
42
|
-
await recoverSupervisedLegacyLock(lockPath, supervisionPath);
|
|
43
|
-
await createSupervisionMarker(supervisionPath);
|
|
44
|
-
supervised = true;
|
|
45
|
-
const result = await operation(lease.fd);
|
|
46
|
-
completed = true;
|
|
47
|
-
return result;
|
|
48
|
-
}
|
|
49
|
-
finally {
|
|
50
|
-
try {
|
|
51
|
-
if (supervised && completed)
|
|
52
|
-
await unlink(supervisionPath).catch(ignoreMissing);
|
|
53
|
-
}
|
|
54
|
-
finally {
|
|
55
|
-
if (leased)
|
|
56
|
-
releaseNativeFileLock(lease);
|
|
57
|
-
await lease.close();
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
25
|
/**
|
|
63
26
|
* The callback may pass the lease fd as an extra child stdio descriptor. The
|
|
64
27
|
* advisory lock then survives a parent crash until that exact child exits.
|
|
@@ -93,10 +56,6 @@ export async function withProcessLifetimeFileUpdateLock(targetPath, operation, t
|
|
|
93
56
|
}
|
|
94
57
|
});
|
|
95
58
|
}
|
|
96
|
-
async function createSupervisionMarker(path) {
|
|
97
|
-
const marker = await open(path, fsConstants.O_CREAT | fsConstants.O_EXCL | fsConstants.O_WRONLY | fsConstants.O_NOFOLLOW, 0o600);
|
|
98
|
-
await marker.close();
|
|
99
|
-
}
|
|
100
59
|
async function recoverSupervisedLegacyLock(lockPath, supervisionPath) {
|
|
101
60
|
const supervision = await lstat(supervisionPath).catch((error) => {
|
|
102
61
|
if (isNodeError(error, 'ENOENT'))
|
|
@@ -26,7 +26,6 @@ import { CONNECTION_CATALOG_MAX_CONNECTIONS, decodeCanonicalConnectionCatalogEnt
|
|
|
26
26
|
import { PROVIDER_REGISTRY, reconcileConnectionAfterModelFetch } from '@maka/core/llm-connections';
|
|
27
27
|
import { modelIdAliasesForProvider, providerReportsCompleteModelCatalog, } from '@maka/core/model-metadata';
|
|
28
28
|
import { isRetiredProvider } from '@maka/core/provider-registry';
|
|
29
|
-
import { pruneModelOverrides } from '@maka/core/model-thinking';
|
|
30
29
|
import { deepFreeze, nextRevision, record, revision, unique } from './codec.js';
|
|
31
30
|
import { codecError, decodeConnectionInput, decodePersistedDomain, RuntimePolicyStoreError, } from './errors.js';
|
|
32
31
|
import { CATALOG_DOCUMENT_MAX_BYTES, readBoundedJsonDocument, serializeJsonDocument, writeJsonDocument, } from './document-io.js';
|
|
@@ -285,67 +284,6 @@ export class ConnectionCatalogDocumentOwner {
|
|
|
285
284
|
await this.write(root, next);
|
|
286
285
|
return committed(next);
|
|
287
286
|
}
|
|
288
|
-
/**
|
|
289
|
-
* Built-in seed evolution as ONE atomic catalog mutation. A row whose
|
|
290
|
-
* `enabledModelIds` still exactly match a historical system seed is provably
|
|
291
|
-
* system-owned: it follows the current seed, its static inventory is
|
|
292
|
-
* re-derived from the current build, and a default target the migration
|
|
293
|
-
* removes is retargeted inside the same document write — so no restart can
|
|
294
|
-
* observe enabled ids without their inventory, or a nulled default awaiting
|
|
295
|
-
* a second write. Any other inventory (including a reordering) is a user
|
|
296
|
-
* selection and is never touched; an already-null default stays null.
|
|
297
|
-
*/
|
|
298
|
-
async migrateSystemSeed(root, input) {
|
|
299
|
-
if (!input.enabledModelIds.includes(input.defaultModelId)) {
|
|
300
|
-
throw codecError('invalid_connection_input', 'Seed default must be in the seed selection');
|
|
301
|
-
}
|
|
302
|
-
const current = await this.read(root);
|
|
303
|
-
const index = current.connections.findIndex((item) => item.slug === input.slug && item.providerType === input.providerType);
|
|
304
|
-
const previous = current.connections[index];
|
|
305
|
-
const retired = new Set(input.retiredModelIds);
|
|
306
|
-
const sameIds = (left, right) => left.length === right.length && left.every((id, position) => id === right[position]);
|
|
307
|
-
const isLegacySeed = previous
|
|
308
|
-
? input.legacyEnabledModelIds.some((seed) => sameIds(previous.enabledModelIds, seed))
|
|
309
|
-
: false;
|
|
310
|
-
const hasRetiredModels = previous
|
|
311
|
-
? previous.enabledModelIds.some((id) => retired.has(id)) ||
|
|
312
|
-
previous.models.some((model) => retired.has(model.id))
|
|
313
|
-
: false;
|
|
314
|
-
if (!previous || (!isLegacySeed && !hasRetiredModels)) {
|
|
315
|
-
return committed(current);
|
|
316
|
-
}
|
|
317
|
-
// A legacy seed's stored inventory was the registry's shipped list copied
|
|
318
|
-
// in at write time. Clearing it is the migration: the resolver prepends
|
|
319
|
-
// that list from the current build, so the row stops carrying a stale
|
|
320
|
-
// second copy of it. Any other row keeps its own inventory, minus the
|
|
321
|
-
// retired ids.
|
|
322
|
-
const models = isLegacySeed ? [] : previous.models.filter((model) => !retired.has(model.id));
|
|
323
|
-
const { lastTest: _lastTest, modelSource: _modelSource, modelsFetchedAt: _modelsFetchedAt, ...retained } = previous;
|
|
324
|
-
const migratedEnabledModelIds = isLegacySeed
|
|
325
|
-
? [...input.enabledModelIds]
|
|
326
|
-
: previous.enabledModelIds.filter((id) => !retired.has(id));
|
|
327
|
-
const connections = [...current.connections];
|
|
328
|
-
const modelOverrides = pruneModelOverrides(previous.modelOverrides, Object.keys(previous.modelOverrides ?? {}).filter((id) => !retired.has(id)));
|
|
329
|
-
connections[index] = {
|
|
330
|
-
...retained,
|
|
331
|
-
revision: nextRevision(previous.revision),
|
|
332
|
-
enabledModelIds: migratedEnabledModelIds,
|
|
333
|
-
models,
|
|
334
|
-
...(isLegacySeed || previous.modelSource === undefined
|
|
335
|
-
? {}
|
|
336
|
-
: { modelSource: previous.modelSource, modelsFetchedAt: previous.modelsFetchedAt }),
|
|
337
|
-
...(modelOverrides === undefined ? {} : { modelOverrides }),
|
|
338
|
-
};
|
|
339
|
-
const target = current.defaultTarget;
|
|
340
|
-
const defaultTarget = target !== null &&
|
|
341
|
-
target.connectionId === previous.connectionId &&
|
|
342
|
-
!migratedEnabledModelIds.includes(target.modelId)
|
|
343
|
-
? { connectionId: previous.connectionId, modelId: input.defaultModelId }
|
|
344
|
-
: target;
|
|
345
|
-
const next = this.nextDocument(current, connections, defaultTarget);
|
|
346
|
-
await this.write(root, next);
|
|
347
|
-
return committed(next);
|
|
348
|
-
}
|
|
349
287
|
async setDefaultTarget(root, rawInput) {
|
|
350
288
|
const input = decodeConnectionInput(() => normalizeSetDefaultConnectionTargetInput(rawInput));
|
|
351
289
|
const current = await this.read(root);
|