anbaric 1.35.0 → 1.36.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/docs/README.md CHANGED
@@ -27,6 +27,7 @@ What the framework gives you, one capability at a time.
27
27
  - [The SQL store](features/sql-store.md) — a relational database for structured data
28
28
  - [Auditing](features/auditing.md) — the record of who changed what
29
29
  - [Entitlements](features/entitlements.md) — what a user has been granted, checked per request
30
+ - [Prompts](features/prompts.md) — versioned model instructions and schemas, saved at startup
30
31
  - [Serving a web UI](features/serving-a-web-ui.md) — putting your data on a page
31
32
  - [The admin console and widgets](features/admin-console-and-widgets.md) — dashboards and plugins
32
33
  - [Deploying](features/deploying.md) — from laptop to Anbaric Cloud
@@ -36,6 +36,7 @@ defaulting to a local implementation otherwise).
36
36
  | `ANBARIC_SQL_STORE_TYPE` | the SQL store (`sqlite` / `cloud`\|`postgres`) | SQLite |
37
37
  | `ANBARIC_SESSION_RESOLVER_TYPE` | how `Human.fromSession` resolves sessions | in-memory |
38
38
  | `ANBARIC_ENTITLEMENTS_TYPE` | how `hasEntitlement` is answered (`cloud` → platform) | permissive (always `true`) |
39
+ | `ANBARIC_PROMPT_MANAGER_TYPE` | the [prompt manager](../features/prompts.md) | in-memory |
39
40
 
40
41
  ## Store configuration
41
42
 
@@ -86,6 +86,42 @@ const key = await secrets.retrieve("stripe-key", actor);
86
86
 
87
87
  ---
88
88
 
89
+ ## `PromptManager`
90
+
91
+ Versioned prompts - instructions plus optional input and output schemas - owned
92
+ by the calling app.
93
+
94
+ ```ts
95
+ PromptManagerFactory.instance() : PromptManager
96
+
97
+ // methods:
98
+ save(promptId : string, instructions : string, inputSchema? : JsonSchema, outputSchema? : JsonSchema) : Promise<Prompt>
99
+ retrieve(promptId : string, version? : number) : Promise<Prompt>
100
+ list() : Promise<Array<Prompt>>
101
+ history(promptId : string) : Promise<Array<Prompt>>
102
+
103
+ type Prompt = {
104
+ appId : string, promptId : string, version : number, instructions : string,
105
+ inputSchema? : JsonSchema, outputSchema? : JsonSchema, createdAt : string,
106
+ }
107
+ ```
108
+
109
+ ```ts
110
+ const prompts = PromptManagerFactory.instance();
111
+ await prompts.save("triage", "Decide the priority.", undefined, { type: "object", properties: { priority: { type: "string" } } });
112
+ const latest = await prompts.retrieve("triage"); // highest version
113
+ const specific = await prompts.retrieve("triage", 1);
114
+ const all = await prompts.list(); // latest of each prompt
115
+ const versions = await prompts.history("triage"); // newest first
116
+ ```
117
+
118
+ - `save` stores a new version only when the content differs from the latest; an identical save returns the existing version, so registering at every startup is safe.
119
+ - Versions auto-increment from 1; there is no rollback or tagging.
120
+ - `retrieve` of an unknown prompt throws `No prompt found with id "..."`.
121
+ - Env var: **`ANBARIC_PROMPT_MANAGER_TYPE`** (`cloud` deployed; in-memory otherwise).
122
+
123
+ ---
124
+
89
125
  ## `SqlStore`
90
126
 
91
127
  A relational database — SQLite locally, PostgreSQL deployed.
@@ -9,7 +9,7 @@ import {
9
9
  StateMachine, State, Terminal, Action, Await, Transition,
10
10
  Job, PropertyDefinition,
11
11
  Code, Human, SystemActor, Agent, OpenAIAgent, RemoteLLMAgenticAction,
12
- JsonStoreFactory, SecretStoreFactory, SqlStoreFactory,
12
+ JsonStoreFactory, SecretStoreFactory, SqlStoreFactory, PromptManagerFactory,
13
13
  registerEntitlement, hasEntitlement,
14
14
  } from "anbaric";
15
15
 
@@ -27,8 +27,10 @@ An Anbaric app is a standard Node.js **ESM** program in TypeScript: set
27
27
  `Actor`.
28
28
  - **[Actors and agents](actors-and-agents.md)** — `Code`, `Human`,
29
29
  `SystemActor`, `Agent`, `RemoteLLMAgenticAction`, `OpenAIAgent`.
30
- - **[Stores](stores.md)** — `JsonStore`, `SecretStore`, `SqlStore` and their
31
- factories, plus `JsonSchema`.
30
+ - **[Stores](stores.md)** — `JsonStore`, `SecretStore`, `SqlStore`,
31
+ `PromptManager` and their factories, plus `JsonSchema`.
32
+ - **[Entitlements](../features/entitlements.md)** — `registerEntitlement`,
33
+ `hasEntitlement`.
32
34
  - **[Environment and factories](environment.md)** — the `ANBARIC_*` variables
33
35
  the factories read.
34
36
 
@@ -54,6 +54,25 @@ must return. The model is constrained to it (strict structured output), so you
54
54
  get well-typed properties back rather than free text. Keep the schema tight —
55
55
  only the properties you want written to the job.
56
56
 
