@triplef/agent 0.1.9 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/prompts/index.d.ts +4 -2
- package/dist/prompts/index.mjs +39 -12
- package/dist/schemas/index.mjs +9 -5
- package/dist/tools/index.mjs +2 -2
- package/package.json +2 -2
package/dist/prompts/index.d.ts
CHANGED
|
@@ -111,15 +111,17 @@ declare function buildMemoryProfilePrompt(params: {
|
|
|
111
111
|
maxPayloadChars?: number;
|
|
112
112
|
}): string;
|
|
113
113
|
|
|
114
|
-
declare const MEMORY_WRITE_INSTRUCTIONS = "MEMORY WRITE JOB \u2014 one purpose: decide whether THIS turn yielded anything worth persisting, and store it in the correct lane via the memory-partition-remember or memory-cognition-remember tool.\n\nTwo lanes, never confused:\n- memory-partition = the user's OWN statements (facts they stated or asked you to remember).\n- memory-cognition = YOUR derived understanding of the user (inferred traits, standing interests, connections).\n\nYou receive:\n- USER REQUEST: what the user asked.\n- PRIOR MEMORY: facts already stored for this user (may be empty).\n- PROBED THIS TURN: what memory-partition-recall already surfaced for this turn (may be empty) \u2014 already known, never re-store.\n- GATHERED DATA: summarized tool results from this turn (web searches, lookups).\n\nStore into the PARTITION lane (call memory-partition-remember) only when it is durable and user-specific:\n- A preference, interest, or durable detail the user states about themselves (favorite X, their setup, contact info, a decision \u2014 however phrased, any language).\n- A notable fact the user asks you to track or remember.\n- Knowledge about a subject the user cares about that was gathered this turn and extends what is already in PRIOR MEMORY.\n\nStore into the COGNITION lane (call memory-cognition-remember) only when it is something you LEARN about the user that they did not state outright:\n- An inferred trait, a standing interest, a working nuance, or a connection between facts the turn supports.\n- Never a stated fact \u2014 those belong in the partition lane.\n\nSTORAGE MECHANICS \u2014 how your memory works (write for the retriever):\n- Each stored record is embedded as a whole AND matched sentence-by-sentence at recall time (multi-variant retrieval). One self-contained fact per call; a single long, dense sentence is fine, but lead with the subject (\"Sam's phone number is 555-1234\", never \"His number is \u2026\").\n- Restating a record verbatim OVERWRITES it in place \u2014 updates are restatements of the full corrected statement, not diffs.\n- tags are the ONLY topic-filter vocabulary at recall \u2014 reuse stable, lowercase
|
|
114
|
+
declare const MEMORY_WRITE_INSTRUCTIONS = "MEMORY WRITE JOB \u2014 one purpose: decide whether THIS turn yielded anything worth persisting, and store it in the correct lane via the memory-partition-remember or memory-cognition-remember tool.\n\nTwo lanes, never confused:\n- memory-partition = the user's OWN statements (facts they stated or asked you to remember).\n- memory-cognition = YOUR derived understanding of the user (inferred traits, standing interests, connections).\n\nYou receive:\n- USER REQUEST: what the user asked.\n- PRIOR MEMORY: facts already stored for this user (may be empty).\n- PROBED THIS TURN: what memory-partition-recall already surfaced for this turn (may be empty) \u2014 already known, never re-store.\n- GATHERED DATA: summarized tool results from this turn (web searches, lookups).\n\nStore into the PARTITION lane (call memory-partition-remember) only when it is durable and user-specific:\n- A preference, interest, or durable detail the user states about themselves (favorite X, their setup, contact info, a decision \u2014 however phrased, any language).\n- A notable fact the user asks you to track or remember.\n- Knowledge about a subject the user cares about that was gathered this turn and extends what is already in PRIOR MEMORY.\n\nStore into the COGNITION lane (call memory-cognition-remember) only when it is something you LEARN about the user that they did not state outright:\n- An inferred trait, a standing interest, a working nuance, or a connection between facts the turn supports.\n- Never a stated fact \u2014 those belong in the partition lane.\n\nSTORAGE MECHANICS \u2014 how your memory works (write for the retriever):\n- Each stored record is embedded as a whole AND matched sentence-by-sentence at recall time (multi-variant retrieval). One self-contained fact per call; a single long, dense sentence is fine, but lead with the subject (\"Sam's phone number is 555-1234\", never \"His number is \u2026\").\n- Restating a record verbatim OVERWRITES it in place \u2014 updates are restatements of the full corrected statement, not diffs.\n- tags are the ONLY topic-filter vocabulary at recall \u2014 reuse stable, lowercase topic labels (partition lane only). Tags are NARROW and specific: entity names, product names, game titles (\"amd\", \"stellar blade\", \"stellar blade blood rain\").\n- category is the broad family the fact belongs to (partition lane only): ONE lowercase PLURAL family noun per remember call \u2014 stocks, games, pets, work, health, finance, contacts \u2026 \u2014 chosen so narrow topics group into families. A category is NEVER a specific entity, product, company, or game title: \"amd\" is a tag under the category \"stocks\"; \"stellar blade\" and \"stellar blade blood rain\" are tags under the category \"games\". Always include it; tags stay narrow, category stays broad and plural.\n\nDo NOT store:\n- Public facts merely fetched this turn that do not relate to the user (e.g. generic web results).\n- Anything already covered by PRIOR MEMORY or PROBED THIS TURN \u2014 extend or update it via the remember call; do not repeat.\n- Tool artifacts: URLs, search scores, image metadata, raw JSON keys.\n- Inferred, assumed, or extrapolated details about the user that neither their words nor GATHERED DATA support \u2014 if the user did not state it (or clearly imply it), it is not memory; when in doubt, answer \"none\".\n\nRules:\n- Each remember call stores ONE self-contained statement (stand-alone, understandable weeks later without this conversation's context).\n- Call each remember tool once per distinct durable item \u2014 no more.\n- If nothing durable surfaced, produce a one-word text answer (\"none\") and make NO tool call. An empty memory write is a correct outcome, never a failure.";
|
|
115
115
|
declare function buildMemoryWritePrompt(params: {
|
|
116
116
|
userRequest: string;
|
|
117
117
|
priorMemory?: string;
|
|
118
118
|
probedMemory?: string;
|
|
119
119
|
gathered?: string;
|
|
120
|
+
knownCategories?: string[];
|
|
121
|
+
knownTags?: string[];
|
|
120
122
|
}): string;
|
|
121
123
|
|
|
122
|
-
declare function buildExtractionPrompt(): string;
|
|
124
|
+
declare function buildExtractionPrompt(knownCategories?: readonly string[], knownTags?: readonly string[]): string;
|
|
123
125
|
declare function buildExtractionCorrectionPrompt(error: string): string;
|
|
124
126
|
|
|
125
127
|
declare const COMMONMARK_FORMAT = "MARKDOWN FORMAT (strict CommonMark):\n- Use ASCII asterisks only: *italic* and **bold**.\n- Never put spaces inside the markers: write **bold**, never ** bold **.\n- Never use fullwidth or unicode asterisk characters (\uFF0A or \u2217).\n- Separate paragraphs with a blank line; keep paragraphs short.\n- Use Markdown links for URLs: [label](https://...). Never paste bare URLs.\n- Use emphasis sparingly. Bold only the single most important term in a paragraph \u2014 never a whole sentence or a lead-in clause.\n- Prefer ## or ### headings to introduce sections instead of bolding the lead-in.\n- Use - bullets for parallel items and 1. numbers for ordered steps.";
|
package/dist/prompts/index.mjs
CHANGED
|
@@ -644,14 +644,18 @@ var ExtractionSchema = z.object({
|
|
|
644
644
|
facts: z.array(z.string()),
|
|
645
645
|
/**
|
|
646
646
|
* 2–6 stable, reusable lowercase topic labels describing the text; the open
|
|
647
|
-
* vocabulary that powers topic-filtered recall.
|
|
647
|
+
* vocabulary that powers topic-filtered recall. Tags are NARROW and
|
|
648
|
+
* specific — entity names, product names, game titles (e.g. `amd`,
|
|
649
|
+
* `stellar blade`, `stellar blade blood rain`).
|
|
648
650
|
*/
|
|
649
651
|
tags: z.array(z.string()),
|
|
650
652
|
/**
|
|
651
|
-
* One broad lowercase family label for the whole turn-side (e.g.
|
|
652
|
-
* `pets`, `games`) — groups the narrow tags into one topic family
|
|
653
|
-
* constellation's community tier and the relink job's per-category
|
|
654
|
-
*
|
|
653
|
+
* One broad lowercase PLURAL family label for the whole turn-side (e.g.
|
|
654
|
+
* `stocks`, `pets`, `games`) — groups the narrow tags into one topic family
|
|
655
|
+
* for the constellation's community tier and the relink job's per-category
|
|
656
|
+
* passes. Never a specific entity, product, company, or game title: `amd`
|
|
657
|
+
* belongs under `stocks`; `stellar blade` belongs under `games`. Optional:
|
|
658
|
+
* a turn with nothing durable may omit it.
|
|
655
659
|
*/
|
|
656
660
|
category: z.string().optional()
|
|
657
661
|
});
|
|
@@ -3169,8 +3173,8 @@ Store into the COGNITION lane (call memory-cognition-remember) only when it is s
|
|
|
3169
3173
|
STORAGE MECHANICS \u2014 how your memory works (write for the retriever):
|
|
3170
3174
|
- Each stored record is embedded as a whole AND matched sentence-by-sentence at recall time (multi-variant retrieval). One self-contained fact per call; a single long, dense sentence is fine, but lead with the subject ("Sam's phone number is 555-1234", never "His number is \u2026").
|
|
3171
3175
|
- Restating a record verbatim OVERWRITES it in place \u2014 updates are restatements of the full corrected statement, not diffs.
|
|
3172
|
-
- tags are the ONLY topic-filter vocabulary at recall \u2014 reuse stable, lowercase
|
|
3173
|
-
- category is the broad family the fact belongs to (partition lane only): ONE lowercase
|
|
3176
|
+
- tags are the ONLY topic-filter vocabulary at recall \u2014 reuse stable, lowercase topic labels (partition lane only). Tags are NARROW and specific: entity names, product names, game titles ("amd", "stellar blade", "stellar blade blood rain").
|
|
3177
|
+
- category is the broad family the fact belongs to (partition lane only): ONE lowercase PLURAL family noun per remember call \u2014 stocks, games, pets, work, health, finance, contacts \u2026 \u2014 chosen so narrow topics group into families. A category is NEVER a specific entity, product, company, or game title: "amd" is a tag under the category "stocks"; "stellar blade" and "stellar blade blood rain" are tags under the category "games". Always include it; tags stay narrow, category stays broad and plural.
|
|
3174
3178
|
|
|
3175
3179
|
Do NOT store:
|
|
3176
3180
|
- Public facts merely fetched this turn that do not relate to the user (e.g. generic web results).
|
|
@@ -3183,18 +3187,31 @@ Rules:
|
|
|
3183
3187
|
- Call each remember tool once per distinct durable item \u2014 no more.
|
|
3184
3188
|
- If nothing durable surfaced, produce a one-word text answer ("none") and make NO tool call. An empty memory write is a correct outcome, never a failure.`;
|
|
3185
3189
|
function buildMemoryWritePrompt(params) {
|
|
3190
|
+
const vocabulary = buildVocabularySection(params.knownCategories, params.knownTags);
|
|
3186
3191
|
return [
|
|
3187
3192
|
`USER REQUEST: ${params.userRequest}`,
|
|
3188
3193
|
`PRIOR MEMORY: ${params.priorMemory?.trim() || "(none stored yet)"}`,
|
|
3189
3194
|
`PROBED THIS TURN: ${params.probedMemory?.trim() || "(nothing probed this turn)"}`,
|
|
3190
3195
|
`GATHERED DATA: ${params.gathered?.trim() || "(no tools produced data this turn)"}`,
|
|
3196
|
+
vocabulary,
|
|
3191
3197
|
MEMORY_WRITE_VERDICT
|
|
3192
|
-
].join("\n\n");
|
|
3198
|
+
].filter(Boolean).join("\n\n");
|
|
3199
|
+
}
|
|
3200
|
+
function buildVocabularySection(knownCategories = [], knownTags = []) {
|
|
3201
|
+
if (knownCategories.length === 0 && knownTags.length === 0) return "";
|
|
3202
|
+
const lines = [];
|
|
3203
|
+
if (knownCategories.length > 0) {
|
|
3204
|
+
lines.push(
|
|
3205
|
+
`KNOWN CATEGORIES (reuse one when it fits; only mint a new plural family noun when none applies): ${knownCategories.join(", ")}`
|
|
3206
|
+
);
|
|
3207
|
+
}
|
|
3208
|
+
if (knownTags.length > 0) lines.push(`KNOWN TOPICS (reuse these tag labels when they fit): ${knownTags.join(", ")}`);
|
|
3209
|
+
return lines.join("\n");
|
|
3193
3210
|
}
|
|
3194
3211
|
var MEMORY_WRITE_VERDICT = 'Decide: store each durable user-specific fact with one memory-partition-remember call, each derived understanding with one memory-cognition-remember call, or answer "none" if the turn surfaced nothing durable about this user.';
|
|
3195
3212
|
|
|
3196
3213
|
// src/prompts/memory/vectorize-prompt.constant.ts
|
|
3197
|
-
function buildExtractionPrompt() {
|
|
3214
|
+
function buildExtractionPrompt(knownCategories = [], knownTags = []) {
|
|
3198
3215
|
return buildStructuredPrompt(ExtractionSchema, {
|
|
3199
3216
|
before: "OUTPUT FORMAT \u2014 output ONLY valid JSON matching this exact schema:",
|
|
3200
3217
|
after: `
|
|
@@ -3204,10 +3221,10 @@ YOUR TASK \u2014 decide what is worth remembering:
|
|
|
3204
3221
|
- Facts must be self-contained \u2014 no "this"/"that" references; write them as third-person statements.
|
|
3205
3222
|
- Storage mechanics: each fact is embedded as a whole and matched sentence-by-sentence at recall time (multi-variant retrieval). One dense sentence is fine \u2014 put the subject up front ("User prefers single-line if statements", not "They prefer that style").
|
|
3206
3223
|
- Skip transient content: greetings, small talk, one-off instructions, filler \u2014 anything with no future recall value. When in doubt about whether a detail is durable, keep it: a durable detail is cheaper to store than to lose.
|
|
3207
|
-
- Tags: 2 to 6 stable, reusable, lowercase topic labels describing what the text is about (e.g. "work", "rust", "contacts"). They are the vocabulary for topic-filtered recall later.
|
|
3208
|
-
- Category: ONE broad lowercase family
|
|
3224
|
+
- Tags: 2 to 6 stable, reusable, lowercase topic labels describing what the text is about (e.g. "work", "rust", "contacts", "amd", "stellar blade"). Tags are NARROW and specific \u2014 entity names, product names, game titles. They are the vocabulary for topic-filtered recall later.
|
|
3225
|
+
- Category: ONE broad lowercase PLURAL family noun for the whole text (e.g. "stocks", "pets", "games", "health") that groups the narrow tags into one topic family. A category is NEVER a specific entity, product, company, or game title: "amd" belongs under "stocks"; "stellar blade" and "stellar blade blood rain" belong under "games". Always include it when facts are emitted; omit it when nothing durable is found.
|
|
3209
3226
|
- If nothing durable is found, return an empty facts array; tags may still label the topic when useful.
|
|
3210
|
-
|
|
3227
|
+
${buildVocabularySection2(knownCategories, knownTags)}
|
|
3211
3228
|
PRIOR MEMORY (when the user message ends with an "ALREADY STORED IN MEMORY" section):
|
|
3212
3229
|
- That section lists facts already stored in YOUR long-term memory from prior turns. NEVER emit a fact already covered there.
|
|
3213
3230
|
- If this turn refines, corrects, or completes a stored fact, DO emit it \u2014 as one fuller, self-contained restatement (a full restatement of the corrected claim overwrites the old record in place; it is never a diff).
|
|
@@ -3223,6 +3240,16 @@ FINAL REMINDER:
|
|
|
3223
3240
|
- Output ONLY valid JSON matching the exact schema above. No markdown code fences, no explanations, preamble, or postscript.`
|
|
3224
3241
|
});
|
|
3225
3242
|
}
|
|
3243
|
+
function buildVocabularySection2(knownCategories, knownTags) {
|
|
3244
|
+
if (knownCategories.length === 0 && knownTags.length === 0) return "";
|
|
3245
|
+
const lines = [];
|
|
3246
|
+
if (knownCategories.length > 0)
|
|
3247
|
+
lines.push(
|
|
3248
|
+
`KNOWN CATEGORIES (reuse one when it fits; only mint a new plural family noun when none applies): ${knownCategories.join(", ")}`
|
|
3249
|
+
);
|
|
3250
|
+
if (knownTags.length > 0) lines.push(`KNOWN TOPICS (reuse these tag labels when they fit): ${knownTags.join(", ")}`);
|
|
3251
|
+
return lines.join("\n");
|
|
3252
|
+
}
|
|
3226
3253
|
function buildExtractionCorrectionPrompt(error) {
|
|
3227
3254
|
return `Your previous response was not valid.
|
|
3228
3255
|
Error: ${error}
|
package/dist/schemas/index.mjs
CHANGED
|
@@ -490,14 +490,18 @@ var ExtractionSchema = z.object({
|
|
|
490
490
|
facts: z.array(z.string()),
|
|
491
491
|
/**
|
|
492
492
|
* 2–6 stable, reusable lowercase topic labels describing the text; the open
|
|
493
|
-
* vocabulary that powers topic-filtered recall.
|
|
493
|
+
* vocabulary that powers topic-filtered recall. Tags are NARROW and
|
|
494
|
+
* specific — entity names, product names, game titles (e.g. `amd`,
|
|
495
|
+
* `stellar blade`, `stellar blade blood rain`).
|
|
494
496
|
*/
|
|
495
497
|
tags: z.array(z.string()),
|
|
496
498
|
/**
|
|
497
|
-
* One broad lowercase family label for the whole turn-side (e.g.
|
|
498
|
-
* `pets`, `games`) — groups the narrow tags into one topic family
|
|
499
|
-
* constellation's community tier and the relink job's per-category
|
|
500
|
-
*
|
|
499
|
+
* One broad lowercase PLURAL family label for the whole turn-side (e.g.
|
|
500
|
+
* `stocks`, `pets`, `games`) — groups the narrow tags into one topic family
|
|
501
|
+
* for the constellation's community tier and the relink job's per-category
|
|
502
|
+
* passes. Never a specific entity, product, company, or game title: `amd`
|
|
503
|
+
* belongs under `stocks`; `stellar blade` belongs under `games`. Optional:
|
|
504
|
+
* a turn with nothing durable may omit it.
|
|
501
505
|
*/
|
|
502
506
|
category: z.string().optional()
|
|
503
507
|
});
|
package/dist/tools/index.mjs
CHANGED
|
@@ -960,10 +960,10 @@ ${lines.join("\n")}`;
|
|
|
960
960
|
var memoryPartitionRememberSchema = z.object({
|
|
961
961
|
text: z.string().min(1).max(2e3).describe('The fact to remember, as a self-contained statement, e.g. "Sams phone number is 555-1234".'),
|
|
962
962
|
category: z.string().min(1).max(40).optional().describe(
|
|
963
|
-
'One broad lowercase category the fact belongs to, e.g. "games", "pets", "work", "
|
|
963
|
+
'One broad lowercase PLURAL category the fact belongs to, e.g. "stocks", "games", "pets", "work" \u2014 a family noun, never a specific entity/product/company/game name ("amd" \u2192 "stocks"; "stellar blade" \u2192 "games"). Always include it.'
|
|
964
964
|
),
|
|
965
965
|
tags: z.array(z.string().min(1).max(40)).max(8).optional().describe(
|
|
966
|
-
'Optional topic labels (lowercase, reusable) so future recall can filter by topic, e.g. ["contacts", "sam"].'
|
|
966
|
+
'Optional topic labels (lowercase, reusable, NARROW \u2014 entity/product/game names) so future recall can filter by topic, e.g. ["contacts", "sam"], ["amd"], ["stellar blade"].'
|
|
967
967
|
)
|
|
968
968
|
});
|
|
969
969
|
function createMemoryPartitionRememberTool(deps) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@triplef/agent",
|
|
3
3
|
"description": "tripleF (3F) agent domain — structured-output schemas, prompt builders, and model tools shared across the apps.",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.11",
|
|
5
5
|
"packageManager": "pnpm@11.25.0",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"type": "module",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"turndown": "^7.2.4"
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
|
-
"ai": "^7.0.
|
|
63
|
+
"ai": "^7.0.85",
|
|
64
64
|
"zod": "^4.5.4"
|
|
65
65
|
},
|
|
66
66
|
"peerDependenciesMeta": {
|