opencode-gateway 0.2.7 → 0.2.9

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/README.md CHANGED
@@ -51,6 +51,17 @@ opencode serve
51
51
  state_db = "/home/you/.local/share/opencode-gateway/state.db"
52
52
  # log_level = "warn"
53
53
 
54
+ # Optional mailbox batching and route overrides.
55
+ # [gateway.mailbox]
56
+ # batch_replies = false
57
+ # batch_window_ms = 1500
58
+ #
59
+ # [[gateway.mailbox.routes]]
60
+ # channel = "telegram"
61
+ # target = "6212645712"
62
+ # topic = "12345"
63
+ # mailbox_key = "shared:telegram:dev"
64
+
54
65
  [cron]
55
66
  enabled = true
56
67
  tick_seconds = 5
@@ -60,9 +71,15 @@ max_concurrent_runs = 1
60
71
  enabled = false
61
72
  bot_token_env = "TELEGRAM_BOT_TOKEN"
62
73
  poll_timeout_seconds = 25
74
+ # Configure at least one allowlist when Telegram is enabled.
63
75
  allowed_chats = []
64
76
  allowed_users = []
65
77
 
78
+ [[memory.entries]]
79
+ path = "USER.md"
80
+ description = "Persistent user profile and preference memory. Keep this file accurate and concise. Record stable preferences, communication style, workflow habits, project conventions, tool constraints, review expectations, and other recurring facts that should shape future assistance. Update it proactively when you learn something durable about the user. Do not store one-off task details or transient context here."
81
+ inject_content = true
82
+
66
83
  [[memory.entries]]
67
84
  path = "memory/project.md"
68
85
  description = "Project conventions and long-lived context"
@@ -85,6 +102,13 @@ export TELEGRAM_BOT_TOKEN="..."
85
102
  Gateway plugin logs are off by default. Set `gateway.log_level` to `error`,
86
103
  `warn`, `info`, or `debug` to emit that level and anything above it.
87
104
 
105
+ Mailbox rules:
106
+
107
+ - `gateway.mailbox.batch_replies` defaults to `false`
108
+ - `gateway.mailbox.batch_window_ms` defaults to `1500`
109
+ - `gateway.mailbox.routes` lets multiple ingress targets share one logical mailbox/session
110
+ - each route needs `channel`, `target`, optional `topic`, and a `mailbox_key`
111
+
88
112
  Memory rules:
89
113
 
90
114
  - all entries inject their configured path and description
@@ -95,4 +119,6 @@ Memory rules:
95
119
  text files
96
120
  - relative paths are resolved from `opencode-gateway-workspace`
97
121
  - absolute paths are still allowed
122
+ - missing files and directories are created automatically on load
123
+ - the default template includes `USER.md` as persistent user-profile memory
98
124
  - memory is injected only into gateway-managed sessions