57
+ ## Keep the prompt in the prompt manager
58
+
59
+ Instructions change more often than code. Rather than a string literal, save
60
+ the prompt with the [prompt manager](prompts.md) at startup and read the
61
+ latest where the action is built - every edit is versioned and visible in the
62
+ console's **Prompts** page:
63
+
64
+ ```ts
65
+ import {PromptManagerFactory} from "anbaric";
66
+
67
+ const prompts = PromptManagerFactory.instance();
68
+ await prompts.save("triage", "Decide the priority of the support ticket from its subject.",
69
+ undefined, { type: "object", properties: { priority: { type: "string", enum: ["low", "high"] } } });
70
+
71
+ const prompt = await prompts.retrieve("triage");
72
+ const triage = new RemoteLLMAgenticAction("Triage the ticket", triager,
73
+ [{ role: "system", content: prompt.instructions }], prompt.outputSchema!);
74
+ ```
75
+
57
76
  ## Bring your own model
58
77
 
59
78
  `OpenAIAgent` targets any OpenAI-compatible endpoint. Configure it with a
@@ -0,0 +1,78 @@
1
+ # Prompts
2
+
3
+ The instructions you give a model are part of your app, but they change more
4
+ often than code and you want to see what was said when. The **prompt manager**
5
+ keeps each prompt your app uses as a **versioned** record: save it at startup,
6
+ fetch it where you call the model, and every change is kept in the console with
7
+ its history. Like every other store, it's in-memory locally and platform-backed
8
+ once deployed - no code change.
9
+
10
+ ## Register prompts at startup
11
+
12
+ Save each prompt once when the app starts. If nothing changed since the last
13
+ run, no new version is stored - so registering on every boot is free.
14
+
15
+ ```ts
16
+ import {PromptManagerFactory} from "anbaric";
17
+
18
+ const prompts = PromptManagerFactory.instance();
19
+
20
+ await prompts.save(
21
+ "triage",
22
+ "Decide the priority of the support ticket from its subject and body. Escalate anything mentioning an outage.",
23
+ { type: "object", required: ["subject", "body"], properties: { subject: { type: "string" }, body: { type: "string" } } },
24
+ { type: "object", required: ["priority"], properties: { priority: { type: "string", enum: ["low", "high"] } } },
25
+ );
26
+ ```
27
+
28
+ A prompt has an **id**, its **instructions**, and optionally an **input
29
+ schema** (the shape of what the model is given) and an **output schema** (what
30
+ it must produce). Edit the instructions and redeploy: the next save stores
31
+ version 2. There's no rollback and no tagging - an app always gets the latest.
32
+
33
+ ## Use the latest where you call the model
34
+
35
+ ```ts
36
+ import {OpenAIAgent, RemoteLLMAgenticAction} from "anbaric";
37
+
38
+ const triagePrompt = await prompts.retrieve("triage");
39
+
40
+ const triage = new RemoteLLMAgenticAction(
41
+ "Triage the ticket",
42
+ new OpenAIAgent("triager", "support", { apiKey: process.env.OPENAI_API_KEY!, model: "gpt-5.4-mini" }),
43
+ [{ role: "system", content: triagePrompt.instructions }],
44
+ triagePrompt.outputSchema!,
45
+ );
46
+ ```
47
+
48
+ `retrieve(id)` returns the latest version; `retrieve(id, 3)` a specific one.
49
+ An unknown prompt throws `No prompt found with id "..."`.
50
+
51
+ ## Look back
52
+
53
+ ```ts
54
+ const latest = await prompts.list(); // the latest version of every prompt this app has
55
+ const versions = await prompts.history("triage"); // every version, newest first
56
+ ```
57
+
58
+ The console's **Prompts** page shows the same for every app on the tenant: each
59
+ prompt, its current instructions and schemas, and the full history to browse.
60
+
61
+ ## Everything is scoped to your app
62
+
63
+ Deployed, prompts are **owned by your app** - two apps can both have a `triage`
64
+ prompt without seeing each other's. The platform scopes every read and write to
65
+ your app automatically.
66
+
67
+ ## Choosing an implementation
68
+
69
+ You don't - the factory does, from the environment:
70
+
71
+ | Factory | Env var | Local default | Deployed |
72
+ | --- | --- | --- | --- |
73
+ | `PromptManagerFactory.instance()` | `ANBARIC_PROMPT_MANAGER_TYPE` | in-memory | platform (`cloud`) |
74
+
75
+ ## Next
76
+
77
+ - [AI agents](ai-agents.md) - putting a prompt to work in a state
78
+ - [API: Stores](../api/stores.md#promptmanager)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anbaric",
3
- "version": "1.35.0",
3
+ "version": "1.36.0",
4
4
  "description": "Everything needed to write an Anbaric app: state machines, jobs, document and secret stores, local in-memory implementations and the Anbaric Cloud clients",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -24,9 +24,9 @@
24
24
  "prepublishOnly": "npm run build"
25
25
  },
26
26
  "dependencies": {
27
- "anbaric-impl-cloud": "^1.35.0",
28
- "anbaric-data-store": "^1.35.0",
29
- "anbaric-state-machine": "^1.35.0",
30
- "anbaric-tsapi": "^1.35.0"
27
+ "anbaric-impl-cloud": "^1.36.0",
28
+ "anbaric-data-store": "^1.36.0",
29
+ "anbaric-state-machine": "^1.36.0",
30
+ "anbaric-tsapi": "^1.36.0"
31
31
  }
32
32
  }