@octelium/console-agent 0.1.0-b-ca02.1.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.
Files changed (97) hide show
  1. package/LICENSE +267 -0
  2. package/README.md +207 -0
  3. package/apis/octelium.binpb +0 -0
  4. package/dist/agent/pi/auth.d.ts +32 -0
  5. package/dist/agent/pi/auth.js +279 -0
  6. package/dist/agent/pi/auth.js.map +1 -0
  7. package/dist/agent/pi/backend.d.ts +77 -0
  8. package/dist/agent/pi/backend.js +518 -0
  9. package/dist/agent/pi/backend.js.map +1 -0
  10. package/dist/agent/pi/mapper.d.ts +33 -0
  11. package/dist/agent/pi/mapper.js +386 -0
  12. package/dist/agent/pi/mapper.js.map +1 -0
  13. package/dist/agent/pi/model.d.ts +47 -0
  14. package/dist/agent/pi/model.js +199 -0
  15. package/dist/agent/pi/model.js.map +1 -0
  16. package/dist/agent/prompt.d.ts +22 -0
  17. package/dist/agent/prompt.js +75 -0
  18. package/dist/agent/prompt.js.map +1 -0
  19. package/dist/agent/resources.d.ts +13 -0
  20. package/dist/agent/resources.js +78 -0
  21. package/dist/agent/resources.js.map +1 -0
  22. package/dist/agent/tools/builtin.d.ts +13 -0
  23. package/dist/agent/tools/builtin.js +80 -0
  24. package/dist/agent/tools/builtin.js.map +1 -0
  25. package/dist/agent/tools/octelium.d.ts +28 -0
  26. package/dist/agent/tools/octelium.js +236 -0
  27. package/dist/agent/tools/octelium.js.map +1 -0
  28. package/dist/agent/tools/present.d.ts +61 -0
  29. package/dist/agent/tools/present.js +273 -0
  30. package/dist/agent/tools/present.js.map +1 -0
  31. package/dist/agent/tools/util.d.ts +19 -0
  32. package/dist/agent/tools/util.js +103 -0
  33. package/dist/agent/tools/util.js.map +1 -0
  34. package/dist/agent/tools/web.d.ts +24 -0
  35. package/dist/agent/tools/web.js +237 -0
  36. package/dist/agent/tools/web.js.map +1 -0
  37. package/dist/agent/types.d.ts +60 -0
  38. package/dist/agent/types.js +2 -0
  39. package/dist/agent/types.js.map +1 -0
  40. package/dist/app.d.ts +36 -0
  41. package/dist/app.js +126 -0
  42. package/dist/app.js.map +1 -0
  43. package/dist/cli.d.ts +2 -0
  44. package/dist/cli.js +249 -0
  45. package/dist/cli.js.map +1 -0
  46. package/dist/config.d.ts +159 -0
  47. package/dist/config.js +251 -0
  48. package/dist/config.js.map +1 -0
  49. package/dist/errors.d.ts +13 -0
  50. package/dist/errors.js +18 -0
  51. package/dist/errors.js.map +1 -0
  52. package/dist/index.d.ts +6 -0
  53. package/dist/index.js +6 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/log.d.ts +11 -0
  56. package/dist/log.js +41 -0
  57. package/dist/log.js.map +1 -0
  58. package/dist/octelium/catalog.d.ts +61 -0
  59. package/dist/octelium/catalog.js +595 -0
  60. package/dist/octelium/catalog.js.map +1 -0
  61. package/dist/octelium/client.d.ts +53 -0
  62. package/dist/octelium/client.js +201 -0
  63. package/dist/octelium/client.js.map +1 -0
  64. package/dist/octelium/search.d.ts +24 -0
  65. package/dist/octelium/search.js +211 -0
  66. package/dist/octelium/search.js.map +1 -0
  67. package/dist/protocol/index.d.ts +432 -0
  68. package/dist/protocol/index.js +44 -0
  69. package/dist/protocol/index.js.map +1 -0
  70. package/dist/runs/builder.d.ts +17 -0
  71. package/dist/runs/builder.js +81 -0
  72. package/dist/runs/builder.js.map +1 -0
  73. package/dist/runs/manager.d.ts +52 -0
  74. package/dist/runs/manager.js +536 -0
  75. package/dist/runs/manager.js.map +1 -0
  76. package/dist/server/http.d.ts +9 -0
  77. package/dist/server/http.js +100 -0
  78. package/dist/server/http.js.map +1 -0
  79. package/dist/server/server.d.ts +48 -0
  80. package/dist/server/server.js +483 -0
  81. package/dist/server/server.js.map +1 -0
  82. package/dist/skills.d.ts +4 -0
  83. package/dist/skills.js +69 -0
  84. package/dist/skills.js.map +1 -0
  85. package/dist/store/conversations.d.ts +26 -0
  86. package/dist/store/conversations.js +183 -0
  87. package/dist/store/conversations.js.map +1 -0
  88. package/dist/store/files.d.ts +27 -0
  89. package/dist/store/files.js +161 -0
  90. package/dist/store/files.js.map +1 -0
  91. package/dist/store/settings.d.ts +14 -0
  92. package/dist/store/settings.js +48 -0
  93. package/dist/store/settings.js.map +1 -0
  94. package/dist/version.d.ts +1 -0
  95. package/dist/version.js +11 -0
  96. package/dist/version.js.map +1 -0
  97. package/package.json +57 -0
