@deepagents/context 4.2.0 → 4.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -12
- package/dist/browser.js.map +2 -2
- package/dist/index.js +138 -24
- package/dist/index.js.map +3 -3
- package/dist/lib/engine.d.ts +9 -2
- package/dist/lib/engine.d.ts.map +1 -1
- package/dist/lib/sandbox/apple-container-sandbox.d.ts.map +1 -1
- package/dist/lib/sandbox/container-engine.d.ts +0 -1
- package/dist/lib/sandbox/container-engine.d.ts.map +1 -1
- package/dist/lib/sandbox/docker-sandbox.d.ts.map +1 -1
- package/dist/lib/save/save-pipeline.d.ts +13 -1
- package/dist/lib/save/save-pipeline.d.ts.map +1 -1
- package/dist/lib/store/postgres.store.d.ts +2 -1
- package/dist/lib/store/postgres.store.d.ts.map +1 -1
- package/dist/lib/store/sqlite.store.d.ts +2 -1
- package/dist/lib/store/sqlite.store.d.ts.map +1 -1
- package/dist/lib/store/sqlserver.store.d.ts +2 -1
- package/dist/lib/store/sqlserver.store.d.ts.map +1 -1
- package/dist/lib/store/store.d.ts +17 -2
- package/dist/lib/store/store.d.ts.map +1 -1
- package/package.json +3 -4
package/dist/index.js
CHANGED
|
@@ -2616,7 +2616,15 @@ async function evaluateFiredReminders(configs, whenCtx) {
|
|
|
2616
2616
|
}
|
|
2617
2617
|
|
|
2618
2618
|
// packages/context/src/lib/save/save-pipeline.ts
|
|
2619
|
-
var
|
|
2619
|
+
var HeadConflictError = class extends Error {
|
|
2620
|
+
constructor(chatId, headMessageId) {
|
|
2621
|
+
super(
|
|
2622
|
+
`Could not commit head "${headMessageId}" for chat "${chatId}": concurrent writers kept moving the branch head`
|
|
2623
|
+
);
|
|
2624
|
+
this.name = "HeadConflictError";
|
|
2625
|
+
}
|
|
2626
|
+
};
|
|
2627
|
+
var SavePipeline = class _SavePipeline {
|
|
2620
2628
|
#engine;
|
|
2621
2629
|
#pending;
|
|
2622
2630
|
#shouldBranch = true;
|
|
@@ -2672,9 +2680,49 @@ var SavePipeline = class {
|
|
|
2672
2680
|
);
|
|
2673
2681
|
}
|
|
2674
2682
|
await this.#engine.store.addMessages(messages);
|
|
2675
|
-
await this.#
|
|
2683
|
+
await this.#commitHead(messages[0], parentId);
|
|
2676
2684
|
return { headMessageId: parentId };
|
|
2677
2685
|
}
|
|
2686
|
+
static #maxCommitAttempts = 5;
|
|
2687
|
+
/**
|
|
2688
|
+
* Advance the branch head to `newHead` through the store's CAS. A stale
|
|
2689
|
+
* cached head must never rewind the branch (that silently orphans turns
|
|
2690
|
+
* committed in between), so a rejected CAS re-reads the store head and
|
|
2691
|
+
* reconciles:
|
|
2692
|
+
* - the store head already descends from `newHead` (an in-place assistant
|
|
2693
|
+
* fill whose turn was built past): content is on the chain, keep the
|
|
2694
|
+
* store head;
|
|
2695
|
+
* - `newHead` descends from the store head: fast-forward, retry against it;
|
|
2696
|
+
* - true fork (another turn won the same head): graft this turn onto the
|
|
2697
|
+
* winning head by re-parenting the first pending message, then retry.
|
|
2698
|
+
* Grafting applies only to messages chained off the stale head — an
|
|
2699
|
+
* in-place fill keeps its original parent and its content already landed.
|
|
2700
|
+
*/
|
|
2701
|
+
async #commitHead(first2, newHead) {
|
|
2702
|
+
let expected = this.#engine.getActiveBranch().headMessageId;
|
|
2703
|
+
for (let i = 0; i < _SavePipeline.#maxCommitAttempts; i++) {
|
|
2704
|
+
if (await this.#engine.commitHead(newHead, expected)) return;
|
|
2705
|
+
const fresh = (await this.#engine.refreshBranch()).headMessageId;
|
|
2706
|
+
if (fresh === null || fresh === expected) {
|
|
2707
|
+
expected = fresh;
|
|
2708
|
+
continue;
|
|
2709
|
+
}
|
|
2710
|
+
if (await this.#chainContains(fresh, newHead)) return;
|
|
2711
|
+
if (await this.#chainContains(newHead, fresh)) {
|
|
2712
|
+
expected = fresh;
|
|
2713
|
+
continue;
|
|
2714
|
+
}
|
|
2715
|
+
if (first2.parentId !== expected) return;
|
|
2716
|
+
await this.#engine.store.setMessageParent(first2.id, fresh);
|
|
2717
|
+
first2.parentId = fresh;
|
|
2718
|
+
expected = fresh;
|
|
2719
|
+
}
|
|
2720
|
+
throw new HeadConflictError(this.#engine.chatId, newHead);
|
|
2721
|
+
}
|
|
2722
|
+
async #chainContains(headId, messageId) {
|
|
2723
|
+
const chain = await this.#engine.store.getMessageChain(headId);
|
|
2724
|
+
return chain.some((message2) => message2.id === messageId);
|
|
2725
|
+
}
|
|
2678
2726
|
};
|
|
2679
2727
|
|
|
2680
2728
|
// packages/context/src/lib/store/sqlite.store.ts
|
|
@@ -2942,6 +2990,17 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
2942
2990
|
}
|
|
2943
2991
|
});
|
|
2944
2992
|
}
|
|
2993
|
+
async setMessageParent(messageId, parentId) {
|
|
2994
|
+
if (parentId === messageId) {
|
|
2995
|
+
throw new Error(`Message ${messageId} cannot be its own parent`);
|
|
2996
|
+
}
|
|
2997
|
+
const result = this.#stmt(
|
|
2998
|
+
"UPDATE messages SET parentId = ? WHERE id = ?"
|
|
2999
|
+
).run(parentId, messageId);
|
|
3000
|
+
if (result.changes === 0) {
|
|
3001
|
+
throw new Error(`Message ${messageId} not found`);
|
|
3002
|
+
}
|
|
3003
|
+
}
|
|
2945
3004
|
async getMessage(messageId) {
|
|
2946
3005
|
const row = this.#stmt("SELECT * FROM messages WHERE id = ?").get(
|
|
2947
3006
|
messageId
|
|
@@ -3048,11 +3107,11 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
3048
3107
|
this.#db.prepare("UPDATE branches SET isActive = 0 WHERE chatId = ?").run(chatId);
|
|
3049
3108
|
this.#db.prepare("UPDATE branches SET isActive = 1 WHERE id = ?").run(branchId);
|
|
3050
3109
|
}
|
|
3051
|
-
async updateBranchHead(branchId, messageId) {
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3110
|
+
async updateBranchHead(branchId, messageId, expectedHeadMessageId) {
|
|
3111
|
+
const result = this.#stmt(
|
|
3112
|
+
"UPDATE branches SET headMessageId = ? WHERE id = ? AND headMessageId IS ?"
|
|
3113
|
+
).run(messageId, branchId, expectedHeadMessageId);
|
|
3114
|
+
return result.changes > 0;
|
|
3056
3115
|
}
|
|
3057
3116
|
async listBranches(chatId) {
|
|
3058
3117
|
const rows = this.#db.prepare(
|
|
@@ -3963,12 +4022,29 @@ var ContextEngine = class _ContextEngine {
|
|
|
3963
4022
|
id: this.#activeBranch.id,
|
|
3964
4023
|
headMessageId: this.#activeBranch.headMessageId
|
|
3965
4024
|
}),
|
|
3966
|
-
commitHead: async (headMessageId) => {
|
|
3967
|
-
await this.#store.updateBranchHead(
|
|
4025
|
+
commitHead: async (headMessageId, expectedHeadMessageId) => {
|
|
4026
|
+
const committed = await this.#store.updateBranchHead(
|
|
3968
4027
|
this.#activeBranch.id,
|
|
3969
|
-
headMessageId
|
|
4028
|
+
headMessageId,
|
|
4029
|
+
expectedHeadMessageId
|
|
3970
4030
|
);
|
|
3971
|
-
|
|
4031
|
+
if (committed) {
|
|
4032
|
+
this.#activeBranch.headMessageId = headMessageId;
|
|
4033
|
+
}
|
|
4034
|
+
return committed;
|
|
4035
|
+
},
|
|
4036
|
+
refreshBranch: async () => {
|
|
4037
|
+
const fresh = await this.#store.getBranch(
|
|
4038
|
+
this.#chatId,
|
|
4039
|
+
this.#activeBranch.name
|
|
4040
|
+
);
|
|
4041
|
+
if (!fresh) {
|
|
4042
|
+
throw new Error(
|
|
4043
|
+
`Branch "${this.#activeBranch.name}" not found for chat "${this.#chatId}"`
|
|
4044
|
+
);
|
|
4045
|
+
}
|
|
4046
|
+
this.#branch = fresh;
|
|
4047
|
+
return { id: fresh.id, headMessageId: fresh.headMessageId };
|
|
3972
4048
|
},
|
|
3973
4049
|
rewindForUpdate: (parentId) => this.#rewindForUpdate(parentId)
|
|
3974
4050
|
};
|
|
@@ -4069,8 +4145,14 @@ var ContextEngine = class _ContextEngine {
|
|
|
4069
4145
|
*
|
|
4070
4146
|
* @example
|
|
4071
4147
|
* ```ts
|
|
4072
|
-
* context.set(
|
|
4073
|
-
*
|
|
4148
|
+
* context.set(
|
|
4149
|
+
* user({
|
|
4150
|
+
* id: 'q1',
|
|
4151
|
+
* role: 'user',
|
|
4152
|
+
* parts: [{ type: 'text', text: 'What is 2 + 2?' }],
|
|
4153
|
+
* }),
|
|
4154
|
+
* );
|
|
4155
|
+
* context.set(assistantText('The answer is 5.', { id: 'wrong' })); // Oops!
|
|
4074
4156
|
* await context.save();
|
|
4075
4157
|
*
|
|
4076
4158
|
* // Rewind to the question, creates new branch
|
|
@@ -4908,7 +4990,7 @@ async function chat(agent2, options = {}) {
|
|
|
4908
4990
|
execute: async ({ writer }) => {
|
|
4909
4991
|
writer.merge(uiStream);
|
|
4910
4992
|
if (title) {
|
|
4911
|
-
writer.write({ type: "data-chat-title", data: title });
|
|
4993
|
+
writer.write({ type: "data-chat-title", data: title, transient: true });
|
|
4912
4994
|
}
|
|
4913
4995
|
}
|
|
4914
4996
|
});
|
|
@@ -7168,7 +7250,6 @@ var appleEngine = {
|
|
|
7168
7250
|
inspectArgs(containerId) {
|
|
7169
7251
|
return ["inspect", containerId];
|
|
7170
7252
|
},
|
|
7171
|
-
mountArg: buildMountArg,
|
|
7172
7253
|
parseStatus(stdout) {
|
|
7173
7254
|
const entries = safeParseArray(stdout);
|
|
7174
7255
|
if (entries.length === 0) return "absent";
|
|
@@ -8428,7 +8509,6 @@ var dockerEngine = {
|
|
|
8428
8509
|
containerId
|
|
8429
8510
|
];
|
|
8430
8511
|
},
|
|
8431
|
-
mountArg: dockerMountArg,
|
|
8432
8512
|
parseStatus(status) {
|
|
8433
8513
|
return status === "running" ? "running" : "stopped";
|
|
8434
8514
|
},
|
|
@@ -10204,6 +10284,18 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
|
|
|
10204
10284
|
);
|
|
10205
10285
|
});
|
|
10206
10286
|
}
|
|
10287
|
+
async setMessageParent(messageId, parentId) {
|
|
10288
|
+
if (parentId === messageId) {
|
|
10289
|
+
throw new Error(`Message ${messageId} cannot be its own parent`);
|
|
10290
|
+
}
|
|
10291
|
+
const rows = await this.#query(
|
|
10292
|
+
`UPDATE ${this.#t("messages")} SET parentId = $1 WHERE id = $2 RETURNING id`,
|
|
10293
|
+
[parentId, messageId]
|
|
10294
|
+
);
|
|
10295
|
+
if (rows.length === 0) {
|
|
10296
|
+
throw new Error(`Message ${messageId} not found`);
|
|
10297
|
+
}
|
|
10298
|
+
}
|
|
10207
10299
|
async getMessage(messageId) {
|
|
10208
10300
|
const rows = await this.#query(`SELECT * FROM ${this.#t("messages")} WHERE id = $1`, [messageId]);
|
|
10209
10301
|
if (rows.length === 0) {
|
|
@@ -10326,11 +10418,14 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
|
|
|
10326
10418
|
);
|
|
10327
10419
|
});
|
|
10328
10420
|
}
|
|
10329
|
-
async updateBranchHead(branchId, messageId) {
|
|
10330
|
-
await this.#query(
|
|
10331
|
-
`UPDATE ${this.#t("branches")} SET headMessageId = $1
|
|
10332
|
-
|
|
10421
|
+
async updateBranchHead(branchId, messageId, expectedHeadMessageId) {
|
|
10422
|
+
const rows = await this.#query(
|
|
10423
|
+
`UPDATE ${this.#t("branches")} SET headMessageId = $1
|
|
10424
|
+
WHERE id = $2 AND headMessageId IS NOT DISTINCT FROM $3
|
|
10425
|
+
RETURNING id`,
|
|
10426
|
+
[messageId, branchId, expectedHeadMessageId]
|
|
10333
10427
|
);
|
|
10428
|
+
return rows.length > 0;
|
|
10334
10429
|
}
|
|
10335
10430
|
async listBranches(chatId) {
|
|
10336
10431
|
const branches = await this.#query(
|
|
@@ -10993,6 +11088,20 @@ var SqlServerContextStore = class _SqlServerContextStore extends ContextStore {
|
|
|
10993
11088
|
`);
|
|
10994
11089
|
});
|
|
10995
11090
|
}
|
|
11091
|
+
async setMessageParent(messageId, parentId) {
|
|
11092
|
+
if (parentId === messageId) {
|
|
11093
|
+
throw new Error(`Message ${messageId} cannot be its own parent`);
|
|
11094
|
+
}
|
|
11095
|
+
const rows = await this.#query(
|
|
11096
|
+
`UPDATE ${this.#t("messages")} SET parentId = @p0
|
|
11097
|
+
OUTPUT INSERTED.id
|
|
11098
|
+
WHERE id = @p1`,
|
|
11099
|
+
[parentId, messageId]
|
|
11100
|
+
);
|
|
11101
|
+
if (rows.length === 0) {
|
|
11102
|
+
throw new Error(`Message ${messageId} not found`);
|
|
11103
|
+
}
|
|
11104
|
+
}
|
|
10996
11105
|
async getMessage(messageId) {
|
|
10997
11106
|
const rows = await this.#query(`SELECT * FROM ${this.#t("messages")} WHERE id = @p0`, [messageId]);
|
|
10998
11107
|
if (rows.length === 0) {
|
|
@@ -11118,11 +11227,15 @@ var SqlServerContextStore = class _SqlServerContextStore extends ContextStore {
|
|
|
11118
11227
|
);
|
|
11119
11228
|
});
|
|
11120
11229
|
}
|
|
11121
|
-
async updateBranchHead(branchId, messageId) {
|
|
11122
|
-
await this.#query(
|
|
11123
|
-
`UPDATE ${this.#t("branches")} SET headMessageId = @p0
|
|
11124
|
-
|
|
11230
|
+
async updateBranchHead(branchId, messageId, expectedHeadMessageId) {
|
|
11231
|
+
const rows = await this.#query(
|
|
11232
|
+
`UPDATE ${this.#t("branches")} SET headMessageId = @p0
|
|
11233
|
+
OUTPUT INSERTED.id
|
|
11234
|
+
WHERE id = @p1
|
|
11235
|
+
AND (headMessageId = @p2 OR (headMessageId IS NULL AND @p2 IS NULL))`,
|
|
11236
|
+
[messageId, branchId, expectedHeadMessageId]
|
|
11125
11237
|
);
|
|
11238
|
+
return rows.length > 0;
|
|
11126
11239
|
}
|
|
11127
11240
|
async listBranches(chatId) {
|
|
11128
11241
|
const branches = await this.#query(
|
|
@@ -12974,6 +13087,7 @@ export {
|
|
|
12974
13087
|
FunctionResolver,
|
|
12975
13088
|
GeneratorResolver,
|
|
12976
13089
|
GithubReleaseInstaller,
|
|
13090
|
+
HeadConflictError,
|
|
12977
13091
|
InMemoryContextStore,
|
|
12978
13092
|
InstallError,
|
|
12979
13093
|
Installer,
|