@adonis-agora/agent 0.30.2 → 0.33.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 +866 -0
- package/dist/assets/spa/assets/{index-Cfi3g3b2.js → index-3Q2m5_Ax.js} +1 -1
- package/dist/assets/spa/index.html +1 -1
- package/dist/providers/agent_provider.d.ts.map +1 -1
- package/dist/providers/agent_provider.js +157 -9
- package/dist/providers/agent_provider.js.map +1 -1
- package/dist/src/agent-deps-factory.d.ts +16 -2
- package/dist/src/agent-deps-factory.d.ts.map +1 -1
- package/dist/src/agent-deps-factory.js +8 -0
- package/dist/src/agent-deps-factory.js.map +1 -1
- package/dist/src/agent-deps.d.ts +21 -1
- package/dist/src/agent-deps.d.ts.map +1 -1
- package/dist/src/agent-deps.js.map +1 -1
- package/dist/src/agent-loop.d.ts +226 -9
- package/dist/src/agent-loop.d.ts.map +1 -1
- package/dist/src/agent-loop.js +1311 -208
- package/dist/src/agent-loop.js.map +1 -1
- package/dist/src/agent-service.d.ts +27 -0
- package/dist/src/agent-service.d.ts.map +1 -1
- package/dist/src/agent-service.js +29 -0
- package/dist/src/agent-service.js.map +1 -1
- package/dist/src/ai-sdk/ai-sdk-model.d.ts.map +1 -1
- package/dist/src/ai-sdk/ai-sdk-model.js +21 -1
- package/dist/src/ai-sdk/ai-sdk-model.js.map +1 -1
- package/dist/src/client/sse.d.ts +32 -2
- package/dist/src/client/sse.d.ts.map +1 -1
- package/dist/src/client/sse.js +45 -2
- package/dist/src/client/sse.js.map +1 -1
- package/dist/src/define_config.d.ts +41 -7
- package/dist/src/define_config.d.ts.map +1 -1
- package/dist/src/define_config.js.map +1 -1
- package/dist/src/durable/agent-run-workflow.d.ts +10 -11
- package/dist/src/durable/agent-run-workflow.d.ts.map +1 -1
- package/dist/src/durable/agent-run-workflow.js +49 -21
- package/dist/src/durable/agent-run-workflow.js.map +1 -1
- package/dist/src/durable/durable-agent-runner.d.ts +3 -2
- package/dist/src/durable/durable-agent-runner.d.ts.map +1 -1
- package/dist/src/durable/durable-agent-runner.js +2 -2
- package/dist/src/durable/durable-agent-runner.js.map +1 -1
- package/dist/src/elicitation.d.ts +207 -0
- package/dist/src/elicitation.d.ts.map +1 -0
- package/dist/src/elicitation.js +315 -0
- package/dist/src/elicitation.js.map +1 -0
- package/dist/src/evals/approval-prior.d.ts +58 -0
- package/dist/src/evals/approval-prior.d.ts.map +1 -0
- package/dist/src/evals/approval-prior.js +82 -0
- package/dist/src/evals/approval-prior.js.map +1 -0
- package/dist/src/evals/evaluate.d.ts +51 -0
- package/dist/src/evals/evaluate.d.ts.map +1 -0
- package/dist/src/evals/evaluate.js +76 -0
- package/dist/src/evals/evaluate.js.map +1 -0
- package/dist/src/evals/governance-sample-source.d.ts +23 -0
- package/dist/src/evals/governance-sample-source.d.ts.map +1 -0
- package/dist/src/evals/governance-sample-source.js +93 -0
- package/dist/src/evals/governance-sample-source.js.map +1 -0
- package/dist/src/evals/in-memory-score-store.d.ts +16 -0
- package/dist/src/evals/in-memory-score-store.d.ts.map +1 -0
- package/dist/src/evals/in-memory-score-store.js +57 -0
- package/dist/src/evals/in-memory-score-store.js.map +1 -0
- package/dist/src/evals/index.d.ts +15 -0
- package/dist/src/evals/index.d.ts.map +1 -0
- package/dist/src/evals/index.js +14 -0
- package/dist/src/evals/index.js.map +1 -0
- package/dist/src/evals/judge.d.ts +30 -0
- package/dist/src/evals/judge.d.ts.map +1 -0
- package/dist/src/evals/judge.js +53 -0
- package/dist/src/evals/judge.js.map +1 -0
- package/dist/src/evals/live-scoring.d.ts +42 -0
- package/dist/src/evals/live-scoring.d.ts.map +1 -0
- package/dist/src/evals/live-scoring.js +103 -0
- package/dist/src/evals/live-scoring.js.map +1 -0
- package/dist/src/evals/sample-source.d.ts +40 -0
- package/dist/src/evals/sample-source.d.ts.map +1 -0
- package/dist/src/evals/sample-source.js +33 -0
- package/dist/src/evals/sample-source.js.map +1 -0
- package/dist/src/evals/score-store.d.ts +54 -0
- package/dist/src/evals/score-store.d.ts.map +1 -0
- package/dist/src/evals/score-store.js +2 -0
- package/dist/src/evals/score-store.js.map +1 -0
- package/dist/src/evals/scorers/answer-relevancy.scorer.d.ts +28 -0
- package/dist/src/evals/scorers/answer-relevancy.scorer.d.ts.map +1 -0
- package/dist/src/evals/scorers/answer-relevancy.scorer.js +42 -0
- package/dist/src/evals/scorers/answer-relevancy.scorer.js.map +1 -0
- package/dist/src/evals/scorers/approval-outcome.scorer.d.ts +22 -0
- package/dist/src/evals/scorers/approval-outcome.scorer.d.ts.map +1 -0
- package/dist/src/evals/scorers/approval-outcome.scorer.js +60 -0
- package/dist/src/evals/scorers/approval-outcome.scorer.js.map +1 -0
- package/dist/src/evals/scorers/approval-risk.scorer.d.ts +28 -0
- package/dist/src/evals/scorers/approval-risk.scorer.d.ts.map +1 -0
- package/dist/src/evals/scorers/approval-risk.scorer.js +54 -0
- package/dist/src/evals/scorers/approval-risk.scorer.js.map +1 -0
- package/dist/src/evals/scorers/run-completion.scorer.d.ts +18 -0
- package/dist/src/evals/scorers/run-completion.scorer.d.ts.map +1 -0
- package/dist/src/evals/scorers/run-completion.scorer.js +55 -0
- package/dist/src/evals/scorers/run-completion.scorer.js.map +1 -0
- package/dist/src/evals/summarize.d.ts +44 -0
- package/dist/src/evals/summarize.d.ts.map +1 -0
- package/dist/src/evals/summarize.js +87 -0
- package/dist/src/evals/summarize.js.map +1 -0
- package/dist/src/evals/types.d.ts +81 -0
- package/dist/src/evals/types.d.ts.map +1 -0
- package/dist/src/evals/types.js +15 -0
- package/dist/src/evals/types.js.map +1 -0
- package/dist/src/history-window.d.ts +50 -11
- package/dist/src/history-window.d.ts.map +1 -1
- package/dist/src/history-window.js +84 -12
- package/dist/src/history-window.js.map +1 -1
- package/dist/src/index.d.ts +11 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +10 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/server.d.ts +8 -0
- package/dist/src/mcp/server.d.ts.map +1 -1
- package/dist/src/mcp/server.js +27 -1
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/mcp-client/importer.d.ts +75 -0
- package/dist/src/mcp-client/importer.d.ts.map +1 -0
- package/dist/src/mcp-client/importer.js +161 -0
- package/dist/src/mcp-client/importer.js.map +1 -0
- package/dist/src/mcp-client/index.d.ts +9 -0
- package/dist/src/mcp-client/index.d.ts.map +1 -0
- package/dist/src/mcp-client/index.js +8 -0
- package/dist/src/mcp-client/index.js.map +1 -0
- package/dist/src/mcp-client/options.d.ts +99 -0
- package/dist/src/mcp-client/options.d.ts.map +1 -0
- package/dist/src/mcp-client/options.js +2 -0
- package/dist/src/mcp-client/options.js.map +1 -0
- package/dist/src/mcp-client/tool-input.d.ts +39 -0
- package/dist/src/mcp-client/tool-input.d.ts.map +1 -0
- package/dist/src/mcp-client/tool-input.js +61 -0
- package/dist/src/mcp-client/tool-input.js.map +1 -0
- package/dist/src/mcp-client/tool-kind.d.ts +37 -0
- package/dist/src/mcp-client/tool-kind.d.ts.map +1 -0
- package/dist/src/mcp-client/tool-kind.js +20 -0
- package/dist/src/mcp-client/tool-kind.js.map +1 -0
- package/dist/src/mcp-client/tool-name.d.ts +22 -0
- package/dist/src/mcp-client/tool-name.d.ts.map +1 -0
- package/dist/src/mcp-client/tool-name.js +35 -0
- package/dist/src/mcp-client/tool-name.js.map +1 -0
- package/dist/src/mcp-client/tool-source.d.ts +75 -0
- package/dist/src/mcp-client/tool-source.d.ts.map +1 -0
- package/dist/src/mcp-client/tool-source.js +244 -0
- package/dist/src/mcp-client/tool-source.js.map +1 -0
- package/dist/src/mcp-client/transient.d.ts +28 -0
- package/dist/src/mcp-client/transient.d.ts.map +1 -0
- package/dist/src/mcp-client/transient.js +126 -0
- package/dist/src/mcp-client/transient.js.map +1 -0
- package/dist/src/mcp-client/unsafe-regex.d.ts +23 -0
- package/dist/src/mcp-client/unsafe-regex.d.ts.map +1 -0
- package/dist/src/mcp-client/unsafe-regex.js +194 -0
- package/dist/src/mcp-client/unsafe-regex.js.map +1 -0
- package/dist/src/memory.d.ts +448 -0
- package/dist/src/memory.d.ts.map +1 -0
- package/dist/src/memory.js +330 -0
- package/dist/src/memory.js.map +1 -0
- package/dist/src/pagination.d.ts +63 -0
- package/dist/src/pagination.d.ts.map +1 -0
- package/dist/src/pagination.js +16 -0
- package/dist/src/pagination.js.map +1 -0
- package/dist/src/processors.d.ts +134 -0
- package/dist/src/processors.d.ts.map +1 -0
- package/dist/src/processors.js +215 -0
- package/dist/src/processors.js.map +1 -0
- package/dist/src/rag/qdrant-store.d.ts +48 -6
- package/dist/src/rag/qdrant-store.d.ts.map +1 -1
- package/dist/src/rag/qdrant-store.js +77 -24
- package/dist/src/rag/qdrant-store.js.map +1 -1
- package/dist/src/replay-integrity.d.ts +17 -0
- package/dist/src/replay-integrity.d.ts.map +1 -0
- package/dist/src/replay-integrity.js +19 -0
- package/dist/src/replay-integrity.js.map +1 -0
- package/dist/src/runners/inline-agent-runner.d.ts +33 -7
- package/dist/src/runners/inline-agent-runner.d.ts.map +1 -1
- package/dist/src/runners/inline-agent-runner.js +113 -27
- package/dist/src/runners/inline-agent-runner.js.map +1 -1
- package/dist/src/skills.d.ts +291 -0
- package/dist/src/skills.d.ts.map +1 -0
- package/dist/src/skills.js +0 -0
- package/dist/src/skills.js.map +1 -0
- package/dist/src/spi/agent-runner.d.ts +20 -6
- package/dist/src/spi/agent-runner.d.ts.map +1 -1
- package/dist/src/spi/agent-store.d.ts +53 -0
- package/dist/src/spi/agent-store.d.ts.map +1 -1
- package/dist/src/spi/governance-queries.d.ts +33 -13
- package/dist/src/spi/governance-queries.d.ts.map +1 -1
- package/dist/src/spi/history-window.d.ts +64 -10
- package/dist/src/spi/history-window.d.ts.map +1 -1
- package/dist/src/spi/model-provider.d.ts +18 -0
- package/dist/src/spi/model-provider.d.ts.map +1 -1
- package/dist/src/spi/processors.d.ts +161 -0
- package/dist/src/spi/processors.d.ts.map +1 -0
- package/dist/src/spi/processors.js +57 -0
- package/dist/src/spi/processors.js.map +1 -0
- package/dist/src/spi/token-stream-sink.d.ts +43 -0
- package/dist/src/spi/token-stream-sink.d.ts.map +1 -1
- package/dist/src/spi/token-stream-sink.js +17 -1
- package/dist/src/spi/token-stream-sink.js.map +1 -1
- package/dist/src/sse.d.ts +5 -2
- package/dist/src/sse.d.ts.map +1 -1
- package/dist/src/sse.js +11 -2
- package/dist/src/sse.js.map +1 -1
- package/dist/src/stores/lucid-governance-queries.d.ts +5 -2
- package/dist/src/stores/lucid-governance-queries.d.ts.map +1 -1
- package/dist/src/stores/lucid-governance-queries.js +14 -5
- package/dist/src/stores/lucid-governance-queries.js.map +1 -1
- package/dist/src/stores/lucid-schema.d.ts.map +1 -1
- package/dist/src/stores/lucid-schema.js +15 -0
- package/dist/src/stores/lucid-schema.js.map +1 -1
- package/dist/src/stores/lucid.d.ts +11 -3
- package/dist/src/stores/lucid.d.ts.map +1 -1
- package/dist/src/stores/lucid.js +65 -0
- package/dist/src/stores/lucid.js.map +1 -1
- package/dist/src/structured-output.d.ts +57 -0
- package/dist/src/structured-output.d.ts.map +1 -0
- package/dist/src/structured-output.js +80 -0
- package/dist/src/structured-output.js.map +1 -0
- package/dist/src/telescope/agent-governance-providers.js +2 -2
- package/dist/src/telescope/agent-governance-providers.js.map +1 -1
- package/dist/src/testing/fake-model-provider.d.ts +8 -4
- package/dist/src/testing/fake-model-provider.d.ts.map +1 -1
- package/dist/src/testing/fake-model-provider.js +6 -9
- package/dist/src/testing/fake-model-provider.js.map +1 -1
- package/dist/src/testing/in-memory-governance-queries.d.ts.map +1 -1
- package/dist/src/testing/in-memory-governance-queries.js +8 -3
- package/dist/src/testing/in-memory-governance-queries.js.map +1 -1
- package/dist/src/testing/in-memory-store.d.ts +4 -3
- package/dist/src/testing/in-memory-store.d.ts.map +1 -1
- package/dist/src/testing/in-memory-store.js +13 -7
- package/dist/src/testing/in-memory-store.js.map +1 -1
- package/dist/src/testing/index.d.ts +1 -1
- package/dist/src/testing/index.d.ts.map +1 -1
- package/dist/src/testing/index.js.map +1 -1
- package/dist/src/tool-registry.d.ts +9 -0
- package/dist/src/tool-registry.d.ts.map +1 -1
- package/dist/src/tool-registry.js +11 -0
- package/dist/src/tool-registry.js.map +1 -1
- package/dist/src/types.d.ts +55 -2
- package/dist/src/types.d.ts.map +1 -1
- package/package.json +20 -10
- package/skills/agent-personas-agents/SKILL.md +16 -12
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory: what the assistant has concluded about a person or an organisation, carried across turns
|
|
3
|
+
* and across threads.
|
|
4
|
+
*
|
|
5
|
+
* HOW A READER TELLS IT FROM RAG. Retrieval answers "what do the documents say"; memory answers
|
|
6
|
+
* "what did I decide about you". A passage is content a person authored and can correct at its
|
|
7
|
+
* source, and it is cited. A memory has no source to go and fix: it is the agent's own inference,
|
|
8
|
+
* which is why every record carries an {@link MemoryOrigin} (who wrote it, in which conversation),
|
|
9
|
+
* why the block tells the model to treat it as fallible, and why `forget` is a REQUIRED method on
|
|
10
|
+
* the provider rather than an optional one. A wrong document is a content problem. A wrong memory is
|
|
11
|
+
* the assistant being confidently wrong about someone with nobody aware it is there, so the whole
|
|
12
|
+
* design is arranged around making it visible and removable.
|
|
13
|
+
*
|
|
14
|
+
* WHAT IT COSTS THE PROMPT. One line per memory, capped by `maxMemories`, and each line capped by
|
|
15
|
+
* `maxFactChars` at WRITE time — so the block a turn can carry is the product of two numbers an
|
|
16
|
+
* operator sets, rather than however much the model felt like writing down. Unlike a skill, a memory
|
|
17
|
+
* has no body/catalog split: a fact that cannot be stated in a line is not a memory, it is a
|
|
18
|
+
* document, and documents are retrieval's job.
|
|
19
|
+
*
|
|
20
|
+
* WHAT IT IS NOT: recall over a TRANSCRIPT. Searching what was said earlier is retrieval, and this
|
|
21
|
+
* library already has `Retriever`/`Reranker` for that.
|
|
22
|
+
*
|
|
23
|
+
* RECALL OVER THE MEMORIES THEMSELVES IS A DIFFERENT QUESTION, and it is answered here. The prompt
|
|
24
|
+
* budget must be bounded; the store has no reason to be. A person accumulates preferences over
|
|
25
|
+
* months and an organisation publishes facts for everyone in it, so the applicable set outgrows
|
|
26
|
+
* `maxMemories` quickly — and once it does, WHICH of them the block carries is a decision somebody
|
|
27
|
+
* has to make. Making it by scope starves the widest scopes first, which is precisely backwards: the
|
|
28
|
+
* facts that apply to the most people are the ones nobody sees. So a provider MAY supply
|
|
29
|
+
* {@link MemoryProvider.search}, and where it does, the block is filled by relevance to the turn
|
|
30
|
+
* (see {@link resolveMemoryDigest}) with scope still a hard filter and never a ranking signal.
|
|
31
|
+
* `maxMemories` then means "how many matter right now" rather than "how many a person may have".
|
|
32
|
+
*/
|
|
33
|
+
import { actorScope, defaultScopeResolver, } from './skills.js';
|
|
34
|
+
/**
|
|
35
|
+
* How many memories the block carries. The same ceiling shape as `maxSkills`, and for the same
|
|
36
|
+
* reason: a prompt that grows with how much the agent has written down is a prompt whose cost nobody
|
|
37
|
+
* set. A budget on the PROMPT and never on the store — with a provider that can
|
|
38
|
+
* {@link MemoryProvider.search}, it is how many matter right now rather than how many a person may
|
|
39
|
+
* have.
|
|
40
|
+
*/
|
|
41
|
+
export const DEFAULT_MAX_MEMORIES = 20;
|
|
42
|
+
/**
|
|
43
|
+
* How long one memory may be, enforced when it is WRITTEN rather than when it is rendered. Enforcing
|
|
44
|
+
* it at render time would make the prompt disagree with the store; enforcing it at write time makes
|
|
45
|
+
* the block's whole ceiling a multiplication an operator can do — `maxMemories × maxFactChars` — and
|
|
46
|
+
* pushes back on the model at the moment it is writing an essay instead of a fact.
|
|
47
|
+
*/
|
|
48
|
+
export const DEFAULT_MAX_FACT_CHARS = 240;
|
|
49
|
+
export function resolveMemoryDigest({ records, scopes, maxMemories = DEFAULT_MAX_MEMORIES, ranked = false, }) {
|
|
50
|
+
const rank = new Map(scopes.map((scope, index) => [scope, index]));
|
|
51
|
+
const byKey = new Map();
|
|
52
|
+
for (const entry of records) {
|
|
53
|
+
// A scope the resolver did not return is one this actor has no claim on, whatever the provider
|
|
54
|
+
// thinks. Dropping it here is what makes over-returning a performance mistake, not a leak.
|
|
55
|
+
if (!rank.has(entry.scope)) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const existing = byKey.get(entry.key);
|
|
59
|
+
if (existing === undefined) {
|
|
60
|
+
byKey.set(entry.key, [entry]);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
existing.push(entry);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const resolved = [];
|
|
67
|
+
for (const candidates of byKey.values()) {
|
|
68
|
+
const ordered = [...candidates].sort((a, b) => (rank.get(a.scope) ?? 0) - (rank.get(b.scope) ?? 0));
|
|
69
|
+
const winner = ordered[0];
|
|
70
|
+
if (winner === undefined) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const overrides = ordered.slice(1).map((beaten) => ({
|
|
74
|
+
scope: beaten.scope,
|
|
75
|
+
text: beaten.text,
|
|
76
|
+
author: beaten.origin.author,
|
|
77
|
+
}));
|
|
78
|
+
// A pin belongs to the QUESTION, not to the record that currently answers it: pinning "which
|
|
79
|
+
// fiscal year" and then letting a personal override of it fall out of the block would make
|
|
80
|
+
// always-on mean "always-on until someone disagrees with it".
|
|
81
|
+
const pinned = ordered.some((candidate) => candidate.pinned === true);
|
|
82
|
+
resolved.push({
|
|
83
|
+
...winner,
|
|
84
|
+
...(pinned ? { pinned: true } : {}),
|
|
85
|
+
...(overrides.length > 0 ? { overrides } : {}),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
// Three orders, answering three different questions.
|
|
89
|
+
//
|
|
90
|
+
// ALWAYS-ON FIRST, whatever else is true: a pinned fact is in the block whether or not the turn is
|
|
91
|
+
// about it. It spends the same budget as everything else, so the ceiling stays a product of two
|
|
92
|
+
// numbers an operator set rather than growing with how much got pinned.
|
|
93
|
+
//
|
|
94
|
+
// Then SELECTION among the rest — by relevance where the candidates were ranked, else by narrowest
|
|
95
|
+
// scope and newest within it. That second rule is right only while nothing is being starved, which
|
|
96
|
+
// is the case a host running no index is in: `list` returns the whole applicable set, so a ceiling
|
|
97
|
+
// that bites is dropping what the deployment can best afford to lose. Once the set outgrows the
|
|
98
|
+
// block it is exactly wrong, because the scopes it drops first are the ones shared by the most
|
|
99
|
+
// people — one person's twentieth note would end every chance their organisation's facts had.
|
|
100
|
+
//
|
|
101
|
+
// RENDERING is by scope then key, stable between turns: ordering the block by recency or by score
|
|
102
|
+
// would reshuffle it on every write and throw away the provider's prompt cache. Pinned entries
|
|
103
|
+
// lead, because they are the part of the block that does not move from turn to turn.
|
|
104
|
+
const byPrecedence = (a, b) => (rank.get(a.scope) ?? 0) - (rank.get(b.scope) ?? 0) ||
|
|
105
|
+
compare(b.updatedAt, a.updatedAt) ||
|
|
106
|
+
compare(a.key, b.key);
|
|
107
|
+
const selected = resolved
|
|
108
|
+
.map((entry, index) => ({ entry, index }))
|
|
109
|
+
.sort((a, b) => pinRank(a.entry) - pinRank(b.entry) ||
|
|
110
|
+
(ranked && a.entry.pinned !== true ? a.index - b.index : byPrecedence(a.entry, b.entry)))
|
|
111
|
+
.slice(0, maxMemories)
|
|
112
|
+
.map((candidate) => candidate.entry);
|
|
113
|
+
const pinnedOmitted = resolved.filter((entry) => entry.pinned === true).length -
|
|
114
|
+
selected.filter((entry) => entry.pinned === true).length;
|
|
115
|
+
selected.sort((a, b) => pinRank(a) - pinRank(b) ||
|
|
116
|
+
(rank.get(a.scope) ?? 0) - (rank.get(b.scope) ?? 0) ||
|
|
117
|
+
compare(a.key, b.key));
|
|
118
|
+
return {
|
|
119
|
+
entries: selected,
|
|
120
|
+
omitted: Math.max(0, resolved.length - maxMemories),
|
|
121
|
+
pinnedOmitted,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function pinRank(entry) {
|
|
125
|
+
return entry.pinned === true ? 0 : 1;
|
|
126
|
+
}
|
|
127
|
+
function compare(a, b) {
|
|
128
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Resolve the scopes and the digest for one turn. Called INSIDE the loop's `memory:digest` step, and
|
|
132
|
+
* that placement is the whole of its determinism: a search is the most re-derivable thing in this
|
|
133
|
+
* library — the index moves, a neighbour is written, embeddings are recomputed — so its result has
|
|
134
|
+
* to be part of the checkpoint every replay reads back, never something a replaying process asks
|
|
135
|
+
* again.
|
|
136
|
+
*/
|
|
137
|
+
export async function offerMemories({ config, ctx, query, }) {
|
|
138
|
+
const scopes = await (config.scopes ?? defaultScopeResolver).resolve(ctx);
|
|
139
|
+
const maxMemories = config.maxMemories ?? DEFAULT_MAX_MEMORIES;
|
|
140
|
+
// A search keyed on nothing ranks on noise, so a turn with no text to search with reads the scope
|
|
141
|
+
// plainly rather than making a worse selection out of it. What carries a fact through a turn like
|
|
142
|
+
// that is `pinned`, not a cleverer query.
|
|
143
|
+
const trimmed = query?.trim() ?? '';
|
|
144
|
+
const search = trimmed.length > 0 ? config.provider.search : undefined;
|
|
145
|
+
const records = search !== undefined
|
|
146
|
+
? await search({ scopes, query: trimmed, limit: maxMemories, ctx })
|
|
147
|
+
: await config.provider.list({ scopes, ctx });
|
|
148
|
+
return {
|
|
149
|
+
scopes,
|
|
150
|
+
recalled: search !== undefined,
|
|
151
|
+
...resolveMemoryDigest({ records, scopes, maxMemories, ranked: search !== undefined }),
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
const ASSERTED_FRAMING = 'Stated by people. A person wrote each of these deliberately — the user about themselves, or someone administering their organisation. Treat them as you would any other instruction you were given. If the user says something that contradicts one, say which note it conflicts with and at what scope it is held, rather than quietly setting it aside.';
|
|
155
|
+
const CONCLUDED_FRAMING = 'Concluded by you. These are your own notes from earlier turns, not documents anyone wrote: they may be wrong or out of date, so prefer what the user says now, and say where a note came from if you act on it.';
|
|
156
|
+
const PARTIAL_FRAMING = 'You are being shown a selection, not everything on file. Other notes exist that are not in this list, so never read something’s absence from it as evidence that it was never recorded.';
|
|
157
|
+
function memorySection(framing, entries) {
|
|
158
|
+
if (entries.length === 0) {
|
|
159
|
+
return [];
|
|
160
|
+
}
|
|
161
|
+
return [
|
|
162
|
+
framing,
|
|
163
|
+
...entries.flatMap((entry) => [
|
|
164
|
+
`- [${entry.scope}] ${entry.key}: ${entry.text}`,
|
|
165
|
+
...(entry.overrides ?? []).map((beaten) => ` ↳ [${beaten.scope}] ${beaten.author === 'human' ? 'a person stated' : 'instead has'}: ${beaten.text}`),
|
|
166
|
+
]),
|
|
167
|
+
];
|
|
168
|
+
}
|
|
169
|
+
export function buildMemoryBlock({ entries, writable, partial }) {
|
|
170
|
+
const writeLine = writable
|
|
171
|
+
? [
|
|
172
|
+
`When you learn something durable about this user, record it with the \`${REMEMBER_TOOL_NAME}\` tool; when one of these turns out to be wrong, record the corrected fact under the same key. What you record that way is one of your own notes, not something stated by a person.`,
|
|
173
|
+
]
|
|
174
|
+
: [];
|
|
175
|
+
const body = [
|
|
176
|
+
'What is on file about this user and their organisation, carried over from earlier conversations. Each line is a scope, a key and the fact. A narrower scope overrides a wider one; where the wider value is shown underneath, tell the user their setting differs from it rather than silently choosing one.',
|
|
177
|
+
...(partial ? [PARTIAL_FRAMING] : []),
|
|
178
|
+
...writeLine,
|
|
179
|
+
// People before inferences: the model meets what it was told before what it worked out.
|
|
180
|
+
...memorySection(ASSERTED_FRAMING, entries.filter((entry) => entry.origin.author === 'human')),
|
|
181
|
+
...memorySection(CONCLUDED_FRAMING, entries.filter((entry) => entry.origin.author !== 'human')),
|
|
182
|
+
];
|
|
183
|
+
return `<memory>\n${body.join('\n')}\n</memory>`;
|
|
184
|
+
}
|
|
185
|
+
/** The reserved name of the built-in memory-writing tool. */
|
|
186
|
+
export const REMEMBER_TOOL_NAME = 'remember';
|
|
187
|
+
const REMEMBER_JSON_SCHEMA = {
|
|
188
|
+
type: 'object',
|
|
189
|
+
additionalProperties: false,
|
|
190
|
+
required: ['key', 'fact'],
|
|
191
|
+
properties: {
|
|
192
|
+
key: {
|
|
193
|
+
type: 'string',
|
|
194
|
+
description: 'A short, stable handle for what this fact is ABOUT (e.g. "fiscal-year", "preferred-units"). Reusing an existing key replaces that fact rather than adding a second one.',
|
|
195
|
+
},
|
|
196
|
+
fact: {
|
|
197
|
+
type: 'string',
|
|
198
|
+
description: 'The fact itself, in one sentence, stated so it still makes sense in a conversation months from now.',
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
function issue(path, message) {
|
|
203
|
+
return { message, path };
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* The `remember` tool's input schema. Hand-written for the same reason `askInputSchema` and
|
|
207
|
+
* `skillInputSchema` are: core depends on no validator and has to publish a JSON Schema a provider
|
|
208
|
+
* can constrain generation against.
|
|
209
|
+
*
|
|
210
|
+
* THERE IS NO SCOPE PARAMETER, and that is the enforcement rather than a simplification. An agent
|
|
211
|
+
* may only ever write the actor it is running for (see {@link memoryWriteVerdict}), so a scope
|
|
212
|
+
* argument could only ever be a request that gets refused — and a refusable request is one a model
|
|
213
|
+
* will keep making, and one a future reader will be tempted to make grantable.
|
|
214
|
+
*/
|
|
215
|
+
export const rememberInputSchema = {
|
|
216
|
+
'~standard': {
|
|
217
|
+
version: 1,
|
|
218
|
+
vendor: 'adonis-agora-agent',
|
|
219
|
+
validate: (value) => {
|
|
220
|
+
if (typeof value !== 'object' || value === null) {
|
|
221
|
+
return { issues: [issue([], 'must be an object')] };
|
|
222
|
+
}
|
|
223
|
+
const candidate = value;
|
|
224
|
+
if (typeof candidate.key !== 'string' || candidate.key.length === 0) {
|
|
225
|
+
return { issues: [issue(['key'], 'must be a non-empty string')] };
|
|
226
|
+
}
|
|
227
|
+
if (typeof candidate.fact !== 'string' || candidate.fact.length === 0) {
|
|
228
|
+
return { issues: [issue(['fact'], 'must be a non-empty string')] };
|
|
229
|
+
}
|
|
230
|
+
return { value: { key: candidate.key, fact: candidate.fact } };
|
|
231
|
+
},
|
|
232
|
+
jsonSchema: { input: () => REMEMBER_JSON_SCHEMA },
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
export const REMEMBER_TOOL_DESCRIPTION = 'Record one durable fact about this user under a key, so later conversations start knowing it. For things that will still be true another day — how they work, what their organisation requires, a correction they made. Not for what this conversation is about, and not for anything you were not told or could not reasonably infer. The user can read and delete everything you record here.';
|
|
236
|
+
/**
|
|
237
|
+
* The `remember` tool as the model sees it. NOT a `ToolSpec` and never registered, exactly like
|
|
238
|
+
* `ask` and `skill`: it has no handler, because the loop serves it against the digest the journal
|
|
239
|
+
* holds. Keeping it out of the `ToolRegistry` is also what keeps its kind off a process-local
|
|
240
|
+
* lookup — see `claimToolCall`.
|
|
241
|
+
*/
|
|
242
|
+
export function rememberToolDefinition() {
|
|
243
|
+
return {
|
|
244
|
+
name: REMEMBER_TOOL_NAME,
|
|
245
|
+
kind: 'memory',
|
|
246
|
+
description: REMEMBER_TOOL_DESCRIPTION,
|
|
247
|
+
inputSchema: rememberInputSchema,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* May this author write a memory at this scope?
|
|
252
|
+
*
|
|
253
|
+
* The same four rules as `skillWriteVerdict`, deliberately duplicated rather than shared: they are
|
|
254
|
+
* the same rules about two different things, and folding them into one function would mean a future
|
|
255
|
+
* change to how skills are authored silently changing who may edit what the assistant believes about
|
|
256
|
+
* a person. Rule three is the one that matters, and it bites harder here than it does for skills:
|
|
257
|
+
*
|
|
258
|
+
* 1. You may only write into a scope you are yourself in.
|
|
259
|
+
* 2. Your OWN scope is yours. A memory at `actor:<you>` affects exactly one prompt — your own.
|
|
260
|
+
* 3. NOTHING BUT A HUMAN MAY WRITE ABOVE ITS OWN SCOPE, whatever `elevated` says. A skill an agent
|
|
261
|
+
* could publish at `tenant:` is a procedure anyone in the tenant can edit by talking to the
|
|
262
|
+
* assistant; a MEMORY it could publish there is a fact everyone in the tenant is then answered
|
|
263
|
+
* from, with no document to inspect and nobody aware it was written. An agent that has genuinely
|
|
264
|
+
* learned something the organisation should know proposes it; a person publishes it.
|
|
265
|
+
* 4. A human writing above their own scope needs the host to say so (`elevated`).
|
|
266
|
+
*/
|
|
267
|
+
export function memoryWriteVerdict(request) {
|
|
268
|
+
const { scope, scopes, author, actor } = request;
|
|
269
|
+
if (!scopes.includes(scope)) {
|
|
270
|
+
return { allowed: false, reason: `"${scope}" is not a scope this actor belongs to` };
|
|
271
|
+
}
|
|
272
|
+
const own = actorScope(actor);
|
|
273
|
+
if (scope === own) {
|
|
274
|
+
return { allowed: true };
|
|
275
|
+
}
|
|
276
|
+
if (author.kind !== 'human') {
|
|
277
|
+
return {
|
|
278
|
+
allowed: false,
|
|
279
|
+
reason: `only a human may write a memory at "${scope}"; an agent may write only at "${own}"`,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
return request.elevated === true
|
|
283
|
+
? { allowed: true }
|
|
284
|
+
: { allowed: false, reason: `writing at "${scope}" requires an elevated human author` };
|
|
285
|
+
}
|
|
286
|
+
export function memoryForgetVerdict({ record, actor }) {
|
|
287
|
+
return record.scope === actorScope(actor)
|
|
288
|
+
? { allowed: true }
|
|
289
|
+
: {
|
|
290
|
+
allowed: false,
|
|
291
|
+
reason: `"${record.scope}" is not this actor's own scope; deleting it is an administrative action`,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
export async function writeMemory({ config, digest, call, ctx, runId, }) {
|
|
295
|
+
const write = config.provider.write;
|
|
296
|
+
if (write === undefined) {
|
|
297
|
+
return { ok: false, error: 'Memory is read-only in this deployment.' };
|
|
298
|
+
}
|
|
299
|
+
const key = call.key.trim();
|
|
300
|
+
const text = call.fact.trim();
|
|
301
|
+
if (key.length === 0 || text.length === 0) {
|
|
302
|
+
return { ok: false, error: 'A memory needs both a key and a fact.' };
|
|
303
|
+
}
|
|
304
|
+
const maxFactChars = config.maxFactChars ?? DEFAULT_MAX_FACT_CHARS;
|
|
305
|
+
if (text.length > maxFactChars) {
|
|
306
|
+
return {
|
|
307
|
+
ok: false,
|
|
308
|
+
error: `A memory must be at most ${maxFactChars} characters; that was ${text.length}. State the fact more briefly.`,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
const scope = actorScope(ctx.actor);
|
|
312
|
+
const verdict = memoryWriteVerdict({
|
|
313
|
+
scope,
|
|
314
|
+
actor: ctx.actor,
|
|
315
|
+
scopes: digest.scopes,
|
|
316
|
+
author: { kind: 'agent', actorRef: ctx.actor.id },
|
|
317
|
+
});
|
|
318
|
+
if (!verdict.allowed) {
|
|
319
|
+
return { ok: false, error: verdict.reason };
|
|
320
|
+
}
|
|
321
|
+
const record = await write({
|
|
322
|
+
key,
|
|
323
|
+
text,
|
|
324
|
+
scope,
|
|
325
|
+
origin: { author: 'agent', threadId: ctx.threadId, runId, actorRef: ctx.actor.id },
|
|
326
|
+
ctx,
|
|
327
|
+
});
|
|
328
|
+
return { ok: true, record };
|
|
329
|
+
}
|
|
330
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ecosystem's cursor-pagination vocabulary.
|
|
3
|
+
*
|
|
4
|
+
* These two types **intentionally mirror `@adonis-agora/filter`'s `CursorParams` / `CursorPage<T>`
|
|
5
|
+
* STRUCTURALLY** — same property names, same meanings — so every `@adonis-agora/*` package speaks the
|
|
6
|
+
* one pagination interface and a consumer can move a page between them without a translation layer.
|
|
7
|
+
* The mirroring is deliberate and must be kept in sync by hand: this package does NOT depend on
|
|
8
|
+
* `@adonis-agora/filter` (it has no need for the rest of it, and a runtime dependency purely to share
|
|
9
|
+
* two interfaces would be a worse trade than the duplication). If `@adonis-agora/filter` changes the
|
|
10
|
+
* shape, change it here too.
|
|
11
|
+
*
|
|
12
|
+
* The one intentional difference is that every paginated surface in THIS package is **forward-only**,
|
|
13
|
+
* so {@link CursorParams} omits `before`/`last` — see its docblock.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Cursor pagination parameters, as a caller supplies them.
|
|
17
|
+
*
|
|
18
|
+
* - `after` — return the page immediately following this opaque cursor.
|
|
19
|
+
* - `first` — page size.
|
|
20
|
+
*
|
|
21
|
+
* **Forward-only.** `@adonis-agora/filter`'s `CursorParams` also carries `before`/`last` for backward
|
|
22
|
+
* paging, because it builds keyset predicates over SQL it controls and can therefore run the keyset
|
|
23
|
+
* comparison in reverse. Neither backend behind this package's paginated surfaces can:
|
|
24
|
+
*
|
|
25
|
+
* - Qdrant's scroll returns an opaque `next_page_offset` (the id to resume *after*) and offers no
|
|
26
|
+
* "previous page" token at all — there is nothing to send.
|
|
27
|
+
* - The governance run read-model paginates the runs table with an opaque forward cursor of the same
|
|
28
|
+
* shape, and its consumers (a "load more" table) only ever page forward.
|
|
29
|
+
*
|
|
30
|
+
* So `before`/`last` are omitted rather than declared-and-ignored: a parameter that type-checks and
|
|
31
|
+
* then silently does nothing is worse than one that does not exist.
|
|
32
|
+
*/
|
|
33
|
+
export interface CursorParams {
|
|
34
|
+
/** Opaque cursor from a prior page's {@link CursorPage.nextCursor}; omit for the first page. */
|
|
35
|
+
after?: string;
|
|
36
|
+
/** Page size. Each surface documents its own default and ceiling. */
|
|
37
|
+
first?: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* One page of cursor-paginated results.
|
|
41
|
+
*
|
|
42
|
+
* - `items` — the rows for this page, in the surface's documented order.
|
|
43
|
+
* - `nextCursor` — opaque cursor to pass back as {@link CursorParams.after} for the next page, or
|
|
44
|
+
* `null` when this was the last page.
|
|
45
|
+
* - `prevCursor` / `hasPrev` — **always `null` / `false` here.** Every backend in this package is
|
|
46
|
+
* forward-only (see {@link CursorParams}), so there is no backward cursor to hand out. The fields
|
|
47
|
+
* are still present because the point of this type is that it is the SAME shape as
|
|
48
|
+
* `@adonis-agora/filter`'s `CursorPage`: a consumer written against one renders the other without a
|
|
49
|
+
* conditional, and a surface that later gains backward paging fills them in without a breaking
|
|
50
|
+
* change. They are constants, not a bug.
|
|
51
|
+
* - `hasNext` — mirrors `nextCursor !== null`.
|
|
52
|
+
*
|
|
53
|
+
* Cursor values are **opaque**: they encode whatever the backend needs to resume (for Qdrant, its own
|
|
54
|
+
* `next_page_offset`), and callers must treat them as bytes to hand back, never parse.
|
|
55
|
+
*/
|
|
56
|
+
export interface CursorPage<T> {
|
|
57
|
+
items: T[];
|
|
58
|
+
nextCursor: string | null;
|
|
59
|
+
prevCursor: string | null;
|
|
60
|
+
hasNext: boolean;
|
|
61
|
+
hasPrev: boolean;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=pagination.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../src/pagination.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,YAAY;IAC3B,gGAAgG;IAChG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CAClB"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ecosystem's cursor-pagination vocabulary.
|
|
3
|
+
*
|
|
4
|
+
* These two types **intentionally mirror `@adonis-agora/filter`'s `CursorParams` / `CursorPage<T>`
|
|
5
|
+
* STRUCTURALLY** — same property names, same meanings — so every `@adonis-agora/*` package speaks the
|
|
6
|
+
* one pagination interface and a consumer can move a page between them without a translation layer.
|
|
7
|
+
* The mirroring is deliberate and must be kept in sync by hand: this package does NOT depend on
|
|
8
|
+
* `@adonis-agora/filter` (it has no need for the rest of it, and a runtime dependency purely to share
|
|
9
|
+
* two interfaces would be a worse trade than the duplication). If `@adonis-agora/filter` changes the
|
|
10
|
+
* shape, change it here too.
|
|
11
|
+
*
|
|
12
|
+
* The one intentional difference is that every paginated surface in THIS package is **forward-only**,
|
|
13
|
+
* so {@link CursorParams} omits `before`/`last` — see its docblock.
|
|
14
|
+
*/
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=pagination.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../src/pagination.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Running the processor chains, and the stream buffering an output gate requires. See
|
|
3
|
+
* `./spi/processors.ts` for the seams themselves and the boundary against `HistoryWindow`.
|
|
4
|
+
*/
|
|
5
|
+
import { type InputProcessor, type ModelAnswer, type OutputProcessor, type ProcessedPrompt, type ProcessorContext } from './spi/processors.js';
|
|
6
|
+
import type { SinkWriter, StreamFrame } from './spi/token-stream-sink.js';
|
|
7
|
+
/**
|
|
8
|
+
* Holds a model call's stream frames instead of letting them reach the subscriber. `end` is
|
|
9
|
+
* swallowed because the loop owns the run's stream lifecycle across however many steps the turn
|
|
10
|
+
* takes, and the model call is one step of it.
|
|
11
|
+
*
|
|
12
|
+
* A {@link StreamFrame} is a plain typed object, so the buffer rides a durable checkpoint as-is —
|
|
13
|
+
* which it has to, since the gate must survive a suspend between the model call and the verdict.
|
|
14
|
+
*/
|
|
15
|
+
export interface FrameBuffer {
|
|
16
|
+
writer: SinkWriter;
|
|
17
|
+
/** Everything written so far, in write order. */
|
|
18
|
+
frames(): StreamFrame[];
|
|
19
|
+
}
|
|
20
|
+
export declare function createFrameBuffer(): FrameBuffer;
|
|
21
|
+
/**
|
|
22
|
+
* The frames a passed gate releases to the live stream: the held ones, with every text frame
|
|
23
|
+
* collapsed into ONE carrying `text` — the answer as the chain left it, which is the only version
|
|
24
|
+
* anything downstream is allowed to see. The substitution happens in place, so the answer keeps its
|
|
25
|
+
* position relative to any non-text frame the provider interleaved with it.
|
|
26
|
+
*/
|
|
27
|
+
export declare function releaseGatedFrames(args: {
|
|
28
|
+
frames: readonly StreamFrame[];
|
|
29
|
+
text: string;
|
|
30
|
+
}): StreamFrame[];
|
|
31
|
+
/**
|
|
32
|
+
* Fold the prompt through each processor in order, every one seeing what the previous one produced.
|
|
33
|
+
* A throw is wrapped so it cannot read as the model call failing — see {@link ProcessorFailedError}.
|
|
34
|
+
*/
|
|
35
|
+
export declare function runInputProcessors(args: {
|
|
36
|
+
processors: readonly InputProcessor[];
|
|
37
|
+
prompt: ProcessedPrompt;
|
|
38
|
+
ctx: ProcessorContext;
|
|
39
|
+
}): Promise<ProcessedPrompt>;
|
|
40
|
+
/** Who refused an answer, and why. Carried out of a checkpoint, so it stays JSON-round-trippable. */
|
|
41
|
+
export interface GateRejection {
|
|
42
|
+
processor: string;
|
|
43
|
+
reason: string;
|
|
44
|
+
}
|
|
45
|
+
/** A settled output chain: the answer as the chain left it, plus who refused it if anyone did. */
|
|
46
|
+
export interface OutputGateResult {
|
|
47
|
+
/** The text every downstream consumer sees — the stream, the persisted message, the next step. */
|
|
48
|
+
text: string;
|
|
49
|
+
/** Set only on a refusal; the run ends with an `OutputRejectedError` naming these. */
|
|
50
|
+
rejection?: GateRejection;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Fold the answer through each processor in order. The FIRST rejection ends the chain: a later
|
|
54
|
+
* processor has nothing to add about text that is never going anywhere, and running it would bill a
|
|
55
|
+
* moderation call for a turn already refused.
|
|
56
|
+
*/
|
|
57
|
+
export declare function runOutputProcessors(args: {
|
|
58
|
+
processors: readonly OutputProcessor[];
|
|
59
|
+
answer: ModelAnswer;
|
|
60
|
+
ctx: ProcessorContext;
|
|
61
|
+
}): Promise<OutputGateResult>;
|
|
62
|
+
/**
|
|
63
|
+
* How much of a turn's stream an output chain costs the reader.
|
|
64
|
+
*
|
|
65
|
+
* `off` — nothing registered, the model writes straight to the run's sink.
|
|
66
|
+
* `whole` — at least one processor needs the complete answer, so every frame is held until the chain
|
|
67
|
+
* has passed and the answer arrives as one `text` frame.
|
|
68
|
+
* `incremental` — every processor declared {@link import('./spi/processors.js').IncrementalGating},
|
|
69
|
+
* so a lookback-bounded prefix is released while the call streams.
|
|
70
|
+
*/
|
|
71
|
+
export type OutputGateMode = 'off' | 'whole' | 'incremental';
|
|
72
|
+
/**
|
|
73
|
+
* ALL or nothing: one undeclared processor puts the whole chain on the whole-answer path. Its author
|
|
74
|
+
* wrote `process` against the complete text, and a chain that ran it on a prefix because a neighbour
|
|
75
|
+
* opted in would be handing it an input it never agreed to read.
|
|
76
|
+
*/
|
|
77
|
+
export declare function resolveOutputGateMode(processors: readonly OutputProcessor[]): OutputGateMode;
|
|
78
|
+
/**
|
|
79
|
+
* The chain's window is the WIDEST any member asked for: a release safe for the shortest-sighted
|
|
80
|
+
* processor is not safe for the one that matches longer patterns, and the gate makes one release
|
|
81
|
+
* decision for all of them.
|
|
82
|
+
*
|
|
83
|
+
* An undeclared processor contributes nothing rather than the default — it has no window, because a
|
|
84
|
+
* chain containing one never reaches the incremental path at all.
|
|
85
|
+
*/
|
|
86
|
+
export declare function resolveGateLookback(processors: readonly OutputProcessor[]): number;
|
|
87
|
+
/** A live gate over one model call: the sink the model writes to, plus what it let through. */
|
|
88
|
+
export interface IncrementalGate {
|
|
89
|
+
/** Hand this to the model instead of the run's writer. */
|
|
90
|
+
writer: SinkWriter;
|
|
91
|
+
/** Resolves once every frame handed to {@link IncrementalGate.writer} has been ruled on. */
|
|
92
|
+
settled(): Promise<void>;
|
|
93
|
+
/** The transformed prefix already written to the run's sink. */
|
|
94
|
+
released(): string;
|
|
95
|
+
/** Set once a prefix was refused; nothing further was released after that. */
|
|
96
|
+
rejection(): GateRejection | undefined;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Releases a model call's answer to `writer` as it arrives, holding back the last `lookbackChars`
|
|
100
|
+
* characters of what the chain produces so a processor can still change them.
|
|
101
|
+
*
|
|
102
|
+
* The chain runs over the whole PREFIX accumulated so far rather than over each new frame, so a
|
|
103
|
+
* processor always sees well-formed text and never has to reassemble a pattern split across frames —
|
|
104
|
+
* which is what makes {@link import('./spi/processors.js').IncrementalGating}'s promise a claim
|
|
105
|
+
* about prefixes. It runs once per streamed text frame.
|
|
106
|
+
*
|
|
107
|
+
* Only an EXTENSION of what the reader already has is ever written: a chain whose output stops
|
|
108
|
+
* agreeing with its earlier output has broken its promise, and the loop's whole-answer pass reports
|
|
109
|
+
* that rather than this gate papering over it by re-sending a different answer.
|
|
110
|
+
*
|
|
111
|
+
* Frames that are not text are forwarded live, in arrival order — they are not the answer, so the
|
|
112
|
+
* gate does not own them.
|
|
113
|
+
*/
|
|
114
|
+
export declare function createIncrementalGate(args: {
|
|
115
|
+
processors: readonly OutputProcessor[];
|
|
116
|
+
ctx: ProcessorContext;
|
|
117
|
+
lookbackChars: number;
|
|
118
|
+
writer: SinkWriter;
|
|
119
|
+
}): IncrementalGate;
|
|
120
|
+
/**
|
|
121
|
+
* The tail an incremental gate still owes the reader once the whole-answer pass has settled: the
|
|
122
|
+
* authoritative text minus the prefix already released.
|
|
123
|
+
*
|
|
124
|
+
* Throws when the settled answer is not an extension of that prefix. That check is the reason the
|
|
125
|
+
* final pass stays authoritative for both the stream and the store rather than the stream being
|
|
126
|
+
* stitched together from per-prefix results: agreement between what was streamed and what was stored
|
|
127
|
+
* becomes structural instead of assumed.
|
|
128
|
+
*/
|
|
129
|
+
export declare function gateTail(args: {
|
|
130
|
+
processors: readonly OutputProcessor[];
|
|
131
|
+
released: string;
|
|
132
|
+
text: string;
|
|
133
|
+
}): string;
|
|
134
|
+
//# sourceMappingURL=processors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processors.d.ts","sourceRoot":"","sources":["../../src/processors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,eAAe,EAEpB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EAEtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE1E;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,UAAU,CAAC;IACnB,iDAAiD;IACjD,MAAM,IAAI,WAAW,EAAE,CAAC;CACzB;AAED,wBAAgB,iBAAiB,IAAI,WAAW,CAW/C;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,WAAW,EAAE,CAkBhB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,UAAU,EAAE,SAAS,cAAc,EAAE,CAAC;IACtC,MAAM,EAAE,eAAe,CAAC;IACxB,GAAG,EAAE,gBAAgB,CAAC;CACvB,GAAG,OAAO,CAAC,eAAe,CAAC,CAU3B;AAED,qGAAqG;AACrG,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,kGAAkG;AAClG,MAAM,WAAW,gBAAgB;IAC/B,kGAAkG;IAClG,IAAI,EAAE,MAAM,CAAC;IACb,sFAAsF;IACtF,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,UAAU,EAAE,SAAS,eAAe,EAAE,CAAC;IACvC,MAAM,EAAE,WAAW,CAAC;IACpB,GAAG,EAAE,gBAAgB,CAAC;CACvB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAkB5B;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,OAAO,GAAG,aAAa,CAAC;AAE7D;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,SAAS,eAAe,EAAE,GAAG,cAAc,CAO5F;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,SAAS,eAAe,EAAE,GAAG,MAAM,CAWlF;AAED,+FAA+F;AAC/F,MAAM,WAAW,eAAe;IAC9B,0DAA0D;IAC1D,MAAM,EAAE,UAAU,CAAC;IACnB,4FAA4F;IAC5F,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,gEAAgE;IAChE,QAAQ,IAAI,MAAM,CAAC;IACnB,8EAA8E;IAC9E,SAAS,IAAI,aAAa,GAAG,SAAS,CAAC;CACxC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,UAAU,EAAE,SAAS,eAAe,EAAE,CAAC;IACvC,GAAG,EAAE,gBAAgB,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,UAAU,CAAC;CACpB,GAAG,eAAe,CAsElB;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE;IAC7B,UAAU,EAAE,SAAS,eAAe,EAAE,CAAC;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,MAAM,CAYT"}
|