package/dist/cli.js ADDED
@@ -0,0 +1,249 @@
1
+ #!/usr/bin/env node
2
+ import { parseArgs } from "node:util";
3
+ import { createApp } from "./app.js";
4
+ import { resolveModel } from "./agent/pi/model.js";
5
+ import { ConfigError, loadConfig, } from "./config.js";
6
+ import { logger, setLogLevel } from "./log.js";
7
+ import { APICatalog } from "./octelium/catalog.js";
8
+ import { OcteliumClient } from "./octelium/client.js";
9
+ import { syncSkills } from "./skills.js";
10
+ import { getVersion } from "./version.js";
11
+ const usage = `Usage: octelium-console-agent <command> [options]
12
+
13
+ Commands:
14
+ serve Run the agent HTTP server (default)
15
+ doctor Check the configuration, the Octelium API and the LLM access
16
+ api search <query...> Search the Octelium API catalog
17
+ api describe <method|type> Describe an Octelium API method or type
18
+ api call <method> [json] Invoke an Octelium API method
19
+ config Print the effective configuration
20
+ version Print the version
21
+
22
+ Options:
23
+ -c, --config <path> Path to the JSON config file
24
+ -l, --listen <host:port> The HTTP listen address (default 0.0.0.0:8080)
25
+ --data-dir <path> The data directory
26
+ --work-dir <path> The agent's working directory
27
+ --log-level <level> debug, info, warn or error
28
+ -h, --help Show this help
29
+ `;
30
+ const parseListen = (value) => {
31
+ const idx = value.lastIndexOf(":");
32
+ if (idx < 0) {
33
+ return { port: Number(value) };
34
+ }
35
+ const host = value.slice(0, idx).replace(/^\[|\]$/g, "");
36
+ return { host: host || undefined, port: Number(value.slice(idx + 1)) };
37
+ };
38
+ const redactConfig = (config) => ({
39
+ ...config,
40
+ server: {
41
+ ...config.server,
42
+ authToken: config.server.authToken ? "<redacted>" : undefined,
43
+ },
44
+ octelium: {
45
+ ...config.octelium,
46
+ accessToken: config.octelium.accessToken ? "<redacted>" : undefined,
47
+ },
48
+ llm: { ...config.llm, apiKey: config.llm.apiKey ? "<redacted>" : undefined },
49
+ webSearch: config.webSearch
50
+ ? {
51
+ ...config.webSearch,
52
+ apiKey: config.webSearch.apiKey ? "<redacted>" : undefined,
53
+ }
54
+ : undefined,
55
+ });
56
+ const serve = async (config) => {
57
+ const app = await createApp({ config });
58
+ const addr = await app.start();
59
+ logger.info("The console agent is listening", {
60
+ address: `${addr.address}:${addr.port}`,
61
+ version: getVersion(),
62
+ });
63
+ let closing = false;
64
+ const shutdown = async (signal) => {
65
+ if (closing) {
66
+ return;
67
+ }
68
+ closing = true;
69
+ logger.info("Shutting down", { signal });
70
+ try {
71
+ await app.close();
72
+ }
73
+ finally {
74
+ process.exit(0);
75
+ }
76
+ };
77
+ process.on("SIGINT", () => void shutdown("SIGINT"));
78
+ process.on("SIGTERM", () => void shutdown("SIGTERM"));
79
+ };
80
+ const doctor = async (config) => {
81
+ let ok = true;
82
+ const report = (passed, msg) => {
83
+ if (!passed) {
84
+ ok = false;
85
+ }
86
+ process.stdout.write(`${passed ? "✓" : "✗"} ${msg}\n`);
87
+ };
88
+ let catalog;
89
+ try {
90
+ catalog = APICatalog.load();
91
+ report(true, `Loaded the API catalog (${catalog.methods.length} methods)`);
92
+ }
93
+ catch (err) {
94
+ report(false, `Could not load the API catalog: ${err.message}`);
95
+ return false;
96
+ }
97
+ const { client, reason } = OcteliumClient.fromConfig(catalog, config.octelium);
98
+ if (reason) {
99
+ report(false, `Octelium API: ${reason}`);
100
+ }
101
+ else {
102
+ try {
103
+ const status = await client.call("user.v1.MainService/GetStatus", {}, { timeoutMs: 15000 });
104
+ report(true, `Octelium API (${client.mode} mode): authenticated as ${status.user?.metadata?.name ?? "<unknown>"}`);
105
+ }
106
+ catch (err) {
107
+ report(false, `Octelium API (${client.mode} mode): ${err.message}`);
108
+ }
109
+ }
110
+ const { ModelRuntime } = await import("@earendil-works/pi-coding-agent");
111
+ process.env.PI_OFFLINE ??= "1";
112
+ process.env.PI_TELEMETRY ??= "0";
113
+ try {
114
+ const modelRuntime = await ModelRuntime.create({
115
+ modelsPath: null,
116
+ allowModelNetwork: false,
117
+ refreshOnCreate: false,
118
+ });
119
+ const resolved = await resolveModel(config.llm, {
120
+ modelRuntime,
121
+ octelium: client,
122
+ domain: config.octelium.domain,
123
+ logger,
124
+ });
125
+ report(true, `LLM model: ${resolved.model.provider}/${resolved.model.id} (${resolved.model.api}${resolved.baseUrl ? ` at ${resolved.baseUrl}` : ""})`);
126
+ const res = await modelRuntime.completeSimple(resolved.model, {
127
+ messages: [
128
+ {
129
+ role: "user",
130
+ content: "Reply with the single word OK.",
131
+ timestamp: Date.now(),
132
+ },
133
+ ],
134
+ }, { maxTokens: 256, signal: AbortSignal.timeout(60000) });
135
+ if (res.stopReason === "error" || res.stopReason === "aborted") {
136
+ report(false, `LLM request failed: ${res.errorMessage ?? res.stopReason}`);
137
+ }
138
+ else {
139
+ report(true, "LLM request succeeded");
140
+ }
141
+ }
142
+ catch (err) {
143
+ report(false, `LLM: ${err.message}`);
144
+ }
145
+ const skills = await syncSkills(config, logger);
146
+ report(true, `Skills paths: ${skills.length > 0 ? skills.join(", ") : "(none)"}`);
147
+ return ok;
148
+ };
149
+ const api = async (config, args) => {
150
+ const [sub, ...rest] = args;
151
+ const catalog = APICatalog.load();
152
+ switch (sub) {
153
+ case "search": {
154
+ process.stdout.write(`${catalog.formatSearchResults(catalog.search(rest.join(" "), 10))}\n`);
155
+ return true;
156
+ }
157
+ case "describe": {
158
+ const name = rest[0] ?? "";
159
+ const method = catalog.resolveMethod(name);
160
+ if (method) {
161
+ process.stdout.write(`${catalog.describeMethod(method)}\n`);
162
+ return true;
163
+ }
164
+ const type = catalog.resolveType(name);
165
+ if (type) {
166
+ process.stdout.write(`${catalog.describeType(type)}\n`);
167
+ return true;
168
+ }
169
+ process.stderr.write(`Unknown method or type: ${name}\n`);
170
+ return false;
171
+ }
172
+ case "call": {
173
+ const method = catalog.resolveMethod(rest[0] ?? "");
174
+ if (!method) {
175
+ process.stderr.write(`Unknown method: ${rest[0] ?? ""}\n`);
176
+ return false;
177
+ }
178
+ const { client, reason } = OcteliumClient.fromConfig(catalog, config.octelium);
179
+ if (reason) {
180
+ process.stderr.write(`${reason}\n`);
181
+ return false;
182
+ }
183
+ const res = await client.invoke(method, rest[1] ? JSON.parse(rest[1]) : {});
184
+ process.stdout.write(`${JSON.stringify(res.response, null, 2)}\n`);
185
+ return true;
186
+ }
187
+ default:
188
+ process.stderr.write(usage);
189
+ return false;
190
+ }
191
+ };
192
+ const main = async () => {
193
+ const { values, positionals } = parseArgs({
194
+ allowPositionals: true,
195
+ options: {
196
+ config: { type: "string", short: "c" },
197
+ listen: { type: "string", short: "l" },
198
+ "data-dir": { type: "string" },
199
+ "work-dir": { type: "string" },
200
+ "log-level": { type: "string" },
201
+ help: { type: "boolean", short: "h" },
202
+ },
203
+ });
204
+ if (values.help) {
205
+ process.stdout.write(usage);
206
+ return;
207
+ }
208
+ const [command = "serve", ...args] = positionals;
209
+ if (command === "version") {
210
+ process.stdout.write(`${getVersion()}\n`);
211
+ return;
212
+ }
213
+ const overrides = {
214
+ dataDir: values["data-dir"],
215
+ workDir: values["work-dir"],
216
+ logLevel: values["log-level"],
217
+ server: values.listen ? parseListen(values.listen) : undefined,
218
+ };
219
+ const config = loadConfig({ configPath: values.config, overrides });
220
+ setLogLevel(config.logLevel);
221
+ switch (command) {
222
+ case "serve":
223
+ await serve(config);
224
+ return;
225
+ case "doctor":
226
+ process.exitCode = (await doctor(config)) ? 0 : 1;
227
+ return;
228
+ case "api":
229
+ process.exitCode = (await api(config, args)) ? 0 : 1;
230
+ return;
231
+ case "config":
232
+ process.stdout.write(`${JSON.stringify(redactConfig(config), null, 2)}\n`);
233
+ return;
234
+ default:
235
+ process.stderr.write(usage);
236
+ process.exitCode = 1;
237
+ }
238
+ };
239
+ main().catch((err) => {
240
+ if (err instanceof ConfigError) {
241
+ process.stderr.write(`${err.message}\n`);
242
+ }
243
+ else {
244
+ logger.error("Fatal error", { error: err });
245
+ process.stderr.write(`${err.stack ?? String(err)}\n`);
246
+ }
247
+ process.exit(1);
248
+ });
249
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,159 @@
1
+ import { Type, type Static } from "typebox";
2
+ export declare const THINKING_LEVELS: readonly ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
3
+ export type ThinkingLevel = (typeof THINKING_LEVELS)[number];
4
+ export declare const BUILTIN_TOOLS: readonly ["read", "bash", "edit", "write", "grep", "find", "ls"];
5
+ export declare const DEFAULT_BUILTIN_TOOLS: string[];
6
+ export declare const DEFAULT_SKILLS_REPOSITORY = "https://github.com/octelium/octelium-skills";
7
+ export declare const DEFAULT_LOGIN_PROVIDERS: string[];
8
+ declare const ConfigInputSchema: Type.TObject<{
9
+ dataDir: Type.TOptional<Type.TString>;
10
+ workDir: Type.TOptional<Type.TString>;
11
+ logLevel: Type.TOptional<Type.TEnum<["debug", "info", "warn", "error"]>>;
12
+ server: Type.TOptional<Type.TObject<{
13
+ host: Type.TOptional<Type.TString>;
14
+ port: Type.TOptional<Type.TInteger>;
15
+ allowedOrigins: Type.TOptional<Type.TArray<Type.TString>>;
16
+ cors: Type.TOptional<Type.TBoolean>;
17
+ authToken: Type.TOptional<Type.TString>;
18
+ maxUploadBytes: Type.TOptional<Type.TInteger>;
19
+ }>>;
20
+ octelium: Type.TOptional<Type.TObject<{
21
+ mode: Type.TOptional<Type.TEnum<["auto", "proxy", "direct", "disabled"]>>;
22
+ domain: Type.TOptional<Type.TString>;
23
+ authProxySocket: Type.TOptional<Type.TString>;
24
+ accessToken: Type.TOptional<Type.TString>;
25
+ insecureTLS: Type.TOptional<Type.TBoolean>;
26
+ timeoutSeconds: Type.TOptional<Type.TInteger>;
27
+ }>>;
28
+ llm: Type.TOptional<Type.TObject<{
29
+ provider: Type.TOptional<Type.TString>;
30
+ service: Type.TOptional<Type.TString>;
31
+ baseUrl: Type.TOptional<Type.TString>;
32
+ api: Type.TOptional<Type.TString>;
33
+ model: Type.TOptional<Type.TString>;
34
+ apiKey: Type.TOptional<Type.TString>;
35
+ apiKeyEnv: Type.TOptional<Type.TString>;
36
+ headers: Type.TOptional<Type.TRecord<"^.*$", Type.TString>>;
37
+ thinkingLevel: Type.TOptional<Type.TEnum<["off", "minimal", "low", "medium", "high", "xhigh", "max"]>>;
38
+ reasoning: Type.TOptional<Type.TBoolean>;
39
+ contextWindow: Type.TOptional<Type.TInteger>;
40
+ maxTokens: Type.TOptional<Type.TInteger>;
41
+ input: Type.TOptional<Type.TArray<Type.TEnum<["text", "image"]>>>;
42
+ loginProviders: Type.TOptional<Type.TArray<Type.TString>>;
43
+ }>>;
44
+ agent: Type.TOptional<Type.TObject<{
45
+ tools: Type.TOptional<Type.TArray<Type.TEnum<["read", "bash", "edit", "write", "grep", "find", "ls"]>>>;
46
+ systemPromptAppend: Type.TOptional<Type.TString>;
47
+ loadContextFiles: Type.TOptional<Type.TBoolean>;
48
+ maxConcurrentRuns: Type.TOptional<Type.TInteger>;
49
+ sessionIdleTimeoutSeconds: Type.TOptional<Type.TInteger>;
50
+ compaction: Type.TOptional<Type.TBoolean>;
51
+ maxRetries: Type.TOptional<Type.TInteger>;
52
+ generateTitles: Type.TOptional<Type.TBoolean>;
53
+ }>>;
54
+ approvals: Type.TOptional<Type.TObject<{
55
+ octeliumAPI: Type.TOptional<Type.TEnum<["never", "destructive", "write"]>>;
56
+ bash: Type.TOptional<Type.TBoolean>;
57
+ }>>;
58
+ skills: Type.TOptional<Type.TObject<{
59
+ enabled: Type.TOptional<Type.TBoolean>;
60
+ paths: Type.TOptional<Type.TArray<Type.TString>>;
61
+ repositories: Type.TOptional<Type.TArray<Type.TObject<{
62
+ url: Type.TString;
63
+ ref: Type.TOptional<Type.TString>;
64
+ path: Type.TOptional<Type.TString>;
65
+ }>>>;
66
+ }>>;
67
+ webSearch: Type.TOptional<Type.TObject<{
68
+ provider: Type.TEnum<["brave", "tavily", "searxng"]>;
69
+ baseUrl: Type.TOptional<Type.TString>;
70
+ apiKey: Type.TOptional<Type.TString>;
71
+ apiKeyEnv: Type.TOptional<Type.TString>;
72
+ }>>;
73
+ }>;
74
+ export type ConfigInput = Static<typeof ConfigInputSchema>;
75
+ export interface SkillsRepository {
76
+ url: string;
77
+ ref?: string;
78
+ path?: string;
79
+ }
80
+ export interface WebSearchConfig {
81
+ provider: "brave" | "tavily" | "searxng";
82
+ baseUrl?: string;
83
+ apiKey?: string;
84
+ apiKeyEnv?: string;
85
+ }
86
+ export interface Config {
87
+ dataDir: string;
88
+ workDir: string;
89
+ logLevel: "debug" | "info" | "warn" | "error";
90
+ server: {
91
+ host: string;
92
+ port: number;
93
+ allowedOrigins: string[];
94
+ cors: boolean;
95
+ authToken?: string;
96
+ maxUploadBytes: number;
97
+ };
98
+ octelium: {
99
+ mode: "auto" | "proxy" | "direct" | "disabled";
100
+ domain?: string;
101
+ authProxySocket?: string;
102
+ accessToken?: string;
103
+ insecureTLS: boolean;
104
+ timeoutSeconds: number;
105
+ };
106
+ llm: {
107
+ provider: string;
108
+ service?: string;
109
+ baseUrl?: string;
110
+ api?: string;
111
+ model?: string;
112
+ apiKey?: string;
113
+ apiKeyEnv?: string;
114
+ headers?: Record<string, string>;
115
+ thinkingLevel: ThinkingLevel;
116
+ reasoning?: boolean;
117
+ contextWindow?: number;
118
+ maxTokens?: number;
119
+ input?: ("text" | "image")[];
120
+ loginProviders: string[];
121
+ };
122
+ agent: {
123
+ tools: string[];
124
+ systemPromptAppend?: string;
125
+ loadContextFiles: boolean;
126
+ maxConcurrentRuns: number;
127
+ sessionIdleTimeoutSeconds: number;
128
+ compaction: boolean;
129
+ maxRetries: number;
130
+ generateTitles: boolean;
131
+ };
132
+ approvals: {
133
+ octeliumAPI: "never" | "destructive" | "write";
134
+ bash: boolean;
135
+ };
136
+ skills: {
137
+ enabled: boolean;
138
+ paths: string[];
139
+ repositories: SkillsRepository[];
140
+ };
141
+ webSearch?: WebSearchConfig;
142
+ }
143
+ export declare class ConfigError extends Error {
144
+ }
145
+ type Env = Record<string, string | undefined>;
146
+ export declare const expandHome: (p: string) => string;
147
+ export declare const mergeConfigInputs: (...inputs: (ConfigInput | undefined)[]) => ConfigInput;
148
+ export declare const validateConfigInput: (input: unknown, source: string) => ConfigInput;
149
+ export declare const readConfigFile: (filePath: string) => ConfigInput;
150
+ export declare const getDefaultDataDir: (env?: Env) => string;
151
+ export declare const getConsoleOrigin: (domain: string) => string;
152
+ export declare const resolveConfig: (input: ConfigInput, env?: Env) => Config;
153
+ export interface LoadConfigOptions {
154
+ configPath?: string;
155
+ overrides?: ConfigInput;
156
+ env?: Env;
157
+ }
158
+ export declare const loadConfig: (opts?: LoadConfigOptions) => Config;
159
+ export {};
package/dist/config.js ADDED
@@ -0,0 +1,251 @@
1
+ import * as fs from "node:fs";
2
+ import * as os from "node:os";
3
+ import * as path from "node:path";
4
+ import { Type } from "typebox";
5
+ import Value from "typebox/value";
6
+ export const THINKING_LEVELS = [
7
+ "off",
8
+ "minimal",
9
+ "low",
10
+ "medium",
11
+ "high",
12
+ "xhigh",
13
+ "max",
14
+ ];
15
+ export const BUILTIN_TOOLS = [
16
+ "read",
17
+ "bash",
18
+ "edit",
19
+ "write",
20
+ "grep",
21
+ "find",
22
+ "ls",
23
+ ];
24
+ export const DEFAULT_BUILTIN_TOOLS = [...BUILTIN_TOOLS];
25
+ export const DEFAULT_SKILLS_REPOSITORY = "https://github.com/octelium/octelium-skills";
26
+ export const DEFAULT_LOGIN_PROVIDERS = ["anthropic", "openai"];
27
+ const ConfigInputSchema = Type.Object({
28
+ dataDir: Type.Optional(Type.String()),
29
+ workDir: Type.Optional(Type.String()),
30
+ logLevel: Type.Optional(Type.Enum(["debug", "info", "warn", "error"])),
31
+ server: Type.Optional(Type.Object({
32
+ host: Type.Optional(Type.String()),
33
+ port: Type.Optional(Type.Integer({ minimum: 0, maximum: 65535 })),
34
+ allowedOrigins: Type.Optional(Type.Array(Type.String())),
35
+ cors: Type.Optional(Type.Boolean()),
36
+ authToken: Type.Optional(Type.String()),
37
+ maxUploadBytes: Type.Optional(Type.Integer({ minimum: 1 })),
38
+ }, { additionalProperties: false })),
39
+ octelium: Type.Optional(Type.Object({
40
+ mode: Type.Optional(Type.Enum(["auto", "proxy", "direct", "disabled"])),
41
+ domain: Type.Optional(Type.String()),
42
+ authProxySocket: Type.Optional(Type.String()),
43
+ accessToken: Type.Optional(Type.String()),
44
+ insecureTLS: Type.Optional(Type.Boolean()),
45
+ timeoutSeconds: Type.Optional(Type.Integer({ minimum: 1 })),
46
+ }, { additionalProperties: false })),
47
+ llm: Type.Optional(Type.Object({
48
+ provider: Type.Optional(Type.String({ minLength: 1 })),
49
+ service: Type.Optional(Type.String()),
50
+ baseUrl: Type.Optional(Type.String()),
51
+ api: Type.Optional(Type.String()),
52
+ model: Type.Optional(Type.String()),
53
+ apiKey: Type.Optional(Type.String()),
54
+ apiKeyEnv: Type.Optional(Type.String()),
55
+ headers: Type.Optional(Type.Record(Type.String(), Type.String())),
56
+ thinkingLevel: Type.Optional(Type.Enum([...THINKING_LEVELS])),
57
+ reasoning: Type.Optional(Type.Boolean()),
58
+ contextWindow: Type.Optional(Type.Integer({ minimum: 1 })),
59
+ maxTokens: Type.Optional(Type.Integer({ minimum: 1 })),
60
+ input: Type.Optional(Type.Array(Type.Enum(["text", "image"]))),
61
+ loginProviders: Type.Optional(Type.Array(Type.String())),
62
+ }, { additionalProperties: false })),
63
+ agent: Type.Optional(Type.Object({
64
+ tools: Type.Optional(Type.Array(Type.Enum([...BUILTIN_TOOLS]))),
65
+ systemPromptAppend: Type.Optional(Type.String()),
66
+ loadContextFiles: Type.Optional(Type.Boolean()),
67
+ maxConcurrentRuns: Type.Optional(Type.Integer({ minimum: 1 })),
68
+ sessionIdleTimeoutSeconds: Type.Optional(Type.Integer({ minimum: 1 })),
69
+ compaction: Type.Optional(Type.Boolean()),
70
+ maxRetries: Type.Optional(Type.Integer({ minimum: 0 })),
71
+ generateTitles: Type.Optional(Type.Boolean()),
72
+ }, { additionalProperties: false })),
73
+ approvals: Type.Optional(Type.Object({
74
+ octeliumAPI: Type.Optional(Type.Enum(["never", "destructive", "write"])),
75
+ bash: Type.Optional(Type.Boolean()),
76
+ }, { additionalProperties: false })),
77
+ skills: Type.Optional(Type.Object({
78
+ enabled: Type.Optional(Type.Boolean()),
79
+ paths: Type.Optional(Type.Array(Type.String())),
80
+ repositories: Type.Optional(Type.Array(Type.Object({
81
+ url: Type.String({ minLength: 1 }),
82
+ ref: Type.Optional(Type.String()),
83
+ path: Type.Optional(Type.String()),
84
+ }, { additionalProperties: false }))),
85
+ }, { additionalProperties: false })),
86
+ webSearch: Type.Optional(Type.Object({
87
+ provider: Type.Enum(["brave", "tavily", "searxng"]),
88
+ baseUrl: Type.Optional(Type.String()),
89
+ apiKey: Type.Optional(Type.String()),
90
+ apiKeyEnv: Type.Optional(Type.String()),
91
+ }, { additionalProperties: false })),
92
+ }, { additionalProperties: false });
93
+ export class ConfigError extends Error {
94
+ }
95
+ export const expandHome = (p) => {
96
+ if (p === "~") {
97
+ return os.homedir();
98
+ }
99
+ if (p.startsWith("~/")) {
100
+ return path.join(os.homedir(), p.slice(2));
101
+ }
102
+ return p;
103
+ };
104
+ const isObject = (arg) => typeof arg === "object" && arg !== null && !Array.isArray(arg);
105
+ export const mergeConfigInputs = (...inputs) => {
106
+ const merge = (target, source) => {
107
+ for (const [key, value] of Object.entries(source)) {
108
+ if (value === undefined) {
109
+ continue;
110
+ }
111
+ const current = target[key];
112
+ if (isObject(current) && isObject(value) && key !== "headers") {
113
+ target[key] = merge({ ...current }, value);
114
+ }
115
+ else {
116
+ target[key] = value;
117
+ }
118
+ }
119
+ return target;
120
+ };
121
+ return inputs.reduce((acc, input) => (input ? merge(acc, input) : acc), {});
122
+ };
123
+ export const validateConfigInput = (input, source) => {
124
+ if (Value.Check(ConfigInputSchema, input)) {
125
+ return input;
126
+ }
127
+ const errors = [...Value.Errors(ConfigInputSchema, input)]
128
+ .filter((err) => err.keyword !== "boolean")
129
+ .slice(0, 8)
130
+ .map((err) => {
131
+ const location = err.instancePath === "" ? "/" : err.instancePath;
132
+ const extra = err.keyword === "additionalProperties"
133
+ ? ` (${err.params.additionalProperties?.join(", ")})`
134
+ : "";
135
+ return `${location}: ${err.message}${extra}`;
136
+ });
137
+ throw new ConfigError(`Invalid config in ${source}: ${errors.join("; ")}`);
138
+ };
139
+ export const readConfigFile = (filePath) => {
140
+ let raw;
141
+ try {
142
+ raw = fs.readFileSync(filePath, "utf8");
143
+ }
144
+ catch (err) {
145
+ throw new ConfigError(`Could not read config file ${filePath}: ${err.message}`);
146
+ }
147
+ let parsed;
148
+ try {
149
+ parsed = JSON.parse(raw);
150
+ }
151
+ catch (err) {
152
+ throw new ConfigError(`Could not parse config file ${filePath}: ${err.message}`);
153
+ }
154
+ return validateConfigInput(parsed, filePath);
155
+ };
156
+ export const getDefaultDataDir = (env = process.env) => env.OCTELIUM_CONSOLE_AGENT_DATA_DIR
157
+ ? expandHome(env.OCTELIUM_CONSOLE_AGENT_DATA_DIR)
158
+ : path.join(os.homedir(), ".octelium-console-agent");
159
+ const getDefaultWorkDir = () => fs.existsSync("/workspace") ? "/workspace" : os.homedir();
160
+ export const getConsoleOrigin = (domain) => `https://console.octelium.${domain}`;
161
+ export const resolveConfig = (input, env = process.env) => {
162
+ const domain = input.octelium?.domain ?? env.OCTELIUM_DOMAIN;
163
+ const allowedOrigins = [...(input.server?.allowedOrigins ?? [])];
164
+ if (domain) {
165
+ allowedOrigins.push(getConsoleOrigin(domain));
166
+ }
167
+ if (env.CORDIUM_HOSTNAME) {
168
+ allowedOrigins.push(`https://${env.CORDIUM_HOSTNAME}`);
169
+ }
170
+ const llm = input.llm ?? {};
171
+ return {
172
+ dataDir: expandHome(input.dataDir ?? getDefaultDataDir(env)),
173
+ workDir: expandHome(input.workDir ?? getDefaultWorkDir()),
174
+ logLevel: input.logLevel ??
175
+ env.OCTELIUM_CONSOLE_AGENT_LOG_LEVEL ??
176
+ "info",
177
+ server: {
178
+ host: input.server?.host ?? "0.0.0.0",
179
+ port: input.server?.port ?? 8080,
180
+ allowedOrigins: [...new Set(allowedOrigins)],
181
+ cors: input.server?.cors ?? false,
182
+ authToken: input.server?.authToken,
183
+ maxUploadBytes: input.server?.maxUploadBytes ?? 100 * 1024 * 1024,
184
+ },
185
+ octelium: {
186
+ mode: input.octelium?.mode ?? "auto",
187
+ domain,
188
+ authProxySocket: input.octelium?.authProxySocket ?? env.OCTELIUM_AUTH_PROXY_SOCKET,
189
+ accessToken: input.octelium?.accessToken ?? env.OCTELIUM_ACCESS_TOKEN,
190
+ insecureTLS: input.octelium?.insecureTLS ?? env.OCTELIUM_INSECURE_TLS === "true",
191
+ timeoutSeconds: input.octelium?.timeoutSeconds ?? 30,
192
+ },
193
+ llm: {
194
+ ...llm,
195
+ provider: llm.provider ?? "octelium",
196
+ thinkingLevel: llm.thinkingLevel ?? "medium",
197
+ loginProviders: llm.loginProviders ?? [...DEFAULT_LOGIN_PROVIDERS],
198
+ },
199
+ agent: {
200
+ tools: input.agent?.tools ?? [...DEFAULT_BUILTIN_TOOLS],
201
+ systemPromptAppend: input.agent?.systemPromptAppend,
202
+ loadContextFiles: input.agent?.loadContextFiles ?? false,
203
+ maxConcurrentRuns: input.agent?.maxConcurrentRuns ?? 4,
204
+ sessionIdleTimeoutSeconds: input.agent?.sessionIdleTimeoutSeconds ?? 1800,
205
+ compaction: input.agent?.compaction ?? true,
206
+ maxRetries: input.agent?.maxRetries ?? 3,
207
+ generateTitles: input.agent?.generateTitles ?? true,
208
+ },
209
+ approvals: {
210
+ octeliumAPI: input.approvals?.octeliumAPI ?? "write",
211
+ bash: input.approvals?.bash ?? false,
212
+ },
213
+ skills: {
214
+ enabled: input.skills?.enabled ?? true,
215
+ paths: (input.skills?.paths ?? []).map(expandHome),
216
+ repositories: input.skills?.repositories ?? [
217
+ { url: DEFAULT_SKILLS_REPOSITORY, ref: "main" },
218
+ ],
219
+ },
220
+ webSearch: input.webSearch,
221
+ };
222
+ };
223
+ export const loadConfig = (opts = {}) => {
224
+ const env = opts.env ?? process.env;
225
+ let configPath = opts.configPath ?? env.OCTELIUM_CONSOLE_AGENT_CONFIG;
226
+ if (!configPath) {
227
+ const defaultPath = path.join(expandHome(opts.overrides?.dataDir ?? getDefaultDataDir(env)), "config.json");
228
+ if (fs.existsSync(defaultPath)) {
229
+ configPath = defaultPath;
230
+ }
231
+ }
232
+ const fileInput = configPath
233
+ ? readConfigFile(expandHome(configPath))
234
+ : undefined;
235
+ let envInput;
236
+ if (env.OCTELIUM_CONSOLE_AGENT_CONFIG_JSON) {
237
+ let parsed;
238
+ try {
239
+ parsed = JSON.parse(env.OCTELIUM_CONSOLE_AGENT_CONFIG_JSON);
240
+ }
241
+ catch (err) {
242
+ throw new ConfigError(`Could not parse OCTELIUM_CONSOLE_AGENT_CONFIG_JSON: ${err.message}`);
243
+ }
244
+ envInput = validateConfigInput(parsed, "OCTELIUM_CONSOLE_AGENT_CONFIG_JSON");
245
+ }
246
+ const overrides = opts.overrides
247
+ ? validateConfigInput(opts.overrides, "overrides")
248
+ : undefined;
249
+ return resolveConfig(mergeConfigInputs(fileInput, envInput, overrides), env);
250
+ };
251
+ //# sourceMappingURL=config.js.map