opencode-gateway 0.1.1 → 0.2.1
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 +30 -3
- package/dist/binding/gateway.d.ts +2 -1
- package/dist/binding/index.d.ts +1 -1
- package/dist/cli/doctor.js +7 -19
- package/dist/cli/init.js +5 -3
- package/dist/cli/opencode-config-file.d.ts +5 -0
- package/dist/cli/opencode-config-file.js +18 -0
- package/dist/cli/opencode-config.d.ts +2 -0
- package/dist/cli/opencode-config.js +141 -9
- package/dist/cli/templates.js +15 -0
- package/dist/cli.js +186 -32
- package/dist/config/gateway.d.ts +4 -0
- package/dist/config/gateway.js +4 -0
- package/dist/config/memory.d.ts +18 -0
- package/dist/config/memory.js +105 -0
- package/dist/config/paths.d.ts +2 -0
- package/dist/config/paths.js +2 -0
- package/dist/gateway.d.ts +3 -1
- package/dist/gateway.js +10 -4
- package/dist/host/logger.d.ts +8 -0
- package/dist/host/logger.js +53 -0
- package/dist/index.js +2 -2
- package/dist/memory/prompt.d.ts +9 -0
- package/dist/memory/prompt.js +122 -0
- package/dist/runtime/executor.d.ts +1 -0
- package/dist/runtime/executor.js +14 -2
- package/dist/session/context.d.ts +1 -1
- package/dist/session/context.js +2 -29
- package/dist/session/system-prompt.d.ts +8 -0
- package/dist/session/system-prompt.js +52 -0
- package/dist/store/sqlite.d.ts +1 -0
- package/dist/store/sqlite.js +22 -0
- package/package.json +1 -1
- package/dist/host/noop.d.ts +0 -4
- package/dist/host/noop.js +0 -14
package/README.md
CHANGED
|
@@ -12,13 +12,14 @@ npx opencode-gateway init
|
|
|
12
12
|
|
|
13
13
|
This ensures:
|
|
14
14
|
|
|
15
|
-
- `plugin
|
|
16
|
-
- `opencode-gateway.toml` exists next to
|
|
15
|
+
- `plugin` contains `opencode-gateway@latest`
|
|
16
|
+
- `opencode-gateway.toml` exists next to the preferred OpenCode config file
|
|
17
17
|
|
|
18
18
|
By default the CLI uses `OPENCODE_CONFIG_DIR` when it is set, otherwise it
|
|
19
19
|
writes to:
|
|
20
20
|
|
|
21
|
-
- `~/.config/opencode/opencode.json`
|
|
21
|
+
- an existing `~/.config/opencode/opencode.jsonc` or `~/.config/opencode/opencode.json`
|
|
22
|
+
- otherwise a new `~/.config/opencode/opencode.jsonc`
|
|
22
23
|
- `~/.config/opencode/opencode-gateway.toml`
|
|
23
24
|
|
|
24
25
|
Check what it resolved:
|
|
@@ -48,6 +49,7 @@ opencode serve
|
|
|
48
49
|
```toml
|
|
49
50
|
[gateway]
|
|
50
51
|
state_db = "/home/you/.local/share/opencode-gateway/state.db"
|
|
52
|
+
# log_level = "warn"
|
|
51
53
|
|
|
52
54
|
[cron]
|
|
53
55
|
enabled = true
|
|
@@ -60,6 +62,17 @@ bot_token_env = "TELEGRAM_BOT_TOKEN"
|
|
|
60
62
|
poll_timeout_seconds = 25
|
|
61
63
|
allowed_chats = []
|
|
62
64
|
allowed_users = []
|
|
65
|
+
|
|
66
|
+
[[memory.entries]]
|
|
67
|
+
path = "memory/project.md"
|
|
68
|
+
description = "Project conventions and long-lived context"
|
|
69
|
+
inject_content = true
|
|
70
|
+
|
|
71
|
+
[[memory.entries]]
|
|
72
|
+
path = "memory/notes"
|
|
73
|
+
description = "Domain notes and operating docs"
|
|
74
|
+
inject_markdown_contents = true
|
|
75
|
+
globs = ["**/*.rs", "notes/**/*.txt"]
|
|
63
76
|
```
|
|
64
77
|
|
|
65
78
|
When Telegram is enabled, export the bot token through the configured
|
|
@@ -68,3 +81,17 @@ environment variable, for example:
|
|
|
68
81
|
```bash
|
|
69
82
|
export TELEGRAM_BOT_TOKEN="..."
|
|
70
83
|
```
|
|
84
|
+
|
|
85
|
+
Gateway plugin logs are off by default. Set `gateway.log_level` to `error`,
|
|
86
|
+
`warn`, `info`, or `debug` to emit that level and anything above it.
|
|
87
|
+
|
|
88
|
+
Memory rules:
|
|
89
|
+
|
|
90
|
+
- all entries inject their configured path and description
|
|
91
|
+
- file contents are injected only when `inject_content = true`
|
|
92
|
+
- directory entries default to description-only
|
|
93
|
+
- `inject_markdown_contents = true` recursively injects `*.md` and `*.markdown`
|
|
94
|
+
- `globs` are relative to the configured directory and may match other UTF-8
|
|
95
|
+
text files
|
|
96
|
+
- relative paths are resolved from `opencode-gateway.toml`
|
|
97
|
+
- memory is injected only into gateway-managed sessions
|
|
@@ -60,8 +60,9 @@ export type BindingOutboundMessage = {
|
|
|
60
60
|
export type BindingTransportHost = {
|
|
61
61
|
sendMessage(message: BindingOutboundMessage): Promise<BindingHostAck>;
|
|
62
62
|
};
|
|
63
|
+
export type BindingLogLevel = "debug" | "info" | "warn" | "error";
|
|
63
64
|
export type BindingLoggerHost = {
|
|
64
|
-
log(level:
|
|
65
|
+
log(level: BindingLogLevel, message: string): void;
|
|
65
66
|
};
|
|
66
67
|
export type GatewayContract = {
|
|
67
68
|
gatewayStatus(): GatewayStatusSnapshot;
|
package/dist/binding/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { BindingCronJobSpec, BindingInboundMessage, BindingPreparedExecution, GatewayContract } from "./gateway";
|
|
2
2
|
import type { BindingOpencodeExecutionInput, OpencodeExecutionDriver } from "./opencode";
|
|
3
3
|
export type { BindingExecutionObservation, BindingProgressiveDirective } from "./execution";
|
|
4
|
-
export type { BindingCronJobSpec, BindingDeliveryTarget, BindingHostAck, BindingInboundAttachment, BindingInboundMessage, BindingLoggerHost, BindingOutboundMessage, BindingPreparedExecution, BindingPromptPart, BindingRuntimeReport, BindingTransportHost, GatewayContract, GatewayStatusSnapshot, } from "./gateway";
|
|
4
|
+
export type { BindingCronJobSpec, BindingDeliveryTarget, BindingHostAck, BindingInboundAttachment, BindingInboundMessage, BindingLoggerHost, BindingLogLevel, BindingOutboundMessage, BindingPreparedExecution, BindingPromptPart, BindingRuntimeReport, BindingTransportHost, GatewayContract, GatewayStatusSnapshot, } from "./gateway";
|
|
5
5
|
export type { BindingOpencodeCommand, BindingOpencodeCommandPart, BindingOpencodeCommandResult, BindingOpencodeDriverStep, BindingOpencodeExecutionInput, BindingOpencodeMessage, BindingOpencodeMessagePart, BindingOpencodePrompt, OpencodeExecutionDriver, } from "./opencode";
|
|
6
6
|
export type GatewayBindingModule = GatewayContract & {
|
|
7
7
|
prepareInboundExecution: (message: BindingInboundMessage) => BindingPreparedExecution;
|
package/dist/cli/doctor.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import { GATEWAY_CONFIG_FILE,
|
|
4
|
-
import { parseOpencodeConfig } from "./opencode-config";
|
|
3
|
+
import { GATEWAY_CONFIG_FILE, resolveGatewayWorkspacePath } from "../config/paths";
|
|
4
|
+
import { inspectGatewayPlugin, parseOpencodeConfig } from "./opencode-config";
|
|
5
|
+
import { resolveOpencodeConfigFile } from "./opencode-config-file";
|
|
5
6
|
import { pathExists, resolveCliConfigDir } from "./paths";
|
|
6
7
|
export async function runDoctor(options, env) {
|
|
7
8
|
const configDir = resolveCliConfigDir(options, env);
|
|
8
|
-
const opencodeConfigPath = join(configDir, OPENCODE_CONFIG_FILE);
|
|
9
9
|
const gatewayConfigPath = join(configDir, GATEWAY_CONFIG_FILE);
|
|
10
10
|
const workspaceDirPath = resolveGatewayWorkspacePath(gatewayConfigPath);
|
|
11
|
-
const
|
|
11
|
+
const opencodeConfig = await resolveOpencodeConfigFile(configDir);
|
|
12
|
+
const opencodeStatus = await inspectOpencodeConfig(opencodeConfig.path);
|
|
12
13
|
const gatewayOverride = env.OPENCODE_GATEWAY_CONFIG?.trim() || null;
|
|
13
14
|
console.log("doctor report");
|
|
14
15
|
console.log(` config dir: ${configDir}`);
|
|
15
|
-
console.log(` opencode config: ${await describePath(
|
|
16
|
+
console.log(` opencode config: ${await describePath(opencodeConfig.path)}`);
|
|
16
17
|
console.log(` gateway config: ${await describePath(gatewayConfigPath)}`);
|
|
17
18
|
console.log(` gateway workspace: ${await describePath(workspaceDirPath)}`);
|
|
18
19
|
console.log(` gateway config override: ${gatewayOverride ?? "not set"}`);
|
|
@@ -34,21 +35,8 @@ async function inspectOpencodeConfig(path) {
|
|
|
34
35
|
}
|
|
35
36
|
try {
|
|
36
37
|
const parsed = parseOpencodeConfig(await readFile(path, "utf8"), path);
|
|
37
|
-
const plugins = parsed.plugin;
|
|
38
|
-
if (plugins === undefined) {
|
|
39
|
-
return {
|
|
40
|
-
pluginConfigured: "no",
|
|
41
|
-
error: null,
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
if (!Array.isArray(plugins)) {
|
|
45
|
-
return {
|
|
46
|
-
pluginConfigured: "invalid",
|
|
47
|
-
error: "`plugin` is not an array",
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
38
|
return {
|
|
51
|
-
pluginConfigured:
|
|
39
|
+
pluginConfigured: inspectGatewayPlugin(parsed),
|
|
52
40
|
error: null,
|
|
53
41
|
};
|
|
54
42
|
}
|
package/dist/cli/init.js
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
|
-
import { defaultGatewayStateDbPath, GATEWAY_CONFIG_FILE,
|
|
3
|
+
import { defaultGatewayStateDbPath, GATEWAY_CONFIG_FILE, resolveGatewayWorkspacePath } from "../config/paths";
|
|
4
4
|
import { createDefaultOpencodeConfig, ensureGatewayPlugin, parseOpencodeConfig, stringifyOpencodeConfig, } from "./opencode-config";
|
|
5
|
+
import { resolveOpencodeConfigFile } from "./opencode-config-file";
|
|
5
6
|
import { pathExists, resolveCliConfigDir } from "./paths";
|
|
6
7
|
import { buildGatewayConfigTemplate } from "./templates";
|
|
7
8
|
export async function runInit(options, env) {
|
|
8
9
|
const configDir = resolveCliConfigDir(options, env);
|
|
9
|
-
const opencodeConfigPath = join(configDir, OPENCODE_CONFIG_FILE);
|
|
10
10
|
const gatewayConfigPath = join(configDir, GATEWAY_CONFIG_FILE);
|
|
11
11
|
const workspaceDirPath = resolveGatewayWorkspacePath(gatewayConfigPath);
|
|
12
|
+
const opencodeConfig = await resolveOpencodeConfigFile(configDir);
|
|
13
|
+
const opencodeConfigPath = opencodeConfig.path;
|
|
12
14
|
await mkdir(configDir, { recursive: true });
|
|
13
15
|
await mkdir(workspaceDirPath, { recursive: true });
|
|
14
16
|
let opencodeStatus = "already present";
|
|
15
|
-
if (!
|
|
17
|
+
if (!opencodeConfig.exists) {
|
|
16
18
|
await writeFile(opencodeConfigPath, stringifyOpencodeConfig(createDefaultOpencodeConfig(options.managed)));
|
|
17
19
|
opencodeStatus = "created";
|
|
18
20
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { OPENCODE_CONFIG_FILE_CANDIDATES, OPENCODE_CONFIG_FILE_JSONC } from "../config/paths";
|
|
3
|
+
import { pathExists } from "./paths";
|
|
4
|
+
export async function resolveOpencodeConfigFile(configDir) {
|
|
5
|
+
for (const fileName of OPENCODE_CONFIG_FILE_CANDIDATES) {
|
|
6
|
+
const path = join(configDir, fileName);
|
|
7
|
+
if (await pathExists(path)) {
|
|
8
|
+
return {
|
|
9
|
+
path,
|
|
10
|
+
exists: true,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
path: join(configDir, OPENCODE_CONFIG_FILE_JSONC),
|
|
16
|
+
exists: false,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -3,8 +3,10 @@ export type EnsurePluginResult = {
|
|
|
3
3
|
changed: boolean;
|
|
4
4
|
document: OpencodeConfigDocument;
|
|
5
5
|
};
|
|
6
|
+
export type GatewayPluginStatus = "yes" | "no" | "needs_update";
|
|
6
7
|
export declare function createDefaultOpencodeConfig(managed: boolean): OpencodeConfigDocument;
|
|
7
8
|
export declare function ensureGatewayPlugin(document: OpencodeConfigDocument): EnsurePluginResult;
|
|
8
9
|
export declare function parseOpencodeConfig(source: string, path: string): OpencodeConfigDocument;
|
|
9
10
|
export declare function stringifyOpencodeConfig(document: OpencodeConfigDocument): string;
|
|
11
|
+
export declare function inspectGatewayPlugin(document: OpencodeConfigDocument): GatewayPluginStatus;
|
|
10
12
|
export {};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
const OPENCODE_SCHEMA_URL = "https://opencode.ai/config.json";
|
|
2
2
|
const PACKAGE_NAME = "opencode-gateway";
|
|
3
|
+
const PACKAGE_SPEC = "opencode-gateway@latest";
|
|
3
4
|
export function createDefaultOpencodeConfig(managed) {
|
|
4
5
|
const document = {
|
|
5
6
|
$schema: OPENCODE_SCHEMA_URL,
|
|
6
|
-
plugin: [
|
|
7
|
+
plugin: [PACKAGE_SPEC],
|
|
7
8
|
};
|
|
8
9
|
if (managed) {
|
|
9
10
|
document.server = {
|
|
@@ -14,20 +15,17 @@ export function createDefaultOpencodeConfig(managed) {
|
|
|
14
15
|
return document;
|
|
15
16
|
}
|
|
16
17
|
export function ensureGatewayPlugin(document) {
|
|
17
|
-
const plugins = document
|
|
18
|
+
const plugins = readPluginArray(document);
|
|
18
19
|
if (plugins === undefined) {
|
|
19
20
|
return {
|
|
20
21
|
changed: true,
|
|
21
22
|
document: {
|
|
22
23
|
...document,
|
|
23
|
-
plugin: [
|
|
24
|
+
plugin: [PACKAGE_SPEC],
|
|
24
25
|
},
|
|
25
26
|
};
|
|
26
27
|
}
|
|
27
|
-
if (
|
|
28
|
-
throw new Error("opencode.json field `plugin` must be an array when present");
|
|
29
|
-
}
|
|
30
|
-
if (plugins.some((entry) => entry === PACKAGE_NAME)) {
|
|
28
|
+
if (plugins.includes(PACKAGE_SPEC)) {
|
|
31
29
|
return {
|
|
32
30
|
changed: false,
|
|
33
31
|
document,
|
|
@@ -37,14 +35,14 @@ export function ensureGatewayPlugin(document) {
|
|
|
37
35
|
changed: true,
|
|
38
36
|
document: {
|
|
39
37
|
...document,
|
|
40
|
-
plugin: [...plugins,
|
|
38
|
+
plugin: [...plugins, PACKAGE_SPEC],
|
|
41
39
|
},
|
|
42
40
|
};
|
|
43
41
|
}
|
|
44
42
|
export function parseOpencodeConfig(source, path) {
|
|
45
43
|
let parsed;
|
|
46
44
|
try {
|
|
47
|
-
parsed = JSON.parse(source);
|
|
45
|
+
parsed = JSON.parse(toStrictJson(source));
|
|
48
46
|
}
|
|
49
47
|
catch (error) {
|
|
50
48
|
throw new Error(`failed to parse opencode config ${path}: ${formatError(error)}`);
|
|
@@ -57,6 +55,140 @@ export function parseOpencodeConfig(source, path) {
|
|
|
57
55
|
export function stringifyOpencodeConfig(document) {
|
|
58
56
|
return `${JSON.stringify(document, null, 2)}\n`;
|
|
59
57
|
}
|
|
58
|
+
export function inspectGatewayPlugin(document) {
|
|
59
|
+
const plugins = readPluginArray(document);
|
|
60
|
+
if (plugins === undefined) {
|
|
61
|
+
return "no";
|
|
62
|
+
}
|
|
63
|
+
if (plugins.includes(PACKAGE_SPEC)) {
|
|
64
|
+
return "yes";
|
|
65
|
+
}
|
|
66
|
+
return plugins.some((entry) => isGatewayPluginReference(entry)) ? "needs_update" : "no";
|
|
67
|
+
}
|
|
60
68
|
function formatError(error) {
|
|
61
69
|
return error instanceof Error ? error.message : String(error);
|
|
62
70
|
}
|
|
71
|
+
function readPluginArray(document) {
|
|
72
|
+
const plugins = document.plugin;
|
|
73
|
+
if (plugins === undefined) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
if (!Array.isArray(plugins)) {
|
|
77
|
+
throw new Error("opencode config field `plugin` must be an array when present");
|
|
78
|
+
}
|
|
79
|
+
const normalized = [];
|
|
80
|
+
for (const [index, entry] of plugins.entries()) {
|
|
81
|
+
if (typeof entry !== "string") {
|
|
82
|
+
throw new Error(`opencode config field \`plugin[${index}]\` must be a string`);
|
|
83
|
+
}
|
|
84
|
+
normalized.push(entry);
|
|
85
|
+
}
|
|
86
|
+
return normalized;
|
|
87
|
+
}
|
|
88
|
+
function toStrictJson(source) {
|
|
89
|
+
return stripTrailingCommas(stripJsonComments(source));
|
|
90
|
+
}
|
|
91
|
+
function stripJsonComments(source) {
|
|
92
|
+
let result = "";
|
|
93
|
+
let inString = false;
|
|
94
|
+
let escaped = false;
|
|
95
|
+
let inLineComment = false;
|
|
96
|
+
let inBlockComment = false;
|
|
97
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
98
|
+
const current = source[index];
|
|
99
|
+
const next = source[index + 1];
|
|
100
|
+
if (inLineComment) {
|
|
101
|
+
if (current === "\n") {
|
|
102
|
+
inLineComment = false;
|
|
103
|
+
result += current;
|
|
104
|
+
}
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (inBlockComment) {
|
|
108
|
+
if (current === "*" && next === "/") {
|
|
109
|
+
inBlockComment = false;
|
|
110
|
+
index += 1;
|
|
111
|
+
}
|
|
112
|
+
else if (current === "\n") {
|
|
113
|
+
result += current;
|
|
114
|
+
}
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (inString) {
|
|
118
|
+
result += current;
|
|
119
|
+
if (escaped) {
|
|
120
|
+
escaped = false;
|
|
121
|
+
}
|
|
122
|
+
else if (current === "\\") {
|
|
123
|
+
escaped = true;
|
|
124
|
+
}
|
|
125
|
+
else if (current === '"') {
|
|
126
|
+
inString = false;
|
|
127
|
+
}
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (current === '"') {
|
|
131
|
+
inString = true;
|
|
132
|
+
result += current;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (current === "/" && next === "/") {
|
|
136
|
+
inLineComment = true;
|
|
137
|
+
index += 1;
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
if (current === "/" && next === "*") {
|
|
141
|
+
inBlockComment = true;
|
|
142
|
+
index += 1;
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
result += current;
|
|
146
|
+
}
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
149
|
+
function stripTrailingCommas(source) {
|
|
150
|
+
let result = "";
|
|
151
|
+
let inString = false;
|
|
152
|
+
let escaped = false;
|
|
153
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
154
|
+
const current = source[index];
|
|
155
|
+
if (inString) {
|
|
156
|
+
result += current;
|
|
157
|
+
if (escaped) {
|
|
158
|
+
escaped = false;
|
|
159
|
+
}
|
|
160
|
+
else if (current === "\\") {
|
|
161
|
+
escaped = true;
|
|
162
|
+
}
|
|
163
|
+
else if (current === '"') {
|
|
164
|
+
inString = false;
|
|
165
|
+
}
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (current === '"') {
|
|
169
|
+
inString = true;
|
|
170
|
+
result += current;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
if (current === ",") {
|
|
174
|
+
const nextSignificant = findNextSignificantCharacter(source, index + 1);
|
|
175
|
+
if (nextSignificant === "]" || nextSignificant === "}") {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
result += current;
|
|
180
|
+
}
|
|
181
|
+
return result;
|
|
182
|
+
}
|
|
183
|
+
function findNextSignificantCharacter(source, startIndex) {
|
|
184
|
+
for (let index = startIndex; index < source.length; index += 1) {
|
|
185
|
+
const current = source[index];
|
|
186
|
+
if (!/\s/.test(current)) {
|
|
187
|
+
return current;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
function isGatewayPluginReference(entry) {
|
|
193
|
+
return entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`);
|
|
194
|
+
}
|
package/dist/cli/templates.js
CHANGED
|
@@ -5,6 +5,7 @@ export function buildGatewayConfigTemplate(stateDbPath) {
|
|
|
5
5
|
"",
|
|
6
6
|
"[gateway]",
|
|
7
7
|
`state_db = "${escapeTomlString(stateDbPath)}"`,
|
|
8
|
+
'# log_level = "warn"',
|
|
8
9
|
"",
|
|
9
10
|
"[cron]",
|
|
10
11
|
"enabled = true",
|
|
@@ -19,6 +20,20 @@ export function buildGatewayConfigTemplate(stateDbPath) {
|
|
|
19
20
|
"allowed_chats = []",
|
|
20
21
|
"allowed_users = []",
|
|
21
22
|
"",
|
|
23
|
+
"# Optional long-lived memory sources injected into gateway-managed sessions.",
|
|
24
|
+
"# Relative paths are resolved from this config file.",
|
|
25
|
+
"#",
|
|
26
|
+
"# [[memory.entries]]",
|
|
27
|
+
'# path = "memory/project.md"',
|
|
28
|
+
'# description = "Project conventions and long-lived context"',
|
|
29
|
+
"# inject_content = true",
|
|
30
|
+
"#",
|
|
31
|
+
"# [[memory.entries]]",
|
|
32
|
+
'# path = "memory/notes"',
|
|
33
|
+
'# description = "Domain notes and operating docs"',
|
|
34
|
+
"# inject_markdown_contents = true",
|
|
35
|
+
'# globs = ["**/*.rs", "notes/**/*.txt"]',
|
|
36
|
+
"",
|
|
22
37
|
].join("\n");
|
|
23
38
|
}
|
|
24
39
|
function escapeTomlString(value) {
|