@openacp/cli 2026.402.5 → 2026.403.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{channel-DzDoNxa7.d.ts → channel-BL33p1ZP.d.ts} +1 -1
- package/dist/cli.js +1093 -717
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1459 -1438
- package/dist/index.js +14794 -14185
- package/dist/index.js.map +1 -1
- package/dist/testing.d.ts +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1634,21 +1634,23 @@ var init_security_guard = __esm({
|
|
|
1634
1634
|
"src/plugins/security/security-guard.ts"() {
|
|
1635
1635
|
"use strict";
|
|
1636
1636
|
SecurityGuard = class {
|
|
1637
|
-
constructor(
|
|
1638
|
-
this.
|
|
1637
|
+
constructor(getSecurityConfig, sessionManager) {
|
|
1638
|
+
this.getSecurityConfig = getSecurityConfig;
|
|
1639
1639
|
this.sessionManager = sessionManager;
|
|
1640
1640
|
}
|
|
1641
|
-
checkAccess(message) {
|
|
1642
|
-
const config = this.
|
|
1643
|
-
|
|
1641
|
+
async checkAccess(message) {
|
|
1642
|
+
const config = await this.getSecurityConfig();
|
|
1643
|
+
const allowedIds = config.allowedUserIds ?? [];
|
|
1644
|
+
const maxSessions = config.maxConcurrentSessions ?? 20;
|
|
1645
|
+
if (allowedIds.length > 0) {
|
|
1644
1646
|
const userId = String(message.userId);
|
|
1645
|
-
if (!
|
|
1647
|
+
if (!allowedIds.includes(userId)) {
|
|
1646
1648
|
return { allowed: false, reason: "Unauthorized user" };
|
|
1647
1649
|
}
|
|
1648
1650
|
}
|
|
1649
1651
|
const active = this.sessionManager.listSessions().filter((s) => s.status === "active" || s.status === "initializing");
|
|
1650
|
-
if (active.length >=
|
|
1651
|
-
return { allowed: false, reason: `Session limit reached (${
|
|
1652
|
+
if (active.length >= maxSessions) {
|
|
1653
|
+
return { allowed: false, reason: `Session limit reached (${maxSessions})` };
|
|
1652
1654
|
}
|
|
1653
1655
|
return { allowed: true };
|
|
1654
1656
|
}
|
|
@@ -1668,7 +1670,7 @@ function createSecurityPlugin() {
|
|
|
1668
1670
|
description: "User access control and session limits",
|
|
1669
1671
|
essential: false,
|
|
1670
1672
|
permissions: ["services:register", "middleware:register", "kernel:access", "commands:register"],
|
|
1671
|
-
inheritableKeys: ["
|
|
1673
|
+
inheritableKeys: ["allowedUserIds", "maxConcurrentSessions", "sessionTimeoutMinutes"],
|
|
1672
1674
|
async install(ctx) {
|
|
1673
1675
|
const { settings, legacyConfig, terminal } = ctx;
|
|
1674
1676
|
if (legacyConfig) {
|
|
@@ -1745,10 +1747,28 @@ function createSecurityPlugin() {
|
|
|
1745
1747
|
},
|
|
1746
1748
|
async setup(ctx) {
|
|
1747
1749
|
const core = ctx.core;
|
|
1748
|
-
const
|
|
1750
|
+
const settingsManager = core.lifecycleManager?.settingsManager;
|
|
1751
|
+
const pluginName = ctx.pluginName;
|
|
1752
|
+
const getSecurityConfig = async () => {
|
|
1753
|
+
if (settingsManager) {
|
|
1754
|
+
const settings = await settingsManager.loadSettings(pluginName);
|
|
1755
|
+
if (Object.keys(settings).length > 0) {
|
|
1756
|
+
return {
|
|
1757
|
+
allowedUserIds: settings.allowedUserIds ?? [],
|
|
1758
|
+
maxConcurrentSessions: settings.maxConcurrentSessions ?? 20
|
|
1759
|
+
};
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
const cfg = ctx.pluginConfig;
|
|
1763
|
+
return {
|
|
1764
|
+
allowedUserIds: cfg.allowedUserIds ?? [],
|
|
1765
|
+
maxConcurrentSessions: cfg.maxConcurrentSessions ?? 20
|
|
1766
|
+
};
|
|
1767
|
+
};
|
|
1768
|
+
const guard = new SecurityGuard(getSecurityConfig, core.sessionManager);
|
|
1749
1769
|
ctx.registerMiddleware("message:incoming", {
|
|
1750
1770
|
handler: async (payload, next) => {
|
|
1751
|
-
const access2 = guard.checkAccess(payload);
|
|
1771
|
+
const access2 = await guard.checkAccess(payload);
|
|
1752
1772
|
if (!access2.allowed) {
|
|
1753
1773
|
ctx.log.info(`Access denied: ${access2.reason}`);
|
|
1754
1774
|
return null;
|
|
@@ -3869,7 +3889,7 @@ var init_speech = __esm({
|
|
|
3869
3889
|
essential: false,
|
|
3870
3890
|
optionalPluginDependencies: { "@openacp/file-service": "^1.0.0" },
|
|
3871
3891
|
permissions: ["services:register", "commands:register", "kernel:access"],
|
|
3872
|
-
inheritableKeys: ["
|
|
3892
|
+
inheritableKeys: ["ttsProvider", "ttsVoice"],
|
|
3873
3893
|
async install(ctx) {
|
|
3874
3894
|
const { terminal, settings, legacyConfig } = ctx;
|
|
3875
3895
|
const pluginsDir = ctx.instanceRoot ? path13.join(ctx.instanceRoot, "plugins") : void 0;
|
|
@@ -6826,6 +6846,289 @@ var init_token_store = __esm({
|
|
|
6826
6846
|
}
|
|
6827
6847
|
});
|
|
6828
6848
|
|
|
6849
|
+
// src/core/instance/instance-context.ts
|
|
6850
|
+
var instance_context_exports = {};
|
|
6851
|
+
__export(instance_context_exports, {
|
|
6852
|
+
createInstanceContext: () => createInstanceContext,
|
|
6853
|
+
generateSlug: () => generateSlug,
|
|
6854
|
+
getGlobalRoot: () => getGlobalRoot,
|
|
6855
|
+
resolveInstanceRoot: () => resolveInstanceRoot
|
|
6856
|
+
});
|
|
6857
|
+
import path21 from "path";
|
|
6858
|
+
import fs17 from "fs";
|
|
6859
|
+
import os10 from "os";
|
|
6860
|
+
function createInstanceContext(opts) {
|
|
6861
|
+
const { id, root, isGlobal } = opts;
|
|
6862
|
+
return {
|
|
6863
|
+
id,
|
|
6864
|
+
root,
|
|
6865
|
+
isGlobal,
|
|
6866
|
+
paths: {
|
|
6867
|
+
config: path21.join(root, "config.json"),
|
|
6868
|
+
sessions: path21.join(root, "sessions.json"),
|
|
6869
|
+
agents: path21.join(root, "agents.json"),
|
|
6870
|
+
registryCache: path21.join(root, "registry-cache.json"),
|
|
6871
|
+
plugins: path21.join(root, "plugins"),
|
|
6872
|
+
pluginsData: path21.join(root, "plugins", "data"),
|
|
6873
|
+
pluginRegistry: path21.join(root, "plugins.json"),
|
|
6874
|
+
logs: path21.join(root, "logs"),
|
|
6875
|
+
pid: path21.join(root, "openacp.pid"),
|
|
6876
|
+
running: path21.join(root, "running"),
|
|
6877
|
+
apiPort: path21.join(root, "api.port"),
|
|
6878
|
+
apiSecret: path21.join(root, "api-secret"),
|
|
6879
|
+
bin: path21.join(root, "bin"),
|
|
6880
|
+
cache: path21.join(root, "cache"),
|
|
6881
|
+
tunnels: path21.join(root, "tunnels.json"),
|
|
6882
|
+
agentsDir: path21.join(root, "agents")
|
|
6883
|
+
}
|
|
6884
|
+
};
|
|
6885
|
+
}
|
|
6886
|
+
function generateSlug(name) {
|
|
6887
|
+
const slug = name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
6888
|
+
return slug || "openacp";
|
|
6889
|
+
}
|
|
6890
|
+
function expandHome2(p2) {
|
|
6891
|
+
if (p2.startsWith("~")) return path21.join(os10.homedir(), p2.slice(1));
|
|
6892
|
+
return p2;
|
|
6893
|
+
}
|
|
6894
|
+
function resolveInstanceRoot(opts) {
|
|
6895
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
6896
|
+
if (opts.dir) return path21.join(expandHome2(opts.dir), ".openacp");
|
|
6897
|
+
if (opts.local) return path21.join(cwd, ".openacp");
|
|
6898
|
+
if (opts.global) return path21.join(os10.homedir(), ".openacp");
|
|
6899
|
+
const localRoot = path21.join(cwd, ".openacp");
|
|
6900
|
+
if (fs17.existsSync(localRoot)) return localRoot;
|
|
6901
|
+
if (process.env.OPENACP_INSTANCE_ROOT) return process.env.OPENACP_INSTANCE_ROOT;
|
|
6902
|
+
return null;
|
|
6903
|
+
}
|
|
6904
|
+
function getGlobalRoot() {
|
|
6905
|
+
return path21.join(os10.homedir(), ".openacp");
|
|
6906
|
+
}
|
|
6907
|
+
var init_instance_context = __esm({
|
|
6908
|
+
"src/core/instance/instance-context.ts"() {
|
|
6909
|
+
"use strict";
|
|
6910
|
+
}
|
|
6911
|
+
});
|
|
6912
|
+
|
|
6913
|
+
// src/core/config/config-registry.ts
|
|
6914
|
+
var config_registry_exports = {};
|
|
6915
|
+
__export(config_registry_exports, {
|
|
6916
|
+
CONFIG_REGISTRY: () => CONFIG_REGISTRY,
|
|
6917
|
+
ConfigValidationError: () => ConfigValidationError,
|
|
6918
|
+
getConfigValue: () => getConfigValue,
|
|
6919
|
+
getFieldDef: () => getFieldDef,
|
|
6920
|
+
getFieldValueAsync: () => getFieldValueAsync,
|
|
6921
|
+
getSafeFields: () => getSafeFields,
|
|
6922
|
+
isHotReloadable: () => isHotReloadable,
|
|
6923
|
+
resolveOptions: () => resolveOptions,
|
|
6924
|
+
setFieldValueAsync: () => setFieldValueAsync
|
|
6925
|
+
});
|
|
6926
|
+
import * as fs18 from "fs";
|
|
6927
|
+
import * as path22 from "path";
|
|
6928
|
+
function getFieldDef(path68) {
|
|
6929
|
+
return CONFIG_REGISTRY.find((f) => f.path === path68);
|
|
6930
|
+
}
|
|
6931
|
+
function getSafeFields() {
|
|
6932
|
+
return CONFIG_REGISTRY.filter((f) => f.scope === "safe");
|
|
6933
|
+
}
|
|
6934
|
+
function isHotReloadable(path68) {
|
|
6935
|
+
const def = getFieldDef(path68);
|
|
6936
|
+
return def?.hotReload ?? false;
|
|
6937
|
+
}
|
|
6938
|
+
function resolveOptions(def, config) {
|
|
6939
|
+
if (!def.options) return void 0;
|
|
6940
|
+
return typeof def.options === "function" ? def.options(config) : def.options;
|
|
6941
|
+
}
|
|
6942
|
+
function getConfigValue(config, path68) {
|
|
6943
|
+
const parts = path68.split(".");
|
|
6944
|
+
let current = config;
|
|
6945
|
+
for (const part of parts) {
|
|
6946
|
+
if (current && typeof current === "object" && part in current) {
|
|
6947
|
+
current = current[part];
|
|
6948
|
+
} else {
|
|
6949
|
+
return void 0;
|
|
6950
|
+
}
|
|
6951
|
+
}
|
|
6952
|
+
return current;
|
|
6953
|
+
}
|
|
6954
|
+
async function getFieldValueAsync(field, configManager, settingsManager) {
|
|
6955
|
+
if (field.plugin && settingsManager) {
|
|
6956
|
+
const settings = await settingsManager.loadSettings(field.plugin.name);
|
|
6957
|
+
return settings[field.plugin.key];
|
|
6958
|
+
}
|
|
6959
|
+
return getConfigValue(configManager.get(), field.path);
|
|
6960
|
+
}
|
|
6961
|
+
function validateFieldValue(field, value) {
|
|
6962
|
+
switch (field.type) {
|
|
6963
|
+
case "number":
|
|
6964
|
+
if (typeof value !== "number" || Number.isNaN(value)) {
|
|
6965
|
+
throw new ConfigValidationError(`"${field.path}" expects a number, got ${typeof value}`);
|
|
6966
|
+
}
|
|
6967
|
+
break;
|
|
6968
|
+
case "toggle":
|
|
6969
|
+
if (typeof value !== "boolean") {
|
|
6970
|
+
throw new ConfigValidationError(`"${field.path}" expects a boolean, got ${typeof value}`);
|
|
6971
|
+
}
|
|
6972
|
+
break;
|
|
6973
|
+
case "string":
|
|
6974
|
+
if (typeof value !== "string") {
|
|
6975
|
+
throw new ConfigValidationError(`"${field.path}" expects a string, got ${typeof value}`);
|
|
6976
|
+
}
|
|
6977
|
+
break;
|
|
6978
|
+
case "select": {
|
|
6979
|
+
if (typeof value !== "string") {
|
|
6980
|
+
throw new ConfigValidationError(`"${field.path}" expects a string, got ${typeof value}`);
|
|
6981
|
+
}
|
|
6982
|
+
break;
|
|
6983
|
+
}
|
|
6984
|
+
}
|
|
6985
|
+
}
|
|
6986
|
+
async function setFieldValueAsync(field, value, configManager, settingsManager) {
|
|
6987
|
+
validateFieldValue(field, value);
|
|
6988
|
+
if (field.plugin && settingsManager) {
|
|
6989
|
+
await settingsManager.updatePluginSettings(field.plugin.name, {
|
|
6990
|
+
[field.plugin.key]: value
|
|
6991
|
+
});
|
|
6992
|
+
if (configManager.emit) {
|
|
6993
|
+
configManager.emit("config:changed", { path: field.path, value, oldValue: void 0 });
|
|
6994
|
+
}
|
|
6995
|
+
return { needsRestart: !field.hotReload };
|
|
6996
|
+
}
|
|
6997
|
+
await configManager.setPath(field.path, value);
|
|
6998
|
+
return { needsRestart: !field.hotReload };
|
|
6999
|
+
}
|
|
7000
|
+
var CONFIG_REGISTRY, ConfigValidationError;
|
|
7001
|
+
var init_config_registry = __esm({
|
|
7002
|
+
"src/core/config/config-registry.ts"() {
|
|
7003
|
+
"use strict";
|
|
7004
|
+
init_instance_context();
|
|
7005
|
+
CONFIG_REGISTRY = [
|
|
7006
|
+
{
|
|
7007
|
+
path: "defaultAgent",
|
|
7008
|
+
displayName: "Default Agent",
|
|
7009
|
+
group: "agent",
|
|
7010
|
+
type: "select",
|
|
7011
|
+
options: (config) => {
|
|
7012
|
+
try {
|
|
7013
|
+
const agentsPath = path22.join(getGlobalRoot(), "agents.json");
|
|
7014
|
+
if (fs18.existsSync(agentsPath)) {
|
|
7015
|
+
const data = JSON.parse(fs18.readFileSync(agentsPath, "utf-8"));
|
|
7016
|
+
return Object.keys(data.installed ?? {});
|
|
7017
|
+
}
|
|
7018
|
+
} catch {
|
|
7019
|
+
}
|
|
7020
|
+
return Object.keys(config.agents ?? {});
|
|
7021
|
+
},
|
|
7022
|
+
scope: "safe",
|
|
7023
|
+
hotReload: true
|
|
7024
|
+
},
|
|
7025
|
+
{
|
|
7026
|
+
path: "channels.telegram.outputMode",
|
|
7027
|
+
displayName: "Telegram Output Mode",
|
|
7028
|
+
group: "display",
|
|
7029
|
+
type: "select",
|
|
7030
|
+
options: ["low", "medium", "high"],
|
|
7031
|
+
scope: "safe",
|
|
7032
|
+
hotReload: true
|
|
7033
|
+
},
|
|
7034
|
+
{
|
|
7035
|
+
path: "channels.discord.outputMode",
|
|
7036
|
+
displayName: "Discord Output Mode",
|
|
7037
|
+
group: "display",
|
|
7038
|
+
type: "select",
|
|
7039
|
+
options: ["low", "medium", "high"],
|
|
7040
|
+
scope: "safe",
|
|
7041
|
+
hotReload: true
|
|
7042
|
+
},
|
|
7043
|
+
{
|
|
7044
|
+
path: "logging.level",
|
|
7045
|
+
displayName: "Log Level",
|
|
7046
|
+
group: "logging",
|
|
7047
|
+
type: "select",
|
|
7048
|
+
options: ["silent", "debug", "info", "warn", "error", "fatal"],
|
|
7049
|
+
scope: "safe",
|
|
7050
|
+
hotReload: true
|
|
7051
|
+
},
|
|
7052
|
+
{
|
|
7053
|
+
path: "tunnel.enabled",
|
|
7054
|
+
displayName: "Tunnel",
|
|
7055
|
+
group: "tunnel",
|
|
7056
|
+
type: "toggle",
|
|
7057
|
+
scope: "safe",
|
|
7058
|
+
hotReload: false,
|
|
7059
|
+
plugin: { name: "@openacp/tunnel", key: "enabled" }
|
|
7060
|
+
},
|
|
7061
|
+
{
|
|
7062
|
+
path: "security.maxConcurrentSessions",
|
|
7063
|
+
displayName: "Max Concurrent Sessions",
|
|
7064
|
+
group: "security",
|
|
7065
|
+
type: "number",
|
|
7066
|
+
scope: "safe",
|
|
7067
|
+
hotReload: true,
|
|
7068
|
+
plugin: { name: "@openacp/security", key: "maxConcurrentSessions" }
|
|
7069
|
+
},
|
|
7070
|
+
{
|
|
7071
|
+
path: "security.sessionTimeoutMinutes",
|
|
7072
|
+
displayName: "Session Timeout (min)",
|
|
7073
|
+
group: "security",
|
|
7074
|
+
type: "number",
|
|
7075
|
+
scope: "safe",
|
|
7076
|
+
hotReload: true,
|
|
7077
|
+
plugin: { name: "@openacp/security", key: "sessionTimeoutMinutes" }
|
|
7078
|
+
},
|
|
7079
|
+
{
|
|
7080
|
+
path: "workspace.baseDir",
|
|
7081
|
+
displayName: "Workspace Directory",
|
|
7082
|
+
group: "workspace",
|
|
7083
|
+
type: "string",
|
|
7084
|
+
scope: "safe",
|
|
7085
|
+
hotReload: true
|
|
7086
|
+
},
|
|
7087
|
+
{
|
|
7088
|
+
path: "sessionStore.ttlDays",
|
|
7089
|
+
displayName: "Session Store TTL (days)",
|
|
7090
|
+
group: "storage",
|
|
7091
|
+
type: "number",
|
|
7092
|
+
scope: "safe",
|
|
7093
|
+
hotReload: true
|
|
7094
|
+
},
|
|
7095
|
+
{
|
|
7096
|
+
path: "speech.stt.provider",
|
|
7097
|
+
displayName: "Speech to Text",
|
|
7098
|
+
group: "speech",
|
|
7099
|
+
type: "select",
|
|
7100
|
+
options: ["groq"],
|
|
7101
|
+
scope: "safe",
|
|
7102
|
+
hotReload: true,
|
|
7103
|
+
plugin: { name: "@openacp/speech", key: "sttProvider" }
|
|
7104
|
+
},
|
|
7105
|
+
{
|
|
7106
|
+
path: "speech.stt.apiKey",
|
|
7107
|
+
displayName: "STT API Key",
|
|
7108
|
+
group: "speech",
|
|
7109
|
+
type: "string",
|
|
7110
|
+
scope: "sensitive",
|
|
7111
|
+
hotReload: true,
|
|
7112
|
+
plugin: { name: "@openacp/speech", key: "groqApiKey" }
|
|
7113
|
+
},
|
|
7114
|
+
{
|
|
7115
|
+
path: "agentSwitch.labelHistory",
|
|
7116
|
+
displayName: "Label Agent in History",
|
|
7117
|
+
group: "agent",
|
|
7118
|
+
type: "toggle",
|
|
7119
|
+
scope: "safe",
|
|
7120
|
+
hotReload: true
|
|
7121
|
+
}
|
|
7122
|
+
];
|
|
7123
|
+
ConfigValidationError = class extends Error {
|
|
7124
|
+
constructor(message) {
|
|
7125
|
+
super(message);
|
|
7126
|
+
this.name = "ConfigValidationError";
|
|
7127
|
+
}
|
|
7128
|
+
};
|
|
7129
|
+
}
|
|
7130
|
+
});
|
|
7131
|
+
|
|
6829
7132
|
// src/plugins/api-server/middleware/error-handler.ts
|
|
6830
7133
|
var error_handler_exports = {};
|
|
6831
7134
|
__export(error_handler_exports, {
|
|
@@ -6848,6 +7151,16 @@ function globalErrorHandler(error, _request, reply) {
|
|
|
6848
7151
|
});
|
|
6849
7152
|
return;
|
|
6850
7153
|
}
|
|
7154
|
+
if (error instanceof ConfigValidationError) {
|
|
7155
|
+
reply.status(400).send({
|
|
7156
|
+
error: {
|
|
7157
|
+
code: "VALIDATION_ERROR",
|
|
7158
|
+
message: error.message,
|
|
7159
|
+
statusCode: 400
|
|
7160
|
+
}
|
|
7161
|
+
});
|
|
7162
|
+
return;
|
|
7163
|
+
}
|
|
6851
7164
|
if (error instanceof BadRequestError) {
|
|
6852
7165
|
reply.status(400).send({
|
|
6853
7166
|
error: {
|
|
@@ -6900,6 +7213,7 @@ var NotFoundError, BadRequestError, ServiceUnavailableError, AuthError;
|
|
|
6900
7213
|
var init_error_handler = __esm({
|
|
6901
7214
|
"src/plugins/api-server/middleware/error-handler.ts"() {
|
|
6902
7215
|
"use strict";
|
|
7216
|
+
init_config_registry();
|
|
6903
7217
|
NotFoundError = class extends Error {
|
|
6904
7218
|
constructor(code, message) {
|
|
6905
7219
|
super(message);
|
|
@@ -7204,7 +7518,7 @@ var init_sse_manager = __esm({
|
|
|
7204
7518
|
handleRequest(req, res) {
|
|
7205
7519
|
const parsedUrl = new URL(req.url || "", "http://localhost");
|
|
7206
7520
|
const sessionFilter = parsedUrl.searchParams.get("sessionId");
|
|
7207
|
-
console.log(`[sse]
|
|
7521
|
+
console.log(`[sse] +connection total=${this.sseConnections.size + 1}`);
|
|
7208
7522
|
const origin = req.headers.origin;
|
|
7209
7523
|
const corsHeaders = {
|
|
7210
7524
|
"Content-Type": "text/event-stream",
|
|
@@ -7226,7 +7540,7 @@ var init_sse_manager = __esm({
|
|
|
7226
7540
|
const cleanup = () => {
|
|
7227
7541
|
this.sseConnections.delete(res);
|
|
7228
7542
|
this.sseCleanupHandlers.delete(res);
|
|
7229
|
-
console.log(`[sse] connection
|
|
7543
|
+
console.log(`[sse] -connection remaining=${this.sseConnections.size}`);
|
|
7230
7544
|
};
|
|
7231
7545
|
this.sseCleanupHandlers.set(res, cleanup);
|
|
7232
7546
|
req.on("close", cleanup);
|
|
@@ -7286,8 +7600,8 @@ var static_server_exports = {};
|
|
|
7286
7600
|
__export(static_server_exports, {
|
|
7287
7601
|
StaticServer: () => StaticServer
|
|
7288
7602
|
});
|
|
7289
|
-
import * as
|
|
7290
|
-
import * as
|
|
7603
|
+
import * as fs19 from "fs";
|
|
7604
|
+
import * as path23 from "path";
|
|
7291
7605
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
7292
7606
|
var MIME_TYPES, StaticServer;
|
|
7293
7607
|
var init_static_server = __esm({
|
|
@@ -7311,16 +7625,16 @@ var init_static_server = __esm({
|
|
|
7311
7625
|
this.uiDir = uiDir;
|
|
7312
7626
|
if (!this.uiDir) {
|
|
7313
7627
|
const __filename = fileURLToPath2(import.meta.url);
|
|
7314
|
-
const candidate =
|
|
7315
|
-
if (
|
|
7628
|
+
const candidate = path23.resolve(path23.dirname(__filename), "../../ui/dist");
|
|
7629
|
+
if (fs19.existsSync(path23.join(candidate, "index.html"))) {
|
|
7316
7630
|
this.uiDir = candidate;
|
|
7317
7631
|
}
|
|
7318
7632
|
if (!this.uiDir) {
|
|
7319
|
-
const publishCandidate =
|
|
7320
|
-
|
|
7633
|
+
const publishCandidate = path23.resolve(
|
|
7634
|
+
path23.dirname(__filename),
|
|
7321
7635
|
"../ui"
|
|
7322
7636
|
);
|
|
7323
|
-
if (
|
|
7637
|
+
if (fs19.existsSync(path23.join(publishCandidate, "index.html"))) {
|
|
7324
7638
|
this.uiDir = publishCandidate;
|
|
7325
7639
|
}
|
|
7326
7640
|
}
|
|
@@ -7332,12 +7646,12 @@ var init_static_server = __esm({
|
|
|
7332
7646
|
serve(req, res) {
|
|
7333
7647
|
if (!this.uiDir) return false;
|
|
7334
7648
|
const urlPath = (req.url || "/").split("?")[0];
|
|
7335
|
-
const safePath =
|
|
7336
|
-
const filePath =
|
|
7337
|
-
if (!filePath.startsWith(this.uiDir +
|
|
7649
|
+
const safePath = path23.normalize(urlPath);
|
|
7650
|
+
const filePath = path23.join(this.uiDir, safePath);
|
|
7651
|
+
if (!filePath.startsWith(this.uiDir + path23.sep) && filePath !== this.uiDir)
|
|
7338
7652
|
return false;
|
|
7339
|
-
if (
|
|
7340
|
-
const ext =
|
|
7653
|
+
if (fs19.existsSync(filePath) && fs19.statSync(filePath).isFile()) {
|
|
7654
|
+
const ext = path23.extname(filePath);
|
|
7341
7655
|
const contentType = MIME_TYPES[ext] ?? "application/octet-stream";
|
|
7342
7656
|
const isHashed = /\.[a-zA-Z0-9]{8,}\.(js|css)$/.test(filePath);
|
|
7343
7657
|
const cacheControl = isHashed ? "public, max-age=31536000, immutable" : "no-cache";
|
|
@@ -7345,16 +7659,16 @@ var init_static_server = __esm({
|
|
|
7345
7659
|
"Content-Type": contentType,
|
|
7346
7660
|
"Cache-Control": cacheControl
|
|
7347
7661
|
});
|
|
7348
|
-
|
|
7662
|
+
fs19.createReadStream(filePath).pipe(res);
|
|
7349
7663
|
return true;
|
|
7350
7664
|
}
|
|
7351
|
-
const indexPath =
|
|
7352
|
-
if (
|
|
7665
|
+
const indexPath = path23.join(this.uiDir, "index.html");
|
|
7666
|
+
if (fs19.existsSync(indexPath)) {
|
|
7353
7667
|
res.writeHead(200, {
|
|
7354
7668
|
"Content-Type": "text/html; charset=utf-8",
|
|
7355
7669
|
"Cache-Control": "no-cache"
|
|
7356
7670
|
});
|
|
7357
|
-
|
|
7671
|
+
fs19.createReadStream(indexPath).pipe(res);
|
|
7358
7672
|
return true;
|
|
7359
7673
|
}
|
|
7360
7674
|
return false;
|
|
@@ -7841,291 +8155,68 @@ var init_common = __esm({
|
|
|
7841
8155
|
})
|
|
7842
8156
|
});
|
|
7843
8157
|
}
|
|
7844
|
-
});
|
|
7845
|
-
|
|
7846
|
-
// src/core/agents/agent-registry.ts
|
|
7847
|
-
var agent_registry_exports = {};
|
|
7848
|
-
__export(agent_registry_exports, {
|
|
7849
|
-
getAgentCapabilities: () => getAgentCapabilities
|
|
7850
|
-
});
|
|
7851
|
-
var init_agent_registry = __esm({
|
|
7852
|
-
"src/core/agents/agent-registry.ts"() {
|
|
7853
|
-
"use strict";
|
|
7854
|
-
init_agent_dependencies();
|
|
7855
|
-
}
|
|
7856
|
-
});
|
|
7857
|
-
|
|
7858
|
-
// src/plugins/api-server/routes/agents.ts
|
|
7859
|
-
var agents_exports = {};
|
|
7860
|
-
__export(agents_exports, {
|
|
7861
|
-
agentRoutes: () => agentRoutes
|
|
7862
|
-
});
|
|
7863
|
-
async function agentRoutes(app, deps) {
|
|
7864
|
-
app.get("/", { preHandler: requireScopes("agents:read") }, async () => {
|
|
7865
|
-
const agents = deps.core.agentManager.getAvailableAgents();
|
|
7866
|
-
const defaultAgent = deps.core.configManager.get().defaultAgent;
|
|
7867
|
-
const agentsWithCaps = agents.map((a) => ({
|
|
7868
|
-
...a,
|
|
7869
|
-
capabilities: getAgentCapabilities(a.name)
|
|
7870
|
-
}));
|
|
7871
|
-
return { agents: agentsWithCaps, default: defaultAgent };
|
|
7872
|
-
});
|
|
7873
|
-
app.get("/:name", { preHandler: requireScopes("agents:read") }, async (request) => {
|
|
7874
|
-
const { name } = NameParamSchema.parse(request.params);
|
|
7875
|
-
const agent = deps.core.agentCatalog.getInstalledAgent(name);
|
|
7876
|
-
if (!agent) {
|
|
7877
|
-
throw new NotFoundError("AGENT_NOT_FOUND", `Agent "${name}" not found`);
|
|
7878
|
-
}
|
|
7879
|
-
return {
|
|
7880
|
-
...agent,
|
|
7881
|
-
key: name,
|
|
7882
|
-
capabilities: getAgentCapabilities(name)
|
|
7883
|
-
};
|
|
7884
|
-
});
|
|
7885
|
-
}
|
|
7886
|
-
var init_agents = __esm({
|
|
7887
|
-
"src/plugins/api-server/routes/agents.ts"() {
|
|
7888
|
-
"use strict";
|
|
7889
|
-
init_common();
|
|
7890
|
-
init_error_handler();
|
|
7891
|
-
init_auth();
|
|
7892
|
-
init_agent_registry();
|
|
7893
|
-
}
|
|
7894
|
-
});
|
|
7895
|
-
|
|
7896
|
-
// src/plugins/api-server/schemas/config.ts
|
|
7897
|
-
import { z as z3 } from "zod";
|
|
7898
|
-
var UpdateConfigBodySchema;
|
|
7899
|
-
var init_config = __esm({
|
|
7900
|
-
"src/plugins/api-server/schemas/config.ts"() {
|
|
7901
|
-
"use strict";
|
|
7902
|
-
UpdateConfigBodySchema = z3.object({
|
|
7903
|
-
path: z3.string().min(1),
|
|
7904
|
-
value: z3.unknown()
|
|
7905
|
-
});
|
|
7906
|
-
}
|
|
7907
|
-
});
|
|
7908
|
-
|
|
7909
|
-
// src/core/instance/instance-context.ts
|
|
7910
|
-
var instance_context_exports = {};
|
|
7911
|
-
__export(instance_context_exports, {
|
|
7912
|
-
createInstanceContext: () => createInstanceContext,
|
|
7913
|
-
generateSlug: () => generateSlug,
|
|
7914
|
-
getGlobalRoot: () => getGlobalRoot,
|
|
7915
|
-
resolveInstanceRoot: () => resolveInstanceRoot
|
|
7916
|
-
});
|
|
7917
|
-
import path22 from "path";
|
|
7918
|
-
import fs18 from "fs";
|
|
7919
|
-
import os10 from "os";
|
|
7920
|
-
function createInstanceContext(opts) {
|
|
7921
|
-
const { id, root, isGlobal } = opts;
|
|
7922
|
-
return {
|
|
7923
|
-
id,
|
|
7924
|
-
root,
|
|
7925
|
-
isGlobal,
|
|
7926
|
-
paths: {
|
|
7927
|
-
config: path22.join(root, "config.json"),
|
|
7928
|
-
sessions: path22.join(root, "sessions.json"),
|
|
7929
|
-
agents: path22.join(root, "agents.json"),
|
|
7930
|
-
registryCache: path22.join(root, "registry-cache.json"),
|
|
7931
|
-
plugins: path22.join(root, "plugins"),
|
|
7932
|
-
pluginsData: path22.join(root, "plugins", "data"),
|
|
7933
|
-
pluginRegistry: path22.join(root, "plugins.json"),
|
|
7934
|
-
logs: path22.join(root, "logs"),
|
|
7935
|
-
pid: path22.join(root, "openacp.pid"),
|
|
7936
|
-
running: path22.join(root, "running"),
|
|
7937
|
-
apiPort: path22.join(root, "api.port"),
|
|
7938
|
-
apiSecret: path22.join(root, "api-secret"),
|
|
7939
|
-
bin: path22.join(root, "bin"),
|
|
7940
|
-
cache: path22.join(root, "cache"),
|
|
7941
|
-
tunnels: path22.join(root, "tunnels.json"),
|
|
7942
|
-
agentsDir: path22.join(root, "agents")
|
|
7943
|
-
}
|
|
7944
|
-
};
|
|
7945
|
-
}
|
|
7946
|
-
function generateSlug(name) {
|
|
7947
|
-
const slug = name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
7948
|
-
return slug || "openacp";
|
|
7949
|
-
}
|
|
7950
|
-
function expandHome2(p2) {
|
|
7951
|
-
if (p2.startsWith("~")) return path22.join(os10.homedir(), p2.slice(1));
|
|
7952
|
-
return p2;
|
|
7953
|
-
}
|
|
7954
|
-
function resolveInstanceRoot(opts) {
|
|
7955
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
7956
|
-
if (opts.dir) return path22.join(expandHome2(opts.dir), ".openacp");
|
|
7957
|
-
if (opts.local) return path22.join(cwd, ".openacp");
|
|
7958
|
-
if (opts.global) return path22.join(os10.homedir(), ".openacp");
|
|
7959
|
-
const localRoot = path22.join(cwd, ".openacp");
|
|
7960
|
-
if (fs18.existsSync(localRoot)) return localRoot;
|
|
7961
|
-
if (process.env.OPENACP_INSTANCE_ROOT) return process.env.OPENACP_INSTANCE_ROOT;
|
|
7962
|
-
return null;
|
|
7963
|
-
}
|
|
7964
|
-
function getGlobalRoot() {
|
|
7965
|
-
return path22.join(os10.homedir(), ".openacp");
|
|
7966
|
-
}
|
|
7967
|
-
var init_instance_context = __esm({
|
|
7968
|
-
"src/core/instance/instance-context.ts"() {
|
|
7969
|
-
"use strict";
|
|
7970
|
-
}
|
|
7971
|
-
});
|
|
7972
|
-
|
|
7973
|
-
// src/core/config/config-registry.ts
|
|
7974
|
-
var config_registry_exports = {};
|
|
7975
|
-
__export(config_registry_exports, {
|
|
7976
|
-
CONFIG_REGISTRY: () => CONFIG_REGISTRY,
|
|
7977
|
-
getConfigValue: () => getConfigValue,
|
|
7978
|
-
getFieldDef: () => getFieldDef,
|
|
7979
|
-
getSafeFields: () => getSafeFields,
|
|
7980
|
-
isHotReloadable: () => isHotReloadable,
|
|
7981
|
-
resolveOptions: () => resolveOptions
|
|
7982
|
-
});
|
|
7983
|
-
import * as fs19 from "fs";
|
|
7984
|
-
import * as path23 from "path";
|
|
7985
|
-
function getFieldDef(path67) {
|
|
7986
|
-
return CONFIG_REGISTRY.find((f) => f.path === path67);
|
|
7987
|
-
}
|
|
7988
|
-
function getSafeFields() {
|
|
7989
|
-
return CONFIG_REGISTRY.filter((f) => f.scope === "safe");
|
|
7990
|
-
}
|
|
7991
|
-
function isHotReloadable(path67) {
|
|
7992
|
-
const def = getFieldDef(path67);
|
|
7993
|
-
return def?.hotReload ?? false;
|
|
7994
|
-
}
|
|
7995
|
-
function resolveOptions(def, config) {
|
|
7996
|
-
if (!def.options) return void 0;
|
|
7997
|
-
return typeof def.options === "function" ? def.options(config) : def.options;
|
|
7998
|
-
}
|
|
7999
|
-
function getConfigValue(config, path67) {
|
|
8000
|
-
const parts = path67.split(".");
|
|
8001
|
-
let current = config;
|
|
8002
|
-
for (const part of parts) {
|
|
8003
|
-
if (current && typeof current === "object" && part in current) {
|
|
8004
|
-
current = current[part];
|
|
8005
|
-
} else {
|
|
8006
|
-
return void 0;
|
|
8007
|
-
}
|
|
8008
|
-
}
|
|
8009
|
-
return current;
|
|
8010
|
-
}
|
|
8011
|
-
var CONFIG_REGISTRY;
|
|
8012
|
-
var init_config_registry = __esm({
|
|
8013
|
-
"src/core/config/config-registry.ts"() {
|
|
8014
|
-
"use strict";
|
|
8015
|
-
init_instance_context();
|
|
8016
|
-
CONFIG_REGISTRY = [
|
|
8017
|
-
{
|
|
8018
|
-
path: "defaultAgent",
|
|
8019
|
-
displayName: "Default Agent",
|
|
8020
|
-
group: "agent",
|
|
8021
|
-
type: "select",
|
|
8022
|
-
options: (config) => {
|
|
8023
|
-
try {
|
|
8024
|
-
const agentsPath = path23.join(getGlobalRoot(), "agents.json");
|
|
8025
|
-
if (fs19.existsSync(agentsPath)) {
|
|
8026
|
-
const data = JSON.parse(fs19.readFileSync(agentsPath, "utf-8"));
|
|
8027
|
-
return Object.keys(data.installed ?? {});
|
|
8028
|
-
}
|
|
8029
|
-
} catch {
|
|
8030
|
-
}
|
|
8031
|
-
return Object.keys(config.agents ?? {});
|
|
8032
|
-
},
|
|
8033
|
-
scope: "safe",
|
|
8034
|
-
hotReload: true
|
|
8035
|
-
},
|
|
8036
|
-
{
|
|
8037
|
-
path: "channels.telegram.outputMode",
|
|
8038
|
-
displayName: "Telegram Output Mode",
|
|
8039
|
-
group: "display",
|
|
8040
|
-
type: "select",
|
|
8041
|
-
options: ["low", "medium", "high"],
|
|
8042
|
-
scope: "safe",
|
|
8043
|
-
hotReload: true
|
|
8044
|
-
},
|
|
8045
|
-
{
|
|
8046
|
-
path: "channels.discord.outputMode",
|
|
8047
|
-
displayName: "Discord Output Mode",
|
|
8048
|
-
group: "display",
|
|
8049
|
-
type: "select",
|
|
8050
|
-
options: ["low", "medium", "high"],
|
|
8051
|
-
scope: "safe",
|
|
8052
|
-
hotReload: true
|
|
8053
|
-
},
|
|
8054
|
-
{
|
|
8055
|
-
path: "logging.level",
|
|
8056
|
-
displayName: "Log Level",
|
|
8057
|
-
group: "logging",
|
|
8058
|
-
type: "select",
|
|
8059
|
-
options: ["silent", "debug", "info", "warn", "error", "fatal"],
|
|
8060
|
-
scope: "safe",
|
|
8061
|
-
hotReload: true
|
|
8062
|
-
},
|
|
8063
|
-
{
|
|
8064
|
-
path: "tunnel.enabled",
|
|
8065
|
-
displayName: "Tunnel",
|
|
8066
|
-
group: "tunnel",
|
|
8067
|
-
type: "toggle",
|
|
8068
|
-
scope: "safe",
|
|
8069
|
-
hotReload: false
|
|
8070
|
-
},
|
|
8071
|
-
{
|
|
8072
|
-
path: "security.maxConcurrentSessions",
|
|
8073
|
-
displayName: "Max Concurrent Sessions",
|
|
8074
|
-
group: "security",
|
|
8075
|
-
type: "number",
|
|
8076
|
-
scope: "safe",
|
|
8077
|
-
hotReload: true
|
|
8078
|
-
},
|
|
8079
|
-
{
|
|
8080
|
-
path: "security.sessionTimeoutMinutes",
|
|
8081
|
-
displayName: "Session Timeout (min)",
|
|
8082
|
-
group: "security",
|
|
8083
|
-
type: "number",
|
|
8084
|
-
scope: "safe",
|
|
8085
|
-
hotReload: true
|
|
8086
|
-
},
|
|
8087
|
-
{
|
|
8088
|
-
path: "workspace.baseDir",
|
|
8089
|
-
displayName: "Workspace Directory",
|
|
8090
|
-
group: "workspace",
|
|
8091
|
-
type: "string",
|
|
8092
|
-
scope: "safe",
|
|
8093
|
-
hotReload: true
|
|
8094
|
-
},
|
|
8095
|
-
{
|
|
8096
|
-
path: "sessionStore.ttlDays",
|
|
8097
|
-
displayName: "Session Store TTL (days)",
|
|
8098
|
-
group: "storage",
|
|
8099
|
-
type: "number",
|
|
8100
|
-
scope: "safe",
|
|
8101
|
-
hotReload: true
|
|
8102
|
-
},
|
|
8103
|
-
{
|
|
8104
|
-
path: "speech.stt.provider",
|
|
8105
|
-
displayName: "Speech to Text",
|
|
8106
|
-
group: "speech",
|
|
8107
|
-
type: "select",
|
|
8108
|
-
options: ["groq"],
|
|
8109
|
-
scope: "safe",
|
|
8110
|
-
hotReload: true
|
|
8111
|
-
},
|
|
8112
|
-
{
|
|
8113
|
-
path: "speech.stt.apiKey",
|
|
8114
|
-
displayName: "STT API Key",
|
|
8115
|
-
group: "speech",
|
|
8116
|
-
type: "string",
|
|
8117
|
-
scope: "sensitive",
|
|
8118
|
-
hotReload: true
|
|
8119
|
-
},
|
|
8120
|
-
{
|
|
8121
|
-
path: "agentSwitch.labelHistory",
|
|
8122
|
-
displayName: "Label Agent in History",
|
|
8123
|
-
group: "agent",
|
|
8124
|
-
type: "toggle",
|
|
8125
|
-
scope: "safe",
|
|
8126
|
-
hotReload: true
|
|
8127
|
-
}
|
|
8128
|
-
];
|
|
8158
|
+
});
|
|
8159
|
+
|
|
8160
|
+
// src/core/agents/agent-registry.ts
|
|
8161
|
+
var agent_registry_exports = {};
|
|
8162
|
+
__export(agent_registry_exports, {
|
|
8163
|
+
getAgentCapabilities: () => getAgentCapabilities
|
|
8164
|
+
});
|
|
8165
|
+
var init_agent_registry = __esm({
|
|
8166
|
+
"src/core/agents/agent-registry.ts"() {
|
|
8167
|
+
"use strict";
|
|
8168
|
+
init_agent_dependencies();
|
|
8169
|
+
}
|
|
8170
|
+
});
|
|
8171
|
+
|
|
8172
|
+
// src/plugins/api-server/routes/agents.ts
|
|
8173
|
+
var agents_exports = {};
|
|
8174
|
+
__export(agents_exports, {
|
|
8175
|
+
agentRoutes: () => agentRoutes
|
|
8176
|
+
});
|
|
8177
|
+
async function agentRoutes(app, deps) {
|
|
8178
|
+
app.get("/", { preHandler: requireScopes("agents:read") }, async () => {
|
|
8179
|
+
const agents = deps.core.agentManager.getAvailableAgents();
|
|
8180
|
+
const defaultAgent = deps.core.configManager.get().defaultAgent;
|
|
8181
|
+
const agentsWithCaps = agents.map((a) => ({
|
|
8182
|
+
...a,
|
|
8183
|
+
capabilities: getAgentCapabilities(a.name)
|
|
8184
|
+
}));
|
|
8185
|
+
return { agents: agentsWithCaps, default: defaultAgent };
|
|
8186
|
+
});
|
|
8187
|
+
app.get("/:name", { preHandler: requireScopes("agents:read") }, async (request) => {
|
|
8188
|
+
const { name } = NameParamSchema.parse(request.params);
|
|
8189
|
+
const agent = deps.core.agentCatalog.getInstalledAgent(name);
|
|
8190
|
+
if (!agent) {
|
|
8191
|
+
throw new NotFoundError("AGENT_NOT_FOUND", `Agent "${name}" not found`);
|
|
8192
|
+
}
|
|
8193
|
+
return {
|
|
8194
|
+
...agent,
|
|
8195
|
+
key: name,
|
|
8196
|
+
capabilities: getAgentCapabilities(name)
|
|
8197
|
+
};
|
|
8198
|
+
});
|
|
8199
|
+
}
|
|
8200
|
+
var init_agents = __esm({
|
|
8201
|
+
"src/plugins/api-server/routes/agents.ts"() {
|
|
8202
|
+
"use strict";
|
|
8203
|
+
init_common();
|
|
8204
|
+
init_error_handler();
|
|
8205
|
+
init_auth();
|
|
8206
|
+
init_agent_registry();
|
|
8207
|
+
}
|
|
8208
|
+
});
|
|
8209
|
+
|
|
8210
|
+
// src/plugins/api-server/schemas/config.ts
|
|
8211
|
+
import { z as z3 } from "zod";
|
|
8212
|
+
var UpdateConfigBodySchema;
|
|
8213
|
+
var init_config = __esm({
|
|
8214
|
+
"src/plugins/api-server/schemas/config.ts"() {
|
|
8215
|
+
"use strict";
|
|
8216
|
+
UpdateConfigBodySchema = z3.object({
|
|
8217
|
+
path: z3.string().min(1),
|
|
8218
|
+
value: z3.unknown()
|
|
8219
|
+
});
|
|
8129
8220
|
}
|
|
8130
8221
|
});
|
|
8131
8222
|
|
|
@@ -8533,6 +8624,26 @@ var init_config2 = __esm({
|
|
|
8533
8624
|
fs21.mkdirSync(dir, { recursive: true });
|
|
8534
8625
|
fs21.writeFileSync(this.configPath, JSON.stringify(config, null, 2));
|
|
8535
8626
|
}
|
|
8627
|
+
async applyEnvToPluginSettings(settingsManager) {
|
|
8628
|
+
const pluginOverrides = [
|
|
8629
|
+
{ envVar: "OPENACP_TUNNEL_ENABLED", pluginName: "@openacp/tunnel", key: "enabled", transform: (v) => v === "true" },
|
|
8630
|
+
{ envVar: "OPENACP_TUNNEL_PORT", pluginName: "@openacp/tunnel", key: "port", transform: (v) => Number(v) },
|
|
8631
|
+
{ envVar: "OPENACP_TUNNEL_PROVIDER", pluginName: "@openacp/tunnel", key: "provider" },
|
|
8632
|
+
{ envVar: "OPENACP_API_PORT", pluginName: "@openacp/api-server", key: "port", transform: (v) => Number(v) },
|
|
8633
|
+
{ envVar: "OPENACP_SPEECH_STT_PROVIDER", pluginName: "@openacp/speech", key: "sttProvider" },
|
|
8634
|
+
{ envVar: "OPENACP_SPEECH_GROQ_API_KEY", pluginName: "@openacp/speech", key: "groqApiKey" },
|
|
8635
|
+
{ envVar: "OPENACP_TELEGRAM_BOT_TOKEN", pluginName: "@openacp/telegram", key: "botToken" },
|
|
8636
|
+
{ envVar: "OPENACP_TELEGRAM_CHAT_ID", pluginName: "@openacp/telegram", key: "chatId", transform: (v) => Number(v) }
|
|
8637
|
+
];
|
|
8638
|
+
for (const { envVar, pluginName, key, transform } of pluginOverrides) {
|
|
8639
|
+
const value = process.env[envVar];
|
|
8640
|
+
if (value !== void 0) {
|
|
8641
|
+
const resolved = transform ? transform(value) : value;
|
|
8642
|
+
await settingsManager.updatePluginSettings(pluginName, { [key]: resolved });
|
|
8643
|
+
log12.debug({ envVar, pluginName, key }, "Env var override applied to plugin settings");
|
|
8644
|
+
}
|
|
8645
|
+
}
|
|
8646
|
+
}
|
|
8536
8647
|
applyEnvOverrides(raw) {
|
|
8537
8648
|
const overrides = [
|
|
8538
8649
|
["OPENACP_TELEGRAM_BOT_TOKEN", ["channels", "telegram", "botToken"]],
|
|
@@ -8645,18 +8756,19 @@ function redactDeep(obj) {
|
|
|
8645
8756
|
}
|
|
8646
8757
|
async function configRoutes(app, deps) {
|
|
8647
8758
|
app.get("/editable", { preHandler: requireScopes("config:read") }, async () => {
|
|
8648
|
-
const { getSafeFields: getSafeFields2, resolveOptions: resolveOptions2,
|
|
8759
|
+
const { getSafeFields: getSafeFields2, resolveOptions: resolveOptions2, getFieldValueAsync: getFieldValueAsync2 } = await Promise.resolve().then(() => (init_config_registry(), config_registry_exports));
|
|
8649
8760
|
const config = deps.core.configManager.get();
|
|
8761
|
+
const settingsManager = deps.core.settingsManager;
|
|
8650
8762
|
const safeFields = getSafeFields2();
|
|
8651
|
-
const fields = safeFields.map((def) => ({
|
|
8763
|
+
const fields = await Promise.all(safeFields.map(async (def) => ({
|
|
8652
8764
|
path: def.path,
|
|
8653
8765
|
displayName: def.displayName,
|
|
8654
8766
|
group: def.group,
|
|
8655
8767
|
type: def.type,
|
|
8656
8768
|
options: resolveOptions2(def, config),
|
|
8657
|
-
value:
|
|
8769
|
+
value: await getFieldValueAsync2(def, deps.core.configManager, settingsManager),
|
|
8658
8770
|
hotReload: def.hotReload
|
|
8659
|
-
}));
|
|
8771
|
+
})));
|
|
8660
8772
|
return { fields };
|
|
8661
8773
|
});
|
|
8662
8774
|
app.get("/schema", { preHandler: requireScopes("config:read") }, async () => {
|
|
@@ -8676,16 +8788,20 @@ async function configRoutes(app, deps) {
|
|
|
8676
8788
|
if (configPath.split(".").some((p2) => BLOCKED_KEYS.has(p2))) {
|
|
8677
8789
|
return reply.status(400).send({ error: "Invalid config path" });
|
|
8678
8790
|
}
|
|
8679
|
-
const { getFieldDef: getFieldDef2 } = await Promise.resolve().then(() => (init_config_registry(), config_registry_exports));
|
|
8791
|
+
const { getFieldDef: getFieldDef2, setFieldValueAsync: setFieldValueAsync2 } = await Promise.resolve().then(() => (init_config_registry(), config_registry_exports));
|
|
8680
8792
|
const fieldDef = getFieldDef2(configPath);
|
|
8681
8793
|
if (!fieldDef || fieldDef.scope !== "safe") {
|
|
8682
8794
|
return reply.status(403).send({
|
|
8683
8795
|
error: "This config field cannot be modified via the API"
|
|
8684
8796
|
});
|
|
8685
8797
|
}
|
|
8686
|
-
|
|
8687
|
-
const {
|
|
8688
|
-
|
|
8798
|
+
const settingsManager = deps.core.settingsManager;
|
|
8799
|
+
const { needsRestart } = await setFieldValueAsync2(
|
|
8800
|
+
fieldDef,
|
|
8801
|
+
value,
|
|
8802
|
+
deps.core.configManager,
|
|
8803
|
+
settingsManager
|
|
8804
|
+
);
|
|
8689
8805
|
return {
|
|
8690
8806
|
ok: true,
|
|
8691
8807
|
needsRestart,
|
|
@@ -9196,13 +9312,152 @@ var init_workspace = __esm({
|
|
|
9196
9312
|
}
|
|
9197
9313
|
});
|
|
9198
9314
|
|
|
9315
|
+
// src/plugins/api-server/routes/plugins.ts
|
|
9316
|
+
var plugins_exports = {};
|
|
9317
|
+
__export(plugins_exports, {
|
|
9318
|
+
pluginRoutes: () => pluginRoutes
|
|
9319
|
+
});
|
|
9320
|
+
import path26 from "path";
|
|
9321
|
+
import os12 from "os";
|
|
9322
|
+
async function pluginRoutes(app, deps) {
|
|
9323
|
+
const { lifecycleManager } = deps;
|
|
9324
|
+
const admin = [requireScopes("system:admin")];
|
|
9325
|
+
app.get("/", { preHandler: admin }, async () => {
|
|
9326
|
+
if (!lifecycleManager?.registry) return { plugins: [] };
|
|
9327
|
+
const registry = lifecycleManager.registry;
|
|
9328
|
+
const loadedSet = new Set(lifecycleManager.loadedPlugins);
|
|
9329
|
+
const failedSet = new Set(lifecycleManager.failedPlugins);
|
|
9330
|
+
const loadOrderMap = new Map(lifecycleManager.plugins.map((p2) => [p2.name, p2]));
|
|
9331
|
+
const coreMap = new Map(corePlugins.map((p2) => [p2.name, p2]));
|
|
9332
|
+
const plugins = Array.from(registry.list().entries()).map(([name, entry]) => {
|
|
9333
|
+
const def = loadOrderMap.get(name) ?? coreMap.get(name);
|
|
9334
|
+
return {
|
|
9335
|
+
name,
|
|
9336
|
+
version: entry.version,
|
|
9337
|
+
description: entry.description,
|
|
9338
|
+
source: entry.source,
|
|
9339
|
+
enabled: entry.enabled,
|
|
9340
|
+
loaded: loadedSet.has(name),
|
|
9341
|
+
failed: failedSet.has(name),
|
|
9342
|
+
essential: def?.essential ?? false,
|
|
9343
|
+
hasConfigure: typeof def?.configure === "function"
|
|
9344
|
+
};
|
|
9345
|
+
});
|
|
9346
|
+
return { plugins };
|
|
9347
|
+
});
|
|
9348
|
+
app.get("/marketplace", { preHandler: admin }, async (_req, reply) => {
|
|
9349
|
+
try {
|
|
9350
|
+
const data = await registryClient.getRegistry();
|
|
9351
|
+
const installedNames = new Set(
|
|
9352
|
+
lifecycleManager?.registry ? Array.from(lifecycleManager.registry.list().keys()) : []
|
|
9353
|
+
);
|
|
9354
|
+
const plugins = data.plugins.map((p2) => ({
|
|
9355
|
+
...p2,
|
|
9356
|
+
installed: installedNames.has(p2.name) || installedNames.has(p2.npm)
|
|
9357
|
+
}));
|
|
9358
|
+
return { plugins, categories: data.categories };
|
|
9359
|
+
} catch {
|
|
9360
|
+
return reply.status(503).send({ error: "Marketplace unavailable" });
|
|
9361
|
+
}
|
|
9362
|
+
});
|
|
9363
|
+
app.post("/:name/enable", { preHandler: admin }, async (req, reply) => {
|
|
9364
|
+
if (!lifecycleManager?.registry) {
|
|
9365
|
+
return reply.status(503).send({ error: "Plugin manager unavailable" });
|
|
9366
|
+
}
|
|
9367
|
+
const name = req.params.name;
|
|
9368
|
+
const registry = lifecycleManager.registry;
|
|
9369
|
+
const entry = registry.get(name);
|
|
9370
|
+
if (!entry) {
|
|
9371
|
+
return reply.status(404).send({ error: `Plugin "${name}" not found` });
|
|
9372
|
+
}
|
|
9373
|
+
if (lifecycleManager.loadedPlugins.includes(name)) {
|
|
9374
|
+
registry.setEnabled(name, true);
|
|
9375
|
+
await registry.save();
|
|
9376
|
+
return { ok: true };
|
|
9377
|
+
}
|
|
9378
|
+
let pluginDef = lifecycleManager.plugins.find((p2) => p2.name === name);
|
|
9379
|
+
if (!pluginDef) {
|
|
9380
|
+
if (entry.source === "builtin") {
|
|
9381
|
+
pluginDef = corePlugins.find((p2) => p2.name === name);
|
|
9382
|
+
} else {
|
|
9383
|
+
const { importFromDir: importFromDir2 } = await Promise.resolve().then(() => (init_plugin_installer(), plugin_installer_exports));
|
|
9384
|
+
const instanceRoot = lifecycleManager.instanceRoot ?? path26.join(os12.homedir(), ".openacp");
|
|
9385
|
+
const pluginsDir = path26.join(instanceRoot, "plugins");
|
|
9386
|
+
try {
|
|
9387
|
+
const mod = await importFromDir2(name, pluginsDir);
|
|
9388
|
+
pluginDef = mod.default ?? mod;
|
|
9389
|
+
} catch {
|
|
9390
|
+
return reply.status(500).send({ error: "Plugin module could not be loaded. Try restarting the server." });
|
|
9391
|
+
}
|
|
9392
|
+
}
|
|
9393
|
+
}
|
|
9394
|
+
if (!pluginDef) {
|
|
9395
|
+
return reply.status(500).send({ error: `Plugin definition not found for "${name}"` });
|
|
9396
|
+
}
|
|
9397
|
+
registry.setEnabled(name, true);
|
|
9398
|
+
await registry.save();
|
|
9399
|
+
await lifecycleManager.boot([pluginDef]);
|
|
9400
|
+
if (lifecycleManager.failedPlugins.includes(name)) {
|
|
9401
|
+
return reply.status(500).send({ error: `Plugin "${name}" failed to start` });
|
|
9402
|
+
}
|
|
9403
|
+
return { ok: true };
|
|
9404
|
+
});
|
|
9405
|
+
app.post("/:name/disable", { preHandler: admin }, async (req, reply) => {
|
|
9406
|
+
if (!lifecycleManager?.registry) {
|
|
9407
|
+
return reply.status(503).send({ error: "Plugin manager unavailable" });
|
|
9408
|
+
}
|
|
9409
|
+
const name = req.params.name;
|
|
9410
|
+
const registry = lifecycleManager.registry;
|
|
9411
|
+
const entry = registry.get(name);
|
|
9412
|
+
if (!entry) {
|
|
9413
|
+
return reply.status(404).send({ error: `Plugin "${name}" not found` });
|
|
9414
|
+
}
|
|
9415
|
+
const def = lifecycleManager.plugins.find((p2) => p2.name === name) ?? corePlugins.find((p2) => p2.name === name);
|
|
9416
|
+
if (def?.essential) {
|
|
9417
|
+
return reply.status(409).send({ error: "Essential plugins cannot be disabled" });
|
|
9418
|
+
}
|
|
9419
|
+
await lifecycleManager.unloadPlugin(name);
|
|
9420
|
+
registry.setEnabled(name, false);
|
|
9421
|
+
await registry.save();
|
|
9422
|
+
return { ok: true };
|
|
9423
|
+
});
|
|
9424
|
+
app.delete("/:name", { preHandler: admin }, async (req, reply) => {
|
|
9425
|
+
if (!lifecycleManager?.registry) {
|
|
9426
|
+
return reply.status(503).send({ error: "Plugin manager unavailable" });
|
|
9427
|
+
}
|
|
9428
|
+
const name = req.params.name;
|
|
9429
|
+
const registry = lifecycleManager.registry;
|
|
9430
|
+
const entry = registry.get(name);
|
|
9431
|
+
if (!entry) {
|
|
9432
|
+
return reply.status(404).send({ error: `Plugin "${name}" not found` });
|
|
9433
|
+
}
|
|
9434
|
+
if (entry.source === "builtin") {
|
|
9435
|
+
return reply.status(400).send({ error: "Builtin plugins cannot be uninstalled. Use disable instead." });
|
|
9436
|
+
}
|
|
9437
|
+
await lifecycleManager.unloadPlugin(name);
|
|
9438
|
+
registry.remove(name);
|
|
9439
|
+
await registry.save();
|
|
9440
|
+
return { ok: true };
|
|
9441
|
+
});
|
|
9442
|
+
}
|
|
9443
|
+
var registryClient;
|
|
9444
|
+
var init_plugins = __esm({
|
|
9445
|
+
"src/plugins/api-server/routes/plugins.ts"() {
|
|
9446
|
+
"use strict";
|
|
9447
|
+
init_auth();
|
|
9448
|
+
init_core_plugins();
|
|
9449
|
+
init_registry_client();
|
|
9450
|
+
registryClient = new RegistryClient();
|
|
9451
|
+
}
|
|
9452
|
+
});
|
|
9453
|
+
|
|
9199
9454
|
// src/core/instance/instance-registry.ts
|
|
9200
9455
|
var instance_registry_exports = {};
|
|
9201
9456
|
__export(instance_registry_exports, {
|
|
9202
9457
|
InstanceRegistry: () => InstanceRegistry
|
|
9203
9458
|
});
|
|
9204
9459
|
import fs22 from "fs";
|
|
9205
|
-
import
|
|
9460
|
+
import path27 from "path";
|
|
9206
9461
|
var InstanceRegistry;
|
|
9207
9462
|
var init_instance_registry = __esm({
|
|
9208
9463
|
"src/core/instance/instance-registry.ts"() {
|
|
@@ -9240,7 +9495,7 @@ var init_instance_registry = __esm({
|
|
|
9240
9495
|
}
|
|
9241
9496
|
}
|
|
9242
9497
|
save() {
|
|
9243
|
-
const dir =
|
|
9498
|
+
const dir = path27.dirname(this.registryPath);
|
|
9244
9499
|
fs22.mkdirSync(dir, { recursive: true });
|
|
9245
9500
|
fs22.writeFileSync(this.registryPath, JSON.stringify(this.data, null, 2));
|
|
9246
9501
|
}
|
|
@@ -9276,13 +9531,13 @@ __export(api_server_exports, {
|
|
|
9276
9531
|
});
|
|
9277
9532
|
import * as fs23 from "fs";
|
|
9278
9533
|
import * as crypto2 from "crypto";
|
|
9279
|
-
import * as
|
|
9534
|
+
import * as path28 from "path";
|
|
9280
9535
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
9281
9536
|
function getVersion() {
|
|
9282
9537
|
if (cachedVersion) return cachedVersion;
|
|
9283
9538
|
try {
|
|
9284
9539
|
const __filename = fileURLToPath3(import.meta.url);
|
|
9285
|
-
const pkgPath =
|
|
9540
|
+
const pkgPath = path28.resolve(path28.dirname(__filename), "../../../package.json");
|
|
9286
9541
|
const pkg = JSON.parse(fs23.readFileSync(pkgPath, "utf-8"));
|
|
9287
9542
|
cachedVersion = pkg.version ?? "0.0.0-dev";
|
|
9288
9543
|
} catch {
|
|
@@ -9291,7 +9546,7 @@ function getVersion() {
|
|
|
9291
9546
|
return cachedVersion;
|
|
9292
9547
|
}
|
|
9293
9548
|
function loadOrCreateSecret(secretFilePath) {
|
|
9294
|
-
const dir =
|
|
9549
|
+
const dir = path28.dirname(secretFilePath);
|
|
9295
9550
|
fs23.mkdirSync(dir, { recursive: true });
|
|
9296
9551
|
try {
|
|
9297
9552
|
const existing = fs23.readFileSync(secretFilePath, "utf-8").trim();
|
|
@@ -9317,7 +9572,7 @@ function loadOrCreateSecret(secretFilePath) {
|
|
|
9317
9572
|
return secret;
|
|
9318
9573
|
}
|
|
9319
9574
|
function writePortFile(portFilePath, port) {
|
|
9320
|
-
const dir =
|
|
9575
|
+
const dir = path28.dirname(portFilePath);
|
|
9321
9576
|
fs23.mkdirSync(dir, { recursive: true });
|
|
9322
9577
|
fs23.writeFileSync(portFilePath, String(port));
|
|
9323
9578
|
}
|
|
@@ -9409,10 +9664,10 @@ function createApiServerPlugin() {
|
|
|
9409
9664
|
{ port: apiConfig.port, host: apiConfig.host, instanceRoot },
|
|
9410
9665
|
"API server plugin setup \u2014 config loaded"
|
|
9411
9666
|
);
|
|
9412
|
-
portFilePath =
|
|
9413
|
-
const secretFilePath =
|
|
9414
|
-
const jwtSecretFilePath =
|
|
9415
|
-
const tokensFilePath =
|
|
9667
|
+
portFilePath = path28.join(instanceRoot, "api.port");
|
|
9668
|
+
const secretFilePath = path28.join(instanceRoot, "api-secret");
|
|
9669
|
+
const jwtSecretFilePath = path28.join(instanceRoot, "jwt-secret");
|
|
9670
|
+
const tokensFilePath = path28.join(instanceRoot, "tokens.json");
|
|
9416
9671
|
const startedAt = Date.now();
|
|
9417
9672
|
const secret = loadOrCreateSecret(secretFilePath);
|
|
9418
9673
|
const jwtSecret = loadOrCreateSecret(jwtSecretFilePath);
|
|
@@ -9435,6 +9690,7 @@ function createApiServerPlugin() {
|
|
|
9435
9690
|
const { commandRoutes: commandRoutes2 } = await Promise.resolve().then(() => (init_commands2(), commands_exports));
|
|
9436
9691
|
const { authRoutes: authRoutes2 } = await Promise.resolve().then(() => (init_auth3(), auth_exports3));
|
|
9437
9692
|
const { workspaceRoute: workspaceRoute2 } = await Promise.resolve().then(() => (init_workspace(), workspace_exports));
|
|
9693
|
+
const { pluginRoutes: pluginRoutes2 } = await Promise.resolve().then(() => (init_plugins(), plugins_exports));
|
|
9438
9694
|
server = await createApiServer2({
|
|
9439
9695
|
port: apiConfig.port,
|
|
9440
9696
|
host: apiConfig.host,
|
|
@@ -9453,7 +9709,8 @@ function createApiServerPlugin() {
|
|
|
9453
9709
|
getVersion,
|
|
9454
9710
|
commandRegistry,
|
|
9455
9711
|
authPreHandler: routeAuthPreHandler,
|
|
9456
|
-
contextManager
|
|
9712
|
+
contextManager,
|
|
9713
|
+
lifecycleManager: core.lifecycleManager
|
|
9457
9714
|
};
|
|
9458
9715
|
server.registerPlugin("/api/v1/sessions", async (app) => sessionRoutes2(app, deps));
|
|
9459
9716
|
server.registerPlugin("/api/v1/agents", async (app) => agentRoutes2(app, deps));
|
|
@@ -9464,16 +9721,17 @@ function createApiServerPlugin() {
|
|
|
9464
9721
|
server.registerPlugin("/api/v1/notify", async (app) => notifyRoutes2(app, deps));
|
|
9465
9722
|
server.registerPlugin("/api/v1/commands", async (app) => commandRoutes2(app, deps));
|
|
9466
9723
|
server.registerPlugin("/api/v1/auth", async (app) => authRoutes2(app, { tokenStore, getJwtSecret: () => jwtSecret }));
|
|
9724
|
+
server.registerPlugin("/api/v1/plugins", async (app) => pluginRoutes2(app, deps));
|
|
9467
9725
|
const { InstanceRegistry: InstanceRegistry2 } = await Promise.resolve().then(() => (init_instance_registry(), instance_registry_exports));
|
|
9468
9726
|
const { getGlobalRoot: getGlobalRoot2 } = await Promise.resolve().then(() => (init_instance_context(), instance_context_exports));
|
|
9469
9727
|
const globalRoot = getGlobalRoot2();
|
|
9470
|
-
const instanceReg = new InstanceRegistry2(
|
|
9728
|
+
const instanceReg = new InstanceRegistry2(path28.join(globalRoot, "instances.json"));
|
|
9471
9729
|
instanceReg.load();
|
|
9472
9730
|
const instanceEntry = instanceReg.getByRoot(instanceRoot);
|
|
9473
9731
|
const workspaceId = instanceEntry?.id ?? "main";
|
|
9474
9732
|
const appConfig = core.configManager.get();
|
|
9475
9733
|
const workspaceName = appConfig.instanceName ?? "Main";
|
|
9476
|
-
const workspaceDir =
|
|
9734
|
+
const workspaceDir = path28.dirname(instanceRoot);
|
|
9477
9735
|
server.registerPlugin("/api/v1", async (app) => {
|
|
9478
9736
|
await app.register(workspaceRoute2, {
|
|
9479
9737
|
id: workspaceId,
|
|
@@ -10408,8 +10666,8 @@ function formatToolSummary(name, rawInput, displaySummary) {
|
|
|
10408
10666
|
}
|
|
10409
10667
|
if (lowerName === "grep") {
|
|
10410
10668
|
const pattern = args2.pattern ?? "";
|
|
10411
|
-
const
|
|
10412
|
-
return pattern ? `\u{1F50D} Grep "${pattern}"${
|
|
10669
|
+
const path68 = args2.path ?? "";
|
|
10670
|
+
return pattern ? `\u{1F50D} Grep "${pattern}"${path68 ? ` in ${path68}` : ""}` : `\u{1F527} ${name}`;
|
|
10413
10671
|
}
|
|
10414
10672
|
if (lowerName === "glob") {
|
|
10415
10673
|
const pattern = args2.pattern ?? "";
|
|
@@ -10445,8 +10703,8 @@ function formatToolTitle(name, rawInput, displayTitle) {
|
|
|
10445
10703
|
}
|
|
10446
10704
|
if (lowerName === "grep") {
|
|
10447
10705
|
const pattern = args2.pattern ?? "";
|
|
10448
|
-
const
|
|
10449
|
-
return pattern ? `"${pattern}"${
|
|
10706
|
+
const path68 = args2.path ?? "";
|
|
10707
|
+
return pattern ? `"${pattern}"${path68 ? ` in ${path68}` : ""}` : name;
|
|
10450
10708
|
}
|
|
10451
10709
|
if (lowerName === "glob") {
|
|
10452
10710
|
return String(args2.pattern ?? name);
|
|
@@ -12254,12 +12512,11 @@ var init_menu = __esm({
|
|
|
12254
12512
|
|
|
12255
12513
|
// src/plugins/telegram/commands/settings.ts
|
|
12256
12514
|
import { InlineKeyboard as InlineKeyboard6 } from "grammy";
|
|
12257
|
-
function buildSettingsKeyboard(core) {
|
|
12258
|
-
const config = core.configManager.get();
|
|
12515
|
+
async function buildSettingsKeyboard(core) {
|
|
12259
12516
|
const fields = getSafeFields();
|
|
12260
12517
|
const kb = new InlineKeyboard6();
|
|
12261
12518
|
for (const field of fields) {
|
|
12262
|
-
const value =
|
|
12519
|
+
const value = await getFieldValueAsync(field, core.configManager, core.settingsManager);
|
|
12263
12520
|
const label = formatFieldLabel(field, value);
|
|
12264
12521
|
if (field.type === "toggle") {
|
|
12265
12522
|
kb.text(`${label}`, `s:toggle:${field.path}`).row();
|
|
@@ -12290,7 +12547,7 @@ function formatFieldLabel(field, value) {
|
|
|
12290
12547
|
return `${icon} ${field.displayName}: ${displayValue}`;
|
|
12291
12548
|
}
|
|
12292
12549
|
async function handleSettings(ctx, core) {
|
|
12293
|
-
const kb = buildSettingsKeyboard(core);
|
|
12550
|
+
const kb = await buildSettingsKeyboard(core);
|
|
12294
12551
|
await ctx.reply(`<b>\u2699\uFE0F Settings</b>
|
|
12295
12552
|
Tap to change:`, {
|
|
12296
12553
|
parse_mode: "HTML",
|
|
@@ -12300,19 +12557,20 @@ Tap to change:`, {
|
|
|
12300
12557
|
function setupSettingsCallbacks(bot, core, getAssistantSession) {
|
|
12301
12558
|
bot.callbackQuery(/^s:toggle:/, async (ctx) => {
|
|
12302
12559
|
const fieldPath = ctx.callbackQuery.data.replace("s:toggle:", "");
|
|
12303
|
-
const
|
|
12304
|
-
|
|
12560
|
+
const fieldDef = getSafeFields().find((f) => f.path === fieldPath);
|
|
12561
|
+
if (!fieldDef) return;
|
|
12562
|
+
const settingsManager = core.settingsManager;
|
|
12563
|
+
const currentValue = await getFieldValueAsync(fieldDef, core.configManager, settingsManager);
|
|
12305
12564
|
const newValue = !currentValue;
|
|
12306
12565
|
try {
|
|
12307
|
-
|
|
12308
|
-
await core.configManager.save(updates, fieldPath);
|
|
12566
|
+
await setFieldValueAsync(fieldDef, newValue, core.configManager, settingsManager);
|
|
12309
12567
|
const toast = isHotReloadable(fieldPath) ? `\u2705 ${fieldPath} = ${newValue}` : `\u2705 ${fieldPath} = ${newValue} (restart needed)`;
|
|
12310
12568
|
try {
|
|
12311
12569
|
await ctx.answerCallbackQuery({ text: toast });
|
|
12312
12570
|
} catch {
|
|
12313
12571
|
}
|
|
12314
12572
|
try {
|
|
12315
|
-
await ctx.editMessageReplyMarkup({ reply_markup: buildSettingsKeyboard(core) });
|
|
12573
|
+
await ctx.editMessageReplyMarkup({ reply_markup: await buildSettingsKeyboard(core) });
|
|
12316
12574
|
} catch {
|
|
12317
12575
|
}
|
|
12318
12576
|
} catch (err) {
|
|
@@ -12329,7 +12587,7 @@ function setupSettingsCallbacks(bot, core, getAssistantSession) {
|
|
|
12329
12587
|
const fieldDef = getSafeFields().find((f) => f.path === fieldPath);
|
|
12330
12588
|
if (!fieldDef) return;
|
|
12331
12589
|
const options = resolveOptions(fieldDef, config) ?? [];
|
|
12332
|
-
const currentValue =
|
|
12590
|
+
const currentValue = await getFieldValueAsync(fieldDef, core.configManager, core.settingsManager);
|
|
12333
12591
|
const kb = new InlineKeyboard6();
|
|
12334
12592
|
for (const opt of options) {
|
|
12335
12593
|
const marker = opt === String(currentValue) ? " \u2713" : "";
|
|
@@ -12353,11 +12611,21 @@ Select a value:`, {
|
|
|
12353
12611
|
const parts = ctx.callbackQuery.data.replace("s:pick:", "").split(":");
|
|
12354
12612
|
const fieldPath = parts.slice(0, -1).join(":");
|
|
12355
12613
|
const newValue = parts[parts.length - 1];
|
|
12614
|
+
const fieldDef = getSafeFields().find((f) => f.path === fieldPath);
|
|
12615
|
+
if (!fieldDef) return;
|
|
12356
12616
|
try {
|
|
12357
12617
|
if (fieldPath === "speech.stt.provider") {
|
|
12358
|
-
const
|
|
12359
|
-
|
|
12360
|
-
if (
|
|
12618
|
+
const sm = core.settingsManager;
|
|
12619
|
+
let hasApiKey = false;
|
|
12620
|
+
if (sm) {
|
|
12621
|
+
const speechSettings = await sm.loadSettings("@openacp/speech");
|
|
12622
|
+
hasApiKey = !!speechSettings.groqApiKey;
|
|
12623
|
+
} else {
|
|
12624
|
+
const config = core.configManager.get();
|
|
12625
|
+
const providerConfig = config.speech?.stt?.providers?.[newValue];
|
|
12626
|
+
hasApiKey = !!providerConfig?.apiKey;
|
|
12627
|
+
}
|
|
12628
|
+
if (!hasApiKey) {
|
|
12361
12629
|
const assistant = getAssistantSession();
|
|
12362
12630
|
if (assistant) {
|
|
12363
12631
|
try {
|
|
@@ -12375,8 +12643,7 @@ Select a value:`, {
|
|
|
12375
12643
|
return;
|
|
12376
12644
|
}
|
|
12377
12645
|
}
|
|
12378
|
-
|
|
12379
|
-
await core.configManager.save(updates, fieldPath);
|
|
12646
|
+
await setFieldValueAsync(fieldDef, newValue, core.configManager, core.settingsManager);
|
|
12380
12647
|
try {
|
|
12381
12648
|
await ctx.answerCallbackQuery({ text: `\u2705 ${fieldPath} = ${newValue}` });
|
|
12382
12649
|
} catch {
|
|
@@ -12385,7 +12652,7 @@ Select a value:`, {
|
|
|
12385
12652
|
await ctx.editMessageText(`<b>\u2699\uFE0F Settings</b>
|
|
12386
12653
|
Tap to change:`, {
|
|
12387
12654
|
parse_mode: "HTML",
|
|
12388
|
-
reply_markup: buildSettingsKeyboard(core)
|
|
12655
|
+
reply_markup: await buildSettingsKeyboard(core)
|
|
12389
12656
|
});
|
|
12390
12657
|
} catch {
|
|
12391
12658
|
}
|
|
@@ -12399,10 +12666,9 @@ Tap to change:`, {
|
|
|
12399
12666
|
});
|
|
12400
12667
|
bot.callbackQuery(/^s:input:/, async (ctx) => {
|
|
12401
12668
|
const fieldPath = ctx.callbackQuery.data.replace("s:input:", "");
|
|
12402
|
-
const config = core.configManager.get();
|
|
12403
12669
|
const fieldDef = getSafeFields().find((f) => f.path === fieldPath);
|
|
12404
12670
|
if (!fieldDef) return;
|
|
12405
|
-
const currentValue =
|
|
12671
|
+
const currentValue = await getFieldValueAsync(fieldDef, core.configManager, core.settingsManager);
|
|
12406
12672
|
const assistant = getAssistantSession();
|
|
12407
12673
|
if (!assistant) {
|
|
12408
12674
|
try {
|
|
@@ -12443,23 +12709,12 @@ Choose an action:`, {
|
|
|
12443
12709
|
await ctx.editMessageText(`<b>\u2699\uFE0F Settings</b>
|
|
12444
12710
|
Tap to change:`, {
|
|
12445
12711
|
parse_mode: "HTML",
|
|
12446
|
-
reply_markup: buildSettingsKeyboard(core)
|
|
12712
|
+
reply_markup: await buildSettingsKeyboard(core)
|
|
12447
12713
|
});
|
|
12448
12714
|
} catch {
|
|
12449
12715
|
}
|
|
12450
12716
|
});
|
|
12451
12717
|
}
|
|
12452
|
-
function buildNestedUpdate(dotPath, value) {
|
|
12453
|
-
const parts = dotPath.split(".");
|
|
12454
|
-
const result = {};
|
|
12455
|
-
let target = result;
|
|
12456
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
12457
|
-
target[parts[i]] = {};
|
|
12458
|
-
target = target[parts[i]];
|
|
12459
|
-
}
|
|
12460
|
-
target[parts[parts.length - 1]] = value;
|
|
12461
|
-
return result;
|
|
12462
|
-
}
|
|
12463
12718
|
var log18;
|
|
12464
12719
|
var init_settings = __esm({
|
|
12465
12720
|
"src/plugins/telegram/commands/settings.ts"() {
|
|
@@ -12534,7 +12789,7 @@ var init_config4 = __esm({
|
|
|
12534
12789
|
// src/core/doctor/checks/agents.ts
|
|
12535
12790
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
12536
12791
|
import * as fs25 from "fs";
|
|
12537
|
-
import * as
|
|
12792
|
+
import * as path29 from "path";
|
|
12538
12793
|
function commandExists2(cmd) {
|
|
12539
12794
|
try {
|
|
12540
12795
|
execFileSync3("which", [cmd], { stdio: "pipe" });
|
|
@@ -12543,9 +12798,9 @@ function commandExists2(cmd) {
|
|
|
12543
12798
|
}
|
|
12544
12799
|
let dir = process.cwd();
|
|
12545
12800
|
while (true) {
|
|
12546
|
-
const binPath =
|
|
12801
|
+
const binPath = path29.join(dir, "node_modules", ".bin", cmd);
|
|
12547
12802
|
if (fs25.existsSync(binPath)) return true;
|
|
12548
|
-
const parent =
|
|
12803
|
+
const parent = path29.dirname(dir);
|
|
12549
12804
|
if (parent === dir) break;
|
|
12550
12805
|
dir = parent;
|
|
12551
12806
|
}
|
|
@@ -12820,9 +13075,9 @@ var init_workspace2 = __esm({
|
|
|
12820
13075
|
|
|
12821
13076
|
// src/core/doctor/checks/plugins.ts
|
|
12822
13077
|
import * as fs28 from "fs";
|
|
12823
|
-
import * as
|
|
13078
|
+
import * as path30 from "path";
|
|
12824
13079
|
var pluginsCheck;
|
|
12825
|
-
var
|
|
13080
|
+
var init_plugins2 = __esm({
|
|
12826
13081
|
"src/core/doctor/checks/plugins.ts"() {
|
|
12827
13082
|
"use strict";
|
|
12828
13083
|
pluginsCheck = {
|
|
@@ -12839,7 +13094,7 @@ var init_plugins = __esm({
|
|
|
12839
13094
|
fix: async () => {
|
|
12840
13095
|
fs28.mkdirSync(ctx.pluginsDir, { recursive: true });
|
|
12841
13096
|
fs28.writeFileSync(
|
|
12842
|
-
|
|
13097
|
+
path30.join(ctx.pluginsDir, "package.json"),
|
|
12843
13098
|
JSON.stringify({ name: "openacp-plugins", private: true, dependencies: {} }, null, 2)
|
|
12844
13099
|
);
|
|
12845
13100
|
return { success: true, message: "initialized plugins directory" };
|
|
@@ -12848,7 +13103,7 @@ var init_plugins = __esm({
|
|
|
12848
13103
|
return results;
|
|
12849
13104
|
}
|
|
12850
13105
|
results.push({ status: "pass", message: "Plugins directory exists" });
|
|
12851
|
-
const pkgPath =
|
|
13106
|
+
const pkgPath = path30.join(ctx.pluginsDir, "package.json");
|
|
12852
13107
|
if (!fs28.existsSync(pkgPath)) {
|
|
12853
13108
|
results.push({
|
|
12854
13109
|
status: "warn",
|
|
@@ -12995,8 +13250,8 @@ var init_daemon = __esm({
|
|
|
12995
13250
|
|
|
12996
13251
|
// src/core/doctor/checks/tunnel.ts
|
|
12997
13252
|
import * as fs30 from "fs";
|
|
12998
|
-
import * as
|
|
12999
|
-
import * as
|
|
13253
|
+
import * as path31 from "path";
|
|
13254
|
+
import * as os13 from "os";
|
|
13000
13255
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
13001
13256
|
var tunnelCheck;
|
|
13002
13257
|
var init_tunnel3 = __esm({
|
|
@@ -13018,8 +13273,8 @@ var init_tunnel3 = __esm({
|
|
|
13018
13273
|
const provider = ctx.config.tunnel.provider;
|
|
13019
13274
|
results.push({ status: "pass", message: `Tunnel provider: ${provider}` });
|
|
13020
13275
|
if (provider === "cloudflare") {
|
|
13021
|
-
const binName =
|
|
13022
|
-
const binPath =
|
|
13276
|
+
const binName = os13.platform() === "win32" ? "cloudflared.exe" : "cloudflared";
|
|
13277
|
+
const binPath = path31.join(ctx.dataDir, "bin", binName);
|
|
13023
13278
|
let found = false;
|
|
13024
13279
|
if (fs30.existsSync(binPath)) {
|
|
13025
13280
|
found = true;
|
|
@@ -13068,7 +13323,7 @@ __export(doctor_exports, {
|
|
|
13068
13323
|
DoctorEngine: () => DoctorEngine
|
|
13069
13324
|
});
|
|
13070
13325
|
import * as fs31 from "fs";
|
|
13071
|
-
import * as
|
|
13326
|
+
import * as path32 from "path";
|
|
13072
13327
|
var ALL_CHECKS, CHECK_TIMEOUT_MS, DoctorEngine;
|
|
13073
13328
|
var init_doctor = __esm({
|
|
13074
13329
|
"src/core/doctor/index.ts"() {
|
|
@@ -13080,7 +13335,7 @@ var init_doctor = __esm({
|
|
|
13080
13335
|
init_telegram();
|
|
13081
13336
|
init_storage();
|
|
13082
13337
|
init_workspace2();
|
|
13083
|
-
|
|
13338
|
+
init_plugins2();
|
|
13084
13339
|
init_daemon();
|
|
13085
13340
|
init_tunnel3();
|
|
13086
13341
|
ALL_CHECKS = [
|
|
@@ -13150,7 +13405,7 @@ var init_doctor = __esm({
|
|
|
13150
13405
|
}
|
|
13151
13406
|
async buildContext() {
|
|
13152
13407
|
const dataDir = this.dataDir;
|
|
13153
|
-
const configPath = process.env.OPENACP_CONFIG_PATH ||
|
|
13408
|
+
const configPath = process.env.OPENACP_CONFIG_PATH || path32.join(dataDir, "config.json");
|
|
13154
13409
|
let config = null;
|
|
13155
13410
|
let rawConfig = null;
|
|
13156
13411
|
try {
|
|
@@ -13161,16 +13416,16 @@ var init_doctor = __esm({
|
|
|
13161
13416
|
config = cm.get();
|
|
13162
13417
|
} catch {
|
|
13163
13418
|
}
|
|
13164
|
-
const logsDir = config ? expandHome3(config.logging.logDir) :
|
|
13419
|
+
const logsDir = config ? expandHome3(config.logging.logDir) : path32.join(dataDir, "logs");
|
|
13165
13420
|
return {
|
|
13166
13421
|
config,
|
|
13167
13422
|
rawConfig,
|
|
13168
13423
|
configPath,
|
|
13169
13424
|
dataDir,
|
|
13170
|
-
sessionsPath:
|
|
13171
|
-
pidPath:
|
|
13172
|
-
portFilePath:
|
|
13173
|
-
pluginsDir:
|
|
13425
|
+
sessionsPath: path32.join(dataDir, "sessions.json"),
|
|
13426
|
+
pidPath: path32.join(dataDir, "openacp.pid"),
|
|
13427
|
+
portFilePath: path32.join(dataDir, "api.port"),
|
|
13428
|
+
pluginsDir: path32.join(dataDir, "plugins"),
|
|
13174
13429
|
logsDir
|
|
13175
13430
|
};
|
|
13176
13431
|
}
|
|
@@ -16913,7 +17168,7 @@ __export(settings_manager_exports, {
|
|
|
16913
17168
|
SettingsManager: () => SettingsManager
|
|
16914
17169
|
});
|
|
16915
17170
|
import fs32 from "fs";
|
|
16916
|
-
import
|
|
17171
|
+
import path33 from "path";
|
|
16917
17172
|
var SettingsManager, SettingsAPIImpl;
|
|
16918
17173
|
var init_settings_manager = __esm({
|
|
16919
17174
|
"src/core/plugin/settings-manager.ts"() {
|
|
@@ -16950,7 +17205,7 @@ var init_settings_manager = __esm({
|
|
|
16950
17205
|
};
|
|
16951
17206
|
}
|
|
16952
17207
|
getSettingsPath(pluginName) {
|
|
16953
|
-
return
|
|
17208
|
+
return path33.join(this.basePath, pluginName, "settings.json");
|
|
16954
17209
|
}
|
|
16955
17210
|
async getPluginSettings(pluginName) {
|
|
16956
17211
|
return this.loadSettings(pluginName);
|
|
@@ -16978,7 +17233,7 @@ var init_settings_manager = __esm({
|
|
|
16978
17233
|
}
|
|
16979
17234
|
}
|
|
16980
17235
|
writeFile(data) {
|
|
16981
|
-
const dir =
|
|
17236
|
+
const dir = path33.dirname(this.settingsPath);
|
|
16982
17237
|
fs32.mkdirSync(dir, { recursive: true });
|
|
16983
17238
|
fs32.writeFileSync(this.settingsPath, JSON.stringify(data, null, 2));
|
|
16984
17239
|
this.cache = data;
|
|
@@ -17077,10 +17332,10 @@ var install_context_exports = {};
|
|
|
17077
17332
|
__export(install_context_exports, {
|
|
17078
17333
|
createInstallContext: () => createInstallContext
|
|
17079
17334
|
});
|
|
17080
|
-
import
|
|
17335
|
+
import path34 from "path";
|
|
17081
17336
|
function createInstallContext(opts) {
|
|
17082
17337
|
const { pluginName, settingsManager, basePath, legacyConfig, instanceRoot } = opts;
|
|
17083
|
-
const dataDir =
|
|
17338
|
+
const dataDir = path34.join(basePath, pluginName, "data");
|
|
17084
17339
|
return {
|
|
17085
17340
|
pluginName,
|
|
17086
17341
|
terminal: createTerminalIO(),
|
|
@@ -17108,13 +17363,13 @@ __export(api_client_exports, {
|
|
|
17108
17363
|
removeStalePortFile: () => removeStalePortFile
|
|
17109
17364
|
});
|
|
17110
17365
|
import * as fs33 from "fs";
|
|
17111
|
-
import * as
|
|
17112
|
-
import * as
|
|
17366
|
+
import * as path35 from "path";
|
|
17367
|
+
import * as os14 from "os";
|
|
17113
17368
|
function defaultPortFile(root) {
|
|
17114
|
-
return
|
|
17369
|
+
return path35.join(root ?? DEFAULT_ROOT, "api.port");
|
|
17115
17370
|
}
|
|
17116
17371
|
function defaultSecretFile(root) {
|
|
17117
|
-
return
|
|
17372
|
+
return path35.join(root ?? DEFAULT_ROOT, "api-secret");
|
|
17118
17373
|
}
|
|
17119
17374
|
function readApiPort(portFilePath, instanceRoot) {
|
|
17120
17375
|
const filePath = portFilePath ?? defaultPortFile(instanceRoot);
|
|
@@ -17154,7 +17409,7 @@ var DEFAULT_ROOT;
|
|
|
17154
17409
|
var init_api_client = __esm({
|
|
17155
17410
|
"src/cli/api-client.ts"() {
|
|
17156
17411
|
"use strict";
|
|
17157
|
-
DEFAULT_ROOT =
|
|
17412
|
+
DEFAULT_ROOT = path35.join(os14.homedir(), ".openacp");
|
|
17158
17413
|
}
|
|
17159
17414
|
});
|
|
17160
17415
|
|
|
@@ -17202,16 +17457,16 @@ var init_suggest = __esm({
|
|
|
17202
17457
|
|
|
17203
17458
|
// src/cli/instance-hint.ts
|
|
17204
17459
|
import fs34 from "fs";
|
|
17205
|
-
import
|
|
17206
|
-
import
|
|
17460
|
+
import path36 from "path";
|
|
17461
|
+
import os15 from "os";
|
|
17207
17462
|
function printInstanceHint(root) {
|
|
17208
17463
|
const globalRoot = getGlobalRoot();
|
|
17209
17464
|
const isGlobal = root === globalRoot;
|
|
17210
|
-
const displayPath = root.replace(
|
|
17465
|
+
const displayPath = root.replace(os15.homedir(), "~");
|
|
17211
17466
|
const label = isGlobal ? "global" : "local";
|
|
17212
17467
|
console.log(` Workspace: ${label} \u2014 ${displayPath}`);
|
|
17213
17468
|
if (isGlobal) {
|
|
17214
|
-
const localRoot =
|
|
17469
|
+
const localRoot = path36.join(process.cwd(), ".openacp");
|
|
17215
17470
|
if (fs34.existsSync(localRoot)) {
|
|
17216
17471
|
console.log(` \x1B[2mhint: local workspace exists in current directory \u2014 use --local to use it\x1B[0m`);
|
|
17217
17472
|
}
|
|
@@ -17243,22 +17498,22 @@ __export(daemon_exports, {
|
|
|
17243
17498
|
});
|
|
17244
17499
|
import { spawn as spawn6 } from "child_process";
|
|
17245
17500
|
import * as fs35 from "fs";
|
|
17246
|
-
import * as
|
|
17247
|
-
import * as
|
|
17501
|
+
import * as path37 from "path";
|
|
17502
|
+
import * as os16 from "os";
|
|
17248
17503
|
function getPidPath(root) {
|
|
17249
17504
|
const base = root ?? DEFAULT_ROOT2;
|
|
17250
|
-
return
|
|
17505
|
+
return path37.join(base, "openacp.pid");
|
|
17251
17506
|
}
|
|
17252
17507
|
function getLogDir(root) {
|
|
17253
17508
|
const base = root ?? DEFAULT_ROOT2;
|
|
17254
|
-
return
|
|
17509
|
+
return path37.join(base, "logs");
|
|
17255
17510
|
}
|
|
17256
17511
|
function getRunningMarker(root) {
|
|
17257
17512
|
const base = root ?? DEFAULT_ROOT2;
|
|
17258
|
-
return
|
|
17513
|
+
return path37.join(base, "running");
|
|
17259
17514
|
}
|
|
17260
17515
|
function writePidFile(pidPath, pid) {
|
|
17261
|
-
const dir =
|
|
17516
|
+
const dir = path37.dirname(pidPath);
|
|
17262
17517
|
fs35.mkdirSync(dir, { recursive: true });
|
|
17263
17518
|
fs35.writeFileSync(pidPath, String(pid));
|
|
17264
17519
|
}
|
|
@@ -17307,8 +17562,8 @@ function startDaemon(pidPath = getPidPath(), logDir2, instanceRoot) {
|
|
|
17307
17562
|
}
|
|
17308
17563
|
const resolvedLogDir = logDir2 ? expandHome3(logDir2) : getLogDir(instanceRoot);
|
|
17309
17564
|
fs35.mkdirSync(resolvedLogDir, { recursive: true });
|
|
17310
|
-
const logFile =
|
|
17311
|
-
const cliPath =
|
|
17565
|
+
const logFile = path37.join(resolvedLogDir, "openacp.log");
|
|
17566
|
+
const cliPath = path37.resolve(process.argv[1]);
|
|
17312
17567
|
const nodePath = process.execPath;
|
|
17313
17568
|
const out = fs35.openSync(logFile, "a");
|
|
17314
17569
|
const err = fs35.openSync(logFile, "a");
|
|
@@ -17392,7 +17647,7 @@ async function stopDaemon(pidPath = getPidPath(), instanceRoot) {
|
|
|
17392
17647
|
}
|
|
17393
17648
|
function markRunning(root) {
|
|
17394
17649
|
const marker = getRunningMarker(root);
|
|
17395
|
-
fs35.mkdirSync(
|
|
17650
|
+
fs35.mkdirSync(path37.dirname(marker), { recursive: true });
|
|
17396
17651
|
fs35.writeFileSync(marker, "");
|
|
17397
17652
|
}
|
|
17398
17653
|
function clearRunning(root) {
|
|
@@ -17409,7 +17664,7 @@ var init_daemon2 = __esm({
|
|
|
17409
17664
|
"src/cli/daemon.ts"() {
|
|
17410
17665
|
"use strict";
|
|
17411
17666
|
init_config2();
|
|
17412
|
-
DEFAULT_ROOT2 =
|
|
17667
|
+
DEFAULT_ROOT2 = path37.join(os16.homedir(), ".openacp");
|
|
17413
17668
|
}
|
|
17414
17669
|
});
|
|
17415
17670
|
|
|
@@ -17418,12 +17673,12 @@ var stop_exports = {};
|
|
|
17418
17673
|
__export(stop_exports, {
|
|
17419
17674
|
cmdStop: () => cmdStop
|
|
17420
17675
|
});
|
|
17421
|
-
import
|
|
17422
|
-
import
|
|
17676
|
+
import path39 from "path";
|
|
17677
|
+
import os18 from "os";
|
|
17423
17678
|
async function cmdStop(args2 = [], instanceRoot) {
|
|
17424
17679
|
const json = isJsonMode(args2);
|
|
17425
17680
|
if (json) await muteForJson();
|
|
17426
|
-
const root = instanceRoot ??
|
|
17681
|
+
const root = instanceRoot ?? path39.join(os18.homedir(), ".openacp");
|
|
17427
17682
|
if (!json && wantsHelp(args2)) {
|
|
17428
17683
|
console.log(`
|
|
17429
17684
|
\x1B[1mopenacp stop\x1B[0m \u2014 Stop the background daemon
|
|
@@ -17765,7 +18020,7 @@ var init_mcp_manager = __esm({
|
|
|
17765
18020
|
|
|
17766
18021
|
// src/core/utils/debug-tracer.ts
|
|
17767
18022
|
import fs37 from "fs";
|
|
17768
|
-
import
|
|
18023
|
+
import path40 from "path";
|
|
17769
18024
|
function createDebugTracer(sessionId, workingDirectory) {
|
|
17770
18025
|
if (!DEBUG_ENABLED) return null;
|
|
17771
18026
|
return new DebugTracer(sessionId, workingDirectory);
|
|
@@ -17779,7 +18034,7 @@ var init_debug_tracer = __esm({
|
|
|
17779
18034
|
constructor(sessionId, workingDirectory) {
|
|
17780
18035
|
this.sessionId = sessionId;
|
|
17781
18036
|
this.workingDirectory = workingDirectory;
|
|
17782
|
-
this.logDir =
|
|
18037
|
+
this.logDir = path40.join(workingDirectory, ".log");
|
|
17783
18038
|
}
|
|
17784
18039
|
dirCreated = false;
|
|
17785
18040
|
logDir;
|
|
@@ -17789,7 +18044,7 @@ var init_debug_tracer = __esm({
|
|
|
17789
18044
|
fs37.mkdirSync(this.logDir, { recursive: true });
|
|
17790
18045
|
this.dirCreated = true;
|
|
17791
18046
|
}
|
|
17792
|
-
const filePath =
|
|
18047
|
+
const filePath = path40.join(this.logDir, `${this.sessionId}_${layer}.jsonl`);
|
|
17793
18048
|
const seen = /* @__PURE__ */ new WeakSet();
|
|
17794
18049
|
const line = JSON.stringify({ ts: Date.now(), ...data }, (_key, value) => {
|
|
17795
18050
|
if (typeof value === "object" && value !== null) {
|
|
@@ -17813,16 +18068,16 @@ var init_debug_tracer = __esm({
|
|
|
17813
18068
|
import { spawn as spawn8, execFileSync as execFileSync5 } from "child_process";
|
|
17814
18069
|
import { Transform } from "stream";
|
|
17815
18070
|
import fs38 from "fs";
|
|
17816
|
-
import
|
|
18071
|
+
import path41 from "path";
|
|
17817
18072
|
import { ClientSideConnection, ndJsonStream } from "@agentclientprotocol/sdk";
|
|
17818
18073
|
import { PROTOCOL_VERSION } from "@agentclientprotocol/sdk";
|
|
17819
18074
|
function findPackageRoot(startDir) {
|
|
17820
18075
|
let dir = startDir;
|
|
17821
|
-
while (dir !==
|
|
17822
|
-
if (fs38.existsSync(
|
|
18076
|
+
while (dir !== path41.dirname(dir)) {
|
|
18077
|
+
if (fs38.existsSync(path41.join(dir, "package.json"))) {
|
|
17823
18078
|
return dir;
|
|
17824
18079
|
}
|
|
17825
|
-
dir =
|
|
18080
|
+
dir = path41.dirname(dir);
|
|
17826
18081
|
}
|
|
17827
18082
|
return startDir;
|
|
17828
18083
|
}
|
|
@@ -17834,8 +18089,8 @@ function resolveAgentCommand(cmd) {
|
|
|
17834
18089
|
}
|
|
17835
18090
|
for (const root of searchRoots) {
|
|
17836
18091
|
const packageDirs = [
|
|
17837
|
-
|
|
17838
|
-
|
|
18092
|
+
path41.resolve(root, "node_modules", "@zed-industries", cmd, "dist", "index.js"),
|
|
18093
|
+
path41.resolve(root, "node_modules", cmd, "dist", "index.js")
|
|
17839
18094
|
];
|
|
17840
18095
|
for (const jsPath of packageDirs) {
|
|
17841
18096
|
if (fs38.existsSync(jsPath)) {
|
|
@@ -17844,7 +18099,7 @@ function resolveAgentCommand(cmd) {
|
|
|
17844
18099
|
}
|
|
17845
18100
|
}
|
|
17846
18101
|
for (const root of searchRoots) {
|
|
17847
|
-
const localBin =
|
|
18102
|
+
const localBin = path41.resolve(root, "node_modules", ".bin", cmd);
|
|
17848
18103
|
if (fs38.existsSync(localBin)) {
|
|
17849
18104
|
const content = fs38.readFileSync(localBin, "utf-8");
|
|
17850
18105
|
if (content.startsWith("#!/usr/bin/env node")) {
|
|
@@ -17852,7 +18107,7 @@ function resolveAgentCommand(cmd) {
|
|
|
17852
18107
|
}
|
|
17853
18108
|
const match = content.match(/"([^"]+\.js)"/);
|
|
17854
18109
|
if (match) {
|
|
17855
|
-
const target =
|
|
18110
|
+
const target = path41.resolve(path41.dirname(localBin), match[1]);
|
|
17856
18111
|
if (fs38.existsSync(target)) {
|
|
17857
18112
|
return { command: process.execPath, args: [target] };
|
|
17858
18113
|
}
|
|
@@ -18253,7 +18508,7 @@ ${stderr}`
|
|
|
18253
18508
|
writePath = result.path;
|
|
18254
18509
|
writeContent = result.content;
|
|
18255
18510
|
}
|
|
18256
|
-
await fs38.promises.mkdir(
|
|
18511
|
+
await fs38.promises.mkdir(path41.dirname(writePath), { recursive: true });
|
|
18257
18512
|
await fs38.promises.writeFile(writePath, writeContent, "utf-8");
|
|
18258
18513
|
return {};
|
|
18259
18514
|
},
|
|
@@ -19865,7 +20120,7 @@ var init_message_transformer = __esm({
|
|
|
19865
20120
|
|
|
19866
20121
|
// src/core/sessions/session-store.ts
|
|
19867
20122
|
import fs40 from "fs";
|
|
19868
|
-
import
|
|
20123
|
+
import path42 from "path";
|
|
19869
20124
|
var log30, DEBOUNCE_MS2, JsonFileSessionStore;
|
|
19870
20125
|
var init_session_store = __esm({
|
|
19871
20126
|
"src/core/sessions/session-store.ts"() {
|
|
@@ -19941,7 +20196,7 @@ var init_session_store = __esm({
|
|
|
19941
20196
|
version: 1,
|
|
19942
20197
|
sessions: Object.fromEntries(this.records)
|
|
19943
20198
|
};
|
|
19944
|
-
const dir =
|
|
20199
|
+
const dir = path42.dirname(this.filePath);
|
|
19945
20200
|
if (!fs40.existsSync(dir)) fs40.mkdirSync(dir, { recursive: true });
|
|
19946
20201
|
fs40.writeFileSync(this.filePath, JSON.stringify(data, null, 2));
|
|
19947
20202
|
}
|
|
@@ -20516,8 +20771,8 @@ __export(agent_store_exports, {
|
|
|
20516
20771
|
AgentStore: () => AgentStore
|
|
20517
20772
|
});
|
|
20518
20773
|
import * as fs41 from "fs";
|
|
20519
|
-
import * as
|
|
20520
|
-
import * as
|
|
20774
|
+
import * as path43 from "path";
|
|
20775
|
+
import * as os19 from "os";
|
|
20521
20776
|
import { z as z7 } from "zod";
|
|
20522
20777
|
var log33, InstalledAgentSchema, AgentStoreSchema, AgentStore;
|
|
20523
20778
|
var init_agent_store = __esm({
|
|
@@ -20545,7 +20800,7 @@ var init_agent_store = __esm({
|
|
|
20545
20800
|
data = { version: 1, installed: {} };
|
|
20546
20801
|
filePath;
|
|
20547
20802
|
constructor(filePath) {
|
|
20548
|
-
this.filePath = filePath ??
|
|
20803
|
+
this.filePath = filePath ?? path43.join(os19.homedir(), ".openacp", "agents.json");
|
|
20549
20804
|
}
|
|
20550
20805
|
load() {
|
|
20551
20806
|
if (!fs41.existsSync(this.filePath)) {
|
|
@@ -20587,7 +20842,7 @@ var init_agent_store = __esm({
|
|
|
20587
20842
|
return key in this.data.installed;
|
|
20588
20843
|
}
|
|
20589
20844
|
save() {
|
|
20590
|
-
fs41.mkdirSync(
|
|
20845
|
+
fs41.mkdirSync(path43.dirname(this.filePath), { recursive: true });
|
|
20591
20846
|
const tmpPath = this.filePath + ".tmp";
|
|
20592
20847
|
fs41.writeFileSync(tmpPath, JSON.stringify(this.data, null, 2));
|
|
20593
20848
|
fs41.renameSync(tmpPath, this.filePath);
|
|
@@ -20598,8 +20853,8 @@ var init_agent_store = __esm({
|
|
|
20598
20853
|
|
|
20599
20854
|
// src/core/agents/agent-installer.ts
|
|
20600
20855
|
import * as fs42 from "fs";
|
|
20601
|
-
import * as
|
|
20602
|
-
import * as
|
|
20856
|
+
import * as path44 from "path";
|
|
20857
|
+
import * as os20 from "os";
|
|
20603
20858
|
function getPlatformKey() {
|
|
20604
20859
|
const platform2 = PLATFORM_MAP[process.platform] ?? process.platform;
|
|
20605
20860
|
const arch = ARCH_MAP[process.arch] ?? process.arch;
|
|
@@ -20650,7 +20905,7 @@ function buildInstalledAgent(registryId, name, version, dist, binaryPath) {
|
|
|
20650
20905
|
binaryPath: null
|
|
20651
20906
|
};
|
|
20652
20907
|
}
|
|
20653
|
-
const absCmd =
|
|
20908
|
+
const absCmd = path44.resolve(binaryPath, dist.cmd);
|
|
20654
20909
|
return {
|
|
20655
20910
|
registryId,
|
|
20656
20911
|
name,
|
|
@@ -20723,7 +20978,7 @@ Install it with: pip install uv`;
|
|
|
20723
20978
|
return { ok: true, agentKey, setupSteps: setup?.setupSteps };
|
|
20724
20979
|
}
|
|
20725
20980
|
async function downloadAndExtract(agentId, archiveUrl, progress, agentsDir) {
|
|
20726
|
-
const destDir =
|
|
20981
|
+
const destDir = path44.join(agentsDir ?? DEFAULT_AGENTS_DIR, agentId);
|
|
20727
20982
|
fs42.mkdirSync(destDir, { recursive: true });
|
|
20728
20983
|
await progress?.onStep("Downloading...");
|
|
20729
20984
|
log34.info({ agentId, url: archiveUrl }, "Downloading agent binary");
|
|
@@ -20767,15 +21022,15 @@ function validateExtractedPaths(destDir) {
|
|
|
20767
21022
|
for (const entry of entries) {
|
|
20768
21023
|
const dirent = entry;
|
|
20769
21024
|
const parentPath = dirent.parentPath ?? dirent.path ?? destDir;
|
|
20770
|
-
const fullPath =
|
|
21025
|
+
const fullPath = path44.join(parentPath, entry.name);
|
|
20771
21026
|
let realPath;
|
|
20772
21027
|
try {
|
|
20773
21028
|
realPath = fs42.realpathSync(fullPath);
|
|
20774
21029
|
} catch {
|
|
20775
21030
|
const linkTarget = fs42.readlinkSync(fullPath);
|
|
20776
|
-
realPath =
|
|
21031
|
+
realPath = path44.resolve(path44.dirname(fullPath), linkTarget);
|
|
20777
21032
|
}
|
|
20778
|
-
if (!realPath.startsWith(realDest +
|
|
21033
|
+
if (!realPath.startsWith(realDest + path44.sep) && realPath !== realDest) {
|
|
20779
21034
|
fs42.rmSync(destDir, { recursive: true, force: true });
|
|
20780
21035
|
throw new Error(`Archive contains unsafe path: ${entry.name}`);
|
|
20781
21036
|
}
|
|
@@ -20783,7 +21038,7 @@ function validateExtractedPaths(destDir) {
|
|
|
20783
21038
|
}
|
|
20784
21039
|
async function extractTarGz(buffer, destDir) {
|
|
20785
21040
|
const { execFileSync: execFileSync8 } = await import("child_process");
|
|
20786
|
-
const tmpFile =
|
|
21041
|
+
const tmpFile = path44.join(destDir, "_archive.tar.gz");
|
|
20787
21042
|
fs42.writeFileSync(tmpFile, buffer);
|
|
20788
21043
|
try {
|
|
20789
21044
|
execFileSync8("tar", ["xzf", tmpFile, "-C", destDir], { stdio: "pipe" });
|
|
@@ -20794,7 +21049,7 @@ async function extractTarGz(buffer, destDir) {
|
|
|
20794
21049
|
}
|
|
20795
21050
|
async function extractZip(buffer, destDir) {
|
|
20796
21051
|
const { execFileSync: execFileSync8 } = await import("child_process");
|
|
20797
|
-
const tmpFile =
|
|
21052
|
+
const tmpFile = path44.join(destDir, "_archive.zip");
|
|
20798
21053
|
fs42.writeFileSync(tmpFile, buffer);
|
|
20799
21054
|
try {
|
|
20800
21055
|
execFileSync8("unzip", ["-o", tmpFile, "-d", destDir], { stdio: "pipe" });
|
|
@@ -20819,7 +21074,7 @@ var init_agent_installer = __esm({
|
|
|
20819
21074
|
init_log();
|
|
20820
21075
|
init_agent_dependencies();
|
|
20821
21076
|
log34 = createChildLogger({ module: "agent-installer" });
|
|
20822
|
-
DEFAULT_AGENTS_DIR =
|
|
21077
|
+
DEFAULT_AGENTS_DIR = path44.join(os20.homedir(), ".openacp", "agents");
|
|
20823
21078
|
ARCH_MAP = {
|
|
20824
21079
|
arm64: "aarch64",
|
|
20825
21080
|
x64: "x86_64"
|
|
@@ -20838,8 +21093,8 @@ __export(agent_catalog_exports, {
|
|
|
20838
21093
|
AgentCatalog: () => AgentCatalog
|
|
20839
21094
|
});
|
|
20840
21095
|
import * as fs43 from "fs";
|
|
20841
|
-
import * as
|
|
20842
|
-
import * as
|
|
21096
|
+
import * as path45 from "path";
|
|
21097
|
+
import * as os21 from "os";
|
|
20843
21098
|
var log35, REGISTRY_URL2, DEFAULT_TTL_HOURS, AgentCatalog;
|
|
20844
21099
|
var init_agent_catalog = __esm({
|
|
20845
21100
|
"src/core/agents/agent-catalog.ts"() {
|
|
@@ -20858,7 +21113,7 @@ var init_agent_catalog = __esm({
|
|
|
20858
21113
|
agentsDir;
|
|
20859
21114
|
constructor(store, cachePath, agentsDir) {
|
|
20860
21115
|
this.store = store ?? new AgentStore();
|
|
20861
|
-
this.cachePath = cachePath ??
|
|
21116
|
+
this.cachePath = cachePath ?? path45.join(os21.homedir(), ".openacp", "registry-cache.json");
|
|
20862
21117
|
this.agentsDir = agentsDir;
|
|
20863
21118
|
}
|
|
20864
21119
|
load() {
|
|
@@ -20879,7 +21134,7 @@ var init_agent_catalog = __esm({
|
|
|
20879
21134
|
ttlHours: DEFAULT_TTL_HOURS,
|
|
20880
21135
|
data
|
|
20881
21136
|
};
|
|
20882
|
-
fs43.mkdirSync(
|
|
21137
|
+
fs43.mkdirSync(path45.dirname(this.cachePath), { recursive: true });
|
|
20883
21138
|
fs43.writeFileSync(this.cachePath, JSON.stringify(cache, null, 2));
|
|
20884
21139
|
log35.info({ count: this.registryAgents.length }, "Registry updated");
|
|
20885
21140
|
} catch (err) {
|
|
@@ -21065,9 +21320,9 @@ var init_agent_catalog = __esm({
|
|
|
21065
21320
|
}
|
|
21066
21321
|
try {
|
|
21067
21322
|
const candidates = [
|
|
21068
|
-
|
|
21069
|
-
|
|
21070
|
-
|
|
21323
|
+
path45.join(import.meta.dirname, "data", "registry-snapshot.json"),
|
|
21324
|
+
path45.join(import.meta.dirname, "..", "data", "registry-snapshot.json"),
|
|
21325
|
+
path45.join(import.meta.dirname, "..", "..", "data", "registry-snapshot.json")
|
|
21071
21326
|
];
|
|
21072
21327
|
for (const candidate of candidates) {
|
|
21073
21328
|
if (fs43.existsSync(candidate)) {
|
|
@@ -21365,7 +21620,7 @@ var init_error_tracker = __esm({
|
|
|
21365
21620
|
|
|
21366
21621
|
// src/core/plugin/plugin-storage.ts
|
|
21367
21622
|
import fs44 from "fs";
|
|
21368
|
-
import
|
|
21623
|
+
import path46 from "path";
|
|
21369
21624
|
var PluginStorageImpl;
|
|
21370
21625
|
var init_plugin_storage = __esm({
|
|
21371
21626
|
"src/core/plugin/plugin-storage.ts"() {
|
|
@@ -21375,8 +21630,8 @@ var init_plugin_storage = __esm({
|
|
|
21375
21630
|
dataDir;
|
|
21376
21631
|
writeChain = Promise.resolve();
|
|
21377
21632
|
constructor(baseDir) {
|
|
21378
|
-
this.dataDir =
|
|
21379
|
-
this.kvPath =
|
|
21633
|
+
this.dataDir = path46.join(baseDir, "data");
|
|
21634
|
+
this.kvPath = path46.join(baseDir, "kv.json");
|
|
21380
21635
|
fs44.mkdirSync(baseDir, { recursive: true });
|
|
21381
21636
|
}
|
|
21382
21637
|
readKv() {
|
|
@@ -21422,8 +21677,8 @@ var init_plugin_storage = __esm({
|
|
|
21422
21677
|
});
|
|
21423
21678
|
|
|
21424
21679
|
// src/core/plugin/plugin-context.ts
|
|
21425
|
-
import
|
|
21426
|
-
import
|
|
21680
|
+
import path47 from "path";
|
|
21681
|
+
import os22 from "os";
|
|
21427
21682
|
function requirePermission(permissions, required, action) {
|
|
21428
21683
|
if (!permissions.includes(required)) {
|
|
21429
21684
|
throw new Error(`Plugin does not have '${required}' permission required for ${action}`);
|
|
@@ -21442,7 +21697,7 @@ function createPluginContext(opts) {
|
|
|
21442
21697
|
config,
|
|
21443
21698
|
core
|
|
21444
21699
|
} = opts;
|
|
21445
|
-
const instanceRoot = opts.instanceRoot ??
|
|
21700
|
+
const instanceRoot = opts.instanceRoot ?? path47.join(os22.homedir(), ".openacp");
|
|
21446
21701
|
const registeredListeners = [];
|
|
21447
21702
|
const registeredCommands = [];
|
|
21448
21703
|
const noopLog = {
|
|
@@ -21665,7 +21920,7 @@ var init_lifecycle_manager = __esm({
|
|
|
21665
21920
|
log;
|
|
21666
21921
|
settingsManager;
|
|
21667
21922
|
pluginRegistry;
|
|
21668
|
-
|
|
21923
|
+
_instanceRoot;
|
|
21669
21924
|
contexts = /* @__PURE__ */ new Map();
|
|
21670
21925
|
loadOrder = [];
|
|
21671
21926
|
_loaded = /* @__PURE__ */ new Set();
|
|
@@ -21679,6 +21934,14 @@ var init_lifecycle_manager = __esm({
|
|
|
21679
21934
|
get registry() {
|
|
21680
21935
|
return this.pluginRegistry;
|
|
21681
21936
|
}
|
|
21937
|
+
/** Plugin definitions currently in load order (loaded + failed). */
|
|
21938
|
+
get plugins() {
|
|
21939
|
+
return [...this.loadOrder];
|
|
21940
|
+
}
|
|
21941
|
+
/** Root directory of this OpenACP instance (e.g. ~/.openacp). */
|
|
21942
|
+
get instanceRoot() {
|
|
21943
|
+
return this._instanceRoot;
|
|
21944
|
+
}
|
|
21682
21945
|
constructor(opts) {
|
|
21683
21946
|
this.serviceRegistry = opts?.serviceRegistry ?? new ServiceRegistry();
|
|
21684
21947
|
this.middlewareChain = opts?.middlewareChain ?? new MiddlewareChain();
|
|
@@ -21698,7 +21961,7 @@ var init_lifecycle_manager = __esm({
|
|
|
21698
21961
|
this.log = opts?.log;
|
|
21699
21962
|
this.settingsManager = opts?.settingsManager;
|
|
21700
21963
|
this.pluginRegistry = opts?.pluginRegistry;
|
|
21701
|
-
this.
|
|
21964
|
+
this._instanceRoot = opts?.instanceRoot;
|
|
21702
21965
|
}
|
|
21703
21966
|
getPluginLogger(pluginName) {
|
|
21704
21967
|
if (this.log && typeof this.log.child === "function") {
|
|
@@ -21809,7 +22072,7 @@ var init_lifecycle_manager = __esm({
|
|
|
21809
22072
|
config: this.config,
|
|
21810
22073
|
core: this.core,
|
|
21811
22074
|
log: this.log,
|
|
21812
|
-
instanceRoot: this.
|
|
22075
|
+
instanceRoot: this._instanceRoot
|
|
21813
22076
|
});
|
|
21814
22077
|
try {
|
|
21815
22078
|
await withTimeout(plugin2.setup(ctx), SETUP_TIMEOUT_MS, `${plugin2.name}.setup()`);
|
|
@@ -22285,8 +22548,8 @@ var init_core_items = __esm({
|
|
|
22285
22548
|
});
|
|
22286
22549
|
|
|
22287
22550
|
// src/core/core.ts
|
|
22288
|
-
import
|
|
22289
|
-
import
|
|
22551
|
+
import path48 from "path";
|
|
22552
|
+
import os23 from "os";
|
|
22290
22553
|
var log39, OpenACPCore;
|
|
22291
22554
|
var init_core = __esm({
|
|
22292
22555
|
"src/core/core.ts"() {
|
|
@@ -22354,6 +22617,9 @@ var init_core = __esm({
|
|
|
22354
22617
|
get contextManager() {
|
|
22355
22618
|
return this.getService("context");
|
|
22356
22619
|
}
|
|
22620
|
+
get settingsManager() {
|
|
22621
|
+
return this.lifecycleManager.settingsManager;
|
|
22622
|
+
}
|
|
22357
22623
|
constructor(configManager, ctx) {
|
|
22358
22624
|
this.configManager = configManager;
|
|
22359
22625
|
this.instanceContext = ctx;
|
|
@@ -22365,7 +22631,7 @@ var init_core = __esm({
|
|
|
22365
22631
|
);
|
|
22366
22632
|
this.agentCatalog.load();
|
|
22367
22633
|
this.agentManager = new AgentManager(this.agentCatalog);
|
|
22368
|
-
const storePath = ctx?.paths.sessions ??
|
|
22634
|
+
const storePath = ctx?.paths.sessions ?? path48.join(os23.homedir(), ".openacp", "sessions.json");
|
|
22369
22635
|
this.sessionStore = new JsonFileSessionStore(
|
|
22370
22636
|
storePath,
|
|
22371
22637
|
config.sessionStore.ttlDays
|
|
@@ -22389,7 +22655,7 @@ var init_core = __esm({
|
|
|
22389
22655
|
sessions: this.sessionManager,
|
|
22390
22656
|
config: this.configManager,
|
|
22391
22657
|
core: this,
|
|
22392
|
-
storagePath: ctx?.paths.pluginsData ??
|
|
22658
|
+
storagePath: ctx?.paths.pluginsData ?? path48.join(os23.homedir(), ".openacp", "plugins", "data"),
|
|
22393
22659
|
instanceRoot: ctx?.root,
|
|
22394
22660
|
log: createChildLogger({ module: "plugin" })
|
|
22395
22661
|
});
|
|
@@ -22421,22 +22687,36 @@ var init_core = __esm({
|
|
|
22421
22687
|
log39.info({ level: value }, "Log level changed at runtime");
|
|
22422
22688
|
}
|
|
22423
22689
|
if (configPath.startsWith("speech.")) {
|
|
22424
|
-
const speechSvc = this.
|
|
22690
|
+
const speechSvc = this.lifecycleManager.serviceRegistry.get("speech");
|
|
22425
22691
|
if (speechSvc) {
|
|
22426
|
-
const
|
|
22427
|
-
|
|
22428
|
-
|
|
22429
|
-
|
|
22430
|
-
|
|
22431
|
-
|
|
22432
|
-
|
|
22692
|
+
const settingsMgr = this.settingsManager;
|
|
22693
|
+
if (settingsMgr) {
|
|
22694
|
+
const pluginCfg = await settingsMgr.loadSettings("@openacp/speech");
|
|
22695
|
+
const groqApiKey = pluginCfg.groqApiKey;
|
|
22696
|
+
const sttProviders = {};
|
|
22697
|
+
if (groqApiKey) {
|
|
22698
|
+
sttProviders.groq = { apiKey: groqApiKey };
|
|
22699
|
+
}
|
|
22700
|
+
const newSpeechConfig = {
|
|
22701
|
+
stt: {
|
|
22702
|
+
provider: groqApiKey ? "groq" : null,
|
|
22703
|
+
providers: sttProviders
|
|
22704
|
+
},
|
|
22705
|
+
tts: {
|
|
22706
|
+
provider: pluginCfg.ttsProvider ?? null,
|
|
22707
|
+
providers: {}
|
|
22708
|
+
}
|
|
22709
|
+
};
|
|
22710
|
+
speechSvc.refreshProviders(newSpeechConfig);
|
|
22711
|
+
log39.info("Speech service config updated at runtime (from plugin settings)");
|
|
22712
|
+
}
|
|
22433
22713
|
}
|
|
22434
22714
|
}
|
|
22435
22715
|
}
|
|
22436
22716
|
);
|
|
22437
22717
|
registerCoreMenuItems(this.menuRegistry);
|
|
22438
22718
|
if (ctx?.root) {
|
|
22439
|
-
this.assistantRegistry.setInstanceRoot(
|
|
22719
|
+
this.assistantRegistry.setInstanceRoot(path48.dirname(ctx.root));
|
|
22440
22720
|
}
|
|
22441
22721
|
this.assistantRegistry.register(createSessionsSection(this));
|
|
22442
22722
|
this.assistantRegistry.register(createAgentsSection(this));
|
|
@@ -22530,7 +22810,7 @@ var init_core = __esm({
|
|
|
22530
22810
|
if (!result) return;
|
|
22531
22811
|
message = result;
|
|
22532
22812
|
}
|
|
22533
|
-
const access2 = this.securityGuard.checkAccess(message);
|
|
22813
|
+
const access2 = await this.securityGuard.checkAccess(message);
|
|
22534
22814
|
if (!access2.allowed) {
|
|
22535
22815
|
log39.warn({ userId: message.userId, reason: access2.reason }, "Access denied");
|
|
22536
22816
|
if (access2.reason.includes("Session limit")) {
|
|
@@ -23993,8 +24273,8 @@ __export(autostart_exports, {
|
|
|
23993
24273
|
});
|
|
23994
24274
|
import { execFileSync as execFileSync7 } from "child_process";
|
|
23995
24275
|
import * as fs45 from "fs";
|
|
23996
|
-
import * as
|
|
23997
|
-
import * as
|
|
24276
|
+
import * as path49 from "path";
|
|
24277
|
+
import * as os24 from "os";
|
|
23998
24278
|
function isAutoStartSupported() {
|
|
23999
24279
|
return process.platform === "darwin" || process.platform === "linux";
|
|
24000
24280
|
}
|
|
@@ -24006,7 +24286,7 @@ function escapeSystemdValue(str) {
|
|
|
24006
24286
|
return `"${escaped}"`;
|
|
24007
24287
|
}
|
|
24008
24288
|
function generateLaunchdPlist(nodePath, cliPath, logDir2) {
|
|
24009
|
-
const logFile =
|
|
24289
|
+
const logFile = path49.join(logDir2, "openacp.log");
|
|
24010
24290
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
24011
24291
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
24012
24292
|
<plist version="1.0">
|
|
@@ -24051,12 +24331,12 @@ function installAutoStart(logDir2) {
|
|
|
24051
24331
|
return { success: false, error: "Auto-start not supported on this platform" };
|
|
24052
24332
|
}
|
|
24053
24333
|
const nodePath = process.execPath;
|
|
24054
|
-
const cliPath =
|
|
24055
|
-
const resolvedLogDir = logDir2.startsWith("~") ?
|
|
24334
|
+
const cliPath = path49.resolve(process.argv[1]);
|
|
24335
|
+
const resolvedLogDir = logDir2.startsWith("~") ? path49.join(os24.homedir(), logDir2.slice(1)) : logDir2;
|
|
24056
24336
|
try {
|
|
24057
24337
|
if (process.platform === "darwin") {
|
|
24058
24338
|
const plist = generateLaunchdPlist(nodePath, cliPath, resolvedLogDir);
|
|
24059
|
-
const dir =
|
|
24339
|
+
const dir = path49.dirname(LAUNCHD_PLIST_PATH);
|
|
24060
24340
|
fs45.mkdirSync(dir, { recursive: true });
|
|
24061
24341
|
fs45.writeFileSync(LAUNCHD_PLIST_PATH, plist);
|
|
24062
24342
|
execFileSync7("launchctl", ["load", LAUNCHD_PLIST_PATH], { stdio: "pipe" });
|
|
@@ -24065,7 +24345,7 @@ function installAutoStart(logDir2) {
|
|
|
24065
24345
|
}
|
|
24066
24346
|
if (process.platform === "linux") {
|
|
24067
24347
|
const unit = generateSystemdUnit(nodePath, cliPath);
|
|
24068
|
-
const dir =
|
|
24348
|
+
const dir = path49.dirname(SYSTEMD_SERVICE_PATH);
|
|
24069
24349
|
fs45.mkdirSync(dir, { recursive: true });
|
|
24070
24350
|
fs45.writeFileSync(SYSTEMD_SERVICE_PATH, unit);
|
|
24071
24351
|
execFileSync7("systemctl", ["--user", "daemon-reload"], { stdio: "pipe" });
|
|
@@ -24131,8 +24411,8 @@ var init_autostart = __esm({
|
|
|
24131
24411
|
init_log();
|
|
24132
24412
|
log40 = createChildLogger({ module: "autostart" });
|
|
24133
24413
|
LAUNCHD_LABEL = "com.openacp.daemon";
|
|
24134
|
-
LAUNCHD_PLIST_PATH =
|
|
24135
|
-
SYSTEMD_SERVICE_PATH =
|
|
24414
|
+
LAUNCHD_PLIST_PATH = path49.join(os24.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
|
|
24415
|
+
SYSTEMD_SERVICE_PATH = path49.join(os24.homedir(), ".config", "systemd", "user", "openacp.service");
|
|
24136
24416
|
}
|
|
24137
24417
|
});
|
|
24138
24418
|
|
|
@@ -24251,7 +24531,7 @@ var init_setup_integrations = __esm({
|
|
|
24251
24531
|
});
|
|
24252
24532
|
|
|
24253
24533
|
// src/core/setup/setup-channels.ts
|
|
24254
|
-
import * as
|
|
24534
|
+
import * as path50 from "path";
|
|
24255
24535
|
import * as clack7 from "@clack/prompts";
|
|
24256
24536
|
function getChannelStatuses(config) {
|
|
24257
24537
|
const statuses = [];
|
|
@@ -24317,7 +24597,7 @@ async function configureViaPlugin(channelId) {
|
|
|
24317
24597
|
if (plugin2?.configure) {
|
|
24318
24598
|
const { SettingsManager: SettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), settings_manager_exports));
|
|
24319
24599
|
const { createInstallContext: createInstallContext2 } = await Promise.resolve().then(() => (init_install_context(), install_context_exports));
|
|
24320
|
-
const basePath =
|
|
24600
|
+
const basePath = path50.join(getGlobalRoot(), "plugins", "data");
|
|
24321
24601
|
const settingsManager = new SettingsManager2(basePath);
|
|
24322
24602
|
const ctx = createInstallContext2({
|
|
24323
24603
|
pluginName: plugin2.name,
|
|
@@ -24399,55 +24679,70 @@ __export(instance_copy_exports, {
|
|
|
24399
24679
|
copyInstance: () => copyInstance
|
|
24400
24680
|
});
|
|
24401
24681
|
import fs46 from "fs";
|
|
24402
|
-
import
|
|
24682
|
+
import path51 from "path";
|
|
24403
24683
|
async function copyInstance(src, dst, opts) {
|
|
24404
24684
|
const { inheritableKeys = {}, onProgress } = opts;
|
|
24405
24685
|
fs46.mkdirSync(dst, { recursive: true });
|
|
24406
|
-
const configSrc =
|
|
24686
|
+
const configSrc = path51.join(src, "config.json");
|
|
24407
24687
|
if (fs46.existsSync(configSrc)) {
|
|
24408
24688
|
onProgress?.("Configuration", "start");
|
|
24409
24689
|
const config = JSON.parse(fs46.readFileSync(configSrc, "utf-8"));
|
|
24410
24690
|
delete config.instanceName;
|
|
24411
|
-
|
|
24412
|
-
|
|
24413
|
-
|
|
24691
|
+
delete config.security;
|
|
24692
|
+
delete config.tunnel;
|
|
24693
|
+
delete config.api;
|
|
24694
|
+
delete config.speech;
|
|
24695
|
+
delete config.usage;
|
|
24696
|
+
if (config.channels && typeof config.channels === "object") {
|
|
24697
|
+
const CORE_CHANNEL_KEYS = /* @__PURE__ */ new Set(["enabled", "outputMode", "adapter", "displayVerbosity"]);
|
|
24698
|
+
for (const ch of Object.values(config.channels)) {
|
|
24699
|
+
if (ch && typeof ch === "object") {
|
|
24700
|
+
for (const key of Object.keys(ch)) {
|
|
24701
|
+
if (!CORE_CHANNEL_KEYS.has(key)) {
|
|
24702
|
+
delete ch[key];
|
|
24703
|
+
}
|
|
24704
|
+
}
|
|
24705
|
+
}
|
|
24706
|
+
}
|
|
24707
|
+
}
|
|
24708
|
+
fs46.writeFileSync(path51.join(dst, "config.json"), JSON.stringify(config, null, 2));
|
|
24414
24709
|
onProgress?.("Configuration", "done");
|
|
24415
24710
|
}
|
|
24416
|
-
const pluginsSrc =
|
|
24711
|
+
const pluginsSrc = path51.join(src, "plugins.json");
|
|
24417
24712
|
if (fs46.existsSync(pluginsSrc)) {
|
|
24418
24713
|
onProgress?.("Plugin list", "start");
|
|
24419
|
-
fs46.copyFileSync(pluginsSrc,
|
|
24714
|
+
fs46.copyFileSync(pluginsSrc, path51.join(dst, "plugins.json"));
|
|
24420
24715
|
onProgress?.("Plugin list", "done");
|
|
24421
24716
|
}
|
|
24422
|
-
const pluginsDir =
|
|
24717
|
+
const pluginsDir = path51.join(src, "plugins");
|
|
24423
24718
|
if (fs46.existsSync(pluginsDir)) {
|
|
24424
24719
|
onProgress?.("Plugins", "start");
|
|
24425
|
-
const dstPlugins =
|
|
24720
|
+
const dstPlugins = path51.join(dst, "plugins");
|
|
24426
24721
|
fs46.mkdirSync(dstPlugins, { recursive: true });
|
|
24427
|
-
const pkgJson =
|
|
24428
|
-
if (fs46.existsSync(pkgJson)) fs46.copyFileSync(pkgJson,
|
|
24429
|
-
const nodeModules =
|
|
24430
|
-
if (fs46.existsSync(nodeModules)) fs46.cpSync(nodeModules,
|
|
24722
|
+
const pkgJson = path51.join(pluginsDir, "package.json");
|
|
24723
|
+
if (fs46.existsSync(pkgJson)) fs46.copyFileSync(pkgJson, path51.join(dstPlugins, "package.json"));
|
|
24724
|
+
const nodeModules = path51.join(pluginsDir, "node_modules");
|
|
24725
|
+
if (fs46.existsSync(nodeModules)) fs46.cpSync(nodeModules, path51.join(dstPlugins, "node_modules"), { recursive: true });
|
|
24431
24726
|
onProgress?.("Plugins", "done");
|
|
24432
24727
|
}
|
|
24433
|
-
const agentsJson =
|
|
24728
|
+
const agentsJson = path51.join(src, "agents.json");
|
|
24434
24729
|
if (fs46.existsSync(agentsJson)) {
|
|
24435
24730
|
onProgress?.("Agents", "start");
|
|
24436
|
-
fs46.copyFileSync(agentsJson,
|
|
24437
|
-
const agentsDir =
|
|
24438
|
-
if (fs46.existsSync(agentsDir)) fs46.cpSync(agentsDir,
|
|
24731
|
+
fs46.copyFileSync(agentsJson, path51.join(dst, "agents.json"));
|
|
24732
|
+
const agentsDir = path51.join(src, "agents");
|
|
24733
|
+
if (fs46.existsSync(agentsDir)) fs46.cpSync(agentsDir, path51.join(dst, "agents"), { recursive: true });
|
|
24439
24734
|
onProgress?.("Agents", "done");
|
|
24440
24735
|
}
|
|
24441
|
-
const binDir =
|
|
24736
|
+
const binDir = path51.join(src, "bin");
|
|
24442
24737
|
if (fs46.existsSync(binDir)) {
|
|
24443
24738
|
onProgress?.("Tools", "start");
|
|
24444
|
-
fs46.cpSync(binDir,
|
|
24739
|
+
fs46.cpSync(binDir, path51.join(dst, "bin"), { recursive: true });
|
|
24445
24740
|
onProgress?.("Tools", "done");
|
|
24446
24741
|
}
|
|
24447
|
-
const pluginDataSrc =
|
|
24742
|
+
const pluginDataSrc = path51.join(src, "plugins", "data");
|
|
24448
24743
|
if (fs46.existsSync(pluginDataSrc)) {
|
|
24449
24744
|
onProgress?.("Preferences", "start");
|
|
24450
|
-
copyPluginSettings(pluginDataSrc,
|
|
24745
|
+
copyPluginSettings(pluginDataSrc, path51.join(dst, "plugins", "data"), inheritableKeys);
|
|
24451
24746
|
onProgress?.("Preferences", "done");
|
|
24452
24747
|
}
|
|
24453
24748
|
}
|
|
@@ -24462,10 +24757,10 @@ function copyPluginSettings(srcData, dstData, inheritableKeys) {
|
|
|
24462
24757
|
if (key in settings) filtered[key] = settings[key];
|
|
24463
24758
|
}
|
|
24464
24759
|
if (Object.keys(filtered).length > 0) {
|
|
24465
|
-
const relative =
|
|
24466
|
-
const dstDir =
|
|
24760
|
+
const relative = path51.relative(srcData, path51.dirname(settingsPath));
|
|
24761
|
+
const dstDir = path51.join(dstData, relative);
|
|
24467
24762
|
fs46.mkdirSync(dstDir, { recursive: true });
|
|
24468
|
-
fs46.writeFileSync(
|
|
24763
|
+
fs46.writeFileSync(path51.join(dstDir, "settings.json"), JSON.stringify(filtered, null, 2));
|
|
24469
24764
|
}
|
|
24470
24765
|
} catch {
|
|
24471
24766
|
}
|
|
@@ -24476,15 +24771,15 @@ function walkPluginDirs(base, cb) {
|
|
|
24476
24771
|
for (const entry of fs46.readdirSync(base, { withFileTypes: true })) {
|
|
24477
24772
|
if (!entry.isDirectory()) continue;
|
|
24478
24773
|
if (entry.name.startsWith("@")) {
|
|
24479
|
-
const scopeDir =
|
|
24774
|
+
const scopeDir = path51.join(base, entry.name);
|
|
24480
24775
|
for (const sub of fs46.readdirSync(scopeDir, { withFileTypes: true })) {
|
|
24481
24776
|
if (!sub.isDirectory()) continue;
|
|
24482
24777
|
const pluginName = `${entry.name}/${sub.name}`;
|
|
24483
|
-
const settingsPath =
|
|
24778
|
+
const settingsPath = path51.join(scopeDir, sub.name, "settings.json");
|
|
24484
24779
|
if (fs46.existsSync(settingsPath)) cb(pluginName, settingsPath);
|
|
24485
24780
|
}
|
|
24486
24781
|
} else {
|
|
24487
|
-
const settingsPath =
|
|
24782
|
+
const settingsPath = path51.join(base, entry.name, "settings.json");
|
|
24488
24783
|
if (fs46.existsSync(settingsPath)) cb(entry.name, settingsPath);
|
|
24489
24784
|
}
|
|
24490
24785
|
}
|
|
@@ -24497,14 +24792,14 @@ var init_instance_copy = __esm({
|
|
|
24497
24792
|
|
|
24498
24793
|
// src/core/setup/git-protect.ts
|
|
24499
24794
|
import fs47 from "fs";
|
|
24500
|
-
import
|
|
24795
|
+
import path52 from "path";
|
|
24501
24796
|
function protectLocalInstance(projectDir) {
|
|
24502
24797
|
ensureGitignore(projectDir);
|
|
24503
24798
|
ensureClaudeMd(projectDir);
|
|
24504
24799
|
printSecurityWarning();
|
|
24505
24800
|
}
|
|
24506
24801
|
function ensureGitignore(projectDir) {
|
|
24507
|
-
const gitignorePath =
|
|
24802
|
+
const gitignorePath = path52.join(projectDir, ".gitignore");
|
|
24508
24803
|
const entry = ".openacp";
|
|
24509
24804
|
if (fs47.existsSync(gitignorePath)) {
|
|
24510
24805
|
const content = fs47.readFileSync(gitignorePath, "utf-8");
|
|
@@ -24524,7 +24819,7 @@ ${entry}
|
|
|
24524
24819
|
}
|
|
24525
24820
|
}
|
|
24526
24821
|
function ensureClaudeMd(projectDir) {
|
|
24527
|
-
const claudeMdPath =
|
|
24822
|
+
const claudeMdPath = path52.join(projectDir, "CLAUDE.md");
|
|
24528
24823
|
const marker = "## Local OpenACP Workspace";
|
|
24529
24824
|
if (fs47.existsSync(claudeMdPath)) {
|
|
24530
24825
|
const content = fs47.readFileSync(claudeMdPath, "utf-8");
|
|
@@ -24567,9 +24862,9 @@ var init_git_protect = __esm({
|
|
|
24567
24862
|
});
|
|
24568
24863
|
|
|
24569
24864
|
// src/core/setup/wizard.ts
|
|
24570
|
-
import * as
|
|
24865
|
+
import * as path53 from "path";
|
|
24571
24866
|
import * as fs48 from "fs";
|
|
24572
|
-
import * as
|
|
24867
|
+
import * as os25 from "os";
|
|
24573
24868
|
import * as clack8 from "@clack/prompts";
|
|
24574
24869
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
24575
24870
|
async function fetchCommunityAdapters() {
|
|
@@ -24591,7 +24886,7 @@ function checkDesktopAppInstalled() {
|
|
|
24591
24886
|
const platform2 = process.platform;
|
|
24592
24887
|
if (platform2 === "darwin") {
|
|
24593
24888
|
candidates.push("/Applications/OpenACP.app");
|
|
24594
|
-
candidates.push(`${
|
|
24889
|
+
candidates.push(`${os25.homedir()}/Applications/OpenACP.app`);
|
|
24595
24890
|
} else if (platform2 === "win32") {
|
|
24596
24891
|
const localAppData = process.env["LOCALAPPDATA"] ?? "";
|
|
24597
24892
|
candidates.push(`${localAppData}\\Programs\\OpenACP\\OpenACP.exe`);
|
|
@@ -24599,7 +24894,7 @@ function checkDesktopAppInstalled() {
|
|
|
24599
24894
|
} else {
|
|
24600
24895
|
candidates.push("/usr/bin/openacp-desktop");
|
|
24601
24896
|
candidates.push("/usr/local/bin/openacp-desktop");
|
|
24602
|
-
candidates.push(`${
|
|
24897
|
+
candidates.push(`${os25.homedir()}/.local/bin/openacp-desktop`);
|
|
24603
24898
|
}
|
|
24604
24899
|
return candidates.some((p2) => fs48.existsSync(p2));
|
|
24605
24900
|
}
|
|
@@ -24616,8 +24911,8 @@ async function runSetup(configManager, opts) {
|
|
|
24616
24911
|
const isGlobal = instanceRoot === getGlobalRoot();
|
|
24617
24912
|
let instanceName = opts?.instanceName;
|
|
24618
24913
|
if (!instanceName) {
|
|
24619
|
-
const defaultName = isGlobal ? "Global workspace" :
|
|
24620
|
-
const locationHint = isGlobal ? "global (~/.openacp)" : `local (${instanceRoot.replace(/\/.openacp$/, "").replace(
|
|
24914
|
+
const defaultName = isGlobal ? "Global workspace" : path53.basename(path53.dirname(instanceRoot));
|
|
24915
|
+
const locationHint = isGlobal ? "global (~/.openacp)" : `local (${instanceRoot.replace(/\/.openacp$/, "").replace(os25.homedir(), "~")})`;
|
|
24621
24916
|
const nameResult = await clack8.text({
|
|
24622
24917
|
message: `Name for this workspace (${locationHint})`,
|
|
24623
24918
|
initialValue: defaultName,
|
|
@@ -24627,13 +24922,13 @@ async function runSetup(configManager, opts) {
|
|
|
24627
24922
|
instanceName = nameResult.trim();
|
|
24628
24923
|
}
|
|
24629
24924
|
const globalRoot = getGlobalRoot();
|
|
24630
|
-
const registryPath =
|
|
24925
|
+
const registryPath = path53.join(globalRoot, "instances.json");
|
|
24631
24926
|
const instanceRegistry = new InstanceRegistry(registryPath);
|
|
24632
24927
|
await instanceRegistry.load();
|
|
24633
24928
|
let didCopy = false;
|
|
24634
24929
|
if (opts?.from) {
|
|
24635
|
-
const fromRoot =
|
|
24636
|
-
if (fs48.existsSync(
|
|
24930
|
+
const fromRoot = path53.join(opts.from, ".openacp");
|
|
24931
|
+
if (fs48.existsSync(path53.join(fromRoot, "config.json"))) {
|
|
24637
24932
|
const inheritableMap = buildInheritableKeysMap();
|
|
24638
24933
|
await copyInstance(fromRoot, instanceRoot, { inheritableKeys: inheritableMap });
|
|
24639
24934
|
didCopy = true;
|
|
@@ -24644,7 +24939,7 @@ async function runSetup(configManager, opts) {
|
|
|
24644
24939
|
}
|
|
24645
24940
|
if (!didCopy) {
|
|
24646
24941
|
const existingInstances = instanceRegistry.list().filter(
|
|
24647
|
-
(e) => fs48.existsSync(
|
|
24942
|
+
(e) => fs48.existsSync(path53.join(e.root, "config.json")) && e.root !== instanceRoot
|
|
24648
24943
|
);
|
|
24649
24944
|
if (existingInstances.length > 0) {
|
|
24650
24945
|
let singleLabel;
|
|
@@ -24652,12 +24947,12 @@ async function runSetup(configManager, opts) {
|
|
|
24652
24947
|
const e = existingInstances[0];
|
|
24653
24948
|
let name = e.id;
|
|
24654
24949
|
try {
|
|
24655
|
-
const cfg = JSON.parse(fs48.readFileSync(
|
|
24950
|
+
const cfg = JSON.parse(fs48.readFileSync(path53.join(e.root, "config.json"), "utf-8"));
|
|
24656
24951
|
if (cfg.instanceName) name = cfg.instanceName;
|
|
24657
24952
|
} catch {
|
|
24658
24953
|
}
|
|
24659
24954
|
const isGlobalEntry = e.root === getGlobalRoot();
|
|
24660
|
-
const displayPath = e.root.replace(
|
|
24955
|
+
const displayPath = e.root.replace(os25.homedir(), "~");
|
|
24661
24956
|
const type = isGlobalEntry ? "global" : "local";
|
|
24662
24957
|
singleLabel = `${name} workspace (${type} \u2014 ${displayPath})`;
|
|
24663
24958
|
}
|
|
@@ -24677,12 +24972,12 @@ async function runSetup(configManager, opts) {
|
|
|
24677
24972
|
options: existingInstances.map((e) => {
|
|
24678
24973
|
let name = e.id;
|
|
24679
24974
|
try {
|
|
24680
|
-
const cfg = JSON.parse(fs48.readFileSync(
|
|
24975
|
+
const cfg = JSON.parse(fs48.readFileSync(path53.join(e.root, "config.json"), "utf-8"));
|
|
24681
24976
|
if (cfg.instanceName) name = cfg.instanceName;
|
|
24682
24977
|
} catch {
|
|
24683
24978
|
}
|
|
24684
24979
|
const isGlobalEntry = e.root === getGlobalRoot();
|
|
24685
|
-
const displayPath = e.root.replace(
|
|
24980
|
+
const displayPath = e.root.replace(os25.homedir(), "~");
|
|
24686
24981
|
const type = isGlobalEntry ? "global" : "local";
|
|
24687
24982
|
return { value: e.root, label: `${name} workspace (${type} \u2014 ${displayPath})` };
|
|
24688
24983
|
})
|
|
@@ -24774,9 +25069,9 @@ async function runSetup(configManager, opts) {
|
|
|
24774
25069
|
if (channelId.startsWith("official:")) {
|
|
24775
25070
|
const npmPackage = channelId.slice("official:".length);
|
|
24776
25071
|
const { execFileSync: execFileSync8 } = await import("child_process");
|
|
24777
|
-
const pluginsDir =
|
|
24778
|
-
const nodeModulesDir =
|
|
24779
|
-
const installedPath =
|
|
25072
|
+
const pluginsDir = path53.join(instanceRoot, "plugins");
|
|
25073
|
+
const nodeModulesDir = path53.join(pluginsDir, "node_modules");
|
|
25074
|
+
const installedPath = path53.join(nodeModulesDir, npmPackage);
|
|
24780
25075
|
if (!fs48.existsSync(installedPath)) {
|
|
24781
25076
|
try {
|
|
24782
25077
|
clack8.log.step(`Installing ${npmPackage}...`);
|
|
@@ -24790,9 +25085,9 @@ async function runSetup(configManager, opts) {
|
|
|
24790
25085
|
}
|
|
24791
25086
|
}
|
|
24792
25087
|
try {
|
|
24793
|
-
const installedPkgPath =
|
|
25088
|
+
const installedPkgPath = path53.join(nodeModulesDir, npmPackage, "package.json");
|
|
24794
25089
|
const installedPkg = JSON.parse(fs48.readFileSync(installedPkgPath, "utf-8"));
|
|
24795
|
-
const pluginModule = await import(
|
|
25090
|
+
const pluginModule = await import(path53.join(nodeModulesDir, npmPackage, installedPkg.main ?? "dist/index.js"));
|
|
24796
25091
|
const plugin2 = pluginModule.default;
|
|
24797
25092
|
if (plugin2?.install) {
|
|
24798
25093
|
const installCtx = createInstallContext2({
|
|
@@ -24822,8 +25117,8 @@ async function runSetup(configManager, opts) {
|
|
|
24822
25117
|
if (channelId.startsWith("community:")) {
|
|
24823
25118
|
const npmPackage = channelId.slice("community:".length);
|
|
24824
25119
|
const { execFileSync: execFileSync8 } = await import("child_process");
|
|
24825
|
-
const pluginsDir =
|
|
24826
|
-
const nodeModulesDir =
|
|
25120
|
+
const pluginsDir = path53.join(instanceRoot, "plugins");
|
|
25121
|
+
const nodeModulesDir = path53.join(pluginsDir, "node_modules");
|
|
24827
25122
|
try {
|
|
24828
25123
|
execFileSync8("npm", ["install", npmPackage, "--prefix", pluginsDir, "--save"], {
|
|
24829
25124
|
stdio: "inherit",
|
|
@@ -24835,9 +25130,9 @@ async function runSetup(configManager, opts) {
|
|
|
24835
25130
|
}
|
|
24836
25131
|
try {
|
|
24837
25132
|
const { readFileSync: readFileSync19 } = await import("fs");
|
|
24838
|
-
const installedPkgPath =
|
|
25133
|
+
const installedPkgPath = path53.join(nodeModulesDir, npmPackage, "package.json");
|
|
24839
25134
|
const installedPkg = JSON.parse(readFileSync19(installedPkgPath, "utf-8"));
|
|
24840
|
-
const pluginModule = await import(
|
|
25135
|
+
const pluginModule = await import(path53.join(nodeModulesDir, npmPackage, installedPkg.main ?? "dist/index.js"));
|
|
24841
25136
|
const plugin2 = pluginModule.default;
|
|
24842
25137
|
if (plugin2?.install) {
|
|
24843
25138
|
const installCtx = createInstallContext2({
|
|
@@ -24892,7 +25187,7 @@ async function runSetup(configManager, opts) {
|
|
|
24892
25187
|
security,
|
|
24893
25188
|
logging: {
|
|
24894
25189
|
level: "info",
|
|
24895
|
-
logDir:
|
|
25190
|
+
logDir: path53.join(instanceRoot, "logs"),
|
|
24896
25191
|
maxFileSize: "10m",
|
|
24897
25192
|
maxFiles: 7,
|
|
24898
25193
|
sessionLogRetentionDays: 30
|
|
@@ -24944,9 +25239,9 @@ async function runSetup(configManager, opts) {
|
|
|
24944
25239
|
instanceRegistry.register(id, instanceRoot);
|
|
24945
25240
|
await instanceRegistry.save();
|
|
24946
25241
|
}
|
|
24947
|
-
const isLocal = instanceRoot !==
|
|
25242
|
+
const isLocal = instanceRoot !== path53.join(getGlobalRoot());
|
|
24948
25243
|
if (isLocal) {
|
|
24949
|
-
const projectDir =
|
|
25244
|
+
const projectDir = path53.dirname(instanceRoot);
|
|
24950
25245
|
protectLocalInstance(projectDir);
|
|
24951
25246
|
}
|
|
24952
25247
|
clack8.outro(`Config saved to ${configManager.getConfigPath()}`);
|
|
@@ -25234,7 +25529,7 @@ __export(dev_loader_exports, {
|
|
|
25234
25529
|
DevPluginLoader: () => DevPluginLoader
|
|
25235
25530
|
});
|
|
25236
25531
|
import fs49 from "fs";
|
|
25237
|
-
import
|
|
25532
|
+
import path54 from "path";
|
|
25238
25533
|
var loadCounter, DevPluginLoader;
|
|
25239
25534
|
var init_dev_loader = __esm({
|
|
25240
25535
|
"src/core/plugin/dev-loader.ts"() {
|
|
@@ -25243,11 +25538,11 @@ var init_dev_loader = __esm({
|
|
|
25243
25538
|
DevPluginLoader = class {
|
|
25244
25539
|
pluginPath;
|
|
25245
25540
|
constructor(pluginPath) {
|
|
25246
|
-
this.pluginPath =
|
|
25541
|
+
this.pluginPath = path54.resolve(pluginPath);
|
|
25247
25542
|
}
|
|
25248
25543
|
async load() {
|
|
25249
|
-
const distIndex =
|
|
25250
|
-
const srcIndex =
|
|
25544
|
+
const distIndex = path54.join(this.pluginPath, "dist", "index.js");
|
|
25545
|
+
const srcIndex = path54.join(this.pluginPath, "src", "index.ts");
|
|
25251
25546
|
if (!fs49.existsSync(distIndex) && !fs49.existsSync(srcIndex)) {
|
|
25252
25547
|
throw new Error(`Plugin not found at ${this.pluginPath}. Expected dist/index.js or src/index.ts`);
|
|
25253
25548
|
}
|
|
@@ -25266,7 +25561,7 @@ var init_dev_loader = __esm({
|
|
|
25266
25561
|
return this.pluginPath;
|
|
25267
25562
|
}
|
|
25268
25563
|
getDistPath() {
|
|
25269
|
-
return
|
|
25564
|
+
return path54.join(this.pluginPath, "dist");
|
|
25270
25565
|
}
|
|
25271
25566
|
};
|
|
25272
25567
|
}
|
|
@@ -25278,13 +25573,13 @@ __export(main_exports, {
|
|
|
25278
25573
|
RESTART_EXIT_CODE: () => RESTART_EXIT_CODE,
|
|
25279
25574
|
startServer: () => startServer
|
|
25280
25575
|
});
|
|
25281
|
-
import
|
|
25576
|
+
import path55 from "path";
|
|
25282
25577
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
25283
25578
|
import fs50 from "fs";
|
|
25284
25579
|
async function startServer(opts) {
|
|
25285
25580
|
const globalRoot = getGlobalRoot();
|
|
25286
25581
|
if (!opts?.instanceContext) {
|
|
25287
|
-
const reg = new InstanceRegistry(
|
|
25582
|
+
const reg = new InstanceRegistry(path55.join(globalRoot, "instances.json"));
|
|
25288
25583
|
reg.load();
|
|
25289
25584
|
const entry = reg.getByRoot(globalRoot);
|
|
25290
25585
|
opts = { ...opts, instanceContext: createInstanceContext({ id: entry?.id ?? randomUUID3(), root: globalRoot, isGlobal: true }) };
|
|
@@ -25325,6 +25620,7 @@ async function startServer(opts) {
|
|
|
25325
25620
|
const config = configManager.get();
|
|
25326
25621
|
initLogger(config.logging);
|
|
25327
25622
|
log.debug({ configPath: configManager.getConfigPath() }, "Config loaded");
|
|
25623
|
+
await configManager.applyEnvToPluginSettings(settingsManager);
|
|
25328
25624
|
if (pluginRegistry.list().size === 0) {
|
|
25329
25625
|
await autoRegisterBuiltinPlugins(settingsManager, pluginRegistry, configManager);
|
|
25330
25626
|
}
|
|
@@ -25368,22 +25664,22 @@ async function startServer(opts) {
|
|
|
25368
25664
|
try {
|
|
25369
25665
|
let modulePath;
|
|
25370
25666
|
if (name.startsWith("/") || name.startsWith(".")) {
|
|
25371
|
-
const resolved =
|
|
25372
|
-
const pkgPath =
|
|
25667
|
+
const resolved = path55.resolve(name);
|
|
25668
|
+
const pkgPath = path55.join(resolved, "package.json");
|
|
25373
25669
|
const pkg = JSON.parse(await fs50.promises.readFile(pkgPath, "utf-8"));
|
|
25374
|
-
modulePath =
|
|
25670
|
+
modulePath = path55.join(resolved, pkg.main || "dist/index.js");
|
|
25375
25671
|
} else {
|
|
25376
|
-
const nodeModulesDir =
|
|
25377
|
-
let pkgDir =
|
|
25378
|
-
if (!fs50.existsSync(
|
|
25672
|
+
const nodeModulesDir = path55.join(ctx.paths.plugins, "node_modules");
|
|
25673
|
+
let pkgDir = path55.join(nodeModulesDir, name);
|
|
25674
|
+
if (!fs50.existsSync(path55.join(pkgDir, "package.json"))) {
|
|
25379
25675
|
let found = false;
|
|
25380
25676
|
const scopes = fs50.existsSync(nodeModulesDir) ? fs50.readdirSync(nodeModulesDir).filter((d) => d.startsWith("@")) : [];
|
|
25381
25677
|
for (const scope of scopes) {
|
|
25382
|
-
const scopeDir =
|
|
25678
|
+
const scopeDir = path55.join(nodeModulesDir, scope);
|
|
25383
25679
|
const pkgs = fs50.readdirSync(scopeDir);
|
|
25384
25680
|
for (const pkg2 of pkgs) {
|
|
25385
|
-
const candidateDir =
|
|
25386
|
-
const candidatePkgPath =
|
|
25681
|
+
const candidateDir = path55.join(scopeDir, pkg2);
|
|
25682
|
+
const candidatePkgPath = path55.join(candidateDir, "package.json");
|
|
25387
25683
|
if (fs50.existsSync(candidatePkgPath)) {
|
|
25388
25684
|
try {
|
|
25389
25685
|
const candidatePkg = JSON.parse(fs50.readFileSync(candidatePkgPath, "utf-8"));
|
|
@@ -25400,9 +25696,9 @@ async function startServer(opts) {
|
|
|
25400
25696
|
if (found) break;
|
|
25401
25697
|
}
|
|
25402
25698
|
}
|
|
25403
|
-
const pkgJsonPath =
|
|
25699
|
+
const pkgJsonPath = path55.join(pkgDir, "package.json");
|
|
25404
25700
|
const pkg = JSON.parse(await fs50.promises.readFile(pkgJsonPath, "utf-8"));
|
|
25405
|
-
modulePath =
|
|
25701
|
+
modulePath = path55.join(pkgDir, pkg.main || "dist/index.js");
|
|
25406
25702
|
}
|
|
25407
25703
|
log.debug({ plugin: name, modulePath }, "Loading community plugin");
|
|
25408
25704
|
const mod = await import(modulePath);
|
|
@@ -25565,7 +25861,7 @@ async function startServer(opts) {
|
|
|
25565
25861
|
await core.start();
|
|
25566
25862
|
try {
|
|
25567
25863
|
const globalRoot2 = getGlobalRoot();
|
|
25568
|
-
const registryPath =
|
|
25864
|
+
const registryPath = path55.join(globalRoot2, "instances.json");
|
|
25569
25865
|
const instanceReg = new InstanceRegistry(registryPath);
|
|
25570
25866
|
await instanceReg.load();
|
|
25571
25867
|
if (!instanceReg.getByRoot(ctx.root)) {
|
|
@@ -25728,13 +26024,13 @@ var restart_exports = {};
|
|
|
25728
26024
|
__export(restart_exports, {
|
|
25729
26025
|
cmdRestart: () => cmdRestart
|
|
25730
26026
|
});
|
|
25731
|
-
import
|
|
25732
|
-
import
|
|
26027
|
+
import path56 from "path";
|
|
26028
|
+
import os26 from "os";
|
|
25733
26029
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
25734
26030
|
async function cmdRestart(args2 = [], instanceRoot) {
|
|
25735
26031
|
const json = isJsonMode(args2);
|
|
25736
26032
|
if (json) await muteForJson();
|
|
25737
|
-
const root = instanceRoot ??
|
|
26033
|
+
const root = instanceRoot ?? path56.join(os26.homedir(), ".openacp");
|
|
25738
26034
|
if (!json && wantsHelp(args2)) {
|
|
25739
26035
|
console.log(`
|
|
25740
26036
|
\x1B[1mopenacp restart\x1B[0m \u2014 Restart the background daemon
|
|
@@ -25782,7 +26078,7 @@ Stops the running daemon (if any) and starts a new one.
|
|
|
25782
26078
|
printInstanceHint(root);
|
|
25783
26079
|
console.log("Starting in foreground mode...");
|
|
25784
26080
|
const { startServer: startServer2 } = await Promise.resolve().then(() => (init_main(), main_exports));
|
|
25785
|
-
const reg = new InstanceRegistry(
|
|
26081
|
+
const reg = new InstanceRegistry(path56.join(getGlobalRoot(), "instances.json"));
|
|
25786
26082
|
reg.load();
|
|
25787
26083
|
const existingEntry = reg.getByRoot(root);
|
|
25788
26084
|
const ctx = createInstanceContext({
|
|
@@ -25798,7 +26094,7 @@ Stops the running daemon (if any) and starts a new one.
|
|
|
25798
26094
|
console.error(result.error);
|
|
25799
26095
|
process.exit(1);
|
|
25800
26096
|
}
|
|
25801
|
-
if (json) jsonSuccess({ pid: result.pid, instanceId:
|
|
26097
|
+
if (json) jsonSuccess({ pid: result.pid, instanceId: path56.basename(root), dir: root });
|
|
25802
26098
|
printInstanceHint(root);
|
|
25803
26099
|
console.log(`OpenACP daemon started (PID ${result.pid})`);
|
|
25804
26100
|
}
|
|
@@ -25822,8 +26118,8 @@ __export(status_exports, {
|
|
|
25822
26118
|
readInstanceInfo: () => readInstanceInfo
|
|
25823
26119
|
});
|
|
25824
26120
|
import fs51 from "fs";
|
|
25825
|
-
import
|
|
25826
|
-
import
|
|
26121
|
+
import path57 from "path";
|
|
26122
|
+
import os27 from "os";
|
|
25827
26123
|
async function cmdStatus(args2 = [], instanceRoot) {
|
|
25828
26124
|
const json = isJsonMode(args2);
|
|
25829
26125
|
if (json) await muteForJson();
|
|
@@ -25840,7 +26136,7 @@ async function cmdStatus(args2 = [], instanceRoot) {
|
|
|
25840
26136
|
await showSingleInstance(root, json);
|
|
25841
26137
|
}
|
|
25842
26138
|
async function showAllInstances(json = false) {
|
|
25843
|
-
const registryPath =
|
|
26139
|
+
const registryPath = path57.join(getGlobalRoot(), "instances.json");
|
|
25844
26140
|
const registry = new InstanceRegistry(registryPath);
|
|
25845
26141
|
await registry.load();
|
|
25846
26142
|
const instances = registry.list();
|
|
@@ -25875,7 +26171,7 @@ async function showAllInstances(json = false) {
|
|
|
25875
26171
|
const mode = info.pid ? info.runMode === "daemon" ? "daemon" : "fg" : "\u2014";
|
|
25876
26172
|
const api = info.apiPort ? String(info.apiPort) : "\u2014";
|
|
25877
26173
|
const tunnel = info.tunnelPort ? String(info.tunnelPort) : "\u2014";
|
|
25878
|
-
const dir = entry.root.replace(/\/.openacp$/, "").replace(
|
|
26174
|
+
const dir = entry.root.replace(/\/.openacp$/, "").replace(os27.homedir(), "~");
|
|
25879
26175
|
const channels = info.channels.join(", ") || "\u2014";
|
|
25880
26176
|
const name = info.name ?? entry.id;
|
|
25881
26177
|
console.log(` ${status.padEnd(10)} ${entry.id.padEnd(16)} ${name.padEnd(16)} ${dir.padEnd(20)} ${mode.padEnd(8)} ${channels.padEnd(10)} ${api.padEnd(6)} ${tunnel}`);
|
|
@@ -25883,7 +26179,7 @@ async function showAllInstances(json = false) {
|
|
|
25883
26179
|
console.log("");
|
|
25884
26180
|
}
|
|
25885
26181
|
async function showInstanceById(id, json = false) {
|
|
25886
|
-
const registryPath =
|
|
26182
|
+
const registryPath = path57.join(getGlobalRoot(), "instances.json");
|
|
25887
26183
|
const registry = new InstanceRegistry(registryPath);
|
|
25888
26184
|
await registry.load();
|
|
25889
26185
|
const entry = registry.get(id);
|
|
@@ -25898,7 +26194,7 @@ async function showSingleInstance(root, json = false) {
|
|
|
25898
26194
|
const info = readInstanceInfo(root);
|
|
25899
26195
|
if (json) {
|
|
25900
26196
|
jsonSuccess({
|
|
25901
|
-
id:
|
|
26197
|
+
id: path57.basename(root),
|
|
25902
26198
|
name: info.name,
|
|
25903
26199
|
status: info.pid ? "online" : "offline",
|
|
25904
26200
|
pid: info.pid,
|
|
@@ -25929,13 +26225,13 @@ function readInstanceInfo(root) {
|
|
|
25929
26225
|
channels: []
|
|
25930
26226
|
};
|
|
25931
26227
|
try {
|
|
25932
|
-
const config = JSON.parse(fs51.readFileSync(
|
|
26228
|
+
const config = JSON.parse(fs51.readFileSync(path57.join(root, "config.json"), "utf-8"));
|
|
25933
26229
|
result.name = config.instanceName ?? null;
|
|
25934
26230
|
result.runMode = config.runMode ?? null;
|
|
25935
26231
|
} catch {
|
|
25936
26232
|
}
|
|
25937
26233
|
try {
|
|
25938
|
-
const pid = parseInt(fs51.readFileSync(
|
|
26234
|
+
const pid = parseInt(fs51.readFileSync(path57.join(root, "openacp.pid"), "utf-8").trim());
|
|
25939
26235
|
if (!isNaN(pid)) {
|
|
25940
26236
|
process.kill(pid, 0);
|
|
25941
26237
|
result.pid = pid;
|
|
@@ -25943,19 +26239,19 @@ function readInstanceInfo(root) {
|
|
|
25943
26239
|
} catch {
|
|
25944
26240
|
}
|
|
25945
26241
|
try {
|
|
25946
|
-
const port = parseInt(fs51.readFileSync(
|
|
26242
|
+
const port = parseInt(fs51.readFileSync(path57.join(root, "api.port"), "utf-8").trim());
|
|
25947
26243
|
if (!isNaN(port)) result.apiPort = port;
|
|
25948
26244
|
} catch {
|
|
25949
26245
|
}
|
|
25950
26246
|
try {
|
|
25951
|
-
const tunnels = JSON.parse(fs51.readFileSync(
|
|
26247
|
+
const tunnels = JSON.parse(fs51.readFileSync(path57.join(root, "tunnels.json"), "utf-8"));
|
|
25952
26248
|
const entries = Object.values(tunnels);
|
|
25953
26249
|
const systemEntry = entries.find((t) => t.type === "system");
|
|
25954
26250
|
if (systemEntry?.port) result.tunnelPort = systemEntry.port;
|
|
25955
26251
|
} catch {
|
|
25956
26252
|
}
|
|
25957
26253
|
try {
|
|
25958
|
-
const plugins = JSON.parse(fs51.readFileSync(
|
|
26254
|
+
const plugins = JSON.parse(fs51.readFileSync(path57.join(root, "plugins.json"), "utf-8"));
|
|
25959
26255
|
const adapters = ["@openacp/telegram", "@openacp/discord", "@openacp/slack"];
|
|
25960
26256
|
for (const name of adapters) {
|
|
25961
26257
|
if (plugins.installed?.[name] && plugins.installed[name].enabled !== false) {
|
|
@@ -25970,7 +26266,7 @@ function formatInstanceStatus(root) {
|
|
|
25970
26266
|
const info = readInstanceInfo(root);
|
|
25971
26267
|
if (!info.pid) return null;
|
|
25972
26268
|
const isGlobal = root === getGlobalRoot();
|
|
25973
|
-
const displayPath = root.replace(
|
|
26269
|
+
const displayPath = root.replace(os27.homedir(), "~");
|
|
25974
26270
|
const label = isGlobal ? "global" : "local";
|
|
25975
26271
|
const lines = [];
|
|
25976
26272
|
lines.push(` PID: ${info.pid}`);
|
|
@@ -26039,7 +26335,7 @@ var config_editor_exports = {};
|
|
|
26039
26335
|
__export(config_editor_exports, {
|
|
26040
26336
|
runConfigEditor: () => runConfigEditor
|
|
26041
26337
|
});
|
|
26042
|
-
import * as
|
|
26338
|
+
import * as path58 from "path";
|
|
26043
26339
|
import * as clack9 from "@clack/prompts";
|
|
26044
26340
|
async function select8(opts) {
|
|
26045
26341
|
const result = await clack9.select({
|
|
@@ -26070,11 +26366,19 @@ async function input(opts) {
|
|
|
26070
26366
|
}
|
|
26071
26367
|
return result;
|
|
26072
26368
|
}
|
|
26073
|
-
async function editTelegram(config, updates) {
|
|
26369
|
+
async function editTelegram(config, updates, settingsManager) {
|
|
26074
26370
|
const tg = config.channels?.telegram ?? {};
|
|
26075
|
-
|
|
26076
|
-
|
|
26077
|
-
|
|
26371
|
+
let currentToken = tg.botToken ?? "";
|
|
26372
|
+
let currentChatId = tg.chatId ?? 0;
|
|
26373
|
+
let currentEnabled = tg.enabled ?? false;
|
|
26374
|
+
if (settingsManager) {
|
|
26375
|
+
const ps = await settingsManager.loadSettings("@openacp/telegram");
|
|
26376
|
+
if (Object.keys(ps).length > 0) {
|
|
26377
|
+
currentToken = ps.botToken ?? currentToken;
|
|
26378
|
+
currentChatId = ps.chatId ?? currentChatId;
|
|
26379
|
+
currentEnabled = ps.enabled ?? currentEnabled;
|
|
26380
|
+
}
|
|
26381
|
+
}
|
|
26078
26382
|
console.log(header("Telegram"));
|
|
26079
26383
|
console.log(` Enabled : ${currentEnabled ? ok2("yes") : dim2("no")}`);
|
|
26080
26384
|
const tokenDisplay = currentToken.length > 12 ? currentToken.slice(0, 6) + "..." + currentToken.slice(-6) : currentToken || dim2("(not set)");
|
|
@@ -26089,7 +26393,11 @@ async function editTelegram(config, updates) {
|
|
|
26089
26393
|
return updates.channels.telegram;
|
|
26090
26394
|
};
|
|
26091
26395
|
while (true) {
|
|
26092
|
-
const isEnabled = (() => {
|
|
26396
|
+
const isEnabled = await (async () => {
|
|
26397
|
+
if (settingsManager) {
|
|
26398
|
+
const ps = await settingsManager.loadSettings("@openacp/telegram");
|
|
26399
|
+
if ("enabled" in ps) return ps.enabled;
|
|
26400
|
+
}
|
|
26093
26401
|
const ch = updates.channels;
|
|
26094
26402
|
const tgUp = ch?.telegram;
|
|
26095
26403
|
if (tgUp && "enabled" in tgUp) return tgUp.enabled;
|
|
@@ -26106,8 +26414,12 @@ async function editTelegram(config, updates) {
|
|
|
26106
26414
|
});
|
|
26107
26415
|
if (choice === "back") break;
|
|
26108
26416
|
if (choice === "toggle") {
|
|
26109
|
-
|
|
26110
|
-
|
|
26417
|
+
if (settingsManager) {
|
|
26418
|
+
await settingsManager.updatePluginSettings("@openacp/telegram", { enabled: !isEnabled });
|
|
26419
|
+
} else {
|
|
26420
|
+
const tgUp = ensureTelegramUpdates();
|
|
26421
|
+
tgUp.enabled = !isEnabled;
|
|
26422
|
+
}
|
|
26111
26423
|
console.log(!isEnabled ? ok2("Telegram enabled") : ok2("Telegram disabled"));
|
|
26112
26424
|
}
|
|
26113
26425
|
if (choice === "token") {
|
|
@@ -26127,9 +26439,13 @@ async function editTelegram(config, updates) {
|
|
|
26127
26439
|
} catch {
|
|
26128
26440
|
console.log(warn2("Telegram validator not available \u2014 skipping validation"));
|
|
26129
26441
|
}
|
|
26130
|
-
|
|
26131
|
-
|
|
26132
|
-
|
|
26442
|
+
if (settingsManager) {
|
|
26443
|
+
await settingsManager.updatePluginSettings("@openacp/telegram", { botToken: token.trim(), enabled: true });
|
|
26444
|
+
} else {
|
|
26445
|
+
const tgUp = ensureTelegramUpdates();
|
|
26446
|
+
tgUp.botToken = token.trim();
|
|
26447
|
+
tgUp.enabled = true;
|
|
26448
|
+
}
|
|
26133
26449
|
}
|
|
26134
26450
|
if (choice === "chatid") {
|
|
26135
26451
|
const chatIdStr = await input({
|
|
@@ -26144,8 +26460,8 @@ async function editTelegram(config, updates) {
|
|
|
26144
26460
|
const chatId = Number(chatIdStr.trim());
|
|
26145
26461
|
const tokenForValidation = (() => {
|
|
26146
26462
|
const ch = updates.channels;
|
|
26147
|
-
const
|
|
26148
|
-
if (typeof
|
|
26463
|
+
const tgUp = ch?.telegram;
|
|
26464
|
+
if (typeof tgUp?.botToken === "string") return tgUp.botToken;
|
|
26149
26465
|
return currentToken;
|
|
26150
26466
|
})();
|
|
26151
26467
|
try {
|
|
@@ -26159,8 +26475,12 @@ async function editTelegram(config, updates) {
|
|
|
26159
26475
|
} catch {
|
|
26160
26476
|
console.log(warn2("Telegram validator not available \u2014 skipping validation"));
|
|
26161
26477
|
}
|
|
26162
|
-
|
|
26163
|
-
|
|
26478
|
+
if (settingsManager) {
|
|
26479
|
+
await settingsManager.updatePluginSettings("@openacp/telegram", { chatId });
|
|
26480
|
+
} else {
|
|
26481
|
+
const tgUp = ensureTelegramUpdates();
|
|
26482
|
+
tgUp.chatId = chatId;
|
|
26483
|
+
}
|
|
26164
26484
|
}
|
|
26165
26485
|
}
|
|
26166
26486
|
}
|
|
@@ -26200,7 +26520,7 @@ async function editDiscord(_config, _updates) {
|
|
|
26200
26520
|
const { createInstallContext: createInstallContext2 } = await Promise.resolve().then(() => (init_install_context(), install_context_exports));
|
|
26201
26521
|
const { getGlobalRoot: getGlobalRoot2 } = await Promise.resolve().then(() => (init_instance_context(), instance_context_exports));
|
|
26202
26522
|
const root = getGlobalRoot2();
|
|
26203
|
-
const basePath =
|
|
26523
|
+
const basePath = path58.join(root, "plugins");
|
|
26204
26524
|
const settingsManager = new SettingsManager2(basePath);
|
|
26205
26525
|
const ctx = createInstallContext2({
|
|
26206
26526
|
pluginName: plugin2.name,
|
|
@@ -26213,7 +26533,7 @@ async function editDiscord(_config, _updates) {
|
|
|
26213
26533
|
console.log(warn2("This plugin does not have a configure() method yet."));
|
|
26214
26534
|
}
|
|
26215
26535
|
}
|
|
26216
|
-
async function editChannels(config, updates) {
|
|
26536
|
+
async function editChannels(config, updates, settingsManager) {
|
|
26217
26537
|
const tgEnabled = config.channels?.telegram?.enabled !== false && config.channels?.telegram;
|
|
26218
26538
|
const dcEnabled = config.channels?.discord?.enabled !== false && config.channels?.discord;
|
|
26219
26539
|
console.log(header("Channels"));
|
|
@@ -26230,7 +26550,7 @@ async function editChannels(config, updates) {
|
|
|
26230
26550
|
]
|
|
26231
26551
|
});
|
|
26232
26552
|
if (choice === "back") break;
|
|
26233
|
-
if (choice === "telegram") await editTelegram(config, updates);
|
|
26553
|
+
if (choice === "telegram") await editTelegram(config, updates, settingsManager);
|
|
26234
26554
|
if (choice === "discord") await editDiscord(config, updates);
|
|
26235
26555
|
}
|
|
26236
26556
|
}
|
|
@@ -26277,8 +26597,18 @@ async function editWorkspace(config, updates) {
|
|
|
26277
26597
|
updates.workspace = { baseDir: newDir.trim() };
|
|
26278
26598
|
console.log(ok2(`Workspace set to ${newDir.trim()}`));
|
|
26279
26599
|
}
|
|
26280
|
-
async function editSecurity(config, updates) {
|
|
26281
|
-
|
|
26600
|
+
async function editSecurity(config, updates, settingsManager) {
|
|
26601
|
+
let sec = config.security ?? { allowedUserIds: [], maxConcurrentSessions: 20, sessionTimeoutMinutes: 60 };
|
|
26602
|
+
if (settingsManager) {
|
|
26603
|
+
const ps = await settingsManager.loadSettings("@openacp/security");
|
|
26604
|
+
if (Object.keys(ps).length > 0) {
|
|
26605
|
+
sec = {
|
|
26606
|
+
allowedUserIds: ps.allowedUserIds ?? sec.allowedUserIds,
|
|
26607
|
+
maxConcurrentSessions: ps.maxConcurrentSessions ?? sec.maxConcurrentSessions,
|
|
26608
|
+
sessionTimeoutMinutes: ps.sessionTimeoutMinutes ?? sec.sessionTimeoutMinutes
|
|
26609
|
+
};
|
|
26610
|
+
}
|
|
26611
|
+
}
|
|
26282
26612
|
console.log(header("Security"));
|
|
26283
26613
|
console.log(` Allowed user IDs : ${sec.allowedUserIds?.length ? sec.allowedUserIds.join(", ") : dim2("(all users allowed)")}`);
|
|
26284
26614
|
console.log(` Max concurrent sessions : ${sec.maxConcurrentSessions}`);
|
|
@@ -26304,8 +26634,12 @@ async function editSecurity(config, updates) {
|
|
|
26304
26634
|
return true;
|
|
26305
26635
|
}
|
|
26306
26636
|
});
|
|
26307
|
-
if (
|
|
26308
|
-
|
|
26637
|
+
if (settingsManager) {
|
|
26638
|
+
await settingsManager.updatePluginSettings("@openacp/security", { maxConcurrentSessions: Number(val.trim()) });
|
|
26639
|
+
} else {
|
|
26640
|
+
if (!updates.security) updates.security = {};
|
|
26641
|
+
updates.security.maxConcurrentSessions = Number(val.trim());
|
|
26642
|
+
}
|
|
26309
26643
|
console.log(ok2(`Max concurrent sessions set to ${val.trim()}`));
|
|
26310
26644
|
}
|
|
26311
26645
|
if (choice === "timeout") {
|
|
@@ -26318,8 +26652,12 @@ async function editSecurity(config, updates) {
|
|
|
26318
26652
|
return true;
|
|
26319
26653
|
}
|
|
26320
26654
|
});
|
|
26321
|
-
if (
|
|
26322
|
-
|
|
26655
|
+
if (settingsManager) {
|
|
26656
|
+
await settingsManager.updatePluginSettings("@openacp/security", { sessionTimeoutMinutes: Number(val.trim()) });
|
|
26657
|
+
} else {
|
|
26658
|
+
if (!updates.security) updates.security = {};
|
|
26659
|
+
updates.security.sessionTimeoutMinutes = Number(val.trim());
|
|
26660
|
+
}
|
|
26323
26661
|
console.log(ok2(`Session timeout set to ${val.trim()} minutes`));
|
|
26324
26662
|
}
|
|
26325
26663
|
}
|
|
@@ -26444,8 +26782,14 @@ async function editRunMode(config, updates) {
|
|
|
26444
26782
|
}
|
|
26445
26783
|
}
|
|
26446
26784
|
}
|
|
26447
|
-
async function editApi(config, updates) {
|
|
26448
|
-
|
|
26785
|
+
async function editApi(config, updates, settingsManager) {
|
|
26786
|
+
let api = config.api ?? { port: 21420, host: "127.0.0.1" };
|
|
26787
|
+
if (settingsManager) {
|
|
26788
|
+
const ps = await settingsManager.loadSettings("@openacp/api-server");
|
|
26789
|
+
if (Object.keys(ps).length > 0) {
|
|
26790
|
+
api = { port: ps.port ?? api.port, host: ps.host ?? api.host };
|
|
26791
|
+
}
|
|
26792
|
+
}
|
|
26449
26793
|
console.log(header("API"));
|
|
26450
26794
|
console.log(` Port : ${api.port}`);
|
|
26451
26795
|
console.log(` Host : ${api.host} ${dim2("(localhost only)")}`);
|
|
@@ -26459,11 +26803,21 @@ async function editApi(config, updates) {
|
|
|
26459
26803
|
return true;
|
|
26460
26804
|
}
|
|
26461
26805
|
});
|
|
26462
|
-
|
|
26806
|
+
if (settingsManager) {
|
|
26807
|
+
await settingsManager.updatePluginSettings("@openacp/api-server", { port: Number(newPort.trim()) });
|
|
26808
|
+
} else {
|
|
26809
|
+
updates.api = { port: Number(newPort.trim()) };
|
|
26810
|
+
}
|
|
26463
26811
|
console.log(ok2(`API port set to ${newPort.trim()}`));
|
|
26464
26812
|
}
|
|
26465
|
-
async function editTunnel(config, updates) {
|
|
26466
|
-
|
|
26813
|
+
async function editTunnel(config, updates, settingsManager) {
|
|
26814
|
+
let tunnel = config.tunnel ?? { enabled: false, port: 3100, provider: "cloudflare", options: {}, storeTtlMinutes: 60, auth: { enabled: false } };
|
|
26815
|
+
if (settingsManager) {
|
|
26816
|
+
const ps = await settingsManager.loadSettings("@openacp/tunnel");
|
|
26817
|
+
if (Object.keys(ps).length > 0) {
|
|
26818
|
+
tunnel = { ...tunnel, ...ps };
|
|
26819
|
+
}
|
|
26820
|
+
}
|
|
26467
26821
|
const currentUpdates = updates.tunnel ?? {};
|
|
26468
26822
|
const getVal = (key, fallback) => key in currentUpdates ? currentUpdates[key] : tunnel[key] ?? fallback;
|
|
26469
26823
|
console.log(header("Tunnel"));
|
|
@@ -26490,6 +26844,9 @@ async function editTunnel(config, updates) {
|
|
|
26490
26844
|
const tun = updates.tunnel;
|
|
26491
26845
|
if (choice === "toggle") {
|
|
26492
26846
|
const current = getVal("enabled", false);
|
|
26847
|
+
if (settingsManager) {
|
|
26848
|
+
await settingsManager.updatePluginSettings("@openacp/tunnel", { enabled: !current });
|
|
26849
|
+
}
|
|
26493
26850
|
tun.enabled = !current;
|
|
26494
26851
|
console.log(!current ? ok2("Tunnel enabled") : ok2("Tunnel disabled"));
|
|
26495
26852
|
}
|
|
@@ -26503,6 +26860,9 @@ async function editTunnel(config, updates) {
|
|
|
26503
26860
|
{ name: "Tailscale Funnel", value: "tailscale" }
|
|
26504
26861
|
]
|
|
26505
26862
|
});
|
|
26863
|
+
if (settingsManager) {
|
|
26864
|
+
await settingsManager.updatePluginSettings("@openacp/tunnel", { provider, options: {} });
|
|
26865
|
+
}
|
|
26506
26866
|
tun.provider = provider;
|
|
26507
26867
|
tun.options = {};
|
|
26508
26868
|
console.log(ok2(`Provider set to ${provider}`));
|
|
@@ -26517,6 +26877,9 @@ async function editTunnel(config, updates) {
|
|
|
26517
26877
|
return true;
|
|
26518
26878
|
}
|
|
26519
26879
|
});
|
|
26880
|
+
if (settingsManager) {
|
|
26881
|
+
await settingsManager.updatePluginSettings("@openacp/tunnel", { port: Number(val.trim()) });
|
|
26882
|
+
}
|
|
26520
26883
|
tun.port = Number(val.trim());
|
|
26521
26884
|
console.log(ok2(`Tunnel port set to ${val.trim()}`));
|
|
26522
26885
|
}
|
|
@@ -26524,11 +26887,17 @@ async function editTunnel(config, updates) {
|
|
|
26524
26887
|
const provider = getVal("provider", "cloudflare");
|
|
26525
26888
|
const currentOptions = getVal("options", {});
|
|
26526
26889
|
await editProviderOptions(provider, currentOptions, tun);
|
|
26890
|
+
if (settingsManager) {
|
|
26891
|
+
await settingsManager.updatePluginSettings("@openacp/tunnel", { options: tun.options });
|
|
26892
|
+
}
|
|
26527
26893
|
}
|
|
26528
26894
|
if (choice === "auth") {
|
|
26529
26895
|
const currentAuth = getVal("auth", { enabled: false });
|
|
26530
26896
|
if (currentAuth.enabled) {
|
|
26531
26897
|
tun.auth = { enabled: false };
|
|
26898
|
+
if (settingsManager) {
|
|
26899
|
+
await settingsManager.updatePluginSettings("@openacp/tunnel", { auth: { enabled: false } });
|
|
26900
|
+
}
|
|
26532
26901
|
console.log(ok2("Tunnel auth disabled"));
|
|
26533
26902
|
} else {
|
|
26534
26903
|
const token = await input({
|
|
@@ -26536,6 +26905,9 @@ async function editTunnel(config, updates) {
|
|
|
26536
26905
|
default: ""
|
|
26537
26906
|
});
|
|
26538
26907
|
tun.auth = token.trim() ? { enabled: true, token: token.trim() } : { enabled: true };
|
|
26908
|
+
if (settingsManager) {
|
|
26909
|
+
await settingsManager.updatePluginSettings("@openacp/tunnel", { auth: tun.auth });
|
|
26910
|
+
}
|
|
26539
26911
|
console.log(ok2("Tunnel auth enabled"));
|
|
26540
26912
|
}
|
|
26541
26913
|
}
|
|
@@ -26601,7 +26973,7 @@ async function editProviderOptions(provider, currentOptions, tun) {
|
|
|
26601
26973
|
console.log(dim2(`No configurable options for provider "${provider}"`));
|
|
26602
26974
|
}
|
|
26603
26975
|
}
|
|
26604
|
-
async function runConfigEditor(configManager, mode = "file", apiPort) {
|
|
26976
|
+
async function runConfigEditor(configManager, mode = "file", apiPort, settingsManager) {
|
|
26605
26977
|
await configManager.load();
|
|
26606
26978
|
const config = configManager.get();
|
|
26607
26979
|
const updates = {};
|
|
@@ -26636,14 +27008,14 @@ ${c2.cyan}${c2.bold}OpenACP Config Editor${c2.reset}`);
|
|
|
26636
27008
|
break;
|
|
26637
27009
|
}
|
|
26638
27010
|
const sectionUpdates = {};
|
|
26639
|
-
if (choice === "channels") await editChannels(config, sectionUpdates);
|
|
27011
|
+
if (choice === "channels") await editChannels(config, sectionUpdates, settingsManager);
|
|
26640
27012
|
else if (choice === "agent") await editAgent(config, sectionUpdates);
|
|
26641
27013
|
else if (choice === "workspace") await editWorkspace(config, sectionUpdates);
|
|
26642
|
-
else if (choice === "security") await editSecurity(config, sectionUpdates);
|
|
27014
|
+
else if (choice === "security") await editSecurity(config, sectionUpdates, settingsManager);
|
|
26643
27015
|
else if (choice === "logging") await editLogging(config, sectionUpdates);
|
|
26644
27016
|
else if (choice === "runMode") await editRunMode(config, sectionUpdates);
|
|
26645
|
-
else if (choice === "api") await editApi(config, sectionUpdates);
|
|
26646
|
-
else if (choice === "tunnel") await editTunnel(config, sectionUpdates);
|
|
27017
|
+
else if (choice === "api") await editApi(config, sectionUpdates, settingsManager);
|
|
27018
|
+
else if (choice === "tunnel") await editTunnel(config, sectionUpdates, settingsManager);
|
|
26647
27019
|
if (mode === "api" && Object.keys(sectionUpdates).length > 0) {
|
|
26648
27020
|
await sendConfigViaApi(apiPort, sectionUpdates);
|
|
26649
27021
|
await configManager.load();
|
|
@@ -26663,17 +27035,17 @@ ${c2.cyan}${c2.bold}OpenACP Config Editor${c2.reset}`);
|
|
|
26663
27035
|
async function sendConfigViaApi(port, updates) {
|
|
26664
27036
|
const { apiCall: call } = await Promise.resolve().then(() => (init_api_client(), api_client_exports));
|
|
26665
27037
|
const paths = flattenToPaths(updates);
|
|
26666
|
-
for (const { path:
|
|
27038
|
+
for (const { path: path68, value } of paths) {
|
|
26667
27039
|
const res = await call(port, "/api/config", {
|
|
26668
27040
|
method: "PATCH",
|
|
26669
27041
|
headers: { "Content-Type": "application/json" },
|
|
26670
|
-
body: JSON.stringify({ path:
|
|
27042
|
+
body: JSON.stringify({ path: path68, value })
|
|
26671
27043
|
});
|
|
26672
27044
|
const data = await res.json();
|
|
26673
27045
|
if (!res.ok) {
|
|
26674
|
-
console.log(warn2(`Failed to update ${
|
|
27046
|
+
console.log(warn2(`Failed to update ${path68}: ${data.error}`));
|
|
26675
27047
|
} else if (data.needsRestart) {
|
|
26676
|
-
console.log(warn2(`${
|
|
27048
|
+
console.log(warn2(`${path68} updated \u2014 restart required`));
|
|
26677
27049
|
}
|
|
26678
27050
|
}
|
|
26679
27051
|
}
|
|
@@ -26782,35 +27154,35 @@ __export(instance_prompt_exports, {
|
|
|
26782
27154
|
promptForInstance: () => promptForInstance
|
|
26783
27155
|
});
|
|
26784
27156
|
import fs56 from "fs";
|
|
26785
|
-
import
|
|
26786
|
-
import
|
|
27157
|
+
import path66 from "path";
|
|
27158
|
+
import os32 from "os";
|
|
26787
27159
|
async function promptForInstance(opts) {
|
|
26788
27160
|
const globalRoot = getGlobalRoot();
|
|
26789
|
-
const globalConfigExists = fs56.existsSync(
|
|
27161
|
+
const globalConfigExists = fs56.existsSync(path66.join(globalRoot, "config.json"));
|
|
26790
27162
|
const cwd = process.cwd();
|
|
26791
|
-
const localRoot =
|
|
27163
|
+
const localRoot = path66.join(cwd, ".openacp");
|
|
26792
27164
|
if (!globalConfigExists) return globalRoot;
|
|
26793
27165
|
const isTTY = process.stdin.isTTY && process.stdout.isTTY;
|
|
26794
27166
|
if (!isTTY) return globalRoot;
|
|
26795
|
-
const registryPath =
|
|
27167
|
+
const registryPath = path66.join(globalRoot, "instances.json");
|
|
26796
27168
|
const registry = new InstanceRegistry(registryPath);
|
|
26797
27169
|
registry.load();
|
|
26798
27170
|
const instances = registry.list().filter((e) => fs56.existsSync(e.root));
|
|
26799
27171
|
const instanceOptions = instances.map((e) => {
|
|
26800
27172
|
let name = e.id;
|
|
26801
27173
|
try {
|
|
26802
|
-
const raw = fs56.readFileSync(
|
|
27174
|
+
const raw = fs56.readFileSync(path66.join(e.root, "config.json"), "utf-8");
|
|
26803
27175
|
const parsed = JSON.parse(raw);
|
|
26804
27176
|
if (parsed.instanceName) name = parsed.instanceName;
|
|
26805
27177
|
} catch {
|
|
26806
27178
|
}
|
|
26807
27179
|
const isGlobal = e.root === globalRoot;
|
|
26808
|
-
const displayPath = e.root.replace(
|
|
27180
|
+
const displayPath = e.root.replace(os32.homedir(), "~");
|
|
26809
27181
|
const type = isGlobal ? "global" : "local";
|
|
26810
27182
|
return { value: e.root, label: `${name} workspace (${type} \u2014 ${displayPath})` };
|
|
26811
27183
|
});
|
|
26812
27184
|
if (instanceOptions.length === 0) {
|
|
26813
|
-
const globalDisplay = globalRoot.replace(
|
|
27185
|
+
const globalDisplay = globalRoot.replace(os32.homedir(), "~");
|
|
26814
27186
|
instanceOptions.push({ value: globalRoot, label: `Global workspace (${globalDisplay})` });
|
|
26815
27187
|
}
|
|
26816
27188
|
if (instanceOptions.length === 1 && !opts.allowCreate) {
|
|
@@ -26821,7 +27193,7 @@ async function promptForInstance(opts) {
|
|
|
26821
27193
|
label: o.label
|
|
26822
27194
|
}));
|
|
26823
27195
|
if (opts.allowCreate) {
|
|
26824
|
-
const localDisplay = localRoot.replace(
|
|
27196
|
+
const localDisplay = localRoot.replace(os32.homedir(), "~");
|
|
26825
27197
|
options.push({ value: localRoot, label: `New local workspace (${localDisplay})` });
|
|
26826
27198
|
}
|
|
26827
27199
|
const clack10 = await import("@clack/prompts");
|
|
@@ -26847,7 +27219,7 @@ var init_instance_prompt = __esm({
|
|
|
26847
27219
|
|
|
26848
27220
|
// src/cli.ts
|
|
26849
27221
|
import { setDefaultAutoSelectFamily } from "net";
|
|
26850
|
-
import
|
|
27222
|
+
import path67 from "path";
|
|
26851
27223
|
|
|
26852
27224
|
// src/cli/commands/help.ts
|
|
26853
27225
|
function printHelp() {
|
|
@@ -27086,11 +27458,11 @@ Shows all plugins registered in the plugin registry.
|
|
|
27086
27458
|
`);
|
|
27087
27459
|
return;
|
|
27088
27460
|
}
|
|
27089
|
-
const
|
|
27090
|
-
const
|
|
27461
|
+
const os33 = await import("os");
|
|
27462
|
+
const path68 = await import("path");
|
|
27091
27463
|
const { PluginRegistry: PluginRegistry2 } = await Promise.resolve().then(() => (init_plugin_registry(), plugin_registry_exports));
|
|
27092
|
-
const root = instanceRoot ??
|
|
27093
|
-
const registryPath =
|
|
27464
|
+
const root = instanceRoot ?? path68.join(os33.homedir(), ".openacp");
|
|
27465
|
+
const registryPath = path68.join(root, "plugins.json");
|
|
27094
27466
|
const registry = new PluginRegistry2(registryPath);
|
|
27095
27467
|
await registry.load();
|
|
27096
27468
|
const plugins = registry.list();
|
|
@@ -27225,11 +27597,11 @@ async function cmdPlugin(args2 = [], instanceRoot) {
|
|
|
27225
27597
|
}
|
|
27226
27598
|
async function setPluginEnabled(name, enabled, instanceRoot, json = false) {
|
|
27227
27599
|
if (json) await muteForJson();
|
|
27228
|
-
const
|
|
27229
|
-
const
|
|
27600
|
+
const os33 = await import("os");
|
|
27601
|
+
const path68 = await import("path");
|
|
27230
27602
|
const { PluginRegistry: PluginRegistry2 } = await Promise.resolve().then(() => (init_plugin_registry(), plugin_registry_exports));
|
|
27231
|
-
const root = instanceRoot ??
|
|
27232
|
-
const registryPath =
|
|
27603
|
+
const root = instanceRoot ?? path68.join(os33.homedir(), ".openacp");
|
|
27604
|
+
const registryPath = path68.join(root, "plugins.json");
|
|
27233
27605
|
const registry = new PluginRegistry2(registryPath);
|
|
27234
27606
|
await registry.load();
|
|
27235
27607
|
const entry = registry.get(name);
|
|
@@ -27244,8 +27616,8 @@ async function setPluginEnabled(name, enabled, instanceRoot, json = false) {
|
|
|
27244
27616
|
console.log(`Plugin ${name} ${enabled ? "enabled" : "disabled"}. Restart to apply.`);
|
|
27245
27617
|
}
|
|
27246
27618
|
async function configurePlugin(name, instanceRoot) {
|
|
27247
|
-
const
|
|
27248
|
-
const
|
|
27619
|
+
const os33 = await import("os");
|
|
27620
|
+
const path68 = await import("path");
|
|
27249
27621
|
const { corePlugins: corePlugins2 } = await Promise.resolve().then(() => (init_core_plugins(), core_plugins_exports));
|
|
27250
27622
|
const { SettingsManager: SettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), settings_manager_exports));
|
|
27251
27623
|
const { createInstallContext: createInstallContext2 } = await Promise.resolve().then(() => (init_install_context(), install_context_exports));
|
|
@@ -27254,8 +27626,8 @@ async function configurePlugin(name, instanceRoot) {
|
|
|
27254
27626
|
console.error(`Plugin "${name}" not found.`);
|
|
27255
27627
|
process.exit(1);
|
|
27256
27628
|
}
|
|
27257
|
-
const root = instanceRoot ??
|
|
27258
|
-
const basePath =
|
|
27629
|
+
const root = instanceRoot ?? path68.join(os33.homedir(), ".openacp");
|
|
27630
|
+
const basePath = path68.join(root, "plugins", "data");
|
|
27259
27631
|
const settingsManager = new SettingsManager2(basePath);
|
|
27260
27632
|
const ctx = createInstallContext2({ pluginName: name, settingsManager, basePath });
|
|
27261
27633
|
if (plugin2.configure) {
|
|
@@ -27268,14 +27640,14 @@ async function configurePlugin(name, instanceRoot) {
|
|
|
27268
27640
|
}
|
|
27269
27641
|
async function installPlugin(input2, instanceRoot, json = false) {
|
|
27270
27642
|
if (json) await muteForJson();
|
|
27271
|
-
const
|
|
27272
|
-
const
|
|
27643
|
+
const os33 = await import("os");
|
|
27644
|
+
const path68 = await import("path");
|
|
27273
27645
|
const { execFileSync: execFileSync8 } = await import("child_process");
|
|
27274
27646
|
const { getCurrentVersion: getCurrentVersion2 } = await Promise.resolve().then(() => (init_version(), version_exports));
|
|
27275
27647
|
const { SettingsManager: SettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), settings_manager_exports));
|
|
27276
27648
|
const { createInstallContext: createInstallContext2 } = await Promise.resolve().then(() => (init_install_context(), install_context_exports));
|
|
27277
27649
|
const { PluginRegistry: PluginRegistry2 } = await Promise.resolve().then(() => (init_plugin_registry(), plugin_registry_exports));
|
|
27278
|
-
const root = instanceRoot ??
|
|
27650
|
+
const root = instanceRoot ?? path68.join(os33.homedir(), ".openacp");
|
|
27279
27651
|
let pkgName;
|
|
27280
27652
|
let pkgVersion;
|
|
27281
27653
|
if (input2.startsWith("@")) {
|
|
@@ -27320,9 +27692,9 @@ async function installPlugin(input2, instanceRoot, json = false) {
|
|
|
27320
27692
|
if (!json) console.log(`Installing ${installSpec}...`);
|
|
27321
27693
|
const { corePlugins: corePlugins2 } = await Promise.resolve().then(() => (init_core_plugins(), core_plugins_exports));
|
|
27322
27694
|
const builtinPlugin = corePlugins2.find((p2) => p2.name === pkgName);
|
|
27323
|
-
const basePath =
|
|
27695
|
+
const basePath = path68.join(root, "plugins", "data");
|
|
27324
27696
|
const settingsManager = new SettingsManager2(basePath);
|
|
27325
|
-
const registryPath =
|
|
27697
|
+
const registryPath = path68.join(root, "plugins.json");
|
|
27326
27698
|
const pluginRegistry = new PluginRegistry2(registryPath);
|
|
27327
27699
|
await pluginRegistry.load();
|
|
27328
27700
|
if (builtinPlugin) {
|
|
@@ -27342,8 +27714,8 @@ async function installPlugin(input2, instanceRoot, json = false) {
|
|
|
27342
27714
|
console.log(`\u2713 ${builtinPlugin.name} installed! Restart to activate.`);
|
|
27343
27715
|
return;
|
|
27344
27716
|
}
|
|
27345
|
-
const pluginsDir =
|
|
27346
|
-
const nodeModulesDir =
|
|
27717
|
+
const pluginsDir = path68.join(root, "plugins");
|
|
27718
|
+
const nodeModulesDir = path68.join(pluginsDir, "node_modules");
|
|
27347
27719
|
try {
|
|
27348
27720
|
execFileSync8("npm", ["install", installSpec, "--prefix", pluginsDir, "--save"], {
|
|
27349
27721
|
stdio: json ? "pipe" : "inherit",
|
|
@@ -27357,8 +27729,8 @@ async function installPlugin(input2, instanceRoot, json = false) {
|
|
|
27357
27729
|
const cliVersion = getCurrentVersion2();
|
|
27358
27730
|
const isLocalPath = pkgName.startsWith("/") || pkgName.startsWith(".");
|
|
27359
27731
|
try {
|
|
27360
|
-
const pluginRoot = isLocalPath ?
|
|
27361
|
-
const installedPkgPath =
|
|
27732
|
+
const pluginRoot = isLocalPath ? path68.resolve(pkgName) : path68.join(nodeModulesDir, pkgName);
|
|
27733
|
+
const installedPkgPath = path68.join(pluginRoot, "package.json");
|
|
27362
27734
|
const { readFileSync: readFileSync19 } = await import("fs");
|
|
27363
27735
|
const installedPkg = JSON.parse(readFileSync19(installedPkgPath, "utf-8"));
|
|
27364
27736
|
const minVersion = installedPkg.engines?.openacp?.replace(/[>=^~\s]/g, "");
|
|
@@ -27373,7 +27745,7 @@ async function installPlugin(input2, instanceRoot, json = false) {
|
|
|
27373
27745
|
}
|
|
27374
27746
|
}
|
|
27375
27747
|
}
|
|
27376
|
-
const pluginModule = await import(
|
|
27748
|
+
const pluginModule = await import(path68.join(pluginRoot, installedPkg.main ?? "dist/index.js"));
|
|
27377
27749
|
const plugin2 = pluginModule.default;
|
|
27378
27750
|
if (plugin2?.install) {
|
|
27379
27751
|
const ctx = createInstallContext2({ pluginName: plugin2.name ?? pkgName, settingsManager, basePath });
|
|
@@ -27403,12 +27775,12 @@ async function installPlugin(input2, instanceRoot, json = false) {
|
|
|
27403
27775
|
}
|
|
27404
27776
|
async function uninstallPlugin(name, purge, instanceRoot, json = false) {
|
|
27405
27777
|
if (json) await muteForJson();
|
|
27406
|
-
const
|
|
27407
|
-
const
|
|
27778
|
+
const os33 = await import("os");
|
|
27779
|
+
const path68 = await import("path");
|
|
27408
27780
|
const fs57 = await import("fs");
|
|
27409
27781
|
const { PluginRegistry: PluginRegistry2 } = await Promise.resolve().then(() => (init_plugin_registry(), plugin_registry_exports));
|
|
27410
|
-
const root = instanceRoot ??
|
|
27411
|
-
const registryPath =
|
|
27782
|
+
const root = instanceRoot ?? path68.join(os33.homedir(), ".openacp");
|
|
27783
|
+
const registryPath = path68.join(root, "plugins.json");
|
|
27412
27784
|
const registry = new PluginRegistry2(registryPath);
|
|
27413
27785
|
await registry.load();
|
|
27414
27786
|
const entry = registry.get(name);
|
|
@@ -27428,7 +27800,7 @@ async function uninstallPlugin(name, purge, instanceRoot, json = false) {
|
|
|
27428
27800
|
if (plugin2?.uninstall) {
|
|
27429
27801
|
const { SettingsManager: SettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), settings_manager_exports));
|
|
27430
27802
|
const { createInstallContext: createInstallContext2 } = await Promise.resolve().then(() => (init_install_context(), install_context_exports));
|
|
27431
|
-
const basePath =
|
|
27803
|
+
const basePath = path68.join(root, "plugins", "data");
|
|
27432
27804
|
const settingsManager = new SettingsManager2(basePath);
|
|
27433
27805
|
const ctx = createInstallContext2({ pluginName: name, settingsManager, basePath });
|
|
27434
27806
|
await plugin2.uninstall(ctx, { purge });
|
|
@@ -27436,7 +27808,7 @@ async function uninstallPlugin(name, purge, instanceRoot, json = false) {
|
|
|
27436
27808
|
} catch {
|
|
27437
27809
|
}
|
|
27438
27810
|
if (purge) {
|
|
27439
|
-
const pluginDir =
|
|
27811
|
+
const pluginDir = path68.join(root, "plugins", name);
|
|
27440
27812
|
fs57.rmSync(pluginDir, { recursive: true, force: true });
|
|
27441
27813
|
}
|
|
27442
27814
|
registry.remove(name);
|
|
@@ -28266,13 +28638,13 @@ init_version();
|
|
|
28266
28638
|
init_helpers();
|
|
28267
28639
|
init_output();
|
|
28268
28640
|
init_instance_hint();
|
|
28269
|
-
import
|
|
28270
|
-
import
|
|
28641
|
+
import path38 from "path";
|
|
28642
|
+
import os17 from "os";
|
|
28271
28643
|
import fs36 from "fs";
|
|
28272
28644
|
async function cmdStart(args2 = [], instanceRoot) {
|
|
28273
28645
|
const json = isJsonMode(args2);
|
|
28274
28646
|
if (json) await muteForJson();
|
|
28275
|
-
const root = instanceRoot ??
|
|
28647
|
+
const root = instanceRoot ?? path38.join(os17.homedir(), ".openacp");
|
|
28276
28648
|
if (!json && wantsHelp(args2)) {
|
|
28277
28649
|
console.log(`
|
|
28278
28650
|
\x1B[1mopenacp start\x1B[0m \u2014 Start OpenACP as a background daemon
|
|
@@ -28298,7 +28670,7 @@ Requires an existing config \u2014 run 'openacp' first to set up.
|
|
|
28298
28670
|
await checkAndPromptUpdate();
|
|
28299
28671
|
const { startDaemon: startDaemon2, getPidPath: getPidPath2 } = await Promise.resolve().then(() => (init_daemon2(), daemon_exports));
|
|
28300
28672
|
const { ConfigManager: ConfigManager2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
28301
|
-
const cm = new ConfigManager2(
|
|
28673
|
+
const cm = new ConfigManager2(path38.join(root, "config.json"));
|
|
28302
28674
|
if (await cm.exists()) {
|
|
28303
28675
|
await cm.load();
|
|
28304
28676
|
const config = cm.get();
|
|
@@ -28309,11 +28681,11 @@ Requires an existing config \u2014 run 'openacp' first to set up.
|
|
|
28309
28681
|
process.exit(1);
|
|
28310
28682
|
}
|
|
28311
28683
|
if (json) {
|
|
28312
|
-
let instanceId =
|
|
28684
|
+
let instanceId = path38.basename(root);
|
|
28313
28685
|
try {
|
|
28314
28686
|
const { getGlobalRoot: getGlobalRoot2 } = await Promise.resolve().then(() => (init_instance_context(), instance_context_exports));
|
|
28315
28687
|
const { InstanceRegistry: InstanceRegistry2 } = await Promise.resolve().then(() => (init_instance_registry(), instance_registry_exports));
|
|
28316
|
-
const reg = new InstanceRegistry2(
|
|
28688
|
+
const reg = new InstanceRegistry2(path38.join(getGlobalRoot2(), "instances.json"));
|
|
28317
28689
|
reg.load();
|
|
28318
28690
|
const entry = reg.getByRoot(root);
|
|
28319
28691
|
if (entry) instanceId = entry.id;
|
|
@@ -28321,7 +28693,7 @@ Requires an existing config \u2014 run 'openacp' first to set up.
|
|
|
28321
28693
|
}
|
|
28322
28694
|
let port = null;
|
|
28323
28695
|
try {
|
|
28324
|
-
const portStr = fs36.readFileSync(
|
|
28696
|
+
const portStr = fs36.readFileSync(path38.join(root, "api.port"), "utf-8").trim();
|
|
28325
28697
|
port = parseInt(portStr) || null;
|
|
28326
28698
|
} catch {
|
|
28327
28699
|
port = config.api.port ?? null;
|
|
@@ -28330,7 +28702,7 @@ Requires an existing config \u2014 run 'openacp' first to set up.
|
|
|
28330
28702
|
pid: result.pid,
|
|
28331
28703
|
instanceId,
|
|
28332
28704
|
name: config.instanceName ?? null,
|
|
28333
|
-
directory:
|
|
28705
|
+
directory: path38.dirname(root),
|
|
28334
28706
|
dir: root,
|
|
28335
28707
|
port
|
|
28336
28708
|
});
|
|
@@ -28467,16 +28839,20 @@ the API for live updates. When stopped, edits config file directly.
|
|
|
28467
28839
|
}
|
|
28468
28840
|
const { runConfigEditor: runConfigEditor2 } = await Promise.resolve().then(() => (init_config_editor(), config_editor_exports));
|
|
28469
28841
|
const { ConfigManager: ConfigManager2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
28842
|
+
const { SettingsManager: SettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), settings_manager_exports));
|
|
28843
|
+
const { getGlobalRoot: getGlobalRoot2 } = await Promise.resolve().then(() => (init_instance_context(), instance_context_exports));
|
|
28470
28844
|
const cm = new ConfigManager2(instanceRoot ? pathMod.join(instanceRoot, "config.json") : void 0);
|
|
28471
28845
|
if (!await cm.exists()) {
|
|
28472
28846
|
console.error('No config found. Run "openacp" first to set up.');
|
|
28473
28847
|
process.exit(1);
|
|
28474
28848
|
}
|
|
28849
|
+
const root = instanceRoot ?? getGlobalRoot2();
|
|
28850
|
+
const settingsManager = new SettingsManager2(pathMod.join(root, "plugins"));
|
|
28475
28851
|
const port = readApiPort(void 0, instanceRoot);
|
|
28476
28852
|
if (port !== null) {
|
|
28477
|
-
await runConfigEditor2(cm, "api", port);
|
|
28853
|
+
await runConfigEditor2(cm, "api", port, settingsManager);
|
|
28478
28854
|
} else {
|
|
28479
|
-
await runConfigEditor2(cm, "file");
|
|
28855
|
+
await runConfigEditor2(cm, "file", void 0, settingsManager);
|
|
28480
28856
|
}
|
|
28481
28857
|
}
|
|
28482
28858
|
|
|
@@ -28497,9 +28873,9 @@ start fresh with the setup wizard. The daemon must be stopped first.
|
|
|
28497
28873
|
`);
|
|
28498
28874
|
return;
|
|
28499
28875
|
}
|
|
28500
|
-
const
|
|
28501
|
-
const
|
|
28502
|
-
const root = instanceRoot ??
|
|
28876
|
+
const os33 = await import("os");
|
|
28877
|
+
const path68 = await import("path");
|
|
28878
|
+
const root = instanceRoot ?? path68.join(os33.homedir(), ".openacp");
|
|
28503
28879
|
const { getStatus: getStatus2, getPidPath: getPidPath2 } = await Promise.resolve().then(() => (init_daemon2(), daemon_exports));
|
|
28504
28880
|
const status = getStatus2(getPidPath2(root));
|
|
28505
28881
|
if (status.running) {
|
|
@@ -28657,11 +29033,11 @@ init_instance_context();
|
|
|
28657
29033
|
init_status();
|
|
28658
29034
|
init_output();
|
|
28659
29035
|
init_helpers();
|
|
28660
|
-
import
|
|
28661
|
-
import
|
|
29036
|
+
import path59 from "path";
|
|
29037
|
+
import os28 from "os";
|
|
28662
29038
|
import fs52 from "fs";
|
|
28663
29039
|
async function buildInstanceListEntries() {
|
|
28664
|
-
const registryPath =
|
|
29040
|
+
const registryPath = path59.join(getGlobalRoot(), "instances.json");
|
|
28665
29041
|
const registry = new InstanceRegistry(registryPath);
|
|
28666
29042
|
registry.load();
|
|
28667
29043
|
return registry.list().map((entry) => {
|
|
@@ -28669,7 +29045,7 @@ async function buildInstanceListEntries() {
|
|
|
28669
29045
|
return {
|
|
28670
29046
|
id: entry.id,
|
|
28671
29047
|
name: info.name,
|
|
28672
|
-
directory:
|
|
29048
|
+
directory: path59.dirname(entry.root),
|
|
28673
29049
|
root: entry.root,
|
|
28674
29050
|
status: info.pid ? "running" : "stopped",
|
|
28675
29051
|
port: info.apiPort
|
|
@@ -28719,7 +29095,7 @@ async function cmdInstancesList(args2) {
|
|
|
28719
29095
|
for (const e of entries) {
|
|
28720
29096
|
const status = e.status === "running" ? "\u25CF running" : "\u25CB stopped";
|
|
28721
29097
|
const port = e.port ? `:${e.port}` : "\u2014";
|
|
28722
|
-
const dir = e.directory.replace(
|
|
29098
|
+
const dir = e.directory.replace(os28.homedir(), "~");
|
|
28723
29099
|
const name = (e.name ?? e.id).padEnd(16);
|
|
28724
29100
|
console.log(` ${status.padEnd(10)} ${e.id.padEnd(16)} ${name} ${dir} ${port}`);
|
|
28725
29101
|
}
|
|
@@ -28742,9 +29118,9 @@ async function cmdInstancesCreate(args2) {
|
|
|
28742
29118
|
const agentIdx = args2.indexOf("--agent");
|
|
28743
29119
|
const agent = agentIdx !== -1 ? args2[agentIdx + 1] : void 0;
|
|
28744
29120
|
const noInteractive = args2.includes("--no-interactive");
|
|
28745
|
-
const resolvedDir =
|
|
28746
|
-
const instanceRoot =
|
|
28747
|
-
const registryPath =
|
|
29121
|
+
const resolvedDir = path59.resolve(rawDir.replace(/^~/, os28.homedir()));
|
|
29122
|
+
const instanceRoot = path59.join(resolvedDir, ".openacp");
|
|
29123
|
+
const registryPath = path59.join(getGlobalRoot(), "instances.json");
|
|
28748
29124
|
const registry = new InstanceRegistry(registryPath);
|
|
28749
29125
|
registry.load();
|
|
28750
29126
|
if (fs52.existsSync(instanceRoot)) {
|
|
@@ -28754,8 +29130,8 @@ async function cmdInstancesCreate(args2) {
|
|
|
28754
29130
|
console.error(`Error: Instance already exists at ${resolvedDir} (id: ${existing.id})`);
|
|
28755
29131
|
process.exit(1);
|
|
28756
29132
|
}
|
|
28757
|
-
const configPath =
|
|
28758
|
-
let name2 =
|
|
29133
|
+
const configPath = path59.join(instanceRoot, "config.json");
|
|
29134
|
+
let name2 = path59.basename(resolvedDir);
|
|
28759
29135
|
try {
|
|
28760
29136
|
const config = JSON.parse(fs52.readFileSync(configPath, "utf-8"));
|
|
28761
29137
|
name2 = config.instanceName ?? name2;
|
|
@@ -28770,15 +29146,15 @@ async function cmdInstancesCreate(args2) {
|
|
|
28770
29146
|
const name = instanceName ?? `openacp-${registry.list().length + 1}`;
|
|
28771
29147
|
const id = registry.uniqueId(generateSlug(name));
|
|
28772
29148
|
if (rawFrom) {
|
|
28773
|
-
const fromRoot =
|
|
28774
|
-
if (!fs52.existsSync(
|
|
29149
|
+
const fromRoot = path59.join(path59.resolve(rawFrom.replace(/^~/, os28.homedir())), ".openacp");
|
|
29150
|
+
if (!fs52.existsSync(path59.join(fromRoot, "config.json"))) {
|
|
28775
29151
|
console.error(`Error: No OpenACP instance found at ${rawFrom}`);
|
|
28776
29152
|
process.exit(1);
|
|
28777
29153
|
}
|
|
28778
29154
|
fs52.mkdirSync(instanceRoot, { recursive: true });
|
|
28779
29155
|
const { copyInstance: copyInstance2 } = await Promise.resolve().then(() => (init_instance_copy(), instance_copy_exports));
|
|
28780
29156
|
await copyInstance2(fromRoot, instanceRoot, {});
|
|
28781
|
-
const configPath =
|
|
29157
|
+
const configPath = path59.join(instanceRoot, "config.json");
|
|
28782
29158
|
try {
|
|
28783
29159
|
const config = JSON.parse(fs52.readFileSync(configPath, "utf-8"));
|
|
28784
29160
|
config.instanceName = name;
|
|
@@ -28789,14 +29165,14 @@ async function cmdInstancesCreate(args2) {
|
|
|
28789
29165
|
fs52.mkdirSync(instanceRoot, { recursive: true });
|
|
28790
29166
|
const config = { instanceName: name, runMode: "daemon" };
|
|
28791
29167
|
if (agent) config.defaultAgent = agent;
|
|
28792
|
-
fs52.writeFileSync(
|
|
28793
|
-
fs52.writeFileSync(
|
|
29168
|
+
fs52.writeFileSync(path59.join(instanceRoot, "config.json"), JSON.stringify(config, null, 2));
|
|
29169
|
+
fs52.writeFileSync(path59.join(instanceRoot, "plugins.json"), JSON.stringify({ version: 1, installed: {} }, null, 2));
|
|
28794
29170
|
} else {
|
|
28795
29171
|
fs52.mkdirSync(instanceRoot, { recursive: true });
|
|
28796
29172
|
const config = { instanceName: name, runMode: "daemon" };
|
|
28797
29173
|
if (agent) config.defaultAgent = agent;
|
|
28798
|
-
fs52.writeFileSync(
|
|
28799
|
-
fs52.writeFileSync(
|
|
29174
|
+
fs52.writeFileSync(path59.join(instanceRoot, "config.json"), JSON.stringify(config, null, 2));
|
|
29175
|
+
fs52.writeFileSync(path59.join(instanceRoot, "plugins.json"), JSON.stringify({ version: 1, installed: {} }, null, 2));
|
|
28800
29176
|
console.log(`Instance created at ${resolvedDir}. Run 'openacp setup' inside that directory to configure it.`);
|
|
28801
29177
|
}
|
|
28802
29178
|
registry.register(id, instanceRoot);
|
|
@@ -28808,7 +29184,7 @@ async function outputInstance(json, { id, root }) {
|
|
|
28808
29184
|
const entry = {
|
|
28809
29185
|
id,
|
|
28810
29186
|
name: info.name,
|
|
28811
|
-
directory:
|
|
29187
|
+
directory: path59.dirname(root),
|
|
28812
29188
|
root,
|
|
28813
29189
|
status: info.pid ? "running" : "stopped",
|
|
28814
29190
|
port: info.apiPort
|
|
@@ -28817,7 +29193,7 @@ async function outputInstance(json, { id, root }) {
|
|
|
28817
29193
|
jsonSuccess(entry);
|
|
28818
29194
|
return;
|
|
28819
29195
|
}
|
|
28820
|
-
console.log(`Instance created: ${info.name ?? id} at ${
|
|
29196
|
+
console.log(`Instance created: ${info.name ?? id} at ${path59.dirname(root)}`);
|
|
28821
29197
|
}
|
|
28822
29198
|
|
|
28823
29199
|
// src/cli/commands/integrate.ts
|
|
@@ -29580,16 +29956,16 @@ Options:
|
|
|
29580
29956
|
}
|
|
29581
29957
|
|
|
29582
29958
|
// src/cli/commands/onboard.ts
|
|
29583
|
-
import * as
|
|
29959
|
+
import * as path60 from "path";
|
|
29584
29960
|
async function cmdOnboard(instanceRoot) {
|
|
29585
29961
|
const { ConfigManager: ConfigManager2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
29586
29962
|
const { SettingsManager: SettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), settings_manager_exports));
|
|
29587
29963
|
const { PluginRegistry: PluginRegistry2 } = await Promise.resolve().then(() => (init_plugin_registry(), plugin_registry_exports));
|
|
29588
29964
|
const { getGlobalRoot: getGlobalRoot2 } = await Promise.resolve().then(() => (init_instance_context(), instance_context_exports));
|
|
29589
29965
|
const OPENACP_DIR = instanceRoot ?? getGlobalRoot2();
|
|
29590
|
-
const PLUGINS_DATA_DIR =
|
|
29591
|
-
const REGISTRY_PATH =
|
|
29592
|
-
const cm = new ConfigManager2(
|
|
29966
|
+
const PLUGINS_DATA_DIR = path60.join(OPENACP_DIR, "plugins", "data");
|
|
29967
|
+
const REGISTRY_PATH = path60.join(OPENACP_DIR, "plugins.json");
|
|
29968
|
+
const cm = new ConfigManager2(path60.join(OPENACP_DIR, "config.json"));
|
|
29593
29969
|
const settingsManager = new SettingsManager2(PLUGINS_DATA_DIR);
|
|
29594
29970
|
const pluginRegistry = new PluginRegistry2(REGISTRY_PATH);
|
|
29595
29971
|
await pluginRegistry.load();
|
|
@@ -29608,17 +29984,17 @@ init_instance_context();
|
|
|
29608
29984
|
init_instance_registry();
|
|
29609
29985
|
init_instance_hint();
|
|
29610
29986
|
init_output();
|
|
29611
|
-
import
|
|
29612
|
-
import
|
|
29987
|
+
import path61 from "path";
|
|
29988
|
+
import os29 from "os";
|
|
29613
29989
|
import fs53 from "fs";
|
|
29614
29990
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
29615
29991
|
async function cmdDefault(command2, instanceRoot) {
|
|
29616
29992
|
const args2 = command2 ? [command2] : [];
|
|
29617
29993
|
const json = isJsonMode(args2);
|
|
29618
29994
|
if (json) await muteForJson();
|
|
29619
|
-
const root = instanceRoot ??
|
|
29620
|
-
const pluginsDataDir =
|
|
29621
|
-
const registryPath =
|
|
29995
|
+
const root = instanceRoot ?? path61.join(os29.homedir(), ".openacp");
|
|
29996
|
+
const pluginsDataDir = path61.join(root, "plugins", "data");
|
|
29997
|
+
const registryPath = path61.join(root, "plugins.json");
|
|
29622
29998
|
const forceForeground = command2 === "--foreground";
|
|
29623
29999
|
if (command2 && !command2.startsWith("-")) {
|
|
29624
30000
|
const { suggestMatch: suggestMatch2 } = await Promise.resolve().then(() => (init_suggest(), suggest_exports));
|
|
@@ -29650,7 +30026,7 @@ async function cmdDefault(command2, instanceRoot) {
|
|
|
29650
30026
|
}
|
|
29651
30027
|
await checkAndPromptUpdate();
|
|
29652
30028
|
const { ConfigManager: ConfigManager2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
29653
|
-
const configPath =
|
|
30029
|
+
const configPath = path61.join(root, "config.json");
|
|
29654
30030
|
const cm = new ConfigManager2(configPath);
|
|
29655
30031
|
if (!await cm.exists()) {
|
|
29656
30032
|
const { SettingsManager: SettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), settings_manager_exports));
|
|
@@ -29678,9 +30054,9 @@ async function cmdDefault(command2, instanceRoot) {
|
|
|
29678
30054
|
process.exit(1);
|
|
29679
30055
|
}
|
|
29680
30056
|
if (json) {
|
|
29681
|
-
let instanceId2 =
|
|
30057
|
+
let instanceId2 = path61.basename(root);
|
|
29682
30058
|
try {
|
|
29683
|
-
const reg2 = new InstanceRegistry(
|
|
30059
|
+
const reg2 = new InstanceRegistry(path61.join(getGlobalRoot(), "instances.json"));
|
|
29684
30060
|
reg2.load();
|
|
29685
30061
|
const entry = reg2.getByRoot(root);
|
|
29686
30062
|
if (entry) instanceId2 = entry.id;
|
|
@@ -29688,7 +30064,7 @@ async function cmdDefault(command2, instanceRoot) {
|
|
|
29688
30064
|
}
|
|
29689
30065
|
let port = null;
|
|
29690
30066
|
try {
|
|
29691
|
-
const portStr = fs53.readFileSync(
|
|
30067
|
+
const portStr = fs53.readFileSync(path61.join(root, "api.port"), "utf-8").trim();
|
|
29692
30068
|
port = parseInt(portStr) || null;
|
|
29693
30069
|
} catch {
|
|
29694
30070
|
port = config.api.port ?? null;
|
|
@@ -29697,7 +30073,7 @@ async function cmdDefault(command2, instanceRoot) {
|
|
|
29697
30073
|
pid: result.pid,
|
|
29698
30074
|
instanceId: instanceId2,
|
|
29699
30075
|
name: config.instanceName ?? null,
|
|
29700
|
-
directory:
|
|
30076
|
+
directory: path61.dirname(root),
|
|
29701
30077
|
dir: root,
|
|
29702
30078
|
port
|
|
29703
30079
|
});
|
|
@@ -29710,7 +30086,7 @@ async function cmdDefault(command2, instanceRoot) {
|
|
|
29710
30086
|
markRunning2(root);
|
|
29711
30087
|
printInstanceHint(root);
|
|
29712
30088
|
const { startServer: startServer2 } = await Promise.resolve().then(() => (init_main(), main_exports));
|
|
29713
|
-
const reg = new InstanceRegistry(
|
|
30089
|
+
const reg = new InstanceRegistry(path61.join(getGlobalRoot(), "instances.json"));
|
|
29714
30090
|
reg.load();
|
|
29715
30091
|
const existingEntry = reg.getByRoot(root);
|
|
29716
30092
|
const instanceId = existingEntry?.id ?? randomUUID5();
|
|
@@ -29722,7 +30098,7 @@ async function cmdDefault(command2, instanceRoot) {
|
|
|
29722
30098
|
if (json) {
|
|
29723
30099
|
let port = null;
|
|
29724
30100
|
try {
|
|
29725
|
-
const portStr = fs53.readFileSync(
|
|
30101
|
+
const portStr = fs53.readFileSync(path61.join(root, "api.port"), "utf-8").trim();
|
|
29726
30102
|
port = parseInt(portStr) || null;
|
|
29727
30103
|
} catch {
|
|
29728
30104
|
port = config.api.port ?? null;
|
|
@@ -29731,7 +30107,7 @@ async function cmdDefault(command2, instanceRoot) {
|
|
|
29731
30107
|
pid: process.pid,
|
|
29732
30108
|
instanceId,
|
|
29733
30109
|
name: config.instanceName ?? null,
|
|
29734
|
-
directory:
|
|
30110
|
+
directory: path61.dirname(root),
|
|
29735
30111
|
dir: root,
|
|
29736
30112
|
port
|
|
29737
30113
|
});
|
|
@@ -29800,7 +30176,7 @@ async function showAlreadyRunningMenu(root) {
|
|
|
29800
30176
|
// src/cli/commands/dev.ts
|
|
29801
30177
|
init_helpers();
|
|
29802
30178
|
import fs54 from "fs";
|
|
29803
|
-
import
|
|
30179
|
+
import path62 from "path";
|
|
29804
30180
|
async function cmdDev(args2 = []) {
|
|
29805
30181
|
if (wantsHelp(args2)) {
|
|
29806
30182
|
console.log(`
|
|
@@ -29827,12 +30203,12 @@ async function cmdDev(args2 = []) {
|
|
|
29827
30203
|
console.error("Error: missing plugin path. Usage: openacp dev <plugin-path>");
|
|
29828
30204
|
process.exit(1);
|
|
29829
30205
|
}
|
|
29830
|
-
const pluginPath =
|
|
30206
|
+
const pluginPath = path62.resolve(pluginPathArg);
|
|
29831
30207
|
if (!fs54.existsSync(pluginPath)) {
|
|
29832
30208
|
console.error(`Error: plugin path does not exist: ${pluginPath}`);
|
|
29833
30209
|
process.exit(1);
|
|
29834
30210
|
}
|
|
29835
|
-
const tsconfigPath =
|
|
30211
|
+
const tsconfigPath = path62.join(pluginPath, "tsconfig.json");
|
|
29836
30212
|
const hasTsconfig = fs54.existsSync(tsconfigPath);
|
|
29837
30213
|
if (hasTsconfig) {
|
|
29838
30214
|
console.log("Compiling plugin TypeScript...");
|
|
@@ -29874,10 +30250,10 @@ async function cmdDev(args2 = []) {
|
|
|
29874
30250
|
|
|
29875
30251
|
// src/cli/commands/attach.ts
|
|
29876
30252
|
init_helpers();
|
|
29877
|
-
import
|
|
29878
|
-
import
|
|
30253
|
+
import path63 from "path";
|
|
30254
|
+
import os30 from "os";
|
|
29879
30255
|
async function cmdAttach(args2 = [], instanceRoot) {
|
|
29880
|
-
const root = instanceRoot ??
|
|
30256
|
+
const root = instanceRoot ?? path63.join(os30.homedir(), ".openacp");
|
|
29881
30257
|
if (wantsHelp(args2)) {
|
|
29882
30258
|
console.log(`
|
|
29883
30259
|
\x1B[1mopenacp attach\x1B[0m \u2014 Attach to a running daemon
|
|
@@ -29911,15 +30287,15 @@ Press Ctrl+C to detach.
|
|
|
29911
30287
|
console.log("");
|
|
29912
30288
|
const { spawn: spawn9 } = await import("child_process");
|
|
29913
30289
|
const { expandHome: expandHome4 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
29914
|
-
let logDir2 =
|
|
30290
|
+
let logDir2 = path63.join(root, "logs");
|
|
29915
30291
|
try {
|
|
29916
|
-
const configPath =
|
|
30292
|
+
const configPath = path63.join(root, "config.json");
|
|
29917
30293
|
const { readFileSync: readFileSync19 } = await import("fs");
|
|
29918
30294
|
const config = JSON.parse(readFileSync19(configPath, "utf-8"));
|
|
29919
30295
|
if (config.logging?.logDir) logDir2 = expandHome4(config.logging.logDir);
|
|
29920
30296
|
} catch {
|
|
29921
30297
|
}
|
|
29922
|
-
const logFile =
|
|
30298
|
+
const logFile = path63.join(logDir2, "openacp.log");
|
|
29923
30299
|
const tail = spawn9("tail", ["-f", "-n", "50", logFile], { stdio: "inherit" });
|
|
29924
30300
|
tail.on("error", (err) => {
|
|
29925
30301
|
console.error(`Cannot tail log file: ${err.message}`);
|
|
@@ -29931,8 +30307,8 @@ Press Ctrl+C to detach.
|
|
|
29931
30307
|
init_api_client();
|
|
29932
30308
|
init_instance_registry();
|
|
29933
30309
|
init_output();
|
|
29934
|
-
import
|
|
29935
|
-
import
|
|
30310
|
+
import path64 from "path";
|
|
30311
|
+
import os31 from "os";
|
|
29936
30312
|
import qrcode from "qrcode-terminal";
|
|
29937
30313
|
async function cmdRemote(args2, instanceRoot) {
|
|
29938
30314
|
const json = isJsonMode(args2);
|
|
@@ -29947,7 +30323,7 @@ async function cmdRemote(args2, instanceRoot) {
|
|
|
29947
30323
|
const scopes = scopesRaw ? scopesRaw.split(",").map((s) => s.trim()) : void 0;
|
|
29948
30324
|
let resolvedInstanceRoot2 = instanceRoot;
|
|
29949
30325
|
if (instanceId) {
|
|
29950
|
-
const registryPath =
|
|
30326
|
+
const registryPath = path64.join(os31.homedir(), ".openacp", "instances.json");
|
|
29951
30327
|
const registry = new InstanceRegistry(registryPath);
|
|
29952
30328
|
await registry.load();
|
|
29953
30329
|
const entry = registry.get(instanceId);
|
|
@@ -30085,7 +30461,7 @@ function extractFlag(args2, flag) {
|
|
|
30085
30461
|
// src/cli/commands/setup.ts
|
|
30086
30462
|
init_output();
|
|
30087
30463
|
import * as fs55 from "fs";
|
|
30088
|
-
import * as
|
|
30464
|
+
import * as path65 from "path";
|
|
30089
30465
|
function parseFlag(args2, flag) {
|
|
30090
30466
|
const idx = args2.indexOf(flag);
|
|
30091
30467
|
return idx !== -1 ? args2[idx + 1] : void 0;
|
|
@@ -30113,7 +30489,7 @@ async function cmdSetup(args2, instanceRoot) {
|
|
|
30113
30489
|
}
|
|
30114
30490
|
const runMode = rawRunMode;
|
|
30115
30491
|
const defaultAgent = agentRaw.split(",")[0].trim();
|
|
30116
|
-
const configPath =
|
|
30492
|
+
const configPath = path65.join(instanceRoot, "config.json");
|
|
30117
30493
|
let existing = {};
|
|
30118
30494
|
if (fs55.existsSync(configPath)) {
|
|
30119
30495
|
try {
|
|
@@ -30221,7 +30597,7 @@ async function main() {
|
|
|
30221
30597
|
if (envRoot) {
|
|
30222
30598
|
const { createInstanceContext: createInstanceContext2, getGlobalRoot: getGlobal } = await Promise.resolve().then(() => (init_instance_context(), instance_context_exports));
|
|
30223
30599
|
const { InstanceRegistry: InstanceRegistry2 } = await Promise.resolve().then(() => (init_instance_registry(), instance_registry_exports));
|
|
30224
|
-
const registry = new InstanceRegistry2(
|
|
30600
|
+
const registry = new InstanceRegistry2(path67.join(getGlobal(), "instances.json"));
|
|
30225
30601
|
await registry.load();
|
|
30226
30602
|
const entry = registry.getByRoot(envRoot);
|
|
30227
30603
|
const { randomUUID: randomUUID6 } = await import("crypto");
|