bazis 0.100.4 → 0.100.5

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.
@@ -232,7 +232,7 @@ export class CodexAppServerClient implements CodexClient {
232
232
  if (method === "account/updated") this.modelCache = undefined;
233
233
  }, () => { this.clearLogin(); this.modelCache = undefined; });
234
234
  const initialized = await client.request("initialize", {
235
- clientInfo: { name: "bazis", title: "Bazis", version: "0.100.4" }, capabilities: { experimentalApi: true },
235
+ clientInfo: { name: "bazis", title: "Bazis", version: "0.100.5" }, capabilities: { experimentalApi: true },
236
236
  }, 15_000, signal);
237
237
  if (resolve(text(initialized.codexHome, 4096)) !== this.paths.home) throw new CodexError("PROTOCOL_ERROR");
238
238
  client.notify("initialized");
@@ -31,7 +31,9 @@ export interface LlmConnectorOptions {
31
31
  /**
32
32
  * Check the provider at start (the adapter's `connect`: `GET /models` for an
33
33
  * OpenAI-compatible API, five seconds), so a wrong key or address stops the
34
- * start instead of the first agent request. Default `true`.
34
+ * start instead of the first agent request. By default it runs in
35
+ * development and production and not in the `test` environment, where a
36
+ * test replaces the model; `true` checks there too, `false` never checks.
35
37
  */
36
38
  readonly checkOnStart?: boolean;
37
39
  }
@@ -92,7 +94,7 @@ export function llmConnect<T extends LlmConfigShape>(
92
94
  adapter: LlmProviderAdapter,
93
95
  options: LlmConnectorOptions = {},
94
96
  ): InfraConnector<AgentModelProvider> {
95
- const described = new WeakMap<AgentModelProvider, { connection: LlmConnectionOptions; settings: string[] }>();
97
+ const described = new WeakMap<AgentModelProvider, { connection: LlmConnectionOptions; settings: string[]; check: boolean }>();
96
98
  return identifyConnector({
97
99
  token: AGENT_MODEL_PROVIDER,
98
100
  config,
@@ -101,11 +103,14 @@ export function llmConnect<T extends LlmConfigShape>(
101
103
  create(configs) {
102
104
  const connection = resolveLlmConnectionOptions(config, options, configs);
103
105
  const provider = adapter.create(connection);
104
- described.set(provider, { connection, settings: settingNames(config, configs, ["baseUrl", "apiKey"]) });
106
+ // The environment of this kernel's configuration: tests do not call the real provider.
107
+ const environment = (configs?.get(config) as { environment?: string } | undefined)?.environment;
108
+ const check = options.checkOnStart ?? environment !== "test";
109
+ described.set(provider, { connection, settings: settingNames(config, configs, ["baseUrl", "apiKey"]), check });
105
110
  return provider;
106
111
  },
107
112
  connect(provider, signal) {
108
- if (options.checkOnStart === false) return;
113
+ if (described.get(provider)?.check === false || options.checkOnStart === false) return;
109
114
  return adapter.connect?.(provider, signal);
110
115
  },
111
116
  describe(provider, { connected }) {
@@ -114,7 +119,7 @@ export function llmConnect<T extends LlmConfigShape>(
114
119
  return {
115
120
  kind: `${known.connection.provider} · ${known.connection.model}`,
116
121
  address: known.connection.baseUrl,
117
- details: connected && options.checkOnStart !== false && adapter.connect !== undefined ? ["checked"] : [],
122
+ details: connected && known.check && adapter.connect !== undefined ? ["checked"] : [],
118
123
  settings: known.settings,
119
124
  };
120
125
  },
@@ -14,6 +14,14 @@ export interface RedisReliableDeliveryOptions {
14
14
  readonly maxReadBytes?: number;
15
15
  }
16
16
 
17
+ /** Redis settings without which an acknowledged write may be lost. */
18
+ const DURABLE_REDIS: Readonly<Record<string, string>> = Object.freeze({
19
+ appendonly: "yes",
20
+ appendfsync: "always",
21
+ "no-appendfsync-on-rewrite": "no",
22
+ "maxmemory-policy": "noeviction",
23
+ });
24
+
17
25
  export class RedisRoomDeliveryStore implements ReliableRoomDelivery {
18
26
  private readonly limits: Required<Omit<RedisReliableDeliveryOptions, "requireAof">>;
19
27
  private readonly requireAof: boolean;
@@ -47,9 +55,18 @@ export class RedisRoomDeliveryStore implements ReliableRoomDelivery {
47
55
  if (Array.isArray(settings)) for (let i = 0; i < settings.length; i += 2) values.set(settings[i]!, settings[i + 1]!);
48
56
  else for (const [key, value] of Object.entries(settings)) values.set(key, value);
49
57
  const info = await this.operations.send("INFO", ["persistence"]) as string;
50
- if (values.get("appendonly") !== "yes" || values.get("appendfsync") !== "always" || values.get("maxmemory-policy") !== "noeviction"
51
- || values.get("no-appendfsync-on-rewrite") !== "no"
52
- || !info.includes("aof_last_write_status:ok") || !info.includes("loading:0")) throw new WebSocketDeliveryError("DURABILITY_CONFIGURATION");
58
+ const problems = Object.entries(DURABLE_REDIS)
59
+ .filter(([name, needed]) => values.get(name) !== needed)
60
+ .map(([name, needed]) => `${name} is ${values.get(name) ?? "unknown"}, needs ${needed}`);
61
+ if (!info.includes("aof_last_write_status:ok")) problems.push("the last append-only file write failed (aof_last_write_status)");
62
+ if (!info.includes("loading:0")) problems.push("Redis is still loading its data");
63
+ if (problems.length > 0) {
64
+ throw new WebSocketDeliveryError(
65
+ "DURABILITY_CONFIGURATION",
66
+ `WebSocket delivery needs a Redis that does not lose writes: ${problems.join("; ")}. `
67
+ + "Set them in redis.conf or with CONFIG SET; otherwise undelivered messages and sessions may be lost.",
68
+ );
69
+ }
53
70
  }
54
71
 
55
72
  async publish(request: ReliableRoomPublication): Promise<ReliableBroadcastReceipt> {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bazis",
3
- "version": "0.100.4",
3
+ "version": "0.100.5",
4
4
  "description": "Modular backend framework for Bun in TypeScript: DI wired by codegen, HTTP, a PostgreSQL ORM, JWT, WebSocket, agents and a CLI.",
5
5
  "license": "MIT",
6
6
  "author": "Alexander Alenin",