negotium 0.2.4 → 0.2.6
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/agent-helpers.js +241 -127
- package/dist/agent-helpers.js.map +19 -19
- package/dist/background-bash.js +1 -3
- package/dist/background-bash.js.map +4 -4
- package/dist/browser-runtime.js +1 -3
- package/dist/browser-runtime.js.map +4 -4
- package/dist/{chunk-1s9ryz8g.js → chunk-qmbcbhyy.js} +20 -12
- package/dist/chunk-qmbcbhyy.js.map +35 -0
- package/dist/hosted-agent.js +13 -10
- package/dist/hosted-agent.js.map +10 -10
- package/dist/main.js +607 -438
- package/dist/main.js.map +30 -29
- package/dist/mcp-factories.js +238 -123
- package/dist/mcp-factories.js.map +18 -18
- package/dist/prompts.js +1 -3
- package/dist/prompts.js.map +4 -4
- package/dist/query-runtime.js +1 -3
- package/dist/query-runtime.js.map +5 -5
- package/dist/registry.js +3 -3
- package/dist/registry.js.map +2 -2
- package/dist/rollout.js +1 -1
- package/dist/runtime/src/agents/api-topic-agent-switch.ts +6 -12
- package/dist/runtime/src/agents/claude-provider.ts +2 -2
- package/dist/runtime/src/agents/codex-provider.ts +1 -0
- package/dist/runtime/src/agents/index.ts +19 -14
- package/dist/runtime/src/agents/maestro-provider.ts +1 -1
- package/dist/runtime/src/agents/rollout/codex.ts +25 -18
- package/dist/runtime/src/agents/self-config-core.ts +2 -4
- package/dist/runtime/src/agents/topic-agent-switch.ts +4 -10
- package/dist/runtime/src/application/submit-runtime-gateway-turn.ts +91 -19
- package/dist/runtime/src/application/switch-topic-model.ts +7 -10
- package/dist/runtime/src/index.ts +4 -0
- package/dist/runtime/src/mcp/wiki-server.ts +19 -12
- package/dist/runtime/src/platform/config.ts +0 -2
- package/dist/runtime/src/platform/log-rotation.ts +45 -0
- package/dist/runtime/src/platform/mcp-config.ts +9 -3
- package/dist/runtime/src/query/active-rooms.ts +7 -1
- package/dist/runtime/src/runtime/errors.ts +1 -0
- package/dist/runtime/src/runtime/turn-event-stream.ts +46 -1
- package/dist/runtime/src/runtime/turn-runner.ts +176 -100
- package/dist/runtime/src/runtime/user-turn-envelope.ts +19 -0
- package/dist/runtime/src/storage/runtime-gateway-submissions.ts +32 -3
- package/dist/runtime/src/storage/runtime-turn-requests.ts +68 -7
- package/dist/runtime/src/types.ts +2 -0
- package/dist/runtime/src/version.ts +1 -1
- package/dist/runtime-helpers.js +1 -3
- package/dist/runtime-helpers.js.map +4 -4
- package/dist/storage.js.map +1 -1
- package/dist/types/packages/core/src/agents/api-topic-agent-switch.d.ts +1 -1
- package/dist/types/packages/core/src/agents/self-config-core.d.ts +1 -1
- package/dist/types/packages/core/src/platform/config.d.ts +0 -1
- package/dist/types/packages/core/src/platform/mcp-config.d.ts +3 -0
- package/dist/types/packages/core/src/query/active-rooms.d.ts +7 -1
- package/dist/types/packages/core/src/runtime/turn-runner.d.ts +42 -1
- package/dist/types/packages/core/src/runtime/user-turn-envelope.d.ts +7 -0
- package/dist/types/packages/core/src/storage/runtime-turn-requests.d.ts +17 -0
- package/dist/types/packages/core/src/types.d.ts +2 -0
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/dist/vault.js +1 -3
- package/dist/vault.js.map +4 -4
- package/package.json +1 -1
- package/dist/chunk-1s9ryz8g.js.map +0 -35
|
@@ -9,6 +9,8 @@ export interface RuntimeGatewaySubmission {
|
|
|
9
9
|
createdAt: string;
|
|
10
10
|
ackCursor: number;
|
|
11
11
|
messageCursor: number;
|
|
12
|
+
/** Hash of every ingress field that can change canonical or execution semantics. */
|
|
13
|
+
payloadHash?: string;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
interface RuntimeGatewaySubmissionRow {
|
|
@@ -20,6 +22,7 @@ interface RuntimeGatewaySubmissionRow {
|
|
|
20
22
|
created_at: string;
|
|
21
23
|
ack_cursor: number | bigint;
|
|
22
24
|
message_cursor: number | bigint;
|
|
25
|
+
payload_hash: string | null;
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
db.exec(`
|
|
@@ -31,7 +34,8 @@ db.exec(`
|
|
|
31
34
|
user_id TEXT NOT NULL,
|
|
32
35
|
created_at TEXT NOT NULL,
|
|
33
36
|
ack_cursor INTEGER NOT NULL DEFAULT 0,
|
|
34
|
-
message_cursor INTEGER NOT NULL DEFAULT 0
|
|
37
|
+
message_cursor INTEGER NOT NULL DEFAULT 0,
|
|
38
|
+
payload_hash TEXT
|
|
35
39
|
)
|
|
36
40
|
`);
|
|
37
41
|
try {
|
|
@@ -39,6 +43,9 @@ try {
|
|
|
39
43
|
"ALTER TABLE runtime_gateway_submissions ADD COLUMN ack_cursor INTEGER NOT NULL DEFAULT 0",
|
|
40
44
|
);
|
|
41
45
|
} catch {}
|
|
46
|
+
try {
|
|
47
|
+
db.exec("ALTER TABLE runtime_gateway_submissions ADD COLUMN payload_hash TEXT");
|
|
48
|
+
} catch {}
|
|
42
49
|
try {
|
|
43
50
|
db.exec(
|
|
44
51
|
"ALTER TABLE runtime_gateway_submissions ADD COLUMN message_cursor INTEGER NOT NULL DEFAULT 0",
|
|
@@ -58,6 +65,7 @@ function rowToSubmission(row: RuntimeGatewaySubmissionRow): RuntimeGatewaySubmis
|
|
|
58
65
|
createdAt: row.created_at,
|
|
59
66
|
ackCursor: Number(row.ack_cursor),
|
|
60
67
|
messageCursor: Number(row.message_cursor),
|
|
68
|
+
payloadHash: row.payload_hash ?? undefined,
|
|
61
69
|
};
|
|
62
70
|
}
|
|
63
71
|
|
|
@@ -76,12 +84,32 @@ export function findRuntimeGatewaySubmission(
|
|
|
76
84
|
return row ? rowToSubmission(row) : null;
|
|
77
85
|
}
|
|
78
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Attach a payload hash to a submission recorded before the `payload_hash`
|
|
89
|
+
* column existed (or before it was populated for that row). Called the first
|
|
90
|
+
* time a legacy row is confirmed to match a duplicate request on every field
|
|
91
|
+
* we *can* verify, so every subsequent replay under the same key is checked
|
|
92
|
+
* against the full semantic payload instead of the narrower legacy field set.
|
|
93
|
+
* A no-op once the row already has a hash, so it never overwrites a value
|
|
94
|
+
* `submitRuntimeGatewayTurn` already trusts.
|
|
95
|
+
*/
|
|
96
|
+
export function backfillRuntimeGatewaySubmissionPayloadHash(
|
|
97
|
+
clientMessageId: string,
|
|
98
|
+
payloadHash: string,
|
|
99
|
+
): void {
|
|
100
|
+
db.query(
|
|
101
|
+
`UPDATE runtime_gateway_submissions
|
|
102
|
+
SET payload_hash = ?
|
|
103
|
+
WHERE client_message_id = ? AND payload_hash IS NULL`,
|
|
104
|
+
).run(payloadHash, clientMessageId);
|
|
105
|
+
}
|
|
106
|
+
|
|
79
107
|
export function recordRuntimeGatewaySubmission(submission: RuntimeGatewaySubmission): void {
|
|
80
108
|
db.query(
|
|
81
109
|
`INSERT INTO runtime_gateway_submissions
|
|
82
110
|
(client_message_id, request_id, topic_id, message_id, user_id, created_at,
|
|
83
|
-
ack_cursor, message_cursor)
|
|
84
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
111
|
+
ack_cursor, message_cursor, payload_hash)
|
|
112
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
85
113
|
).run(
|
|
86
114
|
submission.clientMessageId,
|
|
87
115
|
submission.requestId,
|
|
@@ -91,5 +119,6 @@ export function recordRuntimeGatewaySubmission(submission: RuntimeGatewaySubmiss
|
|
|
91
119
|
submission.createdAt,
|
|
92
120
|
submission.ackCursor,
|
|
93
121
|
submission.messageCursor,
|
|
122
|
+
submission.payloadHash ?? null,
|
|
94
123
|
);
|
|
95
124
|
}
|
|
@@ -2,7 +2,7 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import {
|
|
3
3
|
flattenUserTurnAttachments,
|
|
4
4
|
legacyUserTurnEnvelope,
|
|
5
|
-
|
|
5
|
+
renderUserTurnBatch,
|
|
6
6
|
type UserTurnEnvelope,
|
|
7
7
|
} from "#runtime/user-turn-envelope";
|
|
8
8
|
import { db } from "#storage/forum-db";
|
|
@@ -31,10 +31,14 @@ export interface RuntimeUserTurnExecution {
|
|
|
31
31
|
bridgeSessionFromHistory?: boolean;
|
|
32
32
|
peerBridge?: PeerRuntimeBridgeContext;
|
|
33
33
|
from?: string;
|
|
34
|
+
/** Vault namespace for this turn, independent from the local execution principal. */
|
|
35
|
+
vaultUserId?: string;
|
|
34
36
|
/** Newly accepted user texts not yet recorded in the unified conversation log. */
|
|
35
37
|
conversationPrompts?: string[];
|
|
36
38
|
/** Number of leading userMessages already present in the unified conversation log. */
|
|
37
39
|
loggedUserMessageCount?: number;
|
|
40
|
+
/** Native session whose provider output proves it accepted this request's user turn. */
|
|
41
|
+
providerSessionId?: string;
|
|
38
42
|
/** Request ids whose ordered messages were folded into this replacement. */
|
|
39
43
|
supersededRequestIds?: string[];
|
|
40
44
|
}
|
|
@@ -175,7 +179,11 @@ function rowToRequest(row: RuntimeUserTurnRequestRow): RuntimeUserTurnRequest {
|
|
|
175
179
|
(Array.isArray((item as UserTurnEnvelope).attachments) &&
|
|
176
180
|
(item as UserTurnEnvelope).attachments?.every(
|
|
177
181
|
(attachment) => typeof attachment === "string",
|
|
178
|
-
)))
|
|
182
|
+
))) &&
|
|
183
|
+
((item as UserTurnEnvelope).actorUserId === undefined ||
|
|
184
|
+
typeof (item as UserTurnEnvelope).actorUserId === "string") &&
|
|
185
|
+
((item as UserTurnEnvelope).actorLabel === undefined ||
|
|
186
|
+
typeof (item as UserTurnEnvelope).actorLabel === "string"),
|
|
179
187
|
)
|
|
180
188
|
) {
|
|
181
189
|
userMessages = parsed as UserTurnEnvelope[];
|
|
@@ -285,6 +293,8 @@ export function mergeRuntimeUserTurnRequest(input: {
|
|
|
285
293
|
execution: RuntimeUserTurnExecution;
|
|
286
294
|
topicEpoch: number;
|
|
287
295
|
alreadyIncludedRequestIds?: string[];
|
|
296
|
+
/** Requests already committed to the provider's native session; keep their lineage, not prompts. */
|
|
297
|
+
omitRequestIds?: string[];
|
|
288
298
|
}): { requestId: string; supersededRequestIds: string[] } {
|
|
289
299
|
const now = Date.now();
|
|
290
300
|
return db
|
|
@@ -295,14 +305,23 @@ export function mergeRuntimeUserTurnRequest(input: {
|
|
|
295
305
|
)
|
|
296
306
|
.all(input.topicId);
|
|
297
307
|
const previous = rows.map(rowToRequest);
|
|
308
|
+
const omittedRequestIds = new Set([
|
|
309
|
+
...(input.omitRequestIds ?? []),
|
|
310
|
+
...previous
|
|
311
|
+
.filter((request) => Boolean(request.execution?.providerSessionId))
|
|
312
|
+
.map((request) => request.requestId),
|
|
313
|
+
]);
|
|
314
|
+
const carried = previous.filter((request) => !omittedRequestIds.has(request.requestId));
|
|
298
315
|
const alreadyIncludedRequestIds = new Set(input.alreadyIncludedRequestIds ?? []);
|
|
299
|
-
const alreadyIncludedMessages =
|
|
316
|
+
const alreadyIncludedMessages = carried
|
|
300
317
|
.filter((request) => alreadyIncludedRequestIds.has(request.requestId))
|
|
301
318
|
.flatMap((request) => request.userMessages);
|
|
302
319
|
const includedPrefixMatches = alreadyIncludedMessages.every((message, index) => {
|
|
303
320
|
const candidate = input.userMessages[index];
|
|
304
321
|
return (
|
|
305
322
|
candidate?.prompt === message.prompt &&
|
|
323
|
+
candidate.actorUserId === message.actorUserId &&
|
|
324
|
+
candidate.actorLabel === message.actorLabel &&
|
|
306
325
|
JSON.stringify(candidate.attachments ?? []) === JSON.stringify(message.attachments ?? [])
|
|
307
326
|
);
|
|
308
327
|
});
|
|
@@ -310,7 +329,7 @@ export function mergeRuntimeUserTurnRequest(input: {
|
|
|
310
329
|
? alreadyIncludedMessages.length
|
|
311
330
|
: 0;
|
|
312
331
|
const userMessages = [
|
|
313
|
-
...
|
|
332
|
+
...carried.flatMap((request) => request.userMessages),
|
|
314
333
|
...input.userMessages.slice(alreadyIncludedMessageCount),
|
|
315
334
|
];
|
|
316
335
|
const incomingLoggedCount = Math.min(
|
|
@@ -318,7 +337,7 @@ export function mergeRuntimeUserTurnRequest(input: {
|
|
|
318
337
|
input.userMessages.length,
|
|
319
338
|
);
|
|
320
339
|
const loggedUserMessageCount =
|
|
321
|
-
|
|
340
|
+
carried.reduce((count, request) => count + loggedMessageCount(request), 0) +
|
|
322
341
|
Math.max(0, incomingLoggedCount - alreadyIncludedMessageCount);
|
|
323
342
|
const execution: RuntimeUserTurnExecution = {
|
|
324
343
|
...input.execution,
|
|
@@ -335,7 +354,7 @@ export function mergeRuntimeUserTurnRequest(input: {
|
|
|
335
354
|
.slice(loggedUserMessageCount)
|
|
336
355
|
.map((message) => message.prompt),
|
|
337
356
|
};
|
|
338
|
-
const sessionBase =
|
|
357
|
+
const sessionBase = carried.find(
|
|
339
358
|
(request) => request.execution?.sessionIdSpecified,
|
|
340
359
|
)?.execution;
|
|
341
360
|
if (sessionBase?.sessionIdSpecified) {
|
|
@@ -355,7 +374,7 @@ export function mergeRuntimeUserTurnRequest(input: {
|
|
|
355
374
|
input.requestId,
|
|
356
375
|
input.topicId,
|
|
357
376
|
input.userId,
|
|
358
|
-
|
|
377
|
+
renderUserTurnBatch(userMessages),
|
|
359
378
|
JSON.stringify(userMessages),
|
|
360
379
|
attachments?.length ? JSON.stringify(attachments) : null,
|
|
361
380
|
input.allowAutoContinue ? 1 : 0,
|
|
@@ -371,6 +390,46 @@ export function mergeRuntimeUserTurnRequest(input: {
|
|
|
371
390
|
.immediate();
|
|
372
391
|
}
|
|
373
392
|
|
|
393
|
+
/**
|
|
394
|
+
* Record that provider output proves the native session contains this durable
|
|
395
|
+
* turn. A session-id event alone is insufficient: some providers publish it
|
|
396
|
+
* before appending the user prompt. This marker lets a different runtime
|
|
397
|
+
* process omit only a demonstrably committed prompt when it merges a steering
|
|
398
|
+
* message after preemption.
|
|
399
|
+
*
|
|
400
|
+
* Match only the exact request id. A late session event from a superseded turn
|
|
401
|
+
* must not mark its replacement (whose prompts have not reached the provider).
|
|
402
|
+
*/
|
|
403
|
+
export function markRuntimeUserTurnProviderSessionObserved(
|
|
404
|
+
topicId: string,
|
|
405
|
+
requestId: string,
|
|
406
|
+
sessionId: string,
|
|
407
|
+
): boolean {
|
|
408
|
+
return db
|
|
409
|
+
.transaction(() => {
|
|
410
|
+
const row = db
|
|
411
|
+
.query<RuntimeUserTurnRequestRow, [string, string]>(
|
|
412
|
+
"SELECT * FROM runtime_user_turn_requests WHERE topic_id = ? AND request_id = ?",
|
|
413
|
+
)
|
|
414
|
+
.get(topicId, requestId);
|
|
415
|
+
if (!row) return false;
|
|
416
|
+
const request = rowToRequest(row);
|
|
417
|
+
const execution: RuntimeUserTurnExecution = {
|
|
418
|
+
...request.execution,
|
|
419
|
+
providerSessionId: sessionId,
|
|
420
|
+
};
|
|
421
|
+
const result = db
|
|
422
|
+
.query(
|
|
423
|
+
`UPDATE runtime_user_turn_requests
|
|
424
|
+
SET execution_json = ?
|
|
425
|
+
WHERE topic_id = ? AND request_id = ?`,
|
|
426
|
+
)
|
|
427
|
+
.run(JSON.stringify(execution), topicId, requestId);
|
|
428
|
+
return result.changes === 1;
|
|
429
|
+
})
|
|
430
|
+
.immediate();
|
|
431
|
+
}
|
|
432
|
+
|
|
374
433
|
export function markRuntimeUserTurnMessagesLogged(
|
|
375
434
|
topicId: string,
|
|
376
435
|
requestId: string,
|
|
@@ -392,6 +451,8 @@ export function markRuntimeUserTurnMessagesLogged(
|
|
|
392
451
|
const candidate = request.userMessages[index];
|
|
393
452
|
return (
|
|
394
453
|
candidate?.prompt === message.prompt &&
|
|
454
|
+
candidate.actorUserId === message.actorUserId &&
|
|
455
|
+
candidate.actorLabel === message.actorLabel &&
|
|
395
456
|
JSON.stringify(candidate.attachments ?? []) ===
|
|
396
457
|
JSON.stringify(message.attachments ?? [])
|
|
397
458
|
);
|
|
@@ -176,6 +176,8 @@ export interface AgentQueryOptions {
|
|
|
176
176
|
cwd: string;
|
|
177
177
|
systemPrompt: string;
|
|
178
178
|
userId?: string;
|
|
179
|
+
/** Credential namespace when it differs from the execution principal. */
|
|
180
|
+
vaultUserId?: string;
|
|
179
181
|
session?: string;
|
|
180
182
|
playwrightPort?: number;
|
|
181
183
|
playwrightCapability?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const NEGOTIUM_VERSION = "0.2.
|
|
1
|
+
export const NEGOTIUM_VERSION = "0.2.6";
|
package/dist/runtime-helpers.js
CHANGED
|
@@ -447,7 +447,6 @@ var BROWSER_DIR = resolveLocalStateDir("NEGOTIUM_BROWSER_DIR", "browser");
|
|
|
447
447
|
var BROWSER_PROFILES_DIR = resolve(BROWSER_DIR, "profiles");
|
|
448
448
|
var BINARIES_DIR = resolve(STATE_DIR, "binaries");
|
|
449
449
|
var SECRETS_DIR = resolve(STATE_DIR, "secrets");
|
|
450
|
-
var CONTEXTS_DIR = resolve(STATE_DIR, "data", "contexts");
|
|
451
450
|
var DM_WORKSPACE_DIR = resolve(STATE_DIR, "data", "dm");
|
|
452
451
|
var SESSION_WORKSPACE_DIR = resolve(STATE_DIR, "data", "sessions");
|
|
453
452
|
var CLAUDE_EXECUTABLE_ENV = envText("NEGOTIUM_CLAUDE_EXECUTABLE");
|
|
@@ -590,7 +589,6 @@ mkdirSync2(WORKSPACE_DIR, { recursive: true });
|
|
|
590
589
|
mkdirSync2(TOPIC_WORKSPACE_DIR, { recursive: true });
|
|
591
590
|
mkdirSync2(SHARED_WIKI_DIR, { recursive: true });
|
|
592
591
|
mkdirSync2(CRON_WORKSPACE_DIR, { recursive: true });
|
|
593
|
-
mkdirSync2(CONTEXTS_DIR, { recursive: true });
|
|
594
592
|
mkdirSync2(DM_WORKSPACE_DIR, { recursive: true });
|
|
595
593
|
mkdirSync2(SESSION_WORKSPACE_DIR, { recursive: true });
|
|
596
594
|
mkdirSync2(BROWSER_DIR, { recursive: true });
|
|
@@ -1134,4 +1132,4 @@ export {
|
|
|
1134
1132
|
CLAUDE_EFFORT_VALUES
|
|
1135
1133
|
};
|
|
1136
1134
|
|
|
1137
|
-
//# debugId=
|
|
1135
|
+
//# debugId=38CF47A0C3C063A564756E2164756E21
|