package/dist/cli.js CHANGED
@@ -387,6 +387,18 @@ function buildGatewayConfigTemplate(stateDbPath) {
387
387
  `state_db = "${escapeTomlString(stateDbPath)}"`,
388
388
  '# log_level = "warn"',
389
389
  "",
390
+ "# Optional mailbox settings.",
391
+ "# [gateway.mailbox]",
392
+ "# batch_replies = false",
393
+ "# batch_window_ms = 1500",
394
+ "#",
395
+ "# Optional route overrides. Matching ingress targets can share one mailbox/session.",
396
+ "# [[gateway.mailbox.routes]]",
397
+ '# channel = "telegram"',
398
+ '# target = "6212645712"',
399
+ '# topic = "12345"',
400
+ '# mailbox_key = "shared:telegram:dev"',
401
+ "",
390
402
  "[cron]",
391
403
  "enabled = true",
392
404
  "tick_seconds = 5",
@@ -397,16 +409,18 @@ function buildGatewayConfigTemplate(stateDbPath) {
397
409
  "enabled = false",
398
410
  'bot_token_env = "TELEGRAM_BOT_TOKEN"',
399
411
  "poll_timeout_seconds = 25",
412
+ "# Configure at least one allowlist when Telegram is enabled.",
400
413
  "allowed_chats = []",
401
414
  "allowed_users = []",
402
415
  "",
403
416
  "# Optional long-lived memory sources injected into gateway-managed sessions.",
404
417
  "# Relative paths are resolved from opencode-gateway-workspace.",
418
+ "# Missing files and directories are created automatically.",
405
419
  "#",
406
- "# [[memory.entries]]",
407
- '# path = "memory/project.md"',
408
- '# description = "Project conventions and long-lived context"',
409
- "# inject_content = true",
420
+ "[[memory.entries]]",
421
+ 'path = "USER.md"',
422
+ 'description = "Persistent user profile and preference memory. Keep this file accurate and concise. Record stable preferences, communication style, workflow habits, project conventions, tool constraints, review expectations, and other recurring facts that should shape future assistance. Update it proactively when you learn something durable about the user. Do not store one-off task details or transient context here."',
423
+ "inject_content = true",
410
424
  "#",
411
425
  "# [[memory.entries]]",
412
426
  '# path = "memory/notes"',
package/dist/index.js CHANGED
@@ -14931,38 +14931,74 @@ var require_out4 = __commonJS((exports, module) => {
14931
14931
  // src/store/database.ts
14932
14932
  var exports_database = {};
14933
14933
  __export(exports_database, {
14934
- SqliteDatabase: () => SqliteDatabase
14934
+ openRuntimeSqliteDatabase: () => openRuntimeSqliteDatabase
14935
14935
  });
14936
- import BetterSqlite3 from "better-sqlite3";
14937
-
14938
- class SqliteDatabase {
14939
- db;
14940
- constructor(path) {
14941
- this.db = new BetterSqlite3(path);
14942
- }
14943
- exec(source) {
14944
- this.db.exec(source);
14945
- }
14946
- query(source) {
14947
- const statement = this.db.prepare(source);
14948
- return {
14949
- get: (...params) => statement.get(...toSqliteParams(params)),
14950
- all: (...params) => statement.all(...toSqliteParams(params)),
14951
- run: (...params) => {
14952
- const result = statement.run(...toSqliteParams(params));
14953
- return {
14954
- changes: result.changes,
14955
- lastInsertRowid: result.lastInsertRowid
14956
- };
14957
- }
14958
- };
14959
- }
14960
- transaction(handler) {
14961
- return this.db.transaction((...args) => handler(...args));
14962
- }
14963
- close() {
14964
- this.db.close();
14936
+ async function openRuntimeSqliteDatabase(path) {
14937
+ if (isBunRuntime()) {
14938
+ return await openBunSqliteDatabase(path);
14965
14939
  }
14940
+ return await openNodeSqliteDatabase(path);
14941
+ }
14942
+ async function openNodeSqliteDatabase(path) {
14943
+ const module = await dynamicImport("better-sqlite3");
14944
+ const db2 = new module.default(path);
14945
+ return {
14946
+ exec(source) {
14947
+ db2.exec(source);
14948
+ },
14949
+ query(source) {
14950
+ const statement = db2.prepare(source);
14951
+ return {
14952
+ get: (...params) => statement.get(...toSqliteParams(params)),
14953
+ all: (...params) => statement.all(...toSqliteParams(params)),
14954
+ run: (...params) => {
14955
+ const result = statement.run(...toSqliteParams(params));
14956
+ return {
14957
+ changes: result.changes,
14958
+ lastInsertRowid: result.lastInsertRowid
14959
+ };
14960
+ }
14961
+ };
14962
+ },
14963
+ transaction(handler) {
14964
+ return db2.transaction((...args) => handler(...args));
14965
+ },
14966
+ close() {
14967
+ db2.close();
14968
+ }
14969
+ };
14970
+ }
14971
+ async function openBunSqliteDatabase(path) {
14972
+ const module = await dynamicImport("bun:sqlite");
14973
+ const db2 = new module.Database(path);
14974
+ return {
14975
+ exec(source) {
14976
+ db2.exec(source);
14977
+ },
14978
+ query(source) {
14979
+ const statement = db2.query(source);
14980
+ return {
14981
+ get(...params) {
14982
+ return statement.get(...params);
14983
+ },
14984
+ all(...params) {
14985
+ return statement.all(...params);
14986
+ },
14987
+ run(...params) {
14988
+ return statement.run(...params);
14989
+ }
14990
+ };
14991
+ },
14992
+ transaction(handler) {
14993
+ return db2.transaction((...args) => handler(...args));
14994
+ },
14995
+ close() {
14996
+ db2.close();
14997
+ }
14998
+ };
14999
+ }
15000
+ function isBunRuntime() {
15001
+ return typeof globalThis === "object" && globalThis !== null && "Bun" in globalThis;
14966
15002
  }
14967
15003
  function toSqliteParams(params) {
14968
15004
  return params.map((param) => {
@@ -14972,7 +15008,10 @@ function toSqliteParams(params) {
14972
15008
  throw new Error(`unsupported SQLite parameter type: ${typeof param}`);
14973
15009
  });
14974
15010
  }
14975
- var init_database = () => {};
15011
+ var dynamicImport;
15012
+ var init_database = __esm(() => {
15013
+ dynamicImport = new Function("specifier", "return import(specifier)");
15014
+ });
14976
15015
 
14977
15016
  // src/binding/index.ts
14978
15017
  import { access, readFile } from "node:fs/promises";
@@ -16140,7 +16179,7 @@ async function readMemoryEntry(value, index, workspaceDirPath) {
16140
16179
  }
16141
16180
  throw new Error(`${field}.path must point to a regular file or directory`);
16142
16181
  }
16143
- async function ensurePathMetadata(path, displayPath, entry, field) {
16182
+ async function ensurePathMetadata(path, displayPath, entry, _field) {
16144
16183
  try {
16145
16184
  return await stat(path);
16146
16185
  } catch (error) {
@@ -23339,8 +23378,8 @@ function readBooleanField(value, field, fallback) {
23339
23378
  }
23340
23379
  async function openSqliteStore(path) {
23341
23380
  await mkdir2(dirname3(path), { recursive: true });
23342
- const { SqliteDatabase: SqliteDatabase2 } = await Promise.resolve().then(() => (init_database(), exports_database));
23343
- const db2 = new SqliteDatabase2(path);
23381
+ const { openRuntimeSqliteDatabase: openRuntimeSqliteDatabase2 } = await Promise.resolve().then(() => (init_database(), exports_database));
23382
+ const db2 = await openRuntimeSqliteDatabase2(path);
23344
23383
  migrateGatewayDatabase(db2);
23345
23384
  return new SqliteStore(db2);
23346
23385
  }
@@ -12,11 +12,4 @@ export type SqliteDatabaseLike = {
12
12
  transaction<Args extends unknown[], Result>(handler: (...args: Args) => Result): (...args: Args) => Result;
13
13
  close(): void;
14
14
  };
15
- export declare class SqliteDatabase implements SqliteDatabaseLike {
16
- private readonly db;
17
- constructor(path: string);
18
- exec(source: string): void;
19
- query<Row, Params extends unknown[]>(source: string): SqliteQueryStatementLike<Row, Params>;
20
- transaction<Args extends unknown[], Result>(handler: (...args: Args) => Result): (...args: Args) => Result;
21
- close(): void;
22
- }
15
+ export declare function openRuntimeSqliteDatabase(path: string): Promise<SqliteDatabaseLike>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-gateway",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
4
4
  "description": "Gateway plugin for OpenCode",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -25,7 +25,7 @@
25
25
  "scripts": {
26
26
  "build": "node ./scripts/build.mjs",
27
27
  "build:wasm": "node ../../scripts/build-binding.mjs",
28
- "check": "tsc --noEmit --project tsconfig.json && bun test src && node ./scripts/build.mjs && node ./scripts/smoke-node-import.mjs",
28
+ "check": "tsc --noEmit --project tsconfig.json && bun test src && node ./scripts/build.mjs && node ./scripts/smoke-node-import.mjs && bun ./scripts/smoke-bun-import.mjs",
29
29
  "prepack": "npm run build:wasm && npm run build",
30
30
  "test": "bun test src"
31
31
  },