@bothat-io/molenkopf 0.1.2
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/.env.example +2 -0
- package/LICENSE +21 -0
- package/README.md +199 -0
- package/SECURITY.md +36 -0
- package/bin/launcher.js +76 -0
- package/bin/molenkopf.js +4 -0
- package/docs/DEPLOYMENT.md +104 -0
- package/docs/MOLENKOPF_PLUGIN_API.md +113 -0
- package/docs/MOLENKOPF_PROVIDER_ENV.md +123 -0
- package/docs/MOLENKOPF_USAGE.md +195 -0
- package/docs/PRODUCT_INTENT.md +36 -0
- package/docs/THREAT_MODEL.md +94 -0
- package/molenkopf.config.example.json +68 -0
- package/package.json +98 -0
- package/packages/core/src/auth/password.ts +47 -0
- package/packages/core/src/auth/session.ts +64 -0
- package/packages/core/src/ci/ci-mode.ts +71 -0
- package/packages/core/src/compression/content-classifier.ts +25 -0
- package/packages/core/src/compression/context-compressor.ts +48 -0
- package/packages/core/src/compression/json-compressor.ts +54 -0
- package/packages/core/src/compression/log-compressor.ts +32 -0
- package/packages/core/src/compression/operational-block-compressor.ts +43 -0
- package/packages/core/src/compression/stacktrace-compressor.ts +23 -0
- package/packages/core/src/config/config-policies.ts +146 -0
- package/packages/core/src/config/molenkopf-config.ts +137 -0
- package/packages/core/src/config/provider-config.ts +139 -0
- package/packages/core/src/events/event-bus.ts +88 -0
- package/packages/core/src/identity/api-keys.ts +149 -0
- package/packages/core/src/identity/budget.ts +51 -0
- package/packages/core/src/identity/db.ts +68 -0
- package/packages/core/src/identity/identity-store.ts +175 -0
- package/packages/core/src/identity/identity-validation.ts +102 -0
- package/packages/core/src/identity/key-permissions.ts +18 -0
- package/packages/core/src/identity/pricing.ts +11 -0
- package/packages/core/src/identity/types.ts +87 -0
- package/packages/core/src/identity/usage-snapshot.ts +116 -0
- package/packages/core/src/manifest/audit-activity.ts +74 -0
- package/packages/core/src/manifest/audit-metrics.ts +7 -0
- package/packages/core/src/manifest/audit-safety.ts +113 -0
- package/packages/core/src/manifest/audit-store.ts +189 -0
- package/packages/core/src/manifest/audit-summary.ts +184 -0
- package/packages/core/src/manifest/usage-meter.ts +105 -0
- package/packages/core/src/memory/memory-extractor.ts +57 -0
- package/packages/core/src/memory/memory-graph.ts +55 -0
- package/packages/core/src/pipeline/json-string-spans.ts +143 -0
- package/packages/core/src/pipeline/openai-request-rewriter.ts +66 -0
- package/packages/core/src/plugins/builtin-plugin-descriptors.ts +10 -0
- package/packages/core/src/plugins/builtin-plugin-modules.ts +9 -0
- package/packages/core/src/plugins/plugin-api.ts +96 -0
- package/packages/core/src/plugins/plugin-catalog.ts +42 -0
- package/packages/core/src/plugins/plugin-descriptor.ts +51 -0
- package/packages/core/src/plugins/plugin-sdk.ts +47 -0
- package/packages/core/src/plugins/static-pipeline.ts +5 -0
- package/packages/core/src/profiles/profile-router.ts +45 -0
- package/packages/core/src/providers/provider-catalog.ts +186 -0
- package/packages/core/src/routing/distribution.ts +31 -0
- package/packages/core/src/security/secret-redactor.ts +139 -0
- package/packages/core/src/security/target-policy.ts +61 -0
- package/packages/core/src/storage/local-paths.ts +6 -0
- package/packages/core/src/storage/private-state.ts +30 -0
- package/packages/core/src/storage/purge-dir.ts +10 -0
- package/packages/core/src/store/retrieval-store.ts +114 -0
- package/packages/core/src/utils/hash.ts +9 -0
- package/packages/core/src/utils/text.ts +18 -0
- package/packages/core/src/utils/tokens.ts +3 -0
- package/packages/dashboard/dist/assets/index-B_aSPgHx.js +11 -0
- package/packages/dashboard/dist/assets/index-D6z2TEL2.css +1 -0
- package/packages/dashboard/dist/favicon.png +0 -0
- package/packages/dashboard/dist/index.html +15 -0
- package/packages/dashboard/dist/molenkopf-logo.png +0 -0
- package/packages/dashboard/public/favicon.png +0 -0
- package/packages/dashboard/public/molenkopf-logo.png +0 -0
- package/packages/plugins/context-compressor-plugin/descriptor.ts +19 -0
- package/packages/plugins/context-compressor-plugin/page.html +191 -0
- package/packages/plugins/context-compressor-plugin/plugin.ts +40 -0
- package/packages/plugins/obsidian-graph-plugin/descriptor.ts +19 -0
- package/packages/plugins/obsidian-graph-plugin/page.html +68 -0
- package/packages/plugins/obsidian-graph-plugin/plugin.ts +27 -0
- package/packages/plugins/shared/audit-projects.ts +32 -0
- package/packages/proxy/src/cli/args.ts +34 -0
- package/packages/proxy/src/cli/config-loader.ts +43 -0
- package/packages/proxy/src/cli/env-file.ts +43 -0
- package/packages/proxy/src/cli/main.ts +132 -0
- package/packages/proxy/src/cli/profile-server.ts +176 -0
- package/packages/proxy/src/cli/target.ts +7 -0
- package/packages/proxy/src/http/agent-drafts.ts +103 -0
- package/packages/proxy/src/http/agent-router.ts +69 -0
- package/packages/proxy/src/http/audit-view.ts +15 -0
- package/packages/proxy/src/http/auth-state.ts +44 -0
- package/packages/proxy/src/http/budget-gate.ts +45 -0
- package/packages/proxy/src/http/budget-warnings.ts +7 -0
- package/packages/proxy/src/http/cli-stream-response.ts +51 -0
- package/packages/proxy/src/http/client-identity.ts +51 -0
- package/packages/proxy/src/http/communication-graph.ts +139 -0
- package/packages/proxy/src/http/control-plane-guard.ts +56 -0
- package/packages/proxy/src/http/dashboard-assets.ts +115 -0
- package/packages/proxy/src/http/encoded-usage-meter.ts +32 -0
- package/packages/proxy/src/http/header-utils.ts +65 -0
- package/packages/proxy/src/http/identity-id.ts +11 -0
- package/packages/proxy/src/http/local-api-agent-actions.ts +17 -0
- package/packages/proxy/src/http/local-api-auth.ts +120 -0
- package/packages/proxy/src/http/local-api-consumer-actions.ts +20 -0
- package/packages/proxy/src/http/local-api-identity.ts +194 -0
- package/packages/proxy/src/http/local-api-io.ts +82 -0
- package/packages/proxy/src/http/local-api-keys.ts +126 -0
- package/packages/proxy/src/http/local-api-pipeline.ts +41 -0
- package/packages/proxy/src/http/local-api-plugin-actions.ts +31 -0
- package/packages/proxy/src/http/local-api-provider-actions.ts +181 -0
- package/packages/proxy/src/http/local-api-retention.ts +28 -0
- package/packages/proxy/src/http/local-api-runtime-auth.ts +119 -0
- package/packages/proxy/src/http/local-api-scope.ts +47 -0
- package/packages/proxy/src/http/local-api-state.ts +180 -0
- package/packages/proxy/src/http/local-api.ts +166 -0
- package/packages/proxy/src/http/password-policy.ts +5 -0
- package/packages/proxy/src/http/plugin-data.ts +38 -0
- package/packages/proxy/src/http/plugin-host.ts +87 -0
- package/packages/proxy/src/http/plugin-modules.ts +1 -0
- package/packages/proxy/src/http/plugin-page-loader.ts +24 -0
- package/packages/proxy/src/http/plugin-pipeline.ts +125 -0
- package/packages/proxy/src/http/provider-access.ts +33 -0
- package/packages/proxy/src/http/provider-http-test.ts +133 -0
- package/packages/proxy/src/http/provider-input.ts +39 -0
- package/packages/proxy/src/http/provider-routing-snapshot.ts +28 -0
- package/packages/proxy/src/http/provider-test.ts +149 -0
- package/packages/proxy/src/http/proxy-identity.ts +78 -0
- package/packages/proxy/src/http/public-bind.ts +8 -0
- package/packages/proxy/src/http/request-finish.ts +62 -0
- package/packages/proxy/src/http/request-path.ts +8 -0
- package/packages/proxy/src/http/request-policy.ts +46 -0
- package/packages/proxy/src/http/runtime-auth-proof.ts +55 -0
- package/packages/proxy/src/http/runtime-auth-registry.ts +105 -0
- package/packages/proxy/src/http/runtime-settings.ts +199 -0
- package/packages/proxy/src/http/runtime-state.ts +198 -0
- package/packages/proxy/src/http/server-io.ts +80 -0
- package/packages/proxy/src/http/server-types.ts +17 -0
- package/packages/proxy/src/http/server.ts +190 -0
- package/packages/proxy/src/http/session-secret.ts +19 -0
- package/packages/proxy/src/http/streaming-proxy.ts +88 -0
- package/packages/proxy/src/http/usage-accounting.ts +100 -0
- package/packages/proxy/src/http/usage-restore.ts +15 -0
- package/packages/proxy/src/runtime/cli-diagnostics.ts +64 -0
- package/packages/proxy/src/runtime/cli-env.ts +22 -0
- package/packages/proxy/src/runtime/cli-executor.ts +134 -0
- package/packages/proxy/src/runtime/cli-provider.ts +162 -0
- package/packages/proxy/src/runtime/cli-request.ts +79 -0
- package/packages/proxy/src/runtime/codex-runtime-config.ts +37 -0
- package/packages/proxy/src/runtime/runtime-profile.ts +170 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { join, normalize, posix, win32 } from "node:path";
|
|
2
|
+
import type { RuntimeProfileConfig } from "../../../core/src/providers/provider-catalog.ts";
|
|
3
|
+
import { ensurePrivateDir, writePrivateFile } from "../../../core/src/storage/private-state.ts";
|
|
4
|
+
import { codexConfigSummary } from "./codex-runtime-config.ts";
|
|
5
|
+
|
|
6
|
+
type Runtime = "claude" | "codex";
|
|
7
|
+
type Body = Record<string, unknown>;
|
|
8
|
+
|
|
9
|
+
const CLAUDE_MODES = new Set(["default", "acceptEdits", "auto", "bypassPermissions", "dontAsk", "plan"]);
|
|
10
|
+
const CODEX_SANDBOX = new Set(["read-only", "workspace-write", "danger-full-access"]);
|
|
11
|
+
const CODEX_APPROVAL = new Set(["untrusted", "on-failure", "on-request", "never"]);
|
|
12
|
+
|
|
13
|
+
export type RuntimeProfileImport = { profile?: RuntimeProfileConfig; settingsJson?: string; configToml?: string };
|
|
14
|
+
|
|
15
|
+
export function runtimeProfileFromImport(body: Body, runtime: Runtime): RuntimeProfileImport {
|
|
16
|
+
const profileText = text(body.profileText);
|
|
17
|
+
const profile = profileFields(body, runtime);
|
|
18
|
+
if (runtime === "claude") {
|
|
19
|
+
const settingsSource = text(body.settingsJson) || profileText;
|
|
20
|
+
const settingsJson = settingsSource ? jsonText(settingsSource) : undefined;
|
|
21
|
+
if (settingsSource && !settingsJson) throw new Error("invalid_profile_json");
|
|
22
|
+
const derived = settingsJson ? claudeSettingsSummary(settingsJson) : {};
|
|
23
|
+
return mergeProfile(profile, derived, settingsJson ? { settingsRef: "settings.json" } : {}, { settingsJson });
|
|
24
|
+
}
|
|
25
|
+
const importedConfig = text(body.configToml) || profileText;
|
|
26
|
+
const derived = importedConfig ? codexConfigSummary(importedConfig) : {};
|
|
27
|
+
return mergeProfile(
|
|
28
|
+
profile,
|
|
29
|
+
derived,
|
|
30
|
+
importedConfig ? { configRef: "config.toml" } : {},
|
|
31
|
+
importedConfig ? { configToml: importedConfig } : {}
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function writeRuntimeProfileFiles(authDir: string, runtime: RuntimeProfileImport): Promise<void> {
|
|
36
|
+
if (!runtime.settingsJson && !runtime.configToml) return;
|
|
37
|
+
await ensurePrivateDir(authDir);
|
|
38
|
+
if (runtime.settingsJson) await writePrivateFile(join(authDir, "settings.json"), runtime.settingsJson);
|
|
39
|
+
if (runtime.configToml) await writePrivateFile(join(authDir, "config.toml"), runtime.configToml);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function runtimeCliArgs(runtime: Runtime, authDir: string, profile?: RuntimeProfileConfig): string[] {
|
|
43
|
+
const args = runtime === "claude" ? ["--print"] : ["exec"];
|
|
44
|
+
if (!profile) return args;
|
|
45
|
+
if (runtime === "claude") {
|
|
46
|
+
if (profile.settingsRef) args.push("--settings", join(authDir, "settings.json"));
|
|
47
|
+
if (profile.permissionMode) args.push("--permission-mode", profile.permissionMode);
|
|
48
|
+
pushList(args, "--allowedTools", profile.allowedTools);
|
|
49
|
+
pushList(args, "--disallowedTools", profile.disallowedTools);
|
|
50
|
+
for (const dir of profile.addDirs ?? []) args.push("--add-dir", dir);
|
|
51
|
+
} else {
|
|
52
|
+
if (profile.sandbox) args.push("--sandbox", profile.sandbox);
|
|
53
|
+
if (profile.approval) args.push("-c", `approval_policy="${profile.approval}"`);
|
|
54
|
+
for (const dir of profile.addDirs ?? []) args.push("--add-dir", dir);
|
|
55
|
+
}
|
|
56
|
+
return args;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function profileFields(body: Body, runtime: Runtime): RuntimeProfileConfig | undefined {
|
|
60
|
+
const nested = record(body.profile);
|
|
61
|
+
const source = nested ?? body;
|
|
62
|
+
const profile: RuntimeProfileConfig = {
|
|
63
|
+
permissionMode: runtime === "claude" ? enumValue(source.permissionMode, CLAUDE_MODES, "invalid_permission_mode") : undefined,
|
|
64
|
+
allowedTools: list(source.allowedTools),
|
|
65
|
+
disallowedTools: list(source.disallowedTools),
|
|
66
|
+
addDirs: safeAddDirs(list(source.addDirs)),
|
|
67
|
+
sandbox: runtime === "codex" ? enumValue(field(source, "sandbox", "sandboxMode", "sandbox_mode"), CODEX_SANDBOX, "invalid_sandbox") : undefined,
|
|
68
|
+
approval: runtime === "codex" ? enumValue(field(source, "approval", "approvalPolicy", "approval_policy"), CODEX_APPROVAL, "invalid_approval") : undefined
|
|
69
|
+
};
|
|
70
|
+
return withSummary(profile);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function claudeSettingsSummary(json: string): RuntimeProfileConfig {
|
|
74
|
+
const settings = record(parseJson(json));
|
|
75
|
+
const permissions = record(settings?.permissions);
|
|
76
|
+
return withSummary({
|
|
77
|
+
permissionMode: enumValue(settings?.permissionMode ?? permissions?.defaultMode, CLAUDE_MODES, "invalid_permission_mode"),
|
|
78
|
+
allowedTools: list(settings?.allowedTools ?? permissions?.allow),
|
|
79
|
+
disallowedTools: list(settings?.disallowedTools ?? permissions?.deny),
|
|
80
|
+
addDirs: safeAddDirs(list(settings?.addDirs ?? settings?.additionalDirectories ?? permissions?.addDirs))
|
|
81
|
+
}) ?? {};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function mergeProfile(...items: (RuntimeProfileConfig | RuntimeProfileImport | undefined)[]): RuntimeProfileImport {
|
|
85
|
+
const safe = items.filter((item): item is RuntimeProfileConfig | RuntimeProfileImport => Boolean(item));
|
|
86
|
+
const profile = withSummary(Object.assign({}, ...safe.map((item) => isRuntimeProfileImport(item) ? item.profile : item)));
|
|
87
|
+
const settingsJson = safe.find((item): item is RuntimeProfileImport => isRuntimeProfileImport(item) && Boolean(item.settingsJson))?.settingsJson;
|
|
88
|
+
const configToml = safe.find((item): item is RuntimeProfileImport => isRuntimeProfileImport(item) && Boolean(item.configToml))?.configToml;
|
|
89
|
+
return { profile, settingsJson, configToml };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function isRuntimeProfileImport(item: RuntimeProfileConfig | RuntimeProfileImport): item is RuntimeProfileImport {
|
|
93
|
+
return "profile" in item || "settingsJson" in item || "configToml" in item;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function withSummary(profile: RuntimeProfileConfig): RuntimeProfileConfig | undefined {
|
|
97
|
+
const summary = [
|
|
98
|
+
profile.settingsRef ? "Claude settings" : "",
|
|
99
|
+
profile.configRef ? "Codex config" : "",
|
|
100
|
+
profile.permissionMode ? `mode ${profile.permissionMode}` : "",
|
|
101
|
+
profile.sandbox ? `sandbox ${profile.sandbox}` : "",
|
|
102
|
+
profile.approval ? `approval ${profile.approval}` : "",
|
|
103
|
+
profile.allowedTools?.length ? `${profile.allowedTools.length} allowed tools` : "",
|
|
104
|
+
profile.disallowedTools?.length ? `${profile.disallowedTools.length} denied tools` : "",
|
|
105
|
+
profile.addDirs?.length ? `${profile.addDirs.length} add dirs` : ""
|
|
106
|
+
].filter(Boolean);
|
|
107
|
+
return summary.length ? { ...profile, summary } : undefined;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function pushList(args: string[], flag: string, values?: string[]): void {
|
|
111
|
+
if (values?.length) args.push(flag, values.join(","));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function list(value: unknown): string[] | undefined {
|
|
115
|
+
const values = Array.isArray(value) ? value : typeof value === "string" ? value.split(",") : [];
|
|
116
|
+
const clean = values.map((item) => text(item).slice(0, 160)).filter(Boolean);
|
|
117
|
+
return clean.length ? clean.slice(0, 50) : undefined;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function safeAddDirs(values: string[] | undefined): string[] | undefined {
|
|
121
|
+
if (!values?.length) return undefined;
|
|
122
|
+
const seen = new Set<string>();
|
|
123
|
+
const out: string[] = [];
|
|
124
|
+
for (const value of values) {
|
|
125
|
+
const cleaned = normalize(value);
|
|
126
|
+
const portable = cleaned.replace(/\\/g, "/");
|
|
127
|
+
if (!cleaned || cleaned === "." || /^~(?:[\\/]|$)/.test(cleaned)) throw new Error("invalid_add_dir");
|
|
128
|
+
if (portable === "/" || /^[a-z]:\/?$/i.test(portable)) throw new Error("invalid_add_dir");
|
|
129
|
+
if (portable === ".." || portable.startsWith("../") || portable.includes("/../")) throw new Error("invalid_add_dir");
|
|
130
|
+
if (!posix.isAbsolute(portable) && !win32.isAbsolute(cleaned) && !/^[a-z0-9._-][a-z0-9._\/-]*$/i.test(portable)) throw new Error("invalid_add_dir");
|
|
131
|
+
const key = portable.toLowerCase();
|
|
132
|
+
if (seen.has(key)) continue;
|
|
133
|
+
seen.add(key);
|
|
134
|
+
out.push(cleaned);
|
|
135
|
+
}
|
|
136
|
+
return out.length ? out : undefined;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function text(value: unknown): string {
|
|
140
|
+
return typeof value === "string" ? value.trim() : "";
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function enumValue(value: unknown, allowed: Set<string>, error: string): string | undefined {
|
|
144
|
+
return enumText(text(value), allowed, error);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function enumText(value: string, allowed: Set<string>, error: string): string | undefined {
|
|
148
|
+
if (!value) return undefined;
|
|
149
|
+
const normalized = value.replace(/_/g, "-");
|
|
150
|
+
if (!allowed.has(normalized)) throw new Error(error);
|
|
151
|
+
return normalized;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function record(value: unknown): Body | undefined {
|
|
155
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value as Body : undefined;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function parseJson(value: string): unknown {
|
|
159
|
+
try { return JSON.parse(value); } catch { return undefined; }
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function jsonText(value: string): string | undefined {
|
|
163
|
+
const parsed = parseJson(value);
|
|
164
|
+
return record(parsed) ? `${JSON.stringify(parsed, null, 2)}\n` : undefined;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function field(source: Body, ...names: string[]): unknown {
|
|
168
|
+
for (const name of names) if (source[name] !== undefined) return source[name];
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|