@deepagents/context 0.12.0 → 0.13.0
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/index.js +204 -22
- package/dist/index.js.map +3 -3
- package/dist/lib/agent.d.ts.map +1 -1
- package/dist/lib/engine.d.ts +35 -0
- package/dist/lib/engine.d.ts.map +1 -1
- package/dist/lib/fragments.d.ts +44 -0
- package/dist/lib/fragments.d.ts.map +1 -1
- package/dist/lib/skills/fragments.d.ts +6 -2
- package/dist/lib/skills/fragments.d.ts.map +1 -1
- package/dist/lib/skills/index.d.ts +8 -3
- package/dist/lib/skills/index.d.ts.map +1 -1
- package/dist/lib/skills/types.d.ts +24 -2
- package/dist/lib/skills/types.d.ts.map +1 -1
- package/dist/lib/store/sqlite.store.d.ts.map +1 -1
- package/dist/lib/store/store.d.ts +6 -0
- package/dist/lib/store/store.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// packages/context/src/lib/engine.ts
|
|
2
|
+
import { mergeWith } from "lodash-es";
|
|
3
|
+
|
|
1
4
|
// packages/context/src/lib/estimate.ts
|
|
2
5
|
import { encode } from "gpt-tokenizer";
|
|
3
6
|
var defaultTokenizer = {
|
|
@@ -222,7 +225,7 @@ function message(content) {
|
|
|
222
225
|
} : content;
|
|
223
226
|
return {
|
|
224
227
|
id: message2.id,
|
|
225
|
-
name:
|
|
228
|
+
name: message2.role,
|
|
226
229
|
data: "content",
|
|
227
230
|
type: "message",
|
|
228
231
|
persist: true,
|
|
@@ -244,6 +247,22 @@ function assistantText(content, options) {
|
|
|
244
247
|
parts: [{ type: "text", text: content }]
|
|
245
248
|
});
|
|
246
249
|
}
|
|
250
|
+
var LAZY_ID = Symbol("lazy-id");
|
|
251
|
+
function isLazyFragment(fragment2) {
|
|
252
|
+
return LAZY_ID in fragment2;
|
|
253
|
+
}
|
|
254
|
+
function lastAssistantMessage(content) {
|
|
255
|
+
return {
|
|
256
|
+
name: "assistant",
|
|
257
|
+
type: "message",
|
|
258
|
+
persist: true,
|
|
259
|
+
data: "content",
|
|
260
|
+
[LAZY_ID]: {
|
|
261
|
+
type: "last-assistant",
|
|
262
|
+
content
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
}
|
|
247
266
|
|
|
248
267
|
// packages/context/src/lib/renderers/abstract.renderer.ts
|
|
249
268
|
import pluralize from "pluralize";
|
|
@@ -1038,6 +1057,8 @@ var ContextEngine = class {
|
|
|
1038
1057
|
#branch = null;
|
|
1039
1058
|
#chatData = null;
|
|
1040
1059
|
#initialized = false;
|
|
1060
|
+
/** Initial metadata to merge on first initialization */
|
|
1061
|
+
#initialMetadata;
|
|
1041
1062
|
constructor(options) {
|
|
1042
1063
|
if (!options.chatId) {
|
|
1043
1064
|
throw new Error("chatId is required");
|
|
@@ -1049,6 +1070,7 @@ var ContextEngine = class {
|
|
|
1049
1070
|
this.#chatId = options.chatId;
|
|
1050
1071
|
this.#userId = options.userId;
|
|
1051
1072
|
this.#branchName = "main";
|
|
1073
|
+
this.#initialMetadata = options.metadata;
|
|
1052
1074
|
}
|
|
1053
1075
|
/**
|
|
1054
1076
|
* Initialize the chat and branch if they don't exist.
|
|
@@ -1061,6 +1083,15 @@ var ContextEngine = class {
|
|
|
1061
1083
|
id: this.#chatId,
|
|
1062
1084
|
userId: this.#userId
|
|
1063
1085
|
});
|
|
1086
|
+
if (this.#initialMetadata) {
|
|
1087
|
+
this.#chatData = await this.#store.updateChat(this.#chatId, {
|
|
1088
|
+
metadata: {
|
|
1089
|
+
...this.#chatData.metadata,
|
|
1090
|
+
...this.#initialMetadata
|
|
1091
|
+
}
|
|
1092
|
+
});
|
|
1093
|
+
this.#initialMetadata = void 0;
|
|
1094
|
+
}
|
|
1064
1095
|
this.#branch = await this.#store.getActiveBranch(this.#chatId);
|
|
1065
1096
|
this.#initialized = true;
|
|
1066
1097
|
}
|
|
@@ -1208,6 +1239,12 @@ var ContextEngine = class {
|
|
|
1208
1239
|
if (this.#pendingMessages.length === 0) {
|
|
1209
1240
|
return;
|
|
1210
1241
|
}
|
|
1242
|
+
for (let i = 0; i < this.#pendingMessages.length; i++) {
|
|
1243
|
+
const fragment2 = this.#pendingMessages[i];
|
|
1244
|
+
if (isLazyFragment(fragment2)) {
|
|
1245
|
+
this.#pendingMessages[i] = await this.#resolveLazyFragment(fragment2);
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1211
1248
|
let parentId = this.#branch.headMessageId;
|
|
1212
1249
|
const now = Date.now();
|
|
1213
1250
|
for (const fragment2 of this.#pendingMessages) {
|
|
@@ -1227,6 +1264,39 @@ var ContextEngine = class {
|
|
|
1227
1264
|
this.#branch.headMessageId = parentId;
|
|
1228
1265
|
this.#pendingMessages = [];
|
|
1229
1266
|
}
|
|
1267
|
+
/**
|
|
1268
|
+
* Resolve a lazy fragment by finding the appropriate ID.
|
|
1269
|
+
*/
|
|
1270
|
+
async #resolveLazyFragment(fragment2) {
|
|
1271
|
+
const lazy = fragment2[LAZY_ID];
|
|
1272
|
+
if (lazy.type === "last-assistant") {
|
|
1273
|
+
const lastId = await this.#getLastAssistantId();
|
|
1274
|
+
return assistantText(lazy.content, { id: lastId ?? crypto.randomUUID() });
|
|
1275
|
+
}
|
|
1276
|
+
throw new Error(`Unknown lazy fragment type: ${lazy.type}`);
|
|
1277
|
+
}
|
|
1278
|
+
/**
|
|
1279
|
+
* Find the most recent assistant message ID (pending or persisted).
|
|
1280
|
+
*/
|
|
1281
|
+
async #getLastAssistantId() {
|
|
1282
|
+
for (let i = this.#pendingMessages.length - 1; i >= 0; i--) {
|
|
1283
|
+
const msg = this.#pendingMessages[i];
|
|
1284
|
+
if (msg.name === "assistant" && !isLazyFragment(msg)) {
|
|
1285
|
+
return msg.id;
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
if (this.#branch?.headMessageId) {
|
|
1289
|
+
const chain = await this.#store.getMessageChain(
|
|
1290
|
+
this.#branch.headMessageId
|
|
1291
|
+
);
|
|
1292
|
+
for (let i = chain.length - 1; i >= 0; i--) {
|
|
1293
|
+
if (chain[i].name === "assistant") {
|
|
1294
|
+
return chain[i].id;
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
return void 0;
|
|
1299
|
+
}
|
|
1230
1300
|
/**
|
|
1231
1301
|
* Estimate token count and cost for the full context.
|
|
1232
1302
|
*
|
|
@@ -1495,6 +1565,36 @@ var ContextEngine = class {
|
|
|
1495
1565
|
}
|
|
1496
1566
|
this.#chatData = await this.#store.updateChat(this.#chatId, storeUpdates);
|
|
1497
1567
|
}
|
|
1568
|
+
/**
|
|
1569
|
+
* Track token usage for the current chat.
|
|
1570
|
+
* Accumulates usage metrics in chat.metadata.usage.
|
|
1571
|
+
*
|
|
1572
|
+
* @param usage - Token usage from AI SDK (LanguageModelUsage)
|
|
1573
|
+
*
|
|
1574
|
+
* @example
|
|
1575
|
+
* ```ts
|
|
1576
|
+
* // In onFinish callback
|
|
1577
|
+
* const usage = await result.totalUsage;
|
|
1578
|
+
* await context.trackUsage(usage);
|
|
1579
|
+
* ```
|
|
1580
|
+
*/
|
|
1581
|
+
async trackUsage(usage) {
|
|
1582
|
+
await this.#ensureInitialized();
|
|
1583
|
+
const freshChatData = await this.#store.getChat(this.#chatId);
|
|
1584
|
+
const currentUsage = freshChatData?.metadata?.usage ?? {};
|
|
1585
|
+
const updatedUsage = mergeWith(
|
|
1586
|
+
{},
|
|
1587
|
+
currentUsage,
|
|
1588
|
+
usage,
|
|
1589
|
+
(a, b) => typeof a === "number" || typeof b === "number" ? (a ?? 0) + (b ?? 0) : void 0
|
|
1590
|
+
);
|
|
1591
|
+
this.#chatData = await this.#store.updateChat(this.#chatId, {
|
|
1592
|
+
metadata: {
|
|
1593
|
+
...freshChatData?.metadata,
|
|
1594
|
+
usage: updatedUsage
|
|
1595
|
+
}
|
|
1596
|
+
});
|
|
1597
|
+
}
|
|
1498
1598
|
/**
|
|
1499
1599
|
* Consolidate context fragments (no-op for now).
|
|
1500
1600
|
*
|
|
@@ -1506,6 +1606,35 @@ var ContextEngine = class {
|
|
|
1506
1606
|
consolidate() {
|
|
1507
1607
|
return void 0;
|
|
1508
1608
|
}
|
|
1609
|
+
/**
|
|
1610
|
+
* Extract skill path mappings from available_skills fragments.
|
|
1611
|
+
* Returns array of { host, sandbox } for mounting in sandbox filesystem.
|
|
1612
|
+
*
|
|
1613
|
+
* Reads the original `paths` configuration stored in fragment metadata
|
|
1614
|
+
* by the skills() fragment helper.
|
|
1615
|
+
*
|
|
1616
|
+
* @example
|
|
1617
|
+
* ```ts
|
|
1618
|
+
* const context = new ContextEngine({ store, chatId, userId })
|
|
1619
|
+
* .set(skills({ paths: [{ host: './skills', sandbox: '/skills' }] }));
|
|
1620
|
+
*
|
|
1621
|
+
* const mounts = context.getSkillMounts();
|
|
1622
|
+
* // [{ host: './skills', sandbox: '/skills' }]
|
|
1623
|
+
* ```
|
|
1624
|
+
*/
|
|
1625
|
+
getSkillMounts() {
|
|
1626
|
+
const mounts = [];
|
|
1627
|
+
for (const fragment2 of this.#fragments) {
|
|
1628
|
+
if (fragment2.name === "available_skills" && fragment2.metadata && Array.isArray(fragment2.metadata.paths)) {
|
|
1629
|
+
for (const mapping of fragment2.metadata.paths) {
|
|
1630
|
+
if (typeof mapping === "object" && mapping !== null && typeof mapping.host === "string" && typeof mapping.sandbox === "string") {
|
|
1631
|
+
mounts.push({ host: mapping.host, sandbox: mapping.sandbox });
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
return mounts;
|
|
1637
|
+
}
|
|
1509
1638
|
/**
|
|
1510
1639
|
* Inspect the full context state for debugging.
|
|
1511
1640
|
* Returns a JSON-serializable object with context information.
|
|
@@ -1814,9 +1943,10 @@ var errorRecoveryGuardrail = {
|
|
|
1814
1943
|
"My response format was invalid. Let me try again with a properly formatted response."
|
|
1815
1944
|
);
|
|
1816
1945
|
}
|
|
1946
|
+
console.dir({ part }, { depth: null });
|
|
1817
1947
|
return logAndFail(
|
|
1818
1948
|
"Unknown error",
|
|
1819
|
-
`An error occurred: ${errorText
|
|
1949
|
+
`An error occurred: ${errorText}. Let me try a different approach.`
|
|
1820
1950
|
);
|
|
1821
1951
|
}
|
|
1822
1952
|
};
|
|
@@ -2642,9 +2772,13 @@ function discoverSkillsInDirectory(directory) {
|
|
|
2642
2772
|
|
|
2643
2773
|
// packages/context/src/lib/skills/fragments.ts
|
|
2644
2774
|
function skills(options) {
|
|
2775
|
+
const pathMapping = /* @__PURE__ */ new Map();
|
|
2776
|
+
for (const { host, sandbox } of options.paths) {
|
|
2777
|
+
pathMapping.set(host, sandbox);
|
|
2778
|
+
}
|
|
2645
2779
|
const skillsMap = /* @__PURE__ */ new Map();
|
|
2646
|
-
for (const
|
|
2647
|
-
const discovered = discoverSkillsInDirectory(
|
|
2780
|
+
for (const { host } of options.paths) {
|
|
2781
|
+
const discovered = discoverSkillsInDirectory(host);
|
|
2648
2782
|
for (const skill of discovered) {
|
|
2649
2783
|
skillsMap.set(skill.name, skill);
|
|
2650
2784
|
}
|
|
@@ -2659,14 +2793,26 @@ function skills(options) {
|
|
|
2659
2793
|
(s) => !options.exclude.includes(s.name)
|
|
2660
2794
|
);
|
|
2661
2795
|
}
|
|
2662
|
-
const skillFragments = filteredSkills.map((skill) =>
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2796
|
+
const skillFragments = filteredSkills.map((skill) => {
|
|
2797
|
+
const originalPath = skill.skillMdPath;
|
|
2798
|
+
let sandboxPath = originalPath;
|
|
2799
|
+
for (const [host, sandbox] of pathMapping) {
|
|
2800
|
+
if (originalPath.startsWith(host)) {
|
|
2801
|
+
const relativePath = originalPath.slice(host.length);
|
|
2802
|
+
sandboxPath = sandbox + relativePath;
|
|
2803
|
+
break;
|
|
2804
|
+
}
|
|
2668
2805
|
}
|
|
2669
|
-
|
|
2806
|
+
return {
|
|
2807
|
+
name: "skill",
|
|
2808
|
+
data: {
|
|
2809
|
+
name: skill.name,
|
|
2810
|
+
path: sandboxPath,
|
|
2811
|
+
description: skill.description
|
|
2812
|
+
},
|
|
2813
|
+
metadata: { originalPath }
|
|
2814
|
+
};
|
|
2815
|
+
});
|
|
2670
2816
|
return {
|
|
2671
2817
|
name: "available_skills",
|
|
2672
2818
|
data: [
|
|
@@ -2675,7 +2821,11 @@ function skills(options) {
|
|
|
2675
2821
|
data: SKILLS_INSTRUCTIONS
|
|
2676
2822
|
},
|
|
2677
2823
|
...skillFragments
|
|
2678
|
-
]
|
|
2824
|
+
],
|
|
2825
|
+
metadata: {
|
|
2826
|
+
paths: options.paths
|
|
2827
|
+
// Store original path mappings for getSkillMounts()
|
|
2828
|
+
}
|
|
2679
2829
|
};
|
|
2680
2830
|
}
|
|
2681
2831
|
var SKILLS_INSTRUCTIONS = `When a user's request matches one of the skills listed below, read the skill's SKILL.md file to get detailed instructions before proceeding. Skills provide specialized knowledge and workflows for specific tasks.
|
|
@@ -2870,12 +3020,20 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
2870
3020
|
}
|
|
2871
3021
|
async listChats(options) {
|
|
2872
3022
|
const params = [];
|
|
2873
|
-
|
|
3023
|
+
const whereClauses = [];
|
|
2874
3024
|
let limitClause = "";
|
|
2875
3025
|
if (options?.userId) {
|
|
2876
|
-
|
|
3026
|
+
whereClauses.push("c.userId = ?");
|
|
2877
3027
|
params.push(options.userId);
|
|
2878
3028
|
}
|
|
3029
|
+
if (options?.metadata) {
|
|
3030
|
+
whereClauses.push(`json_extract(c.metadata, '$.' || ?) = ?`);
|
|
3031
|
+
params.push(options.metadata.key);
|
|
3032
|
+
params.push(
|
|
3033
|
+
typeof options.metadata.value === "boolean" ? options.metadata.value ? 1 : 0 : options.metadata.value
|
|
3034
|
+
);
|
|
3035
|
+
}
|
|
3036
|
+
const whereClause = whereClauses.length > 0 ? `WHERE ${whereClauses.join(" AND ")}` : "";
|
|
2879
3037
|
if (options?.limit !== void 0) {
|
|
2880
3038
|
limitClause = " LIMIT ?";
|
|
2881
3039
|
params.push(options.limit);
|
|
@@ -2889,6 +3047,7 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
2889
3047
|
c.id,
|
|
2890
3048
|
c.userId,
|
|
2891
3049
|
c.title,
|
|
3050
|
+
c.metadata,
|
|
2892
3051
|
c.createdAt,
|
|
2893
3052
|
c.updatedAt,
|
|
2894
3053
|
COUNT(DISTINCT m.id) as messageCount,
|
|
@@ -2904,6 +3063,7 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
2904
3063
|
id: row.id,
|
|
2905
3064
|
userId: row.userId,
|
|
2906
3065
|
title: row.title ?? void 0,
|
|
3066
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : void 0,
|
|
2907
3067
|
messageCount: row.messageCount,
|
|
2908
3068
|
branchCount: row.branchCount,
|
|
2909
3069
|
createdAt: row.createdAt,
|
|
@@ -2935,9 +3095,16 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
2935
3095
|
async addMessage(message2) {
|
|
2936
3096
|
this.#db.prepare(
|
|
2937
3097
|
`INSERT INTO messages (id, chatId, parentId, name, type, data, createdAt)
|
|
2938
|
-
VALUES (
|
|
3098
|
+
VALUES (
|
|
3099
|
+
?1,
|
|
3100
|
+
?2,
|
|
3101
|
+
CASE WHEN ?3 = ?1 THEN (SELECT parentId FROM messages WHERE id = ?1) ELSE ?3 END,
|
|
3102
|
+
?4,
|
|
3103
|
+
?5,
|
|
3104
|
+
?6,
|
|
3105
|
+
?7
|
|
3106
|
+
)
|
|
2939
3107
|
ON CONFLICT(id) DO UPDATE SET
|
|
2940
|
-
parentId = excluded.parentId,
|
|
2941
3108
|
name = excluded.name,
|
|
2942
3109
|
type = excluded.type,
|
|
2943
3110
|
data = excluded.data`
|
|
@@ -3487,13 +3654,9 @@ var Agent = class _Agent {
|
|
|
3487
3654
|
writer.write({ type: "finish" });
|
|
3488
3655
|
return;
|
|
3489
3656
|
}
|
|
3490
|
-
writer
|
|
3491
|
-
type: "text-delta",
|
|
3492
|
-
id: generateId2(),
|
|
3493
|
-
delta: ` ${failureFeedback}`
|
|
3494
|
-
});
|
|
3657
|
+
writeText(writer, failureFeedback);
|
|
3495
3658
|
const selfCorrectionText = accumulatedText + " " + failureFeedback;
|
|
3496
|
-
context.set(
|
|
3659
|
+
context.set(lastAssistantMessage(selfCorrectionText));
|
|
3497
3660
|
await context.save();
|
|
3498
3661
|
currentResult = await this.#createRawStream(
|
|
3499
3662
|
contextVariables,
|
|
@@ -3598,6 +3761,22 @@ var repairToolCall = async ({
|
|
|
3598
3761
|
});
|
|
3599
3762
|
return { ...toolCall, input: JSON.stringify(output) };
|
|
3600
3763
|
};
|
|
3764
|
+
function writeText(writer, text) {
|
|
3765
|
+
const feedbackPartId = generateId2();
|
|
3766
|
+
writer.write({
|
|
3767
|
+
id: feedbackPartId,
|
|
3768
|
+
type: "text-start"
|
|
3769
|
+
});
|
|
3770
|
+
writer.write({
|
|
3771
|
+
id: feedbackPartId,
|
|
3772
|
+
type: "text-delta",
|
|
3773
|
+
delta: ` ${text}`
|
|
3774
|
+
});
|
|
3775
|
+
writer.write({
|
|
3776
|
+
id: feedbackPartId,
|
|
3777
|
+
type: "text-end"
|
|
3778
|
+
});
|
|
3779
|
+
}
|
|
3601
3780
|
|
|
3602
3781
|
// packages/context/src/lib/render.ts
|
|
3603
3782
|
function render(tag, ...fragments) {
|
|
@@ -3622,6 +3801,7 @@ export {
|
|
|
3622
3801
|
DockerfileBuildError,
|
|
3623
3802
|
DockerfileStrategy,
|
|
3624
3803
|
InMemoryContextStore,
|
|
3804
|
+
LAZY_ID,
|
|
3625
3805
|
MarkdownRenderer,
|
|
3626
3806
|
ModelsRegistry,
|
|
3627
3807
|
MountPathError,
|
|
@@ -3658,7 +3838,9 @@ export {
|
|
|
3658
3838
|
isDockerfileOptions,
|
|
3659
3839
|
isFragment,
|
|
3660
3840
|
isFragmentObject,
|
|
3841
|
+
isLazyFragment,
|
|
3661
3842
|
isMessageFragment,
|
|
3843
|
+
lastAssistantMessage,
|
|
3662
3844
|
loadSkillMetadata,
|
|
3663
3845
|
message,
|
|
3664
3846
|
parseFrontmatter,
|