@anvia/cli 1.2.0 → 1.3.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.
Files changed (53) hide show
  1. package/README.md +32 -0
  2. package/dist/chunk-ERCP4EIZ.js +607 -0
  3. package/dist/chunk-ERCP4EIZ.js.map +1 -0
  4. package/dist/cli.js +278 -74
  5. package/dist/cli.js.map +1 -1
  6. package/dist/index.d.ts +54 -1
  7. package/dist/index.js +21 -3
  8. package/dist/skills/anvia-agent/SKILL.md +59 -0
  9. package/dist/skills/anvia-agent/references/agent-options.md +83 -0
  10. package/dist/skills/anvia-agent/references/providers.md +22 -0
  11. package/dist/skills/anvia-agent/references/teams.md +84 -0
  12. package/dist/skills/anvia-agent/references/tools.md +71 -0
  13. package/dist/skills/anvia-agent/scripts/check-agent.sh +99 -0
  14. package/dist/skills/anvia-channels/SKILL.md +59 -0
  15. package/dist/skills/anvia-channels/references/adapters.md +53 -0
  16. package/dist/skills/anvia-channels/references/channel-agent.md +52 -0
  17. package/dist/skills/anvia-channels/references/delivery.md +53 -0
  18. package/dist/skills/anvia-channels/scripts/check-channels.sh +79 -0
  19. package/dist/skills/anvia-chat/SKILL.md +61 -0
  20. package/dist/skills/anvia-chat/references/react-ui.md +104 -0
  21. package/dist/skills/anvia-chat/references/server-protocol.md +53 -0
  22. package/dist/skills/anvia-chat/references/transports-state.md +71 -0
  23. package/dist/skills/anvia-chat/scripts/check-chat-boundary.sh +70 -0
  24. package/dist/skills/anvia-evals/SKILL.md +51 -0
  25. package/dist/skills/anvia-evals/references/judges.md +61 -0
  26. package/dist/skills/anvia-evals/references/metrics.md +45 -0
  27. package/dist/skills/anvia-evals/references/running.md +62 -0
  28. package/dist/skills/anvia-evals/scripts/check-evals.sh +73 -0
  29. package/dist/skills/anvia-mcp/SKILL.md +49 -0
  30. package/dist/skills/anvia-mcp/references/clients.md +73 -0
  31. package/dist/skills/anvia-mcp/references/safety.md +25 -0
  32. package/dist/skills/anvia-mcp/scripts/check-mcp.sh +73 -0
  33. package/dist/skills/anvia-pipeline/SKILL.md +52 -0
  34. package/dist/skills/anvia-pipeline/references/agents-extract.md +62 -0
  35. package/dist/skills/anvia-pipeline/references/steps-compose.md +63 -0
  36. package/dist/skills/anvia-pipeline/scripts/check-pipeline.sh +69 -0
  37. package/dist/skills/anvia-rag/SKILL.md +50 -0
  38. package/dist/skills/anvia-rag/references/graph-rag.md +115 -0
  39. package/dist/skills/anvia-rag/references/pipeline.md +81 -0
  40. package/dist/skills/anvia-rag/references/rag-tool.md +43 -0
  41. package/dist/skills/anvia-rag/references/stores.md +68 -0
  42. package/dist/skills/anvia-rag/scripts/check-rag.sh +75 -0
  43. package/dist/skills/anvia-studio/SKILL.md +45 -0
  44. package/dist/skills/anvia-studio/references/inspect.md +33 -0
  45. package/dist/skills/anvia-studio/references/observe.md +34 -0
  46. package/dist/skills/anvia-studio/references/serve.md +65 -0
  47. package/dist/skills/anvia-studio/scripts/check-studio.sh +59 -0
  48. package/dist/skills/release-notes/SKILL.md +18 -0
  49. package/dist/skills/release-notes/references/style.md +6 -0
  50. package/dist/skills/release-notes/scripts/draft.sh +22 -0
  51. package/package.json +2 -2
  52. package/dist/chunk-IH4ZNWHB.js +0 -285
  53. package/dist/chunk-IH4ZNWHB.js.map +0 -1
