@leanandmean/coding-agent 0.74.1-scramjet.70 → 0.74.1-scramjet.71

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 (37) hide show
  1. package/README.md +14 -0
  2. package/dist/cli/args.d.ts +2 -0
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +44 -0
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/core/agent-session-services.d.ts +1 -0
  7. package/dist/core/agent-session-services.d.ts.map +1 -1
  8. package/dist/core/agent-session-services.js +1 -0
  9. package/dist/core/agent-session-services.js.map +1 -1
  10. package/dist/core/agent-session.d.ts +6 -2
  11. package/dist/core/agent-session.d.ts.map +1 -1
  12. package/dist/core/agent-session.js +23 -6
  13. package/dist/core/agent-session.js.map +1 -1
  14. package/dist/core/model-registry.d.ts +99 -0
  15. package/dist/core/model-registry.d.ts.map +1 -1
  16. package/dist/core/model-registry.js +93 -0
  17. package/dist/core/model-registry.js.map +1 -1
  18. package/dist/core/sdk.d.ts +2 -0
  19. package/dist/core/sdk.d.ts.map +1 -1
  20. package/dist/core/sdk.js +9 -1
  21. package/dist/core/sdk.js.map +1 -1
  22. package/dist/main.d.ts +105 -2
  23. package/dist/main.d.ts.map +1 -1
  24. package/dist/main.js +77 -3
  25. package/dist/main.js.map +1 -1
  26. package/dist/modes/interactive/components/model-selector.d.ts +1 -3
  27. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  28. package/dist/modes/interactive/components/model-selector.js +2 -5
  29. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  30. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  31. package/dist/modes/interactive/interactive-mode.js +1 -1
  32. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  33. package/docs/json.md +6 -0
  34. package/docs/models.md +69 -2
  35. package/docs/rpc.md +8 -0
  36. package/docs/sdk.md +17 -0
  37. package/package.json +4 -4
package/docs/json.md CHANGED
@@ -6,6 +6,12 @@ scramjet --mode json "Your prompt"
6
6
 
7
7
  Outputs all session events as JSON lines to stdout. Useful for integrating Scramjet into other tools or custom UIs.
8
8
 
