@deepagents/context 0.23.0 → 0.25.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 CHANGED
@@ -2379,7 +2379,7 @@ function policy(input) {
2379
2379
  }
2380
2380
 
2381
2381
  // packages/context/src/lib/fragments/message/user.ts
2382
- import { generateId as generateId4 } from "ai";
2382
+ import { generateId as generateId4, isTextUIPart } from "ai";
2383
2383
  var SYSTEM_REMINDER_OPEN_TAG = "<system-reminder>";
2384
2384
  var SYSTEM_REMINDER_CLOSE_TAG = "</system-reminder>";
2385
2385
  function getReminderRanges(metadata) {
@@ -2448,6 +2448,9 @@ function stripReminders(message2) {
2448
2448
  }
2449
2449
  return nextMessage;
2450
2450
  }
2451
+ function extractPlainText(message2) {
2452
+ return message2.parts.filter(isTextUIPart).map((part) => part.text).join(" ");
2453
+ }
2451
2454
  function isRecord(value) {
2452
2455
  return typeof value === "object" && value !== null && !Array.isArray(value);
2453
2456
  }
@@ -2512,7 +2515,9 @@ function applyPartReminder(message2, value) {
2512
2515
  };
2513
2516
  }
2514
2517
  function reminder(text, options) {
2515
- assertReminderText(text);
2518
+ if (typeof text === "string") {
2519
+ assertReminderText(text);
2520
+ }
2516
2521
  return {
2517
2522
  text,
2518
2523
  asPart: options?.asPart ?? false
@@ -2526,16 +2531,22 @@ function user(content, ...reminders) {
2526
2531
  } : { ...content, role: "user", parts: [...content.parts] };
2527
2532
  if (reminders.length > 0) {
2528
2533
  const addedReminders = [];
2534
+ const plainText = extractPlainText(message2);
2529
2535
  for (const item of reminders) {
2530
- assertReminderText(item.text);
2536
+ const resolvedText = typeof item.text === "function" ? item.text(plainText) : item.text;
2537
+ if (resolvedText.trim().length === 0) {
2538
+ continue;
2539
+ }
2531
2540
  addedReminders.push(
2532
- item.asPart ? applyPartReminder(message2, item.text) : applyInlineReminder(message2, item.text)
2541
+ item.asPart ? applyPartReminder(message2, resolvedText) : applyInlineReminder(message2, resolvedText)
2533
2542
  );
2534
2543
  }
2535
- const metadata = isRecord(message2.metadata) ? { ...message2.metadata } : {};
2536
- const existingReminders = Array.isArray(metadata.reminders) ? metadata.reminders : [];
2537
- metadata.reminders = [...existingReminders, ...addedReminders];
2538
- message2.metadata = metadata;
2544
+ if (addedReminders.length > 0) {
2545
+ const metadata = isRecord(message2.metadata) ? { ...message2.metadata } : {};
2546
+ const existingReminders = Array.isArray(metadata.reminders) ? metadata.reminders : [];
2547
+ metadata.reminders = [...existingReminders, ...addedReminders];
2548
+ message2.metadata = metadata;
2549
+ }
2539
2550
  }
2540
2551
  return {
2541
2552
  id: message2.id,
@@ -3471,6 +3482,46 @@ async function createContainerTool(options = {}) {
3471
3482
  };
3472
3483
  }
3473
3484
 
3485
+ // packages/context/src/lib/skills/classifier.ts
3486
+ import { Corpus } from "tiny-tfidf";
3487
+ var BM25SkillClassifier = class {
3488
+ #corpus;
3489
+ #skillsByName;
3490
+ constructor(skills2) {
3491
+ const names = skills2.map((s) => s.name);
3492
+ const texts = skills2.map((s) => `${s.name} ${s.description}`);
3493
+ this.#corpus = new Corpus(names, texts);
3494
+ this.#skillsByName = new Map(skills2.map((s) => [s.name, s]));
3495
+ }
3496
+ match(query, options) {
3497
+ const topN = options?.topN ?? 5;
3498
+ const threshold = options?.threshold ?? 0;
3499
+ const results = this.#corpus.getResultsForQuery(query);
3500
+ return results.filter(([, score]) => score > threshold).slice(0, topN).map(([name, score]) => ({
3501
+ skill: this.#skillsByName.get(name),
3502
+ score
3503
+ }));
3504
+ }
3505
+ };
3506
+ function isSkillClassifier(value) {
3507
+ return typeof value === "object" && value !== null && "match" in value && typeof value.match === "function";
3508
+ }
3509
+ function formatSkillReminder(matches) {
3510
+ const lines = matches.map(
3511
+ (m) => `- ${m.skill.name} (${m.score.toFixed(2)}): ${m.skill.description} [${m.skill.skillMdPath}]`
3512
+ );
3513
+ return `Relevant skills:
3514
+ ${lines.join("\n")}`;
3515
+ }
3516
+ function skillsReminder(skillsOrClassifier, options) {
3517
+ const classifier = isSkillClassifier(skillsOrClassifier) ? skillsOrClassifier : new BM25SkillClassifier(skillsOrClassifier);
3518
+ return reminder((content) => {
3519
+ const matches = classifier.match(content, options);
3520
+ if (matches.length === 0) return "";
3521
+ return formatSkillReminder(matches);
3522
+ });
3523
+ }
3524
+
3474
3525
  // packages/context/src/lib/skills/fragments.ts
3475
3526
  import dedent from "dedent";
3476
3527
 
@@ -5881,10 +5932,13 @@ function clampFloat(value, min, max) {
5881
5932
  import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
5882
5933
 
5883
5934
  // packages/context/src/lib/stream/ddl.stream.sqlite.sql
5884
- var ddl_stream_sqlite_default = "PRAGMA journal_mode = WAL;\nPRAGMA synchronous = NORMAL;\nPRAGMA foreign_keys = ON;\n\nCREATE TABLE IF NOT EXISTS streams (\n id TEXT PRIMARY KEY,\n status TEXT NOT NULL DEFAULT 'queued'\n CHECK(status IN ('queued','running','completed','failed','cancelled')),\n createdAt INTEGER NOT NULL,\n startedAt INTEGER,\n finishedAt INTEGER,\n cancelRequestedAt INTEGER,\n error TEXT\n);\n\nCREATE TABLE IF NOT EXISTS stream_chunks (\n streamId TEXT NOT NULL,\n seq INTEGER NOT NULL,\n data TEXT NOT NULL,\n createdAt INTEGER NOT NULL,\n PRIMARY KEY (streamId, seq),\n FOREIGN KEY (streamId) REFERENCES streams(id) ON DELETE CASCADE\n);\n";
5935
+ var ddl_stream_sqlite_default = "PRAGMA journal_mode = WAL;\nPRAGMA synchronous = NORMAL;\nPRAGMA foreign_keys = ON;\n\nCREATE TABLE IF NOT EXISTS streams (\n id TEXT PRIMARY KEY,\n status TEXT NOT NULL DEFAULT 'queued'\n CHECK(status IN ('queued','running','completed','failed','cancelled')),\n createdAt INTEGER NOT NULL,\n startedAt INTEGER,\n finishedAt INTEGER,\n cancelRequestedAt INTEGER,\n error TEXT\n);\n\nCREATE TABLE IF NOT EXISTS stream_chunks (\n streamId TEXT NOT NULL,\n seq INTEGER NOT NULL,\n data TEXT NOT NULL,\n createdAt INTEGER NOT NULL,\n PRIMARY KEY (streamId, seq),\n FOREIGN KEY (streamId) REFERENCES streams(id) ON DELETE CASCADE\n);\n\n-- Supports ordered listing across all streams.\nCREATE INDEX IF NOT EXISTS idx_streams_created_at_id\n ON streams(createdAt, id);\n\n-- Supports status-filtered ordered listing (e.g. running streams).\nCREATE INDEX IF NOT EXISTS idx_streams_status_created_at_id\n ON streams(status, createdAt, id);\n";
5885
5936
 
5886
5937
  // packages/context/src/lib/stream/stream-store.ts
5887
5938
  var StreamStore = class {
5939
+ async listRunningStreamIds() {
5940
+ return this.listStreamIds({ status: "running" });
5941
+ }
5888
5942
  };
5889
5943
 
5890
5944
  // packages/context/src/lib/stream/sqlite.stream-store.ts
@@ -5983,6 +6037,17 @@ var SqliteStreamStore = class extends StreamStore {
5983
6037
  );
5984
6038
  return row?.status;
5985
6039
  }
6040
+ async listStreamIds(options) {
6041
+ let sql = "SELECT id FROM streams";
6042
+ const params = [];
6043
+ if (options?.status) {
6044
+ sql += " WHERE status = ?";
6045
+ params.push(options.status);
6046
+ }
6047
+ sql += " ORDER BY createdAt ASC, id ASC";
6048
+ const rows = this.#stmt(sql).all(...params);
6049
+ return rows.map((row) => row.id);
6050
+ }
5986
6051
  async updateStreamStatus(streamId, status, options) {
5987
6052
  const now = Date.now();
5988
6053
  switch (status) {
@@ -6140,6 +6205,9 @@ var StreamManager = class {
6140
6205
  async cancel(streamId) {
6141
6206
  await this.#store.updateStreamStatus(streamId, "cancelled");
6142
6207
  }
6208
+ async listStreamIds(options) {
6209
+ return this.#store.listStreamIds(options);
6210
+ }
6143
6211
  async persist(stream, streamId, options) {
6144
6212
  const existing = await this.#store.getStream(streamId);
6145
6213
  if (existing && isTerminal(existing.status)) {
@@ -6176,6 +6244,12 @@ var StreamManager = class {
6176
6244
  streamId,
6177
6245
  latencyMs
6178
6246
  });
6247
+ if (options?.onCancelDetected) {
6248
+ try {
6249
+ await options.onCancelDetected({ streamId, latencyMs });
6250
+ } catch {
6251
+ }
6252
+ }
6179
6253
  ac.abort();
6180
6254
  break;
6181
6255
  }
@@ -6464,6 +6538,7 @@ function visualizeGraph(data) {
6464
6538
  return lines.join("\n");
6465
6539
  }
6466
6540
  export {
6541
+ BM25SkillClassifier,
6467
6542
  BinaryInstallError,
6468
6543
  ComposeStartError,
6469
6544
  ComposeStrategy,
@@ -6547,6 +6622,7 @@ export {
6547
6622
  role,
6548
6623
  runGuardrailChain,
6549
6624
  skills,
6625
+ skillsReminder,
6550
6626
  soul,
6551
6627
  stop,
6552
6628
  stripReminders,