@@ -0,0 +1,115 @@
1
+ # Graph RAG
2
+
3
+ Use a knowledge graph when the questions are about connections (which incidents
4
+ affect which products, who owns what) — vectors find similar text, graphs
5
+ traverse relationships. The two compose: managed ingestion embeds chunks for a
6
+ vector store while extracting facts for the graph.
7
+
8
+ Core primitives live in `@anvia/graph`; provisioning, persistence, and queries
9
+ belong to adapters (`@anvia/neo4j`, `@anvia/memgraph`).
10
+
11
+ ## Schema first
12
+
13
+ ```ts
14
+ import { defineGraphSchema } from "@anvia/graph";
15
+
16
+ const schema = defineGraphSchema({
17
+ nodes: {
18
+ Product: {
19
+ description: "A product or service.",
20
+ identity: ["id"],
21
+ properties: z.strictObject({ id: z.string(), name: z.string() }),
22
+ },
23
+ },
24
+ relationships: {
25
+ AFFECTS: {
26
+ description: "An incident affects a product.",
27
+ from: "Incident",
28
+ to: "Product",
29
+ properties: z.strictObject({ severity: z.enum(["low", "medium", "high"]) }),
30
+ },
31
+ },
32
+ });
33
+ ```
34
+
35
+ Design the schema from the questions, not the source tables. `identity` fields
36
+ are how facts merge — wrong identity modeling duplicates entities forever.
37
+
38
+ ## Ingestion
39
+
40
+ ```ts
41
+ import { ingestGraphText } from "@anvia/graph";
42
+
43
+ const ingestion = await ingestGraphText({
44
+ graph,
45
+ document: { id: "incident-42", text, metadata: { tenant: "acme" } },
46
+ extractionModel,
47
+ embeddingModel,
48
+ chunking: {
49
+ strategy: "recursive",
50
+ maxSize: 1_000,
51
+ overlap: 100,
52
+ separators: ["\n\n", "\n", " "],
53
+ },
54
+ conflict: "error",
55
+ orphanEntities: "delete",
56
+ factConflicts: {
57
+ entity: { properties: { summary: "prefer-longest", aliases: "union", confidence: "max" } },
58
+ },
59
+ });
60
+ ```
61
+
62
+ - Managed graphs accept the same raw-text shape as vector ingestion, so reuse
63
+ your chunking settings. `ingestGraphDocuments()` batches; `ingestGraphTextToStores()`
64
+ writes graph + vector store in one call.
65
+ - Two conflict policies: `factConflicts` (disagreements between chunks, rejected
66
+ by default — strategies like `prefer-longest`, `union`, `max`), and `conflict`
67
+ (collisions with already-stored facts). Read both errors; they carry fact
68
+ type, stable key, identity, and source chunk IDs.
69
+ - Graph and vector writes are separate transactions. On partial failure
70
+ (`GraphIngestionStageError`) reconcile from the returned `receipt` — persist
71
+ ingestion status and retry the incomplete stage yourself.
72
+ - Reuse `ingestion.vectorDocuments` for the vector upsert instead of
73
+ re-embedding. Existing graph registrations are read-only ingestion targets.
74
+
75
+ ## Search tool
76
+
77
+ ```ts
78
+ import { createGraphSearchTool } from "@anvia/graph";
79
+
80
+ const searchGraph = createGraphSearchTool({
81
+ name: "search_graph",
82
+ description: "Search connected entities and supporting evidence.", // required — no default
83
+ graph,
84
+ model: embeddingModel,
85
+ search: { type: "vector", seeds: ["entities"], topK: 8 },
86
+ traversal: {
87
+ relationships: ["AFFECTS"],
88
+ direction: "both",
89
+ maxDepth: 2,
90
+ maxNodes: 40,
91
+ maxRelationships: 80,
92
+ },
93
+ evidence: { type: "chunks", maxChunks: 12 },
94
+ });
95
+ ```
96
+
97
+ - `search` has two modes: `{ type: "vector", seeds, topK }` and
98
+ `{ type: "hybrid", seeds, topK, candidatesPerSeed, rrfK }` — hybrid fuses
99
+ vector similarity with per-seed graph matches. Prefer it when seed names
100
+ alone miss paraphrased entities.
101
+ - Bound everything: `maxDepth`, `maxNodes`, `maxRelationships`, `maxChunks`.
102
+ Unbounded traversal is the graph equivalent of `topK: 1000`.
103
+ - Evidence modes depend on the registration: managed graphs hydrate stored
104
+ chunks, existing-graph registrations use `{ type: "none" }`.
105
+ - One search tool per question shape, as with vector tools — graph and vector
106
+ tools coexist on the same agent when some questions are relational and some
107
+ are textual.
108
+
109
+ ## Exploration
110
+
111
+ Adapters implementing `GraphExplorer` expose bounded `overview` / `expand`
112
+ views for visualization (Studio's graph explorer, `@anvia/react`
113
+ `useGraphExplorer`). Explorer IDs are opaque and provider-specific — follow-up
114
+ expansion only, never persistence. Adapters cap requests, return truncation
115
+ metadata, and omit stored embeddings and reserved `__anvia_*` properties.
@@ -0,0 +1,81 @@
1
+ # Chunk and Embed Pipeline
2
+
3
+ ## Chunk
4
+
5
+ `chunkText` from `@anvia/core/documents` splits raw text before embedding. Keep
6
+ chunk ids stable and traceable to the source:
7
+
8
+ ```ts
9
+ import { chunkText } from "@anvia/core/documents";
10
+ import type { Document } from "@anvia/core/completion";
11
+
12
+ const chunks = chunkText({
13
+ text,
14
+ strategy: "recursive",
15
+ maxSize: 80,
16
+ overlap: 10,
17
+ separators: ["\n\n", "\n", " "],
18
+ }).map((chunk): Document => ({
19
+ id: `${path}#chunk=${chunk.index}`,
20
+ text: chunk.text,
21
+ additionalProps: {
22
+ source: path,
23
+ mediaType: "text/plain",
24
+ chunkIndex: String(chunk.index),
25
+ }),
26
+ }));
27
+ ```
28
+
29
+ Small overlap preserves cross-boundary context. Record provenance
30
+ (`source`, `mediaType`, `chunkIndex`) in `additionalProps` — retrieval results
31
+ are only as citable as the metadata you store.
32
+
33
+ ## Embed
34
+
35
+ `embedDocuments` from `@anvia/core/embeddings` maps domain objects to embedded
36
+ documents with explicit selectors. The same model instance must embed documents
37
+ and queries:
38
+
39
+ ```ts
40
+ import { embedDocuments } from "@anvia/core/embeddings";
41
+ import { loadTransformersEmbeddingModel } from "@anvia/transformers";
42
+
43
+ const model = await loadTransformersEmbeddingModel({ modelId: "Xenova/all-MiniLM-L6-v2" });
44
+ const { documents: embedded } = await embedDocuments({
45
+ model,
46
+ documents: reports,
47
+ id: (report) => report.id,
48
+ content: (report) => report.text,
49
+ metadata: (report) => ({ desk: report.desk, priority: report.priority }),
50
+ });
51
+ ```
52
+
53
+ - `id` must be stable across re-index runs or upserts will duplicate.
54
+ - `content` is what gets embedded — keep titles with bodies, drop boilerplate.
55
+ - `metadata` carries everything you will filter or display on (`desk`,
56
+ `priority`, `source`). You cannot filter on what you did not store.
57
+ - Custom models implement `EmbeddingModel` (`provider`, `modelId`,
58
+ `dimensions`, `embedTexts`). Production embeddings can also come from
59
+ provider packages (e.g. Mistral) — same `embedDocuments` contract.
60
+
61
+ ## Retrieve
62
+
63
+ ```ts
64
+ import { InMemoryVectorStore, retrieveDocuments, vectorFilter } from "@anvia/core/vector-store";
65
+
66
+ const store = InMemoryVectorStore.fromDocuments({
67
+ documents: embedded,
68
+ index: { type: "lsh", numTables: 8, numHyperplanes: 1, seed: 11 }, // opt-in for scale
69
+ });
70
+ const results = await retrieveDocuments({
71
+ store,
72
+ model,
73
+ query: "earnings risk remains elevated",
74
+ topK: 3,
75
+ filter: vectorFilter.and(vectorFilter.eq("desk", "markets"), vectorFilter.gt("priority", 2)),
76
+ });
77
+ ```
78
+
79
+ Start with exact retrieval (`topK`, metadata filters) before adding approximate
80
+ indexes — LSH trades recall for speed and needs a fixed `seed` for reproducible
81
+ evals.
@@ -0,0 +1,43 @@
1
+ # RAG Search Tool
2
+
3
+ Give the agent retrieval as a tool, not as pasted context. `createVectorSearchTool`
4
+ from `@anvia/core/vector-store` wraps a store + embedding model with a routing
5
+ description and `topK`:
6
+
7
+ ```ts
8
+ import { Agent } from "@anvia/core/agent";
9
+ import { createVectorSearchTool } from "@anvia/core/vector-store";
10
+
11
+ const searchRunbooks = createVectorSearchTool({
12
+ store,
13
+ model: embeddingModel,
14
+ name: "search_runbooks",
15
+ description: "Search incident runbooks for relevant operational guidance.",
16
+ topK: 2,
17
+ });
18
+
19
+ const agent = new Agent({
20
+ id: "agent",
21
+ model: agentModel,
22
+ instructions: "Use the runbook search tool before answering incident questions.",
23
+ maxTurns: 2,
24
+ tools: [searchRunbooks],
25
+ });
26
+ ```
27
+
28
+ ## Rules
29
+
30
+ - The tool `description` is routing text: say when to call it, not how vectors
31
+ work. It is optional (a generic default exists), but always set it — the
32
+ default cannot route when several corpora exist. One tool per corpus with a
33
+ distinct description beats one generic `search_docs` tool.
34
+ - Keep `topK` small (2–5). The agent reads what the tool returns — large `topK`
35
+ burns context and degrades answers.
36
+ - Instruct the agent to call search _before_ answering, and to cite `source`
37
+ metadata from the results. Retrieval without citation requirements produces
38
+ confident paraphrases of nothing.
39
+ - For static context that always applies (system rules, tiny glossaries), use
40
+ `Agent.context` (`Document` / `VectorContext`) instead of a tool — tools are
41
+ for corpora too large to fit the prompt.
42
+ - Close vector clients (`vectorClient.close()`) when the process ends;
43
+ in-memory stores need no lifecycle.
@@ -0,0 +1,68 @@
1
+ # Vector Store Selection
2
+
3
+ Core contracts live in `@anvia/core/vector-store`
4
+ (`InMemoryVectorStore`, `retrieveDocuments`, `vectorFilter`,
5
+ `createVectorSearchTool`). Durable backends live in adapter packages:
6
+
7
+ | Package | Backend | Best for |
8
+ | ----------------- | -------- | ----------------------------------------- |
9
+ | `@anvia/chroma` | Chroma | local dev with persistence |
10
+ | `@anvia/lancedb` | LanceDB | embedded local persistence, no server |
11
+ | `@anvia/qdrant` | Qdrant | self-hosted production |
12
+ | `@anvia/pgvector` | pgvector | teams already on Postgres |
13
+ | `@anvia/milvus` | Milvus | large-scale self-hosted |
14
+ | `@anvia/pinecone` | Pinecone | managed production |
15
+ | `@anvia/redis` | Redis | existing Redis infra, hybrid search needs |
16
+ | `@anvia/weaviate` | Weaviate | managed / hybrid search features |
17
+
18
+ For connected-entity questions (which incidents affect which products), add a
19
+ knowledge graph alongside the vector store — see `graph-rag.md`. Vectors find
20
+ similar text; graphs traverse relationships.
21
+
22
+ ## Hybrid (dense + sparse) retrieval
23
+
24
+ Keyword-ish recall problems ("error 0x8007", exact identifiers) are a sparse
25
+ retrieval problem. `retrieveDocuments` has a hybrid overload — pass
26
+ `models: { dense, sparse }` instead of `model`, and the store's `searchHybrid`
27
+ fuses both rankings (`fusion` controls the strategy):
28
+
29
+ ```ts
30
+ import { embedSparseQuery } from "@anvia/core/embeddings"; // SparseEmbeddingModel
31
+ // embedSparseTexts embeds documents' sparse side at ingestion
32
+
33
+ const results = await retrieveDocuments({
34
+ store: hybridStore, // e.g. HybridVectorStore or a backend supporting searchHybrid
35
+ query,
36
+ models: { dense: embeddingModel, sparse: sparseModel },
37
+ topK: 5,
38
+ });
39
+ ```
40
+
41
+ Reach for hybrid when plain dense search misses exact tokens; keep pure dense
42
+ when it does not — hybrid adds an ingestion and store-compatibility cost.
43
+
44
+ ## Client store pattern
45
+
46
+ ```ts
47
+ import { ChromaVectorClient } from "@anvia/chroma";
48
+
49
+ const vectorClient = new ChromaVectorClient();
50
+ const store = vectorClient.vectorStore<Runbook>({
51
+ collectionName: "anvia_runbooks",
52
+ dimensions: 384, // must match the embedding model output
53
+ });
54
+ await store.ensure();
55
+ await store.upsert({ documents: embedded });
56
+ // ... retrieve ...
57
+ await vectorClient.close();
58
+ ```
59
+
60
+ ## Rules
61
+
62
+ - `dimensions` must match the embedding model — a 384-dim MiniLM index queried
63
+ with another model's vectors fails silently on quality, not loudly on types.
64
+ - One model instance (or at least one model id) per collection. Never mix
65
+ embedding models in the same collection.
66
+ - `ensure()` before `upsert`; `close()` clients when the process ends.
67
+ - Start with `InMemoryVectorStore.fromDocuments` for spikes and tests, then
68
+ migrate to a client store — the `retrieveDocuments` call does not change.
@@ -0,0 +1,75 @@
1
+ #!/bin/sh
2
+ # Heuristic checks for Anvia retrieval/RAG code in an app directory.
3
+ # Usage: sh scripts/check-rag.sh [--dir <app-root>]
4
+ # Fails with a list of violations; passes silently with "rag OK".
5
+
6
+ DIR="."
7
+ if [ "$1" = "--dir" ] && [ -n "$2" ]; then
8
+ DIR="$2"
9
+ fi
10
+
11
+ ROOTS_FOUND=0
12
+ for root in "$DIR/src" "$DIR/app" "$DIR/lib" "$DIR/server"; do
13
+ if [ -d "$root" ]; then
14
+ ROOTS_FOUND=1
15
+ break
16
+ fi
17
+ done
18
+ if [ "$ROOTS_FOUND" -eq 0 ]; then
19
+ echo "ERROR: no src/app/lib/server directory under '$DIR' — nothing was checked."
20
+ echo "Run from the app root or pass --dir <app-root>."
21
+ exit 1
22
+ fi
23
+
24
+ fail=0
25
+ violation() {
26
+ echo "VIOLATION: $1"
27
+ fail=1
28
+ }
29
+ warning() {
30
+ echo "WARNING: $1"
31
+ }
32
+
33
+ FILES=$(grep -rln --include='*.ts' \
34
+ -e 'embedDocuments' -e 'retrieveDocuments' -e 'createVectorSearchTool' -e 'createGraphSearchTool' -e 'vectorStore' \
35
+ "$DIR/src" "$DIR/app" "$DIR/lib" "$DIR/server" 2>/dev/null | sort -u)
36
+
37
+ if [ -z "$FILES" ]; then
38
+ echo "rag OK (no retrieval code found)"
39
+ exit 0
40
+ fi
41
+
42
+ # 1. embedDocuments needs explicit id/content/metadata selectors.
43
+ if echo "$FILES" | xargs grep -l 'embedDocuments' 2>/dev/null | grep -q .; then
44
+ echo "$FILES" | xargs grep -h -A8 'embedDocuments(' 2>/dev/null | grep -q 'content:' || {
45
+ violation "embedDocuments without content selector (see references/pipeline.md)."
46
+ }
47
+ fi
48
+
49
+ # 2. Client vector stores need dimensions matching the embedding model.
50
+ if echo "$FILES" | xargs grep -l 'vectorStore' 2>/dev/null | grep -q .; then
51
+ echo "$FILES" | xargs grep -h -A5 'vectorStore' 2>/dev/null | grep -q 'dimensions' || {
52
+ violation "vectorStore without dimensions (see references/stores.md)."
53
+ }
54
+ fi
55
+
56
+ # 3. One search tool per corpus needs a routing description (warning: a generic default exists).
57
+ if echo "$FILES" | xargs grep -l 'createVectorSearchTool' 2>/dev/null | grep -q .; then
58
+ echo "$FILES" | xargs grep -h -A7 'createVectorSearchTool(' 2>/dev/null | grep -q 'description' || {
59
+ warning "createVectorSearchTool without description falls back to a generic default (see references/rag-tool.md)."
60
+ }
61
+ fi
62
+
63
+ # 4. Graph search tools have no default description — one is required.
64
+ if echo "$FILES" | xargs grep -l 'createGraphSearchTool' 2>/dev/null | grep -q .; then
65
+ echo "$FILES" | xargs grep -h -A7 'createGraphSearchTool(' 2>/dev/null | grep -q 'description' || {
66
+ violation "createGraphSearchTool without description (see references/graph-rag.md)."
67
+ }
68
+ fi
69
+
70
+ if [ "$fail" -eq 0 ]; then
71
+ echo "rag OK"
72
+ exit 0
73
+ fi
74
+ echo "See skills/anvia-rag/references/ for fixes."
75
+ exit 1
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: anvia-studio
3
+ description: Run and inspect Anvia agents in Studio — local serving, playground, traces, approvals, sessions, evals, and observability.
4
+ ---
5
+
6
+ # Anvia Studio Skill
7
+
8
+ Use this skill when the user wants to run agents locally and see what happens:
9
+ serving agents/pipelines over HTTP, using the playground, inspecting traces and
10
+ sessions, exercising tool approvals, running eval suites, or wiring
11
+ observability.
12
+
13
+ ## Process
14
+
15
+ 1. Serve the agents (`references/serve.md`) — smallest `Studio` that runs.
16
+ 2. Debug through the inspectors (`references/inspect.md`) — playground first,
17
+ then traces, approvals, sessions.
18
+ 3. Wire observability (`references/observe.md`) — only when runs must be
19
+ auditable or production-like.
20
+ 4. Run `scripts/check-studio.sh` from the app root before claiming done.
21
+
22
+ ## Minimal slice
23
+
24
+ ```ts
25
+ import { Agent } from "@anvia/core";
26
+ import { OpenAIClient } from "@anvia/openai";
27
+ import { Studio } from "@anvia/studio";
28
+
29
+ const client = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY });
30
+ const agent = new Agent({
31
+ id: "support",
32
+ model: client.completionModel({ modelId: "gpt-6-astra", api: "responses" }),
33
+ name: "Support",
34
+ description: "Answers support questions.",
35
+ instructions: "Answer support questions clearly.",
36
+ });
37
+
38
+ await new Studio([agent]).serve({ port: 4021 });
39
+ // Open http://localhost:4021/ui/playground
40
+ ```
41
+
42
+ ## Output
43
+
44
+ Studio is a development surface, not production hosting. Point to the relevant
45
+ reference file instead of pasting its contents into chat.
@@ -0,0 +1,33 @@
1
+ # Inspectors
2
+
3
+ Debug in this order: playground → traces → approvals → sessions. Each surface
4
+ answers a different question.
5
+
6
+ - **Playground** — chat with a registered agent or team, switch models per run
7
+ (Studio can expose a shared multi-provider catalog with per-agent allow
8
+ lists), restore control choices from session metadata. First stop for
9
+ "what does it do?".
10
+ - **Trace browser + session logs** — what actually happened: messages, tool
11
+ activity, usage, realtime log stream. First stop for "why did it do that?".
12
+ - **Tool approval workflows** — exercise `requiresApproval` tools and question
13
+ prompts end to end; approvals resolve through the same interaction responses
14
+ the API uses.
15
+ - **Eval suite runner** — run registered `runEvalSuite` configurations from the
16
+ UI. Keep the suite definitions in code (see the `anvia-evals` skill); Studio
17
+ runs them, it does not own them.
18
+ - **Direct tool + MCP inspectors** — invoke tools by hand, including MCP tools.
19
+ Studio reads MCP provenance from `Agent.mcpServers`, so `McpClient`
20
+ `tools.prefix` values stay visible here.
21
+ - **Memory explorer** — users, conversations, messages, transcript steps from
22
+ the session store. Empty here plus working chat means the store is not the
23
+ one the agent writes to — check `stores.sessions`.
24
+ - **Pipelines** — graph, logs, run history, replay-from-history.
25
+ - **Knowledge** — static/dynamic context, dynamic tools, retrieval log. First
26
+ stop for "why didn't it retrieve?".
27
+ - **Status dashboard** — storage adapters, record counts, enabled capabilities.
28
+ First stop for "is anything even configured?".
29
+ - **Graphs** — bounded overview/expansion over registered `GraphExplorer`
30
+ graphs (`@anvia/neo4j`, `@anvia/memgraph`); no raw queries accepted.
31
+
32
+ Sandbox/browser registrations add loopback-only noVNC desktop views with explicit
33
+ takeover leases — local debugging conveniences, not an auth model.
@@ -0,0 +1,34 @@
1
+ # Observability
2
+
3
+ Studio's own surfaces (realtime log stream, trace browser, status dashboard)
4
+ cover development. Production-like auditing needs the observability packages:
5
+
6
+ - `@anvia/langfuse` — tracing, eval reporting, scoring, prompt/dataset helpers.
7
+ - `@anvia/otel` — OpenTelemetry adapters.
8
+ - `@anvia/lens` — native Lens integration (see the cookbook's lens-native example).
9
+
10
+ ## Rules
11
+
12
+ - Close observability clients in Studio's `onShutdown` — they are caller-owned
13
+ resources and outlive runs:
14
+
15
+ ```ts
16
+ await new Studio([agent]).serve({
17
+ port: 4021,
18
+ shutdownTimeoutMs: 30_000,
19
+ onShutdown: async () => {
20
+ await Promise.all([lens.close(), langfuse.close(), otelSdk.shutdown()]); // otelSdk is your OTel SDK instance, not an Anvia export
21
+ },
22
+ });
23
+ ```
24
+
25
+ - Redact before export: `createPiiRedactor` ships with both `@anvia/langfuse`
26
+ and `@anvia/lens`. Wrap exporters with it so customer data never reaches
27
+ trace payloads in the first place.
28
+ - For application logs alongside traces, `@anvia/logger` provides
29
+ `createConsoleLogger`, `createPinoLogger`, and `createLoggerObserver`.
30
+ - Report evals to observability (Langfuse eval reporting, trace refs via
31
+ `resolveEvalTraceRef`) when runs must be auditable — see the `anvia-evals`
32
+ skill's `references/running.md`.
33
+ - Never commit keys, private prompts, customer data, or trace payloads. Read
34
+ credentials from the environment at the boundary, same as provider keys.
@@ -0,0 +1,65 @@
1
+ # Serving Agents
2
+
3
+ `@anvia/studio` serves local agents, pipelines, and agent teams over HTTP with
4
+ a browser UI. Register what you already built — Studio does not redefine agents.
5
+
6
+ ```ts
7
+ import { Agent, AgentTeam } from "@anvia/core/agent";
8
+ import { Studio } from "@anvia/studio";
9
+
10
+ const researcher = new Agent({ id: "researcher", model });
11
+ const team = new AgentTeam({ id: "research-team", model, members: [researcher] });
12
+ await new Studio([researcher, team]).serve({ port: 4021 });
13
+ ```
14
+
15
+ - `serve({ port })` starts HTTP + UI; `.start()` is the non-awaited variant.
16
+ Without a port, Studio uses `RUNNER_PORT`, then falls back to `4021`.
17
+ - The playground lives at `/ui/playground`.
18
+ - A Studio with only teams opens its first team automatically; agent and team
19
+ IDs occupy separate namespaces.
20
+
21
+ ## Sessions
22
+
23
+ Studio uses an in-memory store by default — sessions, traces, and run history
24
+ vanish on restart. Persist with SQLite:
25
+
26
+ ```ts
27
+ import { Studio, createSqliteSessionStore } from "@anvia/studio";
28
+
29
+ new Studio([agent], {
30
+ stores: { sessions: createSqliteSessionStore({ path: ".anvia/studio.sqlite" }) },
31
+ }).start();
32
+ ```
33
+
34
+ SQLite uses dedicated `anvia_studio_*` tables, so it can share an application
35
+ database without touching product tables.
36
+
37
+ ## Lifecycle
38
+
39
+ - `serve()` handles `SIGINT`/`SIGTERM`: stops accepting work, aborts active
40
+ Agent and Pipeline runs, waits for cancellation observers, then runs
41
+ `onShutdown` — close observability clients and other caller-owned resources
42
+ there.
43
+ - `shutdown()` drains the same way for application-managed lifecycles;
44
+ `close()` aborts without waiting (compatibility only).
45
+
46
+ ## Runs
47
+
48
+ The primary execution API is `POST /agents/:agentId/runs`: it streams JSONL
49
+ events and accepts interaction-resume bodies, so scripts and CI can drive an
50
+ agent without the browser UI.
51
+
52
+ ## Teams
53
+
54
+ Team runs stream JSONL events (`POST /teams/:teamId/runs`), with steer, cancel,
55
+ and per-interaction resolve endpoints. Approvals and questions surface as cards
56
+ labeled with the requesting member; several members may block at once. Team
57
+ tasks are page-local and ephemeral — they never enter saved agent sessions.
58
+
59
+ ## Rules
60
+
61
+ - Studio provides no authentication. Apply auth middleware to execution routes
62
+ before exposing it beyond localhost.
63
+ - Disconnecting a stream or shutting down cancels the run and its pending
64
+ interactions — completed runs leave the live registry (later control calls
65
+ 404), and team runs are not resumable.
@@ -0,0 +1,59 @@
1
+ #!/bin/sh
2
+ # Heuristic checks for Anvia Studio code in an app directory.
3
+ # Usage: sh scripts/check-studio.sh [--dir <app-root>]
4
+ # Fails with a list of violations; passes silently with "studio OK".
5
+
6
+ DIR="."
7
+ if [ "$1" = "--dir" ] && [ -n "$2" ]; then
8
+ DIR="$2"
9
+ fi
10
+
11
+ ROOTS_FOUND=0
12
+ for root in "$DIR/src" "$DIR/app" "$DIR/lib" "$DIR/server"; do
13
+ if [ -d "$root" ]; then
14
+ ROOTS_FOUND=1
15
+ break
16
+ fi
17
+ done
18
+ if [ "$ROOTS_FOUND" -eq 0 ]; then
19
+ echo "ERROR: no src/app/lib/server directory under '$DIR' — nothing was checked."
20
+ echo "Run from the app root or pass --dir <app-root>."
21
+ exit 1
22
+ fi
23
+
24
+ fail=0
25
+ violation() {
26
+ echo "VIOLATION: $1"
27
+ fail=1
28
+ }
29
+ warning() {
30
+ echo "WARNING: $1"
31
+ }
32
+
33
+ FILES=$(grep -rln --include='*.ts' \
34
+ -e 'new Studio(' -e '@anvia/studio' \
35
+ "$DIR/src" "$DIR/app" "$DIR/lib" "$DIR/server" 2>/dev/null | sort -u)
36
+
37
+ if [ -z "$FILES" ]; then
38
+ echo "studio OK (no Studio code found)"
39
+ exit 0
40
+ fi
41
+
42
+ # 1. Studio must serve something.
43
+ if echo "$FILES" | xargs grep -h -e 'new Studio(' 2>/dev/null | grep -q -e 'new Studio(\s*\[\s*\]' -e 'new Studio(\s*)'; then
44
+ violation "new Studio with no registered agents/teams (see references/serve.md)."
45
+ fi
46
+
47
+ # 2. Observability clients are caller-owned: close them in onShutdown (warning only).
48
+ if echo "$FILES" | xargs grep -l -e '@anvia/langfuse' -e '@anvia/otel' -e '@anvia/lens' 2>/dev/null | grep -q .; then
49
+ echo "$FILES" | xargs grep -h -e 'onShutdown' 2>/dev/null | grep -q 'onShutdown' || {
50
+ warning "observability clients without onShutdown — they will leak on exit (see references/observe.md)."
51
+ }
52
+ fi
53
+
54
+ if [ "$fail" -eq 0 ]; then
55
+ echo "studio OK"
56
+ exit 0
57
+ fi
58
+ echo "See skills/anvia-studio/references/ for fixes."
59
+ exit 1
@@ -0,0 +1,18 @@
1
+ ---
2
+ name: release-notes
3
+ description: Draft concise product release notes from a list of shipped changes.
4
+ ---
5
+
6
+ # Release Notes Skill
7
+
8
+ Use this skill when the user asks for release notes, changelogs, launch notes, or a concise product update.
9
+
10
+ ## Process
11
+
12
+ 1. Read `references/style.md`.
13
+ 2. Run `scripts/draft.sh` with the shipped changes as one argument.
14
+ 3. Rewrite the script output into final release notes for the requested audience.
15
+
16
+ ## Output
17
+
18
+ Keep the final answer short, concrete, and grouped by user-visible capability.
@@ -0,0 +1,6 @@
1
+ # Release Notes Style
2
+
3
+ - Start with a one-line summary.
4
+ - Use 3 to 5 bullets.
5
+ - Prefer user-visible benefits over implementation details.
6
+ - Mention breaking changes only when they affect users.
@@ -0,0 +1,22 @@
1
+ #!/bin/sh
2
+ # Draft release-notes skeleton from a list of shipped changes (one argument,
3
+ # one change per line). The skill rewrites this skeleton into final notes.
4
+
5
+ changes="$1"
6
+
7
+ if [ -z "$changes" ]; then
8
+ echo "usage: draft.sh \"<shipped changes, one per line>\"" >&2
9
+ exit 1
10
+ fi
11
+
12
+ printf 'Draft release notes\n====================\n\n'
13
+ printf 'Summary: <one sentence covering the theme of these changes>\n\n'
14
+ printf 'Changes:\n'
15
+ printf '%s\n' "$changes" | while IFS= read -r line; do
16
+ if [ -n "$line" ]; then
17
+ case "$line" in
18
+ "- "*) line="${line#- }" ;;
19
+ esac
20
+ printf -- '- %s\n' "$line"
21
+ fi
22
+ done