@plumbus/core 0.8.0-beta.1 → 0.8.0-beta.10
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 +187 -0
- package/README.md +8 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/ai/ai/cost-tracker.d.ts +22 -2
- package/dist/ai/ai/model-pricing.d.ts +8 -2
- package/dist/ai/ai/openai-strict-schema.d.ts +84 -0
- package/dist/ai/ai/provider.d.ts +90 -6
- package/dist/ai/ai-service.d.ts +53 -1
- package/dist/ai/ai-service.d.ts.map +1 -1
- package/dist/ai/ai-service.js +550 -119
- package/dist/ai/ai-service.js.map +1 -1
- package/dist/ai/cost-tracker.d.ts +22 -2
- package/dist/ai/cost-tracker.d.ts.map +1 -1
- package/dist/ai/cost-tracker.js +59 -20
- package/dist/ai/cost-tracker.js.map +1 -1
- package/dist/ai/explainability.d.ts +2 -1
- package/dist/ai/explainability.d.ts.map +1 -1
- package/dist/ai/explainability.js +1 -0
- package/dist/ai/explainability.js.map +1 -1
- package/dist/ai/index.d.ts +2 -2
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +1 -1
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/model-pricing.d.ts +8 -2
- package/dist/ai/model-pricing.d.ts.map +1 -1
- package/dist/ai/model-pricing.js +113 -15
- package/dist/ai/model-pricing.js.map +1 -1
- package/dist/ai/openai-strict-schema.d.ts +85 -0
- package/dist/ai/openai-strict-schema.d.ts.map +1 -0
- package/dist/ai/openai-strict-schema.js +730 -0
- package/dist/ai/openai-strict-schema.js.map +1 -0
- package/dist/ai/prompt-overrides.d.ts +19 -0
- package/dist/ai/prompt-overrides.d.ts.map +1 -0
- package/dist/ai/prompt-overrides.js +60 -0
- package/dist/ai/prompt-overrides.js.map +1 -0
- package/dist/ai/provider-failure.d.ts +9 -0
- package/dist/ai/provider-failure.d.ts.map +1 -0
- package/dist/ai/provider-failure.js +112 -0
- package/dist/ai/provider-failure.js.map +1 -0
- package/dist/ai/provider.d.ts +90 -6
- package/dist/ai/provider.d.ts.map +1 -1
- package/dist/ai/provider.js +546 -97
- package/dist/ai/provider.js.map +1 -1
- package/dist/ai/rag/pipeline.d.ts +21 -1
- package/dist/ai/rag/pipeline.d.ts.map +1 -1
- package/dist/ai/rag/pipeline.js +17 -1
- package/dist/ai/rag/pipeline.js.map +1 -1
- package/dist/ai/tool-loop.d.ts +8 -1
- package/dist/ai/tool-loop.d.ts.map +1 -1
- package/dist/ai/tool-loop.js +7 -0
- package/dist/ai/tool-loop.js.map +1 -1
- package/dist/ai/types/config.d.ts +13 -0
- package/dist/ai/types/fields.d.ts +6 -0
- package/dist/ai/types/prompt.d.ts +9 -0
- package/dist/ai/usage-validation.d.ts.map +1 -1
- package/dist/ai/usage-validation.js +6 -1
- package/dist/ai/usage-validation.js.map +1 -1
- package/dist/ai/validation.d.ts +7 -3
- package/dist/ai/validation.d.ts.map +1 -1
- package/dist/ai/validation.js +38 -25
- package/dist/ai/validation.js.map +1 -1
- package/dist/ai/zod-to-provider-schema.d.ts.map +1 -1
- package/dist/ai/zod-to-provider-schema.js +246 -16
- package/dist/ai/zod-to-provider-schema.js.map +1 -1
- package/dist/api/route-generator.d.ts +2 -12
- package/dist/api/route-generator.d.ts.map +1 -1
- package/dist/api/route-generator.js +33 -41
- package/dist/api/route-generator.js.map +1 -1
- package/dist/approvals/index.d.ts +1 -1
- package/dist/approvals/index.d.ts.map +1 -1
- package/dist/approvals/index.js.map +1 -1
- package/dist/approvals/memory-store.d.ts.map +1 -1
- package/dist/approvals/memory-store.js +22 -0
- package/dist/approvals/memory-store.js.map +1 -1
- package/dist/approvals/schema.d.ts +34 -0
- package/dist/approvals/schema.d.ts.map +1 -1
- package/dist/approvals/schema.js +2 -0
- package/dist/approvals/schema.js.map +1 -1
- package/dist/approvals/service.d.ts.map +1 -1
- package/dist/approvals/service.js +36 -0
- package/dist/approvals/service.js.map +1 -1
- package/dist/approvals/sql-store.d.ts.map +1 -1
- package/dist/approvals/sql-store.js +42 -1
- package/dist/approvals/sql-store.js.map +1 -1
- package/dist/approvals/types.d.ts +11 -0
- package/dist/approvals/types.d.ts.map +1 -1
- package/dist/approvals/types.js +1 -0
- package/dist/approvals/types.js.map +1 -1
- package/dist/audit/service.d.ts.map +1 -1
- package/dist/audit/service.js +16 -1
- package/dist/audit/service.js.map +1 -1
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +2 -1
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/commands/browser-extension.d.ts +16 -0
- package/dist/cli/commands/browser-extension.d.ts.map +1 -1
- package/dist/cli/commands/browser-extension.js +16 -5
- package/dist/cli/commands/browser-extension.js.map +1 -1
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +7 -1
- package/dist/cli/commands/dev.js.map +1 -1
- package/dist/cli/commands/e2e.d.ts +12 -0
- package/dist/cli/commands/e2e.d.ts.map +1 -1
- package/dist/cli/commands/e2e.js +11 -0
- package/dist/cli/commands/e2e.js.map +1 -1
- package/dist/cli/commands/generate-openapi-from-zod.d.ts.map +1 -1
- package/dist/cli/commands/generate-openapi-from-zod.js +9 -1
- package/dist/cli/commands/generate-openapi-from-zod.js.map +1 -1
- package/dist/cli/commands/index.d.ts +1 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +1 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +63 -3
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/migrate.d.ts.map +1 -1
- package/dist/cli/commands/migrate.js +8 -14
- package/dist/cli/commands/migrate.js.map +1 -1
- package/dist/cli/commands/payments.d.ts +56 -0
- package/dist/cli/commands/payments.d.ts.map +1 -0
- package/dist/cli/commands/payments.js +184 -0
- package/dist/cli/commands/payments.js.map +1 -0
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +2 -7
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/seed.d.ts.map +1 -1
- package/dist/cli/commands/seed.js +2 -7
- package/dist/cli/commands/seed.js.map +1 -1
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +9 -1
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/worker.js +1 -1
- package/dist/cli/commands/worker.js.map +1 -1
- package/dist/cli/discover.d.ts +2 -0
- package/dist/cli/discover.d.ts.map +1 -1
- package/dist/cli/discover.js +39 -5
- package/dist/cli/discover.js.map +1 -1
- package/dist/config/loader.d.ts +4 -1
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +112 -24
- package/dist/config/loader.js.map +1 -1
- package/dist/data/connection.d.ts +23 -0
- package/dist/data/connection.d.ts.map +1 -1
- package/dist/data/connection.js +23 -6
- package/dist/data/connection.js.map +1 -1
- package/dist/data/schema-generator.d.ts.map +1 -1
- package/dist/data/schema-generator.js +2 -2
- package/dist/data/schema-generator.js.map +1 -1
- package/dist/define/definePrompt.d.ts.map +1 -1
- package/dist/define/definePrompt.js +6 -0
- package/dist/define/definePrompt.js.map +1 -1
- package/dist/durable/index.d.ts +2 -2
- package/dist/durable/index.d.ts.map +1 -1
- package/dist/durable/index.js +2 -2
- package/dist/durable/index.js.map +1 -1
- package/dist/durable/postgres-persist.d.ts +47 -2
- package/dist/durable/postgres-persist.d.ts.map +1 -1
- package/dist/durable/postgres-persist.js +152 -6
- package/dist/durable/postgres-persist.js.map +1 -1
- package/dist/durable/spine-claim.d.ts +22 -1
- package/dist/durable/spine-claim.d.ts.map +1 -1
- package/dist/durable/spine-claim.js +54 -3
- package/dist/durable/spine-claim.js.map +1 -1
- package/dist/events/dispatcher.d.ts +20 -0
- package/dist/events/dispatcher.d.ts.map +1 -1
- package/dist/events/dispatcher.js +61 -26
- package/dist/events/dispatcher.js.map +1 -1
- package/dist/events/pipeline-audit.d.ts +14 -0
- package/dist/events/pipeline-audit.d.ts.map +1 -0
- package/dist/events/pipeline-audit.js +29 -0
- package/dist/events/pipeline-audit.js.map +1 -0
- package/dist/events/worker.d.ts +3 -0
- package/dist/events/worker.d.ts.map +1 -1
- package/dist/events/worker.js +14 -14
- package/dist/events/worker.js.map +1 -1
- package/dist/execution/capability-error-hook.d.ts +24 -0
- package/dist/execution/capability-error-hook.d.ts.map +1 -0
- package/dist/execution/capability-error-hook.js +17 -0
- package/dist/execution/capability-error-hook.js.map +1 -0
- package/dist/execution/capability-executor.d.ts +2 -2
- package/dist/execution/capability-executor.d.ts.map +1 -1
- package/dist/execution/capability-executor.js +45 -7
- package/dist/execution/capability-executor.js.map +1 -1
- package/dist/execution/context-factory.d.ts.map +1 -1
- package/dist/execution/context-factory.js +9 -1
- package/dist/execution/context-factory.js.map +1 -1
- package/dist/execution/deferred-flow-service.d.ts.map +1 -1
- package/dist/execution/deferred-flow-service.js +7 -0
- package/dist/execution/deferred-flow-service.js.map +1 -1
- package/dist/execution/index.d.ts +1 -0
- package/dist/execution/index.d.ts.map +1 -1
- package/dist/execution/index.js.map +1 -1
- package/dist/fields/index.d.ts +7 -0
- package/dist/fields/index.d.ts.map +1 -1
- package/dist/fields/index.js +10 -1
- package/dist/fields/index.js.map +1 -1
- package/dist/flows/dead-letter.d.ts +18 -1
- package/dist/flows/dead-letter.d.ts.map +1 -1
- package/dist/flows/dead-letter.js +17 -1
- package/dist/flows/dead-letter.js.map +1 -1
- package/dist/flows/engine.d.ts +16 -1
- package/dist/flows/engine.d.ts.map +1 -1
- package/dist/flows/engine.js +218 -29
- package/dist/flows/engine.js.map +1 -1
- package/dist/flows/flow-service.d.ts.map +1 -1
- package/dist/flows/flow-service.js +3 -0
- package/dist/flows/flow-service.js.map +1 -1
- package/dist/flows/step-executor.d.ts +8 -0
- package/dist/flows/step-executor.d.ts.map +1 -1
- package/dist/flows/step-executor.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/runtime/bootstrap.d.ts +18 -1
- package/dist/runtime/bootstrap.d.ts.map +1 -1
- package/dist/runtime/bootstrap.js +36 -5
- package/dist/runtime/bootstrap.js.map +1 -1
- package/dist/runtime/load-extensions.d.ts +2 -1
- package/dist/runtime/load-extensions.d.ts.map +1 -1
- package/dist/runtime/load-extensions.js +49 -1
- package/dist/runtime/load-extensions.js.map +1 -1
- package/dist/runtime/register-consumers.d.ts +3 -0
- package/dist/runtime/register-consumers.d.ts.map +1 -1
- package/dist/runtime/register-consumers.js +27 -6
- package/dist/runtime/register-consumers.js.map +1 -1
- package/dist/runtime/start-worker-pool.d.ts.map +1 -1
- package/dist/runtime/start-worker-pool.js +36 -15
- package/dist/runtime/start-worker-pool.js.map +1 -1
- package/dist/server/bootstrap.d.ts +42 -16
- package/dist/server/bootstrap.d.ts.map +1 -1
- package/dist/server/bootstrap.js +91 -21
- package/dist/server/bootstrap.js.map +1 -1
- package/dist/testing/context.d.ts +2 -0
- package/dist/testing/context.d.ts.map +1 -1
- package/dist/testing/context.js +8 -3
- package/dist/testing/context.js.map +1 -1
- package/dist/testing/field-validation.d.ts.map +1 -1
- package/dist/testing/field-validation.js +3 -0
- package/dist/testing/field-validation.js.map +1 -1
- package/dist/types/config.d.ts +13 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/context.d.ts +70 -4
- package/dist/types/context.d.ts.map +1 -1
- package/dist/types/fields.d.ts +6 -0
- package/dist/types/fields.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/prompt.d.ts +9 -0
- package/dist/types/prompt.d.ts.map +1 -1
- package/dist/worker/bootstrap.d.ts +19 -0
- package/dist/worker/bootstrap.d.ts.map +1 -1
- package/dist/worker/bootstrap.js +156 -84
- package/dist/worker/bootstrap.js.map +1 -1
- package/instructions/README.md +4 -1
- package/instructions/ai-classification.md +132 -0
- package/instructions/ai.md +94 -15
- package/instructions/cli.md +19 -1
- package/instructions/entities.md +3 -1
- package/instructions/flows.md +6 -0
- package/instructions/framework.md +13 -3
- package/instructions/peer-dependencies.md +2 -1
- package/instructions/prompts.md +2 -1
- package/migrations/durable-tenant/0002_approval_cancellation.sql +3 -0
- package/migrations/durable-tenant/meta/_journal.json +7 -0
- package/package.json +6 -5
- package/dist/ai/__typecheck-fixtures__/legacy-cost-api.d.ts +0 -5
- package/dist/ai/__typecheck-fixtures__/legacy-cost-api.d.ts.map +0 -1
- package/dist/ai/__typecheck-fixtures__/legacy-cost-api.js +0 -15
- package/dist/ai/__typecheck-fixtures__/legacy-cost-api.js.map +0 -1
package/instructions/ai.md
CHANGED
|
@@ -31,6 +31,20 @@ Prompts should NOT hardcode `provider` or model `name` unless you have a deliber
|
|
|
31
31
|
|
|
32
32
|
## `ctx.ai` Operations
|
|
33
33
|
|
|
34
|
+
## Provider admission and trace propagation
|
|
35
|
+
|
|
36
|
+
Hosts can export `aiProviderConcurrency`, `resolveAIProviderHeaders`, and `onAIProviderSpan`
|
|
37
|
+
from `app/server.ts`. The concurrency ceiling is shared by every identity-bound AI service and
|
|
38
|
+
defaults to a scope of provider + tenant + `costContext.serviceArea`; saturation throws the
|
|
39
|
+
structured `ai-provider-concurrency-exhausted` refusal immediately rather than waiting. Override
|
|
40
|
+
`resolveScope` only when the host has another non-private package/workload key.
|
|
41
|
+
|
|
42
|
+
`resolveAIProviderHeaders` is called for every real provider attempt, including validation retries
|
|
43
|
+
and streams. Use it for W3C `traceparent`/`tracestate`; credential and content-type headers are
|
|
44
|
+
reserved and refused. `onAIProviderSpan` receives the completed client span and is best effort:
|
|
45
|
+
exporter failures never change the model-call result. Flow workers receive the persisted flow
|
|
46
|
+
correlation id in the same hook, so a host can preserve one trace across request → flow → provider.
|
|
47
|
+
|
|
34
48
|
### Generate
|
|
35
49
|
|
|
36
50
|
Invoke a named prompt with typed input, get validated output:
|
|
@@ -56,6 +70,11 @@ const invoice = await ctx.ai.extract({
|
|
|
56
70
|
|
|
57
71
|
### Classify
|
|
58
72
|
|
|
73
|
+
**Start with [the classification recipe](ai-classification.md)** for provider/model
|
|
74
|
+
selection, TypeSafe/Jev, Laya, and OpenAI Decisions registration, defaults, thresholds,
|
|
75
|
+
and cost hooks (core **0.7.4+** / **0.8.0-beta.6+**). Use `classify()` for matching labels and `decide()`
|
|
76
|
+
for richer typed questions. Keep calls inside capabilities/flows.
|
|
77
|
+
|
|
59
78
|
Classify text into provided categories:
|
|
60
79
|
|
|
61
80
|
```ts
|
|
@@ -74,6 +93,8 @@ const docs = await ctx.ai.retrieve({ query: "refund policy for enterprise custom
|
|
|
74
93
|
// docs: Array<{ content: string, source: string, score: number, metadata?: Record<string, unknown> }>
|
|
75
94
|
```
|
|
76
95
|
|
|
96
|
+
`retrieve` passes its `signal` (inside flow steps `ctx.signal` by default) through the RAG pipeline to the adapter's `embed()` as `EmbeddingRequest.signal`: an abort ends the in-flight embedding request and skips the vector search. RAG `ingest`/`retrieve` take `signal` too. A custom `AIProviderAdapter.embed()` must pass `request.signal` to its transport.
|
|
97
|
+
|
|
77
98
|
Ingest documents with `plumbus rag ingest <path>` (see `cli.md`).
|
|
78
99
|
|
|
79
100
|
### Generate With Usage
|
|
@@ -89,6 +110,12 @@ const { data, usage, model, provider, cost } = await ctx.ai.generateWithUsage({
|
|
|
89
110
|
|
|
90
111
|
`generateWithUsage` is **overloaded**: called without `tools` (as above) it returns the flat `AIFinalGenerateResult` — `.data` is always present, plus a `finishReason`. Called **with** `tools` it returns the discriminated `AIToolEnabledGenerateResult` (see [Tool calling](#tool-calling-provider-native)).
|
|
91
112
|
|
|
113
|
+
On OpenAI reasoning models `usage.reasoningTokens` is the reasoning share of `outputTokens` (Chat Completions and the Responses API alike, summed over validation retries); it is already priced inside `outputTokens`, so never add it to a cost yourself.
|
|
114
|
+
|
|
115
|
+
With `enableStrictStructuredOutputs`, the OpenAI adapter sends an output whose root is not an object (`classify()`, a `z.array`/union/enum `extract()` schema or prompt `output`) inside a `{"value": …}` envelope and unwraps the answer itself, merges an `allOf` of several `.regex()`s into one schema, and names a `.default()` in the description (strict mode has no `default`); Zod still validates the original. For every provider the schema converter merges intersections of objects (`a.and(b)`, `a.and(b.optional())`, `a.and(b.nullable())`) into one object, sends `z.string().cidr()` as IPv4-or-IPv6 patterns, a tuple as an array of its item schemas (order in the description), and an optional output root as the value itself. Nothing to do in app code.
|
|
116
|
+
|
|
117
|
+
`usage.cacheWriteTokens` counts prompt tokens written to the provider cache (Anthropic, and OpenAI's `cache_write_tokens` on Chat Completions and the Responses API); like `cachedInputTokens` it is part of `inputTokens`. Cost charges them 1.25× input on Claude and OpenAI GPT-5.6+, and the input rate on earlier OpenAI models.
|
|
118
|
+
|
|
92
119
|
`generateWithUsage` also accepts per-call `provider`, `model`, and provider-neutral `reasoning` overrides:
|
|
93
120
|
|
|
94
121
|
```ts
|
|
@@ -101,11 +128,27 @@ await ctx.ai.generateWithUsage({
|
|
|
101
128
|
});
|
|
102
129
|
```
|
|
103
130
|
|
|
104
|
-
|
|
131
|
+
A per-call `timeoutMs` (on `generate`, `generateWithUsage`, `streamGenerate`, `extract`, `classify`, `retrieve` and `runToolLoop`; `timeout` on `EmbeddingRequest`, `timeoutMs` on RAG `ingest`/`retrieve`) overrides the prompt's `model.timeoutMs` and the provider's `requestTimeout` for that call; see `prompts.md`. A request its timeout ends throws a non-retryable `ProviderAPIError` carrying `timeoutMs`; detect it with `isProviderTimeoutError(error)` from `@plumbus/core` (`isProviderAPIError` for any provider HTTP failure) instead of checking the error's shape, and raise the timeout rather than retrying.
|
|
132
|
+
|
|
133
|
+
Omit `reasoning` to inherit prompt/config; use `null` to restore the provider/model default for one call, clearing both inherited `reasoning` and inherited legacy `reasoningEffort`. Explicit modes are `{ mode:'disabled' }`, `{ mode:'effort', effort:'minimal'|'low'|'medium'|'high'|'xhigh'|'max' }`, and `{ mode:'budget', maxTokens }`. Built-in core adapters translate the intent: OpenAI uses Chat Completions normally and switches caller-tool requests, and the `structuredOutputTransport:'tool'` function, that need active/default GPT-5.6 or GPT-6 reasoning to the Responses API; Anthropic uses `thinking` + `output_config.effort`. GPT-6 Chat Completions use `max_completion_tokens`; GPT-6 requests omit sampling temperature unless reasoning is explicitly disabled. Responses tool continuations are stateless (`store:false`) and preserve encrypted reasoning items through server-owned `providerState`. Custom providers translate the contract in their own `AIProviderAdapter`. Unsupported modes fail with `AIInvalidRequestError` before provider I/O when the adapter can identify the incompatibility. No GPT-6 model accepts effort `minimal`, and `gpt-6-astra` / `gpt-6.1-sol` have no off switch (`{ mode:'disabled' }` fails; use `low`). Claude Fable 5.1/5, Mythos 5.1/5/Preview, Opus 5.5/5/4.8/4.7, Sonnet 5.5/5, and Haiku 5.5 reject any `temperature` other than 1, so Plumbus omits both its `0.7` default and any explicitly configured temperature for them. On those models disabled is sent as `thinking: { type: 'between_tools' }` on `claude-sonnet-5-5` and fails on Opus 5.5, Fable, and Mythos (thinking cannot be turned off; lower the effort), and budgets fail on all but `claude-mythos-preview`. Deprecated `reasoningEffort` remains the unchanged OpenAI-only `'low' | 'medium' | 'high'` shorthand.
|
|
134
|
+
|
|
135
|
+
### Prompt caching (Anthropic / Bedrock)
|
|
136
|
+
|
|
137
|
+
Included in this beta family (stable core **0.7.9+**). Pass `cache: true` (system + tools) or `{ system?, tools?, messages? }` on `generate` / `generateWithUsage` / `streamGenerate` / `runToolLoop`. To make it the default for every call, set `AI_PROMPT_CACHE=true` (or sections such as `system,messages`); a per-call `cache` overrides it. Anthropic gets `cache_control`; Bedrock Claude gets Converse `cachePoint` (`@plumbus/ai-bedrock` from this beta family, or stable 0.2.2+), except Claude 3 Haiku / Sonnet / Opus and Claude 3.5 Sonnet `20240620`, which reject it, and Claude 3.5 Sonnet v2 (Preview-only on Bedrock). OpenAI and non-Claude Bedrock models ignore the option. Shorter prompts may not meet provider minima — the call still succeeds.
|
|
138
|
+
|
|
139
|
+
`cache: true` marks only the system prompt and tools. In a single-turn call, a prompt's `description` and its input go into the user message, so keep long, stable instructions in `system`. In multi-turn mode (`messages` set), the description and `Input: {...}` are merged into the system prompt, so an input that changes between turns writes a new cache entry every turn.
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
await ctx.ai.generateWithUsage({
|
|
143
|
+
prompt: 'classifyTicket',
|
|
144
|
+
input: { ticketText },
|
|
145
|
+
cache: true,
|
|
146
|
+
});
|
|
147
|
+
```
|
|
105
148
|
|
|
106
149
|
### Tool calling (provider-native)
|
|
107
150
|
|
|
108
|
-
Pass `tools` to `generate` / `generateWithUsage` to let the model call functions natively. Both built-in adapters implement caller tools on the wire (OpenAI `tools`/`tool_calls`; Anthropic `tool_use`/`tool_result` + `input_schema`). Build each `AITool.parameters` from `zodToProviderJsonSchema(schema).schema`:
|
|
151
|
+
Pass `tools` to `generate` / `generateWithUsage` to let the model call functions natively. Both built-in adapters implement caller tools on the wire (OpenAI `tools`/`tool_calls`; Anthropic `tool_use`/`tool_result` + `input_schema`). OpenAI caller tools are non-strict on both transports (the Responses API gets an explicit `strict: false`, since it would otherwise make every property required and the model would invent values for optional arguments), so optional arguments stay optional; still validate `call.arguments` with the tool's Zod input schema. Build each `AITool.parameters` from `zodToProviderJsonSchema(schema).schema`:
|
|
109
152
|
|
|
110
153
|
```ts
|
|
111
154
|
import type { AITool } from "@plumbus/core";
|
|
@@ -155,7 +198,7 @@ const { final, messages, rounds } = await runToolLoop(ctx.ai, {
|
|
|
155
198
|
// final is a flat AIFinalGenerateResult; final.data is the answer.
|
|
156
199
|
```
|
|
157
200
|
|
|
158
|
-
`runToolLoop` defaults to `maxRounds: 8` (hard cap 20). On round exhaustion it makes ONE final request that **omits both `tools` and `toolChoice`** (never `toolChoice: 'none'`), so it always resolves to a non-tool answer. Invalid-argument tool calls are **never** executed — they surface to the model as a bounded `tool_arguments_invalid` observation. Observations are byte-bounded and wrapped in an `untrusted_tool_result` envelope.
|
|
201
|
+
`runToolLoop` defaults to `maxRounds: 8` (hard cap 20). On round exhaustion it makes ONE final request that **omits both `tools` and `toolChoice`** (never `toolChoice: 'none'`), so it always resolves to a non-tool answer. Invalid-argument tool calls are **never** executed — they surface to the model as a bounded `tool_arguments_invalid` observation. Observations are byte-bounded and wrapped in an `untrusted_tool_result` envelope. Pass `cache: true` to reuse the cached system prompt and tools across rounds (core 0.7.9+); it is forwarded to every request.
|
|
159
202
|
|
|
160
203
|
An external `AIProviderAdapter` that omits the optional `capabilities` field is treated as declaring every capability `false` (no tool support).
|
|
161
204
|
|
|
@@ -251,9 +294,11 @@ AI_ANTHROPIC_BASE_URL=https://custom-anthropic.com # optional
|
|
|
251
294
|
AI_ANTHROPIC_MODEL=claude-sonnet-4-20250514
|
|
252
295
|
```
|
|
253
296
|
|
|
297
|
+
Each provider slot (`AI_` single-provider, `AI_OPENAI_`, `AI_ANTHROPIC_`, `AI_BEDROCK_`) also reads `REQUEST_TIMEOUT` (a whole number of ms from 1 to 2147483647), `MAX_TOKENS` (a whole number of tokens, 0 or more) and `DAILY_COST_LIMIT` (US dollars, 0 or more, e.g. `10.5`); Bedrock also `AI_BEDROCK_PRICING_TTL_MS` (whole ms, 0 or more). Write plain numbers, never units: `15m`, `4k`, `$50` or `abc` make `loadConfig()` throw naming the variable (e.g. `Invalid AI_OPENAI_REQUEST_TIMEOUT="15m": expected a whole number of milliseconds from 1 to 2147483647`), so the process does not start; a blank value is unset.
|
|
298
|
+
|
|
254
299
|
### Amazon Bedrock
|
|
255
300
|
|
|
256
|
-
Requires `@plumbus/core` **≥ 0.
|
|
301
|
+
Requires `@plumbus/core` **≥ 0.7.0** (prompt caching needs core **≥ 0.7.9** and `@plumbus/ai-bedrock` **≥ 0.2.2**).
|
|
257
302
|
|
|
258
303
|
```bash
|
|
259
304
|
pnpm add @plumbus/ai-bedrock
|
|
@@ -288,14 +333,22 @@ Set a global fallback model that all prompts use unless overridden:
|
|
|
288
333
|
AI_DEFAULT_MODEL=gpt-4o
|
|
289
334
|
```
|
|
290
335
|
|
|
336
|
+
### Default Prompt Caching
|
|
337
|
+
|
|
338
|
+
Turn on Anthropic / Bedrock prompt caching for every call (see [Prompt caching](#prompt-caching-anthropic--bedrock)):
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
AI_PROMPT_CACHE=true # system + tools; or e.g. system,tools,messages
|
|
342
|
+
```
|
|
343
|
+
|
|
291
344
|
### Per-Prompt Overrides
|
|
292
345
|
|
|
293
|
-
Override model, provider, temperature, or
|
|
346
|
+
Override model, provider, temperature, maxTokens, or the request timeout for any specific prompt via env vars:
|
|
294
347
|
|
|
295
348
|
```bash
|
|
296
349
|
# Format: PROMPT_{NAME}_{FIELD}
|
|
297
350
|
# Name = prompt name with dots → underscores, UPPERCASED
|
|
298
|
-
# Fields: PROVIDER, MODEL, TEMPERATURE, MAX_TOKENS
|
|
351
|
+
# Fields: PROVIDER, MODEL, TEMPERATURE, MAX_TOKENS, TIMEOUT_MS
|
|
299
352
|
|
|
300
353
|
# Route "writer.write_chapter" to Anthropic:
|
|
301
354
|
PROMPT_WRITER_WRITE_CHAPTER_PROVIDER=anthropic
|
|
@@ -305,16 +358,19 @@ PROMPT_WRITER_WRITE_CHAPTER_MODEL=claude-sonnet-4-20250514
|
|
|
305
358
|
PROMPT_INTERVIEW_EXTRACT_METADATA_MODEL=gpt-4o-mini
|
|
306
359
|
```
|
|
307
360
|
|
|
361
|
+
The HTTP server and the worker pool (flows, jobs, event handlers) both apply these. Numeric fields are checked when the config loads — `TIMEOUT_MS` a whole number of ms from 1 to 2147483647, `MAX_TOKENS` a whole number ≥ 1, `TEMPERATURE` 0–2 — and anything else (`abc`, `0`, `15m`) makes `loadConfig()` throw naming the variable, so the process does not start; a blank value is no override.
|
|
362
|
+
|
|
308
363
|
### Model Resolution Chain
|
|
309
364
|
|
|
310
|
-
When a prompt is invoked,
|
|
365
|
+
When a prompt is invoked, each field (`provider`, `model`, `temperature`, `maxTokens`, `reasoning`, `timeoutMs`) is resolved on its own, first set wins:
|
|
311
366
|
|
|
312
|
-
1. **
|
|
313
|
-
2. **
|
|
314
|
-
3. **
|
|
315
|
-
4. **
|
|
367
|
+
1. **Per-call value** (`provider`, `model`, `reasoning`, `timeoutMs` on `generate` / `generateWithUsage` / `streamGenerate`)
|
|
368
|
+
2. **Dynamic overrides** (`resolveAiOverrides` hook's `promptOverrides`)
|
|
369
|
+
3. **Per-prompt env override** (`PROMPT_{NAME}_*`)
|
|
370
|
+
4. **Prompt definition** (`model` in `definePrompt`) — if set
|
|
371
|
+
5. **Defaults** — the hook's `defaultModel` / `defaultProvider`, else `AI_DEFAULT_MODEL` / `AI_DEFAULT_PROVIDER`
|
|
316
372
|
|
|
317
|
-
|
|
373
|
+
A layer decides only the fields it sets: a hook override `{ model: 'gpt-4.1-mini' }` keeps the prompt's `PROMPT_{NAME}_MAX_TOKENS` and `PROMPT_{NAME}_TIMEOUT_MS`. When an override changes `provider`, set `model` with it, or the model of a lower layer goes to the new provider. `reasoning` and the deprecated `reasoningEffort` count as one field: the highest layer that sets either decides both.
|
|
318
374
|
|
|
319
375
|
## Dynamic AI Config (DB Overrides)
|
|
320
376
|
|
|
@@ -330,14 +386,14 @@ export const resolveAiOverrides: NonNullable<ServerConfig['resolveAiOverrides']>
|
|
|
330
386
|
return {
|
|
331
387
|
defaultModel: 'gpt-4o', // override global default
|
|
332
388
|
defaultProvider: 'openai', // override global provider
|
|
333
|
-
promptOverrides: { // per-prompt overrides
|
|
334
|
-
|
|
389
|
+
promptOverrides: { // per-prompt overrides, keyed by prompt name
|
|
390
|
+
'interview.ask_next_question': { model: 'gpt-4o', temperature: 0.7 },
|
|
335
391
|
},
|
|
336
392
|
};
|
|
337
393
|
};
|
|
338
394
|
```
|
|
339
395
|
|
|
340
|
-
The framework calls this hook before each `generate()`, `generateWithUsage()`, and `streamGenerate()` call.
|
|
396
|
+
The framework calls this hook before each `generate()`, `generateWithUsage()`, and `streamGenerate()` call, on the HTTP server and the worker pool alike. Its answer replaces the previous one (an override it stops returning no longer applies) and sits above the env config field by field, as in the chain above; unset fields keep the env and prompt values. Key `promptOverrides` by the prompt's name (`interview.ask_next_question`) or its env-style key (`interview_ask_next_question`, lower case, dots → underscores); when both are present, the entry under the name wins.
|
|
341
397
|
|
|
342
398
|
**Important**: The resolver should implement caching (e.g. 60-second TTL) to avoid querying the database on every AI call. API credentials (API keys) always come from environment variables — only model selection, temperature, and maxTokens should be stored in the database.
|
|
343
399
|
|
|
@@ -368,3 +424,26 @@ See `docs/ai/ai-integration.md` and `docs/upgrading-contract-alignment.md` §12.
|
|
|
368
424
|
- With security configured, generate/stream/extract/classify apply the field-classification policy. Extract/classify use the `text` field; arbitrary free-text PII is not automatically detected. Explainability stores redacted input.
|
|
369
425
|
- Unknown prior spend rejects further requests when a dollar cap is configured. Local/unpriced providers still work without dollar caps; explicit free prices stay supported. Never supply fake zero costs to bypass budgets.
|
|
370
426
|
- Read [the security release checklist](./upgrading-security-release.md) before upgrading custom cost hooks or AI wrappers.
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
## Typed decisions (core 0.7.4+ / 0.8.0-beta.6+)
|
|
430
|
+
|
|
431
|
+
For choices, scores, and probabilities, use `ctx.ai.decide()` inside capabilities
|
|
432
|
+
and flows. Define reusable contracts with `defineDecision` from
|
|
433
|
+
`@plumbus/ai-decision`; CLI startup discovers `app/decisions/`. The shared contract
|
|
434
|
+
package is provided by core; install only the TypeSafe, Laya, or OpenAI Decisions
|
|
435
|
+
provider required by the app. Export `decisions = { providers, defaultProvider }` from
|
|
436
|
+
`app/server.ts` for both API and workers, using `createTypeSafeDecisionAdapter`,
|
|
437
|
+
`createLayaDecisionAdapter`, or `createOpenAIDecisionAdapter` at that server-owned
|
|
438
|
+
boundary. Do not register these adapters as text-completion providers or call them
|
|
439
|
+
directly for app business logic.
|
|
440
|
+
|
|
441
|
+
Core records `operation: 'decide'` with actual model, usage, cost, tenant/actor,
|
|
442
|
+
optional `decisionName`, and the caller's `costContext`. Existing
|
|
443
|
+
`onAICostRecorded(record, costContext, db)` hooks persist these rows; include the
|
|
444
|
+
new operation in any app-owned ledger enum/schema. Failed responses and cancelled
|
|
445
|
+
calls also produce rows. Unknown USD cost is null, never a free zero. Security
|
|
446
|
+
scans state and structured questions; budgets are checked before provider work.
|
|
447
|
+
Use `mockAI({ decide: result })` and test through `runCapability`/`simulateFlow`.
|
|
448
|
+
|
|
449
|
+
Guide: https://github.com/plumbus-framework/plumbus/blob/main/docs/ai/decision-providers.md
|
package/instructions/cli.md
CHANGED
|
@@ -183,7 +183,7 @@ plumbus start --port $PLUMBUS_START_PORT
|
|
|
183
183
|
plumbus start --port 8080 --host 127.0.0.1
|
|
184
184
|
```
|
|
185
185
|
|
|
186
|
-
Behind a load balancer set `TRUST_PROXY=true` (or a specific IP/CIDR) so Fastify trusts `X-Forwarded-*` headers. `app/server.ts` extension hooks (`onRoutesRegistered`, `resolveAiOverrides`, `onCapabilityError`, `onProcessError`, `onAICostRecorded`, `onFlowError`, `enableStrictStructuredOutputs`, `credentials`) are loaded automatically.
|
|
186
|
+
Behind a load balancer set `TRUST_PROXY=true` (or a specific IP/CIDR) so Fastify trusts `X-Forwarded-*` headers. `app/server.ts` extension hooks (`onRoutesRegistered`, `resolveAiOverrides`, `onCapabilityError`, `onProcessError`, `onAICostRecorded`, `onFlowError`, `enableStrictStructuredOutputs`, `credentials`, `authenticationRuntime`) are loaded automatically.
|
|
187
187
|
|
|
188
188
|
## Background work
|
|
189
189
|
|
|
@@ -228,6 +228,24 @@ If `@plumbus/mcp` is not installed, `plumbus mcp serve` prints `Run: pnpm add @p
|
|
|
228
228
|
|
|
229
229
|
Read `node_modules/@plumbus/core/instructions/mcp.md` and `node_modules/@plumbus/mcp/instructions/README.md` for MCP.
|
|
230
230
|
|
|
231
|
+
## Payments
|
|
232
|
+
|
|
233
|
+
For apps with the optional `@plumbus/payments` add-on. The commands load the `payments` export of `app/payments/index.ts`; core does not depend on the add-on.
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
# Check the payments config; --live also checks keys, webhook destinations, and the billing catalog at the provider
|
|
237
|
+
plumbus payments doctor --live --webhook-url https://api.example.com/payments/webhooks/stripe
|
|
238
|
+
|
|
239
|
+
# Create the provider's webhook destinations (prints each signing secret once; re-run after upgrading the add-on)
|
|
240
|
+
plumbus payments webhooks setup --url https://api.example.com/payments/webhooks/stripe
|
|
241
|
+
|
|
242
|
+
# Create or update the billing catalog (plans, prices, features, meters) from `billing` in the config
|
|
243
|
+
plumbus payments catalog sync
|
|
244
|
+
plumbus payments catalog check # read-only; exits 1 when the provider differs (CI)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Read `node_modules/@plumbus/payments/instructions/README.md` for payments.
|
|
248
|
+
|
|
231
249
|
## App Commands
|
|
232
250
|
|
|
233
251
|
Run custom command scripts defined in your project's `app/commands/` directory. Use this for setup scripts, data migration tasks, and other one-off operations that need framework infrastructure (DB, config, password hashing).
|
package/instructions/entities.md
CHANGED
|
@@ -35,7 +35,9 @@ export const User = defineEntity({
|
|
|
35
35
|
|-------------|-----------|-------|
|
|
36
36
|
| `field.id()` | UUID string | Primary key |
|
|
37
37
|
| `field.string(opts)` | Text | General text |
|
|
38
|
-
| `field.number(opts)` |
|
|
38
|
+
| `field.number(opts)` | 32-bit integer | Counts and small integers |
|
|
39
|
+
| `field.bigint(opts)` | 64-bit integer | Money in minor units (cents) and totals; JS number, safe integers only (core 0.7.7+) |
|
|
40
|
+
| `field.decimal(opts)` | Floating point | Measurements; never money |
|
|
39
41
|
| `field.boolean(opts)` | Boolean | |
|
|
40
42
|
| `field.timestamp(opts)` | Datetime | ISO timestamps |
|
|
41
43
|
| `field.json(opts)` | JSONB | Arbitrary structured data |
|
package/instructions/flows.md
CHANGED
|
@@ -114,6 +114,12 @@ retry: {
|
|
|
114
114
|
|
|
115
115
|
Steps that fail with transient errors are retried. Permanent failures stop the flow and move it to the dead-letter queue.
|
|
116
116
|
|
|
117
|
+
Operators can stop an open execution through the framework service. `ctx.flows.cancel(id)`
|
|
118
|
+
aborts the active step and runs every declared compensation for completed steps;
|
|
119
|
+
`ctx.flows.terminate(id)` aborts and closes the execution without compensation. Both leave the
|
|
120
|
+
execution in the terminal `cancelled` state, never `completed`; applications should audit the
|
|
121
|
+
operator, reason, and which action was chosen in their recovery capability.
|
|
122
|
+
|
|
117
123
|
## Compiled definitions
|
|
118
124
|
|
|
119
125
|
Scheduled flows use `createFlowScheduler` and `flow_schedules`. Set `schedule.catchUpPolicy` to `catch-up` for bounded missed-tick catch-up; default is `skip`. Do not add a second scheduler.
|
|
@@ -117,6 +117,10 @@ package.json # Private root — delegates scripts via pnpm -r
|
|
|
117
117
|
|
|
118
118
|
In monorepo mode the `app/` and `config/` directories live under `backend/`. The CLI auto-detects the layout.
|
|
119
119
|
|
|
120
|
+
### Discovery
|
|
121
|
+
|
|
122
|
+
The CLI registers every capability, entity, flow, event, prompt, and translation **exported** from a file under the matching `app/` directory (file names and nesting are free). An exported array, or a plain object without a `name` field, is expanded one level, so an add-on's collections register with one line each — for example `export const paymentCapabilities = payments.capabilities` and `export { paymentEntities } from '@plumbus/payments'`. A definition exported both alone and inside a collection is registered once.
|
|
123
|
+
|
|
120
124
|
## Framework-Provided Dependencies
|
|
121
125
|
|
|
122
126
|
The framework provides common dependencies — **consumer apps must NOT install them separately**. Import through the framework's subpath exports:
|
|
@@ -141,20 +145,24 @@ The framework provides common dependencies — **consumer apps must NOT install
|
|
|
141
145
|
|
|
142
146
|
## Server Extensions (`app/server.ts`)
|
|
143
147
|
|
|
144
|
-
The optional `app/server.ts` file exports hooks that customize server behavior. The framework auto-discovers this file on `plumbus dev` and `plumbus
|
|
148
|
+
The optional `app/server.ts` file exports hooks that customize server behavior. The framework auto-discovers this file on `plumbus dev`, `plumbus start`, and `plumbus worker`.
|
|
145
149
|
|
|
146
150
|
### Available Hooks
|
|
147
151
|
|
|
148
152
|
| Hook | When it fires | Use for |
|
|
149
153
|
|------|--------------|---------|
|
|
150
154
|
| `onRoutesRegistered` | After capability routes are registered | Adding custom routes (e.g. streaming endpoints) |
|
|
151
|
-
| `onCapabilityError` | After a capability returns a non-success result | Logging capability failures to a system log table |
|
|
155
|
+
| `onCapabilityError` | After a capability returns a non-success result in an HTTP route, flow step, job, or event handler (`info.source`: `'http'`, `'flow'`, `'job'`, `'event'`) | Logging capability failures to a system log table |
|
|
152
156
|
| `onFlowError` | After a flow fails permanently (retries exhausted) | Logging flow failures to a system log table |
|
|
153
157
|
| `onProcessError` | On uncaught exceptions, unhandled rejections, and Fastify-level errors | Logging process-level crashes that bypass capability/flow hooks |
|
|
154
158
|
| `resolveAiOverrides` | Before each AI call | Dynamic model/provider configuration from DB |
|
|
155
159
|
| `onAICostRecorded` | After each AI cost record is written | Custom cost analytics or billing hooks |
|
|
160
|
+
| `aiProviderConcurrency` | Around each provider attempt | Immediate per-tenant/provider/package concurrency admission |
|
|
161
|
+
| `resolveAIProviderHeaders` | Before each provider attempt | Trusted W3C propagation headers |
|
|
162
|
+
| `onAIProviderSpan` | After each provider attempt | Export provider client spans |
|
|
156
163
|
| `enableStrictStructuredOutputs` | Server bootstrap | Global toggle for strict structured-output mode |
|
|
157
164
|
| `credentials` | Server bootstrap | Optional host credential catalog (`export const credentials`). Passed to `createServer({ credentials })`. Names, types, refs, and public labels only — secrets stay in the host resolver. |
|
|
165
|
+
| `authenticationRuntime` | Server bootstrap (included in the 0.8 beta family; stable core 0.7.8+) | Browser sign-in with `@plumbus/auth` (`createAuthRuntime(...)`): the same value `createServer({ authenticationRuntime })` takes |
|
|
158
166
|
|
|
159
167
|
### Error Capture Coverage
|
|
160
168
|
|
|
@@ -162,12 +170,14 @@ The framework provides hooks for **every error category**:
|
|
|
162
170
|
|
|
163
171
|
| Error Type | Hook | Source Field |
|
|
164
172
|
|------------|------|-------------|
|
|
165
|
-
| Capability failure (handler throw, validation, access) | `onCapabilityError` | capability name, domain, error code |
|
|
173
|
+
| Capability failure (handler throw, validation, access) in HTTP routes, flow steps, jobs, and event handlers | `onCapabilityError` | capability name, domain, error code, `source` |
|
|
166
174
|
| Flow permanent failure (retries exhausted) | `onFlowError` | flow name, step, execution ID |
|
|
167
175
|
| Uncaught exception (process crash) | `onProcessError` | `source: 'uncaughtException'` |
|
|
168
176
|
| Unhandled promise rejection | `onProcessError` | `source: 'unhandledRejection'` |
|
|
169
177
|
| Fastify request error (malformed request, timeout) | `onProcessError` | `source: 'fastify'` |
|
|
170
178
|
|
|
179
|
+
`onCapabilityError` fires once per failed attempt: an event handler that fails on all N delivery attempts fires N times, and a retried flow step fires once per failed attempt. A failed job fires once. `sourceIp` and `userAgent` are set only for `source: 'http'`. Rejections before the capability runs (HTTP authentication, the worker's event/job payload and access checks) and nested `ctx.capabilities.invoke()` calls do not fire it.
|
|
180
|
+
|
|
171
181
|
### Example: Full Error Logging
|
|
172
182
|
|
|
173
183
|
```ts
|
|
@@ -22,6 +22,7 @@ The previous family remains on core 0.7.x, UI 0.8.x, MCP 0.6.x, voice 0.5.x, and
|
|
|
22
22
|
| `@plumbus/chat-ui` | `@plumbus/chat` | `">=0.3.0-beta.0 <0.4.0"` (stable: `"0.3.x"`) |
|
|
23
23
|
| `@plumbus/auth-cognito` | `@plumbus/auth` | `">=0.3.0-beta.0 <0.4.0"` (stable: `"0.3.x"`) |
|
|
24
24
|
| Every `@plumbus/voice-*` provider | `@plumbus/voice` | `">=0.6.0-beta.0 <0.7.0"` (stable: `"0.6.x"`) |
|
|
25
|
+
| `@plumbus/payments-stripe` | `@plumbus/payments` | `">=0.3.0-beta.0 <0.4.0"` (stable: `"0.3.x"`) |
|
|
25
26
|
|
|
26
27
|
UI 0.9.x keeps the required core peer (no direct core dependency) and uses `workspace:*` only for development. This prevents npm from accepting old application core plus a hidden new core nested inside UI. Install core and UI together. All Plumbus packages share the application runtime through peers.
|
|
27
28
|
|
|
@@ -43,4 +44,4 @@ Run lint, format checking, typechecking, tests, and packed npm install checks be
|
|
|
43
44
|
|
|
44
45
|
## Consumer upgrade
|
|
45
46
|
|
|
46
|
-
Read [upgrading-security-release.md](./upgrading-security-release.md) and the 0.8 notes in the root docs, explicitly select the new package versions for every installed Plumbus add-on, and run `plumbus init --patch` for agent wiring **
|
|
47
|
+
Read [upgrading-security-release.md](./upgrading-security-release.md) and the 0.8 notes in the root docs, explicitly select the new package versions for every installed Plumbus add-on, and run `plumbus init --patch --agent all` for current agent wiring (**v19** in this beta family and stable core 0.7.9+; v17 added the classification recipe). For classification/provider/model selection, read [ai-classification.md](./ai-classification.md). Keep application business logic in Plumbus primitives and `ctx.*`; do not bypass security checks to make a migration pass.
|
package/instructions/prompts.md
CHANGED
|
@@ -58,12 +58,13 @@ By default, any input keys not referenced as `{{key}}` in `system`/`description`
|
|
|
58
58
|
| `maxTokens` | number? | Max output tokens |
|
|
59
59
|
| `reasoning` | `{ mode:'disabled' } \| { mode:'effort', effort } \| { mode:'budget', maxTokens }?` | Provider-neutral reasoning intent; the selected adapter translates or explicitly rejects it |
|
|
60
60
|
| `reasoningEffort` | `'low' \| 'medium' \| 'high'?` | Deprecated OpenAI-only shorthand; unchanged for source/runtime compatibility |
|
|
61
|
+
| `timeoutMs` | number? | How long one provider request may take, in ms (whole number, 1–2147483647), the whole answer included; unset keeps the provider's `requestTimeout` (default 120 000). Raise it for long answers (large `maxTokens`, reasoning); a request it ends fails with a non-retryable `ProviderAPIError` carrying `timeoutMs` |
|
|
61
62
|
|
|
62
63
|
**Recommended convention:** omit `provider` and `name` in the prompt definition and resolve them via env (`AI_DEFAULT_PROVIDER`, `AI_DEFAULT_MODEL`, `PROMPT_{NAME}_*`) or the `resolveAiOverrides` hook in `app/server.ts`. Set only `temperature`, `maxTokens`, and (when needed) `reasoning` in the prompt when you want per-prompt tuning baked into the contract.
|
|
63
64
|
|
|
64
65
|
Bare `z.string()` prompt `output` schemas run in plain text mode (same as a single-string-field object). Prefer that for free-text prompts; use an object schema when you need structured fields.
|
|
65
66
|
|
|
66
|
-
Resolution order: `resolveAiOverrides` → per-prompt env vars → prompt `model` fields → `AI_DEFAULT_MODEL` / `AI_DEFAULT_PROVIDER
|
|
67
|
+
Resolution order, field by field (each of `provider`, `model`, `temperature`, `maxTokens`, `reasoning`, `timeoutMs` on its own): per-call value → `resolveAiOverrides` → per-prompt env vars → prompt `model` fields → defaults (the hook's `defaultModel` / `defaultProvider`, else `AI_DEFAULT_MODEL` / `AI_DEFAULT_PROVIDER`). A layer decides only the fields it sets, so a hook override of `model` keeps `PROMPT_{NAME}_TIMEOUT_MS` and `_MAX_TOKENS`; the hook's `promptOverrides` may be keyed by the prompt name or its env-style key (`report_summarize`), the name winning.
|
|
67
68
|
|
|
68
69
|
## Structured output and streaming flags
|
|
69
70
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plumbus/core",
|
|
3
|
-
"version": "0.8.0-beta.
|
|
3
|
+
"version": "0.8.0-beta.10",
|
|
4
4
|
"description": "Plumbus framework core — types, SDK, runtime, CLI, test utilities",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -89,7 +89,8 @@
|
|
|
89
89
|
"xml-crypto": "^6.1.2",
|
|
90
90
|
"xpath": "^0.0.34",
|
|
91
91
|
"zod": "^3.24.0",
|
|
92
|
-
"zod-to-json-schema": "^3.25.2"
|
|
92
|
+
"zod-to-json-schema": "^3.25.2",
|
|
93
|
+
"@plumbus/ai-decision": "~0.3.0-beta.1"
|
|
93
94
|
},
|
|
94
95
|
"peerDependencies": {
|
|
95
96
|
"@plumbus/api": ">=0.3.0-beta.0 <0.4.0",
|
|
@@ -121,10 +122,10 @@
|
|
|
121
122
|
"@vitest/browser": "^3.0.0",
|
|
122
123
|
"esbuild": "^0.25.12",
|
|
123
124
|
"typescript": "^5.7.0",
|
|
124
|
-
"@plumbus/
|
|
125
|
-
"@plumbus/voice": "0.6.0-beta.
|
|
125
|
+
"@plumbus/api": "0.3.0-beta.0",
|
|
126
|
+
"@plumbus/voice": "0.6.0-beta.1",
|
|
126
127
|
"@plumbus/mcp": "0.7.0-beta.0",
|
|
127
|
-
"@plumbus/
|
|
128
|
+
"@plumbus/ai-bedrock": "0.3.0-beta.1"
|
|
128
129
|
},
|
|
129
130
|
"scripts": {
|
|
130
131
|
"build": "tsc -b",
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { type AIService, type RAGPipelineConfig, type RunToolLoopParams } from '@plumbus/core';
|
|
2
|
-
export declare function legacyConsumer(ai: AIService, params: RunToolLoopParams): Promise<number>;
|
|
3
|
-
export declare const legacyEmbeddingCallback: RAGPipelineConfig['onEmbeddingCost'];
|
|
4
|
-
export declare const uncheckedEstimate: number;
|
|
5
|
-
//# sourceMappingURL=legacy-cost-api.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"legacy-cost-api.d.ts","sourceRoot":"","sources":["../../../src/ai/__typecheck-fixtures__/legacy-cost-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,SAAS,EACd,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACvB,MAAM,eAAe,CAAC;AAEvB,wBAAsB,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAM9F;AAED,eAAO,MAAM,uBAAuB,EAAE,iBAAiB,CAAC,iBAAiB,CAGxE,CAAC;AAGF,eAAO,MAAM,iBAAiB,EAAE,MAAyC,CAAC"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { calculateModelCost, estimateModelCost, runToolLoop, } from '@plumbus/core';
|
|
2
|
-
export async function legacyConsumer(ai, params) {
|
|
3
|
-
const result = await ai.generateWithUsage({ prompt: 'p', input: {} });
|
|
4
|
-
const cost = result.cost;
|
|
5
|
-
const loop = await runToolLoop(ai, params);
|
|
6
|
-
const total = loop.aggregatedCost;
|
|
7
|
-
return cost + total + calculateModelCost(1, 1, 'local');
|
|
8
|
-
}
|
|
9
|
-
export const legacyEmbeddingCallback = (info) => {
|
|
10
|
-
const numericCost = info.cost;
|
|
11
|
-
void numericCost;
|
|
12
|
-
};
|
|
13
|
-
// @ts-expect-error Unknown-aware estimates cannot be treated as definitely priced.
|
|
14
|
-
export const uncheckedEstimate = estimateModelCost(1, 1, 'local');
|
|
15
|
-
//# sourceMappingURL=legacy-cost-api.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"legacy-cost-api.js","sourceRoot":"","sources":["../../../src/ai/__typecheck-fixtures__/legacy-cost-api.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,GAIZ,MAAM,eAAe,CAAC;AAEvB,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,EAAa,EAAE,MAAyB;IAC3E,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IACtE,MAAM,IAAI,GAAW,MAAM,CAAC,IAAI,CAAC;IACjC,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAW,IAAI,CAAC,cAAc,CAAC;IAC1C,OAAO,IAAI,GAAG,KAAK,GAAG,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,CAAC,MAAM,uBAAuB,GAAyC,CAAC,IAAI,EAAE,EAAE;IACpF,MAAM,WAAW,GAAW,IAAI,CAAC,IAAI,CAAC;IACtC,KAAK,WAAW,CAAC;AACnB,CAAC,CAAC;AAEF,mFAAmF;AACnF,MAAM,CAAC,MAAM,iBAAiB,GAAW,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC"}
|