maka-agent 0.2.0-dev.31.20260913 → 0.2.0-dev.32.20260914
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/pi-transcript.js +3 -4
- package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
- package/node_modules/@maka/core/dist/agent-graph-schedule.js +15 -4
- package/node_modules/@maka/core/dist/executor-id.js +22 -0
- package/node_modules/@maka/core/dist/external-session.js +18 -0
- package/node_modules/@maka/core/dist/model-call-usage-projection.js +0 -13
- package/node_modules/@maka/core/dist/runtime-event.js +19 -3
- package/node_modules/@maka/core/dist/session-send-projection.js +6 -3
- package/node_modules/@maka/core/dist/session.js +8 -2
- package/node_modules/@maka/core/dist/shell-run-result.js +1 -0
- package/node_modules/@maka/core/dist/shell-run.js +4 -0
- package/node_modules/@maka/core/dist/work-board.js +94 -1
- package/node_modules/@maka/core/package.json +1 -0
- package/node_modules/@maka/eval/dist/fleet-simulation.js +270 -0
- package/node_modules/@maka/eval/dist/fleet-store.js +243 -0
- package/node_modules/@maka/eval/dist/fleet-worker.js +125 -0
- package/node_modules/@maka/eval/dist/fleet.js +329 -0
- package/node_modules/@maka/eval/dist/index.js +3 -0
- package/node_modules/@maka/runtime/dist/agent-run.js +2 -17
- package/node_modules/@maka/runtime/dist/ai-sdk-compaction.js +6 -2
- package/node_modules/@maka/runtime/dist/ai-sdk-message-projection.js +36 -24
- package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +257 -330
- package/node_modules/@maka/runtime/dist/background-task-health-tool.js +104 -0
- package/node_modules/@maka/runtime/dist/history-compaction.js +3 -1
- package/node_modules/@maka/runtime/dist/local-web-fetch.js +1 -1
- package/node_modules/@maka/runtime/dist/model-adapter.js +62 -53
- package/node_modules/@maka/runtime/dist/model-history.js +1 -5
- package/node_modules/@maka/runtime/dist/plugin-executor-backend.js +311 -0
- package/node_modules/@maka/runtime/dist/plugin-executor-service.js +344 -0
- package/node_modules/@maka/runtime/dist/provider-error-classification.js +7 -1
- package/node_modules/@maka/runtime/dist/provider-request-telemetry.js +35 -8
- package/node_modules/@maka/runtime/dist/runtime-event-backfill.js +7 -1
- package/node_modules/@maka/runtime/dist/runtime-event-read-model.js +1 -0
- package/node_modules/@maka/runtime/dist/runtime-invocation-route.js +49 -0
- package/node_modules/@maka/runtime/dist/runtime-kernel.js +72 -150
- package/node_modules/@maka/runtime/dist/runtime-read-model.js +0 -2
- package/node_modules/@maka/runtime/dist/session-event-runtime-mapper.js +3 -0
- package/node_modules/@maka/runtime/dist/session-manager.js +100 -58
- package/node_modules/@maka/runtime/dist/shell-run-manager.js +9 -3
- package/node_modules/@maka/runtime/dist/shell-run-tool-result.js +1 -0
- package/node_modules/@maka/runtime/dist/stream-graph-schedule-reconcile.js +1 -0
- package/node_modules/@maka/runtime/dist/stream-graph-supervisor-tools.js +26 -4
- package/node_modules/@maka/runtime/dist/subagent-tools.js +7 -0
- package/node_modules/@maka/runtime/dist/tool-runtime.js +45 -466
- package/node_modules/@maka/runtime/package.json +3 -0
- package/node_modules/@maka/runtime-host/dist/adapter/session-projector.js +7 -2
- package/node_modules/@maka/runtime-host/dist/client/session-catalog-summary.js +1 -0
- package/node_modules/@maka/runtime-host/dist/protocol/external-session.js +24 -3
- package/node_modules/@maka/runtime-host/dist/protocol/index.js +4 -1
- package/node_modules/@maka/runtime-host/dist/protocol/plugin-platform.js +42 -5
- package/node_modules/@maka/runtime-host/dist/protocol/session-catalog.js +31 -3
- package/node_modules/@maka/runtime-host/dist/protocol/session-continuity.js +6 -0
- package/node_modules/@maka/runtime-host/dist/server/child-agent-composition.js +1 -0
- package/node_modules/@maka/runtime-host/dist/server/execution-artifacts.js +1 -22
- package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +54 -8
- package/node_modules/@maka/runtime-host/dist/server/external-session-coordinator.js +14 -1
- package/node_modules/@maka/runtime-host/dist/server/host-session-availability.js +10 -2
- package/node_modules/@maka/runtime-host/dist/server/plugin-platform-coordinator.js +6 -0
- package/node_modules/@maka/runtime-host/dist/server/plugin-platform.js +6 -0
- package/node_modules/@maka/runtime-host/dist/server/session-catalog-coordinator.js +56 -16
- package/node_modules/@maka/runtime-host/dist/server/session-continuity-coordinator.js +4 -3
- package/node_modules/@maka/runtime-host/dist/server/session-revision-coordinator.js +4 -0
- package/node_modules/@maka/runtime-host/dist/server/web-fetch-tool.js +37 -1
- package/node_modules/@maka/storage/dist/claude-code-session-adapter.js +450 -234
- package/node_modules/@maka/storage/dist/claude-code-transcript-lineage.js +106 -77
- package/node_modules/@maka/storage/dist/legacy-run-header.js +2 -2
- package/node_modules/@maka/storage/dist/model-call-usage-sql.js +1 -1
- package/node_modules/@maka/storage/dist/session-store.js +12 -2
- package/node_modules/@maka/storage/dist/sqlite-long-term-memory-store.js +86 -12
- package/node_modules/@maka/storage/dist/work-board-store.js +40 -1
- package/package.json +1 -1
package/dist/pi-transcript.js
CHANGED
|
@@ -945,10 +945,9 @@ function systemNoteText(message) {
|
|
|
945
945
|
const data = message.data;
|
|
946
946
|
const used = typeof data?.inputTokens === 'number' ? data.inputTokens : undefined;
|
|
947
947
|
const prior = typeof data?.priorInputTokens === 'number' ? data.priorInputTokens : undefined;
|
|
948
|
-
if (used === undefined || prior === undefined)
|
|
949
|
-
return
|
|
950
|
-
}
|
|
951
|
-
return `The provider is dropping or rewriting context: content was appended, and it counted ${used} input tokens against ${prior} before, which is no growth. Declare a context window for this model so Maka compacts first.`;
|
|
948
|
+
if (used === undefined || prior === undefined)
|
|
949
|
+
return "After content was appended, the provider-reported input token count did not grow; context may have been truncated or rewritten. If this persists, check that the model's actual context capacity and the connection settings agree.";
|
|
950
|
+
return `After content was appended, the provider-reported input token count did not grow; context may have been truncated or rewritten (${used} tokens versus ${prior} before). If this persists, check that the model's actual context capacity and the connection settings agree.`;
|
|
952
951
|
}
|
|
953
952
|
case 'context_overflow_after_compaction':
|
|
954
953
|
return 'History was compacted and the provider still called this request too large. What remains also carries the system prompt, the tool schemas, the summary and the recent tail; shortening this message is the part you control.';
|
|
Binary file
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* specific language governing permissions and limitations
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
|
+
import { isExecutorId } from './executor-id.js';
|
|
19
20
|
export const AGENT_GRAPH_SCHEDULE_UPDATE_SCHEMA_VERSION = 1;
|
|
20
21
|
export const AGENT_GRAPH_SCHEDULE_MAX_ADD_WORK = 32;
|
|
21
22
|
export const AGENT_GRAPH_SCHEDULE_MAX_STOP = 20;
|
|
@@ -192,14 +193,24 @@ function isSelectedResultInput(value) {
|
|
|
192
193
|
function isWorkTarget(value) {
|
|
193
194
|
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
194
195
|
return false;
|
|
195
|
-
if (isExactRecord(value, [
|
|
196
|
+
if (isExactRecord(value, [
|
|
197
|
+
'kind',
|
|
198
|
+
'agentId',
|
|
199
|
+
...(hasOwn(value, 'executorId') ? ['executorId'] : []),
|
|
200
|
+
]) &&
|
|
196
201
|
value.kind === 'agent' &&
|
|
197
|
-
isOpaqueIdentity(value.agentId)
|
|
202
|
+
isOpaqueIdentity(value.agentId) &&
|
|
203
|
+
(value.executorId === undefined || isExecutorId(value.executorId))) {
|
|
198
204
|
return true;
|
|
199
205
|
}
|
|
200
|
-
if (isExactRecord(value, [
|
|
206
|
+
if (isExactRecord(value, [
|
|
207
|
+
'kind',
|
|
208
|
+
'presetId',
|
|
209
|
+
...(hasOwn(value, 'executorId') ? ['executorId'] : []),
|
|
210
|
+
]) &&
|
|
201
211
|
value.kind === 'preset' &&
|
|
202
|
-
isOpaqueIdentity(value.presetId)
|
|
212
|
+
isOpaqueIdentity(value.presetId) &&
|
|
213
|
+
(value.executorId === undefined || isExecutorId(value.executorId))) {
|
|
203
214
|
return true;
|
|
204
215
|
}
|
|
205
216
|
return (isExactRecord(value, ['kind', 'operatorId']) &&
|
|
@@ -0,0 +1,22 @@
|
|
|
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
|
+
export const EXECUTOR_ID_PATTERN = /^[A-Za-z][A-Za-z0-9._:-]{0,127}$/u;
|
|
20
|
+
export function isExecutorId(value) {
|
|
21
|
+
return typeof value === 'string' && EXECUTOR_ID_PATTERN.test(value);
|
|
22
|
+
}
|
|
@@ -114,6 +114,24 @@ function normalizeExternalSessionPath(value) {
|
|
|
114
114
|
const trimmed = stripped.length > 0 ? stripped : folded.length > 0 ? '/' : '';
|
|
115
115
|
return /^[A-Za-z]:\//u.test(trimmed) ? trimmed.toLowerCase() : trimmed;
|
|
116
116
|
}
|
|
117
|
+
export const EXTERNAL_SESSION_LIMIT_KINDS = [
|
|
118
|
+
'transcript_bytes',
|
|
119
|
+
'record_bytes',
|
|
120
|
+
'records',
|
|
121
|
+
'converted_bytes',
|
|
122
|
+
'messages',
|
|
123
|
+
];
|
|
124
|
+
export class ExternalSessionLimitError extends Error {
|
|
125
|
+
limit;
|
|
126
|
+
constructor(kind, max, message) {
|
|
127
|
+
super(message);
|
|
128
|
+
if (!EXTERNAL_SESSION_LIMIT_KINDS.includes(kind) || !Number.isSafeInteger(max) || max <= 0) {
|
|
129
|
+
throw new Error('Invalid external Session import limit');
|
|
130
|
+
}
|
|
131
|
+
this.name = 'ExternalSessionLimitError';
|
|
132
|
+
this.limit = Object.freeze({ kind, max });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
117
135
|
export class ExternalSessionAdapterRegistry {
|
|
118
136
|
adapters = new Map();
|
|
119
137
|
constructor(adapters = []) {
|
|
@@ -29,19 +29,6 @@ export function resolveUsageRange(range, now) {
|
|
|
29
29
|
};
|
|
30
30
|
return { from: now - spans[range], to: now };
|
|
31
31
|
}
|
|
32
|
-
/**
|
|
33
|
-
* Maps a physical attempt outcome onto the status vocabulary the Usage surface
|
|
34
|
-
* filters by. `interrupted` joins `aborted`: both mean the call stopped short
|
|
35
|
-
* without the provider reporting a failure, and collapsing it into `error`
|
|
36
|
-
* would inflate the error rate with user cancellations.
|
|
37
|
-
*/
|
|
38
|
-
export function usageStatusForAttempt(status) {
|
|
39
|
-
if (status === 'completed')
|
|
40
|
-
return 'success';
|
|
41
|
-
if (status === 'failed')
|
|
42
|
-
return 'error';
|
|
43
|
-
return 'aborted';
|
|
44
|
-
}
|
|
45
32
|
export function clampCacheReadTokens(inputTokens, cacheReadTokens) {
|
|
46
33
|
return Math.min(cacheReadTokens, inputTokens);
|
|
47
34
|
}
|
|
@@ -40,6 +40,7 @@ import { isPermissionMode, } from './permission.js';
|
|
|
40
40
|
import { isCollaborationMode } from './collaboration.js';
|
|
41
41
|
import { isAgentSwarmAuthorizationSource, isEffectiveOrchestrationSource, isOrchestrationMode, } from './orchestration.js';
|
|
42
42
|
import { isToolMode } from './tool-mode.js';
|
|
43
|
+
import { isExecutorId } from './executor-id.js';
|
|
43
44
|
import { isRuntimeSystemNoteKind, } from './session.js';
|
|
44
45
|
import { decodeTurnOrigin } from './turn-origin.js';
|
|
45
46
|
import { defineObjectShape, hasExactShape, isFiniteNumber, isOptionalMember, isOptionalString, isRecord, isStringArray, } from './record-schema.js';
|
|
@@ -172,6 +173,7 @@ export function runtimeEventEnvelopeValueDomains() {
|
|
|
172
173
|
const RUNTIME_EVENT_SHAPE = defineObjectShape()(['id', 'invocationId', 'runId', 'sessionId', 'turnId', 'ts', 'partial', 'role', 'author'], ['branch', 'origin', 'modelVisibility', 'status', 'content', 'actions', 'refs']);
|
|
173
174
|
const TEXT_CONTENT_SHAPE = defineObjectShape()(['kind', 'text'], [
|
|
174
175
|
'displayText',
|
|
176
|
+
'interrupted',
|
|
175
177
|
'origin',
|
|
176
178
|
'attachments',
|
|
177
179
|
'directoryReferences',
|
|
@@ -186,7 +188,15 @@ const FUNCTION_RESPONSE_CONTENT_SHAPE = defineObjectShape()(['kind', 'id', 'name
|
|
|
186
188
|
const ERROR_CONTENT_SHAPE = defineObjectShape()(['kind', 'message'], ['code', 'reason', 'details', 'retry']);
|
|
187
189
|
const SYSTEM_NOTE_CONTENT_SHAPE = defineObjectShape()(['kind', 'note'], ['data']);
|
|
188
190
|
const INVOCATION_OPENED_CONTENT_SHAPE = defineObjectShape()(['kind', 'protocol', 'route', 'configuration', 'root', 'source'], ['lineage']);
|
|
189
|
-
const
|
|
191
|
+
const INVOCATION_ROUTE_RUNTIME_MODEL_SHAPE = defineObjectShape()(['provenance', 'backendKind', 'llmConnectionId', 'llmConnectionSlug', 'modelId'], ['providerStateIdentity']);
|
|
192
|
+
const INVOCATION_ROUTE_RUNTIME_EXECUTOR_SHAPE = defineObjectShape()([
|
|
193
|
+
'provenance',
|
|
194
|
+
'backendKind',
|
|
195
|
+
'executorId',
|
|
196
|
+
'llmConnectionSlug',
|
|
197
|
+
'modelId',
|
|
198
|
+
'providerStateIdentity',
|
|
199
|
+
], []);
|
|
190
200
|
const INVOCATION_ROUTE_UNKNOWN_SHAPE = defineObjectShape()(['provenance', 'backendKind', 'llmConnectionSlug', 'modelId'], []);
|
|
191
201
|
const INVOCATION_CONFIGURATION_SHAPE = defineObjectShape()([
|
|
192
202
|
'cwd',
|
|
@@ -394,6 +404,7 @@ function isRuntimeEventContent(value) {
|
|
|
394
404
|
if (!hasExactShape(value, TEXT_CONTENT_SHAPE) ||
|
|
395
405
|
(value.origin !== undefined && !isTurnOrigin(value.origin)) ||
|
|
396
406
|
(value.steering !== undefined && value.steering !== true) ||
|
|
407
|
+
(value.interrupted !== undefined && value.interrupted !== true) ||
|
|
397
408
|
(value.providerOptions !== undefined && !isRecord(value.providerOptions))) {
|
|
398
409
|
return false;
|
|
399
410
|
}
|
|
@@ -481,14 +492,19 @@ function isRuntimeInvocationRoute(value) {
|
|
|
481
492
|
return false;
|
|
482
493
|
}
|
|
483
494
|
if (value.provenance === 'runtime') {
|
|
484
|
-
|
|
495
|
+
if (value.backendKind === 'plugin-executor') {
|
|
496
|
+
return (hasExactShape(value, INVOCATION_ROUTE_RUNTIME_EXECUTOR_SHAPE) &&
|
|
497
|
+
isExecutorId(value.executorId) &&
|
|
498
|
+
isSha256Digest(value.providerStateIdentity));
|
|
499
|
+
}
|
|
500
|
+
return (hasExactShape(value, INVOCATION_ROUTE_RUNTIME_MODEL_SHAPE) &&
|
|
485
501
|
isNonEmptyString(value.llmConnectionId) &&
|
|
486
502
|
(value.providerStateIdentity === undefined || isSha256Digest(value.providerStateIdentity)));
|
|
487
503
|
}
|
|
488
504
|
return value.provenance === 'unknown' && hasExactShape(value, INVOCATION_ROUTE_UNKNOWN_SHAPE);
|
|
489
505
|
}
|
|
490
506
|
function isPersistedBackendKind(value) {
|
|
491
|
-
return value === 'ai-sdk' || value === 'fake';
|
|
507
|
+
return value === 'ai-sdk' || value === 'plugin-executor' || value === 'fake';
|
|
492
508
|
}
|
|
493
509
|
function isRuntimeInvocationConfiguration(value) {
|
|
494
510
|
return (isRecord(value) &&
|
|
@@ -26,11 +26,12 @@
|
|
|
26
26
|
* whether that exact target looks usable for presentation and readiness checks.
|
|
27
27
|
*
|
|
28
28
|
* The compatibility rules are:
|
|
29
|
-
* 1.
|
|
29
|
+
* 1. Plugin executor Sessions do not depend on Maka model connections.
|
|
30
|
+
* 2. The session's own connection must pass `isConnectionReady` with
|
|
30
31
|
* the sticky session model.
|
|
31
|
-
*
|
|
32
|
+
* 3. Legacy Sessions without an immutable connection id are blocked until
|
|
32
33
|
* the user explicitly selects an account.
|
|
33
|
-
*
|
|
34
|
+
* 4. A missing id, slug mismatch, or unusable exact connection is blocked.
|
|
34
35
|
*
|
|
35
36
|
* `lastTestStatus` deliberately plays no part here (E4): telemetry about
|
|
36
37
|
* a past credential test must not gate send, so it must not gate the
|
|
@@ -71,6 +72,8 @@ function sessionOwnConnectionBlockReason(session, ownConnection, hasSecret) {
|
|
|
71
72
|
return verdict.ready ? undefined : verdict.reason;
|
|
72
73
|
}
|
|
73
74
|
function ownConnectionBlockReason(session, connections, hasSecret) {
|
|
75
|
+
if (session.backend === 'plugin-executor')
|
|
76
|
+
return undefined;
|
|
74
77
|
if (session.backend === 'fake')
|
|
75
78
|
return 'fake_backend';
|
|
76
79
|
if (!session.llmConnectionId)
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
19
|
import { isWorkHubActionReceipt } from './workhub-action-result.js';
|
|
20
|
+
import { isExecutorId } from './executor-id.js';
|
|
20
21
|
import { MODEL_FAILURE_MESSAGE_MAX_BYTES, isModelRetryDecision, } from './model-failure.js';
|
|
21
22
|
import { decodeMessageContent, TOOL_ACTIVITY_KINDS, } from './events.js';
|
|
22
23
|
import { isPermissionMode, isToolCategory, } from './permission.js';
|
|
@@ -290,10 +291,14 @@ export const WORKHUB_COORDINATION_REPLACEMENT_SCHEMA_VERSION = 2;
|
|
|
290
291
|
export const WORKHUB_COORDINATION_STOP_SCHEMA_VERSION = 3;
|
|
291
292
|
export function isWorkHubCreateDefaults(value) {
|
|
292
293
|
if (!isRecord(value) ||
|
|
293
|
-
Object.keys(value).some((key) => key !== 'model' && key !== 'permissionMode'))
|
|
294
|
+
Object.keys(value).some((key) => key !== 'executorId' && key !== 'model' && key !== 'permissionMode'))
|
|
294
295
|
return false;
|
|
295
296
|
if (value.permissionMode !== undefined && !isPermissionMode(value.permissionMode))
|
|
296
297
|
return false;
|
|
298
|
+
if (value.executorId !== undefined && !isExecutorId(value.executorId))
|
|
299
|
+
return false;
|
|
300
|
+
if (value.executorId !== undefined && value.model !== undefined)
|
|
301
|
+
return false;
|
|
297
302
|
if (value.model === undefined)
|
|
298
303
|
return true;
|
|
299
304
|
const model = value.model;
|
|
@@ -349,7 +354,7 @@ const USER_MESSAGE_SHAPE = defineObjectShape()(['type', 'id', 'turnId', 'ts', 't
|
|
|
349
354
|
'coordinationActionId',
|
|
350
355
|
'origin',
|
|
351
356
|
]);
|
|
352
|
-
const ASSISTANT_MESSAGE_SHAPE = defineObjectShape()(['type', 'id', 'turnId', 'ts', 'text', 'modelId'], ['thinking', 'contentOrder', 'providerOptions']);
|
|
357
|
+
const ASSISTANT_MESSAGE_SHAPE = defineObjectShape()(['type', 'id', 'turnId', 'ts', 'text', 'modelId'], ['thinking', 'contentOrder', 'providerOptions', 'interrupted']);
|
|
353
358
|
const TOOL_CALL_MESSAGE_SHAPE = defineObjectShape()(['type', 'id', 'turnId', 'ts', 'toolName', 'args'], [
|
|
354
359
|
'activityKind',
|
|
355
360
|
'displayName',
|
|
@@ -567,6 +572,7 @@ function decodeMessage(value, decodeToolResultContent) {
|
|
|
567
572
|
hasMessageEnvelope(message, true) &&
|
|
568
573
|
typeof message.text === 'string' &&
|
|
569
574
|
typeof message.modelId === 'string' &&
|
|
575
|
+
(message.interrupted === undefined || message.interrupted === true) &&
|
|
570
576
|
(message.providerOptions === undefined || isRecord(message.providerOptions)) &&
|
|
571
577
|
(message.thinking === undefined || isAssistantThinking(message.thinking)) &&
|
|
572
578
|
(message.contentOrder === undefined ||
|
|
@@ -67,6 +67,7 @@ export class ShellRunUpdateBuffer {
|
|
|
67
67
|
}
|
|
68
68
|
const CURRENT_TERMINAL_RESULT_SHAPE = defineObjectShape()(['kind', 'cwd', 'cmd', 'status', 'output'], ['exitCode', 'failureMessage', 'sandboxDenial']);
|
|
69
69
|
const CURRENT_SHELL_RUN_RESULT_SHAPE = defineObjectShape()(['kind', 'ref', 'mode', 'status', 'cwd', 'cmd', 'startedAt', 'updatedAt', 'revision'], [
|
|
70
|
+
'pid',
|
|
70
71
|
'completedAt',
|
|
71
72
|
'exitCode',
|
|
72
73
|
'failureMessage',
|
|
@@ -162,6 +162,7 @@ export function isValidShellRunState(value) {
|
|
|
162
162
|
const SHELL_RUN_SESSION_ID_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;
|
|
163
163
|
const SHELL_RUN_PATCH_KEYS = new Set([
|
|
164
164
|
'status',
|
|
165
|
+
'pid',
|
|
165
166
|
'exitCode',
|
|
166
167
|
'failureMessage',
|
|
167
168
|
'updatedAt',
|
|
@@ -179,6 +180,7 @@ const SHELL_RUN_RECORD_KEYS = new Set([
|
|
|
179
180
|
'cwd',
|
|
180
181
|
'command',
|
|
181
182
|
'status',
|
|
183
|
+
'pid',
|
|
182
184
|
'startedAt',
|
|
183
185
|
'updatedAt',
|
|
184
186
|
'completedAt',
|
|
@@ -227,6 +229,7 @@ export function normalizeShellRunRecord(value, sessionId, shellRunId) {
|
|
|
227
229
|
record.sessionId === sessionId &&
|
|
228
230
|
record.shellRunId === shellRunId &&
|
|
229
231
|
isShellRunStatus(record.status) &&
|
|
232
|
+
(record.pid === undefined || isPositiveInteger(record.pid)) &&
|
|
230
233
|
isFiniteNumber(record.startedAt) &&
|
|
231
234
|
isFiniteNumber(record.updatedAt) &&
|
|
232
235
|
isPositiveInteger(record.revision) &&
|
|
@@ -349,6 +352,7 @@ function isShellRunSandboxEscalation(value, execution) {
|
|
|
349
352
|
}
|
|
350
353
|
function canonicalShellRunRecord(record) {
|
|
351
354
|
return {
|
|
355
|
+
...(record.pid !== undefined ? { pid: record.pid } : {}),
|
|
352
356
|
shellRunId: record.shellRunId,
|
|
353
357
|
sessionId: record.sessionId,
|
|
354
358
|
...(record.sourceRunId !== undefined ? { sourceRunId: record.sourceRunId } : {}),
|
|
@@ -32,9 +32,18 @@ export const WORK_BOARD_ID_MAX_CHARS = 64;
|
|
|
32
32
|
export const WORK_BOARD_SESSION_ID_MAX_CHARS = 160;
|
|
33
33
|
export const WORK_BOARD_MESSAGE_ID_MAX_CHARS = 256;
|
|
34
34
|
export const WORK_BOARD_PROJECT_ID_MAX_CHARS = 160;
|
|
35
|
+
export const WORK_BOARD_HOST_ID_MAX_CHARS = 160;
|
|
36
|
+
export const WORK_BOARD_PROFILE_ID_MAX_CHARS = 160;
|
|
35
37
|
export const WORK_BOARD_DEFAULT_PAGE_SIZE = 50;
|
|
36
38
|
export const WORK_BOARD_PAGE_SIZE_MAX = 100;
|
|
37
39
|
export const WORK_BOARD_CURSOR_MAX_CHARS = 1024;
|
|
40
|
+
/**
|
|
41
|
+
* Single-link contract: a project-scoped item owns at most one started
|
|
42
|
+
* Session at a time. Linking a freshly started Session replaces any previous
|
|
43
|
+
* link, keeping `linkedSessions` bounded instead of growing on repeated
|
|
44
|
+
* starts. Read paths stay tolerant of legacy arrays with more entries.
|
|
45
|
+
*/
|
|
46
|
+
export const WORK_BOARD_MAX_LINKED_SESSIONS = 1;
|
|
38
47
|
export const WORK_BOARD_ITEM_STATES = ['todo', 'in_progress', 'done'];
|
|
39
48
|
const WORK_BOARD_SCOPE_INBOX_SHAPE = defineObjectShape()(['kind'], []);
|
|
40
49
|
const WORK_BOARD_SCOPE_PROJECT_SHAPE = defineObjectShape()(['kind', 'projectId'], []);
|
|
@@ -55,7 +64,7 @@ const WORK_BOARD_ITEM_SHAPE = defineObjectShape()([
|
|
|
55
64
|
'createdAt',
|
|
56
65
|
'updatedAt',
|
|
57
66
|
'archived',
|
|
58
|
-
], ['notes', 'archivedAt']);
|
|
67
|
+
], ['notes', 'archivedAt', 'linkedSessions']);
|
|
59
68
|
const WORK_BOARD_CREATE_INPUT_SHAPE = defineObjectShape()(['scope', 'title', 'creator', 'provenance'], ['notes']);
|
|
60
69
|
const WORK_BOARD_UPDATE_INPUT_SHAPE = defineObjectShape()([], ['title', 'notes', 'scope', 'state']);
|
|
61
70
|
const WORK_BOARD_LIST_QUERY_SHAPE = defineObjectShape()([], ['scope', 'projectIds', 'includeArchived', 'limit', 'cursor']);
|
|
@@ -236,6 +245,87 @@ export function normalizeCreateWorkBoardItemInput(input) {
|
|
|
236
245
|
},
|
|
237
246
|
};
|
|
238
247
|
}
|
|
248
|
+
const WORK_BOARD_LINKED_SESSION_SHAPE = defineObjectShape()(['profileId', 'hostId', 'sessionId', 'linkedAt'], []);
|
|
249
|
+
export function normalizeWorkBoardLinkedSession(input) {
|
|
250
|
+
if (!isRecord(input) || !hasExactShape(input, WORK_BOARD_LINKED_SESSION_SHAPE)) {
|
|
251
|
+
return fail('Work Board linked Session reference is invalid');
|
|
252
|
+
}
|
|
253
|
+
const profileId = normalizeIdString(input.profileId, {
|
|
254
|
+
field: 'linkedSessions.profileId',
|
|
255
|
+
max: WORK_BOARD_PROFILE_ID_MAX_CHARS,
|
|
256
|
+
});
|
|
257
|
+
if (!profileId.ok)
|
|
258
|
+
return profileId;
|
|
259
|
+
const hostId = normalizeIdString(input.hostId, {
|
|
260
|
+
field: 'linkedSessions.hostId',
|
|
261
|
+
max: WORK_BOARD_HOST_ID_MAX_CHARS,
|
|
262
|
+
});
|
|
263
|
+
if (!hostId.ok)
|
|
264
|
+
return hostId;
|
|
265
|
+
const sessionId = normalizeIdString(input.sessionId, {
|
|
266
|
+
field: 'linkedSessions.sessionId',
|
|
267
|
+
max: WORK_BOARD_SESSION_ID_MAX_CHARS,
|
|
268
|
+
});
|
|
269
|
+
if (!sessionId.ok)
|
|
270
|
+
return sessionId;
|
|
271
|
+
const linkedAt = asSafeInteger(input.linkedAt);
|
|
272
|
+
if (linkedAt === null || linkedAt < 0)
|
|
273
|
+
return fail('linkedAt must be a non-negative integer');
|
|
274
|
+
return {
|
|
275
|
+
ok: true,
|
|
276
|
+
value: {
|
|
277
|
+
profileId: profileId.value,
|
|
278
|
+
hostId: hostId.value,
|
|
279
|
+
sessionId: sessionId.value,
|
|
280
|
+
linkedAt,
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
export function normalizeWorkBoardLinkedSessions(input) {
|
|
285
|
+
if (input === undefined)
|
|
286
|
+
return { ok: true, value: [] };
|
|
287
|
+
if (!Array.isArray(input))
|
|
288
|
+
return fail('linkedSessions must be an array');
|
|
289
|
+
const result = [];
|
|
290
|
+
const seen = new Set();
|
|
291
|
+
for (const entry of input) {
|
|
292
|
+
const normalized = normalizeWorkBoardLinkedSession(entry);
|
|
293
|
+
if (!normalized.ok)
|
|
294
|
+
return normalized;
|
|
295
|
+
const key = `${normalized.value.profileId}\u0000${normalized.value.hostId}\u0000${normalized.value.sessionId}`;
|
|
296
|
+
if (seen.has(key))
|
|
297
|
+
return fail('linkedSessions contains duplicates');
|
|
298
|
+
seen.add(key);
|
|
299
|
+
result.push(normalized.value);
|
|
300
|
+
}
|
|
301
|
+
if (result.length > WORK_BOARD_MAX_LINKED_SESSIONS) {
|
|
302
|
+
return fail(`linkedSessions must hold at most ${WORK_BOARD_MAX_LINKED_SESSIONS} entry (single-link contract)`);
|
|
303
|
+
}
|
|
304
|
+
return { ok: true, value: result };
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Lenient read path for stored items: drop malformed or duplicate link entries
|
|
308
|
+
* instead of failing the whole item, so one corrupt reference cannot hide an
|
|
309
|
+
* otherwise valid board item. The strict {@link normalizeWorkBoardLinkedSessions}
|
|
310
|
+
* guard remains on the write path.
|
|
311
|
+
*/
|
|
312
|
+
function tolerantWorkBoardLinkedSessions(value) {
|
|
313
|
+
if (!Array.isArray(value))
|
|
314
|
+
return [];
|
|
315
|
+
const result = [];
|
|
316
|
+
const seen = new Set();
|
|
317
|
+
for (const entry of value) {
|
|
318
|
+
const normalized = normalizeWorkBoardLinkedSession(entry);
|
|
319
|
+
if (!normalized.ok)
|
|
320
|
+
continue;
|
|
321
|
+
const key = `${normalized.value.profileId}\u0000${normalized.value.hostId}\u0000${normalized.value.sessionId}`;
|
|
322
|
+
if (seen.has(key))
|
|
323
|
+
continue;
|
|
324
|
+
seen.add(key);
|
|
325
|
+
result.push(normalized.value);
|
|
326
|
+
}
|
|
327
|
+
return result;
|
|
328
|
+
}
|
|
239
329
|
export function normalizeUpdateWorkBoardItemInput(input) {
|
|
240
330
|
if (!isRecord(input))
|
|
241
331
|
return fail('Work Board update must be an object');
|
|
@@ -395,6 +485,7 @@ export function decodeWorkBoardItem(value) {
|
|
|
395
485
|
const provenance = normalizeWorkBoardProvenance(value.provenance);
|
|
396
486
|
if (!provenance.ok)
|
|
397
487
|
return null;
|
|
488
|
+
const linkedSessions = tolerantWorkBoardLinkedSessions(value.linkedSessions);
|
|
398
489
|
const createdAt = asSafeInteger(value.createdAt);
|
|
399
490
|
const updatedAt = asSafeInteger(value.updatedAt);
|
|
400
491
|
if (createdAt === null || updatedAt === null)
|
|
@@ -418,6 +509,7 @@ export function decodeWorkBoardItem(value) {
|
|
|
418
509
|
archivedAt,
|
|
419
510
|
creator: creator.value,
|
|
420
511
|
provenance: provenance.value,
|
|
512
|
+
linkedSessions,
|
|
421
513
|
createdAt,
|
|
422
514
|
updatedAt,
|
|
423
515
|
};
|
|
@@ -435,6 +527,7 @@ export function decodeWorkBoardItem(value) {
|
|
|
435
527
|
archived: false,
|
|
436
528
|
creator: creator.value,
|
|
437
529
|
provenance: provenance.value,
|
|
530
|
+
linkedSessions,
|
|
438
531
|
createdAt,
|
|
439
532
|
updatedAt,
|
|
440
533
|
};
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
"type": "module",
|
|
7
7
|
"sideEffects": false,
|
|
8
8
|
"exports": {
|
|
9
|
+
"./executor-id": "./dist/executor-id.js",
|
|
9
10
|
"./durable-tool-result-projection": "./dist/durable-tool-result-projection.js",
|
|
10
11
|
"./model-projection-transition": "./dist/model-projection-transition.js",
|
|
11
12
|
"./canonical-runtime-event": "./dist/canonical-runtime-event.js",
|