@agent-native/core 0.52.0 → 0.54.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/README.md +41 -95
- package/blueprints/action/crud.md +98 -0
- package/blueprints/channel/discord.md +74 -0
- package/blueprints/provider/stripe.md +87 -0
- package/blueprints/sandbox/docker.md +78 -0
- package/dist/action.d.ts +64 -1
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js +73 -2
- package/dist/action.js.map +1 -1
- package/dist/agent/index.d.ts +1 -0
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +1 -0
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/observational-memory/compactor.d.ts +43 -0
- package/dist/agent/observational-memory/compactor.d.ts.map +1 -0
- package/dist/agent/observational-memory/compactor.js +50 -0
- package/dist/agent/observational-memory/compactor.js.map +1 -0
- package/dist/agent/observational-memory/config.d.ts +37 -0
- package/dist/agent/observational-memory/config.d.ts.map +1 -0
- package/dist/agent/observational-memory/config.js +48 -0
- package/dist/agent/observational-memory/config.js.map +1 -0
- package/dist/agent/observational-memory/index.d.ts +26 -0
- package/dist/agent/observational-memory/index.d.ts.map +1 -0
- package/dist/agent/observational-memory/index.js +25 -0
- package/dist/agent/observational-memory/index.js.map +1 -0
- package/dist/agent/observational-memory/internal-run.d.ts +37 -0
- package/dist/agent/observational-memory/internal-run.d.ts.map +1 -0
- package/dist/agent/observational-memory/internal-run.js +59 -0
- package/dist/agent/observational-memory/internal-run.js.map +1 -0
- package/dist/agent/observational-memory/message-text.d.ts +13 -0
- package/dist/agent/observational-memory/message-text.d.ts.map +1 -0
- package/dist/agent/observational-memory/message-text.js +46 -0
- package/dist/agent/observational-memory/message-text.js.map +1 -0
- package/dist/agent/observational-memory/migrations.d.ts +13 -0
- package/dist/agent/observational-memory/migrations.d.ts.map +1 -0
- package/dist/agent/observational-memory/migrations.js +43 -0
- package/dist/agent/observational-memory/migrations.js.map +1 -0
- package/dist/agent/observational-memory/observer.d.ts +37 -0
- package/dist/agent/observational-memory/observer.d.ts.map +1 -0
- package/dist/agent/observational-memory/observer.js +82 -0
- package/dist/agent/observational-memory/observer.js.map +1 -0
- package/dist/agent/observational-memory/plugin.d.ts +16 -0
- package/dist/agent/observational-memory/plugin.d.ts.map +1 -0
- package/dist/agent/observational-memory/plugin.js +26 -0
- package/dist/agent/observational-memory/plugin.js.map +1 -0
- package/dist/agent/observational-memory/prompts.d.ts +27 -0
- package/dist/agent/observational-memory/prompts.d.ts.map +1 -0
- package/dist/agent/observational-memory/prompts.js +42 -0
- package/dist/agent/observational-memory/prompts.js.map +1 -0
- package/dist/agent/observational-memory/read.d.ts +45 -0
- package/dist/agent/observational-memory/read.d.ts.map +1 -0
- package/dist/agent/observational-memory/read.js +97 -0
- package/dist/agent/observational-memory/read.js.map +1 -0
- package/dist/agent/observational-memory/reflector.d.ts +31 -0
- package/dist/agent/observational-memory/reflector.d.ts.map +1 -0
- package/dist/agent/observational-memory/reflector.js +76 -0
- package/dist/agent/observational-memory/reflector.js.map +1 -0
- package/dist/agent/observational-memory/schema.d.ts +267 -0
- package/dist/agent/observational-memory/schema.d.ts.map +1 -0
- package/dist/agent/observational-memory/schema.js +48 -0
- package/dist/agent/observational-memory/schema.js.map +1 -0
- package/dist/agent/observational-memory/store.d.ts +52 -0
- package/dist/agent/observational-memory/store.d.ts.map +1 -0
- package/dist/agent/observational-memory/store.js +197 -0
- package/dist/agent/observational-memory/store.js.map +1 -0
- package/dist/agent/observational-memory/types.d.ts +61 -0
- package/dist/agent/observational-memory/types.d.ts.map +1 -0
- package/dist/agent/observational-memory/types.js +9 -0
- package/dist/agent/observational-memory/types.js.map +1 -0
- package/dist/agent/processors.d.ts +146 -0
- package/dist/agent/processors.d.ts.map +1 -0
- package/dist/agent/processors.js +122 -0
- package/dist/agent/processors.js.map +1 -0
- package/dist/agent/production-agent.d.ts +25 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +341 -1
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
- package/dist/agent/run-loop-with-resume.js +48 -0
- package/dist/agent/run-loop-with-resume.js.map +1 -1
- package/dist/agent/run-store.d.ts +17 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +55 -0
- package/dist/agent/run-store.js.map +1 -1
- package/dist/agent/runtime-context.d.ts +30 -0
- package/dist/agent/runtime-context.d.ts.map +1 -1
- package/dist/agent/runtime-context.js +54 -1
- package/dist/agent/runtime-context.js.map +1 -1
- package/dist/agent/tool-call-journal.d.ts +99 -0
- package/dist/agent/tool-call-journal.d.ts.map +1 -0
- package/dist/agent/tool-call-journal.js +212 -0
- package/dist/agent/tool-call-journal.js.map +1 -0
- package/dist/agent/types.d.ts +35 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/cli/add.d.ts +109 -0
- package/dist/cli/add.d.ts.map +1 -0
- package/dist/cli/add.js +352 -0
- package/dist/cli/add.js.map +1 -0
- package/dist/cli/connect.d.ts +2 -2
- package/dist/cli/connect.d.ts.map +1 -1
- package/dist/cli/connect.js +92 -24
- package/dist/cli/connect.js.map +1 -1
- package/dist/cli/eval.d.ts +17 -0
- package/dist/cli/eval.d.ts.map +1 -0
- package/dist/cli/eval.js +121 -0
- package/dist/cli/eval.js.map +1 -0
- package/dist/cli/index.js +44 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp.d.ts.map +1 -1
- package/dist/cli/mcp.js +11 -5
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli/plan-local.d.ts +66 -5
- package/dist/cli/plan-local.d.ts.map +1 -1
- package/dist/cli/plan-local.js +622 -21
- package/dist/cli/plan-local.js.map +1 -1
- package/dist/cli/skills.d.ts +2 -2
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +108 -62
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +118 -92
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +16 -0
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts +20 -1
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +32 -7
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts +13 -0
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +21 -0
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/coding-tools/run-code.d.ts.map +1 -1
- package/dist/coding-tools/run-code.js +18 -2
- package/dist/coding-tools/run-code.js.map +1 -1
- package/dist/db/client.d.ts +4 -2
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +6 -4
- package/dist/db/client.js.map +1 -1
- package/dist/deploy/route-discovery.d.ts.map +1 -1
- package/dist/deploy/route-discovery.js +1 -0
- package/dist/deploy/route-discovery.js.map +1 -1
- package/dist/eval/agent-runner.d.ts +63 -0
- package/dist/eval/agent-runner.d.ts.map +1 -0
- package/dist/eval/agent-runner.js +142 -0
- package/dist/eval/agent-runner.js.map +1 -0
- package/dist/eval/define-eval.d.ts +29 -0
- package/dist/eval/define-eval.d.ts.map +1 -0
- package/dist/eval/define-eval.js +43 -0
- package/dist/eval/define-eval.js.map +1 -0
- package/dist/eval/index.d.ts +18 -0
- package/dist/eval/index.d.ts.map +1 -0
- package/dist/eval/index.js +17 -0
- package/dist/eval/index.js.map +1 -0
- package/dist/eval/report.d.ts +8 -0
- package/dist/eval/report.d.ts.map +1 -0
- package/dist/eval/report.js +44 -0
- package/dist/eval/report.js.map +1 -0
- package/dist/eval/runner.d.ts +67 -0
- package/dist/eval/runner.d.ts.map +1 -0
- package/dist/eval/runner.js +256 -0
- package/dist/eval/runner.js.map +1 -0
- package/dist/eval/scorer.d.ts +83 -0
- package/dist/eval/scorer.d.ts.map +1 -0
- package/dist/eval/scorer.js +195 -0
- package/dist/eval/scorer.js.map +1 -0
- package/dist/eval/types.d.ts +162 -0
- package/dist/eval/types.d.ts.map +1 -0
- package/dist/eval/types.js +20 -0
- package/dist/eval/types.js.map +1 -0
- package/dist/extensions/fetch-tool.d.ts.map +1 -1
- package/dist/extensions/fetch-tool.js +80 -15
- package/dist/extensions/fetch-tool.js.map +1 -1
- package/dist/extensions/web-content.d.ts +61 -0
- package/dist/extensions/web-content.d.ts.map +1 -0
- package/dist/extensions/web-content.js +468 -0
- package/dist/extensions/web-content.js.map +1 -0
- package/dist/extensions/web-search-tool.js +3 -3
- package/dist/extensions/web-search-tool.js.map +1 -1
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js +4 -1
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/observability/traces.d.ts.map +1 -1
- package/dist/observability/traces.js +100 -1
- package/dist/observability/traces.js.map +1 -1
- package/dist/observability/tracing.d.ts +73 -0
- package/dist/observability/tracing.d.ts.map +1 -0
- package/dist/observability/tracing.js +126 -0
- package/dist/observability/tracing.js.map +1 -0
- package/dist/onboarding/default-steps.d.ts.map +1 -1
- package/dist/onboarding/default-steps.js +4 -1
- package/dist/onboarding/default-steps.js.map +1 -1
- package/dist/provider-api/actions/query-staged-dataset.d.ts +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +80 -0
- package/dist/provider-api/corpus-jobs.d.ts.map +1 -1
- package/dist/provider-api/corpus-jobs.js +219 -22
- package/dist/provider-api/corpus-jobs.js.map +1 -1
- package/dist/provider-api/index.d.ts +24 -32
- package/dist/provider-api/index.d.ts.map +1 -1
- package/dist/provider-api/index.js +28 -1
- package/dist/provider-api/index.js.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js +10 -3
- package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +4 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +9 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +119 -111
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-teams.d.ts +62 -0
- package/dist/server/agent-teams.d.ts.map +1 -1
- package/dist/server/agent-teams.js +99 -2
- package/dist/server/agent-teams.js.map +1 -1
- package/dist/server/better-auth-instance.d.ts +7 -0
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +90 -0
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +7 -4
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +2 -0
- package/dist/server/credential-provider.js.map +1 -1
- package/dist/server/deep-link.d.ts +7 -0
- package/dist/server/deep-link.d.ts.map +1 -1
- package/dist/server/deep-link.js +13 -2
- package/dist/server/deep-link.js.map +1 -1
- package/dist/server/framework-request-handler.d.ts.map +1 -1
- package/dist/server/framework-request-handler.js +33 -1
- package/dist/server/framework-request-handler.js.map +1 -1
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2 -1
- package/dist/server/index.js.map +1 -1
- package/dist/templates/default/.agents/skills/actions/SKILL.md +52 -1
- package/dist/templates/default/.agents/skills/security/SKILL.md +22 -0
- package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +52 -1
- package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +16 -4
- package/dist/templates/workspace-core/.agents/skills/harness-agents/SKILL.md +20 -0
- package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +31 -0
- package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +22 -0
- package/docs/content/actions.md +50 -0
- package/docs/content/agent-teams.md +32 -0
- package/docs/content/blueprint-installer.md +73 -0
- package/docs/content/durable-resume.md +49 -0
- package/docs/content/evals.md +141 -0
- package/docs/content/external-agents.md +2 -2
- package/docs/content/human-approval.md +101 -0
- package/docs/content/observability.md +21 -0
- package/docs/content/observational-memory.md +63 -0
- package/docs/content/plan-plugin.md +5 -0
- package/docs/content/pr-visual-recap.md +9 -5
- package/docs/content/processors.md +99 -0
- package/docs/content/sandbox-adapters.md +134 -0
- package/docs/content/template-plan.md +97 -21
- package/package.json +10 -1
- package/src/templates/default/.agents/skills/actions/SKILL.md +52 -1
- package/src/templates/default/.agents/skills/security/SKILL.md +22 -0
- package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +52 -1
- package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +16 -4
- package/src/templates/workspace-core/.agents/skills/harness-agents/SKILL.md +20 -0
- package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +31 -0
- package/src/templates/workspace-core/.agents/skills/security/SKILL.md +22 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { table, text, integer, ownableColumns } from "../../db/schema.js";
|
|
2
|
+
/**
|
|
3
|
+
* Observational Memory (OM) entries.
|
|
4
|
+
*
|
|
5
|
+
* A long-running agent thread is compacted in the background into a dated,
|
|
6
|
+
* three-tier context so it costs far fewer tokens and stays prompt-cache
|
|
7
|
+
* stable:
|
|
8
|
+
*
|
|
9
|
+
* recent raw messages → dense "observations" → higher-level "reflections"
|
|
10
|
+
*
|
|
11
|
+
* Each row is ONE compaction artifact for a thread:
|
|
12
|
+
*
|
|
13
|
+
* - `tier = "observation"` — a dense, dated digest of a contiguous range of
|
|
14
|
+
* thread messages (task status, names, dates, decisions preserved). Produced
|
|
15
|
+
* by the Observer once a thread's unobserved messages exceed a token
|
|
16
|
+
* threshold.
|
|
17
|
+
* - `tier = "reflection"` — a higher-level condensation OVER observations,
|
|
18
|
+
* produced by the Reflector once the observation log itself grows past its
|
|
19
|
+
* own threshold.
|
|
20
|
+
*
|
|
21
|
+
* The table is ownable (scoped reads/writes via `accessFilter`/`assertAccess`
|
|
22
|
+
* per the `security` skill) and dialect-agnostic (Drizzle helpers from
|
|
23
|
+
* `db/schema`, never raw SQLite types). The companion migrations live in
|
|
24
|
+
* `./migrations.ts` and are additive-only.
|
|
25
|
+
*/
|
|
26
|
+
export const observationalMemory = table("observational_memory", {
|
|
27
|
+
id: text("id").primaryKey(),
|
|
28
|
+
threadId: text("thread_id").notNull(),
|
|
29
|
+
/** Which tier this entry belongs to. */
|
|
30
|
+
tier: text("tier", { enum: ["observation", "reflection"] }).notNull(),
|
|
31
|
+
/** The dated, compacted text content of this entry. */
|
|
32
|
+
text: text("text").notNull(),
|
|
33
|
+
/** Estimated token count of `text` (used for the reflection threshold). */
|
|
34
|
+
tokenEstimate: integer("token_estimate").notNull().default(0),
|
|
35
|
+
/**
|
|
36
|
+
* Inclusive index range of the source thread messages this entry summarizes.
|
|
37
|
+
* For observations these are indices into the flattened thread-message array;
|
|
38
|
+
* for reflections they span the observation indices that were folded.
|
|
39
|
+
*/
|
|
40
|
+
sourceStartIndex: integer("source_start_index"),
|
|
41
|
+
sourceEndIndex: integer("source_end_index"),
|
|
42
|
+
/** How many source messages/observations this entry covers. */
|
|
43
|
+
sourceMessageCount: integer("source_message_count").notNull().default(0),
|
|
44
|
+
createdAt: integer("created_at").notNull(),
|
|
45
|
+
updatedAt: integer("updated_at").notNull(),
|
|
46
|
+
...ownableColumns(),
|
|
47
|
+
});
|
|
48
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/agent/observational-memory/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,CAAC,sBAAsB,EAAE;IAC/D,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE;IAC3B,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,EAAE;IACrC,wCAAwC;IACxC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,aAAa,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE;IACrE,uDAAuD;IACvD,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE;IAC5B,2EAA2E;IAC3E,aAAa,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7D;;;;OAIG;IACH,gBAAgB,EAAE,OAAO,CAAC,oBAAoB,CAAC;IAC/C,cAAc,EAAE,OAAO,CAAC,kBAAkB,CAAC;IAC3C,+DAA+D;IAC/D,kBAAkB,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACxE,SAAS,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;IAC1C,SAAS,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;IAC1C,GAAG,cAAc,EAAE;CACpB,CAAC,CAAC","sourcesContent":["import { table, text, integer, ownableColumns } from \"../../db/schema.js\";\n\n/**\n * Observational Memory (OM) entries.\n *\n * A long-running agent thread is compacted in the background into a dated,\n * three-tier context so it costs far fewer tokens and stays prompt-cache\n * stable:\n *\n * recent raw messages → dense \"observations\" → higher-level \"reflections\"\n *\n * Each row is ONE compaction artifact for a thread:\n *\n * - `tier = \"observation\"` — a dense, dated digest of a contiguous range of\n * thread messages (task status, names, dates, decisions preserved). Produced\n * by the Observer once a thread's unobserved messages exceed a token\n * threshold.\n * - `tier = \"reflection\"` — a higher-level condensation OVER observations,\n * produced by the Reflector once the observation log itself grows past its\n * own threshold.\n *\n * The table is ownable (scoped reads/writes via `accessFilter`/`assertAccess`\n * per the `security` skill) and dialect-agnostic (Drizzle helpers from\n * `db/schema`, never raw SQLite types). The companion migrations live in\n * `./migrations.ts` and are additive-only.\n */\nexport const observationalMemory = table(\"observational_memory\", {\n id: text(\"id\").primaryKey(),\n threadId: text(\"thread_id\").notNull(),\n /** Which tier this entry belongs to. */\n tier: text(\"tier\", { enum: [\"observation\", \"reflection\"] }).notNull(),\n /** The dated, compacted text content of this entry. */\n text: text(\"text\").notNull(),\n /** Estimated token count of `text` (used for the reflection threshold). */\n tokenEstimate: integer(\"token_estimate\").notNull().default(0),\n /**\n * Inclusive index range of the source thread messages this entry summarizes.\n * For observations these are indices into the flattened thread-message array;\n * for reflections they span the observation indices that were folded.\n */\n sourceStartIndex: integer(\"source_start_index\"),\n sourceEndIndex: integer(\"source_end_index\"),\n /** How many source messages/observations this entry covers. */\n sourceMessageCount: integer(\"source_message_count\").notNull().default(0),\n createdAt: integer(\"created_at\").notNull(),\n updatedAt: integer(\"updated_at\").notNull(),\n ...ownableColumns(),\n});\n"]}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persistence for Observational Memory entries.
|
|
3
|
+
*
|
|
4
|
+
* Owner-scoped throughout: every read and write takes an `ownerEmail` and the
|
|
5
|
+
* SQL always filters by it, so the ownable table is never read or written
|
|
6
|
+
* cross-owner (per the `security` skill). Dialect-agnostic — only `getDbExec()`
|
|
7
|
+
* and parameterized SQL, never raw SQLite/Postgres types or string interpolation
|
|
8
|
+
* of user data.
|
|
9
|
+
*
|
|
10
|
+
* `ensureTable()` lazily creates the table on first use (the same belt-and-
|
|
11
|
+
* suspenders pattern as `chat-threads/store.ts`), so OM works in tests and at
|
|
12
|
+
* runtime even before the migration plugin is registered.
|
|
13
|
+
*/
|
|
14
|
+
import type { ObservationalMemoryEntry, ObservationalMemoryOwner, ObservationalMemoryTier } from "./types.js";
|
|
15
|
+
/** Reset the cached ensureTable promise — test-only seam. */
|
|
16
|
+
export declare function __resetObservationalMemoryTableCache(): void;
|
|
17
|
+
export interface InsertObservationalMemoryInput extends ObservationalMemoryOwner {
|
|
18
|
+
threadId: string;
|
|
19
|
+
tier: ObservationalMemoryTier;
|
|
20
|
+
text: string;
|
|
21
|
+
tokenEstimate: number;
|
|
22
|
+
sourceStartIndex?: number | null;
|
|
23
|
+
sourceEndIndex?: number | null;
|
|
24
|
+
sourceMessageCount?: number;
|
|
25
|
+
visibility?: "private" | "org" | "public";
|
|
26
|
+
}
|
|
27
|
+
/** Insert one OM entry, returning the persisted row. */
|
|
28
|
+
export declare function insertObservationalMemory(input: InsertObservationalMemoryInput): Promise<ObservationalMemoryEntry>;
|
|
29
|
+
export interface ListObservationalMemoryOptions extends ObservationalMemoryOwner {
|
|
30
|
+
threadId: string;
|
|
31
|
+
/** When set, only entries of this tier are returned. */
|
|
32
|
+
tier?: ObservationalMemoryTier;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* List a thread's OM entries for an owner, oldest → newest. Always
|
|
36
|
+
* owner-scoped; `org_id` is matched too when supplied so org-visible rows
|
|
37
|
+
* don't leak across orgs.
|
|
38
|
+
*/
|
|
39
|
+
export declare function listObservationalMemory(options: ListObservationalMemoryOptions): Promise<ObservationalMemoryEntry[]>;
|
|
40
|
+
/**
|
|
41
|
+
* The highest source-message index already folded into an observation for this
|
|
42
|
+
* thread/owner, or -1 if none. The Observer uses this to know which messages
|
|
43
|
+
* are still unobserved.
|
|
44
|
+
*/
|
|
45
|
+
export declare function getObservedThroughIndex(options: ObservationalMemoryOwner & {
|
|
46
|
+
threadId: string;
|
|
47
|
+
}): Promise<number>;
|
|
48
|
+
/** Sum the token estimates of a thread's observation entries for an owner. */
|
|
49
|
+
export declare function getObservationLogTokens(options: ObservationalMemoryOwner & {
|
|
50
|
+
threadId: string;
|
|
51
|
+
}): Promise<number>;
|
|
52
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/agent/observational-memory/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EACV,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,EACxB,MAAM,YAAY,CAAC;AA0CpB,6DAA6D;AAC7D,wBAAgB,oCAAoC,IAAI,IAAI,CAE3D;AAqDD,MAAM,WAAW,8BAA+B,SAAQ,wBAAwB;IAC9E,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,uBAAuB,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,QAAQ,CAAC;CAC3C;AAED,wDAAwD;AACxD,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,8BAA8B,GACpC,OAAO,CAAC,wBAAwB,CAAC,CAyCnC;AAED,MAAM,WAAW,8BAA+B,SAAQ,wBAAwB;IAC9E,QAAQ,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,IAAI,CAAC,EAAE,uBAAuB,CAAC;CAChC;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,8BAA8B,GACtC,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAiBrC;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,wBAAwB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GACvD,OAAO,CAAC,MAAM,CAAC,CAejB;AAED,8EAA8E;AAC9E,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,wBAAwB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GACvD,OAAO,CAAC,MAAM,CAAC,CAcjB"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persistence for Observational Memory entries.
|
|
3
|
+
*
|
|
4
|
+
* Owner-scoped throughout: every read and write takes an `ownerEmail` and the
|
|
5
|
+
* SQL always filters by it, so the ownable table is never read or written
|
|
6
|
+
* cross-owner (per the `security` skill). Dialect-agnostic — only `getDbExec()`
|
|
7
|
+
* and parameterized SQL, never raw SQLite/Postgres types or string interpolation
|
|
8
|
+
* of user data.
|
|
9
|
+
*
|
|
10
|
+
* `ensureTable()` lazily creates the table on first use (the same belt-and-
|
|
11
|
+
* suspenders pattern as `chat-threads/store.ts`), so OM works in tests and at
|
|
12
|
+
* runtime even before the migration plugin is registered.
|
|
13
|
+
*/
|
|
14
|
+
import { getDbExec } from "../../db/client.js";
|
|
15
|
+
import { isPostgres } from "../../db/client.js";
|
|
16
|
+
let tableReady = null;
|
|
17
|
+
async function ensureTable() {
|
|
18
|
+
if (tableReady)
|
|
19
|
+
return tableReady;
|
|
20
|
+
tableReady = (async () => {
|
|
21
|
+
const client = getDbExec();
|
|
22
|
+
const intType = isPostgres() ? "BIGINT" : "INTEGER";
|
|
23
|
+
await client.execute(`CREATE TABLE IF NOT EXISTS observational_memory (
|
|
24
|
+
id TEXT PRIMARY KEY,
|
|
25
|
+
thread_id TEXT NOT NULL,
|
|
26
|
+
tier TEXT NOT NULL,
|
|
27
|
+
text TEXT NOT NULL,
|
|
28
|
+
token_estimate ${intType} NOT NULL DEFAULT 0,
|
|
29
|
+
source_start_index ${intType},
|
|
30
|
+
source_end_index ${intType},
|
|
31
|
+
source_message_count ${intType} NOT NULL DEFAULT 0,
|
|
32
|
+
created_at ${intType} NOT NULL,
|
|
33
|
+
updated_at ${intType} NOT NULL,
|
|
34
|
+
owner_email TEXT NOT NULL,
|
|
35
|
+
org_id TEXT,
|
|
36
|
+
visibility TEXT NOT NULL DEFAULT 'private'
|
|
37
|
+
)`);
|
|
38
|
+
await client.execute(`CREATE INDEX IF NOT EXISTS observational_memory_thread_tier_idx
|
|
39
|
+
ON observational_memory(thread_id, tier, created_at)`);
|
|
40
|
+
await client.execute(`CREATE INDEX IF NOT EXISTS observational_memory_thread_owner_idx
|
|
41
|
+
ON observational_memory(thread_id, owner_email)`);
|
|
42
|
+
})().catch((err) => {
|
|
43
|
+
// Reset so a transient failure (e.g. SQLITE_BUSY on HMR) can retry.
|
|
44
|
+
tableReady = null;
|
|
45
|
+
throw err;
|
|
46
|
+
});
|
|
47
|
+
return tableReady;
|
|
48
|
+
}
|
|
49
|
+
/** Reset the cached ensureTable promise — test-only seam. */
|
|
50
|
+
export function __resetObservationalMemoryTableCache() {
|
|
51
|
+
tableReady = null;
|
|
52
|
+
}
|
|
53
|
+
function entryId() {
|
|
54
|
+
return `om-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
55
|
+
}
|
|
56
|
+
function numOrNull(value) {
|
|
57
|
+
if (value === null || value === undefined)
|
|
58
|
+
return null;
|
|
59
|
+
const n = Number(value);
|
|
60
|
+
return Number.isFinite(n) ? n : null;
|
|
61
|
+
}
|
|
62
|
+
function rowToEntry(row) {
|
|
63
|
+
const ownerEmail = typeof row.owner_email === "string" && row.owner_email.trim()
|
|
64
|
+
? row.owner_email
|
|
65
|
+
: null;
|
|
66
|
+
if (!ownerEmail) {
|
|
67
|
+
throw new Error("Observational memory row is missing owner_email.");
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
id: String(row.id),
|
|
71
|
+
threadId: String(row.thread_id),
|
|
72
|
+
tier: row.tier,
|
|
73
|
+
text: typeof row.text === "string" ? row.text : "",
|
|
74
|
+
tokenEstimate: Number(row.token_estimate) || 0,
|
|
75
|
+
sourceStartIndex: numOrNull(row.source_start_index),
|
|
76
|
+
sourceEndIndex: numOrNull(row.source_end_index),
|
|
77
|
+
sourceMessageCount: Number(row.source_message_count) || 0,
|
|
78
|
+
createdAt: Number(row.created_at) || 0,
|
|
79
|
+
updatedAt: Number(row.updated_at) || 0,
|
|
80
|
+
ownerEmail,
|
|
81
|
+
orgId: typeof row.org_id === "string" ? row.org_id : null,
|
|
82
|
+
visibility: row.visibility ?? "private",
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function addOwnerScope(clauses, args, owner) {
|
|
86
|
+
clauses.push("owner_email = ?");
|
|
87
|
+
args.push(owner.ownerEmail);
|
|
88
|
+
if (owner.orgId == null) {
|
|
89
|
+
clauses.push("org_id IS NULL");
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
clauses.push("org_id = ?");
|
|
93
|
+
args.push(owner.orgId);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/** Insert one OM entry, returning the persisted row. */
|
|
97
|
+
export async function insertObservationalMemory(input) {
|
|
98
|
+
await ensureTable();
|
|
99
|
+
const client = getDbExec();
|
|
100
|
+
const now = Date.now();
|
|
101
|
+
const id = entryId();
|
|
102
|
+
const entry = {
|
|
103
|
+
id,
|
|
104
|
+
threadId: input.threadId,
|
|
105
|
+
tier: input.tier,
|
|
106
|
+
text: input.text,
|
|
107
|
+
tokenEstimate: input.tokenEstimate,
|
|
108
|
+
sourceStartIndex: input.sourceStartIndex ?? null,
|
|
109
|
+
sourceEndIndex: input.sourceEndIndex ?? null,
|
|
110
|
+
sourceMessageCount: input.sourceMessageCount ?? 0,
|
|
111
|
+
createdAt: now,
|
|
112
|
+
updatedAt: now,
|
|
113
|
+
ownerEmail: input.ownerEmail,
|
|
114
|
+
orgId: input.orgId ?? null,
|
|
115
|
+
visibility: input.visibility ?? "private",
|
|
116
|
+
};
|
|
117
|
+
await client.execute({
|
|
118
|
+
sql: `INSERT INTO observational_memory
|
|
119
|
+
(id, thread_id, tier, text, token_estimate, source_start_index, source_end_index, source_message_count, created_at, updated_at, owner_email, org_id, visibility)
|
|
120
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
121
|
+
args: [
|
|
122
|
+
entry.id,
|
|
123
|
+
entry.threadId,
|
|
124
|
+
entry.tier,
|
|
125
|
+
entry.text,
|
|
126
|
+
entry.tokenEstimate,
|
|
127
|
+
entry.sourceStartIndex,
|
|
128
|
+
entry.sourceEndIndex,
|
|
129
|
+
entry.sourceMessageCount,
|
|
130
|
+
entry.createdAt,
|
|
131
|
+
entry.updatedAt,
|
|
132
|
+
entry.ownerEmail,
|
|
133
|
+
entry.orgId,
|
|
134
|
+
entry.visibility,
|
|
135
|
+
],
|
|
136
|
+
});
|
|
137
|
+
return entry;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* List a thread's OM entries for an owner, oldest → newest. Always
|
|
141
|
+
* owner-scoped; `org_id` is matched too when supplied so org-visible rows
|
|
142
|
+
* don't leak across orgs.
|
|
143
|
+
*/
|
|
144
|
+
export async function listObservationalMemory(options) {
|
|
145
|
+
await ensureTable();
|
|
146
|
+
const client = getDbExec();
|
|
147
|
+
const clauses = ["thread_id = ?"];
|
|
148
|
+
const args = [options.threadId];
|
|
149
|
+
addOwnerScope(clauses, args, options);
|
|
150
|
+
if (options.tier) {
|
|
151
|
+
clauses.push("tier = ?");
|
|
152
|
+
args.push(options.tier);
|
|
153
|
+
}
|
|
154
|
+
const result = await client.execute({
|
|
155
|
+
sql: `SELECT * FROM observational_memory WHERE ${clauses.join(" AND ")} ORDER BY created_at ASC, id ASC`,
|
|
156
|
+
args,
|
|
157
|
+
});
|
|
158
|
+
return result.rows.map(rowToEntry);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* The highest source-message index already folded into an observation for this
|
|
162
|
+
* thread/owner, or -1 if none. The Observer uses this to know which messages
|
|
163
|
+
* are still unobserved.
|
|
164
|
+
*/
|
|
165
|
+
export async function getObservedThroughIndex(options) {
|
|
166
|
+
await ensureTable();
|
|
167
|
+
const client = getDbExec();
|
|
168
|
+
const clauses = ["thread_id = ?", "tier = 'observation'"];
|
|
169
|
+
const args = [options.threadId];
|
|
170
|
+
addOwnerScope(clauses, args, options);
|
|
171
|
+
const result = await client.execute({
|
|
172
|
+
sql: `SELECT MAX(source_end_index) AS max_idx
|
|
173
|
+
FROM observational_memory
|
|
174
|
+
WHERE ${clauses.join(" AND ")}`,
|
|
175
|
+
args,
|
|
176
|
+
});
|
|
177
|
+
const row = result.rows[0];
|
|
178
|
+
const max = numOrNull(row?.max_idx);
|
|
179
|
+
return max == null ? -1 : max;
|
|
180
|
+
}
|
|
181
|
+
/** Sum the token estimates of a thread's observation entries for an owner. */
|
|
182
|
+
export async function getObservationLogTokens(options) {
|
|
183
|
+
await ensureTable();
|
|
184
|
+
const client = getDbExec();
|
|
185
|
+
const clauses = ["thread_id = ?", "tier = 'observation'"];
|
|
186
|
+
const args = [options.threadId];
|
|
187
|
+
addOwnerScope(clauses, args, options);
|
|
188
|
+
const result = await client.execute({
|
|
189
|
+
sql: `SELECT COALESCE(SUM(token_estimate), 0) AS total
|
|
190
|
+
FROM observational_memory
|
|
191
|
+
WHERE ${clauses.join(" AND ")}`,
|
|
192
|
+
args,
|
|
193
|
+
});
|
|
194
|
+
const row = result.rows[0];
|
|
195
|
+
return Number(row?.total) || 0;
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/agent/observational-memory/store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Persistence for Observational Memory entries.\n *\n * Owner-scoped throughout: every read and write takes an `ownerEmail` and the\n * SQL always filters by it, so the ownable table is never read or written\n * cross-owner (per the `security` skill). Dialect-agnostic — only `getDbExec()`\n * and parameterized SQL, never raw SQLite/Postgres types or string interpolation\n * of user data.\n *\n * `ensureTable()` lazily creates the table on first use (the same belt-and-\n * suspenders pattern as `chat-threads/store.ts`), so OM works in tests and at\n * runtime even before the migration plugin is registered.\n */\n\nimport { getDbExec } from \"../../db/client.js\";\nimport { isPostgres } from \"../../db/client.js\";\nimport type {\n ObservationalMemoryEntry,\n ObservationalMemoryOwner,\n ObservationalMemoryTier,\n} from \"./types.js\";\n\nlet tableReady: Promise<void> | null = null;\n\nasync function ensureTable(): Promise<void> {\n if (tableReady) return tableReady;\n tableReady = (async () => {\n const client = getDbExec();\n const intType = isPostgres() ? \"BIGINT\" : \"INTEGER\";\n await client.execute(\n `CREATE TABLE IF NOT EXISTS observational_memory (\n id TEXT PRIMARY KEY,\n thread_id TEXT NOT NULL,\n tier TEXT NOT NULL,\n text TEXT NOT NULL,\n token_estimate ${intType} NOT NULL DEFAULT 0,\n source_start_index ${intType},\n source_end_index ${intType},\n source_message_count ${intType} NOT NULL DEFAULT 0,\n created_at ${intType} NOT NULL,\n updated_at ${intType} NOT NULL,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n visibility TEXT NOT NULL DEFAULT 'private'\n )`,\n );\n await client.execute(\n `CREATE INDEX IF NOT EXISTS observational_memory_thread_tier_idx\n ON observational_memory(thread_id, tier, created_at)`,\n );\n await client.execute(\n `CREATE INDEX IF NOT EXISTS observational_memory_thread_owner_idx\n ON observational_memory(thread_id, owner_email)`,\n );\n })().catch((err) => {\n // Reset so a transient failure (e.g. SQLITE_BUSY on HMR) can retry.\n tableReady = null;\n throw err;\n });\n return tableReady;\n}\n\n/** Reset the cached ensureTable promise — test-only seam. */\nexport function __resetObservationalMemoryTableCache(): void {\n tableReady = null;\n}\n\nfunction entryId(): string {\n return `om-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction numOrNull(value: unknown): number | null {\n if (value === null || value === undefined) return null;\n const n = Number(value);\n return Number.isFinite(n) ? n : null;\n}\n\nfunction rowToEntry(row: Record<string, unknown>): ObservationalMemoryEntry {\n const ownerEmail =\n typeof row.owner_email === \"string\" && row.owner_email.trim()\n ? row.owner_email\n : null;\n if (!ownerEmail) {\n throw new Error(\"Observational memory row is missing owner_email.\");\n }\n return {\n id: String(row.id),\n threadId: String(row.thread_id),\n tier: row.tier as ObservationalMemoryTier,\n text: typeof row.text === \"string\" ? row.text : \"\",\n tokenEstimate: Number(row.token_estimate) || 0,\n sourceStartIndex: numOrNull(row.source_start_index),\n sourceEndIndex: numOrNull(row.source_end_index),\n sourceMessageCount: Number(row.source_message_count) || 0,\n createdAt: Number(row.created_at) || 0,\n updatedAt: Number(row.updated_at) || 0,\n ownerEmail,\n orgId: typeof row.org_id === \"string\" ? row.org_id : null,\n visibility:\n (row.visibility as ObservationalMemoryEntry[\"visibility\"]) ?? \"private\",\n };\n}\n\nfunction addOwnerScope(\n clauses: string[],\n args: unknown[],\n owner: ObservationalMemoryOwner,\n): void {\n clauses.push(\"owner_email = ?\");\n args.push(owner.ownerEmail);\n if (owner.orgId == null) {\n clauses.push(\"org_id IS NULL\");\n } else {\n clauses.push(\"org_id = ?\");\n args.push(owner.orgId);\n }\n}\n\nexport interface InsertObservationalMemoryInput extends ObservationalMemoryOwner {\n threadId: string;\n tier: ObservationalMemoryTier;\n text: string;\n tokenEstimate: number;\n sourceStartIndex?: number | null;\n sourceEndIndex?: number | null;\n sourceMessageCount?: number;\n visibility?: \"private\" | \"org\" | \"public\";\n}\n\n/** Insert one OM entry, returning the persisted row. */\nexport async function insertObservationalMemory(\n input: InsertObservationalMemoryInput,\n): Promise<ObservationalMemoryEntry> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n const id = entryId();\n const entry: ObservationalMemoryEntry = {\n id,\n threadId: input.threadId,\n tier: input.tier,\n text: input.text,\n tokenEstimate: input.tokenEstimate,\n sourceStartIndex: input.sourceStartIndex ?? null,\n sourceEndIndex: input.sourceEndIndex ?? null,\n sourceMessageCount: input.sourceMessageCount ?? 0,\n createdAt: now,\n updatedAt: now,\n ownerEmail: input.ownerEmail,\n orgId: input.orgId ?? null,\n visibility: input.visibility ?? \"private\",\n };\n await client.execute({\n sql: `INSERT INTO observational_memory\n (id, thread_id, tier, text, token_estimate, source_start_index, source_end_index, source_message_count, created_at, updated_at, owner_email, org_id, visibility)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n entry.id,\n entry.threadId,\n entry.tier,\n entry.text,\n entry.tokenEstimate,\n entry.sourceStartIndex,\n entry.sourceEndIndex,\n entry.sourceMessageCount,\n entry.createdAt,\n entry.updatedAt,\n entry.ownerEmail,\n entry.orgId,\n entry.visibility,\n ],\n });\n return entry;\n}\n\nexport interface ListObservationalMemoryOptions extends ObservationalMemoryOwner {\n threadId: string;\n /** When set, only entries of this tier are returned. */\n tier?: ObservationalMemoryTier;\n}\n\n/**\n * List a thread's OM entries for an owner, oldest → newest. Always\n * owner-scoped; `org_id` is matched too when supplied so org-visible rows\n * don't leak across orgs.\n */\nexport async function listObservationalMemory(\n options: ListObservationalMemoryOptions,\n): Promise<ObservationalMemoryEntry[]> {\n await ensureTable();\n const client = getDbExec();\n const clauses = [\"thread_id = ?\"];\n const args: unknown[] = [options.threadId];\n addOwnerScope(clauses, args, options);\n if (options.tier) {\n clauses.push(\"tier = ?\");\n args.push(options.tier);\n }\n const result = await client.execute({\n sql: `SELECT * FROM observational_memory WHERE ${clauses.join(\n \" AND \",\n )} ORDER BY created_at ASC, id ASC`,\n args,\n });\n return (result.rows as Record<string, unknown>[]).map(rowToEntry);\n}\n\n/**\n * The highest source-message index already folded into an observation for this\n * thread/owner, or -1 if none. The Observer uses this to know which messages\n * are still unobserved.\n */\nexport async function getObservedThroughIndex(\n options: ObservationalMemoryOwner & { threadId: string },\n): Promise<number> {\n await ensureTable();\n const client = getDbExec();\n const clauses = [\"thread_id = ?\", \"tier = 'observation'\"];\n const args: unknown[] = [options.threadId];\n addOwnerScope(clauses, args, options);\n const result = await client.execute({\n sql: `SELECT MAX(source_end_index) AS max_idx\n FROM observational_memory\n WHERE ${clauses.join(\" AND \")}`,\n args,\n });\n const row = (result.rows as Record<string, unknown>[])[0];\n const max = numOrNull(row?.max_idx);\n return max == null ? -1 : max;\n}\n\n/** Sum the token estimates of a thread's observation entries for an owner. */\nexport async function getObservationLogTokens(\n options: ObservationalMemoryOwner & { threadId: string },\n): Promise<number> {\n await ensureTable();\n const client = getDbExec();\n const clauses = [\"thread_id = ?\", \"tier = 'observation'\"];\n const args: unknown[] = [options.threadId];\n addOwnerScope(clauses, args, options);\n const result = await client.execute({\n sql: `SELECT COALESCE(SUM(token_estimate), 0) AS total\n FROM observational_memory\n WHERE ${clauses.join(\" AND \")}`,\n args,\n });\n const row = (result.rows as Record<string, unknown>[])[0];\n return Number(row?.total) || 0;\n}\n"]}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for Observational Memory (OM).
|
|
3
|
+
*
|
|
4
|
+
* Kept in their own module (no DB / engine imports) so both the store and the
|
|
5
|
+
* compactor — and any future read-side consumer in production-agent — can
|
|
6
|
+
* depend on them without pulling in a runtime.
|
|
7
|
+
*/
|
|
8
|
+
import type { EngineMessage } from "../engine/types.js";
|
|
9
|
+
/** The two compaction tiers. */
|
|
10
|
+
export type ObservationalMemoryTier = "observation" | "reflection";
|
|
11
|
+
/** One persisted OM entry (an observation or a reflection). */
|
|
12
|
+
export interface ObservationalMemoryEntry {
|
|
13
|
+
id: string;
|
|
14
|
+
threadId: string;
|
|
15
|
+
tier: ObservationalMemoryTier;
|
|
16
|
+
/** Dated, compacted text. */
|
|
17
|
+
text: string;
|
|
18
|
+
/** Estimated tokens for `text`. */
|
|
19
|
+
tokenEstimate: number;
|
|
20
|
+
/** Inclusive source range this entry summarizes (null when unknown). */
|
|
21
|
+
sourceStartIndex: number | null;
|
|
22
|
+
sourceEndIndex: number | null;
|
|
23
|
+
/** Count of source messages/observations folded into this entry. */
|
|
24
|
+
sourceMessageCount: number;
|
|
25
|
+
createdAt: number;
|
|
26
|
+
updatedAt: number;
|
|
27
|
+
ownerEmail: string;
|
|
28
|
+
orgId: string | null;
|
|
29
|
+
visibility: "private" | "org" | "public";
|
|
30
|
+
}
|
|
31
|
+
/** Owner scoping common to every OM read/write. */
|
|
32
|
+
export interface ObservationalMemoryOwner {
|
|
33
|
+
ownerEmail: string;
|
|
34
|
+
orgId?: string | null;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The three-tier context returned by `buildObservationalContext`, ready to be
|
|
38
|
+
* folded into a prompt:
|
|
39
|
+
*
|
|
40
|
+
* reflections (highest level) + observations (dense) + recent raw messages
|
|
41
|
+
*
|
|
42
|
+
* The caller decides exactly how to serialize these into the system prompt /
|
|
43
|
+
* message list; OM only assembles the tiers and their token accounting.
|
|
44
|
+
*/
|
|
45
|
+
export interface ObservationalContext {
|
|
46
|
+
threadId: string;
|
|
47
|
+
/** Higher-level reflections, oldest → newest. */
|
|
48
|
+
reflections: ObservationalMemoryEntry[];
|
|
49
|
+
/** Dense observations, oldest → newest. */
|
|
50
|
+
observations: ObservationalMemoryEntry[];
|
|
51
|
+
/** The tail of raw thread messages kept verbatim (most recent turns). */
|
|
52
|
+
recentMessages: EngineMessage[];
|
|
53
|
+
/** Token accounting so the caller can reason about prompt budget. */
|
|
54
|
+
tokens: {
|
|
55
|
+
reflections: number;
|
|
56
|
+
observations: number;
|
|
57
|
+
recentMessages: number;
|
|
58
|
+
total: number;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/agent/observational-memory/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,gCAAgC;AAChC,MAAM,MAAM,uBAAuB,GAAG,aAAa,GAAG,YAAY,CAAC;AAEnE,+DAA+D;AAC/D,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,uBAAuB,CAAC;IAC9B,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,oEAAoE;IACpE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,SAAS,GAAG,KAAK,GAAG,QAAQ,CAAC;CAC1C;AAED,mDAAmD;AACnD,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,WAAW,EAAE,wBAAwB,EAAE,CAAC;IACxC,2CAA2C;IAC3C,YAAY,EAAE,wBAAwB,EAAE,CAAC;IACzC,yEAAyE;IACzE,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,qEAAqE;IACrE,MAAM,EAAE;QACN,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for Observational Memory (OM).
|
|
3
|
+
*
|
|
4
|
+
* Kept in their own module (no DB / engine imports) so both the store and the
|
|
5
|
+
* compactor — and any future read-side consumer in production-agent — can
|
|
6
|
+
* depend on them without pulling in a runtime.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/agent/observational-memory/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG","sourcesContent":["/**\n * Shared types for Observational Memory (OM).\n *\n * Kept in their own module (no DB / engine imports) so both the store and the\n * compactor — and any future read-side consumer in production-agent — can\n * depend on them without pulling in a runtime.\n */\n\nimport type { EngineMessage } from \"../engine/types.js\";\n\n/** The two compaction tiers. */\nexport type ObservationalMemoryTier = \"observation\" | \"reflection\";\n\n/** One persisted OM entry (an observation or a reflection). */\nexport interface ObservationalMemoryEntry {\n id: string;\n threadId: string;\n tier: ObservationalMemoryTier;\n /** Dated, compacted text. */\n text: string;\n /** Estimated tokens for `text`. */\n tokenEstimate: number;\n /** Inclusive source range this entry summarizes (null when unknown). */\n sourceStartIndex: number | null;\n sourceEndIndex: number | null;\n /** Count of source messages/observations folded into this entry. */\n sourceMessageCount: number;\n createdAt: number;\n updatedAt: number;\n ownerEmail: string;\n orgId: string | null;\n visibility: \"private\" | \"org\" | \"public\";\n}\n\n/** Owner scoping common to every OM read/write. */\nexport interface ObservationalMemoryOwner {\n ownerEmail: string;\n orgId?: string | null;\n}\n\n/**\n * The three-tier context returned by `buildObservationalContext`, ready to be\n * folded into a prompt:\n *\n * reflections (highest level) + observations (dense) + recent raw messages\n *\n * The caller decides exactly how to serialize these into the system prompt /\n * message list; OM only assembles the tiers and their token accounting.\n */\nexport interface ObservationalContext {\n threadId: string;\n /** Higher-level reflections, oldest → newest. */\n reflections: ObservationalMemoryEntry[];\n /** Dense observations, oldest → newest. */\n observations: ObservationalMemoryEntry[];\n /** The tail of raw thread messages kept verbatim (most recent turns). */\n recentMessages: EngineMessage[];\n /** Token accounting so the caller can reason about prompt budget. */\n tokens: {\n reflections: number;\n observations: number;\n recentMessages: number;\n total: number;\n };\n}\n"]}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-loop processor seam for the agent loop.
|
|
3
|
+
*
|
|
4
|
+
* A `Processor` is loop-internal *configuration* — not a tool, not an authoring
|
|
5
|
+
* DSL, not an action. It observes the model's streamed output and tool calls as
|
|
6
|
+
* the run progresses, may mutate its own per-processor `state`, and may `abort()`
|
|
7
|
+
* the run. This is the structural prerequisite for real-time guardrails and a
|
|
8
|
+
* proof-of-done / coverage gate: code that can watch the model mid-run and halt
|
|
9
|
+
* it (or surface a verdict) before a "done" is claimed.
|
|
10
|
+
*
|
|
11
|
+
* Borrowed from Mastra's output processors. The shape is intentionally minimal:
|
|
12
|
+
*
|
|
13
|
+
* - `processOutputStream` fires per streamed chunk (text / thinking deltas,
|
|
14
|
+
* etc.) while the model is generating, so a guardrail can react before the
|
|
15
|
+
* full turn lands.
|
|
16
|
+
* - `processOutputStep` fires once per model response, around tool execution,
|
|
17
|
+
* with the tool calls the model just requested. A coverage gate can inspect
|
|
18
|
+
* what the model is about to do and abort.
|
|
19
|
+
* - `processOutputResult` fires once at run end with the final text.
|
|
20
|
+
*
|
|
21
|
+
* All hooks are OPTIONAL. When no processors are supplied to `runAgentLoop`, the
|
|
22
|
+
* loop must not run any of this code — the no-processors path is byte-for-byte
|
|
23
|
+
* unchanged and carries zero overhead (callers guard on a non-empty array).
|
|
24
|
+
*
|
|
25
|
+
* Each processor gets its own mutable `state` object that persists across every
|
|
26
|
+
* hook invocation for that processor within a single run, and is isolated from
|
|
27
|
+
* other processors' state.
|
|
28
|
+
*/
|
|
29
|
+
import type { EngineContentPart, EngineEvent } from "./engine/types.js";
|
|
30
|
+
/**
|
|
31
|
+
* Thrown by a processor's `abort()` to halt the run gracefully. The loop catches
|
|
32
|
+
* it, emits a `tripwire` event, and stops. Carries the human-readable `reason`
|
|
33
|
+
* plus optional structured `meta` and the originating `processor` name.
|
|
34
|
+
*
|
|
35
|
+
* Lives here (not in production-agent) so any consumer can `instanceof` it
|
|
36
|
+
* without an import cycle.
|
|
37
|
+
*/
|
|
38
|
+
export declare class TripWire extends Error {
|
|
39
|
+
/** Optional structured metadata supplied at the abort site. */
|
|
40
|
+
readonly meta?: Record<string, unknown>;
|
|
41
|
+
/** Name of the processor that aborted, when known. */
|
|
42
|
+
readonly processor?: string;
|
|
43
|
+
constructor(reason: string, opts?: {
|
|
44
|
+
meta?: Record<string, unknown>;
|
|
45
|
+
processor?: string;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Per-processor mutable scratch space. Each processor sees the SAME object
|
|
50
|
+
* across all of its hook invocations within one run; processors never see each
|
|
51
|
+
* other's state.
|
|
52
|
+
*/
|
|
53
|
+
export type ProcessorState = Record<string, unknown>;
|
|
54
|
+
/** Halts the run by throwing a {@link TripWire}. Never returns normally. */
|
|
55
|
+
export type ProcessorAbort = (reason: string, meta?: Record<string, unknown>) => never;
|
|
56
|
+
/** A single streamed chunk plus the running list of chunks seen so far. */
|
|
57
|
+
export interface ProcessOutputStreamArgs {
|
|
58
|
+
/** The chunk that just streamed from the engine. */
|
|
59
|
+
part: EngineEvent;
|
|
60
|
+
/** Every chunk observed so far this turn, including `part`. */
|
|
61
|
+
streamParts: EngineEvent[];
|
|
62
|
+
/** This processor's mutable, isolated, run-scoped state. */
|
|
63
|
+
state: ProcessorState;
|
|
64
|
+
/** Halt the run; throws {@link TripWire}. */
|
|
65
|
+
abort: ProcessorAbort;
|
|
66
|
+
}
|
|
67
|
+
/** Context for a completed model response, fired around tool execution. */
|
|
68
|
+
export interface ProcessOutputStepArgs {
|
|
69
|
+
/** Tool calls the model requested in this step (empty for a final answer). */
|
|
70
|
+
toolCalls: {
|
|
71
|
+
id: string;
|
|
72
|
+
name: string;
|
|
73
|
+
input: unknown;
|
|
74
|
+
}[];
|
|
75
|
+
/** Terminal stop reason for the step, when the engine reported one. */
|
|
76
|
+
finishReason?: "end_turn" | "tool_use" | "max_tokens" | "stop_sequence" | "error";
|
|
77
|
+
/** Cumulative token usage for the run so far, when available. */
|
|
78
|
+
usage?: {
|
|
79
|
+
inputTokens: number;
|
|
80
|
+
outputTokens: number;
|
|
81
|
+
cacheReadTokens?: number;
|
|
82
|
+
cacheWriteTokens?: number;
|
|
83
|
+
};
|
|
84
|
+
/** This processor's mutable, isolated, run-scoped state. */
|
|
85
|
+
state: ProcessorState;
|
|
86
|
+
/** Halt the run; throws {@link TripWire}. */
|
|
87
|
+
abort: ProcessorAbort;
|
|
88
|
+
}
|
|
89
|
+
/** Context for the end of the whole run. */
|
|
90
|
+
export interface ProcessOutputResultArgs {
|
|
91
|
+
/** The final assistant text for the run. */
|
|
92
|
+
text: string;
|
|
93
|
+
/** This processor's mutable, isolated, run-scoped state. */
|
|
94
|
+
state: ProcessorState;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* A loop-internal observer/guardrail. All hooks are optional; implement only
|
|
98
|
+
* the ones a given guardrail needs. Hooks may be sync or async.
|
|
99
|
+
*/
|
|
100
|
+
export interface Processor {
|
|
101
|
+
/** Stable name, surfaced on `tripwire` events and in per-processor errors. */
|
|
102
|
+
name?: string;
|
|
103
|
+
/** Called per streamed chunk while the model generates. */
|
|
104
|
+
processOutputStream?(args: ProcessOutputStreamArgs): void | Promise<void>;
|
|
105
|
+
/** Called once per model response, around tool execution. */
|
|
106
|
+
processOutputStep?(args: ProcessOutputStepArgs): void | Promise<void>;
|
|
107
|
+
/** Called once at run end with the final text. */
|
|
108
|
+
processOutputResult?(args: ProcessOutputResultArgs): void | Promise<void>;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Runs a chain of processors over the loop's lifecycle. Created once per run;
|
|
112
|
+
* isolates each processor's `state`, runs hooks in registration order, and
|
|
113
|
+
* converts a processor's `abort()` (or any thrown `TripWire`) into a single
|
|
114
|
+
* halt signal the loop can act on.
|
|
115
|
+
*
|
|
116
|
+
* The executor is only constructed when at least one processor is supplied, so
|
|
117
|
+
* the no-processors path never touches any of this.
|
|
118
|
+
*/
|
|
119
|
+
export declare class ProcessorChain {
|
|
120
|
+
private readonly entries;
|
|
121
|
+
/** Accumulates every stream chunk so each `processOutputStream` call sees the running list. */
|
|
122
|
+
private readonly streamParts;
|
|
123
|
+
constructor(processors: Processor[]);
|
|
124
|
+
private makeAbort;
|
|
125
|
+
/** Fire `processOutputStream` for every processor that implements it. */
|
|
126
|
+
runStream(part: EngineEvent): Promise<void>;
|
|
127
|
+
/** Fire `processOutputStep` for every processor that implements it. */
|
|
128
|
+
runStep(args: {
|
|
129
|
+
toolCalls: {
|
|
130
|
+
id: string;
|
|
131
|
+
name: string;
|
|
132
|
+
input: unknown;
|
|
133
|
+
}[];
|
|
134
|
+
finishReason?: ProcessOutputStepArgs["finishReason"];
|
|
135
|
+
usage?: ProcessOutputStepArgs["usage"];
|
|
136
|
+
}): Promise<void>;
|
|
137
|
+
/** Fire `processOutputResult` for every processor that implements it. */
|
|
138
|
+
runResult(text: string): Promise<void>;
|
|
139
|
+
}
|
|
140
|
+
/** Engine content parts → the plain tool-call shape passed to `processOutputStep`. */
|
|
141
|
+
export declare function toolCallsFromContent(parts: EngineContentPart[]): {
|
|
142
|
+
id: string;
|
|
143
|
+
name: string;
|
|
144
|
+
input: unknown;
|
|
145
|
+
}[];
|
|
146
|
+
//# sourceMappingURL=processors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processors.d.ts","sourceRoot":"","sources":["../../src/agent/processors.ts"],"names":[],"mappings":"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"}
|