9
+ ## Invocation-scoped models and failures
10
+
11
+ `--mode json` accepts `--model-definition '<JSON>'` or `--model-definition-env NAME` for a process-local compatible route. See [the complete contract](models.md#invocation-scoped-headless-models) for required deployment-evidenced limits, strict environment credentials, conflicts and persistence. The definition is not automatically activated by ambient environment variables.
12
+
13
+ Invalid definition/environment input fails startup with nonzero status. Generation failures may still exit zero in JSON mode: inspect finalized assistant `message_end` entries for `stopReason: "error"`/`"aborted"`, their `errorMessage`/diagnostics, and retry outcomes rather than treating process exit or `agent_end` as success. Explicit request failures do not silently switch routes; existing same-route recovery remains. Text print errors retain nonzero status; [RPC](rpc.md) separately distinguishes prompt acceptance from generation success. No new event shape or exit policy is introduced.
14
+
9
15
  ## Event Types
10
16
 
11
17
  Events are defined in [`AgentSessionEvent`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/agent-session.ts#L102):
package/docs/models.md CHANGED
@@ -4,6 +4,7 @@ Add custom providers and models (Ollama, vLLM, LM Studio, proxies) via `~/.scram
4
4
 
5
5
  ## Table of Contents
6
6
 
7
+ - [Invocation-scoped Headless Models](#invocation-scoped-headless-models)
7
8
  - [Minimal Example](#minimal-example)
8
9
  - [Full Example](#full-example)
9
10
  - [Supported APIs](#supported-apis)
@@ -14,6 +15,72 @@ Add custom providers and models (Ollama, vLLM, LM Studio, proxies) via `~/.scram
14
15
  - [Anthropic Messages Compatibility](#anthropic-messages-compatibility)
15
16
  - [OpenAI Compatibility](#openai-compatibility)
16
17
 
18
+ ## Invocation-scoped Headless Models
19
+
20
+ Use one model definition for a single headless invocation without editing `models.json` or installing an extension:
21
+
22
+ - `--model-definition '<JSON>'` supplies strict JSON directly.
23
+ - `--model-definition-env NAME` reads strict JSON from the named environment variable only when explicitly selected.
24
+
25
+ Both selectors accept `=value` forms. Missing values, repeated selectors, using both selectors, or combining either with `--provider`, `--model`, `--models` or `--api-key` are errors. Ambient definition variables alone never activate a route. Use `--thinking` separately: the model `id` is a nonblank literal backend ID, preserving case, slashes and colons without fuzzy matching, provider-prefix parsing or thinking-suffix interpretation.
26
+
27
+ Supported execution modes are `--print`, `--mode json`, `--mode rpc`, and print mode selected by redirected stdin. Actual interactive execution is rejected. Help/version need no credentials; `--list-models` can inspect a supplied definition without resolving its credential.
28
+
29
+ ### Definition fields
30
+
31
+ | Field | Requirement and meaning |
32
+ |-------|-------------------------|
33
+ | `api` | Required: `openai-completions`, `openai-responses`, `anthropic-messages`, or `google-generative-ai` |
34
+ | `baseUrl` | Required absolute HTTP(S) URL with a host; no userinfo, query, fragment, controls or whitespace. Supply the adapter-appropriate base path; there is no endpoint/version discovery. |
35
+ | `id` | Required nonblank literal backend model ID |
36
+ | `apiKeyEnv` | Required environment variable identifier containing a nonblank credential at startup |
37
+ | `contextWindow` | Required positive finite maximum supported total context; positive fractional values remain accepted |
38
+ | `maxTokens` | Required positive safe-integer maximum output allowance |
39
+ | `name` | Optional nonempty label; defaults to `id` |
40
+ | `reasoning` | Optional boolean; defaults to `false` |
41
+ | `input` | Optional array of `text`/`image` modalities; defaults to `["text"]` |
42
+ | `thinkingLevelMap` | Optional existing [thinking-level mapping](#thinking-level-map) |
43
+ | `compat` | Optional existing API-valid [OpenAI](#openai-compatibility) or [Anthropic](#anthropic-messages-compatibility) compatibility overrides; API-incompatible fields are rejected |
44
+ | `cost` | Optional complete finite-number `input`, `output`, `cacheRead`, `cacheWrite` estimates per million tokens; defaults to zero estimates |
45
+ | `maxInputTokens` | Optional positive finite independent input constraint, evidenced for the supplied route |
46
+ | `requestLimits` | Optional nonempty array of existing [joint endpoint constraints](#joint-endpoint-constraints) |
47
+
48
+ Unknown fields, including nested unsupported keys/values, are rejected. Credential literals, headers, provider identity, OAuth, custom stream functions, provider collections/overrides, file references and discovery configuration are not supported. JSON comments and trailing commas are rejected; input is never loaded from a file or evaluated as a shell command.
49
+
50
+ Obtain limits and capabilities from the actual deployment's applicable documentation/account metadata. `contextWindow` stays the total-context denominator; input constraints and output allocation remain separate. Output need not be less than total context: existing request-local allocation bounds feasible output without changing either scalar maximum. These estimates/checks do not establish backend acceptance, entitlement or exact serialized token counts. Omitted capabilities are client defaults, not capability evidence; zero cost estimates do not mean free billing. Existing adapter compatibility defaults still apply.
51
+
52
+ ### Example using caller deployment metadata
53
+
54
+ For a deployment confirmed to implement Chat Completions, set `DEPLOYMENT_BASE_URL`, `DEPLOYMENT_MODEL_ID`, `DEPLOYMENT_CONTEXT_WINDOW` and `DEPLOYMENT_MAX_OUTPUT` from its metadata, and export `ROUTE_API_KEY` from your credential source. Then, using `jq` to construct JSON:
55
+
56
+ ```sh
57
+ export ROUTE_DEFINITION="$(jq -n \
58
+ --arg baseUrl "$DEPLOYMENT_BASE_URL" \
59
+ --arg id "$DEPLOYMENT_MODEL_ID" \
60
+ --argjson contextWindow "$DEPLOYMENT_CONTEXT_WINDOW" \
61
+ --argjson maxTokens "$DEPLOYMENT_MAX_OUTPUT" \
62
+ '{api:"openai-completions",baseUrl:$baseUrl,id:$id,apiKeyEnv:"ROUTE_API_KEY",contextWindow:$contextWindow,maxTokens:$maxTokens}')"
63
+ scramjet --print --model-definition-env ROUTE_DEFINITION "Summarize this project"
64
+ # Equivalent inline selector, without putting the credential in JSON:
65
+ scramjet --mode json --model-definition "$ROUTE_DEFINITION" "Summarize this project"
66
+ ```
67
+
68
+ Both environment names must be valid identifiers with nonblank values. The credential is captured once, preserving its bytes; it is never interpreted as a shell command, second variable name or literal fallback. Missing credentials fail startup instead of borrowing saved/provider credentials. For an unauthenticated server, the caller may supply a nonblank placeholder in the named credential variable; Scramjet does not invent one. Definition metadata, including the URL, is nonsecret and normally visible through RPC/model output. Controlled input errors omit raw JSON, rejected URL contents and credential values; arbitrary remote echoes and trusted extensions are not covered by a universal redaction guarantee.
69
+
70
+ ### Lifetime, selection and persistence
71
+
72
+ Each invocation registers a fresh non-vendor `invocation-<UUID>` provider identity in memory and selects its exact model, bypassing saved startup defaults and scopes. Discover this generated identity through RPC `get_state`/`get_available_models`; concurrent invocations using the same backend ID remain independent. Credentials stay in runtime auth overrides, not model metadata or configuration.
73
+
74
+ Refresh/reload retain the registration. Replacement registries re-register the same captured definition/key. `new_session` inherits the live model/thinking after a deliberate switch; non-inherited session switch/fork/import selection uses the supplied definition. Explicit later model switching remains allowed: this is not a route lock or protection against arbitrary trusted extensions. No automatic forwarding of the complete route to subagents is provided.
75
+
76
+ All sessions created by a definition invocation opt out of saving model/thinking defaults, including later setters/cycling, replacements and switches to other models. Live state, events and ordinary journal model/thinking entries still change. Auth/model configuration remains unchanged; unrelated settings, journals and observational files may still be written. Use `--no-session` to disable journal saving, not as a general filesystem sandbox.
77
+
78
+ Endpoints/keys/limits are not revived from journal model identity. Resupply the definition in each fresh process. Reopening without selectors uses ordinary unavailable-model restoration warnings and default/available-model fallback; it is **not** fail-closed ordinary resume. An explicit invocation startup records its effective branch-local model/thinking identity using existing journal shapes.
79
+
80
+ Invalid definition/environment input fails before migrations/runtime construction with nonzero status. Explicit registration or request failures do not silently select a substitute route; existing retries/compaction may retry the same selected route. Text generation failures report errors and nonzero status. JSON generation errors can accompany exit zero: inspect finalized assistant error events. RPC prompt acceptance is not generation success: inspect subsequent events. See [JSON](json.md), [RPC](rpc.md) and [SDK preference persistence](sdk.md#model-preference-persistence).
81
+
82
+ `google-generative-ai` explicitly pins the generic API even when `GOOGLE_GENAI_USE_VERTEXAI` or `GOOGLE_GENAI_USE_ENTERPRISE` is set. This also applies to configured/dynamic models and direct generic AI streams. Vertex routing requires the existing explicit `google-vertex` API/configuration, which is outside invocation-definition support. Compatibility with every enterprise endpoint is not established; ambient cloud flags are not a supported migration mechanism.
83
+
17
84
  ## Minimal Example
18
85
 
19
86
  For local models (Ollama, LM Studio, vLLM), only `id` is required per model:
@@ -237,13 +304,13 @@ Current behavior:
237
304
 
238
305
  ### Thinking Level Map
239
306
 
240
- Use `thinkingLevelMap` on a model to describe model-specific thinking controls. Keys are scramjet thinking levels: `off`, `minimal`, `low`, `medium`, `high`, `xhigh`.
307
+ Use `thinkingLevelMap` on a model to describe model-specific thinking controls. Keys are scramjet thinking levels: `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max`.
241
308
 
242
309
  Values are tristate:
243
310
 
244
311
  | Value | Meaning |
245
312
  |-------|---------|
246
- | omitted | Level is supported and uses the provider's default mapping |
313
+ | omitted | Ordinary levels use the provider's default mapping; `xhigh` and `max` require explicit string mappings to be supported |
247
314
  | string | Level is supported and this value is sent to the provider |
248
315
  | `null` | Level is unsupported and hidden/skipped/clamped away |
249
316
 
package/docs/rpc.md CHANGED
@@ -16,6 +16,14 @@ Common options:
16
16
  - `--no-session`: Disable session persistence
17
17
  - `--session-dir <path>`: Custom session storage directory
18
18
 
19
+ ### Invocation-scoped model startup
20
+
21
+ Start with `scramjet --mode rpc --model-definition-env ROUTE_DEFINITION` or `--model-definition '<JSON>'`. See [the complete field/conflict contract](models.md#invocation-scoped-headless-models); credentials come only from the definition's `apiKeyEnv`. These selectors cannot be combined with `--provider`, `--model`, `--models` or `--api-key`.
22
+
23
+ `get_state` and `get_available_models` expose the normal full model, including nonsecret endpoint/limits and a generated `invocation-<UUID>` provider, but not the captured credential. Use that returned provider and literal ID for later `set_model`. Model/thinking setters and cycling remain supported without saving default model/thinking preferences, even after switching models. `new_session` inherits the live selection; `switch_session` uses the supplied invocation model. All replacement registries retain the same definition/key and opt-out policy.
24
+
25
+ Ordinary journal persistence remains enabled unless `--no-session` is supplied. Resupply the definition in a fresh process; reopening without it uses ordinary unavailable-model restoration warnings/fallback and never revives the endpoint/key. Invalid definitions/missing environment values fail startup with nonzero status before protocol service construction. A successful `prompt` response means acceptance, not successful generation: authentication, transport and stream failures arrive in subsequent assistant error/events, without silent route substitution. This feature does not change JSONL framing or RPC command/result shapes.
26
+
19
27
  ## Protocol Overview
20
28
 
21
29
  - **Commands**: JSON objects sent to stdin, one per line
package/docs/sdk.md CHANGED
@@ -438,6 +438,19 @@ For each built-in provider request, `createAgentSession()` binds the current ext
438
438
 
439
439
  > See [examples/sdk/02-custom-model.ts](../examples/sdk/02-custom-model.ts)
440
440
 
441
+ ### Model preference persistence
442
+
443
+ `createAgentSession()` and `createAgentSessionFromServices()` accept optional `persistModelPreferences` (default `true`); it is also available on `AgentSessionConfig`. Pass `false` to preserve saved default provider/model/thinking while allowing direct selection, both model-cycling paths and thinking changes to update live state, events and journal entries. Authentication and thinking clamping are unchanged. In an opt-out session, actual thinking-level changes on reasoning-capable models are remembered locally across non-reasoning detours, including an explicit `off` choice; the saved default remains unchanged. This local preference is not a new journal field or replacement-session inheritance value. With this opt-out, explicit startup selection also records changed branch-local model/thinking identity when opening an existing journal.
444
+
445
+ ```typescript
446
+ const { session } = await createAgentSession({
447
+ model: myModel,
448
+ persistModelPreferences: false,
449
+ });
450
+ ```
451
+
452
+ This is not blanket settings suppression: unrelated settings writes remain possible. Runtime factories must forward the policy to every replacement session. The CLI's [invocation-definition selectors](models.md#invocation-scoped-headless-models) do this automatically, register the captured route through existing `ModelRegistry.registerProvider()`, and supply its credential through `AuthStorage.setRuntimeApiKey()`. Ingress helpers are not new package-root SDK exports; programmatic callers can continue using those existing registry/auth APIs. Journal identity alone cannot reconstruct an endpoint or credential in a fresh process.
453
+
441
454
  ### Context and output allocation
442
455
 
443
456
  Models and usage expose one authoritative total `contextWindow`; `contextWindowBudget` and `getContextWindowBudget()` are removed. See [the migration guide](models.md#breaking-migration-from-context-budgets) before updating external model definitions or consumers.
@@ -1053,6 +1066,10 @@ const mode = new InteractiveMode(runtime, {
1053
1066
  await mode.run();
1054
1067
  ```
1055
1068
 
1069
+ `/model` selection delegates preference persistence to the session, including `persistModelPreferences: false`.
1070
+
1071
+ **Component migration:** the exported `ModelSelectorComponent` constructor no longer takes `settingsManager` as its third argument. Use `(tui, currentModel, modelRegistry, scopedModels, onSelect, onCancel, initialSearchInput?, outputThroughputHistory?)`; the selection callback must perform model selection through `session.setModel(model)` to retain authentication, journaling and preference policy. The component itself does not save defaults.
1072
+
1056
1073
  ### runPrintMode
1057
1074
 
1058
1075
  Single-shot mode: send prompts, output result, exit:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leanandmean/coding-agent",
3
- "version": "0.74.1-scramjet.70",
3
+ "version": "0.74.1-scramjet.71",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -37,9 +37,9 @@
37
37
  "test": "vitest --run --passWithNoTests"
38
38
  },
39
39
  "dependencies": {
40
- "@leanandmean/agent": "0.74.1-scramjet.49",
41
- "@leanandmean/ai": "0.74.1-scramjet.45",
42
- "@leanandmean/tui": "0.74.1-scramjet.42",
40
+ "@leanandmean/agent": "0.74.1-scramjet.50",
41
+ "@leanandmean/ai": "0.74.1-scramjet.46",
42
+ "@leanandmean/tui": "0.74.1-scramjet.43",
43
43
  "@silvia-odwyer/photon-node": "^0.3.4",
44
44
  "chalk": "^5.5.0",
45
45
  "dictionary-en": "^4.0.0",