@kl-c/matrixos 0.1.23 → 0.1.25
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/dist/cli/config-manager/load-gateway-env.d.ts +3 -2
- package/dist/cli/index.js +73 -24
- package/dist/cli-node/index.js +73 -24
- package/dist/config/schema/dashboard.d.ts +7 -0
- package/dist/config/schema/oh-my-opencode-config.d.ts +5 -0
- package/dist/config/schema.d.ts +1 -0
- package/dist/features/dashboard/frontend/css/style.css +12 -0
- package/dist/features/dashboard/frontend/index.html +1 -0
- package/dist/features/dashboard/frontend/js/api.js +2 -2
- package/dist/features/dashboard/frontend/js/app.js +60 -0
- package/dist/features/dashboard/gateway-token-handler.d.ts +10 -0
- package/dist/features/dashboard/server.d.ts +2 -0
- package/dist/index.js +641 -568
- package/dist/matrixos.schema.json +17 -0
- package/dist/shared/gateway-token-resolver.d.ts +1 -0
- package/dist/tui.js +14 -0
- package/package.json +1 -1
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* - Warns and returns if the file is missing or unreadable — never throws.
|
|
6
6
|
* - Parses `KEY=VALUE` lines tolerating an optional leading `export ` and
|
|
7
7
|
* surrounding quotes.
|
|
8
|
-
* -
|
|
8
|
+
* - By default, only sets keys that are NOT already present in `process.env`.
|
|
9
|
+
* Pass `force: true` to overwrite existing values (used during hot-reload).
|
|
9
10
|
*/
|
|
10
|
-
export declare function loadGatewayEnvFile(configDir?: string): void;
|
|
11
|
+
export declare function loadGatewayEnvFile(configDir?: string, force?: boolean): void;
|
package/dist/cli/index.js
CHANGED
|
@@ -2145,7 +2145,7 @@ var package_default;
|
|
|
2145
2145
|
var init_package = __esm(() => {
|
|
2146
2146
|
package_default = {
|
|
2147
2147
|
name: "@kl-c/matrixos",
|
|
2148
|
-
version: "0.1.
|
|
2148
|
+
version: "0.1.25",
|
|
2149
2149
|
description: "MaTrixOS \u2014 Agentic OS for OpenCode. Personalizable, communicating, self-improving, resilient.",
|
|
2150
2150
|
main: "./dist/index.js",
|
|
2151
2151
|
types: "dist/index.d.ts",
|
|
@@ -117621,19 +117621,19 @@ __export(exports_generate, {
|
|
|
117621
117621
|
executeGenerateCommand: () => executeGenerateCommand,
|
|
117622
117622
|
ProfileNotFoundError: () => ProfileNotFoundError
|
|
117623
117623
|
});
|
|
117624
|
-
import { existsSync as existsSync70, readFileSync as
|
|
117625
|
-
import { dirname as dirname28, isAbsolute as isAbsolute6, join as
|
|
117624
|
+
import { existsSync as existsSync70, readFileSync as readFileSync56, realpathSync as realpathSync10 } from "fs";
|
|
117625
|
+
import { dirname as dirname28, isAbsolute as isAbsolute6, join as join76, resolve as resolve16 } from "path";
|
|
117626
117626
|
function profilesDirFor(opts) {
|
|
117627
117627
|
if (opts.profilesDir)
|
|
117628
117628
|
return opts.profilesDir;
|
|
117629
117629
|
if (opts.cwd)
|
|
117630
|
-
return
|
|
117631
|
-
return
|
|
117630
|
+
return join76(opts.cwd, PROFILES_RELATIVE);
|
|
117631
|
+
return join76(REPO_ROOT, PROFILES_RELATIVE);
|
|
117632
117632
|
}
|
|
117633
117633
|
function loadProfile(name2, options = {}) {
|
|
117634
117634
|
const fs21 = options.fs ?? defaultFS2;
|
|
117635
117635
|
const dir = profilesDirFor(options);
|
|
117636
|
-
const path27 =
|
|
117636
|
+
const path27 = join76(dir, `${name2}.json`);
|
|
117637
117637
|
if (!fs21.existsSync(path27)) {
|
|
117638
117638
|
throw new ProfileNotFoundError(name2);
|
|
117639
117639
|
}
|
|
@@ -117646,7 +117646,7 @@ function listProfiles(options = {}) {
|
|
|
117646
117646
|
const known = options.knownNames ?? ["trader", "plumber"];
|
|
117647
117647
|
const out = [];
|
|
117648
117648
|
for (const name2 of known) {
|
|
117649
|
-
const path27 =
|
|
117649
|
+
const path27 = join76(dir, `${name2}.json`);
|
|
117650
117650
|
if (fs21.existsSync(path27)) {
|
|
117651
117651
|
try {
|
|
117652
117652
|
const raw = JSON.parse(fs21.readFileSync(path27, "utf-8"));
|
|
@@ -117719,7 +117719,7 @@ var init_generate = __esm(() => {
|
|
|
117719
117719
|
init_src4();
|
|
117720
117720
|
init_src4();
|
|
117721
117721
|
REPO_ROOT = resolve16(dirname28(new URL(import.meta.url).pathname), "..", "..", "..", "..", "..");
|
|
117722
|
-
defaultFS2 = { existsSync: existsSync70, readFileSync:
|
|
117722
|
+
defaultFS2 = { existsSync: existsSync70, readFileSync: readFileSync56, realpathSync: realpathSync10 };
|
|
117723
117723
|
ProfileNotFoundError = class ProfileNotFoundError extends Error {
|
|
117724
117724
|
profileName;
|
|
117725
117725
|
constructor(profileName) {
|
|
@@ -117871,8 +117871,8 @@ var exports_profile_resolve = {};
|
|
|
117871
117871
|
__export(exports_profile_resolve, {
|
|
117872
117872
|
executeProfileResolveCommand: () => executeProfileResolveCommand
|
|
117873
117873
|
});
|
|
117874
|
-
import { existsSync as existsSync72, readdirSync as readdirSync15, readFileSync as
|
|
117875
|
-
import { join as
|
|
117874
|
+
import { existsSync as existsSync72, readdirSync as readdirSync15, readFileSync as readFileSync57 } from "fs";
|
|
117875
|
+
import { join as join78, resolve as resolve17, dirname as dirname29 } from "path";
|
|
117876
117876
|
function executeProfileResolveCommand(args) {
|
|
117877
117877
|
if (args.options.help) {
|
|
117878
117878
|
return {
|
|
@@ -117897,7 +117897,7 @@ function executeProfileResolveCommand(args) {
|
|
|
117897
117897
|
` };
|
|
117898
117898
|
}
|
|
117899
117899
|
const name2 = nameRaw.endsWith(".json") ? nameRaw.slice(0, -5) : nameRaw;
|
|
117900
|
-
const profilesDir =
|
|
117900
|
+
const profilesDir = join78(REPO_ROOT2, PROFILES_RELATIVE2);
|
|
117901
117901
|
if (!existsSync72(profilesDir)) {
|
|
117902
117902
|
return { exitCode: 1, stdout: `error: profiles directory not found at ${profilesDir}
|
|
117903
117903
|
` };
|
|
@@ -117917,8 +117917,8 @@ function executeProfileResolveCommand(args) {
|
|
|
117917
117917
|
const registry2 = {};
|
|
117918
117918
|
for (const file3 of profileFiles) {
|
|
117919
117919
|
try {
|
|
117920
|
-
const filePath =
|
|
117921
|
-
const raw = JSON.parse(
|
|
117920
|
+
const filePath = join78(profilesDir, file3);
|
|
117921
|
+
const raw = JSON.parse(readFileSync57(filePath, "utf-8"));
|
|
117922
117922
|
const profile2 = ProfileSchema.parse(raw);
|
|
117923
117923
|
registry2[profile2.name] = profile2;
|
|
117924
117924
|
} catch {}
|
|
@@ -117980,8 +117980,8 @@ __export(exports_export, {
|
|
|
117980
117980
|
getShell: () => getShell,
|
|
117981
117981
|
executeExportCommand: () => executeExportCommand
|
|
117982
117982
|
});
|
|
117983
|
-
import { existsSync as existsSync73, readFileSync as
|
|
117984
|
-
import { isAbsolute as isAbsolute7, join as
|
|
117983
|
+
import { existsSync as existsSync73, readFileSync as readFileSync58, writeFileSync as writeFileSync25, copyFileSync as copyFileSync7, realpathSync as realpathSync11, mkdirSync as mkdirSync26 } from "fs";
|
|
117984
|
+
import { isAbsolute as isAbsolute7, join as join79, resolve as resolve18, dirname as dirname30 } from "path";
|
|
117985
117985
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
117986
117986
|
function setShell(shell) {
|
|
117987
117987
|
activeShell = shell;
|
|
@@ -118022,7 +118022,7 @@ function executeExportCommand(args) {
|
|
|
118022
118022
|
return { exitCode: 1, stdout: `error: generate failed: ${message}
|
|
118023
118023
|
` };
|
|
118024
118024
|
}
|
|
118025
|
-
const pkgPath =
|
|
118025
|
+
const pkgPath = join79(absoluteTargetDir, "package.json");
|
|
118026
118026
|
let pkg;
|
|
118027
118027
|
try {
|
|
118028
118028
|
pkg = JSON.parse(fs21.readFileSync(pkgPath, "utf-8"));
|
|
@@ -118062,7 +118062,7 @@ ${packResult.stdout}
|
|
|
118062
118062
|
return { exitCode: 1, stdout: `error: npm pack produced no tarball name in output
|
|
118063
118063
|
` };
|
|
118064
118064
|
}
|
|
118065
|
-
let tgzPath =
|
|
118065
|
+
let tgzPath = join79(absoluteTargetDir, tgzName);
|
|
118066
118066
|
if (args.options.output) {
|
|
118067
118067
|
const outputPath = args.options.output;
|
|
118068
118068
|
const absoluteOutput = isAbsolute7(outputPath) ? outputPath : resolve18(process.cwd(), outputPath);
|
|
@@ -118104,7 +118104,7 @@ var init_export = __esm(() => {
|
|
|
118104
118104
|
activeShell = defaultShell;
|
|
118105
118105
|
defaultExportFS = {
|
|
118106
118106
|
existsSync: existsSync73,
|
|
118107
|
-
readFileSync:
|
|
118107
|
+
readFileSync: readFileSync58,
|
|
118108
118108
|
writeFileSync: writeFileSync25,
|
|
118109
118109
|
copyFileSync: copyFileSync7,
|
|
118110
118110
|
realpathSync: realpathSync11,
|
|
@@ -122216,6 +122216,13 @@ init_zod();
|
|
|
122216
122216
|
var CronConfigSchema = exports_external.object({
|
|
122217
122217
|
enabled: exports_external.boolean().default(true)
|
|
122218
122218
|
}).strict();
|
|
122219
|
+
// packages/omo-opencode/src/config/schema/dashboard.ts
|
|
122220
|
+
init_zod();
|
|
122221
|
+
var DashboardConfigSchema = exports_external.object({
|
|
122222
|
+
enabled: exports_external.boolean().optional(),
|
|
122223
|
+
port: exports_external.number().int().min(1).max(65535).optional(),
|
|
122224
|
+
gateway_passphrase: exports_external.string().optional()
|
|
122225
|
+
});
|
|
122219
122226
|
// packages/omo-opencode/src/config/schema/default-mode.ts
|
|
122220
122227
|
init_zod();
|
|
122221
122228
|
var DefaultModeConfigSchema = exports_external.object({
|
|
@@ -122723,6 +122730,7 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
|
|
|
122723
122730
|
morpheus: MorpheusConfigSchema.optional(),
|
|
122724
122731
|
start_work: StartWorkConfigSchema.optional(),
|
|
122725
122732
|
gateway: GatewayConfigSectionSchema,
|
|
122733
|
+
dashboard: DashboardConfigSchema.optional(),
|
|
122726
122734
|
watchdog: WatchdogConfigSchema.optional(),
|
|
122727
122735
|
egress: EgressConfigSectionSchema,
|
|
122728
122736
|
cron: CronConfigSchema.optional(),
|
|
@@ -141144,6 +141152,7 @@ async function traceCli(sessionId, options = {}) {
|
|
|
141144
141152
|
|
|
141145
141153
|
// packages/omo-opencode/src/cli/dashboard.ts
|
|
141146
141154
|
import * as path25 from "path";
|
|
141155
|
+
import { readFileSync as readFileSync55 } from "fs";
|
|
141147
141156
|
|
|
141148
141157
|
// packages/omo-opencode/src/features/dashboard/data-provider.ts
|
|
141149
141158
|
import * as os12 from "os";
|
|
@@ -141703,6 +141712,7 @@ function createDataProvider(config4) {
|
|
|
141703
141712
|
}
|
|
141704
141713
|
|
|
141705
141714
|
// packages/omo-opencode/src/features/dashboard/server.ts
|
|
141715
|
+
init_write_gateway_env();
|
|
141706
141716
|
var MIME = {
|
|
141707
141717
|
".html": "text/html; charset=utf-8",
|
|
141708
141718
|
".css": "text/css; charset=utf-8",
|
|
@@ -141726,8 +141736,8 @@ function createDashboardServer(dataProvider, config4) {
|
|
|
141726
141736
|
const path25 = url3.pathname;
|
|
141727
141737
|
const corsHeaders = {
|
|
141728
141738
|
"Access-Control-Allow-Origin": "*",
|
|
141729
|
-
"Access-Control-Allow-Methods": "GET, OPTIONS",
|
|
141730
|
-
"Access-Control-Allow-Headers": "Content-Type"
|
|
141739
|
+
"Access-Control-Allow-Methods": "GET, POST, PUT, OPTIONS",
|
|
141740
|
+
"Access-Control-Allow-Headers": "Content-Type, x-passphrase"
|
|
141731
141741
|
};
|
|
141732
141742
|
if (req.method === "OPTIONS") {
|
|
141733
141743
|
return new Response(null, { headers: corsHeaders });
|
|
@@ -141799,6 +141809,30 @@ function createDashboardServer(dataProvider, config4) {
|
|
|
141799
141809
|
return Response.json(dataProvider.getMemory(), { headers: jsonHeaders });
|
|
141800
141810
|
case "/api/skills":
|
|
141801
141811
|
return Response.json(dataProvider.getSkills(), { headers: jsonHeaders });
|
|
141812
|
+
case "/api/gateway/token": {
|
|
141813
|
+
if (req.method !== "POST") {
|
|
141814
|
+
return new Response("Method Not Allowed", { status: 405, headers: corsHeaders });
|
|
141815
|
+
}
|
|
141816
|
+
const body = await req.json();
|
|
141817
|
+
const type2 = body.type;
|
|
141818
|
+
const token = body.token;
|
|
141819
|
+
const passphrase = body.passphrase;
|
|
141820
|
+
if (type2 !== "telegram" && type2 !== "discord") {
|
|
141821
|
+
return Response.json({ error: "Invalid type. Must be 'telegram' or 'discord'" }, { status: 400, headers: jsonHeaders });
|
|
141822
|
+
}
|
|
141823
|
+
if (typeof token !== "string" || token.length === 0) {
|
|
141824
|
+
return Response.json({ error: "Missing or empty token" }, { status: 400, headers: jsonHeaders });
|
|
141825
|
+
}
|
|
141826
|
+
if (!config4.gatewayPassphrase) {
|
|
141827
|
+
return Response.json({ error: "Passphrase not configured" }, { status: 400, headers: jsonHeaders });
|
|
141828
|
+
}
|
|
141829
|
+
if (passphrase !== config4.gatewayPassphrase) {
|
|
141830
|
+
return Response.json({ error: "Invalid passphrase" }, { status: 401, headers: jsonHeaders });
|
|
141831
|
+
}
|
|
141832
|
+
const key = type2 === "telegram" ? "TELEGRAM_BOT_TOKEN" : "DISCORD_BOT_TOKEN";
|
|
141833
|
+
const envPath = writeGatewayEnvToken(key, token);
|
|
141834
|
+
return Response.json({ ok: true, path: envPath }, { headers: jsonHeaders });
|
|
141835
|
+
}
|
|
141802
141836
|
default:
|
|
141803
141837
|
return new Response("Not Found", { status: 404, headers: corsHeaders });
|
|
141804
141838
|
}
|
|
@@ -141834,21 +141868,36 @@ function createDashboardServer(dataProvider, config4) {
|
|
|
141834
141868
|
server2 = null;
|
|
141835
141869
|
},
|
|
141836
141870
|
get port() {
|
|
141837
|
-
return config4.port;
|
|
141871
|
+
return server2?.port ?? config4.port;
|
|
141838
141872
|
}
|
|
141839
141873
|
};
|
|
141840
141874
|
}
|
|
141841
141875
|
|
|
141842
141876
|
// packages/omo-opencode/src/cli/dashboard.ts
|
|
141877
|
+
init_config_context();
|
|
141878
|
+
init_jsonc_parser2();
|
|
141879
|
+
function loadGatewayPassphrase() {
|
|
141880
|
+
try {
|
|
141881
|
+
const configDir = getConfigDir();
|
|
141882
|
+
const configPath = path25.join(configDir, "matrixos.jsonc");
|
|
141883
|
+
const raw = readFileSync55(configPath, "utf-8");
|
|
141884
|
+
const config4 = parseJsonc(raw);
|
|
141885
|
+
const dashboard2 = config4.dashboard;
|
|
141886
|
+
return typeof dashboard2?.gatewayPassphrase === "string" ? dashboard2.gatewayPassphrase : undefined;
|
|
141887
|
+
} catch {
|
|
141888
|
+
return;
|
|
141889
|
+
}
|
|
141890
|
+
}
|
|
141843
141891
|
async function dashboardCli(options) {
|
|
141844
141892
|
const port = options.port ?? 9123;
|
|
141845
141893
|
const host = options.host ?? "0.0.0.0";
|
|
141846
141894
|
const frontendDir = path25.resolve(import.meta.dir, "../features/dashboard/frontend");
|
|
141895
|
+
const gatewayPassphrase = loadGatewayPassphrase();
|
|
141847
141896
|
console.log(`[dashboard] starting MaTrixOS dashboard on http://${host}:${port}`);
|
|
141848
141897
|
console.log(`[dashboard] frontend: ${frontendDir}`);
|
|
141849
141898
|
try {
|
|
141850
141899
|
const dataProvider = createDataProvider();
|
|
141851
|
-
const server2 = createDashboardServer(dataProvider, { port, host, frontendDir });
|
|
141900
|
+
const server2 = createDashboardServer(dataProvider, { port, host, frontendDir, gatewayPassphrase });
|
|
141852
141901
|
server2.start();
|
|
141853
141902
|
console.log(`[dashboard] ready \u2014 http://${host}:${port}`);
|
|
141854
141903
|
if (!options.daemon) {
|
|
@@ -141875,11 +141924,11 @@ async function dashboardCli(options) {
|
|
|
141875
141924
|
}
|
|
141876
141925
|
|
|
141877
141926
|
// packages/omo-opencode/src/cli/architect.ts
|
|
141878
|
-
import { join as
|
|
141927
|
+
import { join as join74 } from "path";
|
|
141879
141928
|
var IMPROVEMENTS_DIR = ".matrixos/improvements";
|
|
141880
141929
|
function getStore(directory) {
|
|
141881
141930
|
const baseDir = directory ?? process.cwd();
|
|
141882
|
-
return createImprovementStore(
|
|
141931
|
+
return createImprovementStore(join74(baseDir, IMPROVEMENTS_DIR));
|
|
141883
141932
|
}
|
|
141884
141933
|
async function architectReview(options) {
|
|
141885
141934
|
const store4 = getStore(options.directory);
|
package/dist/cli-node/index.js
CHANGED
|
@@ -2145,7 +2145,7 @@ var package_default;
|
|
|
2145
2145
|
var init_package = __esm(() => {
|
|
2146
2146
|
package_default = {
|
|
2147
2147
|
name: "@kl-c/matrixos",
|
|
2148
|
-
version: "0.1.
|
|
2148
|
+
version: "0.1.25",
|
|
2149
2149
|
description: "MaTrixOS \u2014 Agentic OS for OpenCode. Personalizable, communicating, self-improving, resilient.",
|
|
2150
2150
|
main: "./dist/index.js",
|
|
2151
2151
|
types: "dist/index.d.ts",
|
|
@@ -117676,19 +117676,19 @@ __export(exports_generate, {
|
|
|
117676
117676
|
executeGenerateCommand: () => executeGenerateCommand,
|
|
117677
117677
|
ProfileNotFoundError: () => ProfileNotFoundError
|
|
117678
117678
|
});
|
|
117679
|
-
import { existsSync as existsSync70, readFileSync as
|
|
117680
|
-
import { dirname as dirname28, isAbsolute as isAbsolute6, join as
|
|
117679
|
+
import { existsSync as existsSync70, readFileSync as readFileSync56, realpathSync as realpathSync10 } from "fs";
|
|
117680
|
+
import { dirname as dirname28, isAbsolute as isAbsolute6, join as join76, resolve as resolve16 } from "path";
|
|
117681
117681
|
function profilesDirFor(opts) {
|
|
117682
117682
|
if (opts.profilesDir)
|
|
117683
117683
|
return opts.profilesDir;
|
|
117684
117684
|
if (opts.cwd)
|
|
117685
|
-
return
|
|
117686
|
-
return
|
|
117685
|
+
return join76(opts.cwd, PROFILES_RELATIVE);
|
|
117686
|
+
return join76(REPO_ROOT, PROFILES_RELATIVE);
|
|
117687
117687
|
}
|
|
117688
117688
|
function loadProfile(name2, options = {}) {
|
|
117689
117689
|
const fs21 = options.fs ?? defaultFS2;
|
|
117690
117690
|
const dir = profilesDirFor(options);
|
|
117691
|
-
const path27 =
|
|
117691
|
+
const path27 = join76(dir, `${name2}.json`);
|
|
117692
117692
|
if (!fs21.existsSync(path27)) {
|
|
117693
117693
|
throw new ProfileNotFoundError(name2);
|
|
117694
117694
|
}
|
|
@@ -117701,7 +117701,7 @@ function listProfiles(options = {}) {
|
|
|
117701
117701
|
const known = options.knownNames ?? ["trader", "plumber"];
|
|
117702
117702
|
const out = [];
|
|
117703
117703
|
for (const name2 of known) {
|
|
117704
|
-
const path27 =
|
|
117704
|
+
const path27 = join76(dir, `${name2}.json`);
|
|
117705
117705
|
if (fs21.existsSync(path27)) {
|
|
117706
117706
|
try {
|
|
117707
117707
|
const raw = JSON.parse(fs21.readFileSync(path27, "utf-8"));
|
|
@@ -117774,7 +117774,7 @@ var init_generate = __esm(() => {
|
|
|
117774
117774
|
init_src4();
|
|
117775
117775
|
init_src4();
|
|
117776
117776
|
REPO_ROOT = resolve16(dirname28(new URL(import.meta.url).pathname), "..", "..", "..", "..", "..");
|
|
117777
|
-
defaultFS2 = { existsSync: existsSync70, readFileSync:
|
|
117777
|
+
defaultFS2 = { existsSync: existsSync70, readFileSync: readFileSync56, realpathSync: realpathSync10 };
|
|
117778
117778
|
ProfileNotFoundError = class ProfileNotFoundError extends Error {
|
|
117779
117779
|
profileName;
|
|
117780
117780
|
constructor(profileName) {
|
|
@@ -117926,8 +117926,8 @@ var exports_profile_resolve = {};
|
|
|
117926
117926
|
__export(exports_profile_resolve, {
|
|
117927
117927
|
executeProfileResolveCommand: () => executeProfileResolveCommand
|
|
117928
117928
|
});
|
|
117929
|
-
import { existsSync as existsSync72, readdirSync as readdirSync15, readFileSync as
|
|
117930
|
-
import { join as
|
|
117929
|
+
import { existsSync as existsSync72, readdirSync as readdirSync15, readFileSync as readFileSync57 } from "fs";
|
|
117930
|
+
import { join as join78, resolve as resolve17, dirname as dirname29 } from "path";
|
|
117931
117931
|
function executeProfileResolveCommand(args) {
|
|
117932
117932
|
if (args.options.help) {
|
|
117933
117933
|
return {
|
|
@@ -117952,7 +117952,7 @@ function executeProfileResolveCommand(args) {
|
|
|
117952
117952
|
` };
|
|
117953
117953
|
}
|
|
117954
117954
|
const name2 = nameRaw.endsWith(".json") ? nameRaw.slice(0, -5) : nameRaw;
|
|
117955
|
-
const profilesDir =
|
|
117955
|
+
const profilesDir = join78(REPO_ROOT2, PROFILES_RELATIVE2);
|
|
117956
117956
|
if (!existsSync72(profilesDir)) {
|
|
117957
117957
|
return { exitCode: 1, stdout: `error: profiles directory not found at ${profilesDir}
|
|
117958
117958
|
` };
|
|
@@ -117972,8 +117972,8 @@ function executeProfileResolveCommand(args) {
|
|
|
117972
117972
|
const registry2 = {};
|
|
117973
117973
|
for (const file3 of profileFiles) {
|
|
117974
117974
|
try {
|
|
117975
|
-
const filePath =
|
|
117976
|
-
const raw = JSON.parse(
|
|
117975
|
+
const filePath = join78(profilesDir, file3);
|
|
117976
|
+
const raw = JSON.parse(readFileSync57(filePath, "utf-8"));
|
|
117977
117977
|
const profile2 = ProfileSchema.parse(raw);
|
|
117978
117978
|
registry2[profile2.name] = profile2;
|
|
117979
117979
|
} catch {}
|
|
@@ -118035,8 +118035,8 @@ __export(exports_export, {
|
|
|
118035
118035
|
getShell: () => getShell,
|
|
118036
118036
|
executeExportCommand: () => executeExportCommand
|
|
118037
118037
|
});
|
|
118038
|
-
import { existsSync as existsSync73, readFileSync as
|
|
118039
|
-
import { isAbsolute as isAbsolute7, join as
|
|
118038
|
+
import { existsSync as existsSync73, readFileSync as readFileSync58, writeFileSync as writeFileSync25, copyFileSync as copyFileSync7, realpathSync as realpathSync11, mkdirSync as mkdirSync26 } from "fs";
|
|
118039
|
+
import { isAbsolute as isAbsolute7, join as join79, resolve as resolve18, dirname as dirname30 } from "path";
|
|
118040
118040
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
118041
118041
|
function setShell(shell) {
|
|
118042
118042
|
activeShell = shell;
|
|
@@ -118077,7 +118077,7 @@ function executeExportCommand(args) {
|
|
|
118077
118077
|
return { exitCode: 1, stdout: `error: generate failed: ${message}
|
|
118078
118078
|
` };
|
|
118079
118079
|
}
|
|
118080
|
-
const pkgPath =
|
|
118080
|
+
const pkgPath = join79(absoluteTargetDir, "package.json");
|
|
118081
118081
|
let pkg;
|
|
118082
118082
|
try {
|
|
118083
118083
|
pkg = JSON.parse(fs21.readFileSync(pkgPath, "utf-8"));
|
|
@@ -118117,7 +118117,7 @@ ${packResult.stdout}
|
|
|
118117
118117
|
return { exitCode: 1, stdout: `error: npm pack produced no tarball name in output
|
|
118118
118118
|
` };
|
|
118119
118119
|
}
|
|
118120
|
-
let tgzPath =
|
|
118120
|
+
let tgzPath = join79(absoluteTargetDir, tgzName);
|
|
118121
118121
|
if (args.options.output) {
|
|
118122
118122
|
const outputPath = args.options.output;
|
|
118123
118123
|
const absoluteOutput = isAbsolute7(outputPath) ? outputPath : resolve18(process.cwd(), outputPath);
|
|
@@ -118159,7 +118159,7 @@ var init_export = __esm(() => {
|
|
|
118159
118159
|
activeShell = defaultShell;
|
|
118160
118160
|
defaultExportFS = {
|
|
118161
118161
|
existsSync: existsSync73,
|
|
118162
|
-
readFileSync:
|
|
118162
|
+
readFileSync: readFileSync58,
|
|
118163
118163
|
writeFileSync: writeFileSync25,
|
|
118164
118164
|
copyFileSync: copyFileSync7,
|
|
118165
118165
|
realpathSync: realpathSync11,
|
|
@@ -122271,6 +122271,13 @@ init_zod();
|
|
|
122271
122271
|
var CronConfigSchema = exports_external.object({
|
|
122272
122272
|
enabled: exports_external.boolean().default(true)
|
|
122273
122273
|
}).strict();
|
|
122274
|
+
// packages/omo-opencode/src/config/schema/dashboard.ts
|
|
122275
|
+
init_zod();
|
|
122276
|
+
var DashboardConfigSchema = exports_external.object({
|
|
122277
|
+
enabled: exports_external.boolean().optional(),
|
|
122278
|
+
port: exports_external.number().int().min(1).max(65535).optional(),
|
|
122279
|
+
gateway_passphrase: exports_external.string().optional()
|
|
122280
|
+
});
|
|
122274
122281
|
// packages/omo-opencode/src/config/schema/default-mode.ts
|
|
122275
122282
|
init_zod();
|
|
122276
122283
|
var DefaultModeConfigSchema = exports_external.object({
|
|
@@ -122778,6 +122785,7 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
|
|
|
122778
122785
|
morpheus: MorpheusConfigSchema.optional(),
|
|
122779
122786
|
start_work: StartWorkConfigSchema.optional(),
|
|
122780
122787
|
gateway: GatewayConfigSectionSchema,
|
|
122788
|
+
dashboard: DashboardConfigSchema.optional(),
|
|
122781
122789
|
watchdog: WatchdogConfigSchema.optional(),
|
|
122782
122790
|
egress: EgressConfigSectionSchema,
|
|
122783
122791
|
cron: CronConfigSchema.optional(),
|
|
@@ -141199,6 +141207,7 @@ async function traceCli(sessionId, options = {}) {
|
|
|
141199
141207
|
|
|
141200
141208
|
// packages/omo-opencode/src/cli/dashboard.ts
|
|
141201
141209
|
import * as path25 from "path";
|
|
141210
|
+
import { readFileSync as readFileSync55 } from "fs";
|
|
141202
141211
|
|
|
141203
141212
|
// packages/omo-opencode/src/features/dashboard/data-provider.ts
|
|
141204
141213
|
import * as os12 from "os";
|
|
@@ -141758,6 +141767,7 @@ function createDataProvider(config4) {
|
|
|
141758
141767
|
}
|
|
141759
141768
|
|
|
141760
141769
|
// packages/omo-opencode/src/features/dashboard/server.ts
|
|
141770
|
+
init_write_gateway_env();
|
|
141761
141771
|
var MIME = {
|
|
141762
141772
|
".html": "text/html; charset=utf-8",
|
|
141763
141773
|
".css": "text/css; charset=utf-8",
|
|
@@ -141781,8 +141791,8 @@ function createDashboardServer(dataProvider, config4) {
|
|
|
141781
141791
|
const path25 = url3.pathname;
|
|
141782
141792
|
const corsHeaders = {
|
|
141783
141793
|
"Access-Control-Allow-Origin": "*",
|
|
141784
|
-
"Access-Control-Allow-Methods": "GET, OPTIONS",
|
|
141785
|
-
"Access-Control-Allow-Headers": "Content-Type"
|
|
141794
|
+
"Access-Control-Allow-Methods": "GET, POST, PUT, OPTIONS",
|
|
141795
|
+
"Access-Control-Allow-Headers": "Content-Type, x-passphrase"
|
|
141786
141796
|
};
|
|
141787
141797
|
if (req.method === "OPTIONS") {
|
|
141788
141798
|
return new Response(null, { headers: corsHeaders });
|
|
@@ -141854,6 +141864,30 @@ function createDashboardServer(dataProvider, config4) {
|
|
|
141854
141864
|
return Response.json(dataProvider.getMemory(), { headers: jsonHeaders });
|
|
141855
141865
|
case "/api/skills":
|
|
141856
141866
|
return Response.json(dataProvider.getSkills(), { headers: jsonHeaders });
|
|
141867
|
+
case "/api/gateway/token": {
|
|
141868
|
+
if (req.method !== "POST") {
|
|
141869
|
+
return new Response("Method Not Allowed", { status: 405, headers: corsHeaders });
|
|
141870
|
+
}
|
|
141871
|
+
const body = await req.json();
|
|
141872
|
+
const type2 = body.type;
|
|
141873
|
+
const token = body.token;
|
|
141874
|
+
const passphrase = body.passphrase;
|
|
141875
|
+
if (type2 !== "telegram" && type2 !== "discord") {
|
|
141876
|
+
return Response.json({ error: "Invalid type. Must be 'telegram' or 'discord'" }, { status: 400, headers: jsonHeaders });
|
|
141877
|
+
}
|
|
141878
|
+
if (typeof token !== "string" || token.length === 0) {
|
|
141879
|
+
return Response.json({ error: "Missing or empty token" }, { status: 400, headers: jsonHeaders });
|
|
141880
|
+
}
|
|
141881
|
+
if (!config4.gatewayPassphrase) {
|
|
141882
|
+
return Response.json({ error: "Passphrase not configured" }, { status: 400, headers: jsonHeaders });
|
|
141883
|
+
}
|
|
141884
|
+
if (passphrase !== config4.gatewayPassphrase) {
|
|
141885
|
+
return Response.json({ error: "Invalid passphrase" }, { status: 401, headers: jsonHeaders });
|
|
141886
|
+
}
|
|
141887
|
+
const key = type2 === "telegram" ? "TELEGRAM_BOT_TOKEN" : "DISCORD_BOT_TOKEN";
|
|
141888
|
+
const envPath = writeGatewayEnvToken(key, token);
|
|
141889
|
+
return Response.json({ ok: true, path: envPath }, { headers: jsonHeaders });
|
|
141890
|
+
}
|
|
141857
141891
|
default:
|
|
141858
141892
|
return new Response("Not Found", { status: 404, headers: corsHeaders });
|
|
141859
141893
|
}
|
|
@@ -141889,21 +141923,36 @@ function createDashboardServer(dataProvider, config4) {
|
|
|
141889
141923
|
server2 = null;
|
|
141890
141924
|
},
|
|
141891
141925
|
get port() {
|
|
141892
|
-
return config4.port;
|
|
141926
|
+
return server2?.port ?? config4.port;
|
|
141893
141927
|
}
|
|
141894
141928
|
};
|
|
141895
141929
|
}
|
|
141896
141930
|
|
|
141897
141931
|
// packages/omo-opencode/src/cli/dashboard.ts
|
|
141932
|
+
init_config_context();
|
|
141933
|
+
init_jsonc_parser2();
|
|
141934
|
+
function loadGatewayPassphrase() {
|
|
141935
|
+
try {
|
|
141936
|
+
const configDir = getConfigDir();
|
|
141937
|
+
const configPath = path25.join(configDir, "matrixos.jsonc");
|
|
141938
|
+
const raw = readFileSync55(configPath, "utf-8");
|
|
141939
|
+
const config4 = parseJsonc(raw);
|
|
141940
|
+
const dashboard2 = config4.dashboard;
|
|
141941
|
+
return typeof dashboard2?.gatewayPassphrase === "string" ? dashboard2.gatewayPassphrase : undefined;
|
|
141942
|
+
} catch {
|
|
141943
|
+
return;
|
|
141944
|
+
}
|
|
141945
|
+
}
|
|
141898
141946
|
async function dashboardCli(options) {
|
|
141899
141947
|
const port = options.port ?? 9123;
|
|
141900
141948
|
const host = options.host ?? "0.0.0.0";
|
|
141901
141949
|
const frontendDir = path25.resolve(import.meta.dir, "../features/dashboard/frontend");
|
|
141950
|
+
const gatewayPassphrase = loadGatewayPassphrase();
|
|
141902
141951
|
console.log(`[dashboard] starting MaTrixOS dashboard on http://${host}:${port}`);
|
|
141903
141952
|
console.log(`[dashboard] frontend: ${frontendDir}`);
|
|
141904
141953
|
try {
|
|
141905
141954
|
const dataProvider = createDataProvider();
|
|
141906
|
-
const server2 = createDashboardServer(dataProvider, { port, host, frontendDir });
|
|
141955
|
+
const server2 = createDashboardServer(dataProvider, { port, host, frontendDir, gatewayPassphrase });
|
|
141907
141956
|
server2.start();
|
|
141908
141957
|
console.log(`[dashboard] ready \u2014 http://${host}:${port}`);
|
|
141909
141958
|
if (!options.daemon) {
|
|
@@ -141930,11 +141979,11 @@ async function dashboardCli(options) {
|
|
|
141930
141979
|
}
|
|
141931
141980
|
|
|
141932
141981
|
// packages/omo-opencode/src/cli/architect.ts
|
|
141933
|
-
import { join as
|
|
141982
|
+
import { join as join74 } from "path";
|
|
141934
141983
|
var IMPROVEMENTS_DIR = ".matrixos/improvements";
|
|
141935
141984
|
function getStore(directory) {
|
|
141936
141985
|
const baseDir = directory ?? process.cwd();
|
|
141937
|
-
return createImprovementStore(
|
|
141986
|
+
return createImprovementStore(join74(baseDir, IMPROVEMENTS_DIR));
|
|
141938
141987
|
}
|
|
141939
141988
|
async function architectReview(options) {
|
|
141940
141989
|
const store4 = getStore(options.directory);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const DashboardConfigSchema: z.ZodObject<{
|
|
3
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
4
|
+
port: z.ZodOptional<z.ZodNumber>;
|
|
5
|
+
gateway_passphrase: z.ZodOptional<z.ZodString>;
|
|
6
|
+
}, z.core.$strip>;
|
|
7
|
+
export type DashboardConfig = z.infer<typeof DashboardConfigSchema>;
|
|
@@ -2446,6 +2446,11 @@ export declare const OhMyOpenCodeConfigSchema: z.ZodObject<{
|
|
|
2446
2446
|
auditLogPath: z.ZodOptional<z.ZodString>;
|
|
2447
2447
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
2448
2448
|
}, z.core.$strict>>;
|
|
2449
|
+
dashboard: z.ZodOptional<z.ZodObject<{
|
|
2450
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
2451
|
+
port: z.ZodOptional<z.ZodNumber>;
|
|
2452
|
+
gateway_passphrase: z.ZodOptional<z.ZodString>;
|
|
2453
|
+
}, z.core.$strip>>;
|
|
2449
2454
|
watchdog: z.ZodOptional<z.ZodObject<{
|
|
2450
2455
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
2451
2456
|
doomLoopThreshold: z.ZodDefault<z.ZodNumber>;
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export * from "./schema/codegraph";
|
|
|
9
9
|
export * from "./schema/comment-checker";
|
|
10
10
|
export * from "./schema/commands";
|
|
11
11
|
export * from "./schema/cron";
|
|
12
|
+
export * from "./schema/dashboard";
|
|
12
13
|
export * from "./schema/default-mode";
|
|
13
14
|
export * from "./schema/dynamic-context-pruning";
|
|
14
15
|
export * from "./schema/egress";
|
|
@@ -207,5 +207,17 @@ body{font-family:var(--font-body);font-size:var(--text-base);color:var(--text-pr
|
|
|
207
207
|
.config-editor{width:100%;min-height:400px;background:var(--bg-base);color:var(--text-primary);font-family:var(--font-mono);font-size:var(--text-sm);border:none;padding:var(--space-4);resize:vertical;tab-size:2;line-height:1.5}
|
|
208
208
|
.config-editor:focus{outline:1px solid var(--accent-primary)}
|
|
209
209
|
|
|
210
|
+
/* FORM CONTROLS (gateway + future forms) */
|
|
211
|
+
.label{display:block;font-size:var(--text-xs);color:var(--text-secondary);font-weight:500;margin-bottom:var(--space-1);text-transform:uppercase;letter-spacing:.05em}
|
|
212
|
+
.input,.select{width:100%;background:var(--bg-base);color:var(--text-primary);border:1px solid var(--border-default);border-radius:var(--radius-lg);padding:var(--space-2) var(--space-3);font-size:var(--text-sm);font-family:var(--font-body);transition:border-color .15s}
|
|
213
|
+
.input:focus,.select:focus{outline:none;border-color:var(--accent-primary)}
|
|
214
|
+
.input::placeholder{color:var(--text-tertiary)}
|
|
215
|
+
.select{cursor:pointer;appearance:none;-webkit-appearance:none;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none' stroke='%238B8D97' stroke-width='1.5'><path d='M3 5l3 3 3-3'/></svg>");background-repeat:no-repeat;background-position:right var(--space-3) center;padding-right:var(--space-6)}
|
|
216
|
+
.gateway-form{display:flex;flex-direction:column;gap:var(--space-4);max-width:480px}
|
|
217
|
+
.gateway-help{font-size:var(--text-xs);color:var(--text-secondary);line-height:1.5;margin-bottom:var(--space-1)}
|
|
218
|
+
.form-row{display:flex;flex-direction:column}
|
|
219
|
+
.form-actions{display:flex;align-items:center;gap:var(--space-3);margin-top:var(--space-2)}
|
|
220
|
+
.gateway-status{font-size:var(--text-sm);color:var(--text-tertiary)}
|
|
221
|
+
|
|
210
222
|
@media(max-width:1024px){.kpi-grid,.grid-2{grid-template-columns:repeat(2,1fr)}.kanban-board{grid-template-columns:repeat(2,1fr)}.gauge-grid{grid-template-columns:repeat(2,1fr)}}
|
|
211
223
|
@media(max-width:768px){.kpi-grid,.grid-2{grid-template-columns:1fr}.kanban-board{grid-template-columns:1fr}.agent-grid{grid-template-columns:1fr}}
|
|
@@ -166,6 +166,7 @@
|
|
|
166
166
|
</div>
|
|
167
167
|
</div>
|
|
168
168
|
<div class="card"><div class="card-header"><span class="card-title">matrixos.jsonc</span><span id="configStatus" style="font-size:var(--text-xs);color:var(--text-tertiary)"></span></div><div class="card-body"><textarea id="configEditor" class="config-editor" spellcheck="false"></textarea></div></div>
|
|
169
|
+
<div class="card"><div class="card-header"><span class="card-title">Connecter un canal de messagerie</span><span class="badge badge-purple">Gateway</span></div><div class="card-body" id="gatewayBody"></div></div>
|
|
169
170
|
</div>
|
|
170
171
|
|
|
171
172
|
<div id="tab-schedule" class="tab-panel">
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const API={health:()=>fetchJSON('/health'),agents:()=>fetchJSON('/agents'),sessions:(l)=>fetchJSON(`/sessions?limit=${l}`),cost:()=>fetchJSON('/cost'),kanban:()=>fetchJSON('/kanban'),incidents:(l)=>fetchJSON(`/incidents?limit=${l}`),metrics:()=>fetchJSON('/metrics'),config:()=>fetchJSON('/config'),memory:()=>fetchJSON('/memory'),skills:()=>fetchJSON('/skills')}
|
|
2
|
-
async function fetchJSON(e){const r=await fetch(`/api${e}`);if(!r.ok)throw new Error(`API ${e}: ${r.status}`);return r.json()}
|
|
1
|
+
const API={health:()=>fetchJSON('/health'),agents:()=>fetchJSON('/agents'),sessions:(l)=>fetchJSON(`/sessions?limit=${l}`),cost:()=>fetchJSON('/cost'),kanban:()=>fetchJSON('/kanban'),incidents:(l)=>fetchJSON(`/incidents?limit=${l}`),metrics:()=>fetchJSON('/metrics'),config:()=>fetchJSON('/config'),memory:()=>fetchJSON('/memory'),skills:()=>fetchJSON('/skills'),gatewayToken:(type,token,passphrase)=>fetch('/api/gateway/token',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({type,token,passphrase})}).then(r=>r.json())}
|
|
2
|
+
async function fetchJSON(e){const r=await fetch(`/api${e}`);if(!r.ok)throw new Error(`API ${e}: ${r.status}`);return r.json()}
|
|
@@ -266,6 +266,66 @@ async function loadConfig(){
|
|
|
266
266
|
}catch(e){status.textContent=`Invalid JSON: ${e.message}`;status.style.color='var(--danger)'}
|
|
267
267
|
}
|
|
268
268
|
document.getElementById('configRefreshBtn').onclick=loadConfig
|
|
269
|
+
loadGateway()
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// ===== GATEWAY (Connecter un canal) =====
|
|
273
|
+
function loadGateway(){
|
|
274
|
+
const body=document.getElementById('gatewayBody')
|
|
275
|
+
if(!body)return
|
|
276
|
+
body.innerHTML=`
|
|
277
|
+
<div class="gateway-form">
|
|
278
|
+
<p class="gateway-help">Renseignez le token du bot et la passphrase pour connecter un canal de messagerie. Le token est envoyé au backend et n'est jamais stocké côté navigateur.</p>
|
|
279
|
+
<div class="form-row">
|
|
280
|
+
<label class="label" for="gwType">Type</label>
|
|
281
|
+
<select class="select" id="gwType">
|
|
282
|
+
<option value="telegram">Telegram</option>
|
|
283
|
+
<option value="discord">Discord</option>
|
|
284
|
+
</select>
|
|
285
|
+
</div>
|
|
286
|
+
<div class="form-row">
|
|
287
|
+
<label class="label" for="gwToken">Token du bot</label>
|
|
288
|
+
<input class="input" type="password" id="gwToken" autocomplete="off" placeholder="123456:ABC-DEF...">
|
|
289
|
+
</div>
|
|
290
|
+
<div class="form-row">
|
|
291
|
+
<label class="label" for="gwPass">Passphrase</label>
|
|
292
|
+
<input class="input" type="password" id="gwPass" autocomplete="off" placeholder="Passphrase configurée côté serveur">
|
|
293
|
+
</div>
|
|
294
|
+
<div class="form-actions">
|
|
295
|
+
<button class="btn btn-primary" id="gwSubmit">Enregistrer</button>
|
|
296
|
+
<span class="gateway-status" id="gwStatus"></span>
|
|
297
|
+
</div>
|
|
298
|
+
</div>`
|
|
299
|
+
const submit=document.getElementById('gwSubmit')
|
|
300
|
+
const status=document.getElementById('gwStatus')
|
|
301
|
+
submit.onclick=async()=>{
|
|
302
|
+
const type=document.getElementById('gwType').value
|
|
303
|
+
const token=document.getElementById('gwToken').value
|
|
304
|
+
const passphrase=document.getElementById('gwPass').value
|
|
305
|
+
if(!token){status.textContent='Token requis';status.style.color='var(--danger)';return}
|
|
306
|
+
if(!passphrase){status.textContent='Passphrase requise';status.style.color='var(--danger)';return}
|
|
307
|
+
submit.disabled=true
|
|
308
|
+
status.textContent='Envoi en cours...'
|
|
309
|
+
status.style.color='var(--text-tertiary)'
|
|
310
|
+
try{
|
|
311
|
+
const res=await API.gatewayToken(type,token,passphrase)
|
|
312
|
+
if(res&&res.ok){
|
|
313
|
+
status.textContent='Token enregistré ✓'
|
|
314
|
+
status.style.color='var(--success)'
|
|
315
|
+
document.getElementById('gwToken').value=''
|
|
316
|
+
document.getElementById('gwPass').value=''
|
|
317
|
+
}else{
|
|
318
|
+
const msg=(res&&res.error)||(Array.isArray(res)&&res[0]&&res[0].error)||'Erreur inconnue'
|
|
319
|
+
status.textContent='Erreur : '+msg
|
|
320
|
+
status.style.color='var(--danger)'
|
|
321
|
+
}
|
|
322
|
+
}catch(e){
|
|
323
|
+
status.textContent='Erreur : '+e.message
|
|
324
|
+
status.style.color='var(--danger)'
|
|
325
|
+
}finally{
|
|
326
|
+
submit.disabled=false
|
|
327
|
+
}
|
|
328
|
+
}
|
|
269
329
|
}
|
|
270
330
|
|
|
271
331
|
// ===== MEMORY =====
|