@marcopeg/hal 1.0.11
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 +655 -0
- package/dist/agent/index.d.ts +17 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +30 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/bot/commands/clear.d.ts +7 -0
- package/dist/bot/commands/clear.d.ts.map +1 -0
- package/dist/bot/commands/clear.js +23 -0
- package/dist/bot/commands/clear.js.map +1 -0
- package/dist/bot/commands/help.d.ts +3 -0
- package/dist/bot/commands/help.d.ts.map +1 -0
- package/dist/bot/commands/help.js +16 -0
- package/dist/bot/commands/help.js.map +1 -0
- package/dist/bot/commands/loader.d.ts +26 -0
- package/dist/bot/commands/loader.d.ts.map +1 -0
- package/dist/bot/commands/loader.js +206 -0
- package/dist/bot/commands/loader.js.map +1 -0
- package/dist/bot/commands/start.d.ts +3 -0
- package/dist/bot/commands/start.d.ts.map +1 -0
- package/dist/bot/commands/start.js +10 -0
- package/dist/bot/commands/start.js.map +1 -0
- package/dist/bot/commands/watcher.d.ts +11 -0
- package/dist/bot/commands/watcher.d.ts.map +1 -0
- package/dist/bot/commands/watcher.js +106 -0
- package/dist/bot/commands/watcher.js.map +1 -0
- package/dist/bot/handlers/document.d.ts +7 -0
- package/dist/bot/handlers/document.d.ts.map +1 -0
- package/dist/bot/handlers/document.js +128 -0
- package/dist/bot/handlers/document.js.map +1 -0
- package/dist/bot/handlers/index.d.ts +5 -0
- package/dist/bot/handlers/index.d.ts.map +1 -0
- package/dist/bot/handlers/index.js +5 -0
- package/dist/bot/handlers/index.js.map +1 -0
- package/dist/bot/handlers/photo.d.ts +7 -0
- package/dist/bot/handlers/photo.d.ts.map +1 -0
- package/dist/bot/handlers/photo.js +87 -0
- package/dist/bot/handlers/photo.js.map +1 -0
- package/dist/bot/handlers/text.d.ts +7 -0
- package/dist/bot/handlers/text.d.ts.map +1 -0
- package/dist/bot/handlers/text.js +186 -0
- package/dist/bot/handlers/text.js.map +1 -0
- package/dist/bot/handlers/voice.d.ts +7 -0
- package/dist/bot/handlers/voice.d.ts.map +1 -0
- package/dist/bot/handlers/voice.js +147 -0
- package/dist/bot/handlers/voice.js.map +1 -0
- package/dist/bot/middleware/auth.d.ts +7 -0
- package/dist/bot/middleware/auth.d.ts.map +1 -0
- package/dist/bot/middleware/auth.js +23 -0
- package/dist/bot/middleware/auth.js.map +1 -0
- package/dist/bot/middleware/rateLimit.d.ts +11 -0
- package/dist/bot/middleware/rateLimit.d.ts.map +1 -0
- package/dist/bot/middleware/rateLimit.js +49 -0
- package/dist/bot/middleware/rateLimit.js.map +1 -0
- package/dist/bot.d.ts +11 -0
- package/dist/bot.d.ts.map +1 -0
- package/dist/bot.js +93 -0
- package/dist/bot.js.map +1 -0
- package/dist/claude/executor.d.ts +21 -0
- package/dist/claude/executor.d.ts.map +1 -0
- package/dist/claude/executor.js +185 -0
- package/dist/claude/executor.js.map +1 -0
- package/dist/claude/parser.d.ts +13 -0
- package/dist/claude/parser.d.ts.map +1 -0
- package/dist/claude/parser.js +63 -0
- package/dist/claude/parser.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +192 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +216 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +396 -0
- package/dist/config.js.map +1 -0
- package/dist/context/resolver.d.ts +19 -0
- package/dist/context/resolver.d.ts.map +1 -0
- package/dist/context/resolver.js +171 -0
- package/dist/context/resolver.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +17 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +44 -0
- package/dist/logger.js.map +1 -0
- package/dist/telegram/chunker.d.ts +10 -0
- package/dist/telegram/chunker.d.ts.map +1 -0
- package/dist/telegram/chunker.js +88 -0
- package/dist/telegram/chunker.js.map +1 -0
- package/dist/telegram/fileSender.d.ts +8 -0
- package/dist/telegram/fileSender.d.ts.map +1 -0
- package/dist/telegram/fileSender.js +46 -0
- package/dist/telegram/fileSender.js.map +1 -0
- package/dist/transcription/whisper.d.ts +11 -0
- package/dist/transcription/whisper.d.ts.map +1 -0
- package/dist/transcription/whisper.js +58 -0
- package/dist/transcription/whisper.js.map +1 -0
- package/dist/types.d.ts +22 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/user/setup.d.ts +26 -0
- package/dist/user/setup.d.ts.map +1 -0
- package/dist/user/setup.js +73 -0
- package/dist/user/setup.js.map +1 -0
- package/package.json +56 -0
package/dist/config.js
ADDED
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { isAbsolute, join, resolve } from "node:path";
|
|
3
|
+
import { parse as parseEnv } from "dotenv";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
// ─── Zod helpers ──────────────────────────────────────────────────────────────
|
|
6
|
+
const TranscriptionModelSchema = z.enum([
|
|
7
|
+
"tiny",
|
|
8
|
+
"tiny.en",
|
|
9
|
+
"base",
|
|
10
|
+
"base.en",
|
|
11
|
+
"small",
|
|
12
|
+
"small.en",
|
|
13
|
+
"medium",
|
|
14
|
+
"medium.en",
|
|
15
|
+
"large-v1",
|
|
16
|
+
"large",
|
|
17
|
+
"large-v3-turbo",
|
|
18
|
+
]);
|
|
19
|
+
const LogLevelSchema = z.enum(["debug", "info", "warn", "error"]);
|
|
20
|
+
// ─── Globals schema (all fields optional) ─────────────────────────────────────
|
|
21
|
+
const GlobalsFileSchema = z
|
|
22
|
+
.object({
|
|
23
|
+
access: z
|
|
24
|
+
.object({ allowedUserIds: z.array(z.number()) })
|
|
25
|
+
.partial()
|
|
26
|
+
.optional(),
|
|
27
|
+
claude: z.object({ command: z.string() }).partial().optional(),
|
|
28
|
+
logging: z
|
|
29
|
+
.object({
|
|
30
|
+
level: LogLevelSchema,
|
|
31
|
+
flow: z.boolean(),
|
|
32
|
+
persist: z.boolean(),
|
|
33
|
+
})
|
|
34
|
+
.partial()
|
|
35
|
+
.optional(),
|
|
36
|
+
rateLimit: z
|
|
37
|
+
.object({ max: z.number().positive(), windowMs: z.number().positive() })
|
|
38
|
+
.partial()
|
|
39
|
+
.optional(),
|
|
40
|
+
transcription: z
|
|
41
|
+
.object({
|
|
42
|
+
model: TranscriptionModelSchema,
|
|
43
|
+
showTranscription: z.boolean(),
|
|
44
|
+
})
|
|
45
|
+
.partial()
|
|
46
|
+
.optional(),
|
|
47
|
+
dataDir: z.string().optional(),
|
|
48
|
+
})
|
|
49
|
+
.optional();
|
|
50
|
+
// ─── Per-project schema ────────────────────────────────────────────────────────
|
|
51
|
+
const ProjectFileSchema = z.object({
|
|
52
|
+
name: z.string().optional(),
|
|
53
|
+
cwd: z.string().min(1, "project.cwd is required"),
|
|
54
|
+
telegram: z.object({
|
|
55
|
+
botToken: z.string().min(1, "project.telegram.botToken is required"),
|
|
56
|
+
}),
|
|
57
|
+
access: z
|
|
58
|
+
.object({ allowedUserIds: z.array(z.number()) })
|
|
59
|
+
.partial()
|
|
60
|
+
.optional(),
|
|
61
|
+
claude: z.object({ command: z.string() }).partial().optional(),
|
|
62
|
+
logging: z
|
|
63
|
+
.object({
|
|
64
|
+
level: LogLevelSchema,
|
|
65
|
+
flow: z.boolean(),
|
|
66
|
+
persist: z.boolean(),
|
|
67
|
+
})
|
|
68
|
+
.partial()
|
|
69
|
+
.optional(),
|
|
70
|
+
rateLimit: z
|
|
71
|
+
.object({ max: z.number().positive(), windowMs: z.number().positive() })
|
|
72
|
+
.partial()
|
|
73
|
+
.optional(),
|
|
74
|
+
transcription: z
|
|
75
|
+
.object({
|
|
76
|
+
model: TranscriptionModelSchema,
|
|
77
|
+
showTranscription: z.boolean(),
|
|
78
|
+
})
|
|
79
|
+
.partial()
|
|
80
|
+
.optional(),
|
|
81
|
+
dataDir: z.string().optional(),
|
|
82
|
+
context: z.record(z.string(), z.string()).optional(),
|
|
83
|
+
});
|
|
84
|
+
// ─── Multi-project config file schema ─────────────────────────────────────────
|
|
85
|
+
const MultiConfigFileSchema = z.object({
|
|
86
|
+
globals: GlobalsFileSchema,
|
|
87
|
+
context: z.record(z.string(), z.string()).optional(),
|
|
88
|
+
projects: z
|
|
89
|
+
.array(ProjectFileSchema)
|
|
90
|
+
.min(1, "At least one project is required"),
|
|
91
|
+
});
|
|
92
|
+
// ─── Local config partial schema ──────────────────────────────────────────────
|
|
93
|
+
const LocalProjectSchema = ProjectFileSchema.partial().extend({
|
|
94
|
+
name: z.string().optional(),
|
|
95
|
+
cwd: z.string().optional(),
|
|
96
|
+
});
|
|
97
|
+
const LocalConfigFileSchema = z
|
|
98
|
+
.object({
|
|
99
|
+
globals: GlobalsFileSchema,
|
|
100
|
+
context: z.record(z.string(), z.string()).optional(),
|
|
101
|
+
projects: z.array(LocalProjectSchema).optional(),
|
|
102
|
+
})
|
|
103
|
+
.optional();
|
|
104
|
+
// ─── Slug derivation ──────────────────────────────────────────────────────────
|
|
105
|
+
export function deriveSlug(name, cwd) {
|
|
106
|
+
if (name)
|
|
107
|
+
return name;
|
|
108
|
+
return cwd
|
|
109
|
+
.replace(/^\.\//, "") // strip leading ./
|
|
110
|
+
.replace(/^\//, "") // strip leading /
|
|
111
|
+
.replace(/[/\\]/g, "-") // path separators → dash
|
|
112
|
+
.replace(/[^a-zA-Z0-9_-]/g, "-") // sanitize remaining chars
|
|
113
|
+
.replace(/-+/g, "-") // collapse multiple dashes
|
|
114
|
+
.replace(/^-|-$/g, ""); // trim leading/trailing dashes
|
|
115
|
+
}
|
|
116
|
+
// ─── dataDir resolution ────────────────────────────────────────────────────────
|
|
117
|
+
function resolveDataDir(dataDirRaw, projectCwd, configDir, slug) {
|
|
118
|
+
if (!dataDirRaw) {
|
|
119
|
+
return resolve(projectCwd, ".hal", "users");
|
|
120
|
+
}
|
|
121
|
+
if (dataDirRaw === "~") {
|
|
122
|
+
return resolve(configDir, ".hal", slug, "data");
|
|
123
|
+
}
|
|
124
|
+
if (isAbsolute(dataDirRaw)) {
|
|
125
|
+
return dataDirRaw;
|
|
126
|
+
}
|
|
127
|
+
return resolve(projectCwd, dataDirRaw);
|
|
128
|
+
}
|
|
129
|
+
// ─── Merge: project over globals over defaults ─────────────────────────────────
|
|
130
|
+
export function resolveProjectConfig(project, globals, configDir, rootContext) {
|
|
131
|
+
const resolvedCwd = isAbsolute(project.cwd)
|
|
132
|
+
? project.cwd
|
|
133
|
+
: resolve(configDir, project.cwd);
|
|
134
|
+
const slug = deriveSlug(project.name, project.cwd);
|
|
135
|
+
const logDir = resolve(configDir, ".hal", "logs", slug);
|
|
136
|
+
const dataDir = resolveDataDir(project.dataDir ?? globals.dataDir, resolvedCwd, configDir, slug);
|
|
137
|
+
const hasTranscription = project.transcription !== undefined || globals.transcription !== undefined;
|
|
138
|
+
const hasContext = rootContext !== undefined || project.context !== undefined;
|
|
139
|
+
return {
|
|
140
|
+
slug,
|
|
141
|
+
name: project.name,
|
|
142
|
+
cwd: resolvedCwd,
|
|
143
|
+
configDir,
|
|
144
|
+
dataDir,
|
|
145
|
+
logDir,
|
|
146
|
+
telegram: { botToken: project.telegram.botToken },
|
|
147
|
+
access: {
|
|
148
|
+
allowedUserIds: project.access?.allowedUserIds ?? globals.access?.allowedUserIds ?? [],
|
|
149
|
+
},
|
|
150
|
+
claude: {
|
|
151
|
+
command: project.claude?.command ?? globals.claude?.command ?? "claude",
|
|
152
|
+
},
|
|
153
|
+
logging: {
|
|
154
|
+
level: project.logging?.level ?? globals.logging?.level ?? "info",
|
|
155
|
+
flow: project.logging?.flow ?? globals.logging?.flow ?? true,
|
|
156
|
+
persist: project.logging?.persist ?? globals.logging?.persist ?? false,
|
|
157
|
+
},
|
|
158
|
+
rateLimit: {
|
|
159
|
+
max: project.rateLimit?.max ?? globals.rateLimit?.max ?? 10,
|
|
160
|
+
windowMs: project.rateLimit?.windowMs ?? globals.rateLimit?.windowMs ?? 60000,
|
|
161
|
+
},
|
|
162
|
+
transcription: hasTranscription
|
|
163
|
+
? {
|
|
164
|
+
model: project.transcription?.model ??
|
|
165
|
+
globals.transcription?.model ??
|
|
166
|
+
"base.en",
|
|
167
|
+
showTranscription: project.transcription?.showTranscription ??
|
|
168
|
+
globals.transcription?.showTranscription ??
|
|
169
|
+
true,
|
|
170
|
+
}
|
|
171
|
+
: undefined,
|
|
172
|
+
context: hasContext ? { ...rootContext, ...project.context } : undefined,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
// ─── Boot-time uniqueness validation ──────────────────────────────────────────
|
|
176
|
+
export function validateProjects(projects) {
|
|
177
|
+
const cwds = new Set();
|
|
178
|
+
const tokens = new Set();
|
|
179
|
+
const names = new Set();
|
|
180
|
+
for (const project of projects) {
|
|
181
|
+
if (cwds.has(project.cwd)) {
|
|
182
|
+
console.error(`Configuration error: duplicate project cwd "${project.cwd}". Each project must have a unique cwd.`);
|
|
183
|
+
process.exit(1);
|
|
184
|
+
}
|
|
185
|
+
cwds.add(project.cwd);
|
|
186
|
+
if (tokens.has(project.telegram.botToken)) {
|
|
187
|
+
console.error(`Configuration error: duplicate botToken in project "${project.slug}". Each project must use a unique Telegram bot token.`);
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
190
|
+
tokens.add(project.telegram.botToken);
|
|
191
|
+
if (project.name) {
|
|
192
|
+
if (names.has(project.name)) {
|
|
193
|
+
console.error(`Configuration error: duplicate project name "${project.name}". Each named project must have a unique name.`);
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
names.add(project.name);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
function loadEnvFiles(configDir, projectCwds) {
|
|
201
|
+
const loadedFiles = [];
|
|
202
|
+
const vars = {};
|
|
203
|
+
// Candidates in ascending priority order (later entries win)
|
|
204
|
+
const candidates = [];
|
|
205
|
+
// Per-project .env files (lower priority than config-dir)
|
|
206
|
+
for (const cwd of projectCwds) {
|
|
207
|
+
candidates.push(join(cwd, ".env"));
|
|
208
|
+
candidates.push(join(cwd, ".env.local"));
|
|
209
|
+
}
|
|
210
|
+
// Config-dir .env files (higher priority)
|
|
211
|
+
candidates.push(join(configDir, ".env"));
|
|
212
|
+
candidates.push(join(configDir, ".env.local"));
|
|
213
|
+
for (const filePath of candidates) {
|
|
214
|
+
if (!existsSync(filePath))
|
|
215
|
+
continue;
|
|
216
|
+
try {
|
|
217
|
+
const content = readFileSync(filePath, "utf-8");
|
|
218
|
+
const parsed = parseEnv(content);
|
|
219
|
+
Object.assign(vars, parsed);
|
|
220
|
+
loadedFiles.push(filePath);
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
// non-fatal: missing read permission etc. — skip silently
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return { vars, loadedFiles };
|
|
227
|
+
}
|
|
228
|
+
// ─── Phase 2: Variable substitution ──────────────────────────────────────────
|
|
229
|
+
function substituteEnvVars(obj, env, path = "") {
|
|
230
|
+
if (typeof obj === "string") {
|
|
231
|
+
return obj.replace(/\$\{([^}]+)\}/g, (_match, varName) => {
|
|
232
|
+
const value = env[varName] ?? process.env[varName];
|
|
233
|
+
if (value === undefined) {
|
|
234
|
+
console.error(`Configuration error: environment variable "${varName}" is not defined\n` +
|
|
235
|
+
` (referenced in field: ${path || "<root>"})`);
|
|
236
|
+
process.exit(1);
|
|
237
|
+
}
|
|
238
|
+
return value;
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
if (Array.isArray(obj)) {
|
|
242
|
+
return obj.map((item, i) => substituteEnvVars(item, env, path ? `${path}[${i}]` : `[${i}]`));
|
|
243
|
+
}
|
|
244
|
+
if (obj !== null && typeof obj === "object") {
|
|
245
|
+
const result = {};
|
|
246
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
247
|
+
// Skip "context" keys — their ${} patterns are resolved at message time
|
|
248
|
+
// by the context resolver, not at boot time as env vars.
|
|
249
|
+
if (key === "context") {
|
|
250
|
+
result[key] = value;
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
result[key] = substituteEnvVars(value, env, path ? `${path}.${key}` : key);
|
|
254
|
+
}
|
|
255
|
+
return result;
|
|
256
|
+
}
|
|
257
|
+
return obj;
|
|
258
|
+
}
|
|
259
|
+
// ─── Phase 3: Deep merge ──────────────────────────────────────────────────────
|
|
260
|
+
function deepMerge(base, override) {
|
|
261
|
+
const result = { ...base };
|
|
262
|
+
for (const [key, overrideVal] of Object.entries(override)) {
|
|
263
|
+
if (overrideVal === undefined)
|
|
264
|
+
continue;
|
|
265
|
+
const baseVal = result[key];
|
|
266
|
+
if (overrideVal !== null &&
|
|
267
|
+
typeof overrideVal === "object" &&
|
|
268
|
+
!Array.isArray(overrideVal) &&
|
|
269
|
+
baseVal !== null &&
|
|
270
|
+
typeof baseVal === "object" &&
|
|
271
|
+
!Array.isArray(baseVal)) {
|
|
272
|
+
result[key] = deepMerge(baseVal, overrideVal);
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
result[key] = overrideVal;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return result;
|
|
279
|
+
}
|
|
280
|
+
// ─── Phase 3: Local config loading ───────────────────────────────────────────
|
|
281
|
+
function loadLocalConfig(configDir) {
|
|
282
|
+
const localPath = join(configDir, "hal.config.local.json");
|
|
283
|
+
if (!existsSync(localPath))
|
|
284
|
+
return null;
|
|
285
|
+
let raw;
|
|
286
|
+
try {
|
|
287
|
+
const content = readFileSync(localPath, "utf-8");
|
|
288
|
+
raw = JSON.parse(content);
|
|
289
|
+
}
|
|
290
|
+
catch (err) {
|
|
291
|
+
console.error(`Configuration error: failed to read hal.config.local.json — ${err instanceof Error ? err.message : String(err)}`);
|
|
292
|
+
process.exit(1);
|
|
293
|
+
}
|
|
294
|
+
const result = LocalConfigFileSchema.safeParse(raw);
|
|
295
|
+
if (!result.success) {
|
|
296
|
+
const issues = result.error.issues
|
|
297
|
+
.map((i) => ` - ${i.path.join(".")}: ${i.message}`)
|
|
298
|
+
.join("\n");
|
|
299
|
+
console.error(`Configuration error in hal.config.local.json:\n${issues}`);
|
|
300
|
+
process.exit(1);
|
|
301
|
+
}
|
|
302
|
+
return result.data ?? null;
|
|
303
|
+
}
|
|
304
|
+
// ─── Phase 3: Merge local into base ──────────────────────────────────────────
|
|
305
|
+
function mergeLocalIntoBase(base, local) {
|
|
306
|
+
const mergedGlobals = local.globals !== undefined
|
|
307
|
+
? deepMerge(base.globals ?? {}, local.globals)
|
|
308
|
+
: base.globals;
|
|
309
|
+
const mergedContext = local.context !== undefined
|
|
310
|
+
? base.context
|
|
311
|
+
? { ...base.context, ...local.context }
|
|
312
|
+
: local.context
|
|
313
|
+
: base.context;
|
|
314
|
+
if (!local.projects || local.projects.length === 0) {
|
|
315
|
+
return { ...base, globals: mergedGlobals, context: mergedContext };
|
|
316
|
+
}
|
|
317
|
+
const mergedProjects = [...base.projects];
|
|
318
|
+
for (const localProject of local.projects) {
|
|
319
|
+
const matchKey = localProject.name ?? localProject.cwd;
|
|
320
|
+
const idx = mergedProjects.findIndex((bp) => {
|
|
321
|
+
if (localProject.name)
|
|
322
|
+
return bp.name === localProject.name;
|
|
323
|
+
if (localProject.cwd)
|
|
324
|
+
return bp.cwd === localProject.cwd;
|
|
325
|
+
return false;
|
|
326
|
+
});
|
|
327
|
+
if (idx === -1) {
|
|
328
|
+
console.error(`Configuration error: local project "${matchKey}" not found in hal.config.json.\n` +
|
|
329
|
+
` Every entry in hal.config.local.json projects must match a base project by name or cwd.`);
|
|
330
|
+
process.exit(1);
|
|
331
|
+
}
|
|
332
|
+
mergedProjects[idx] = deepMerge(mergedProjects[idx], localProject);
|
|
333
|
+
}
|
|
334
|
+
return {
|
|
335
|
+
globals: mergedGlobals,
|
|
336
|
+
context: mergedContext,
|
|
337
|
+
projects: mergedProjects,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
// ─── Phase 4: Config file loading (public API) ────────────────────────────────
|
|
341
|
+
export function loadMultiConfig(configDir) {
|
|
342
|
+
const configPath = join(configDir, "hal.config.json");
|
|
343
|
+
const localPath = join(configDir, "hal.config.local.json");
|
|
344
|
+
const loadedFiles = [];
|
|
345
|
+
// 1. Load base config
|
|
346
|
+
if (!existsSync(configPath)) {
|
|
347
|
+
console.error(`Configuration error: hal.config.json not found in ${configDir}\n` +
|
|
348
|
+
`Run "npx @marcopeg/hal init" to create one.`);
|
|
349
|
+
process.exit(1);
|
|
350
|
+
}
|
|
351
|
+
let rawBase;
|
|
352
|
+
try {
|
|
353
|
+
const content = readFileSync(configPath, "utf-8");
|
|
354
|
+
rawBase = JSON.parse(content);
|
|
355
|
+
}
|
|
356
|
+
catch (err) {
|
|
357
|
+
console.error(`Configuration error: failed to read hal.config.json — ${err instanceof Error ? err.message : String(err)}`);
|
|
358
|
+
process.exit(1);
|
|
359
|
+
}
|
|
360
|
+
loadedFiles.push(configPath);
|
|
361
|
+
// 2. Validate base config schema
|
|
362
|
+
const baseResult = MultiConfigFileSchema.safeParse(rawBase);
|
|
363
|
+
if (!baseResult.success) {
|
|
364
|
+
const issues = baseResult.error.issues
|
|
365
|
+
.map((i) => ` - ${i.path.join(".")}: ${i.message}`)
|
|
366
|
+
.join("\n");
|
|
367
|
+
console.error(`Configuration error in hal.config.json:\n${issues}`);
|
|
368
|
+
process.exit(1);
|
|
369
|
+
}
|
|
370
|
+
let merged = baseResult.data;
|
|
371
|
+
// 3. Load and merge local config
|
|
372
|
+
const localConfig = loadLocalConfig(configDir);
|
|
373
|
+
if (localConfig !== null) {
|
|
374
|
+
loadedFiles.push(localPath);
|
|
375
|
+
merged = mergeLocalIntoBase(merged, localConfig);
|
|
376
|
+
}
|
|
377
|
+
// 4. Load .env files (using raw cwds from merged config for path resolution)
|
|
378
|
+
const rawCwds = merged.projects.map((p) => isAbsolute(p.cwd) ? p.cwd : resolve(configDir, p.cwd));
|
|
379
|
+
const envSources = loadEnvFiles(configDir, rawCwds);
|
|
380
|
+
// 5. Substitute env vars in the merged raw object (before final Zod pass)
|
|
381
|
+
const substituted = substituteEnvVars(merged, envSources.vars);
|
|
382
|
+
// 6. Re-validate after substitution to catch required fields left empty
|
|
383
|
+
const finalResult = MultiConfigFileSchema.safeParse(substituted);
|
|
384
|
+
if (!finalResult.success) {
|
|
385
|
+
const issues = finalResult.error.issues
|
|
386
|
+
.map((i) => ` - ${i.path.join(".")}: ${i.message}`)
|
|
387
|
+
.join("\n");
|
|
388
|
+
console.error(`Configuration error after environment variable substitution:\n${issues}`);
|
|
389
|
+
process.exit(1);
|
|
390
|
+
}
|
|
391
|
+
return {
|
|
392
|
+
config: finalResult.data,
|
|
393
|
+
loadedFiles: [...loadedFiles, ...envSources.loadedFiles],
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Context as GrammyContext } from "grammy";
|
|
2
|
+
import type pino from "pino";
|
|
3
|
+
export interface BootContext {
|
|
4
|
+
shellCache: Record<string, string>;
|
|
5
|
+
}
|
|
6
|
+
export interface ResolveContextOptions {
|
|
7
|
+
gramCtx: GrammyContext;
|
|
8
|
+
configContext: Record<string, string> | undefined;
|
|
9
|
+
bootContext: BootContext;
|
|
10
|
+
configDir: string;
|
|
11
|
+
projectCwd: string;
|
|
12
|
+
projectName: string | undefined;
|
|
13
|
+
projectSlug: string;
|
|
14
|
+
logger: pino.Logger;
|
|
15
|
+
}
|
|
16
|
+
export declare function evaluateBootTimeShells(context: Record<string, string>, logger: pino.Logger): Record<string, string>;
|
|
17
|
+
export declare function resolveContext(options: ResolveContextOptions): Promise<Record<string, string>>;
|
|
18
|
+
export declare function formatContextPrompt(context: Record<string, string>, userMessage: string): string;
|
|
19
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/context/resolver.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvD,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAI7B,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,aAAa,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IAClD,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;CACrB;AAMD,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,MAAM,EAAE,IAAI,CAAC,MAAM,GAClB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAkBxB;AA8HD,wBAAsB,cAAc,CAClC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAmEjC;AAID,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,WAAW,EAAE,MAAM,GAClB,MAAM,CAGR"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
// ─── Boot-time shell evaluation (#{}) ───────────────────────────────────────
|
|
5
|
+
const BOOT_SHELL_RE = /#\{([^}]+)\}/g;
|
|
6
|
+
export function evaluateBootTimeShells(context, logger) {
|
|
7
|
+
const result = {};
|
|
8
|
+
for (const [key, value] of Object.entries(context)) {
|
|
9
|
+
result[key] = value.replace(BOOT_SHELL_RE, (_match, cmd) => {
|
|
10
|
+
try {
|
|
11
|
+
return execSync(cmd, { encoding: "utf-8", timeout: 10_000 }).trim();
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
logger.warn({ key, cmd, error: err instanceof Error ? err.message : String(err) }, "Boot-time shell command failed, substituting empty string");
|
|
15
|
+
return "";
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
// ─── Message-time shell evaluation (@{}) ────────────────────────────────────
|
|
22
|
+
const MSG_SHELL_RE = /@\{([^}]+)\}/g;
|
|
23
|
+
function evaluateMessageTimeShells(value, logger) {
|
|
24
|
+
return value.replace(MSG_SHELL_RE, (_match, cmd) => {
|
|
25
|
+
try {
|
|
26
|
+
return execSync(cmd, { encoding: "utf-8", timeout: 5_000 }).trim();
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
logger.warn({ cmd, error: err instanceof Error ? err.message : String(err) }, "Message-time shell command failed, substituting empty string");
|
|
30
|
+
return "";
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
// ─── App-level variable substitution (${}) ──────────────────────────────────
|
|
35
|
+
const APP_VAR_RE = /\$\{([^}]+)\}/g;
|
|
36
|
+
function resolveAppVars(value, vars) {
|
|
37
|
+
return value.replace(APP_VAR_RE, (_match, expr) => {
|
|
38
|
+
return vars[expr] ?? process.env[expr] ?? "";
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
// ─── Implicit context: bot.* from Grammy ────────────────────────────────────
|
|
42
|
+
function deriveMessageType(gramCtx) {
|
|
43
|
+
const msg = gramCtx.message;
|
|
44
|
+
if (!msg)
|
|
45
|
+
return "unknown";
|
|
46
|
+
if (msg.text)
|
|
47
|
+
return "text";
|
|
48
|
+
if (msg.photo)
|
|
49
|
+
return "photo";
|
|
50
|
+
if (msg.document)
|
|
51
|
+
return "document";
|
|
52
|
+
if (msg.voice)
|
|
53
|
+
return "voice";
|
|
54
|
+
return "unknown";
|
|
55
|
+
}
|
|
56
|
+
function buildImplicitContext(gramCtx) {
|
|
57
|
+
const msg = gramCtx.message;
|
|
58
|
+
const from = gramCtx.from;
|
|
59
|
+
const ts = msg?.date ?? Math.floor(Date.now() / 1000);
|
|
60
|
+
const dt = new Date(ts * 1000);
|
|
61
|
+
return {
|
|
62
|
+
"bot.messageId": String(msg?.message_id ?? ""),
|
|
63
|
+
"bot.timestamp": String(ts),
|
|
64
|
+
"bot.datetime": dt.toISOString(),
|
|
65
|
+
"bot.userId": String(from?.id ?? ""),
|
|
66
|
+
"bot.username": from?.username ?? "",
|
|
67
|
+
"bot.firstName": from?.first_name ?? "",
|
|
68
|
+
"bot.chatId": String(gramCtx.chat?.id ?? ""),
|
|
69
|
+
"bot.messageType": deriveMessageType(gramCtx),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// ─── Implicit context: sys.* from system ────────────────────────────────────
|
|
73
|
+
function buildSystemContext() {
|
|
74
|
+
const now = new Date();
|
|
75
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
76
|
+
const yyyy = now.getFullYear();
|
|
77
|
+
const mm = pad(now.getMonth() + 1);
|
|
78
|
+
const dd = pad(now.getDate());
|
|
79
|
+
const hh = pad(now.getHours());
|
|
80
|
+
const mi = pad(now.getMinutes());
|
|
81
|
+
const ss = pad(now.getSeconds());
|
|
82
|
+
const tzOffsetMin = -now.getTimezoneOffset();
|
|
83
|
+
const tzSign = tzOffsetMin >= 0 ? "+" : "-";
|
|
84
|
+
const tzH = pad(Math.floor(Math.abs(tzOffsetMin) / 60));
|
|
85
|
+
const tzM = pad(Math.abs(tzOffsetMin) % 60);
|
|
86
|
+
const tzOffset = `${tzSign}${tzH}:${tzM}`;
|
|
87
|
+
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone ?? `UTC${tzOffset}`;
|
|
88
|
+
return {
|
|
89
|
+
"sys.datetime": `${yyyy}-${mm}-${dd} ${hh}:${mi}:${ss} UTC${tzSign}${Math.floor(Math.abs(tzOffsetMin) / 60)}`,
|
|
90
|
+
"sys.date": `${yyyy}-${mm}-${dd}`,
|
|
91
|
+
"sys.time": `${hh}:${mi}:${ss}`,
|
|
92
|
+
"sys.ts": String(Math.floor(now.getTime() / 1000)),
|
|
93
|
+
"sys.tz": tz,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
// ─── Hot-reloaded context hook ──────────────────────────────────────────────
|
|
97
|
+
async function loadAndRunHook(hookPath, context, logger) {
|
|
98
|
+
if (!existsSync(hookPath))
|
|
99
|
+
return context;
|
|
100
|
+
try {
|
|
101
|
+
const { default: hook } = await import(`${hookPath}?t=${Date.now()}`);
|
|
102
|
+
return await hook(context);
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
logger.error({ hookPath, error: err instanceof Error ? err.message : String(err) }, "Context hook failed, using pre-hook context");
|
|
106
|
+
return context;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// ─── Claude Code-compatible slug ────────────────────────────────────────────
|
|
110
|
+
/**
|
|
111
|
+
* Derives a slug from the absolute project cwd matching Claude Code's convention
|
|
112
|
+
* for ~/.claude/projects/ folder names: full path with `/` → `-`, keeping leading `-`.
|
|
113
|
+
*/
|
|
114
|
+
function claudeSlug(absoluteCwd) {
|
|
115
|
+
return absoluteCwd
|
|
116
|
+
.replace(/[/\\]/g, "-")
|
|
117
|
+
.replace(/[^a-zA-Z0-9_-]/g, "-")
|
|
118
|
+
.replace(/-+/g, "-");
|
|
119
|
+
}
|
|
120
|
+
// ─── Main orchestrator ──────────────────────────────────────────────────────
|
|
121
|
+
export async function resolveContext(options) {
|
|
122
|
+
const { gramCtx, configContext, bootContext, configDir, projectCwd, projectName, projectSlug, logger, } = options;
|
|
123
|
+
// 1. Implicit context (bot.* + sys.* + project.*)
|
|
124
|
+
const slug = claudeSlug(projectCwd);
|
|
125
|
+
const implicit = {
|
|
126
|
+
...buildImplicitContext(gramCtx),
|
|
127
|
+
...buildSystemContext(),
|
|
128
|
+
"project.name": projectName ?? projectSlug,
|
|
129
|
+
"project.cwd": projectCwd,
|
|
130
|
+
"project.slug": slug,
|
|
131
|
+
};
|
|
132
|
+
// 2. Merge config context on top (config wins for explicit overrides)
|
|
133
|
+
// Boot-time #{} commands are already resolved in bootContext.shellCache
|
|
134
|
+
let merged;
|
|
135
|
+
if (configContext) {
|
|
136
|
+
// Start with implicit, overlay the config context (which may have #{} already resolved)
|
|
137
|
+
merged = { ...implicit };
|
|
138
|
+
for (const [key, value] of Object.entries(configContext)) {
|
|
139
|
+
// Use the boot-cached version if #{} was present, otherwise the raw config value
|
|
140
|
+
merged[key] = bootContext.shellCache[key] ?? value;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
merged = { ...implicit };
|
|
145
|
+
}
|
|
146
|
+
// 3. Resolve ${} app vars (using implicit + env as lookup)
|
|
147
|
+
for (const [key, value] of Object.entries(merged)) {
|
|
148
|
+
if (APP_VAR_RE.test(value)) {
|
|
149
|
+
APP_VAR_RE.lastIndex = 0;
|
|
150
|
+
merged[key] = resolveAppVars(value, merged);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// 4. Resolve @{} message-time shell commands
|
|
154
|
+
for (const [key, value] of Object.entries(merged)) {
|
|
155
|
+
if (MSG_SHELL_RE.test(value)) {
|
|
156
|
+
MSG_SHELL_RE.lastIndex = 0;
|
|
157
|
+
merged[key] = evaluateMessageTimeShells(value, logger);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// 5. Run global hook (configDir/.hal/hooks/context.mjs)
|
|
161
|
+
merged = await loadAndRunHook(join(configDir, ".hal", "hooks", "context.mjs"), merged, logger);
|
|
162
|
+
// 6. Run project hook (projectCwd/.hal/hooks/context.mjs)
|
|
163
|
+
merged = await loadAndRunHook(join(projectCwd, ".hal", "hooks", "context.mjs"), merged, logger);
|
|
164
|
+
return merged;
|
|
165
|
+
}
|
|
166
|
+
// ─── Prompt formatting ──────────────────────────────────────────────────────
|
|
167
|
+
export function formatContextPrompt(context, userMessage) {
|
|
168
|
+
const lines = Object.entries(context).map(([k, v]) => `- ${k}: ${v}`);
|
|
169
|
+
return `# Context\n${lines.join("\n")}\n\n# User Message\n${userMessage}`;
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/context/resolver.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type { BotHandle } from "./bot.js";
|
|
2
|
+
export { startBot } from "./bot.js";
|
|
3
|
+
export type { ResolvedProjectConfig } from "./config.js";
|
|
4
|
+
export { deriveSlug, loadMultiConfig, resolveProjectConfig, validateProjects, } from "./config.js";
|
|
5
|
+
export { createProjectLogger, createStartupLogger } from "./logger.js";
|
|
6
|
+
export type { ProjectContext } from "./types.js";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,YAAY,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,UAAU,EACV,eAAe,EACf,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Re-exports for programmatic use
|
|
2
|
+
export { startBot } from "./bot.js";
|
|
3
|
+
export { deriveSlug, loadMultiConfig, resolveProjectConfig, validateProjects, } from "./config.js";
|
|
4
|
+
export { createProjectLogger, createStartupLogger } from "./logger.js";
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAGlC,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,OAAO,EACL,UAAU,EACV,eAAe,EACf,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
|