@graphorin/memory 0.5.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/CHANGELOG.md +15 -0
- package/LICENSE +21 -0
- package/README.md +401 -0
- package/dist/conflict/index.d.ts +3 -0
- package/dist/conflict/index.js +7 -0
- package/dist/conflict/locale-packs/en.js +262 -0
- package/dist/conflict/locale-packs/en.js.map +1 -0
- package/dist/conflict/locale-packs/index.js +4 -0
- package/dist/conflict/locale-packs/types.d.ts +103 -0
- package/dist/conflict/locale-packs/types.d.ts.map +1 -0
- package/dist/conflict/locale-packs/types.js +55 -0
- package/dist/conflict/locale-packs/types.js.map +1 -0
- package/dist/conflict/pipeline.d.ts +35 -0
- package/dist/conflict/pipeline.d.ts.map +1 -0
- package/dist/conflict/pipeline.js +257 -0
- package/dist/conflict/pipeline.js.map +1 -0
- package/dist/conflict/stages/helpers.js +66 -0
- package/dist/conflict/stages/helpers.js.map +1 -0
- package/dist/conflict/stages/stage1-exact-dedup.js +21 -0
- package/dist/conflict/stages/stage1-exact-dedup.js.map +1 -0
- package/dist/conflict/stages/stage2-embedding-three-zone.js +37 -0
- package/dist/conflict/stages/stage2-embedding-three-zone.js.map +1 -0
- package/dist/conflict/stages/stage3-heuristic-regex.js +45 -0
- package/dist/conflict/stages/stage3-heuristic-regex.js.map +1 -0
- package/dist/conflict/stages/stage4-subject-predicate.js +31 -0
- package/dist/conflict/stages/stage4-subject-predicate.js.map +1 -0
- package/dist/conflict/stages/stage5-defer-to-deep.js +22 -0
- package/dist/conflict/stages/stage5-defer-to-deep.js.map +1 -0
- package/dist/conflict/types.d.ts +222 -0
- package/dist/conflict/types.d.ts.map +1 -0
- package/dist/conflict/types.js +50 -0
- package/dist/conflict/types.js.map +1 -0
- package/dist/consolidator/budget.d.ts +1 -0
- package/dist/consolidator/budget.js +214 -0
- package/dist/consolidator/budget.js.map +1 -0
- package/dist/consolidator/decay.d.ts +35 -0
- package/dist/consolidator/decay.d.ts.map +1 -0
- package/dist/consolidator/decay.js +91 -0
- package/dist/consolidator/decay.js.map +1 -0
- package/dist/consolidator/dlq.js +58 -0
- package/dist/consolidator/dlq.js.map +1 -0
- package/dist/consolidator/errors.d.ts +54 -0
- package/dist/consolidator/errors.d.ts.map +1 -0
- package/dist/consolidator/errors.js +67 -0
- package/dist/consolidator/errors.js.map +1 -0
- package/dist/consolidator/idempotency.d.ts +1 -0
- package/dist/consolidator/idempotency.js +22 -0
- package/dist/consolidator/idempotency.js.map +1 -0
- package/dist/consolidator/index.d.ts +34 -0
- package/dist/consolidator/index.d.ts.map +1 -0
- package/dist/consolidator/index.js +163 -0
- package/dist/consolidator/index.js.map +1 -0
- package/dist/consolidator/lock.d.ts +2 -0
- package/dist/consolidator/lock.js +89 -0
- package/dist/consolidator/lock.js.map +1 -0
- package/dist/consolidator/noise-filter.d.ts +2 -0
- package/dist/consolidator/noise-filter.js +173 -0
- package/dist/consolidator/noise-filter.js.map +1 -0
- package/dist/consolidator/phases/deep.d.ts +4 -0
- package/dist/consolidator/phases/deep.js +198 -0
- package/dist/consolidator/phases/deep.js.map +1 -0
- package/dist/consolidator/phases/induce.d.ts +154 -0
- package/dist/consolidator/phases/induce.d.ts.map +1 -0
- package/dist/consolidator/phases/induce.js +253 -0
- package/dist/consolidator/phases/induce.js.map +1 -0
- package/dist/consolidator/phases/light.d.ts +4 -0
- package/dist/consolidator/phases/light.js +99 -0
- package/dist/consolidator/phases/light.js.map +1 -0
- package/dist/consolidator/phases/reflect.js +287 -0
- package/dist/consolidator/phases/reflect.js.map +1 -0
- package/dist/consolidator/phases/standard.d.ts +8 -0
- package/dist/consolidator/phases/standard.js +499 -0
- package/dist/consolidator/phases/standard.js.map +1 -0
- package/dist/consolidator/reconcile.js +192 -0
- package/dist/consolidator/reconcile.js.map +1 -0
- package/dist/consolidator/runtime.d.ts +62 -0
- package/dist/consolidator/runtime.d.ts.map +1 -0
- package/dist/consolidator/runtime.js +580 -0
- package/dist/consolidator/runtime.js.map +1 -0
- package/dist/consolidator/scheduler.d.ts +111 -0
- package/dist/consolidator/scheduler.d.ts.map +1 -0
- package/dist/consolidator/scheduler.js +71 -0
- package/dist/consolidator/scheduler.js.map +1 -0
- package/dist/consolidator/triggers.d.ts +40 -0
- package/dist/consolidator/triggers.d.ts.map +1 -0
- package/dist/consolidator/triggers.js +94 -0
- package/dist/consolidator/triggers.js.map +1 -0
- package/dist/consolidator/types.d.ts +397 -0
- package/dist/consolidator/types.d.ts.map +1 -0
- package/dist/consolidator/types.js +117 -0
- package/dist/consolidator/types.js.map +1 -0
- package/dist/context-engine/annotations.d.ts +118 -0
- package/dist/context-engine/annotations.d.ts.map +1 -0
- package/dist/context-engine/annotations.js +102 -0
- package/dist/context-engine/annotations.js.map +1 -0
- package/dist/context-engine/auto-recall.d.ts +52 -0
- package/dist/context-engine/auto-recall.d.ts.map +1 -0
- package/dist/context-engine/auto-recall.js +41 -0
- package/dist/context-engine/auto-recall.js.map +1 -0
- package/dist/context-engine/compaction/clear-tool-results.d.ts +55 -0
- package/dist/context-engine/compaction/clear-tool-results.d.ts.map +1 -0
- package/dist/context-engine/compaction/clear-tool-results.js +97 -0
- package/dist/context-engine/compaction/clear-tool-results.js.map +1 -0
- package/dist/context-engine/compaction/compactor.d.ts +52 -0
- package/dist/context-engine/compaction/compactor.d.ts.map +1 -0
- package/dist/context-engine/compaction/compactor.js +196 -0
- package/dist/context-engine/compaction/compactor.js.map +1 -0
- package/dist/context-engine/compaction/hooks/reanchor-persona-block.d.ts +15 -0
- package/dist/context-engine/compaction/hooks/reanchor-persona-block.d.ts.map +1 -0
- package/dist/context-engine/compaction/hooks/reanchor-persona-block.js +27 -0
- package/dist/context-engine/compaction/hooks/reanchor-persona-block.js.map +1 -0
- package/dist/context-engine/compaction/hooks/reanchor-pinned-facts.d.ts +18 -0
- package/dist/context-engine/compaction/hooks/reanchor-pinned-facts.d.ts.map +1 -0
- package/dist/context-engine/compaction/hooks/reanchor-pinned-facts.js +47 -0
- package/dist/context-engine/compaction/hooks/reanchor-pinned-facts.js.map +1 -0
- package/dist/context-engine/compaction/hooks/reanchor-project-rules.d.ts +15 -0
- package/dist/context-engine/compaction/hooks/reanchor-project-rules.d.ts.map +1 -0
- package/dist/context-engine/compaction/hooks/reanchor-project-rules.js +32 -0
- package/dist/context-engine/compaction/hooks/reanchor-project-rules.js.map +1 -0
- package/dist/context-engine/compaction/hooks/types.d.ts +42 -0
- package/dist/context-engine/compaction/hooks/types.d.ts.map +1 -0
- package/dist/context-engine/compaction/index.d.ts +9 -0
- package/dist/context-engine/compaction/index.js +9 -0
- package/dist/context-engine/compaction/templates/summary-9-section.d.ts +84 -0
- package/dist/context-engine/compaction/templates/summary-9-section.d.ts.map +1 -0
- package/dist/context-engine/compaction/templates/summary-9-section.js +84 -0
- package/dist/context-engine/compaction/templates/summary-9-section.js.map +1 -0
- package/dist/context-engine/compaction/thresholds.d.ts +68 -0
- package/dist/context-engine/compaction/thresholds.d.ts.map +1 -0
- package/dist/context-engine/compaction/thresholds.js +63 -0
- package/dist/context-engine/compaction/thresholds.js.map +1 -0
- package/dist/context-engine/compaction/types.d.ts +202 -0
- package/dist/context-engine/compaction/types.d.ts.map +1 -0
- package/dist/context-engine/engine.d.ts +258 -0
- package/dist/context-engine/engine.d.ts.map +1 -0
- package/dist/context-engine/engine.js +424 -0
- package/dist/context-engine/engine.js.map +1 -0
- package/dist/context-engine/index.d.ts +68 -0
- package/dist/context-engine/index.d.ts.map +1 -0
- package/dist/context-engine/index.js +24 -0
- package/dist/context-engine/locale-packs/en.d.ts +14 -0
- package/dist/context-engine/locale-packs/en.d.ts.map +1 -0
- package/dist/context-engine/locale-packs/en.js +87 -0
- package/dist/context-engine/locale-packs/en.js.map +1 -0
- package/dist/context-engine/locale-packs/index.js +4 -0
- package/dist/context-engine/locale-packs/resolver.d.ts +41 -0
- package/dist/context-engine/locale-packs/resolver.d.ts.map +1 -0
- package/dist/context-engine/locale-packs/resolver.js +119 -0
- package/dist/context-engine/locale-packs/resolver.js.map +1 -0
- package/dist/context-engine/locale-packs/types.d.ts +119 -0
- package/dist/context-engine/locale-packs/types.d.ts.map +1 -0
- package/dist/context-engine/locale-packs/types.js +24 -0
- package/dist/context-engine/locale-packs/types.js.map +1 -0
- package/dist/context-engine/metadata.d.ts +40 -0
- package/dist/context-engine/metadata.d.ts.map +1 -0
- package/dist/context-engine/metadata.js +66 -0
- package/dist/context-engine/metadata.js.map +1 -0
- package/dist/context-engine/preambles/inbound-en.d.ts +20 -0
- package/dist/context-engine/preambles/inbound-en.d.ts.map +1 -0
- package/dist/context-engine/preambles/inbound-en.js +23 -0
- package/dist/context-engine/preambles/inbound-en.js.map +1 -0
- package/dist/context-engine/privacy-filter.d.ts +108 -0
- package/dist/context-engine/privacy-filter.d.ts.map +1 -0
- package/dist/context-engine/privacy-filter.js +113 -0
- package/dist/context-engine/privacy-filter.js.map +1 -0
- package/dist/context-engine/templates/base-en.d.ts +19 -0
- package/dist/context-engine/templates/base-en.d.ts.map +1 -0
- package/dist/context-engine/templates/base-en.js +22 -0
- package/dist/context-engine/templates/base-en.js.map +1 -0
- package/dist/context-engine/templates/composer.d.ts +55 -0
- package/dist/context-engine/templates/composer.d.ts.map +1 -0
- package/dist/context-engine/templates/composer.js +51 -0
- package/dist/context-engine/templates/composer.js.map +1 -0
- package/dist/context-engine/token-budget.d.ts +99 -0
- package/dist/context-engine/token-budget.d.ts.map +1 -0
- package/dist/context-engine/token-budget.js +211 -0
- package/dist/context-engine/token-budget.js.map +1 -0
- package/dist/context-engine/token-counter.d.ts +54 -0
- package/dist/context-engine/token-counter.d.ts.map +1 -0
- package/dist/context-engine/token-counter.js +81 -0
- package/dist/context-engine/token-counter.js.map +1 -0
- package/dist/errors/index.d.ts +171 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +206 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/facade.d.ts +278 -0
- package/dist/facade.d.ts.map +1 -0
- package/dist/facade.js +265 -0
- package/dist/facade.js.map +1 -0
- package/dist/graph/entity-resolver.d.ts +135 -0
- package/dist/graph/entity-resolver.d.ts.map +1 -0
- package/dist/graph/entity-resolver.js +202 -0
- package/dist/graph/entity-resolver.js.map +1 -0
- package/dist/graph/index.d.ts +1 -0
- package/dist/index.d.ts +103 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +95 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/contextualize.d.ts +14 -0
- package/dist/internal/contextualize.d.ts.map +1 -0
- package/dist/internal/contextualize.js +110 -0
- package/dist/internal/contextualize.js.map +1 -0
- package/dist/internal/embedder-binding.js +50 -0
- package/dist/internal/embedder-binding.js.map +1 -0
- package/dist/internal/id.js +24 -0
- package/dist/internal/id.js.map +1 -0
- package/dist/internal/injection-heuristics.js +64 -0
- package/dist/internal/injection-heuristics.js.map +1 -0
- package/dist/internal/spans.js +35 -0
- package/dist/internal/spans.js.map +1 -0
- package/dist/internal/storage-adapter.d.ts +742 -0
- package/dist/internal/storage-adapter.d.ts.map +1 -0
- package/dist/migration/embedder-migration.d.ts +124 -0
- package/dist/migration/embedder-migration.d.ts.map +1 -0
- package/dist/migration/embedder-migration.js +109 -0
- package/dist/migration/embedder-migration.js.map +1 -0
- package/dist/migration/index.d.ts +2 -0
- package/dist/migration/index.js +3 -0
- package/dist/search/explain.d.ts +74 -0
- package/dist/search/explain.d.ts.map +1 -0
- package/dist/search/explain.js +50 -0
- package/dist/search/explain.js.map +1 -0
- package/dist/search/index.d.ts +6 -0
- package/dist/search/index.js +6 -0
- package/dist/search/iterative.d.ts +223 -0
- package/dist/search/iterative.d.ts.map +1 -0
- package/dist/search/iterative.js +330 -0
- package/dist/search/iterative.js.map +1 -0
- package/dist/search/query-transform.d.ts +112 -0
- package/dist/search/query-transform.d.ts.map +1 -0
- package/dist/search/query-transform.js +184 -0
- package/dist/search/query-transform.js.map +1 -0
- package/dist/search/rrf.d.ts +95 -0
- package/dist/search/rrf.d.ts.map +1 -0
- package/dist/search/rrf.js +166 -0
- package/dist/search/rrf.js.map +1 -0
- package/dist/search/types.d.ts +50 -0
- package/dist/search/types.d.ts.map +1 -0
- package/dist/tiers/episodic-memory.d.ts +142 -0
- package/dist/tiers/episodic-memory.d.ts.map +1 -0
- package/dist/tiers/episodic-memory.js +254 -0
- package/dist/tiers/episodic-memory.js.map +1 -0
- package/dist/tiers/index.d.ts +8 -0
- package/dist/tiers/index.js +9 -0
- package/dist/tiers/insight-memory.d.ts +71 -0
- package/dist/tiers/insight-memory.d.ts.map +1 -0
- package/dist/tiers/insight-memory.js +133 -0
- package/dist/tiers/insight-memory.js.map +1 -0
- package/dist/tiers/procedural-memory.d.ts +147 -0
- package/dist/tiers/procedural-memory.d.ts.map +1 -0
- package/dist/tiers/procedural-memory.js +267 -0
- package/dist/tiers/procedural-memory.js.map +1 -0
- package/dist/tiers/semantic-memory.d.ts +461 -0
- package/dist/tiers/semantic-memory.d.ts.map +1 -0
- package/dist/tiers/semantic-memory.js +631 -0
- package/dist/tiers/semantic-memory.js.map +1 -0
- package/dist/tiers/session-memory.d.ts +117 -0
- package/dist/tiers/session-memory.d.ts.map +1 -0
- package/dist/tiers/session-memory.js +163 -0
- package/dist/tiers/session-memory.js.map +1 -0
- package/dist/tiers/shared-memory.d.ts +29 -0
- package/dist/tiers/shared-memory.d.ts.map +1 -0
- package/dist/tiers/shared-memory.js +58 -0
- package/dist/tiers/shared-memory.js.map +1 -0
- package/dist/tiers/working-memory.d.ts +129 -0
- package/dist/tiers/working-memory.d.ts.map +1 -0
- package/dist/tiers/working-memory.js +229 -0
- package/dist/tiers/working-memory.js.map +1 -0
- package/dist/tools/block-tools.d.ts +98 -0
- package/dist/tools/block-tools.d.ts.map +1 -0
- package/dist/tools/block-tools.js +114 -0
- package/dist/tools/block-tools.js.map +1 -0
- package/dist/tools/fact-tools.d.ts +294 -0
- package/dist/tools/fact-tools.d.ts.map +1 -0
- package/dist/tools/fact-tools.js +293 -0
- package/dist/tools/fact-tools.js.map +1 -0
- package/dist/tools/index.d.ts +35 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +36 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/recall-tools.d.ts +209 -0
- package/dist/tools/recall-tools.d.ts.map +1 -0
- package/dist/tools/recall-tools.js +170 -0
- package/dist/tools/recall-tools.js.map +1 -0
- package/dist/tools/types.d.ts +40 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/package.json +119 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { MemoryStoreAdapter } from "../internal/storage-adapter.js";
|
|
2
|
+
import { Block, Sensitivity, SessionScope, Tracer, ZodLikeSchema } from "@graphorin/core";
|
|
3
|
+
|
|
4
|
+
//#region src/tiers/working-memory.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Author-time block specification accepted by
|
|
8
|
+
* {@link defineBlock} and {@link WorkingMemory.define}.
|
|
9
|
+
*
|
|
10
|
+
* @stable
|
|
11
|
+
*/
|
|
12
|
+
interface BlockSpec {
|
|
13
|
+
readonly label: string;
|
|
14
|
+
readonly description?: string;
|
|
15
|
+
readonly schema?: ZodLikeSchema<unknown>;
|
|
16
|
+
/** Maximum length of the rendered value in characters. */
|
|
17
|
+
readonly charLimit: number;
|
|
18
|
+
/** Default `'internal'`. */
|
|
19
|
+
readonly sensitivity?: Sensitivity;
|
|
20
|
+
/** Default `false`. */
|
|
21
|
+
readonly readOnly?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Per-block default value. Applied on first definition only; later
|
|
24
|
+
* runs preserve any value already in storage.
|
|
25
|
+
*/
|
|
26
|
+
readonly defaultValue?: string;
|
|
27
|
+
/** Default `'truncate'` — `'reject'` opt-in for strict use cases. */
|
|
28
|
+
readonly overflowPolicy?: 'truncate' | 'reject';
|
|
29
|
+
/** Optional free-form labels surfaced through `tags`. */
|
|
30
|
+
readonly tags?: ReadonlyArray<string>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Frozen block definition returned by {@link defineBlock}. Re-used by
|
|
34
|
+
* the agent runtime / context engine to know which blocks should be
|
|
35
|
+
* compiled into the system prompt every step.
|
|
36
|
+
*
|
|
37
|
+
* @stable
|
|
38
|
+
*/
|
|
39
|
+
interface BlockDefinition {
|
|
40
|
+
readonly label: string;
|
|
41
|
+
readonly description?: string;
|
|
42
|
+
readonly schema?: ZodLikeSchema<unknown>;
|
|
43
|
+
readonly charLimit: number;
|
|
44
|
+
readonly sensitivity: Sensitivity;
|
|
45
|
+
readonly readOnly: boolean;
|
|
46
|
+
readonly defaultValue?: string;
|
|
47
|
+
readonly overflowPolicy: 'truncate' | 'reject';
|
|
48
|
+
readonly tags?: ReadonlyArray<string>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Build a frozen {@link BlockDefinition}. Surfaced as `blocks.define(...)`
|
|
52
|
+
* for ergonomic call-sites; the underlying object is the same shape
|
|
53
|
+
* the {@link WorkingMemory.define} method accepts.
|
|
54
|
+
*
|
|
55
|
+
* @stable
|
|
56
|
+
*/
|
|
57
|
+
declare function defineBlock(spec: BlockSpec): BlockDefinition;
|
|
58
|
+
/**
|
|
59
|
+
* `WorkingMemory` — labeled, character-bounded blocks rendered into
|
|
60
|
+
* every system prompt. Operations:
|
|
61
|
+
*
|
|
62
|
+
* - `define(spec)`: idempotently registers a block definition; the
|
|
63
|
+
* block's row is created in storage on the next `write` call so
|
|
64
|
+
* operators can change `description` between runs without
|
|
65
|
+
* triggering a write.
|
|
66
|
+
* - `read(scope, label)` / `list(scope)`: surface the current block
|
|
67
|
+
* contents.
|
|
68
|
+
* - `write(scope, label, value)`: full replace.
|
|
69
|
+
* - `append(scope, label, content)`: append-with-newline.
|
|
70
|
+
* - `replace(scope, label, oldUnique, newText)`: targeted replace
|
|
71
|
+
* with a uniqueness check.
|
|
72
|
+
* - `compile(scope)`: render the active blocks for the context
|
|
73
|
+
* engine (used by Phase 10d).
|
|
74
|
+
*
|
|
75
|
+
* @stable
|
|
76
|
+
*/
|
|
77
|
+
declare class WorkingMemory {
|
|
78
|
+
#private;
|
|
79
|
+
constructor(args: {
|
|
80
|
+
store: MemoryStoreAdapter;
|
|
81
|
+
tracer: Tracer;
|
|
82
|
+
});
|
|
83
|
+
/** Register a block definition. Returns the same definition object. */
|
|
84
|
+
define(definition: BlockDefinition): BlockDefinition;
|
|
85
|
+
/** Snapshot of every registered definition. */
|
|
86
|
+
definitions(): ReadonlyArray<BlockDefinition>;
|
|
87
|
+
/** Lookup a definition by label. */
|
|
88
|
+
definitionFor(label: string): BlockDefinition | undefined;
|
|
89
|
+
/** List active (non-deleted) blocks for the supplied scope. */
|
|
90
|
+
list(scope: SessionScope): Promise<ReadonlyArray<Block>>;
|
|
91
|
+
/** Read a single block's value (or `null` when absent). */
|
|
92
|
+
read(scope: SessionScope, label: string): Promise<string | null>;
|
|
93
|
+
/** Replace a block's value entirely. Honours overflow policy. */
|
|
94
|
+
write(scope: SessionScope, label: string, value: string): Promise<Block>;
|
|
95
|
+
/** Append `content` to a block (with a newline separator). */
|
|
96
|
+
append(scope: SessionScope, label: string, content: string): Promise<Block>;
|
|
97
|
+
/**
|
|
98
|
+
* Replace the unique substring `oldUnique` inside the block's value
|
|
99
|
+
* with `newText`. Throws `WorkingBlockReplaceMismatchError` when
|
|
100
|
+
* the substring is missing or appears more than once.
|
|
101
|
+
*/
|
|
102
|
+
replace(scope: SessionScope, label: string, oldUnique: string, newText: string): Promise<Block>;
|
|
103
|
+
/** Run `mutator(current) => next` and persist the result. */
|
|
104
|
+
rethink(scope: SessionScope, label: string, mutator: (current: string) => string | Promise<string>): Promise<Block>;
|
|
105
|
+
/** Soft-delete a block. */
|
|
106
|
+
forget(scope: SessionScope, label: string, reason?: string): Promise<void>;
|
|
107
|
+
/**
|
|
108
|
+
* Attach a working block to an additional agent. Backed by the
|
|
109
|
+
* adapter's `shared.attach(...)` join table so multi-agent crews
|
|
110
|
+
* can share the same block without duplicating storage.
|
|
111
|
+
*/
|
|
112
|
+
attach(scope: SessionScope, blockId: string, agentId: string): Promise<void>;
|
|
113
|
+
/** Detach a working block from an agent. */
|
|
114
|
+
detach(scope: SessionScope, blockId: string, agentId: string): Promise<void>;
|
|
115
|
+
/**
|
|
116
|
+
* Render a deterministic `<memory_blocks>` XML fragment for the
|
|
117
|
+
* supplied scope. The full layered system prompt (six layers) is
|
|
118
|
+
* produced by Phase 10d's ContextEngine; this method ships the
|
|
119
|
+
* minimum-viable rendering used by the smoke acceptance criteria.
|
|
120
|
+
*
|
|
121
|
+
* The optional `agentId` argument is reserved for the per-agent
|
|
122
|
+
* filtering Phase 10d wires through. In Phase 10a the argument is
|
|
123
|
+
* accepted but ignored — the rendering is scope-wide.
|
|
124
|
+
*/
|
|
125
|
+
compile(scope: SessionScope, agentId?: string): Promise<string>;
|
|
126
|
+
}
|
|
127
|
+
//#endregion
|
|
128
|
+
export { BlockDefinition, BlockSpec, WorkingMemory, defineBlock };
|
|
129
|
+
//# sourceMappingURL=working-memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"working-memory.d.ts","names":[],"sources":["../../src/tiers/working-memory.ts"],"sourcesContent":[],"mappings":";;;;;;;AAgBA;;;;AAkB+B,UAlBd,SAAA,CAkBc;EAUd,SAAA,KAAA,EAAA,MAAe;EAGZ,SAAA,WAAA,CAAA,EAAA,MAAA;EAEI,SAAA,MAAA,CAAA,EA9BJ,aA8BI,CAAA,OAAA,CAAA;EAIN;EAAa,SAAA,SAAA,EAAA,MAAA;EAUf;EAyCH,SAAA,WAAa,CAAA,EAjFD,WAiFC;EAKG;EAA4B,SAAA,QAAA,CAAA,EAAA,OAAA;EAOpC;;;;EAWW,SAAA,YAAA,CAAA,EAAA,MAAA;EAKZ;EAAqC,SAAA,cAAA,CAAA,EAAA,UAAA,GAAA,QAAA;EAAd;EAAR,SAAA,IAAA,CAAA,EAlGjB,aAkGiB,CAAA,MAAA,CAAA;;;;;;;;;AA+CxB,UAvIM,eAAA,CAuIN;EAIE,SAAA,KAAA,EAAA,MAAA;EAAR,SAAA,WAAA,CAAA,EAAA,MAAA;EAaM,SAAA,MAAA,CAAA,EArJS,aAqJT,CAAA,OAAA,CAAA;EAEgC,SAAA,SAAA,EAAA,MAAA;EAC9B,SAAA,WAAA,EAtJW,WAsJX;EAAR,SAAA,QAAA,EAAA,OAAA;EAKiB,SAAA,YAAA,CAAA,EAAA,MAAA;EAA+C,SAAA,cAAA,EAAA,UAAA,GAAA,QAAA;EAiB/C,SAAA,IAAA,CAAA,EAxKJ,aAwKI,CAAA,MAAA,CAAA;;;;;;;;;iBA9JN,WAAA,OAAkB,YAAY;;;;;;;;;;;;;;;;;;;;cAyCjC,aAAA;;;WAKgB;YAA4B;;;qBAOpC,kBAAkB;;iBAMtB,cAAc;;gCAKC;;cAKZ,eAAe,QAAQ,cAAc;;cASrC,8BAA8B;;eAoB7B,6CAA6C,QAAQ;;gBAKpD,+CAA+C,QAAQ;;;;;;iBAalE,kEAIN,QAAQ;;iBAaF,oEAEgC,kBACtC,QAAQ;;gBAKS,+CAA+C;;;;;;gBAiB/C,iDAAiD;;gBAiBjD,iDAAiD;;;;;;;;;;;iBA0BhD,iCAAiC"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { withMemorySpan } from "../internal/spans.js";
|
|
2
|
+
import { WorkingBlockOverflowError, WorkingBlockReadOnlyError, WorkingBlockReplaceMismatchError } from "../errors/index.js";
|
|
3
|
+
import { newMemoryId } from "../internal/id.js";
|
|
4
|
+
|
|
5
|
+
//#region src/tiers/working-memory.ts
|
|
6
|
+
/**
|
|
7
|
+
* Build a frozen {@link BlockDefinition}. Surfaced as `blocks.define(...)`
|
|
8
|
+
* for ergonomic call-sites; the underlying object is the same shape
|
|
9
|
+
* the {@link WorkingMemory.define} method accepts.
|
|
10
|
+
*
|
|
11
|
+
* @stable
|
|
12
|
+
*/
|
|
13
|
+
function defineBlock(spec) {
|
|
14
|
+
if (!spec.label || spec.label.length === 0) throw new TypeError("[graphorin/memory] BlockSpec.label must be a non-empty string.");
|
|
15
|
+
if (!Number.isInteger(spec.charLimit) || spec.charLimit <= 0) throw new TypeError(`[graphorin/memory] BlockSpec.charLimit must be a positive integer, got ${String(spec.charLimit)}.`);
|
|
16
|
+
return Object.freeze({
|
|
17
|
+
label: spec.label,
|
|
18
|
+
...spec.description !== void 0 ? { description: spec.description } : {},
|
|
19
|
+
...spec.schema !== void 0 ? { schema: spec.schema } : {},
|
|
20
|
+
charLimit: spec.charLimit,
|
|
21
|
+
sensitivity: spec.sensitivity ?? "internal",
|
|
22
|
+
readOnly: spec.readOnly ?? false,
|
|
23
|
+
...spec.defaultValue !== void 0 ? { defaultValue: spec.defaultValue } : {},
|
|
24
|
+
overflowPolicy: spec.overflowPolicy ?? "truncate",
|
|
25
|
+
...spec.tags !== void 0 ? { tags: Object.freeze([...spec.tags]) } : {}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* `WorkingMemory` — labeled, character-bounded blocks rendered into
|
|
30
|
+
* every system prompt. Operations:
|
|
31
|
+
*
|
|
32
|
+
* - `define(spec)`: idempotently registers a block definition; the
|
|
33
|
+
* block's row is created in storage on the next `write` call so
|
|
34
|
+
* operators can change `description` between runs without
|
|
35
|
+
* triggering a write.
|
|
36
|
+
* - `read(scope, label)` / `list(scope)`: surface the current block
|
|
37
|
+
* contents.
|
|
38
|
+
* - `write(scope, label, value)`: full replace.
|
|
39
|
+
* - `append(scope, label, content)`: append-with-newline.
|
|
40
|
+
* - `replace(scope, label, oldUnique, newText)`: targeted replace
|
|
41
|
+
* with a uniqueness check.
|
|
42
|
+
* - `compile(scope)`: render the active blocks for the context
|
|
43
|
+
* engine (used by Phase 10d).
|
|
44
|
+
*
|
|
45
|
+
* @stable
|
|
46
|
+
*/
|
|
47
|
+
var WorkingMemory = class {
|
|
48
|
+
#store;
|
|
49
|
+
#tracer;
|
|
50
|
+
#defs;
|
|
51
|
+
constructor(args) {
|
|
52
|
+
this.#store = args.store;
|
|
53
|
+
this.#tracer = args.tracer;
|
|
54
|
+
this.#defs = /* @__PURE__ */ new Map();
|
|
55
|
+
}
|
|
56
|
+
/** Register a block definition. Returns the same definition object. */
|
|
57
|
+
define(definition) {
|
|
58
|
+
this.#defs.set(definition.label, definition);
|
|
59
|
+
return definition;
|
|
60
|
+
}
|
|
61
|
+
/** Snapshot of every registered definition. */
|
|
62
|
+
definitions() {
|
|
63
|
+
return Array.from(this.#defs.values());
|
|
64
|
+
}
|
|
65
|
+
/** Lookup a definition by label. */
|
|
66
|
+
definitionFor(label) {
|
|
67
|
+
return this.#defs.get(label);
|
|
68
|
+
}
|
|
69
|
+
/** List active (non-deleted) blocks for the supplied scope. */
|
|
70
|
+
async list(scope) {
|
|
71
|
+
return withMemorySpan(this.#tracer, "memory.read.working", scope, {}, async (span) => {
|
|
72
|
+
const out = await this.#store.working.list(scope);
|
|
73
|
+
span.setAttributes({ "memory.read.working.count": out.length });
|
|
74
|
+
return out;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/** Read a single block's value (or `null` when absent). */
|
|
78
|
+
async read(scope, label) {
|
|
79
|
+
return withMemorySpan(this.#tracer, "memory.read.working", scope, { "memory.block.label": label }, async (span) => {
|
|
80
|
+
const block = await this.#store.working.get(scope, label);
|
|
81
|
+
span.setAttributes({ "memory.read.working.found": block !== null });
|
|
82
|
+
if (block !== null) return block.value;
|
|
83
|
+
return this.#defs.get(label)?.defaultValue ?? null;
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/** Replace a block's value entirely. Honours overflow policy. */
|
|
87
|
+
async write(scope, label, value) {
|
|
88
|
+
return this.#mutate(scope, label, async () => value);
|
|
89
|
+
}
|
|
90
|
+
/** Append `content` to a block (with a newline separator). */
|
|
91
|
+
async append(scope, label, content) {
|
|
92
|
+
return this.#mutate(scope, label, async (current) => {
|
|
93
|
+
if (current === "" || current === void 0) return content;
|
|
94
|
+
return `${current}\n${content}`;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Replace the unique substring `oldUnique` inside the block's value
|
|
99
|
+
* with `newText`. Throws `WorkingBlockReplaceMismatchError` when
|
|
100
|
+
* the substring is missing or appears more than once.
|
|
101
|
+
*/
|
|
102
|
+
async replace(scope, label, oldUnique, newText) {
|
|
103
|
+
return this.#mutate(scope, label, async (current) => {
|
|
104
|
+
const haystack = current ?? "";
|
|
105
|
+
const occurrences = countOccurrences(haystack, oldUnique);
|
|
106
|
+
if (occurrences !== 1) throw new WorkingBlockReplaceMismatchError(label, occurrences);
|
|
107
|
+
return haystack.replace(oldUnique, newText);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
/** Run `mutator(current) => next` and persist the result. */
|
|
111
|
+
async rethink(scope, label, mutator) {
|
|
112
|
+
return this.#mutate(scope, label, async (current) => mutator(current ?? ""));
|
|
113
|
+
}
|
|
114
|
+
/** Soft-delete a block. */
|
|
115
|
+
async forget(scope, label, reason) {
|
|
116
|
+
await withMemorySpan(this.#tracer, "memory.write.working", scope, {
|
|
117
|
+
"memory.block.label": label,
|
|
118
|
+
"memory.write.working.action": "forget"
|
|
119
|
+
}, async () => {
|
|
120
|
+
await this.#store.working.delete(scope, label, reason);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Attach a working block to an additional agent. Backed by the
|
|
125
|
+
* adapter's `shared.attach(...)` join table so multi-agent crews
|
|
126
|
+
* can share the same block without duplicating storage.
|
|
127
|
+
*/
|
|
128
|
+
async attach(scope, blockId, agentId) {
|
|
129
|
+
await withMemorySpan(this.#tracer, "memory.write.working", scope, {
|
|
130
|
+
"memory.write.working.action": "attach",
|
|
131
|
+
"memory.block.id": blockId,
|
|
132
|
+
"memory.write.working.target_agent_id": agentId
|
|
133
|
+
}, async () => {
|
|
134
|
+
await this.#store.shared.attach(blockId, agentId);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
/** Detach a working block from an agent. */
|
|
138
|
+
async detach(scope, blockId, agentId) {
|
|
139
|
+
await withMemorySpan(this.#tracer, "memory.write.working", scope, {
|
|
140
|
+
"memory.write.working.action": "detach",
|
|
141
|
+
"memory.block.id": blockId,
|
|
142
|
+
"memory.write.working.target_agent_id": agentId
|
|
143
|
+
}, async () => {
|
|
144
|
+
await this.#store.shared.detach(blockId, agentId);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Render a deterministic `<memory_blocks>` XML fragment for the
|
|
149
|
+
* supplied scope. The full layered system prompt (six layers) is
|
|
150
|
+
* produced by Phase 10d's ContextEngine; this method ships the
|
|
151
|
+
* minimum-viable rendering used by the smoke acceptance criteria.
|
|
152
|
+
*
|
|
153
|
+
* The optional `agentId` argument is reserved for the per-agent
|
|
154
|
+
* filtering Phase 10d wires through. In Phase 10a the argument is
|
|
155
|
+
* accepted but ignored — the rendering is scope-wide.
|
|
156
|
+
*/
|
|
157
|
+
async compile(scope, agentId) {
|
|
158
|
+
const blocks = await this.list(scope);
|
|
159
|
+
if (blocks.length === 0) return "";
|
|
160
|
+
const lines = ["<memory_blocks>"];
|
|
161
|
+
for (const block of blocks) {
|
|
162
|
+
const description = block.description !== void 0 ? ` description="${escapeXml(block.description)}"` : "";
|
|
163
|
+
lines.push(` <block label="${escapeXml(block.label)}"${description}>`);
|
|
164
|
+
lines.push(` ${escapeXml(block.value)}`);
|
|
165
|
+
lines.push(" </block>");
|
|
166
|
+
}
|
|
167
|
+
lines.push("</memory_blocks>");
|
|
168
|
+
return lines.join("\n");
|
|
169
|
+
}
|
|
170
|
+
async #mutate(scope, label, nextValueFn) {
|
|
171
|
+
return withMemorySpan(this.#tracer, "memory.write.working", scope, { "memory.block.label": label }, async (span) => {
|
|
172
|
+
const definition = this.#requireDefinition(label);
|
|
173
|
+
if (definition.readOnly === true) throw new WorkingBlockReadOnlyError(label);
|
|
174
|
+
const existing = await this.#store.working.get(scope, label);
|
|
175
|
+
const enforcedValue = enforceCharLimit(await nextValueFn(existing?.value ?? definition.defaultValue), definition);
|
|
176
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
177
|
+
const block = {
|
|
178
|
+
id: existing?.id ?? newMemoryId("block"),
|
|
179
|
+
kind: "working",
|
|
180
|
+
userId: scope.userId,
|
|
181
|
+
...scope.sessionId !== void 0 ? { sessionId: scope.sessionId } : {},
|
|
182
|
+
...scope.agentId !== void 0 ? { agentId: scope.agentId } : {},
|
|
183
|
+
sensitivity: definition.sensitivity,
|
|
184
|
+
label,
|
|
185
|
+
...definition.description !== void 0 ? { description: definition.description } : {},
|
|
186
|
+
value: enforcedValue,
|
|
187
|
+
charLimit: definition.charLimit,
|
|
188
|
+
readOnly: definition.readOnly,
|
|
189
|
+
...definition.tags !== void 0 ? { tags: definition.tags } : {},
|
|
190
|
+
createdAt: existing?.createdAt ?? now,
|
|
191
|
+
updatedAt: now
|
|
192
|
+
};
|
|
193
|
+
await this.#store.working.upsert(scope, block);
|
|
194
|
+
span.setAttributes({
|
|
195
|
+
"memory.write.working.action": existing === null ? "create" : "update",
|
|
196
|
+
"memory.write.working.length": enforcedValue.length
|
|
197
|
+
});
|
|
198
|
+
return block;
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
#requireDefinition(label) {
|
|
202
|
+
const def = this.#defs.get(label);
|
|
203
|
+
if (def !== void 0) return def;
|
|
204
|
+
throw new TypeError(`[graphorin/memory] working block '${label}' was not defined. Call memory.working.define(blocks.define({...})) before writing to it.`);
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
function enforceCharLimit(value, definition) {
|
|
208
|
+
if (value.length <= definition.charLimit) return value;
|
|
209
|
+
if (definition.overflowPolicy === "reject") throw new WorkingBlockOverflowError(definition.label, value.length, definition.charLimit);
|
|
210
|
+
return value.slice(0, definition.charLimit);
|
|
211
|
+
}
|
|
212
|
+
function countOccurrences(haystack, needle) {
|
|
213
|
+
if (needle.length === 0) return 0;
|
|
214
|
+
let count = 0;
|
|
215
|
+
let idx = 0;
|
|
216
|
+
for (;;) {
|
|
217
|
+
const next = haystack.indexOf(needle, idx);
|
|
218
|
+
if (next === -1) return count;
|
|
219
|
+
count += 1;
|
|
220
|
+
idx = next + needle.length;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
function escapeXml(value) {
|
|
224
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
//#endregion
|
|
228
|
+
export { WorkingMemory, defineBlock };
|
|
229
|
+
//# sourceMappingURL=working-memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"working-memory.js","names":["#store","#tracer","#defs","#mutate","#requireDefinition","block: Block"],"sources":["../../src/tiers/working-memory.ts"],"sourcesContent":["import type { Block, Sensitivity, SessionScope, Tracer, ZodLikeSchema } from '@graphorin/core';\nimport {\n WorkingBlockOverflowError,\n WorkingBlockReadOnlyError,\n WorkingBlockReplaceMismatchError,\n} from '../errors/index.js';\nimport { newMemoryId } from '../internal/id.js';\nimport { withMemorySpan } from '../internal/spans.js';\nimport type { MemoryStoreAdapter } from '../internal/storage-adapter.js';\n\n/**\n * Author-time block specification accepted by\n * {@link defineBlock} and {@link WorkingMemory.define}.\n *\n * @stable\n */\nexport interface BlockSpec {\n readonly label: string;\n readonly description?: string;\n readonly schema?: ZodLikeSchema<unknown>;\n /** Maximum length of the rendered value in characters. */\n readonly charLimit: number;\n /** Default `'internal'`. */\n readonly sensitivity?: Sensitivity;\n /** Default `false`. */\n readonly readOnly?: boolean;\n /**\n * Per-block default value. Applied on first definition only; later\n * runs preserve any value already in storage.\n */\n readonly defaultValue?: string;\n /** Default `'truncate'` — `'reject'` opt-in for strict use cases. */\n readonly overflowPolicy?: 'truncate' | 'reject';\n /** Optional free-form labels surfaced through `tags`. */\n readonly tags?: ReadonlyArray<string>;\n}\n\n/**\n * Frozen block definition returned by {@link defineBlock}. Re-used by\n * the agent runtime / context engine to know which blocks should be\n * compiled into the system prompt every step.\n *\n * @stable\n */\nexport interface BlockDefinition {\n readonly label: string;\n readonly description?: string;\n readonly schema?: ZodLikeSchema<unknown>;\n readonly charLimit: number;\n readonly sensitivity: Sensitivity;\n readonly readOnly: boolean;\n readonly defaultValue?: string;\n readonly overflowPolicy: 'truncate' | 'reject';\n readonly tags?: ReadonlyArray<string>;\n}\n\n/**\n * Build a frozen {@link BlockDefinition}. Surfaced as `blocks.define(...)`\n * for ergonomic call-sites; the underlying object is the same shape\n * the {@link WorkingMemory.define} method accepts.\n *\n * @stable\n */\nexport function defineBlock(spec: BlockSpec): BlockDefinition {\n if (!spec.label || spec.label.length === 0) {\n throw new TypeError('[graphorin/memory] BlockSpec.label must be a non-empty string.');\n }\n if (!Number.isInteger(spec.charLimit) || spec.charLimit <= 0) {\n throw new TypeError(\n `[graphorin/memory] BlockSpec.charLimit must be a positive integer, got ${String(spec.charLimit)}.`,\n );\n }\n return Object.freeze({\n label: spec.label,\n ...(spec.description !== undefined ? { description: spec.description } : {}),\n ...(spec.schema !== undefined ? { schema: spec.schema } : {}),\n charLimit: spec.charLimit,\n sensitivity: spec.sensitivity ?? 'internal',\n readOnly: spec.readOnly ?? false,\n ...(spec.defaultValue !== undefined ? { defaultValue: spec.defaultValue } : {}),\n overflowPolicy: spec.overflowPolicy ?? 'truncate',\n ...(spec.tags !== undefined ? { tags: Object.freeze([...spec.tags]) } : {}),\n });\n}\n\n/**\n * `WorkingMemory` — labeled, character-bounded blocks rendered into\n * every system prompt. Operations:\n *\n * - `define(spec)`: idempotently registers a block definition; the\n * block's row is created in storage on the next `write` call so\n * operators can change `description` between runs without\n * triggering a write.\n * - `read(scope, label)` / `list(scope)`: surface the current block\n * contents.\n * - `write(scope, label, value)`: full replace.\n * - `append(scope, label, content)`: append-with-newline.\n * - `replace(scope, label, oldUnique, newText)`: targeted replace\n * with a uniqueness check.\n * - `compile(scope)`: render the active blocks for the context\n * engine (used by Phase 10d).\n *\n * @stable\n */\nexport class WorkingMemory {\n readonly #store: MemoryStoreAdapter;\n readonly #tracer: Tracer;\n readonly #defs: Map<string, BlockDefinition>;\n\n constructor(args: { store: MemoryStoreAdapter; tracer: Tracer }) {\n this.#store = args.store;\n this.#tracer = args.tracer;\n this.#defs = new Map();\n }\n\n /** Register a block definition. Returns the same definition object. */\n define(definition: BlockDefinition): BlockDefinition {\n this.#defs.set(definition.label, definition);\n return definition;\n }\n\n /** Snapshot of every registered definition. */\n definitions(): ReadonlyArray<BlockDefinition> {\n return Array.from(this.#defs.values());\n }\n\n /** Lookup a definition by label. */\n definitionFor(label: string): BlockDefinition | undefined {\n return this.#defs.get(label);\n }\n\n /** List active (non-deleted) blocks for the supplied scope. */\n async list(scope: SessionScope): Promise<ReadonlyArray<Block>> {\n return withMemorySpan(this.#tracer, 'memory.read.working', scope, {}, async (span) => {\n const out = await this.#store.working.list(scope);\n span.setAttributes({ 'memory.read.working.count': out.length });\n return out;\n });\n }\n\n /** Read a single block's value (or `null` when absent). */\n async read(scope: SessionScope, label: string): Promise<string | null> {\n return withMemorySpan(\n this.#tracer,\n 'memory.read.working',\n scope,\n { 'memory.block.label': label },\n async (span) => {\n const block = await this.#store.working.get(scope, label);\n span.setAttributes({ 'memory.read.working.found': block !== null });\n if (block !== null) return block.value;\n // MST-8: a defined-but-unwritten block answers with its declared\n // defaultValue (previously advertised, copied into the\n // definition, and then never read by anything).\n const definition = this.#defs.get(label);\n return definition?.defaultValue ?? null;\n },\n );\n }\n\n /** Replace a block's value entirely. Honours overflow policy. */\n async write(scope: SessionScope, label: string, value: string): Promise<Block> {\n return this.#mutate(scope, label, async () => value);\n }\n\n /** Append `content` to a block (with a newline separator). */\n async append(scope: SessionScope, label: string, content: string): Promise<Block> {\n return this.#mutate(scope, label, async (current) => {\n if (current === '' || current === undefined) return content;\n return `${current}\\n${content}`;\n });\n }\n\n /**\n * Replace the unique substring `oldUnique` inside the block's value\n * with `newText`. Throws `WorkingBlockReplaceMismatchError` when\n * the substring is missing or appears more than once.\n */\n async replace(\n scope: SessionScope,\n label: string,\n oldUnique: string,\n newText: string,\n ): Promise<Block> {\n return this.#mutate(scope, label, async (current) => {\n const haystack = current ?? '';\n const occurrences = countOccurrences(haystack, oldUnique);\n if (occurrences !== 1) {\n throw new WorkingBlockReplaceMismatchError(label, occurrences);\n }\n return haystack.replace(oldUnique, newText);\n });\n }\n\n /** Run `mutator(current) => next` and persist the result. */\n async rethink(\n scope: SessionScope,\n label: string,\n mutator: (current: string) => string | Promise<string>,\n ): Promise<Block> {\n return this.#mutate(scope, label, async (current) => mutator(current ?? ''));\n }\n\n /** Soft-delete a block. */\n async forget(scope: SessionScope, label: string, reason?: string): Promise<void> {\n await withMemorySpan(\n this.#tracer,\n 'memory.write.working',\n scope,\n { 'memory.block.label': label, 'memory.write.working.action': 'forget' },\n async () => {\n await this.#store.working.delete(scope, label, reason);\n },\n );\n }\n\n /**\n * Attach a working block to an additional agent. Backed by the\n * adapter's `shared.attach(...)` join table so multi-agent crews\n * can share the same block without duplicating storage.\n */\n async attach(scope: SessionScope, blockId: string, agentId: string): Promise<void> {\n await withMemorySpan(\n this.#tracer,\n 'memory.write.working',\n scope,\n {\n 'memory.write.working.action': 'attach',\n 'memory.block.id': blockId,\n 'memory.write.working.target_agent_id': agentId,\n },\n async () => {\n await this.#store.shared.attach(blockId, agentId);\n },\n );\n }\n\n /** Detach a working block from an agent. */\n async detach(scope: SessionScope, blockId: string, agentId: string): Promise<void> {\n await withMemorySpan(\n this.#tracer,\n 'memory.write.working',\n scope,\n {\n 'memory.write.working.action': 'detach',\n 'memory.block.id': blockId,\n 'memory.write.working.target_agent_id': agentId,\n },\n async () => {\n await this.#store.shared.detach(blockId, agentId);\n },\n );\n }\n\n /**\n * Render a deterministic `<memory_blocks>` XML fragment for the\n * supplied scope. The full layered system prompt (six layers) is\n * produced by Phase 10d's ContextEngine; this method ships the\n * minimum-viable rendering used by the smoke acceptance criteria.\n *\n * The optional `agentId` argument is reserved for the per-agent\n * filtering Phase 10d wires through. In Phase 10a the argument is\n * accepted but ignored — the rendering is scope-wide.\n */\n async compile(scope: SessionScope, agentId?: string): Promise<string> {\n void agentId;\n const blocks = await this.list(scope);\n if (blocks.length === 0) return '';\n const lines = ['<memory_blocks>'];\n for (const block of blocks) {\n const description =\n block.description !== undefined ? ` description=\"${escapeXml(block.description)}\"` : '';\n lines.push(` <block label=\"${escapeXml(block.label)}\"${description}>`);\n lines.push(` ${escapeXml(block.value)}`);\n lines.push(' </block>');\n }\n lines.push('</memory_blocks>');\n return lines.join('\\n');\n }\n\n async #mutate(\n scope: SessionScope,\n label: string,\n nextValueFn: (current: string | undefined) => Promise<string>,\n ): Promise<Block> {\n return withMemorySpan(\n this.#tracer,\n 'memory.write.working',\n scope,\n { 'memory.block.label': label },\n async (span) => {\n const definition = this.#requireDefinition(label);\n if (definition.readOnly === true) {\n // MRET-14: a dedicated kind — the old\n // WorkingBlockReplaceMismatchError(label, 0) read as \"substring\n // matched 0 times\" and misled replace-retry callers.\n throw new WorkingBlockReadOnlyError(label);\n }\n const existing = await this.#store.working.get(scope, label);\n // MST-8: first materialization starts from the declared default,\n // so an append/replace on an unwritten block composes with it.\n const candidate = await nextValueFn(existing?.value ?? definition.defaultValue);\n const enforcedValue = enforceCharLimit(candidate, definition);\n const now = new Date().toISOString();\n const id = existing?.id ?? newMemoryId('block');\n const block: Block = {\n id,\n kind: 'working',\n userId: scope.userId,\n ...(scope.sessionId !== undefined ? { sessionId: scope.sessionId } : {}),\n ...(scope.agentId !== undefined ? { agentId: scope.agentId } : {}),\n sensitivity: definition.sensitivity,\n label,\n ...(definition.description !== undefined ? { description: definition.description } : {}),\n value: enforcedValue,\n charLimit: definition.charLimit,\n readOnly: definition.readOnly,\n ...(definition.tags !== undefined ? { tags: definition.tags } : {}),\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n };\n await this.#store.working.upsert(scope, block);\n span.setAttributes({\n 'memory.write.working.action': existing === null ? 'create' : 'update',\n 'memory.write.working.length': enforcedValue.length,\n });\n return block;\n },\n );\n }\n\n #requireDefinition(label: string): BlockDefinition {\n const def = this.#defs.get(label);\n if (def !== undefined) return def;\n throw new TypeError(\n `[graphorin/memory] working block '${label}' was not defined. ` +\n 'Call memory.working.define(blocks.define({...})) before writing to it.',\n );\n }\n}\n\nfunction enforceCharLimit(value: string, definition: BlockDefinition): string {\n if (value.length <= definition.charLimit) return value;\n if (definition.overflowPolicy === 'reject') {\n throw new WorkingBlockOverflowError(definition.label, value.length, definition.charLimit);\n }\n return value.slice(0, definition.charLimit);\n}\n\nfunction countOccurrences(haystack: string, needle: string): number {\n if (needle.length === 0) return 0;\n let count = 0;\n let idx = 0;\n for (;;) {\n const next = haystack.indexOf(needle, idx);\n if (next === -1) return count;\n count += 1;\n idx = next + needle.length;\n }\n}\n\nfunction escapeXml(value: string): string {\n return value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { MemoryToolDeps } from "./types.js";
|
|
2
|
+
import { Tool } from "@graphorin/core";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
//#region src/tools/block-tools.d.ts
|
|
6
|
+
declare const blockAppendInputSchema: z.ZodObject<{
|
|
7
|
+
label: z.ZodString;
|
|
8
|
+
content: z.ZodString;
|
|
9
|
+
}, "strip", z.ZodTypeAny, {
|
|
10
|
+
label: string;
|
|
11
|
+
content: string;
|
|
12
|
+
}, {
|
|
13
|
+
label: string;
|
|
14
|
+
content: string;
|
|
15
|
+
}>;
|
|
16
|
+
declare const blockAppendOutputSchema: z.ZodObject<{
|
|
17
|
+
label: z.ZodString;
|
|
18
|
+
length: z.ZodNumber;
|
|
19
|
+
}, "strip", z.ZodTypeAny, {
|
|
20
|
+
length: number;
|
|
21
|
+
label: string;
|
|
22
|
+
}, {
|
|
23
|
+
length: number;
|
|
24
|
+
label: string;
|
|
25
|
+
}>;
|
|
26
|
+
type BlockAppendInput = z.infer<typeof blockAppendInputSchema>;
|
|
27
|
+
type BlockAppendOutput = z.infer<typeof blockAppendOutputSchema>;
|
|
28
|
+
declare const blockReplaceInputSchema: z.ZodObject<{
|
|
29
|
+
label: z.ZodString;
|
|
30
|
+
oldUnique: z.ZodString;
|
|
31
|
+
newText: z.ZodString;
|
|
32
|
+
}, "strip", z.ZodTypeAny, {
|
|
33
|
+
label: string;
|
|
34
|
+
oldUnique: string;
|
|
35
|
+
newText: string;
|
|
36
|
+
}, {
|
|
37
|
+
label: string;
|
|
38
|
+
oldUnique: string;
|
|
39
|
+
newText: string;
|
|
40
|
+
}>;
|
|
41
|
+
declare const blockReplaceOutputSchema: z.ZodObject<{
|
|
42
|
+
label: z.ZodString;
|
|
43
|
+
length: z.ZodNumber;
|
|
44
|
+
}, "strip", z.ZodTypeAny, {
|
|
45
|
+
length: number;
|
|
46
|
+
label: string;
|
|
47
|
+
}, {
|
|
48
|
+
length: number;
|
|
49
|
+
label: string;
|
|
50
|
+
}>;
|
|
51
|
+
type BlockReplaceInput = z.infer<typeof blockReplaceInputSchema>;
|
|
52
|
+
type BlockReplaceOutput = z.infer<typeof blockReplaceOutputSchema>;
|
|
53
|
+
declare const blockRethinkInputSchema: z.ZodObject<{
|
|
54
|
+
label: z.ZodString;
|
|
55
|
+
newValue: z.ZodString;
|
|
56
|
+
}, "strip", z.ZodTypeAny, {
|
|
57
|
+
label: string;
|
|
58
|
+
newValue: string;
|
|
59
|
+
}, {
|
|
60
|
+
label: string;
|
|
61
|
+
newValue: string;
|
|
62
|
+
}>;
|
|
63
|
+
declare const blockRethinkOutputSchema: z.ZodObject<{
|
|
64
|
+
label: z.ZodString;
|
|
65
|
+
length: z.ZodNumber;
|
|
66
|
+
}, "strip", z.ZodTypeAny, {
|
|
67
|
+
length: number;
|
|
68
|
+
label: string;
|
|
69
|
+
}, {
|
|
70
|
+
length: number;
|
|
71
|
+
label: string;
|
|
72
|
+
}>;
|
|
73
|
+
type BlockRethinkInput = z.infer<typeof blockRethinkInputSchema>;
|
|
74
|
+
type BlockRethinkOutput = z.infer<typeof blockRethinkOutputSchema>;
|
|
75
|
+
/**
|
|
76
|
+
* `block_append` — append text (with a newline separator) to a working
|
|
77
|
+
* memory block.
|
|
78
|
+
*
|
|
79
|
+
* @stable
|
|
80
|
+
*/
|
|
81
|
+
declare function createBlockAppendTool(deps: MemoryToolDeps): Tool<BlockAppendInput, BlockAppendOutput>;
|
|
82
|
+
/**
|
|
83
|
+
* `block_replace` — replace a unique substring inside a working
|
|
84
|
+
* memory block. Throws when the substring is missing or appears more
|
|
85
|
+
* than once.
|
|
86
|
+
*
|
|
87
|
+
* @stable
|
|
88
|
+
*/
|
|
89
|
+
declare function createBlockReplaceTool(deps: MemoryToolDeps): Tool<BlockReplaceInput, BlockReplaceOutput>;
|
|
90
|
+
/**
|
|
91
|
+
* `block_rethink` — rewrite a working memory block from scratch.
|
|
92
|
+
*
|
|
93
|
+
* @stable
|
|
94
|
+
*/
|
|
95
|
+
declare function createBlockRethinkTool(deps: MemoryToolDeps): Tool<BlockRethinkInput, BlockRethinkOutput>;
|
|
96
|
+
//#endregion
|
|
97
|
+
export { createBlockAppendTool, createBlockReplaceTool, createBlockRethinkTool };
|
|
98
|
+
//# sourceMappingURL=block-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block-tools.d.ts","names":[],"sources":["../../src/tools/block-tools.ts"],"sourcesContent":[],"mappings":";;;;;cAKM,wBAAsB,CAAA,CAAA;;EAAtB,OAAA,aAAA;;;;CAAsB,EAAA;EAAA,KAAA,EAAA,MAAA;EAItB,OAAA,EAAA,MAAA;;cAAA,yBAAuB,CAAA,CAAA;;EAAA,MAAA,aAAA;CAAA,EAAA,OAAA,cAAA,EAAA;EAKxB,MAAA,EAAA,MAAA;EACA,KAAA,EAAA,MAAA;AAA2B,CAAA,EAAA;;;;KAD3B,gBAAA,GAAmB,CAAA,CAAE,aAAa;KAClC,iBAAA,GAAoB,CAAA,CAAE,KAEE,CAAA,OAFW,uBAEX,CAAA;cAAvB,uBAAuB,EAAA,CAAA,CAAA,SAAA,CAAA;EAKvB,KAAA,aAAA;;;;EAAwB,KAAA,EAAA,MAAA;EAAA,SAAA,EAAA,MAAA;EAKzB,OAAA,EAAA,MAAA;AAA2B,CAAA,EAAA;EAG1B,KAAA,EAAA,MAAA;;;;cARA,wBAQuB,EARC,CAAA,CAAA,SAQD,CAAA;EAAA,KAAA,aAAA;EAIvB,MAAA,aAAA;;;;CAAwB,EAAA;EAAA,MAAA,EAAA,MAAA;EAKzB,KAAA,EAAA,MAAA;AAA2B,CAAA,CAAA;AAShC,KArBK,iBAAA,GAAoB,CAAA,CAAE,KAqBU,CAAA,OArBG,uBAqBH,CAAA;KApBhC,kBAAA,GAAqB,CAAA,CAAE,KAqBpB,CAAA,OArBiC,wBAqBjC,CAAA;cAnBF,uBAoBE,EApBqB,CAAA,CAAA,SAoBrB,CAAA;EAAkB,KAAA,aAAA;EAAvB,QAAA,aAAA;CAAI,EAAA,OAAA,cAAA,EAAA;EA2BS,KAAA,EAAA,MAAA;EACR,QAAA,EAAA,MAAA;CACA,EAAA;EAAmB,KAAA,EAAA,MAAA;EAAxB,QAAA,EAAA,MAAA;CAAI,CAAA;AAyBP,cAtEM,wBAsEgC,EAtER,CAAA,CAAA,SAsEQ,CAAA;EAC9B,KAAA,aAAA;EACA,MAAA,aAAA;CAAmB,EAAA,OAAA,cAAA,EAAA;EAAxB,MAAA,EAAA,MAAA;EAAI,KAAA,EAAA,MAAA;;;;;KAnEF,iBAAA,GAAoB,CAAA,CAAE,aAAa;KACnC,kBAAA,GAAqB,CAAA,CAAE,aAAa;;;;;;;iBAQzB,qBAAA,OACR,iBACL,KAAK,kBAAkB;;;;;;;;iBA2BV,sBAAA,OACR,iBACL,KAAK,mBAAmB;;;;;;iBAyBX,sBAAA,OACR,iBACL,KAAK,mBAAmB"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { tool } from "@graphorin/tools";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/tools/block-tools.ts
|
|
5
|
+
const blockAppendInputSchema = z.object({
|
|
6
|
+
label: z.string().min(1).max(128),
|
|
7
|
+
content: z.string().min(1)
|
|
8
|
+
});
|
|
9
|
+
const blockAppendOutputSchema = z.object({
|
|
10
|
+
label: z.string(),
|
|
11
|
+
length: z.number()
|
|
12
|
+
});
|
|
13
|
+
const blockReplaceInputSchema = z.object({
|
|
14
|
+
label: z.string().min(1).max(128),
|
|
15
|
+
oldUnique: z.string().min(1),
|
|
16
|
+
newText: z.string()
|
|
17
|
+
});
|
|
18
|
+
const blockReplaceOutputSchema = z.object({
|
|
19
|
+
label: z.string(),
|
|
20
|
+
length: z.number()
|
|
21
|
+
});
|
|
22
|
+
const blockRethinkInputSchema = z.object({
|
|
23
|
+
label: z.string().min(1).max(128),
|
|
24
|
+
newValue: z.string()
|
|
25
|
+
});
|
|
26
|
+
const blockRethinkOutputSchema = z.object({
|
|
27
|
+
label: z.string(),
|
|
28
|
+
length: z.number()
|
|
29
|
+
});
|
|
30
|
+
/**
|
|
31
|
+
* `block_append` — append text (with a newline separator) to a working
|
|
32
|
+
* memory block.
|
|
33
|
+
*
|
|
34
|
+
* @stable
|
|
35
|
+
*/
|
|
36
|
+
function createBlockAppendTool(deps) {
|
|
37
|
+
return tool({
|
|
38
|
+
name: "block_append",
|
|
39
|
+
description: "Append text to a working memory block. The block is identified by its label (registered via memory.working.define(...)). Use this when accumulating notes, observations, or reasoning steps that should persist across turns.",
|
|
40
|
+
inputSchema: blockAppendInputSchema,
|
|
41
|
+
outputSchema: blockAppendOutputSchema,
|
|
42
|
+
sideEffectClass: "side-effecting",
|
|
43
|
+
sandboxPolicy: "none",
|
|
44
|
+
sensitivity: "internal",
|
|
45
|
+
memoryGuardTier: "memory-aware",
|
|
46
|
+
tags: ["memory", "working"],
|
|
47
|
+
async execute(input, ctx) {
|
|
48
|
+
const scope = await deps.resolveScope(ctx);
|
|
49
|
+
const block = await deps.working.append(scope, input.label, input.content);
|
|
50
|
+
return {
|
|
51
|
+
label: block.label,
|
|
52
|
+
length: block.value.length
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* `block_replace` — replace a unique substring inside a working
|
|
59
|
+
* memory block. Throws when the substring is missing or appears more
|
|
60
|
+
* than once.
|
|
61
|
+
*
|
|
62
|
+
* @stable
|
|
63
|
+
*/
|
|
64
|
+
function createBlockReplaceTool(deps) {
|
|
65
|
+
return tool({
|
|
66
|
+
name: "block_replace",
|
|
67
|
+
description: "Replace a UNIQUE substring inside a working memory block. The substring must appear exactly once; the call fails fast if missing or non-unique. Use block_rethink for full rewrites.",
|
|
68
|
+
inputSchema: blockReplaceInputSchema,
|
|
69
|
+
outputSchema: blockReplaceOutputSchema,
|
|
70
|
+
sideEffectClass: "side-effecting",
|
|
71
|
+
sandboxPolicy: "none",
|
|
72
|
+
sensitivity: "internal",
|
|
73
|
+
memoryGuardTier: "memory-aware",
|
|
74
|
+
tags: ["memory", "working"],
|
|
75
|
+
async execute(input, ctx) {
|
|
76
|
+
const scope = await deps.resolveScope(ctx);
|
|
77
|
+
const block = await deps.working.replace(scope, input.label, input.oldUnique, input.newText);
|
|
78
|
+
return {
|
|
79
|
+
label: block.label,
|
|
80
|
+
length: block.value.length
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* `block_rethink` — rewrite a working memory block from scratch.
|
|
87
|
+
*
|
|
88
|
+
* @stable
|
|
89
|
+
*/
|
|
90
|
+
function createBlockRethinkTool(deps) {
|
|
91
|
+
return tool({
|
|
92
|
+
name: "block_rethink",
|
|
93
|
+
description: "Replace a working memory block's value entirely. Use this when restructuring or summarising the block's contents. For surgical edits, prefer block_replace.",
|
|
94
|
+
inputSchema: blockRethinkInputSchema,
|
|
95
|
+
outputSchema: blockRethinkOutputSchema,
|
|
96
|
+
sideEffectClass: "side-effecting",
|
|
97
|
+
sandboxPolicy: "none",
|
|
98
|
+
sensitivity: "internal",
|
|
99
|
+
memoryGuardTier: "memory-aware",
|
|
100
|
+
tags: ["memory", "working"],
|
|
101
|
+
async execute(input, ctx) {
|
|
102
|
+
const scope = await deps.resolveScope(ctx);
|
|
103
|
+
const block = await deps.working.rethink(scope, input.label, () => input.newValue);
|
|
104
|
+
return {
|
|
105
|
+
label: block.label,
|
|
106
|
+
length: block.value.length
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
//#endregion
|
|
113
|
+
export { createBlockAppendTool, createBlockReplaceTool, createBlockRethinkTool };
|
|
114
|
+
//# sourceMappingURL=block-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block-tools.js","names":[],"sources":["../../src/tools/block-tools.ts"],"sourcesContent":["import type { Tool } from '@graphorin/core';\nimport { tool } from '@graphorin/tools';\nimport { z } from 'zod';\nimport type { MemoryToolDeps } from './types.js';\n\nconst blockAppendInputSchema = z.object({\n label: z.string().min(1).max(128),\n content: z.string().min(1),\n});\nconst blockAppendOutputSchema = z.object({\n label: z.string(),\n length: z.number(),\n});\n\ntype BlockAppendInput = z.infer<typeof blockAppendInputSchema>;\ntype BlockAppendOutput = z.infer<typeof blockAppendOutputSchema>;\n\nconst blockReplaceInputSchema = z.object({\n label: z.string().min(1).max(128),\n oldUnique: z.string().min(1),\n newText: z.string(),\n});\nconst blockReplaceOutputSchema = z.object({\n label: z.string(),\n length: z.number(),\n});\n\ntype BlockReplaceInput = z.infer<typeof blockReplaceInputSchema>;\ntype BlockReplaceOutput = z.infer<typeof blockReplaceOutputSchema>;\n\nconst blockRethinkInputSchema = z.object({\n label: z.string().min(1).max(128),\n newValue: z.string(),\n});\nconst blockRethinkOutputSchema = z.object({\n label: z.string(),\n length: z.number(),\n});\n\ntype BlockRethinkInput = z.infer<typeof blockRethinkInputSchema>;\ntype BlockRethinkOutput = z.infer<typeof blockRethinkOutputSchema>;\n\n/**\n * `block_append` — append text (with a newline separator) to a working\n * memory block.\n *\n * @stable\n */\nexport function createBlockAppendTool(\n deps: MemoryToolDeps,\n): Tool<BlockAppendInput, BlockAppendOutput> {\n return tool<BlockAppendInput, BlockAppendOutput>({\n name: 'block_append',\n description:\n 'Append text to a working memory block. The block is identified by its label (registered via memory.working.define(...)). Use this when accumulating notes, observations, or reasoning steps that should persist across turns.',\n inputSchema: blockAppendInputSchema,\n outputSchema: blockAppendOutputSchema,\n sideEffectClass: 'side-effecting',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'memory-aware',\n tags: ['memory', 'working'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n const block = await deps.working.append(scope, input.label, input.content);\n return { label: block.label, length: block.value.length };\n },\n });\n}\n\n/**\n * `block_replace` — replace a unique substring inside a working\n * memory block. Throws when the substring is missing or appears more\n * than once.\n *\n * @stable\n */\nexport function createBlockReplaceTool(\n deps: MemoryToolDeps,\n): Tool<BlockReplaceInput, BlockReplaceOutput> {\n return tool<BlockReplaceInput, BlockReplaceOutput>({\n name: 'block_replace',\n description:\n 'Replace a UNIQUE substring inside a working memory block. The substring must appear exactly once; the call fails fast if missing or non-unique. Use block_rethink for full rewrites.',\n inputSchema: blockReplaceInputSchema,\n outputSchema: blockReplaceOutputSchema,\n sideEffectClass: 'side-effecting',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'memory-aware',\n tags: ['memory', 'working'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n const block = await deps.working.replace(scope, input.label, input.oldUnique, input.newText);\n return { label: block.label, length: block.value.length };\n },\n });\n}\n\n/**\n * `block_rethink` — rewrite a working memory block from scratch.\n *\n * @stable\n */\nexport function createBlockRethinkTool(\n deps: MemoryToolDeps,\n): Tool<BlockRethinkInput, BlockRethinkOutput> {\n return tool<BlockRethinkInput, BlockRethinkOutput>({\n name: 'block_rethink',\n description:\n \"Replace a working memory block's value entirely. Use this when restructuring or summarising the block's contents. For surgical edits, prefer block_replace.\",\n inputSchema: blockRethinkInputSchema,\n outputSchema: blockRethinkOutputSchema,\n sideEffectClass: 'side-effecting',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'memory-aware',\n tags: ['memory', 'working'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n const block = await deps.working.rethink(scope, input.label, () => input.newValue);\n return { label: block.label, length: block.value.length };\n },\n });\n}\n"],"mappings":";;;;AAKA,MAAM,yBAAyB,EAAE,OAAO;CACtC,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI;CACjC,SAAS,EAAE,QAAQ,CAAC,IAAI,EAAE;CAC3B,CAAC;AACF,MAAM,0BAA0B,EAAE,OAAO;CACvC,OAAO,EAAE,QAAQ;CACjB,QAAQ,EAAE,QAAQ;CACnB,CAAC;AAKF,MAAM,0BAA0B,EAAE,OAAO;CACvC,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI;CACjC,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE;CAC5B,SAAS,EAAE,QAAQ;CACpB,CAAC;AACF,MAAM,2BAA2B,EAAE,OAAO;CACxC,OAAO,EAAE,QAAQ;CACjB,QAAQ,EAAE,QAAQ;CACnB,CAAC;AAKF,MAAM,0BAA0B,EAAE,OAAO;CACvC,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI;CACjC,UAAU,EAAE,QAAQ;CACrB,CAAC;AACF,MAAM,2BAA2B,EAAE,OAAO;CACxC,OAAO,EAAE,QAAQ;CACjB,QAAQ,EAAE,QAAQ;CACnB,CAAC;;;;;;;AAWF,SAAgB,sBACd,MAC2C;AAC3C,QAAO,KAA0C;EAC/C,MAAM;EACN,aACE;EACF,aAAa;EACb,cAAc;EACd,iBAAiB;EACjB,eAAe;EACf,aAAa;EACb,iBAAiB;EACjB,MAAM,CAAC,UAAU,UAAU;EAC3B,MAAM,QAAQ,OAAO,KAAK;GACxB,MAAM,QAAQ,MAAM,KAAK,aAAa,IAAI;GAC1C,MAAM,QAAQ,MAAM,KAAK,QAAQ,OAAO,OAAO,MAAM,OAAO,MAAM,QAAQ;AAC1E,UAAO;IAAE,OAAO,MAAM;IAAO,QAAQ,MAAM,MAAM;IAAQ;;EAE5D,CAAC;;;;;;;;;AAUJ,SAAgB,uBACd,MAC6C;AAC7C,QAAO,KAA4C;EACjD,MAAM;EACN,aACE;EACF,aAAa;EACb,cAAc;EACd,iBAAiB;EACjB,eAAe;EACf,aAAa;EACb,iBAAiB;EACjB,MAAM,CAAC,UAAU,UAAU;EAC3B,MAAM,QAAQ,OAAO,KAAK;GACxB,MAAM,QAAQ,MAAM,KAAK,aAAa,IAAI;GAC1C,MAAM,QAAQ,MAAM,KAAK,QAAQ,QAAQ,OAAO,MAAM,OAAO,MAAM,WAAW,MAAM,QAAQ;AAC5F,UAAO;IAAE,OAAO,MAAM;IAAO,QAAQ,MAAM,MAAM;IAAQ;;EAE5D,CAAC;;;;;;;AAQJ,SAAgB,uBACd,MAC6C;AAC7C,QAAO,KAA4C;EACjD,MAAM;EACN,aACE;EACF,aAAa;EACb,cAAc;EACd,iBAAiB;EACjB,eAAe;EACf,aAAa;EACb,iBAAiB;EACjB,MAAM,CAAC,UAAU,UAAU;EAC3B,MAAM,QAAQ,OAAO,KAAK;GACxB,MAAM,QAAQ,MAAM,KAAK,aAAa,IAAI;GAC1C,MAAM,QAAQ,MAAM,KAAK,QAAQ,QAAQ,OAAO,MAAM,aAAa,MAAM,SAAS;AAClF,UAAO;IAAE,OAAO,MAAM;IAAO,QAAQ,MAAM,MAAM;IAAQ;;EAE5D,CAAC"}
|