@openacp/cli 2026.41.1 → 2026.41.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1097 -502
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +18 -36
- package/dist/index.js +112 -146
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -833,9 +833,7 @@ Register with \`ctx.registerMiddleware(hook, { priority?, handler })\`. Return \
|
|
|
833
833
|
- \`session:afterDestroy\` \u2014 after session destroyed (sessionId, reason, durationMs, promptCount)
|
|
834
834
|
|
|
835
835
|
### Control
|
|
836
|
-
- \`mode:beforeChange\` \u2014 before mode change (sessionId, fromMode, toMode)
|
|
837
836
|
- \`config:beforeChange\` \u2014 before config change (sessionId, configId, oldValue, newValue)
|
|
838
|
-
- \`model:beforeChange\` \u2014 before model change (sessionId, fromModel, toModel)
|
|
839
837
|
- \`agent:beforeCancel\` \u2014 before agent cancellation (sessionId, reason)
|
|
840
838
|
- \`agent:beforeSwitch\` \u2014 **blocking** before agent switch (sessionId, fromAgent, toAgent). Return null/false to block.
|
|
841
839
|
- \`agent:afterSwitch\` \u2014 **fire-and-forget** after agent switch (sessionId, fromAgent, toAgent, resumed). Observational only.
|
|
@@ -3136,10 +3134,6 @@ var init_history_recorder = __esm({
|
|
|
3136
3134
|
steps.push(step2);
|
|
3137
3135
|
break;
|
|
3138
3136
|
}
|
|
3139
|
-
case "current_mode_update": {
|
|
3140
|
-
steps.push({ type: "mode_change", modeId: event.modeId });
|
|
3141
|
-
break;
|
|
3142
|
-
}
|
|
3143
3137
|
case "config_option_update": {
|
|
3144
3138
|
for (const opt of event.options) {
|
|
3145
3139
|
steps.push({
|
|
@@ -4570,7 +4564,7 @@ var init_cloudflare = __esm({
|
|
|
4570
4564
|
settle(() => reject(new Error("Cloudflare tunnel timed out after 30s")));
|
|
4571
4565
|
}, 3e4);
|
|
4572
4566
|
try {
|
|
4573
|
-
this.child = spawn(binaryPath, args2, { stdio: ["ignore", "pipe", "pipe"] });
|
|
4567
|
+
this.child = spawn(binaryPath, args2, { stdio: ["ignore", "pipe", "pipe"], detached: true });
|
|
4574
4568
|
} catch {
|
|
4575
4569
|
clearTimeout(timeout);
|
|
4576
4570
|
settle(() => reject(new Error(`Failed to start cloudflared at ${binaryPath}`)));
|
|
@@ -4606,11 +4600,16 @@ var init_cloudflare = __esm({
|
|
|
4606
4600
|
});
|
|
4607
4601
|
});
|
|
4608
4602
|
}
|
|
4609
|
-
async stop() {
|
|
4603
|
+
async stop(force = false) {
|
|
4610
4604
|
const child = this.child;
|
|
4611
4605
|
if (!child) return;
|
|
4612
4606
|
this.child = null;
|
|
4613
4607
|
this.exitCallback = null;
|
|
4608
|
+
if (force) {
|
|
4609
|
+
child.kill("SIGKILL");
|
|
4610
|
+
log3.info("Cloudflare tunnel force-killed");
|
|
4611
|
+
return;
|
|
4612
|
+
}
|
|
4614
4613
|
child.kill("SIGTERM");
|
|
4615
4614
|
const exited = await Promise.race([
|
|
4616
4615
|
new Promise((resolve8) => child.on("exit", () => resolve8(true))),
|
|
@@ -4679,7 +4678,7 @@ var init_ngrok = __esm({
|
|
|
4679
4678
|
settle(() => reject(new Error("ngrok tunnel timed out after 30s. Is ngrok installed?")));
|
|
4680
4679
|
}, 3e4);
|
|
4681
4680
|
try {
|
|
4682
|
-
this.child = spawn2("ngrok", args2, { stdio: ["ignore", "pipe", "pipe"] });
|
|
4681
|
+
this.child = spawn2("ngrok", args2, { stdio: ["ignore", "pipe", "pipe"], detached: true });
|
|
4683
4682
|
} catch {
|
|
4684
4683
|
clearTimeout(timeout);
|
|
4685
4684
|
settle(() => reject(new Error(
|
|
@@ -4719,11 +4718,16 @@ var init_ngrok = __esm({
|
|
|
4719
4718
|
});
|
|
4720
4719
|
});
|
|
4721
4720
|
}
|
|
4722
|
-
async stop() {
|
|
4721
|
+
async stop(force = false) {
|
|
4723
4722
|
const child = this.child;
|
|
4724
4723
|
if (!child) return;
|
|
4725
4724
|
this.child = null;
|
|
4726
4725
|
this.exitCallback = null;
|
|
4726
|
+
if (force) {
|
|
4727
|
+
child.kill("SIGKILL");
|
|
4728
|
+
log4.info("ngrok tunnel force-killed");
|
|
4729
|
+
return;
|
|
4730
|
+
}
|
|
4727
4731
|
child.kill("SIGTERM");
|
|
4728
4732
|
const exited = await Promise.race([
|
|
4729
4733
|
new Promise((resolve8) => child.on("exit", () => resolve8(true))),
|
|
@@ -4784,7 +4788,7 @@ var init_bore = __esm({
|
|
|
4784
4788
|
settle(() => reject(new Error("Bore tunnel timed out after 30s. Is bore installed?")));
|
|
4785
4789
|
}, 3e4);
|
|
4786
4790
|
try {
|
|
4787
|
-
this.child = spawn3("bore", args2, { stdio: ["ignore", "pipe", "pipe"] });
|
|
4791
|
+
this.child = spawn3("bore", args2, { stdio: ["ignore", "pipe", "pipe"], detached: true });
|
|
4788
4792
|
} catch {
|
|
4789
4793
|
clearTimeout(timeout);
|
|
4790
4794
|
settle(() => reject(new Error(
|
|
@@ -4824,11 +4828,16 @@ var init_bore = __esm({
|
|
|
4824
4828
|
});
|
|
4825
4829
|
});
|
|
4826
4830
|
}
|
|
4827
|
-
async stop() {
|
|
4831
|
+
async stop(force = false) {
|
|
4828
4832
|
const child = this.child;
|
|
4829
4833
|
if (!child) return;
|
|
4830
4834
|
this.child = null;
|
|
4831
4835
|
this.exitCallback = null;
|
|
4836
|
+
if (force) {
|
|
4837
|
+
child.kill("SIGKILL");
|
|
4838
|
+
log5.info("Bore tunnel force-killed");
|
|
4839
|
+
return;
|
|
4840
|
+
}
|
|
4832
4841
|
child.kill("SIGTERM");
|
|
4833
4842
|
const exited = await Promise.race([
|
|
4834
4843
|
new Promise((resolve8) => child.on("exit", () => resolve8(true))),
|
|
@@ -4894,7 +4903,7 @@ var init_tailscale = __esm({
|
|
|
4894
4903
|
settle(() => reject(new Error("Tailscale funnel timed out after 30s. Is tailscale installed?")));
|
|
4895
4904
|
}, 3e4);
|
|
4896
4905
|
try {
|
|
4897
|
-
this.child = spawn4("tailscale", args2, { stdio: ["ignore", "pipe", "pipe"] });
|
|
4906
|
+
this.child = spawn4("tailscale", args2, { stdio: ["ignore", "pipe", "pipe"], detached: true });
|
|
4898
4907
|
} catch {
|
|
4899
4908
|
clearTimeout(timeout);
|
|
4900
4909
|
settle(() => reject(new Error(
|
|
@@ -4941,11 +4950,16 @@ var init_tailscale = __esm({
|
|
|
4941
4950
|
});
|
|
4942
4951
|
});
|
|
4943
4952
|
}
|
|
4944
|
-
async stop() {
|
|
4953
|
+
async stop(force = false) {
|
|
4945
4954
|
const child = this.child;
|
|
4946
4955
|
if (!child) return;
|
|
4947
4956
|
this.child = null;
|
|
4948
4957
|
this.exitCallback = null;
|
|
4958
|
+
if (force) {
|
|
4959
|
+
child.kill("SIGKILL");
|
|
4960
|
+
log6.info("Tailscale funnel force-killed");
|
|
4961
|
+
return;
|
|
4962
|
+
}
|
|
4949
4963
|
child.kill("SIGTERM");
|
|
4950
4964
|
const exited = await Promise.race([
|
|
4951
4965
|
new Promise((resolve8) => child.on("exit", () => resolve8(true))),
|
|
@@ -5076,6 +5090,7 @@ var init_tunnel_registry = __esm({
|
|
|
5076
5090
|
const entry = await this.add(port, opts, false);
|
|
5077
5091
|
entry.retryCount = retryCount;
|
|
5078
5092
|
} catch (err) {
|
|
5093
|
+
if (this.shuttingDown) return;
|
|
5079
5094
|
log7.error({ port, err: err.message, retry: retryCount }, "Tunnel retry failed");
|
|
5080
5095
|
const failedEntry = {
|
|
5081
5096
|
port,
|
|
@@ -5146,7 +5161,7 @@ var init_tunnel_registry = __esm({
|
|
|
5146
5161
|
for (const [, live] of this.entries) {
|
|
5147
5162
|
if (live.retryTimer) clearTimeout(live.retryTimer);
|
|
5148
5163
|
if (live.process) {
|
|
5149
|
-
stopPromises.push(live.process.stop().catch(() => {
|
|
5164
|
+
stopPromises.push(live.process.stop(true).catch(() => {
|
|
5150
5165
|
}));
|
|
5151
5166
|
}
|
|
5152
5167
|
}
|
|
@@ -6651,6 +6666,7 @@ async function createApiServer(options) {
|
|
|
6651
6666
|
return { port: Number(url.port), host: url.hostname };
|
|
6652
6667
|
} catch (err) {
|
|
6653
6668
|
if (err?.code === "EADDRINUSE" && attempt < maxRetries && port < 65535) {
|
|
6669
|
+
console.log(`[api-server] Port ${port} in use, trying ${port + 1}...`);
|
|
6654
6670
|
port++;
|
|
6655
6671
|
continue;
|
|
6656
6672
|
}
|
|
@@ -6896,7 +6912,7 @@ var init_service = __esm({
|
|
|
6896
6912
|
|
|
6897
6913
|
// src/plugins/api-server/schemas/sessions.ts
|
|
6898
6914
|
import { z } from "zod";
|
|
6899
|
-
var ListSessionsQuerySchema, CreateSessionBodySchema, AdoptSessionBodySchema, PromptBodySchema, PermissionResponseBodySchema, DangerousModeBodySchema, UpdateSessionBodySchema, SessionIdParamSchema;
|
|
6915
|
+
var ListSessionsQuerySchema, CreateSessionBodySchema, AdoptSessionBodySchema, PromptBodySchema, PermissionResponseBodySchema, DangerousModeBodySchema, UpdateSessionBodySchema, SessionIdParamSchema, ConfigIdParamSchema, SetConfigOptionBodySchema, SetClientOverridesBodySchema;
|
|
6900
6916
|
var init_sessions = __esm({
|
|
6901
6917
|
"src/plugins/api-server/schemas/sessions.ts"() {
|
|
6902
6918
|
"use strict";
|
|
@@ -6935,6 +6951,16 @@ var init_sessions = __esm({
|
|
|
6935
6951
|
SessionIdParamSchema = z.object({
|
|
6936
6952
|
sessionId: z.string().min(1)
|
|
6937
6953
|
});
|
|
6954
|
+
ConfigIdParamSchema = z.object({
|
|
6955
|
+
sessionId: z.string().min(1),
|
|
6956
|
+
configId: z.string().min(1)
|
|
6957
|
+
});
|
|
6958
|
+
SetConfigOptionBodySchema = z.object({
|
|
6959
|
+
value: z.string()
|
|
6960
|
+
});
|
|
6961
|
+
SetClientOverridesBodySchema = z.object({
|
|
6962
|
+
bypassPermissions: z.boolean().optional()
|
|
6963
|
+
});
|
|
6938
6964
|
}
|
|
6939
6965
|
});
|
|
6940
6966
|
|
|
@@ -6954,15 +6980,12 @@ async function sessionRoutes(app, deps) {
|
|
|
6954
6980
|
name: s.name ?? null,
|
|
6955
6981
|
workspace: s.workingDirectory,
|
|
6956
6982
|
createdAt: s.createdAt.toISOString(),
|
|
6957
|
-
dangerousMode: s.
|
|
6983
|
+
dangerousMode: s.clientOverrides.bypassPermissions ?? false,
|
|
6958
6984
|
queueDepth: s.queueDepth,
|
|
6959
6985
|
promptRunning: s.promptRunning,
|
|
6960
6986
|
lastActiveAt: deps.core.sessionManager.getSessionRecord(s.id)?.lastActiveAt ?? null,
|
|
6961
6987
|
// ACP state
|
|
6962
|
-
|
|
6963
|
-
currentModel: s.currentModel ?? null,
|
|
6964
|
-
availableModes: s.availableModes?.length ? s.availableModes : void 0,
|
|
6965
|
-
availableModels: s.availableModels?.length ? s.availableModels : void 0,
|
|
6988
|
+
configOptions: s.configOptions?.length ? s.configOptions : void 0,
|
|
6966
6989
|
capabilities: s.agentCapabilities ?? null
|
|
6967
6990
|
}))
|
|
6968
6991
|
};
|
|
@@ -6989,17 +7012,13 @@ async function sessionRoutes(app, deps) {
|
|
|
6989
7012
|
name: session.name ?? null,
|
|
6990
7013
|
workspace: session.workingDirectory,
|
|
6991
7014
|
createdAt: session.createdAt.toISOString(),
|
|
6992
|
-
dangerousMode: session.
|
|
7015
|
+
dangerousMode: session.clientOverrides.bypassPermissions ?? false,
|
|
6993
7016
|
queueDepth: session.queueDepth,
|
|
6994
7017
|
promptRunning: session.promptRunning,
|
|
6995
7018
|
threadId: session.threadId,
|
|
6996
7019
|
channelId: session.channelId,
|
|
6997
7020
|
agentSessionId: session.agentSessionId,
|
|
6998
7021
|
// ACP state
|
|
6999
|
-
currentMode: session.currentMode ?? null,
|
|
7000
|
-
currentModel: session.currentModel ?? null,
|
|
7001
|
-
availableModes: session.availableModes?.length ? session.availableModes : void 0,
|
|
7002
|
-
availableModels: session.availableModels?.length ? session.availableModels : void 0,
|
|
7003
7022
|
configOptions: session.configOptions?.length ? session.configOptions : void 0,
|
|
7004
7023
|
capabilities: session.agentCapabilities ?? null
|
|
7005
7024
|
}
|
|
@@ -7173,9 +7192,9 @@ async function sessionRoutes(app, deps) {
|
|
|
7173
7192
|
changes.voiceMode = body.voiceMode;
|
|
7174
7193
|
}
|
|
7175
7194
|
if (body.dangerousMode !== void 0) {
|
|
7176
|
-
session.
|
|
7195
|
+
session.clientOverrides.bypassPermissions = body.dangerousMode;
|
|
7177
7196
|
await deps.core.sessionManager.patchRecord(sessionId, {
|
|
7178
|
-
|
|
7197
|
+
clientOverrides: session.clientOverrides
|
|
7179
7198
|
});
|
|
7180
7199
|
changes.dangerousMode = body.dangerousMode;
|
|
7181
7200
|
}
|
|
@@ -7196,13 +7215,101 @@ async function sessionRoutes(app, deps) {
|
|
|
7196
7215
|
);
|
|
7197
7216
|
}
|
|
7198
7217
|
const body = DangerousModeBodySchema.parse(request.body);
|
|
7199
|
-
session.
|
|
7218
|
+
session.clientOverrides.bypassPermissions = body.enabled;
|
|
7200
7219
|
await deps.core.sessionManager.patchRecord(sessionId, {
|
|
7201
|
-
|
|
7220
|
+
clientOverrides: session.clientOverrides
|
|
7202
7221
|
});
|
|
7203
7222
|
return { ok: true, dangerousMode: body.enabled };
|
|
7204
7223
|
}
|
|
7205
7224
|
);
|
|
7225
|
+
app.get(
|
|
7226
|
+
"/:sessionId/config",
|
|
7227
|
+
{ preHandler: requireScopes("sessions:read") },
|
|
7228
|
+
async (request) => {
|
|
7229
|
+
const { sessionId: rawId } = SessionIdParamSchema.parse(request.params);
|
|
7230
|
+
const sessionId = decodeURIComponent(rawId);
|
|
7231
|
+
const session = deps.core.sessionManager.getSession(sessionId);
|
|
7232
|
+
if (!session) {
|
|
7233
|
+
throw new NotFoundError(
|
|
7234
|
+
"SESSION_NOT_FOUND",
|
|
7235
|
+
`Session "${sessionId}" not found`
|
|
7236
|
+
);
|
|
7237
|
+
}
|
|
7238
|
+
return {
|
|
7239
|
+
configOptions: session.configOptions,
|
|
7240
|
+
clientOverrides: session.clientOverrides
|
|
7241
|
+
};
|
|
7242
|
+
}
|
|
7243
|
+
);
|
|
7244
|
+
app.put(
|
|
7245
|
+
"/:sessionId/config/:configId",
|
|
7246
|
+
{ preHandler: requireScopes("sessions:write") },
|
|
7247
|
+
async (request) => {
|
|
7248
|
+
const { sessionId: rawId, configId } = ConfigIdParamSchema.parse(request.params);
|
|
7249
|
+
const sessionId = decodeURIComponent(rawId);
|
|
7250
|
+
const session = deps.core.sessionManager.getSession(sessionId);
|
|
7251
|
+
if (!session) {
|
|
7252
|
+
throw new NotFoundError(
|
|
7253
|
+
"SESSION_NOT_FOUND",
|
|
7254
|
+
`Session "${sessionId}" not found`
|
|
7255
|
+
);
|
|
7256
|
+
}
|
|
7257
|
+
const body = SetConfigOptionBodySchema.parse(request.body);
|
|
7258
|
+
const response = await session.agentInstance.setConfigOption(configId, {
|
|
7259
|
+
type: "select",
|
|
7260
|
+
value: body.value
|
|
7261
|
+
});
|
|
7262
|
+
if (response.configOptions) {
|
|
7263
|
+
await session.updateConfigOptions(response.configOptions);
|
|
7264
|
+
}
|
|
7265
|
+
await deps.core.sessionManager.patchRecord(sessionId, {
|
|
7266
|
+
acpState: session.toAcpStateSnapshot()
|
|
7267
|
+
});
|
|
7268
|
+
return {
|
|
7269
|
+
configOptions: session.configOptions,
|
|
7270
|
+
clientOverrides: session.clientOverrides
|
|
7271
|
+
};
|
|
7272
|
+
}
|
|
7273
|
+
);
|
|
7274
|
+
app.get(
|
|
7275
|
+
"/:sessionId/config/overrides",
|
|
7276
|
+
{ preHandler: requireScopes("sessions:read") },
|
|
7277
|
+
async (request) => {
|
|
7278
|
+
const { sessionId: rawId } = SessionIdParamSchema.parse(request.params);
|
|
7279
|
+
const sessionId = decodeURIComponent(rawId);
|
|
7280
|
+
const session = deps.core.sessionManager.getSession(sessionId);
|
|
7281
|
+
if (!session) {
|
|
7282
|
+
throw new NotFoundError(
|
|
7283
|
+
"SESSION_NOT_FOUND",
|
|
7284
|
+
`Session "${sessionId}" not found`
|
|
7285
|
+
);
|
|
7286
|
+
}
|
|
7287
|
+
return { clientOverrides: session.clientOverrides };
|
|
7288
|
+
}
|
|
7289
|
+
);
|
|
7290
|
+
app.put(
|
|
7291
|
+
"/:sessionId/config/overrides",
|
|
7292
|
+
{ preHandler: requireScopes("sessions:write") },
|
|
7293
|
+
async (request) => {
|
|
7294
|
+
const { sessionId: rawId } = SessionIdParamSchema.parse(request.params);
|
|
7295
|
+
const sessionId = decodeURIComponent(rawId);
|
|
7296
|
+
const session = deps.core.sessionManager.getSession(sessionId);
|
|
7297
|
+
if (!session) {
|
|
7298
|
+
throw new NotFoundError(
|
|
7299
|
+
"SESSION_NOT_FOUND",
|
|
7300
|
+
`Session "${sessionId}" not found`
|
|
7301
|
+
);
|
|
7302
|
+
}
|
|
7303
|
+
const body = SetClientOverridesBodySchema.parse(request.body);
|
|
7304
|
+
if (body.bypassPermissions !== void 0) {
|
|
7305
|
+
session.clientOverrides.bypassPermissions = body.bypassPermissions;
|
|
7306
|
+
}
|
|
7307
|
+
await deps.core.sessionManager.patchRecord(sessionId, {
|
|
7308
|
+
clientOverrides: session.clientOverrides
|
|
7309
|
+
});
|
|
7310
|
+
return { clientOverrides: session.clientOverrides };
|
|
7311
|
+
}
|
|
7312
|
+
);
|
|
7206
7313
|
app.post(
|
|
7207
7314
|
"/:sessionId/archive",
|
|
7208
7315
|
{ preHandler: requireScopes("sessions:write") },
|
|
@@ -7349,28 +7456,28 @@ import path21 from "path";
|
|
|
7349
7456
|
import fs17 from "fs";
|
|
7350
7457
|
import os10 from "os";
|
|
7351
7458
|
function createInstanceContext(opts) {
|
|
7352
|
-
const { id, root
|
|
7459
|
+
const { id, root, isGlobal } = opts;
|
|
7353
7460
|
return {
|
|
7354
7461
|
id,
|
|
7355
|
-
root
|
|
7462
|
+
root,
|
|
7356
7463
|
isGlobal,
|
|
7357
7464
|
paths: {
|
|
7358
|
-
config: path21.join(
|
|
7359
|
-
sessions: path21.join(
|
|
7360
|
-
agents: path21.join(
|
|
7361
|
-
registryCache: path21.join(
|
|
7362
|
-
plugins: path21.join(
|
|
7363
|
-
pluginsData: path21.join(
|
|
7364
|
-
pluginRegistry: path21.join(
|
|
7365
|
-
logs: path21.join(
|
|
7366
|
-
pid: path21.join(
|
|
7367
|
-
running: path21.join(
|
|
7368
|
-
apiPort: path21.join(
|
|
7369
|
-
apiSecret: path21.join(
|
|
7370
|
-
bin: path21.join(
|
|
7371
|
-
cache: path21.join(
|
|
7372
|
-
tunnels: path21.join(
|
|
7373
|
-
agentsDir: path21.join(
|
|
7465
|
+
config: path21.join(root, "config.json"),
|
|
7466
|
+
sessions: path21.join(root, "sessions.json"),
|
|
7467
|
+
agents: path21.join(root, "agents.json"),
|
|
7468
|
+
registryCache: path21.join(root, "registry-cache.json"),
|
|
7469
|
+
plugins: path21.join(root, "plugins"),
|
|
7470
|
+
pluginsData: path21.join(root, "plugins", "data"),
|
|
7471
|
+
pluginRegistry: path21.join(root, "plugins.json"),
|
|
7472
|
+
logs: path21.join(root, "logs"),
|
|
7473
|
+
pid: path21.join(root, "openacp.pid"),
|
|
7474
|
+
running: path21.join(root, "running"),
|
|
7475
|
+
apiPort: path21.join(root, "api.port"),
|
|
7476
|
+
apiSecret: path21.join(root, "api-secret"),
|
|
7477
|
+
bin: path21.join(root, "bin"),
|
|
7478
|
+
cache: path21.join(root, "cache"),
|
|
7479
|
+
tunnels: path21.join(root, "tunnels.json"),
|
|
7480
|
+
agentsDir: path21.join(root, "agents")
|
|
7374
7481
|
}
|
|
7375
7482
|
};
|
|
7376
7483
|
}
|
|
@@ -7412,22 +7519,22 @@ __export(config_registry_exports, {
|
|
|
7412
7519
|
});
|
|
7413
7520
|
import * as fs18 from "fs";
|
|
7414
7521
|
import * as path22 from "path";
|
|
7415
|
-
function getFieldDef(
|
|
7416
|
-
return CONFIG_REGISTRY.find((f) => f.path ===
|
|
7522
|
+
function getFieldDef(path65) {
|
|
7523
|
+
return CONFIG_REGISTRY.find((f) => f.path === path65);
|
|
7417
7524
|
}
|
|
7418
7525
|
function getSafeFields() {
|
|
7419
7526
|
return CONFIG_REGISTRY.filter((f) => f.scope === "safe");
|
|
7420
7527
|
}
|
|
7421
|
-
function isHotReloadable(
|
|
7422
|
-
const def = getFieldDef(
|
|
7528
|
+
function isHotReloadable(path65) {
|
|
7529
|
+
const def = getFieldDef(path65);
|
|
7423
7530
|
return def?.hotReload ?? false;
|
|
7424
7531
|
}
|
|
7425
7532
|
function resolveOptions(def, config) {
|
|
7426
7533
|
if (!def.options) return void 0;
|
|
7427
7534
|
return typeof def.options === "function" ? def.options(config) : def.options;
|
|
7428
7535
|
}
|
|
7429
|
-
function getConfigValue(config,
|
|
7430
|
-
const parts =
|
|
7536
|
+
function getConfigValue(config, path65) {
|
|
7537
|
+
const parts = path65.split(".");
|
|
7431
7538
|
let current = config;
|
|
7432
7539
|
for (const part of parts) {
|
|
7433
7540
|
if (current && typeof current === "object" && part in current) {
|
|
@@ -8392,14 +8499,14 @@ async function commandRoutes(app, deps) {
|
|
|
8392
8499
|
if (!deps.commandRegistry) {
|
|
8393
8500
|
return { commands: [] };
|
|
8394
8501
|
}
|
|
8395
|
-
const
|
|
8502
|
+
const commands = deps.commandRegistry.getAll().map((cmd) => ({
|
|
8396
8503
|
name: cmd.name,
|
|
8397
8504
|
description: cmd.description,
|
|
8398
8505
|
usage: cmd.usage ?? null,
|
|
8399
8506
|
category: cmd.category,
|
|
8400
8507
|
pluginName: cmd.pluginName ?? null
|
|
8401
8508
|
}));
|
|
8402
|
-
return { commands
|
|
8509
|
+
return { commands };
|
|
8403
8510
|
});
|
|
8404
8511
|
app.post("/execute", { preHandler: requireScopes("commands:execute") }, async (request, reply) => {
|
|
8405
8512
|
if (!deps.commandRegistry) {
|
|
@@ -8628,7 +8735,7 @@ function createApiServerPlugin() {
|
|
|
8628
8735
|
version: "1.0.0",
|
|
8629
8736
|
description: "REST API + SSE streaming server",
|
|
8630
8737
|
essential: false,
|
|
8631
|
-
permissions: ["services:register", "kernel:access", "events:read"],
|
|
8738
|
+
permissions: ["services:register", "services:use", "kernel:access", "events:read"],
|
|
8632
8739
|
async install(ctx) {
|
|
8633
8740
|
const { settings, legacyConfig, terminal } = ctx;
|
|
8634
8741
|
if (legacyConfig) {
|
|
@@ -8695,6 +8802,11 @@ function createApiServerPlugin() {
|
|
|
8695
8802
|
port: config.port ?? 0,
|
|
8696
8803
|
host: config.host ?? "127.0.0.1"
|
|
8697
8804
|
};
|
|
8805
|
+
console.log(`[api-server] setup() called \u2014 port=${apiConfig.port}, host=${apiConfig.host}, instanceRoot=${instanceRoot}`);
|
|
8806
|
+
log13.info(
|
|
8807
|
+
{ port: apiConfig.port, host: apiConfig.host, instanceRoot },
|
|
8808
|
+
"API server plugin setup \u2014 config loaded"
|
|
8809
|
+
);
|
|
8698
8810
|
portFilePath = path25.join(instanceRoot, "api.port");
|
|
8699
8811
|
const secretFilePath = path25.join(instanceRoot, "api-secret");
|
|
8700
8812
|
const jwtSecretFilePath = path25.join(instanceRoot, "jwt-secret");
|
|
@@ -8791,14 +8903,21 @@ function createApiServerPlugin() {
|
|
|
8791
8903
|
ctx.registerService("api-server", apiService);
|
|
8792
8904
|
cleanupInterval = setInterval(() => tokenStore.cleanup(), 60 * 60 * 1e3);
|
|
8793
8905
|
ctx.on("system:ready", async () => {
|
|
8906
|
+
console.log(`[api-server] system:ready fired \u2014 starting server on ${apiConfig.host}:${apiConfig.port}`);
|
|
8907
|
+
log13.info(
|
|
8908
|
+
{ configPort: apiConfig.port, configHost: apiConfig.host },
|
|
8909
|
+
"API server starting..."
|
|
8910
|
+
);
|
|
8794
8911
|
try {
|
|
8795
8912
|
const addr = await server.start();
|
|
8796
8913
|
actualPort = addr.port;
|
|
8797
8914
|
writePortFile(portFilePath, actualPort);
|
|
8798
8915
|
sseManager.setup();
|
|
8799
8916
|
log13.info(
|
|
8800
|
-
{ host: addr.host, port: addr.port },
|
|
8801
|
-
"API server listening"
|
|
8917
|
+
{ host: addr.host, port: addr.port, portFile: portFilePath },
|
|
8918
|
+
"API server listening on http://%s:%d",
|
|
8919
|
+
addr.host,
|
|
8920
|
+
addr.port
|
|
8802
8921
|
);
|
|
8803
8922
|
if (apiConfig.host !== "127.0.0.1" && apiConfig.host !== "localhost") {
|
|
8804
8923
|
log13.warn(
|
|
@@ -8806,7 +8925,7 @@ function createApiServerPlugin() {
|
|
|
8806
8925
|
);
|
|
8807
8926
|
}
|
|
8808
8927
|
} catch (err) {
|
|
8809
|
-
|
|
8928
|
+
log13.error({ err, configPort: apiConfig.port, configHost: apiConfig.host }, "API server failed to start");
|
|
8810
8929
|
}
|
|
8811
8930
|
});
|
|
8812
8931
|
},
|
|
@@ -9266,7 +9385,7 @@ var init_sse_adapter = __esm({
|
|
|
9266
9385
|
"@openacp/security": "^1.0.0",
|
|
9267
9386
|
"@openacp/notifications": "^1.0.0"
|
|
9268
9387
|
},
|
|
9269
|
-
permissions: ["services:register", "kernel:access", "events:read"],
|
|
9388
|
+
permissions: ["services:register", "services:use", "kernel:access", "events:read"],
|
|
9270
9389
|
async setup(ctx) {
|
|
9271
9390
|
const core = ctx.core;
|
|
9272
9391
|
const apiServer = ctx.getService("api-server");
|
|
@@ -9627,8 +9746,8 @@ function formatToolSummary(name, rawInput, displaySummary) {
|
|
|
9627
9746
|
}
|
|
9628
9747
|
if (lowerName === "grep") {
|
|
9629
9748
|
const pattern = args2.pattern ?? "";
|
|
9630
|
-
const
|
|
9631
|
-
return pattern ? `\u{1F50D} Grep "${pattern}"${
|
|
9749
|
+
const path65 = args2.path ?? "";
|
|
9750
|
+
return pattern ? `\u{1F50D} Grep "${pattern}"${path65 ? ` in ${path65}` : ""}` : `\u{1F527} ${name}`;
|
|
9632
9751
|
}
|
|
9633
9752
|
if (lowerName === "glob") {
|
|
9634
9753
|
const pattern = args2.pattern ?? "";
|
|
@@ -9662,8 +9781,8 @@ function formatToolTitle(name, rawInput, displayTitle) {
|
|
|
9662
9781
|
}
|
|
9663
9782
|
if (lowerName === "grep") {
|
|
9664
9783
|
const pattern = args2.pattern ?? "";
|
|
9665
|
-
const
|
|
9666
|
-
return pattern ? `"${pattern}"${
|
|
9784
|
+
const path65 = args2.path ?? "";
|
|
9785
|
+
return pattern ? `"${pattern}"${path65 ? ` in ${path65}` : ""}` : name;
|
|
9667
9786
|
}
|
|
9668
9787
|
if (lowerName === "glob") {
|
|
9669
9788
|
return String(args2.pattern ?? name);
|
|
@@ -9951,14 +10070,15 @@ function setupDangerousModeCallbacks(bot, core) {
|
|
|
9951
10070
|
const sessionId = ctx.callbackQuery.data.slice(2);
|
|
9952
10071
|
const session = core.sessionManager.getSession(sessionId);
|
|
9953
10072
|
if (session) {
|
|
9954
|
-
|
|
10073
|
+
const newDangerousMode2 = !session.clientOverrides.bypassPermissions;
|
|
10074
|
+
session.clientOverrides.bypassPermissions = newDangerousMode2;
|
|
9955
10075
|
log14.info(
|
|
9956
|
-
{ sessionId, dangerousMode:
|
|
10076
|
+
{ sessionId, dangerousMode: newDangerousMode2 },
|
|
9957
10077
|
"Dangerous mode toggled via button"
|
|
9958
10078
|
);
|
|
9959
|
-
core.sessionManager.patchRecord(sessionId, {
|
|
10079
|
+
core.sessionManager.patchRecord(sessionId, { clientOverrides: session.clientOverrides }).catch(() => {
|
|
9960
10080
|
});
|
|
9961
|
-
const toastText2 =
|
|
10081
|
+
const toastText2 = newDangerousMode2 ? "\u2620\uFE0F Dangerous mode enabled \u2014 permissions auto-approved" : "\u{1F510} Dangerous mode disabled \u2014 permissions shown normally";
|
|
9962
10082
|
try {
|
|
9963
10083
|
await ctx.answerCallbackQuery({ text: toastText2 });
|
|
9964
10084
|
} catch {
|
|
@@ -9967,7 +10087,7 @@ function setupDangerousModeCallbacks(bot, core) {
|
|
|
9967
10087
|
await ctx.editMessageReplyMarkup({
|
|
9968
10088
|
reply_markup: buildSessionControlKeyboard(
|
|
9969
10089
|
sessionId,
|
|
9970
|
-
|
|
10090
|
+
newDangerousMode2,
|
|
9971
10091
|
session.voiceMode === "on"
|
|
9972
10092
|
)
|
|
9973
10093
|
});
|
|
@@ -9985,8 +10105,8 @@ function setupDangerousModeCallbacks(bot, core) {
|
|
|
9985
10105
|
}
|
|
9986
10106
|
return;
|
|
9987
10107
|
}
|
|
9988
|
-
const newDangerousMode = !(record.dangerousMode ?? false);
|
|
9989
|
-
core.sessionManager.patchRecord(sessionId, {
|
|
10108
|
+
const newDangerousMode = !(record.clientOverrides?.bypassPermissions ?? record.dangerousMode ?? false);
|
|
10109
|
+
core.sessionManager.patchRecord(sessionId, { clientOverrides: { bypassPermissions: newDangerousMode } }).catch(() => {
|
|
9990
10110
|
});
|
|
9991
10111
|
log14.info(
|
|
9992
10112
|
{ sessionId, dangerousMode: newDangerousMode },
|
|
@@ -10017,19 +10137,19 @@ async function handleEnableDangerous(ctx, core) {
|
|
|
10017
10137
|
});
|
|
10018
10138
|
return;
|
|
10019
10139
|
}
|
|
10020
|
-
const session = core.
|
|
10140
|
+
const session = await core.getOrResumeSession(
|
|
10021
10141
|
"telegram",
|
|
10022
10142
|
String(threadId)
|
|
10023
10143
|
);
|
|
10024
10144
|
if (session) {
|
|
10025
|
-
if (session.
|
|
10145
|
+
if (session.clientOverrides.bypassPermissions) {
|
|
10026
10146
|
await ctx.reply("\u2620\uFE0F Dangerous mode is already enabled.", {
|
|
10027
10147
|
parse_mode: "HTML"
|
|
10028
10148
|
});
|
|
10029
10149
|
return;
|
|
10030
10150
|
}
|
|
10031
|
-
session.
|
|
10032
|
-
core.sessionManager.patchRecord(session.id, {
|
|
10151
|
+
session.clientOverrides.bypassPermissions = true;
|
|
10152
|
+
core.sessionManager.patchRecord(session.id, { clientOverrides: session.clientOverrides }).catch(() => {
|
|
10033
10153
|
});
|
|
10034
10154
|
} else {
|
|
10035
10155
|
const record = core.sessionManager.getRecordByThread(
|
|
@@ -10042,13 +10162,13 @@ async function handleEnableDangerous(ctx, core) {
|
|
|
10042
10162
|
});
|
|
10043
10163
|
return;
|
|
10044
10164
|
}
|
|
10045
|
-
if (record.dangerousMode) {
|
|
10165
|
+
if (record.clientOverrides?.bypassPermissions ?? record.dangerousMode) {
|
|
10046
10166
|
await ctx.reply("\u2620\uFE0F Dangerous mode is already enabled.", {
|
|
10047
10167
|
parse_mode: "HTML"
|
|
10048
10168
|
});
|
|
10049
10169
|
return;
|
|
10050
10170
|
}
|
|
10051
|
-
core.sessionManager.patchRecord(record.sessionId, {
|
|
10171
|
+
core.sessionManager.patchRecord(record.sessionId, { clientOverrides: { bypassPermissions: true } }).catch(() => {
|
|
10052
10172
|
});
|
|
10053
10173
|
}
|
|
10054
10174
|
await ctx.reply(
|
|
@@ -10068,19 +10188,19 @@ async function handleDisableDangerous(ctx, core) {
|
|
|
10068
10188
|
});
|
|
10069
10189
|
return;
|
|
10070
10190
|
}
|
|
10071
|
-
const session = core.
|
|
10191
|
+
const session = await core.getOrResumeSession(
|
|
10072
10192
|
"telegram",
|
|
10073
10193
|
String(threadId)
|
|
10074
10194
|
);
|
|
10075
10195
|
if (session) {
|
|
10076
|
-
if (!session.
|
|
10196
|
+
if (!session.clientOverrides.bypassPermissions) {
|
|
10077
10197
|
await ctx.reply("\u{1F510} Dangerous mode is already disabled.", {
|
|
10078
10198
|
parse_mode: "HTML"
|
|
10079
10199
|
});
|
|
10080
10200
|
return;
|
|
10081
10201
|
}
|
|
10082
|
-
session.
|
|
10083
|
-
core.sessionManager.patchRecord(session.id, {
|
|
10202
|
+
session.clientOverrides.bypassPermissions = false;
|
|
10203
|
+
core.sessionManager.patchRecord(session.id, { clientOverrides: session.clientOverrides }).catch(() => {
|
|
10084
10204
|
});
|
|
10085
10205
|
} else {
|
|
10086
10206
|
const record = core.sessionManager.getRecordByThread(
|
|
@@ -10093,13 +10213,13 @@ async function handleDisableDangerous(ctx, core) {
|
|
|
10093
10213
|
});
|
|
10094
10214
|
return;
|
|
10095
10215
|
}
|
|
10096
|
-
if (!record.dangerousMode) {
|
|
10216
|
+
if (!(record.clientOverrides?.bypassPermissions ?? record.dangerousMode)) {
|
|
10097
10217
|
await ctx.reply("\u{1F510} Dangerous mode is already disabled.", {
|
|
10098
10218
|
parse_mode: "HTML"
|
|
10099
10219
|
});
|
|
10100
10220
|
return;
|
|
10101
10221
|
}
|
|
10102
|
-
core.sessionManager.patchRecord(record.sessionId, {
|
|
10222
|
+
core.sessionManager.patchRecord(record.sessionId, { clientOverrides: { bypassPermissions: false } }).catch(() => {
|
|
10103
10223
|
});
|
|
10104
10224
|
}
|
|
10105
10225
|
await ctx.reply(
|
|
@@ -10149,7 +10269,7 @@ function setupTTSCallbacks(bot, core) {
|
|
|
10149
10269
|
await ctx.editMessageReplyMarkup({
|
|
10150
10270
|
reply_markup: buildSessionControlKeyboard(
|
|
10151
10271
|
sessionId,
|
|
10152
|
-
session.
|
|
10272
|
+
session.clientOverrides.bypassPermissions ?? false,
|
|
10153
10273
|
newMode === "on"
|
|
10154
10274
|
)
|
|
10155
10275
|
});
|
|
@@ -10213,7 +10333,7 @@ async function handleOutputMode(ctx, core) {
|
|
|
10213
10333
|
await ctx.reply("\u26A0\uFE0F This command must be used in a session topic.", { parse_mode: "HTML" });
|
|
10214
10334
|
return;
|
|
10215
10335
|
}
|
|
10216
|
-
const session = core.
|
|
10336
|
+
const session = await core.getOrResumeSession(
|
|
10217
10337
|
"telegram",
|
|
10218
10338
|
String(threadId)
|
|
10219
10339
|
);
|
|
@@ -10522,7 +10642,7 @@ async function handleNewChat(ctx, core, chatId) {
|
|
|
10522
10642
|
);
|
|
10523
10643
|
return;
|
|
10524
10644
|
}
|
|
10525
|
-
const currentSession = core.
|
|
10645
|
+
const currentSession = await core.getOrResumeSession(
|
|
10526
10646
|
"telegram",
|
|
10527
10647
|
String(threadId)
|
|
10528
10648
|
);
|
|
@@ -10802,7 +10922,7 @@ async function handleCancel(ctx, core, assistant) {
|
|
|
10802
10922
|
async function handleStatus(ctx, core) {
|
|
10803
10923
|
const threadId = ctx.message?.message_thread_id;
|
|
10804
10924
|
if (threadId) {
|
|
10805
|
-
const session = core.
|
|
10925
|
+
const session = await core.getOrResumeSession(
|
|
10806
10926
|
"telegram",
|
|
10807
10927
|
String(threadId)
|
|
10808
10928
|
);
|
|
@@ -11188,8 +11308,8 @@ async function handleClear(ctx, assistant) {
|
|
|
11188
11308
|
await ctx.reply(`\u274C Failed to clear: <code>${message}</code>`, { parse_mode: "HTML" });
|
|
11189
11309
|
}
|
|
11190
11310
|
}
|
|
11191
|
-
function buildSkillMessages(
|
|
11192
|
-
const sorted = [...
|
|
11311
|
+
function buildSkillMessages(commands) {
|
|
11312
|
+
const sorted = [...commands].sort((a, b) => a.name.localeCompare(b.name));
|
|
11193
11313
|
const header2 = "\u{1F6E0} <b>Available Skills</b>\n";
|
|
11194
11314
|
const lines = sorted.map((c3) => `<code>/${c3.name}</code>`);
|
|
11195
11315
|
const messages = [];
|
|
@@ -15272,8 +15392,12 @@ var init_send_queue = __esm({
|
|
|
15272
15392
|
const result = await item.fn();
|
|
15273
15393
|
item.resolve(result);
|
|
15274
15394
|
} catch (err) {
|
|
15275
|
-
|
|
15276
|
-
|
|
15395
|
+
if (err instanceof Error && "description" in err && typeof err.description === "string" && err.description.includes("message is not modified")) {
|
|
15396
|
+
item.resolve(void 0);
|
|
15397
|
+
} else {
|
|
15398
|
+
this.config.onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
15399
|
+
item.reject(err);
|
|
15400
|
+
}
|
|
15277
15401
|
} finally {
|
|
15278
15402
|
const now = Date.now();
|
|
15279
15403
|
this.lastExec = now;
|
|
@@ -15474,6 +15598,7 @@ var init_streaming = __esm({
|
|
|
15474
15598
|
flushTimer;
|
|
15475
15599
|
flushPromise = Promise.resolve();
|
|
15476
15600
|
lastSentBuffer = "";
|
|
15601
|
+
lastSentHtml = "";
|
|
15477
15602
|
displayTruncated = false;
|
|
15478
15603
|
tracer;
|
|
15479
15604
|
append(text6) {
|
|
@@ -15533,6 +15658,8 @@ var init_streaming = __esm({
|
|
|
15533
15658
|
this.firstFlushPending = false;
|
|
15534
15659
|
}
|
|
15535
15660
|
} else {
|
|
15661
|
+
if (html === this.lastSentHtml) return;
|
|
15662
|
+
this.lastSentHtml = html;
|
|
15536
15663
|
try {
|
|
15537
15664
|
const result = await this.sendQueue.enqueue(
|
|
15538
15665
|
() => this.bot.api.editMessageText(this.chatId, this.messageId, html, {
|
|
@@ -15767,7 +15894,7 @@ var init_skill_command_manager = __esm({
|
|
|
15767
15894
|
this.sessionManager = sessionManager;
|
|
15768
15895
|
}
|
|
15769
15896
|
messages = /* @__PURE__ */ new Map();
|
|
15770
|
-
async send(sessionId, threadId,
|
|
15897
|
+
async send(sessionId, threadId, commands) {
|
|
15771
15898
|
if (!this.messages.has(sessionId)) {
|
|
15772
15899
|
const record = this.sessionManager.getSessionRecord(sessionId);
|
|
15773
15900
|
const platform2 = record?.platform;
|
|
@@ -15775,11 +15902,11 @@ var init_skill_command_manager = __esm({
|
|
|
15775
15902
|
this.messages.set(sessionId, platform2.skillMsgId);
|
|
15776
15903
|
}
|
|
15777
15904
|
}
|
|
15778
|
-
if (
|
|
15905
|
+
if (commands.length === 0) {
|
|
15779
15906
|
await this.cleanup(sessionId);
|
|
15780
15907
|
return;
|
|
15781
15908
|
}
|
|
15782
|
-
const messages = buildSkillMessages(
|
|
15909
|
+
const messages = buildSkillMessages(commands);
|
|
15783
15910
|
const existingMsgId = this.messages.get(sessionId);
|
|
15784
15911
|
if (existingMsgId) {
|
|
15785
15912
|
try {
|
|
@@ -16417,10 +16544,10 @@ var init_adapter2 = __esm({
|
|
|
16417
16544
|
const chatId = ctx.chat.id;
|
|
16418
16545
|
const topicId = ctx.message.message_thread_id;
|
|
16419
16546
|
try {
|
|
16420
|
-
const sessionId = topicId != null ? this.core.
|
|
16547
|
+
const sessionId = topicId != null ? (await this.core.getOrResumeSession(
|
|
16421
16548
|
"telegram",
|
|
16422
16549
|
String(topicId)
|
|
16423
|
-
)?.id ?? null : null;
|
|
16550
|
+
))?.id ?? null : null;
|
|
16424
16551
|
const response = await registry.execute(text6, {
|
|
16425
16552
|
raw: "",
|
|
16426
16553
|
sessionId,
|
|
@@ -16456,10 +16583,10 @@ var init_adapter2 = __esm({
|
|
|
16456
16583
|
const chatId = ctx.chat.id;
|
|
16457
16584
|
const topicId = ctx.callbackQuery.message?.message_thread_id;
|
|
16458
16585
|
try {
|
|
16459
|
-
const sessionId = topicId != null ? this.core.
|
|
16586
|
+
const sessionId = topicId != null ? (await this.core.getOrResumeSession(
|
|
16460
16587
|
"telegram",
|
|
16461
16588
|
String(topicId)
|
|
16462
|
-
)?.id ?? null : null;
|
|
16589
|
+
))?.id ?? null : null;
|
|
16463
16590
|
const response = await registry.execute(command2, {
|
|
16464
16591
|
raw: "",
|
|
16465
16592
|
sessionId,
|
|
@@ -16541,7 +16668,7 @@ var init_adapter2 = __esm({
|
|
|
16541
16668
|
});
|
|
16542
16669
|
return;
|
|
16543
16670
|
}
|
|
16544
|
-
const session = this.core.
|
|
16671
|
+
const session = await this.core.getOrResumeSession(
|
|
16545
16672
|
"telegram",
|
|
16546
16673
|
String(threadId)
|
|
16547
16674
|
);
|
|
@@ -16813,10 +16940,10 @@ ${lines.join("\n")}`;
|
|
|
16813
16940
|
);
|
|
16814
16941
|
return;
|
|
16815
16942
|
}
|
|
16816
|
-
const sessionId = this.core.
|
|
16943
|
+
const sessionId = (await this.core.getOrResumeSession(
|
|
16817
16944
|
"telegram",
|
|
16818
16945
|
String(threadId)
|
|
16819
|
-
)?.id;
|
|
16946
|
+
))?.id;
|
|
16820
16947
|
if (sessionId) {
|
|
16821
16948
|
this.getTracer(sessionId)?.log("telegram", { action: "incoming:message", sessionId, userId: String(ctx.from?.id), text: ctx.message?.text });
|
|
16822
16949
|
await this.draftManager.finalize(sessionId, this.assistantSession?.id);
|
|
@@ -17282,33 +17409,33 @@ Task completed.
|
|
|
17282
17409
|
);
|
|
17283
17410
|
}
|
|
17284
17411
|
}
|
|
17285
|
-
async sendSkillCommands(sessionId,
|
|
17412
|
+
async sendSkillCommands(sessionId, commands) {
|
|
17286
17413
|
if (sessionId === this.assistantSession?.id) return;
|
|
17287
17414
|
const session = this.core.sessionManager.getSession(sessionId);
|
|
17288
17415
|
if (!session) return;
|
|
17289
17416
|
const threadId = Number(session.threadId);
|
|
17290
17417
|
if (!threadId) {
|
|
17291
|
-
this._pendingSkillCommands.set(sessionId,
|
|
17418
|
+
this._pendingSkillCommands.set(sessionId, commands);
|
|
17292
17419
|
return;
|
|
17293
17420
|
}
|
|
17294
|
-
await this.skillManager.send(sessionId, threadId,
|
|
17421
|
+
await this.skillManager.send(sessionId, threadId, commands);
|
|
17295
17422
|
}
|
|
17296
17423
|
/** Flush any skill commands that were queued before threadId was available */
|
|
17297
17424
|
async flushPendingSkillCommands(sessionId) {
|
|
17298
|
-
const
|
|
17299
|
-
if (!
|
|
17425
|
+
const commands = this._pendingSkillCommands.get(sessionId);
|
|
17426
|
+
if (!commands) return;
|
|
17300
17427
|
this._pendingSkillCommands.delete(sessionId);
|
|
17301
17428
|
const session = this.core.sessionManager.getSession(sessionId);
|
|
17302
17429
|
if (!session) return;
|
|
17303
17430
|
const threadId = Number(session.threadId);
|
|
17304
17431
|
if (!threadId) return;
|
|
17305
|
-
await this.skillManager.send(sessionId, threadId,
|
|
17432
|
+
await this.skillManager.send(sessionId, threadId, commands);
|
|
17306
17433
|
}
|
|
17307
|
-
resolveSessionId(threadId) {
|
|
17308
|
-
return this.core.
|
|
17434
|
+
async resolveSessionId(threadId) {
|
|
17435
|
+
return (await this.core.getOrResumeSession(
|
|
17309
17436
|
"telegram",
|
|
17310
17437
|
String(threadId)
|
|
17311
|
-
)?.id;
|
|
17438
|
+
))?.id;
|
|
17312
17439
|
}
|
|
17313
17440
|
async downloadTelegramFile(fileId) {
|
|
17314
17441
|
try {
|
|
@@ -17329,7 +17456,7 @@ Task completed.
|
|
|
17329
17456
|
if (!downloaded) return;
|
|
17330
17457
|
let buffer = downloaded.buffer;
|
|
17331
17458
|
let originalFilePath;
|
|
17332
|
-
const sessionId = this.resolveSessionId(threadId) || "unknown";
|
|
17459
|
+
const sessionId = await this.resolveSessionId(threadId) || "unknown";
|
|
17333
17460
|
if (convertOggToWav) {
|
|
17334
17461
|
const oggAtt = await this.fileService.saveFile(
|
|
17335
17462
|
sessionId,
|
|
@@ -17364,7 +17491,7 @@ Task completed.
|
|
|
17364
17491
|
}
|
|
17365
17492
|
return;
|
|
17366
17493
|
}
|
|
17367
|
-
const sid = this.resolveSessionId(threadId);
|
|
17494
|
+
const sid = await this.resolveSessionId(threadId);
|
|
17368
17495
|
if (sid) await this.draftManager.finalize(sid, this.assistantSession?.id);
|
|
17369
17496
|
this.core.handleMessage({
|
|
17370
17497
|
channelId: "telegram",
|
|
@@ -17893,11 +18020,11 @@ __export(api_client_exports, {
|
|
|
17893
18020
|
import * as fs32 from "fs";
|
|
17894
18021
|
import * as path33 from "path";
|
|
17895
18022
|
import * as os14 from "os";
|
|
17896
|
-
function defaultPortFile(
|
|
17897
|
-
return path33.join(
|
|
18023
|
+
function defaultPortFile(root) {
|
|
18024
|
+
return path33.join(root ?? DEFAULT_ROOT, "api.port");
|
|
17898
18025
|
}
|
|
17899
|
-
function defaultSecretFile(
|
|
17900
|
-
return path33.join(
|
|
18026
|
+
function defaultSecretFile(root) {
|
|
18027
|
+
return path33.join(root ?? DEFAULT_ROOT, "api-secret");
|
|
17901
18028
|
}
|
|
17902
18029
|
function readApiPort(portFilePath, instanceRoot) {
|
|
17903
18030
|
const filePath = portFilePath ?? defaultPortFile(instanceRoot);
|
|
@@ -17987,17 +18114,16 @@ var init_suggest = __esm({
|
|
|
17987
18114
|
import fs33 from "fs";
|
|
17988
18115
|
import path34 from "path";
|
|
17989
18116
|
import os15 from "os";
|
|
17990
|
-
function printInstanceHint(
|
|
18117
|
+
function printInstanceHint(root) {
|
|
17991
18118
|
const globalRoot = getGlobalRoot();
|
|
17992
|
-
const isGlobal =
|
|
17993
|
-
const displayPath =
|
|
18119
|
+
const isGlobal = root === globalRoot;
|
|
18120
|
+
const displayPath = root.replace(os15.homedir(), "~");
|
|
17994
18121
|
const label = isGlobal ? "global" : "local";
|
|
17995
|
-
console.log(`
|
|
18122
|
+
console.log(` Workspace: ${label} \u2014 ${displayPath}`);
|
|
17996
18123
|
if (isGlobal) {
|
|
17997
18124
|
const localRoot = path34.join(process.cwd(), ".openacp");
|
|
17998
18125
|
if (fs33.existsSync(localRoot)) {
|
|
17999
|
-
|
|
18000
|
-
console.log(` \x1B[2mhint: local instance found at ${localDisplay} \u2014 use --local to use it\x1B[0m`);
|
|
18126
|
+
console.log(` \x1B[2mhint: local workspace exists in current directory \u2014 use --local to use it\x1B[0m`);
|
|
18001
18127
|
}
|
|
18002
18128
|
}
|
|
18003
18129
|
}
|
|
@@ -18029,16 +18155,16 @@ import { spawn as spawn5 } from "child_process";
|
|
|
18029
18155
|
import * as fs34 from "fs";
|
|
18030
18156
|
import * as path35 from "path";
|
|
18031
18157
|
import * as os16 from "os";
|
|
18032
|
-
function getPidPath(
|
|
18033
|
-
const base =
|
|
18158
|
+
function getPidPath(root) {
|
|
18159
|
+
const base = root ?? DEFAULT_ROOT2;
|
|
18034
18160
|
return path35.join(base, "openacp.pid");
|
|
18035
18161
|
}
|
|
18036
|
-
function getLogDir(
|
|
18037
|
-
const base =
|
|
18162
|
+
function getLogDir(root) {
|
|
18163
|
+
const base = root ?? DEFAULT_ROOT2;
|
|
18038
18164
|
return path35.join(base, "logs");
|
|
18039
18165
|
}
|
|
18040
|
-
function getRunningMarker(
|
|
18041
|
-
const base =
|
|
18166
|
+
function getRunningMarker(root) {
|
|
18167
|
+
const base = root ?? DEFAULT_ROOT2;
|
|
18042
18168
|
return path35.join(base, "running");
|
|
18043
18169
|
}
|
|
18044
18170
|
function writePidFile(pidPath, pid) {
|
|
@@ -18174,19 +18300,19 @@ async function stopDaemon(pidPath = getPidPath(), instanceRoot) {
|
|
|
18174
18300
|
}
|
|
18175
18301
|
return { stopped: false, pid, error: "Process did not exit after SIGKILL (possible uninterruptible I/O). PID file retained." };
|
|
18176
18302
|
}
|
|
18177
|
-
function markRunning(
|
|
18178
|
-
const marker = getRunningMarker(
|
|
18303
|
+
function markRunning(root) {
|
|
18304
|
+
const marker = getRunningMarker(root);
|
|
18179
18305
|
fs34.mkdirSync(path35.dirname(marker), { recursive: true });
|
|
18180
18306
|
fs34.writeFileSync(marker, "");
|
|
18181
18307
|
}
|
|
18182
|
-
function clearRunning(
|
|
18308
|
+
function clearRunning(root) {
|
|
18183
18309
|
try {
|
|
18184
|
-
fs34.unlinkSync(getRunningMarker(
|
|
18310
|
+
fs34.unlinkSync(getRunningMarker(root));
|
|
18185
18311
|
} catch {
|
|
18186
18312
|
}
|
|
18187
18313
|
}
|
|
18188
|
-
function shouldAutoStart(
|
|
18189
|
-
return fs34.existsSync(getRunningMarker(
|
|
18314
|
+
function shouldAutoStart(root) {
|
|
18315
|
+
return fs34.existsSync(getRunningMarker(root));
|
|
18190
18316
|
}
|
|
18191
18317
|
var DEFAULT_ROOT2;
|
|
18192
18318
|
var init_daemon2 = __esm({
|
|
@@ -18205,7 +18331,7 @@ __export(stop_exports, {
|
|
|
18205
18331
|
import path37 from "path";
|
|
18206
18332
|
import os18 from "os";
|
|
18207
18333
|
async function cmdStop(args2 = [], instanceRoot) {
|
|
18208
|
-
const
|
|
18334
|
+
const root = instanceRoot ?? path37.join(os18.homedir(), ".openacp");
|
|
18209
18335
|
if (wantsHelp(args2)) {
|
|
18210
18336
|
console.log(`
|
|
18211
18337
|
\x1B[1mopenacp stop\x1B[0m \u2014 Stop the background daemon
|
|
@@ -18218,7 +18344,7 @@ Sends a stop signal to the running OpenACP daemon process.
|
|
|
18218
18344
|
return;
|
|
18219
18345
|
}
|
|
18220
18346
|
const { stopDaemon: stopDaemon2, getPidPath: getPidPath2 } = await Promise.resolve().then(() => (init_daemon2(), daemon_exports));
|
|
18221
|
-
const result = await stopDaemon2(getPidPath2(
|
|
18347
|
+
const result = await stopDaemon2(getPidPath2(root), root);
|
|
18222
18348
|
if (result.stopped) {
|
|
18223
18349
|
console.log(`OpenACP daemon stopped (was PID ${result.pid})`);
|
|
18224
18350
|
} else {
|
|
@@ -18600,10 +18726,10 @@ function resolveAgentCommand(cmd) {
|
|
|
18600
18726
|
if (ownDir !== process.cwd()) {
|
|
18601
18727
|
searchRoots.push(ownDir);
|
|
18602
18728
|
}
|
|
18603
|
-
for (const
|
|
18729
|
+
for (const root of searchRoots) {
|
|
18604
18730
|
const packageDirs = [
|
|
18605
|
-
path39.resolve(
|
|
18606
|
-
path39.resolve(
|
|
18731
|
+
path39.resolve(root, "node_modules", "@zed-industries", cmd, "dist", "index.js"),
|
|
18732
|
+
path39.resolve(root, "node_modules", cmd, "dist", "index.js")
|
|
18607
18733
|
];
|
|
18608
18734
|
for (const jsPath of packageDirs) {
|
|
18609
18735
|
if (fs36.existsSync(jsPath)) {
|
|
@@ -18611,8 +18737,8 @@ function resolveAgentCommand(cmd) {
|
|
|
18611
18737
|
}
|
|
18612
18738
|
}
|
|
18613
18739
|
}
|
|
18614
|
-
for (const
|
|
18615
|
-
const localBin = path39.resolve(
|
|
18740
|
+
for (const root of searchRoots) {
|
|
18741
|
+
const localBin = path39.resolve(root, "node_modules", ".bin", cmd);
|
|
18616
18742
|
if (fs36.existsSync(localBin)) {
|
|
18617
18743
|
const content = fs36.readFileSync(localBin, "utf-8");
|
|
18618
18744
|
if (content.startsWith("#!/usr/bin/env node")) {
|
|
@@ -18953,14 +19079,6 @@ ${stderr}`
|
|
|
18953
19079
|
};
|
|
18954
19080
|
break;
|
|
18955
19081
|
}
|
|
18956
|
-
case "current_mode_update": {
|
|
18957
|
-
const cm = update;
|
|
18958
|
-
event = {
|
|
18959
|
-
type: "current_mode_update",
|
|
18960
|
-
modeId: cm.currentModeId
|
|
18961
|
-
};
|
|
18962
|
-
break;
|
|
18963
|
-
}
|
|
18964
19082
|
case "config_option_update": {
|
|
18965
19083
|
const co = update;
|
|
18966
19084
|
event = {
|
|
@@ -18978,10 +19096,10 @@ ${stderr}`
|
|
|
18978
19096
|
break;
|
|
18979
19097
|
}
|
|
18980
19098
|
// NOTE: model_update is NOT a session update type in the ACP SDK schema.
|
|
18981
|
-
// Model changes are applied via
|
|
18982
|
-
//
|
|
18983
|
-
//
|
|
18984
|
-
//
|
|
19099
|
+
// Model changes are applied via setSessionConfigOption() and the response
|
|
19100
|
+
// is synchronous — the SDK does not push a model_update notification to
|
|
19101
|
+
// the client. Therefore AgentEvent "model_update" cannot originate from
|
|
19102
|
+
// sessionUpdate and must be emitted by callers of setConfigOption()
|
|
18985
19103
|
// if they need to propagate the change downstream.
|
|
18986
19104
|
default:
|
|
18987
19105
|
return;
|
|
@@ -19063,9 +19181,6 @@ ${stderr}`
|
|
|
19063
19181
|
};
|
|
19064
19182
|
}
|
|
19065
19183
|
// ── New ACP methods ──────────────────────────────────────────────────
|
|
19066
|
-
async setMode(modeId) {
|
|
19067
|
-
await this.connection.setSessionMode({ sessionId: this.sessionId, modeId });
|
|
19068
|
-
}
|
|
19069
19184
|
async setConfigOption(configId, value) {
|
|
19070
19185
|
return await this.connection.setSessionConfigOption({
|
|
19071
19186
|
sessionId: this.sessionId,
|
|
@@ -19073,12 +19188,6 @@ ${stderr}`
|
|
|
19073
19188
|
...value
|
|
19074
19189
|
});
|
|
19075
19190
|
}
|
|
19076
|
-
async setModel(modelId) {
|
|
19077
|
-
await this.connection.unstable_setSessionModel({
|
|
19078
|
-
sessionId: this.sessionId,
|
|
19079
|
-
modelId
|
|
19080
|
-
});
|
|
19081
|
-
}
|
|
19082
19191
|
async listSessions(cwd, cursor) {
|
|
19083
19192
|
return await this.connection.listSessions({
|
|
19084
19193
|
cwd: cwd ?? null,
|
|
@@ -19376,12 +19485,8 @@ Additionally, include a [TTS]...[/TTS] block with a spoken-friendly summary of y
|
|
|
19376
19485
|
name;
|
|
19377
19486
|
createdAt = /* @__PURE__ */ new Date();
|
|
19378
19487
|
voiceMode = "off";
|
|
19379
|
-
dangerousMode = false;
|
|
19380
|
-
currentMode;
|
|
19381
|
-
availableModes = [];
|
|
19382
19488
|
configOptions = [];
|
|
19383
|
-
|
|
19384
|
-
availableModels = [];
|
|
19489
|
+
clientOverrides = {};
|
|
19385
19490
|
agentCapabilities;
|
|
19386
19491
|
archiving = false;
|
|
19387
19492
|
promptCount = 0;
|
|
@@ -19675,34 +19780,28 @@ ${result.text}` : result.text;
|
|
|
19675
19780
|
}
|
|
19676
19781
|
}
|
|
19677
19782
|
// --- ACP Mode / Config / Model State ---
|
|
19678
|
-
|
|
19679
|
-
|
|
19680
|
-
|
|
19681
|
-
|
|
19682
|
-
|
|
19683
|
-
|
|
19684
|
-
|
|
19685
|
-
|
|
19686
|
-
|
|
19687
|
-
|
|
19688
|
-
|
|
19689
|
-
|
|
19690
|
-
|
|
19691
|
-
|
|
19692
|
-
|
|
19783
|
+
setInitialConfigOptions(options) {
|
|
19784
|
+
this.configOptions = options ?? [];
|
|
19785
|
+
}
|
|
19786
|
+
setAgentCapabilities(caps) {
|
|
19787
|
+
this.agentCapabilities = caps;
|
|
19788
|
+
}
|
|
19789
|
+
getConfigOption(id) {
|
|
19790
|
+
return this.configOptions.find((o) => o.id === id);
|
|
19791
|
+
}
|
|
19792
|
+
getConfigByCategory(category) {
|
|
19793
|
+
return this.configOptions.find((o) => o.category === category);
|
|
19794
|
+
}
|
|
19795
|
+
getConfigValue(id) {
|
|
19796
|
+
const option = this.getConfigOption(id);
|
|
19797
|
+
if (!option) return void 0;
|
|
19798
|
+
return String(option.currentValue);
|
|
19693
19799
|
}
|
|
19694
19800
|
/** Set session name explicitly and emit 'named' event */
|
|
19695
19801
|
setName(name) {
|
|
19696
19802
|
this.name = name;
|
|
19697
19803
|
this.emit("named", name);
|
|
19698
19804
|
}
|
|
19699
|
-
async updateMode(modeId) {
|
|
19700
|
-
if (this.middlewareChain) {
|
|
19701
|
-
const result = await this.middlewareChain.execute("mode:beforeChange", { sessionId: this.id, fromMode: this.currentMode, toMode: modeId }, async (p2) => p2);
|
|
19702
|
-
if (!result) return;
|
|
19703
|
-
}
|
|
19704
|
-
this.currentMode = modeId;
|
|
19705
|
-
}
|
|
19706
19805
|
async updateConfigOptions(options) {
|
|
19707
19806
|
if (this.middlewareChain) {
|
|
19708
19807
|
const result = await this.middlewareChain.execute("config:beforeChange", { sessionId: this.id, configId: "options", oldValue: this.configOptions, newValue: options }, async (p2) => p2);
|
|
@@ -19710,21 +19809,10 @@ ${result.text}` : result.text;
|
|
|
19710
19809
|
}
|
|
19711
19810
|
this.configOptions = options;
|
|
19712
19811
|
}
|
|
19713
|
-
async updateModel(modelId) {
|
|
19714
|
-
if (this.middlewareChain) {
|
|
19715
|
-
const result = await this.middlewareChain.execute("model:beforeChange", { sessionId: this.id, fromModel: this.currentModel, toModel: modelId }, async (p2) => p2);
|
|
19716
|
-
if (!result) return;
|
|
19717
|
-
}
|
|
19718
|
-
this.currentModel = modelId;
|
|
19719
|
-
}
|
|
19720
19812
|
/** Snapshot of current ACP state for persistence */
|
|
19721
19813
|
toAcpStateSnapshot() {
|
|
19722
19814
|
return {
|
|
19723
|
-
currentMode: this.currentMode,
|
|
19724
|
-
availableModes: this.availableModes.length > 0 ? this.availableModes : void 0,
|
|
19725
19815
|
configOptions: this.configOptions.length > 0 ? this.configOptions : void 0,
|
|
19726
|
-
currentModel: this.currentModel,
|
|
19727
|
-
availableModels: this.availableModels.length > 0 ? this.availableModels : void 0,
|
|
19728
19816
|
agentCapabilities: this.agentCapabilities
|
|
19729
19817
|
};
|
|
19730
19818
|
}
|
|
@@ -19774,10 +19862,6 @@ ${result.text}` : result.text;
|
|
|
19774
19862
|
this.agentSessionId = newAgent.sessionId;
|
|
19775
19863
|
this.promptCount = 0;
|
|
19776
19864
|
this.agentCapabilities = void 0;
|
|
19777
|
-
this.currentMode = void 0;
|
|
19778
|
-
this.availableModes = [];
|
|
19779
|
-
this.currentModel = void 0;
|
|
19780
|
-
this.availableModels = [];
|
|
19781
19865
|
this.configOptions = [];
|
|
19782
19866
|
this.log.info({ from: this.agentSwitchHistory.at(-1).agentName, to: agentName }, "Agent switched");
|
|
19783
19867
|
}
|
|
@@ -19832,7 +19916,7 @@ var init_session_manager = __esm({
|
|
|
19832
19916
|
createdAt: session.createdAt.toISOString(),
|
|
19833
19917
|
lastActiveAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19834
19918
|
name: session.name,
|
|
19835
|
-
|
|
19919
|
+
clientOverrides: {},
|
|
19836
19920
|
platform: {}
|
|
19837
19921
|
});
|
|
19838
19922
|
}
|
|
@@ -19964,12 +20048,26 @@ var init_session_manager = __esm({
|
|
|
19964
20048
|
}
|
|
19965
20049
|
});
|
|
19966
20050
|
|
|
20051
|
+
// src/core/utils/bypass-detection.ts
|
|
20052
|
+
function isPermissionBypass(value) {
|
|
20053
|
+
const lower = value.toLowerCase();
|
|
20054
|
+
return BYPASS_KEYWORDS.some((kw) => lower.includes(kw));
|
|
20055
|
+
}
|
|
20056
|
+
var BYPASS_KEYWORDS;
|
|
20057
|
+
var init_bypass_detection = __esm({
|
|
20058
|
+
"src/core/utils/bypass-detection.ts"() {
|
|
20059
|
+
"use strict";
|
|
20060
|
+
BYPASS_KEYWORDS = ["bypass", "dangerous", "skip", "dontask", "dont_ask", "auto_accept"];
|
|
20061
|
+
}
|
|
20062
|
+
});
|
|
20063
|
+
|
|
19967
20064
|
// src/core/sessions/session-bridge.ts
|
|
19968
20065
|
var log29, SessionBridge;
|
|
19969
20066
|
var init_session_bridge = __esm({
|
|
19970
20067
|
"src/core/sessions/session-bridge.ts"() {
|
|
19971
20068
|
"use strict";
|
|
19972
20069
|
init_log();
|
|
20070
|
+
init_bypass_detection();
|
|
19973
20071
|
log29 = createChildLogger({ module: "session-bridge" });
|
|
19974
20072
|
SessionBridge = class {
|
|
19975
20073
|
constructor(session, adapter, deps) {
|
|
@@ -20128,12 +20226,12 @@ var init_session_bridge = __esm({
|
|
|
20128
20226
|
break;
|
|
20129
20227
|
case "image_content": {
|
|
20130
20228
|
if (this.deps.fileService) {
|
|
20131
|
-
const
|
|
20229
|
+
const fs53 = this.deps.fileService;
|
|
20132
20230
|
const sid = this.session.id;
|
|
20133
20231
|
const { data, mimeType } = event;
|
|
20134
20232
|
const buffer = Buffer.from(data, "base64");
|
|
20135
|
-
const ext =
|
|
20136
|
-
|
|
20233
|
+
const ext = fs53.extensionFromMime(mimeType);
|
|
20234
|
+
fs53.saveFile(sid, `agent-image${ext}`, buffer, mimeType).then((att) => {
|
|
20137
20235
|
this.sendMessage(sid, {
|
|
20138
20236
|
type: "attachment",
|
|
20139
20237
|
text: "",
|
|
@@ -20145,12 +20243,12 @@ var init_session_bridge = __esm({
|
|
|
20145
20243
|
}
|
|
20146
20244
|
case "audio_content": {
|
|
20147
20245
|
if (this.deps.fileService) {
|
|
20148
|
-
const
|
|
20246
|
+
const fs53 = this.deps.fileService;
|
|
20149
20247
|
const sid = this.session.id;
|
|
20150
20248
|
const { data, mimeType } = event;
|
|
20151
20249
|
const buffer = Buffer.from(data, "base64");
|
|
20152
|
-
const ext =
|
|
20153
|
-
|
|
20250
|
+
const ext = fs53.extensionFromMime(mimeType);
|
|
20251
|
+
fs53.saveFile(sid, `agent-audio${ext}`, buffer, mimeType).then((att) => {
|
|
20154
20252
|
this.sendMessage(sid, {
|
|
20155
20253
|
type: "attachment",
|
|
20156
20254
|
text: "",
|
|
@@ -20175,24 +20273,12 @@ var init_session_bridge = __esm({
|
|
|
20175
20273
|
outgoing = this.deps.messageTransformer.transform(event);
|
|
20176
20274
|
this.sendMessage(this.session.id, outgoing);
|
|
20177
20275
|
break;
|
|
20178
|
-
case "current_mode_update":
|
|
20179
|
-
this.session.updateMode(event.modeId);
|
|
20180
|
-
this.persistAcpState();
|
|
20181
|
-
outgoing = this.deps.messageTransformer.transform(event);
|
|
20182
|
-
this.sendMessage(this.session.id, outgoing);
|
|
20183
|
-
break;
|
|
20184
20276
|
case "config_option_update":
|
|
20185
20277
|
this.session.updateConfigOptions(event.options);
|
|
20186
20278
|
this.persistAcpState();
|
|
20187
20279
|
outgoing = this.deps.messageTransformer.transform(event);
|
|
20188
20280
|
this.sendMessage(this.session.id, outgoing);
|
|
20189
20281
|
break;
|
|
20190
|
-
case "model_update":
|
|
20191
|
-
this.session.updateModel(event.modelId);
|
|
20192
|
-
this.persistAcpState();
|
|
20193
|
-
outgoing = this.deps.messageTransformer.transform(event);
|
|
20194
|
-
this.sendMessage(this.session.id, outgoing);
|
|
20195
|
-
break;
|
|
20196
20282
|
case "user_message_chunk":
|
|
20197
20283
|
outgoing = this.deps.messageTransformer.transform(event);
|
|
20198
20284
|
this.sendMessage(this.session.id, outgoing);
|
|
@@ -20212,7 +20298,7 @@ var init_session_bridge = __esm({
|
|
|
20212
20298
|
});
|
|
20213
20299
|
return outgoing;
|
|
20214
20300
|
}
|
|
20215
|
-
/** Persist current ACP state (
|
|
20301
|
+
/** Persist current ACP state (configOptions, agentCapabilities) to session store as cache */
|
|
20216
20302
|
persistAcpState() {
|
|
20217
20303
|
this.deps.sessionManager.patchRecord(this.session.id, {
|
|
20218
20304
|
acpState: this.session.toAcpStateSnapshot()
|
|
@@ -20267,12 +20353,17 @@ var init_session_bridge = __esm({
|
|
|
20267
20353
|
return allowOption.id;
|
|
20268
20354
|
}
|
|
20269
20355
|
}
|
|
20270
|
-
|
|
20356
|
+
const modeOption = this.session.getConfigByCategory("mode");
|
|
20357
|
+
const isAgentBypass = modeOption && isPermissionBypass(
|
|
20358
|
+
typeof modeOption.currentValue === "string" ? modeOption.currentValue : ""
|
|
20359
|
+
);
|
|
20360
|
+
const isClientBypass = this.session.clientOverrides.bypassPermissions;
|
|
20361
|
+
if (isAgentBypass || isClientBypass) {
|
|
20271
20362
|
const allowOption = permReq.options.find((o) => o.isAllow);
|
|
20272
20363
|
if (allowOption) {
|
|
20273
20364
|
log29.info(
|
|
20274
|
-
{ sessionId: this.session.id, requestId: permReq.id, optionId: allowOption.id },
|
|
20275
|
-
"
|
|
20365
|
+
{ sessionId: this.session.id, requestId: permReq.id, optionId: allowOption.id, agentBypass: !!isAgentBypass, clientBypass: !!isClientBypass },
|
|
20366
|
+
"Bypass mode: auto-approving permission"
|
|
20276
20367
|
);
|
|
20277
20368
|
if (mw) {
|
|
20278
20369
|
mw.execute("permission:afterResolve", {
|
|
@@ -20596,24 +20687,12 @@ var init_message_transformer = __esm({
|
|
|
20596
20687
|
text: `Session updated: ${event.title ?? ""}`.trim(),
|
|
20597
20688
|
metadata: { title: event.title, updatedAt: event.updatedAt }
|
|
20598
20689
|
};
|
|
20599
|
-
case "current_mode_update":
|
|
20600
|
-
return {
|
|
20601
|
-
type: "mode_change",
|
|
20602
|
-
text: `Mode: ${event.modeId}`,
|
|
20603
|
-
metadata: { modeId: event.modeId }
|
|
20604
|
-
};
|
|
20605
20690
|
case "config_option_update":
|
|
20606
20691
|
return {
|
|
20607
20692
|
type: "config_update",
|
|
20608
20693
|
text: "Config updated",
|
|
20609
20694
|
metadata: { options: event.options }
|
|
20610
20695
|
};
|
|
20611
|
-
case "model_update":
|
|
20612
|
-
return {
|
|
20613
|
-
type: "model_update",
|
|
20614
|
-
text: `Model: ${event.modelId}`,
|
|
20615
|
-
metadata: { modelId: event.modelId }
|
|
20616
|
-
};
|
|
20617
20696
|
case "user_message_chunk":
|
|
20618
20697
|
return {
|
|
20619
20698
|
type: "user_replay",
|
|
@@ -21009,16 +21088,14 @@ var init_session_factory = __esm({
|
|
|
21009
21088
|
}
|
|
21010
21089
|
const resp = agentInstance.initialSessionResponse;
|
|
21011
21090
|
if (resp) {
|
|
21012
|
-
|
|
21013
|
-
|
|
21014
|
-
|
|
21015
|
-
|
|
21016
|
-
|
|
21017
|
-
}
|
|
21091
|
+
if (resp.configOptions) {
|
|
21092
|
+
session.setInitialConfigOptions(resp.configOptions);
|
|
21093
|
+
}
|
|
21094
|
+
if (agentInstance.agentCapabilities) {
|
|
21095
|
+
session.setAgentCapabilities(agentInstance.agentCapabilities);
|
|
21096
|
+
}
|
|
21018
21097
|
} else if (agentInstance.agentCapabilities) {
|
|
21019
|
-
session.
|
|
21020
|
-
agentCapabilities: agentInstance.agentCapabilities
|
|
21021
|
-
});
|
|
21098
|
+
session.setAgentCapabilities(agentInstance.agentCapabilities);
|
|
21022
21099
|
}
|
|
21023
21100
|
this.sessionManager.registerSession(session);
|
|
21024
21101
|
this.eventBus.emit("session:created", {
|
|
@@ -21068,18 +21145,21 @@ var init_session_factory = __esm({
|
|
|
21068
21145
|
threadId
|
|
21069
21146
|
});
|
|
21070
21147
|
session.activate();
|
|
21071
|
-
|
|
21148
|
+
if (record.clientOverrides) {
|
|
21149
|
+
session.clientOverrides = record.clientOverrides;
|
|
21150
|
+
} else if (record.dangerousMode) {
|
|
21151
|
+
session.clientOverrides = { bypassPermissions: true };
|
|
21152
|
+
}
|
|
21072
21153
|
if (record.firstAgent) session.firstAgent = record.firstAgent;
|
|
21073
21154
|
if (record.agentSwitchHistory) session.agentSwitchHistory = record.agentSwitchHistory;
|
|
21074
21155
|
if (record.currentPromptCount != null) session.promptCount = record.currentPromptCount;
|
|
21075
21156
|
if (record.acpState) {
|
|
21076
|
-
|
|
21077
|
-
|
|
21078
|
-
|
|
21079
|
-
|
|
21080
|
-
|
|
21081
|
-
|
|
21082
|
-
});
|
|
21157
|
+
if (record.acpState.configOptions) {
|
|
21158
|
+
session.setInitialConfigOptions(record.acpState.configOptions);
|
|
21159
|
+
}
|
|
21160
|
+
if (record.acpState.agentCapabilities) {
|
|
21161
|
+
session.setAgentCapabilities(record.acpState.agentCapabilities);
|
|
21162
|
+
}
|
|
21083
21163
|
}
|
|
21084
21164
|
log32.info({ sessionId: session.id, threadId }, "Lazy resume successful");
|
|
21085
21165
|
return session;
|
|
@@ -22655,6 +22735,7 @@ var init_lifecycle_manager = __esm({
|
|
|
22655
22735
|
} catch (err) {
|
|
22656
22736
|
this._failed.add(plugin2.name);
|
|
22657
22737
|
ctx.cleanup();
|
|
22738
|
+
console.error(`[lifecycle] Plugin ${plugin2.name} setup() FAILED:`, err);
|
|
22658
22739
|
this.getPluginLogger(plugin2.name).error(`setup() failed: ${err}`);
|
|
22659
22740
|
this.eventBus?.emit("plugin:failed", { name: plugin2.name, error: String(err) });
|
|
22660
22741
|
}
|
|
@@ -22951,6 +23032,13 @@ var init_core = __esm({
|
|
|
22951
23032
|
{ channelId: message.channelId, threadId: message.threadId },
|
|
22952
23033
|
"No session found for thread (in-memory miss + lazy resume returned null)"
|
|
22953
23034
|
);
|
|
23035
|
+
const adapter = this.adapters.get(message.channelId);
|
|
23036
|
+
if (adapter) {
|
|
23037
|
+
await adapter.sendMessage(message.threadId, {
|
|
23038
|
+
type: "error",
|
|
23039
|
+
text: "\u26A0\uFE0F No active session in this topic. Use /new to start one."
|
|
23040
|
+
});
|
|
23041
|
+
}
|
|
22954
23042
|
return;
|
|
22955
23043
|
}
|
|
22956
23044
|
this.sessionManager.patchRecord(session.id, {
|
|
@@ -23638,6 +23726,162 @@ var init_switch2 = __esm({
|
|
|
23638
23726
|
}
|
|
23639
23727
|
});
|
|
23640
23728
|
|
|
23729
|
+
// src/core/commands/config.ts
|
|
23730
|
+
function flattenChoices(options) {
|
|
23731
|
+
const result = [];
|
|
23732
|
+
for (const item of options) {
|
|
23733
|
+
if ("group" in item && "options" in item) {
|
|
23734
|
+
result.push(...item.options);
|
|
23735
|
+
} else {
|
|
23736
|
+
result.push(item);
|
|
23737
|
+
}
|
|
23738
|
+
}
|
|
23739
|
+
return result;
|
|
23740
|
+
}
|
|
23741
|
+
function registerCategoryCommand(registry, core, category, commandName, notSupportedMsg) {
|
|
23742
|
+
registry.register({
|
|
23743
|
+
name: commandName,
|
|
23744
|
+
description: `Set ${commandName} for this session`,
|
|
23745
|
+
usage: `[value]`,
|
|
23746
|
+
category: "system",
|
|
23747
|
+
handler: async (args2) => {
|
|
23748
|
+
if (!args2.sessionId) {
|
|
23749
|
+
return { type: "error", message: "\u26A0\uFE0F No active session." };
|
|
23750
|
+
}
|
|
23751
|
+
const session = core.sessionManager.getSession(args2.sessionId);
|
|
23752
|
+
if (!session) {
|
|
23753
|
+
return { type: "error", message: "\u26A0\uFE0F Session not found." };
|
|
23754
|
+
}
|
|
23755
|
+
const configOption = session.getConfigByCategory(category);
|
|
23756
|
+
if (!configOption || configOption.type !== "select") {
|
|
23757
|
+
return { type: "error", message: `\u26A0\uFE0F ${notSupportedMsg}` };
|
|
23758
|
+
}
|
|
23759
|
+
const choices = flattenChoices(configOption.options);
|
|
23760
|
+
const raw = args2.raw.trim();
|
|
23761
|
+
if (!raw) {
|
|
23762
|
+
return {
|
|
23763
|
+
type: "menu",
|
|
23764
|
+
title: configOption.name,
|
|
23765
|
+
options: choices.map((c3) => ({
|
|
23766
|
+
label: c3.value === configOption.currentValue ? `\u2705 ${c3.name}` : c3.name,
|
|
23767
|
+
command: `/${commandName} ${c3.value}`,
|
|
23768
|
+
hint: c3.description
|
|
23769
|
+
}))
|
|
23770
|
+
};
|
|
23771
|
+
}
|
|
23772
|
+
const match = choices.find((c3) => c3.value === raw);
|
|
23773
|
+
if (!match) {
|
|
23774
|
+
const valid = choices.map((c3) => c3.value).join(", ");
|
|
23775
|
+
return { type: "error", message: `\u26A0\uFE0F Invalid value "${raw}". Valid: ${valid}` };
|
|
23776
|
+
}
|
|
23777
|
+
if (session.middlewareChain) {
|
|
23778
|
+
const result = await session.middlewareChain.execute("config:beforeChange", {
|
|
23779
|
+
sessionId: session.id,
|
|
23780
|
+
configId: configOption.id,
|
|
23781
|
+
oldValue: configOption.currentValue,
|
|
23782
|
+
newValue: raw
|
|
23783
|
+
}, async (p2) => p2);
|
|
23784
|
+
if (!result) return { type: "error", message: `Config change blocked by middleware.` };
|
|
23785
|
+
}
|
|
23786
|
+
try {
|
|
23787
|
+
const response = await session.agentInstance.setConfigOption(
|
|
23788
|
+
configOption.id,
|
|
23789
|
+
{ type: "select", value: raw }
|
|
23790
|
+
);
|
|
23791
|
+
if (response.configOptions) {
|
|
23792
|
+
session.configOptions = response.configOptions;
|
|
23793
|
+
}
|
|
23794
|
+
return { type: "text", text: `${configOption.name} set to ${match.name}.` };
|
|
23795
|
+
} catch (err) {
|
|
23796
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
23797
|
+
return { type: "error", message: `\u26A0\uFE0F Failed to set ${commandName}: ${msg}` };
|
|
23798
|
+
}
|
|
23799
|
+
}
|
|
23800
|
+
});
|
|
23801
|
+
}
|
|
23802
|
+
function registerDangerousCommand(registry, core) {
|
|
23803
|
+
registry.register({
|
|
23804
|
+
name: "dangerous",
|
|
23805
|
+
description: "Toggle dangerous mode (bypass permissions)",
|
|
23806
|
+
usage: "[on|off]",
|
|
23807
|
+
category: "system",
|
|
23808
|
+
handler: async (args2) => {
|
|
23809
|
+
if (!args2.sessionId) {
|
|
23810
|
+
return { type: "error", message: "\u26A0\uFE0F No active session." };
|
|
23811
|
+
}
|
|
23812
|
+
const session = core.sessionManager.getSession(args2.sessionId);
|
|
23813
|
+
if (!session) {
|
|
23814
|
+
return { type: "error", message: "\u26A0\uFE0F Session not found." };
|
|
23815
|
+
}
|
|
23816
|
+
const raw = args2.raw.trim().toLowerCase();
|
|
23817
|
+
const modeConfig = session.getConfigByCategory("mode");
|
|
23818
|
+
let bypassValue;
|
|
23819
|
+
let nonBypassDefault;
|
|
23820
|
+
if (modeConfig && modeConfig.type === "select") {
|
|
23821
|
+
const choices = flattenChoices(modeConfig.options);
|
|
23822
|
+
bypassValue = choices.find((c3) => isPermissionBypass(c3.value))?.value;
|
|
23823
|
+
nonBypassDefault = choices.find((c3) => !isPermissionBypass(c3.value))?.value;
|
|
23824
|
+
}
|
|
23825
|
+
const isCurrentlyDangerous = bypassValue ? modeConfig.type === "select" && isPermissionBypass(modeConfig.currentValue) : !!session.clientOverrides.bypassPermissions;
|
|
23826
|
+
if (!raw) {
|
|
23827
|
+
const status = isCurrentlyDangerous ? "on" : "off";
|
|
23828
|
+
const toggleCmd = isCurrentlyDangerous ? "/dangerous off" : "/dangerous on";
|
|
23829
|
+
const toggleLabel = isCurrentlyDangerous ? "Turn off" : "Turn on";
|
|
23830
|
+
return {
|
|
23831
|
+
type: "menu",
|
|
23832
|
+
title: `Dangerous mode: ${status}`,
|
|
23833
|
+
options: [{ label: toggleLabel, command: toggleCmd }]
|
|
23834
|
+
};
|
|
23835
|
+
}
|
|
23836
|
+
if (raw !== "on" && raw !== "off") {
|
|
23837
|
+
return { type: "error", message: "\u26A0\uFE0F Usage: /dangerous [on|off]" };
|
|
23838
|
+
}
|
|
23839
|
+
const wantOn = raw === "on";
|
|
23840
|
+
if (bypassValue && modeConfig) {
|
|
23841
|
+
try {
|
|
23842
|
+
const targetValue = wantOn ? bypassValue : nonBypassDefault;
|
|
23843
|
+
const response = await session.agentInstance.setConfigOption(
|
|
23844
|
+
modeConfig.id,
|
|
23845
|
+
{ type: "select", value: targetValue }
|
|
23846
|
+
);
|
|
23847
|
+
if (response.configOptions) {
|
|
23848
|
+
session.configOptions = response.configOptions;
|
|
23849
|
+
}
|
|
23850
|
+
return {
|
|
23851
|
+
type: "text",
|
|
23852
|
+
text: `Dangerous mode ${wantOn ? "enabled" : "disabled"}.`
|
|
23853
|
+
};
|
|
23854
|
+
} catch (err) {
|
|
23855
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
23856
|
+
return { type: "error", message: `\u26A0\uFE0F Failed: ${msg}` };
|
|
23857
|
+
}
|
|
23858
|
+
}
|
|
23859
|
+
session.clientOverrides.bypassPermissions = wantOn;
|
|
23860
|
+
await core.sessionManager.patchRecord(session.id, {
|
|
23861
|
+
clientOverrides: { ...session.clientOverrides }
|
|
23862
|
+
});
|
|
23863
|
+
return {
|
|
23864
|
+
type: "text",
|
|
23865
|
+
text: `Dangerous mode ${wantOn ? "enabled" : "disabled"} (client-side bypass).`
|
|
23866
|
+
};
|
|
23867
|
+
}
|
|
23868
|
+
});
|
|
23869
|
+
}
|
|
23870
|
+
function registerConfigCommands(registry, _core) {
|
|
23871
|
+
const core = _core;
|
|
23872
|
+
registerCategoryCommand(registry, core, "mode", "mode", "Agent does not support mode selection.");
|
|
23873
|
+
registerCategoryCommand(registry, core, "model", "model", "Agent does not support model selection.");
|
|
23874
|
+
registerCategoryCommand(registry, core, "thought_level", "thought", "Agent does not support thought level.");
|
|
23875
|
+
registerDangerousCommand(registry, core);
|
|
23876
|
+
}
|
|
23877
|
+
var init_config5 = __esm({
|
|
23878
|
+
"src/core/commands/config.ts"() {
|
|
23879
|
+
"use strict";
|
|
23880
|
+
init_bypass_detection();
|
|
23881
|
+
init_bypass_detection();
|
|
23882
|
+
}
|
|
23883
|
+
});
|
|
23884
|
+
|
|
23641
23885
|
// src/core/commands/index.ts
|
|
23642
23886
|
function registerSystemCommands(registry, core) {
|
|
23643
23887
|
registerSessionCommands(registry, core);
|
|
@@ -23646,6 +23890,7 @@ function registerSystemCommands(registry, core) {
|
|
|
23646
23890
|
registerHelpCommand(registry, core);
|
|
23647
23891
|
registerMenuCommand(registry, core);
|
|
23648
23892
|
registerSwitchCommands(registry);
|
|
23893
|
+
registerConfigCommands(registry, core);
|
|
23649
23894
|
}
|
|
23650
23895
|
var init_commands4 = __esm({
|
|
23651
23896
|
"src/core/commands/index.ts"() {
|
|
@@ -23656,6 +23901,7 @@ var init_commands4 = __esm({
|
|
|
23656
23901
|
init_help();
|
|
23657
23902
|
init_menu2();
|
|
23658
23903
|
init_switch2();
|
|
23904
|
+
init_config5();
|
|
23659
23905
|
}
|
|
23660
23906
|
});
|
|
23661
23907
|
|
|
@@ -23681,17 +23927,34 @@ var init_instance_registry = __esm({
|
|
|
23681
23927
|
const parsed = JSON.parse(raw);
|
|
23682
23928
|
if (parsed.version === 1 && parsed.instances) {
|
|
23683
23929
|
this.data = parsed;
|
|
23930
|
+
this.deduplicate();
|
|
23684
23931
|
}
|
|
23685
23932
|
} catch {
|
|
23686
23933
|
}
|
|
23687
23934
|
}
|
|
23935
|
+
/** Remove duplicate entries that point to the same root, keeping the first one */
|
|
23936
|
+
deduplicate() {
|
|
23937
|
+
const seen = /* @__PURE__ */ new Set();
|
|
23938
|
+
const toRemove = [];
|
|
23939
|
+
for (const [id, entry] of Object.entries(this.data.instances)) {
|
|
23940
|
+
if (seen.has(entry.root)) {
|
|
23941
|
+
toRemove.push(id);
|
|
23942
|
+
} else {
|
|
23943
|
+
seen.add(entry.root);
|
|
23944
|
+
}
|
|
23945
|
+
}
|
|
23946
|
+
if (toRemove.length > 0) {
|
|
23947
|
+
for (const id of toRemove) delete this.data.instances[id];
|
|
23948
|
+
this.save();
|
|
23949
|
+
}
|
|
23950
|
+
}
|
|
23688
23951
|
save() {
|
|
23689
23952
|
const dir = path47.dirname(this.registryPath);
|
|
23690
23953
|
fs43.mkdirSync(dir, { recursive: true });
|
|
23691
23954
|
fs43.writeFileSync(this.registryPath, JSON.stringify(this.data, null, 2));
|
|
23692
23955
|
}
|
|
23693
|
-
register(id,
|
|
23694
|
-
this.data.instances[id] = { id, root
|
|
23956
|
+
register(id, root) {
|
|
23957
|
+
this.data.instances[id] = { id, root };
|
|
23695
23958
|
}
|
|
23696
23959
|
remove(id) {
|
|
23697
23960
|
delete this.data.instances[id];
|
|
@@ -23699,8 +23962,8 @@ var init_instance_registry = __esm({
|
|
|
23699
23962
|
get(id) {
|
|
23700
23963
|
return this.data.instances[id];
|
|
23701
23964
|
}
|
|
23702
|
-
getByRoot(
|
|
23703
|
-
return Object.values(this.data.instances).find((e) => e.root ===
|
|
23965
|
+
getByRoot(root) {
|
|
23966
|
+
return Object.values(this.data.instances).find((e) => e.root === root);
|
|
23704
23967
|
}
|
|
23705
23968
|
list() {
|
|
23706
23969
|
return Object.values(this.data.instances);
|
|
@@ -23958,14 +24221,15 @@ var init_setup_agents = __esm({
|
|
|
23958
24221
|
// src/core/setup/setup-workspace.ts
|
|
23959
24222
|
import * as clack4 from "@clack/prompts";
|
|
23960
24223
|
async function setupWorkspace(opts) {
|
|
23961
|
-
const { existing, stepNum, totalSteps } = opts ?? {};
|
|
24224
|
+
const { existing, stepNum, totalSteps, isGlobal } = opts ?? {};
|
|
23962
24225
|
if (stepNum != null && totalSteps != null) {
|
|
23963
24226
|
console.log(step(stepNum, totalSteps, "Workspace"));
|
|
23964
24227
|
}
|
|
24228
|
+
const defaultDir = isGlobal === false ? process.cwd() : "~/openacp-workspace";
|
|
23965
24229
|
const baseDir = guardCancel2(
|
|
23966
24230
|
await clack4.text({
|
|
23967
|
-
message: "Base directory for workspaces:",
|
|
23968
|
-
initialValue: existing ??
|
|
24231
|
+
message: "Base directory for agent workspaces:",
|
|
24232
|
+
initialValue: existing ?? defaultDir,
|
|
23969
24233
|
validate: (val) => (val ?? "").toString().trim().length > 0 ? void 0 : "Path cannot be empty"
|
|
23970
24234
|
})
|
|
23971
24235
|
);
|
|
@@ -24491,9 +24755,81 @@ var init_instance_copy = __esm({
|
|
|
24491
24755
|
}
|
|
24492
24756
|
});
|
|
24493
24757
|
|
|
24758
|
+
// src/core/setup/git-protect.ts
|
|
24759
|
+
import fs46 from "fs";
|
|
24760
|
+
import path51 from "path";
|
|
24761
|
+
function protectLocalInstance(projectDir) {
|
|
24762
|
+
ensureGitignore(projectDir);
|
|
24763
|
+
ensureClaudeMd(projectDir);
|
|
24764
|
+
printSecurityWarning();
|
|
24765
|
+
}
|
|
24766
|
+
function ensureGitignore(projectDir) {
|
|
24767
|
+
const gitignorePath = path51.join(projectDir, ".gitignore");
|
|
24768
|
+
const entry = ".openacp";
|
|
24769
|
+
if (fs46.existsSync(gitignorePath)) {
|
|
24770
|
+
const content = fs46.readFileSync(gitignorePath, "utf-8");
|
|
24771
|
+
const lines = content.split("\n").map((l) => l.trim());
|
|
24772
|
+
if (lines.includes(entry) || lines.includes(".openacp")) {
|
|
24773
|
+
return;
|
|
24774
|
+
}
|
|
24775
|
+
const separator = content.endsWith("\n") ? "" : "\n";
|
|
24776
|
+
fs46.appendFileSync(gitignorePath, `${separator}
|
|
24777
|
+
# OpenACP local workspace (contains secrets)
|
|
24778
|
+
${entry}
|
|
24779
|
+
`);
|
|
24780
|
+
} else {
|
|
24781
|
+
fs46.writeFileSync(gitignorePath, `# OpenACP local workspace (contains secrets)
|
|
24782
|
+
${entry}
|
|
24783
|
+
`);
|
|
24784
|
+
}
|
|
24785
|
+
}
|
|
24786
|
+
function ensureClaudeMd(projectDir) {
|
|
24787
|
+
const claudeMdPath = path51.join(projectDir, "CLAUDE.md");
|
|
24788
|
+
const marker = "## Local OpenACP Workspace";
|
|
24789
|
+
if (fs46.existsSync(claudeMdPath)) {
|
|
24790
|
+
const content = fs46.readFileSync(claudeMdPath, "utf-8");
|
|
24791
|
+
if (content.includes(marker)) {
|
|
24792
|
+
return;
|
|
24793
|
+
}
|
|
24794
|
+
const separator = content.endsWith("\n") ? "" : "\n";
|
|
24795
|
+
fs46.appendFileSync(claudeMdPath, `${separator}
|
|
24796
|
+
## Local OpenACP Workspace
|
|
24797
|
+
|
|
24798
|
+
The \`.openacp/\` directory contains a local OpenACP workspace with secrets (bot tokens, API keys). Do not read, commit, or reference files inside it.
|
|
24799
|
+
`);
|
|
24800
|
+
} else {
|
|
24801
|
+
fs46.writeFileSync(claudeMdPath, `# CLAUDE.md
|
|
24802
|
+
|
|
24803
|
+
## Local OpenACP Workspace
|
|
24804
|
+
|
|
24805
|
+
The \`.openacp/\` directory contains a local OpenACP workspace with secrets (bot tokens, API keys). Do not read, commit, or reference files inside it.
|
|
24806
|
+
`);
|
|
24807
|
+
}
|
|
24808
|
+
}
|
|
24809
|
+
function printSecurityWarning() {
|
|
24810
|
+
const red = "\x1B[1;91m";
|
|
24811
|
+
const yellow = "\x1B[1;33m";
|
|
24812
|
+
const reset = "\x1B[0m";
|
|
24813
|
+
const dim3 = "\x1B[2m";
|
|
24814
|
+
console.log("");
|
|
24815
|
+
console.log(`${red} \u26A0 SECURITY WARNING${reset}`);
|
|
24816
|
+
console.log(`${red} \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501${reset}`);
|
|
24817
|
+
console.log(`${yellow} .openacp/ contains bot tokens and API secrets.${reset}`);
|
|
24818
|
+
console.log(`${yellow} It has been added to .gitignore automatically.${reset}`);
|
|
24819
|
+
console.log(`${dim3} Verify before committing: git status${reset}`);
|
|
24820
|
+
console.log(`${red} \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501${reset}`);
|
|
24821
|
+
console.log("");
|
|
24822
|
+
}
|
|
24823
|
+
var init_git_protect = __esm({
|
|
24824
|
+
"src/core/setup/git-protect.ts"() {
|
|
24825
|
+
"use strict";
|
|
24826
|
+
}
|
|
24827
|
+
});
|
|
24828
|
+
|
|
24494
24829
|
// src/core/setup/wizard.ts
|
|
24495
|
-
import * as
|
|
24496
|
-
import * as
|
|
24830
|
+
import * as path52 from "path";
|
|
24831
|
+
import * as fs47 from "fs";
|
|
24832
|
+
import * as os25 from "os";
|
|
24497
24833
|
import * as clack8 from "@clack/prompts";
|
|
24498
24834
|
async function fetchCommunityAdapters() {
|
|
24499
24835
|
try {
|
|
@@ -24522,23 +24858,24 @@ async function runSetup(configManager, opts) {
|
|
|
24522
24858
|
const isGlobal = instanceRoot === getGlobalRoot();
|
|
24523
24859
|
let instanceName = opts?.instanceName;
|
|
24524
24860
|
if (!instanceName) {
|
|
24525
|
-
const defaultName = isGlobal ? "
|
|
24861
|
+
const defaultName = isGlobal ? "Global workspace" : path52.basename(path52.dirname(instanceRoot));
|
|
24862
|
+
const locationHint = isGlobal ? "global (~/.openacp)" : `local (${instanceRoot.replace(/\/.openacp$/, "").replace(os25.homedir(), "~")})`;
|
|
24526
24863
|
const nameResult = await clack8.text({
|
|
24527
|
-
message:
|
|
24528
|
-
|
|
24864
|
+
message: `Name for this workspace (${locationHint})`,
|
|
24865
|
+
initialValue: defaultName,
|
|
24529
24866
|
validate: (v) => !v?.trim() ? "Name cannot be empty" : void 0
|
|
24530
24867
|
});
|
|
24531
24868
|
if (clack8.isCancel(nameResult)) return false;
|
|
24532
24869
|
instanceName = nameResult.trim();
|
|
24533
24870
|
}
|
|
24534
24871
|
const globalRoot = getGlobalRoot();
|
|
24535
|
-
const registryPath =
|
|
24872
|
+
const registryPath = path52.join(globalRoot, "instances.json");
|
|
24536
24873
|
const instanceRegistry = new InstanceRegistry(registryPath);
|
|
24537
24874
|
await instanceRegistry.load();
|
|
24538
24875
|
let didCopy = false;
|
|
24539
24876
|
if (opts?.from) {
|
|
24540
|
-
const fromRoot =
|
|
24541
|
-
if (
|
|
24877
|
+
const fromRoot = path52.join(opts.from, ".openacp");
|
|
24878
|
+
if (fs47.existsSync(path52.join(fromRoot, "config.json"))) {
|
|
24542
24879
|
const inheritableMap = buildInheritableKeysMap();
|
|
24543
24880
|
await copyInstance(fromRoot, instanceRoot, { inheritableKeys: inheritableMap });
|
|
24544
24881
|
didCopy = true;
|
|
@@ -24549,11 +24886,26 @@ async function runSetup(configManager, opts) {
|
|
|
24549
24886
|
}
|
|
24550
24887
|
if (!didCopy) {
|
|
24551
24888
|
const existingInstances = instanceRegistry.list().filter(
|
|
24552
|
-
(e) =>
|
|
24889
|
+
(e) => fs47.existsSync(path52.join(e.root, "config.json")) && e.root !== instanceRoot
|
|
24553
24890
|
);
|
|
24554
24891
|
if (existingInstances.length > 0) {
|
|
24892
|
+
let singleLabel;
|
|
24893
|
+
if (existingInstances.length === 1) {
|
|
24894
|
+
const e = existingInstances[0];
|
|
24895
|
+
let name = e.id;
|
|
24896
|
+
try {
|
|
24897
|
+
const cfg = JSON.parse(fs47.readFileSync(path52.join(e.root, "config.json"), "utf-8"));
|
|
24898
|
+
if (cfg.instanceName) name = cfg.instanceName;
|
|
24899
|
+
} catch {
|
|
24900
|
+
}
|
|
24901
|
+
const isGlobalEntry = e.root === getGlobalRoot();
|
|
24902
|
+
const displayPath = e.root.replace(os25.homedir(), "~");
|
|
24903
|
+
const type = isGlobalEntry ? "global" : "local";
|
|
24904
|
+
singleLabel = `${name} workspace (${type} \u2014 ${displayPath})`;
|
|
24905
|
+
}
|
|
24906
|
+
const confirmMsg = singleLabel ? `Copy config from ${singleLabel}?` : "Copy config from an existing workspace?";
|
|
24555
24907
|
const shouldCopy = await clack8.confirm({
|
|
24556
|
-
message:
|
|
24908
|
+
message: confirmMsg,
|
|
24557
24909
|
initialValue: true
|
|
24558
24910
|
});
|
|
24559
24911
|
if (clack8.isCancel(shouldCopy)) return false;
|
|
@@ -24563,16 +24915,18 @@ async function runSetup(configManager, opts) {
|
|
|
24563
24915
|
sourceRoot = existingInstances[0].root;
|
|
24564
24916
|
} else {
|
|
24565
24917
|
const choice = await clack8.select({
|
|
24566
|
-
message: "Which
|
|
24918
|
+
message: "Which workspace to copy from?",
|
|
24567
24919
|
options: existingInstances.map((e) => {
|
|
24568
24920
|
let name = e.id;
|
|
24569
24921
|
try {
|
|
24570
|
-
const cfg = JSON.parse(
|
|
24922
|
+
const cfg = JSON.parse(fs47.readFileSync(path52.join(e.root, "config.json"), "utf-8"));
|
|
24571
24923
|
if (cfg.instanceName) name = cfg.instanceName;
|
|
24572
24924
|
} catch {
|
|
24573
24925
|
}
|
|
24574
|
-
const
|
|
24575
|
-
|
|
24926
|
+
const isGlobalEntry = e.root === getGlobalRoot();
|
|
24927
|
+
const displayPath = e.root.replace(os25.homedir(), "~");
|
|
24928
|
+
const type = isGlobalEntry ? "global" : "local";
|
|
24929
|
+
return { value: e.root, label: `${name} workspace (${type} \u2014 ${displayPath})` };
|
|
24576
24930
|
})
|
|
24577
24931
|
});
|
|
24578
24932
|
if (clack8.isCancel(choice)) return false;
|
|
@@ -24642,10 +24996,10 @@ async function runSetup(configManager, opts) {
|
|
|
24642
24996
|
if (channelId.startsWith("official:")) {
|
|
24643
24997
|
const npmPackage = channelId.slice("official:".length);
|
|
24644
24998
|
const { execFileSync: execFileSync8 } = await import("child_process");
|
|
24645
|
-
const pluginsDir =
|
|
24646
|
-
const nodeModulesDir =
|
|
24647
|
-
const installedPath =
|
|
24648
|
-
if (!
|
|
24999
|
+
const pluginsDir = path52.join(instanceRoot, "plugins");
|
|
25000
|
+
const nodeModulesDir = path52.join(pluginsDir, "node_modules");
|
|
25001
|
+
const installedPath = path52.join(nodeModulesDir, npmPackage);
|
|
25002
|
+
if (!fs47.existsSync(installedPath)) {
|
|
24649
25003
|
try {
|
|
24650
25004
|
clack8.log.step(`Installing ${npmPackage}...`);
|
|
24651
25005
|
execFileSync8("npm", ["install", npmPackage, "--prefix", pluginsDir, "--save"], {
|
|
@@ -24658,9 +25012,9 @@ async function runSetup(configManager, opts) {
|
|
|
24658
25012
|
}
|
|
24659
25013
|
}
|
|
24660
25014
|
try {
|
|
24661
|
-
const installedPkgPath =
|
|
24662
|
-
const installedPkg = JSON.parse(
|
|
24663
|
-
const pluginModule = await import(
|
|
25015
|
+
const installedPkgPath = path52.join(nodeModulesDir, npmPackage, "package.json");
|
|
25016
|
+
const installedPkg = JSON.parse(fs47.readFileSync(installedPkgPath, "utf-8"));
|
|
25017
|
+
const pluginModule = await import(path52.join(nodeModulesDir, npmPackage, installedPkg.main ?? "dist/index.js"));
|
|
24664
25018
|
const plugin2 = pluginModule.default;
|
|
24665
25019
|
if (plugin2?.install) {
|
|
24666
25020
|
const installCtx = createInstallContext2({
|
|
@@ -24690,8 +25044,8 @@ async function runSetup(configManager, opts) {
|
|
|
24690
25044
|
if (channelId.startsWith("community:")) {
|
|
24691
25045
|
const npmPackage = channelId.slice("community:".length);
|
|
24692
25046
|
const { execFileSync: execFileSync8 } = await import("child_process");
|
|
24693
|
-
const pluginsDir =
|
|
24694
|
-
const nodeModulesDir =
|
|
25047
|
+
const pluginsDir = path52.join(instanceRoot, "plugins");
|
|
25048
|
+
const nodeModulesDir = path52.join(pluginsDir, "node_modules");
|
|
24695
25049
|
try {
|
|
24696
25050
|
execFileSync8("npm", ["install", npmPackage, "--prefix", pluginsDir, "--save"], {
|
|
24697
25051
|
stdio: "inherit",
|
|
@@ -24703,9 +25057,9 @@ async function runSetup(configManager, opts) {
|
|
|
24703
25057
|
}
|
|
24704
25058
|
try {
|
|
24705
25059
|
const { readFileSync: readFileSync18 } = await import("fs");
|
|
24706
|
-
const installedPkgPath =
|
|
25060
|
+
const installedPkgPath = path52.join(nodeModulesDir, npmPackage, "package.json");
|
|
24707
25061
|
const installedPkg = JSON.parse(readFileSync18(installedPkgPath, "utf-8"));
|
|
24708
|
-
const pluginModule = await import(
|
|
25062
|
+
const pluginModule = await import(path52.join(nodeModulesDir, npmPackage, installedPkg.main ?? "dist/index.js"));
|
|
24709
25063
|
const plugin2 = pluginModule.default;
|
|
24710
25064
|
if (plugin2?.install) {
|
|
24711
25065
|
const installCtx = createInstallContext2({
|
|
@@ -24737,7 +25091,7 @@ async function runSetup(configManager, opts) {
|
|
|
24737
25091
|
const { defaultAgent } = await setupAgents();
|
|
24738
25092
|
await setupIntegrations();
|
|
24739
25093
|
currentStep++;
|
|
24740
|
-
const workspace = await setupWorkspace({ stepNum: currentStep, totalSteps });
|
|
25094
|
+
const workspace = await setupWorkspace({ stepNum: currentStep, totalSteps, isGlobal });
|
|
24741
25095
|
let runMode = "foreground";
|
|
24742
25096
|
let autoStart = false;
|
|
24743
25097
|
if (!opts?.skipRunMode) {
|
|
@@ -24760,7 +25114,7 @@ async function runSetup(configManager, opts) {
|
|
|
24760
25114
|
security,
|
|
24761
25115
|
logging: {
|
|
24762
25116
|
level: "info",
|
|
24763
|
-
logDir:
|
|
25117
|
+
logDir: path52.join(instanceRoot, "logs"),
|
|
24764
25118
|
maxFileSize: "10m",
|
|
24765
25119
|
maxFiles: 7,
|
|
24766
25120
|
sessionLogRetentionDays: 30
|
|
@@ -24806,9 +25160,17 @@ async function runSetup(configManager, opts) {
|
|
|
24806
25160
|
await registerBuiltinPlugins(settingsManager, pluginRegistry);
|
|
24807
25161
|
await pluginRegistry.save();
|
|
24808
25162
|
}
|
|
24809
|
-
const
|
|
24810
|
-
|
|
24811
|
-
|
|
25163
|
+
const existingEntry = instanceRegistry.getByRoot(instanceRoot);
|
|
25164
|
+
if (!existingEntry) {
|
|
25165
|
+
const id = instanceRegistry.uniqueId(generateSlug(instanceName));
|
|
25166
|
+
instanceRegistry.register(id, instanceRoot);
|
|
25167
|
+
await instanceRegistry.save();
|
|
25168
|
+
}
|
|
25169
|
+
const isLocal = instanceRoot !== path52.join(getGlobalRoot());
|
|
25170
|
+
if (isLocal) {
|
|
25171
|
+
const projectDir = path52.dirname(instanceRoot);
|
|
25172
|
+
protectLocalInstance(projectDir);
|
|
25173
|
+
}
|
|
24812
25174
|
clack8.outro(`Config saved to ${configManager.getConfigPath()}`);
|
|
24813
25175
|
if (!opts?.skipRunMode) {
|
|
24814
25176
|
console.log(ok("Starting OpenACP..."));
|
|
@@ -24942,6 +25304,7 @@ var init_wizard = __esm({
|
|
|
24942
25304
|
init_instance_registry();
|
|
24943
25305
|
init_instance_context();
|
|
24944
25306
|
init_instance_copy();
|
|
25307
|
+
init_git_protect();
|
|
24945
25308
|
}
|
|
24946
25309
|
});
|
|
24947
25310
|
|
|
@@ -25092,8 +25455,8 @@ var dev_loader_exports = {};
|
|
|
25092
25455
|
__export(dev_loader_exports, {
|
|
25093
25456
|
DevPluginLoader: () => DevPluginLoader
|
|
25094
25457
|
});
|
|
25095
|
-
import
|
|
25096
|
-
import
|
|
25458
|
+
import fs48 from "fs";
|
|
25459
|
+
import path53 from "path";
|
|
25097
25460
|
var loadCounter, DevPluginLoader;
|
|
25098
25461
|
var init_dev_loader = __esm({
|
|
25099
25462
|
"src/core/plugin/dev-loader.ts"() {
|
|
@@ -25102,15 +25465,15 @@ var init_dev_loader = __esm({
|
|
|
25102
25465
|
DevPluginLoader = class {
|
|
25103
25466
|
pluginPath;
|
|
25104
25467
|
constructor(pluginPath) {
|
|
25105
|
-
this.pluginPath =
|
|
25468
|
+
this.pluginPath = path53.resolve(pluginPath);
|
|
25106
25469
|
}
|
|
25107
25470
|
async load() {
|
|
25108
|
-
const distIndex =
|
|
25109
|
-
const srcIndex =
|
|
25110
|
-
if (!
|
|
25471
|
+
const distIndex = path53.join(this.pluginPath, "dist", "index.js");
|
|
25472
|
+
const srcIndex = path53.join(this.pluginPath, "src", "index.ts");
|
|
25473
|
+
if (!fs48.existsSync(distIndex) && !fs48.existsSync(srcIndex)) {
|
|
25111
25474
|
throw new Error(`Plugin not found at ${this.pluginPath}. Expected dist/index.js or src/index.ts`);
|
|
25112
25475
|
}
|
|
25113
|
-
if (!
|
|
25476
|
+
if (!fs48.existsSync(distIndex)) {
|
|
25114
25477
|
throw new Error(`Built plugin not found at ${distIndex}. Run 'npm run build' first.`);
|
|
25115
25478
|
}
|
|
25116
25479
|
const cacheBuster = `v=${Date.now()}-${++loadCounter}`;
|
|
@@ -25125,7 +25488,7 @@ var init_dev_loader = __esm({
|
|
|
25125
25488
|
return this.pluginPath;
|
|
25126
25489
|
}
|
|
25127
25490
|
getDistPath() {
|
|
25128
|
-
return
|
|
25491
|
+
return path53.join(this.pluginPath, "dist");
|
|
25129
25492
|
}
|
|
25130
25493
|
};
|
|
25131
25494
|
}
|
|
@@ -25137,8 +25500,8 @@ __export(main_exports, {
|
|
|
25137
25500
|
RESTART_EXIT_CODE: () => RESTART_EXIT_CODE,
|
|
25138
25501
|
startServer: () => startServer
|
|
25139
25502
|
});
|
|
25140
|
-
import
|
|
25141
|
-
import
|
|
25503
|
+
import path54 from "path";
|
|
25504
|
+
import fs49 from "fs";
|
|
25142
25505
|
async function startServer(opts) {
|
|
25143
25506
|
const ctx = opts?.instanceContext ?? createInstanceContext({
|
|
25144
25507
|
id: "main",
|
|
@@ -25219,25 +25582,25 @@ async function startServer(opts) {
|
|
|
25219
25582
|
try {
|
|
25220
25583
|
let modulePath;
|
|
25221
25584
|
if (name.startsWith("/") || name.startsWith(".")) {
|
|
25222
|
-
const resolved =
|
|
25223
|
-
const pkgPath =
|
|
25224
|
-
const pkg = JSON.parse(await
|
|
25225
|
-
modulePath =
|
|
25585
|
+
const resolved = path54.resolve(name);
|
|
25586
|
+
const pkgPath = path54.join(resolved, "package.json");
|
|
25587
|
+
const pkg = JSON.parse(await fs49.promises.readFile(pkgPath, "utf-8"));
|
|
25588
|
+
modulePath = path54.join(resolved, pkg.main || "dist/index.js");
|
|
25226
25589
|
} else {
|
|
25227
|
-
const nodeModulesDir =
|
|
25228
|
-
let pkgDir =
|
|
25229
|
-
if (!
|
|
25590
|
+
const nodeModulesDir = path54.join(ctx.paths.plugins, "node_modules");
|
|
25591
|
+
let pkgDir = path54.join(nodeModulesDir, name);
|
|
25592
|
+
if (!fs49.existsSync(path54.join(pkgDir, "package.json"))) {
|
|
25230
25593
|
let found = false;
|
|
25231
|
-
const scopes =
|
|
25594
|
+
const scopes = fs49.existsSync(nodeModulesDir) ? fs49.readdirSync(nodeModulesDir).filter((d) => d.startsWith("@")) : [];
|
|
25232
25595
|
for (const scope of scopes) {
|
|
25233
|
-
const scopeDir =
|
|
25234
|
-
const pkgs =
|
|
25596
|
+
const scopeDir = path54.join(nodeModulesDir, scope);
|
|
25597
|
+
const pkgs = fs49.readdirSync(scopeDir);
|
|
25235
25598
|
for (const pkg2 of pkgs) {
|
|
25236
|
-
const candidateDir =
|
|
25237
|
-
const candidatePkgPath =
|
|
25238
|
-
if (
|
|
25599
|
+
const candidateDir = path54.join(scopeDir, pkg2);
|
|
25600
|
+
const candidatePkgPath = path54.join(candidateDir, "package.json");
|
|
25601
|
+
if (fs49.existsSync(candidatePkgPath)) {
|
|
25239
25602
|
try {
|
|
25240
|
-
const candidatePkg = JSON.parse(
|
|
25603
|
+
const candidatePkg = JSON.parse(fs49.readFileSync(candidatePkgPath, "utf-8"));
|
|
25241
25604
|
const pluginName = candidatePkg.openacp?.pluginName;
|
|
25242
25605
|
if (pluginName === name) {
|
|
25243
25606
|
pkgDir = candidateDir;
|
|
@@ -25251,9 +25614,9 @@ async function startServer(opts) {
|
|
|
25251
25614
|
if (found) break;
|
|
25252
25615
|
}
|
|
25253
25616
|
}
|
|
25254
|
-
const pkgJsonPath =
|
|
25255
|
-
const pkg = JSON.parse(await
|
|
25256
|
-
modulePath =
|
|
25617
|
+
const pkgJsonPath = path54.join(pkgDir, "package.json");
|
|
25618
|
+
const pkg = JSON.parse(await fs49.promises.readFile(pkgJsonPath, "utf-8"));
|
|
25619
|
+
modulePath = path54.join(pkgDir, pkg.main || "dist/index.js");
|
|
25257
25620
|
}
|
|
25258
25621
|
log.debug({ plugin: name, modulePath }, "Loading community plugin");
|
|
25259
25622
|
const mod = await import(modulePath);
|
|
@@ -25284,7 +25647,7 @@ async function startServer(opts) {
|
|
|
25284
25647
|
if (!opts.noWatch) {
|
|
25285
25648
|
const distPath = devLoader.getDistPath();
|
|
25286
25649
|
let reloadTimer = null;
|
|
25287
|
-
|
|
25650
|
+
fs49.watch(distPath, { recursive: true }, (_eventType, filename) => {
|
|
25288
25651
|
if (!filename?.endsWith(".js")) return;
|
|
25289
25652
|
if (reloadTimer) clearTimeout(reloadTimer);
|
|
25290
25653
|
reloadTimer = setTimeout(async () => {
|
|
@@ -25362,21 +25725,21 @@ async function startServer(opts) {
|
|
|
25362
25725
|
if (isDaemon) {
|
|
25363
25726
|
const { spawn: spawnChild } = await import("child_process");
|
|
25364
25727
|
const { expandHome: expandHome4 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
25365
|
-
const
|
|
25728
|
+
const fs53 = await import("fs");
|
|
25366
25729
|
const pathMod2 = await import("path");
|
|
25367
25730
|
const cliPath = pathMod2.resolve(process.argv[1]);
|
|
25368
25731
|
const resolvedLogDir = expandHome4(config.logging.logDir);
|
|
25369
|
-
|
|
25732
|
+
fs53.mkdirSync(resolvedLogDir, { recursive: true });
|
|
25370
25733
|
const logFile = pathMod2.join(resolvedLogDir, "openacp.log");
|
|
25371
|
-
const out =
|
|
25372
|
-
const err =
|
|
25734
|
+
const out = fs53.openSync(logFile, "a");
|
|
25735
|
+
const err = fs53.openSync(logFile, "a");
|
|
25373
25736
|
const child = spawnChild(process.execPath, [cliPath, "--daemon-child"], {
|
|
25374
25737
|
detached: true,
|
|
25375
25738
|
stdio: ["ignore", out, err],
|
|
25376
25739
|
env: { ...process.env, OPENACP_SKIP_UPDATE_CHECK: "1" }
|
|
25377
25740
|
});
|
|
25378
|
-
|
|
25379
|
-
|
|
25741
|
+
fs53.closeSync(out);
|
|
25742
|
+
fs53.closeSync(err);
|
|
25380
25743
|
child.unref();
|
|
25381
25744
|
log.info({ newPid: child.pid }, "Respawned daemon for restart");
|
|
25382
25745
|
} else if (!process.env.OPENACP_DEV_LOOP) {
|
|
@@ -25405,7 +25768,7 @@ async function startServer(opts) {
|
|
|
25405
25768
|
await core.start();
|
|
25406
25769
|
try {
|
|
25407
25770
|
const globalRoot = getGlobalRoot();
|
|
25408
|
-
const registryPath =
|
|
25771
|
+
const registryPath = path54.join(globalRoot, "instances.json");
|
|
25409
25772
|
const instanceReg = new InstanceRegistry(registryPath);
|
|
25410
25773
|
await instanceReg.load();
|
|
25411
25774
|
if (!instanceReg.getByRoot(ctx.root)) {
|
|
@@ -25553,10 +25916,10 @@ var restart_exports = {};
|
|
|
25553
25916
|
__export(restart_exports, {
|
|
25554
25917
|
cmdRestart: () => cmdRestart
|
|
25555
25918
|
});
|
|
25556
|
-
import
|
|
25557
|
-
import
|
|
25919
|
+
import path55 from "path";
|
|
25920
|
+
import os26 from "os";
|
|
25558
25921
|
async function cmdRestart(args2 = [], instanceRoot) {
|
|
25559
|
-
const
|
|
25922
|
+
const root = instanceRoot ?? path55.join(os26.homedir(), ".openacp");
|
|
25560
25923
|
if (wantsHelp(args2)) {
|
|
25561
25924
|
console.log(`
|
|
25562
25925
|
\x1B[1mopenacp restart\x1B[0m \u2014 Restart the background daemon
|
|
@@ -25581,8 +25944,8 @@ Stops the running daemon (if any) and starts a new one.
|
|
|
25581
25944
|
const { ConfigManager: ConfigManager2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
25582
25945
|
const { checkAndPromptUpdate: checkAndPromptUpdate2 } = await Promise.resolve().then(() => (init_version(), version_exports));
|
|
25583
25946
|
await checkAndPromptUpdate2();
|
|
25584
|
-
const pidPath = getPidPath2(
|
|
25585
|
-
const stopResult = await stopDaemon2(pidPath,
|
|
25947
|
+
const pidPath = getPidPath2(root);
|
|
25948
|
+
const stopResult = await stopDaemon2(pidPath, root);
|
|
25586
25949
|
if (stopResult.stopped) {
|
|
25587
25950
|
console.log(`Stopped daemon (was PID ${stopResult.pid})`);
|
|
25588
25951
|
}
|
|
@@ -25595,23 +25958,23 @@ Stops the running daemon (if any) and starts a new one.
|
|
|
25595
25958
|
const config = cm.get();
|
|
25596
25959
|
const useForeground = forceForeground || !forceDaemon && config.runMode !== "daemon";
|
|
25597
25960
|
if (useForeground) {
|
|
25598
|
-
markRunning2(
|
|
25599
|
-
printInstanceHint(
|
|
25961
|
+
markRunning2(root);
|
|
25962
|
+
printInstanceHint(root);
|
|
25600
25963
|
console.log("Starting in foreground mode...");
|
|
25601
25964
|
const { startServer: startServer2 } = await Promise.resolve().then(() => (init_main(), main_exports));
|
|
25602
25965
|
const ctx = createInstanceContext({
|
|
25603
25966
|
id: "default",
|
|
25604
|
-
root
|
|
25605
|
-
isGlobal:
|
|
25967
|
+
root,
|
|
25968
|
+
isGlobal: root === getGlobalRoot()
|
|
25606
25969
|
});
|
|
25607
25970
|
await startServer2({ instanceContext: ctx });
|
|
25608
25971
|
} else {
|
|
25609
|
-
const result = startDaemon2(pidPath, config.logging.logDir,
|
|
25972
|
+
const result = startDaemon2(pidPath, config.logging.logDir, root);
|
|
25610
25973
|
if ("error" in result) {
|
|
25611
25974
|
console.error(result.error);
|
|
25612
25975
|
process.exit(1);
|
|
25613
25976
|
}
|
|
25614
|
-
printInstanceHint(
|
|
25977
|
+
printInstanceHint(root);
|
|
25615
25978
|
console.log(`OpenACP daemon started (PID ${result.pid})`);
|
|
25616
25979
|
}
|
|
25617
25980
|
}
|
|
@@ -25631,9 +25994,9 @@ __export(status_exports, {
|
|
|
25631
25994
|
formatInstanceStatus: () => formatInstanceStatus,
|
|
25632
25995
|
readInstanceInfo: () => readInstanceInfo
|
|
25633
25996
|
});
|
|
25634
|
-
import
|
|
25635
|
-
import
|
|
25636
|
-
import
|
|
25997
|
+
import fs50 from "fs";
|
|
25998
|
+
import path56 from "path";
|
|
25999
|
+
import os27 from "os";
|
|
25637
26000
|
async function cmdStatus(args2 = [], instanceRoot) {
|
|
25638
26001
|
if (args2.includes("--all")) {
|
|
25639
26002
|
await showAllInstances();
|
|
@@ -25644,16 +26007,16 @@ async function cmdStatus(args2 = [], instanceRoot) {
|
|
|
25644
26007
|
await showInstanceById(args2[idIdx + 1]);
|
|
25645
26008
|
return;
|
|
25646
26009
|
}
|
|
25647
|
-
const
|
|
25648
|
-
await showSingleInstance(
|
|
26010
|
+
const root = instanceRoot ?? getGlobalRoot();
|
|
26011
|
+
await showSingleInstance(root);
|
|
25649
26012
|
}
|
|
25650
26013
|
async function showAllInstances() {
|
|
25651
|
-
const registryPath =
|
|
26014
|
+
const registryPath = path56.join(getGlobalRoot(), "instances.json");
|
|
25652
26015
|
const registry = new InstanceRegistry(registryPath);
|
|
25653
26016
|
await registry.load();
|
|
25654
26017
|
const instances = registry.list();
|
|
25655
26018
|
if (instances.length === 0) {
|
|
25656
|
-
console.log("No
|
|
26019
|
+
console.log("No workspaces registered.");
|
|
25657
26020
|
return;
|
|
25658
26021
|
}
|
|
25659
26022
|
console.log("");
|
|
@@ -25665,7 +26028,7 @@ async function showAllInstances() {
|
|
|
25665
26028
|
const mode = info.pid ? info.runMode === "daemon" ? "daemon" : "fg" : "\u2014";
|
|
25666
26029
|
const api = info.apiPort ? String(info.apiPort) : "\u2014";
|
|
25667
26030
|
const tunnel = info.tunnelPort ? String(info.tunnelPort) : "\u2014";
|
|
25668
|
-
const dir = entry.root.replace(/\/.openacp$/, "").replace(
|
|
26031
|
+
const dir = entry.root.replace(/\/.openacp$/, "").replace(os27.homedir(), "~");
|
|
25669
26032
|
const channels = info.channels.join(", ") || "\u2014";
|
|
25670
26033
|
const name = info.name ?? entry.id;
|
|
25671
26034
|
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}`);
|
|
@@ -25673,18 +26036,18 @@ async function showAllInstances() {
|
|
|
25673
26036
|
console.log("");
|
|
25674
26037
|
}
|
|
25675
26038
|
async function showInstanceById(id) {
|
|
25676
|
-
const registryPath =
|
|
26039
|
+
const registryPath = path56.join(getGlobalRoot(), "instances.json");
|
|
25677
26040
|
const registry = new InstanceRegistry(registryPath);
|
|
25678
26041
|
await registry.load();
|
|
25679
26042
|
const entry = registry.get(id);
|
|
25680
26043
|
if (!entry) {
|
|
25681
|
-
console.error(`
|
|
26044
|
+
console.error(`Workspace "${id}" not found.`);
|
|
25682
26045
|
process.exit(1);
|
|
25683
26046
|
}
|
|
25684
26047
|
await showSingleInstance(entry.root);
|
|
25685
26048
|
}
|
|
25686
|
-
async function showSingleInstance(
|
|
25687
|
-
const info = readInstanceInfo(
|
|
26049
|
+
async function showSingleInstance(root) {
|
|
26050
|
+
const info = readInstanceInfo(root);
|
|
25688
26051
|
if (info.pid) {
|
|
25689
26052
|
console.log(`OpenACP is running (PID ${info.pid})`);
|
|
25690
26053
|
if (info.name) console.log(` Name: ${info.name}`);
|
|
@@ -25695,7 +26058,7 @@ async function showSingleInstance(root2) {
|
|
|
25695
26058
|
console.log("OpenACP is not running.");
|
|
25696
26059
|
}
|
|
25697
26060
|
}
|
|
25698
|
-
function readInstanceInfo(
|
|
26061
|
+
function readInstanceInfo(root) {
|
|
25699
26062
|
const result = {
|
|
25700
26063
|
name: null,
|
|
25701
26064
|
pid: null,
|
|
@@ -25705,13 +26068,13 @@ function readInstanceInfo(root2) {
|
|
|
25705
26068
|
channels: []
|
|
25706
26069
|
};
|
|
25707
26070
|
try {
|
|
25708
|
-
const config = JSON.parse(
|
|
26071
|
+
const config = JSON.parse(fs50.readFileSync(path56.join(root, "config.json"), "utf-8"));
|
|
25709
26072
|
result.name = config.instanceName ?? null;
|
|
25710
26073
|
result.runMode = config.runMode ?? null;
|
|
25711
26074
|
} catch {
|
|
25712
26075
|
}
|
|
25713
26076
|
try {
|
|
25714
|
-
const pid = parseInt(
|
|
26077
|
+
const pid = parseInt(fs50.readFileSync(path56.join(root, "openacp.pid"), "utf-8").trim());
|
|
25715
26078
|
if (!isNaN(pid)) {
|
|
25716
26079
|
process.kill(pid, 0);
|
|
25717
26080
|
result.pid = pid;
|
|
@@ -25719,19 +26082,19 @@ function readInstanceInfo(root2) {
|
|
|
25719
26082
|
} catch {
|
|
25720
26083
|
}
|
|
25721
26084
|
try {
|
|
25722
|
-
const port = parseInt(
|
|
26085
|
+
const port = parseInt(fs50.readFileSync(path56.join(root, "api.port"), "utf-8").trim());
|
|
25723
26086
|
if (!isNaN(port)) result.apiPort = port;
|
|
25724
26087
|
} catch {
|
|
25725
26088
|
}
|
|
25726
26089
|
try {
|
|
25727
|
-
const tunnels = JSON.parse(
|
|
26090
|
+
const tunnels = JSON.parse(fs50.readFileSync(path56.join(root, "tunnels.json"), "utf-8"));
|
|
25728
26091
|
const entries = Object.values(tunnels);
|
|
25729
26092
|
const systemEntry = entries.find((t) => t.type === "system");
|
|
25730
26093
|
if (systemEntry?.port) result.tunnelPort = systemEntry.port;
|
|
25731
26094
|
} catch {
|
|
25732
26095
|
}
|
|
25733
26096
|
try {
|
|
25734
|
-
const plugins = JSON.parse(
|
|
26097
|
+
const plugins = JSON.parse(fs50.readFileSync(path56.join(root, "plugins.json"), "utf-8"));
|
|
25735
26098
|
const adapters = ["@openacp/telegram", "@openacp/discord", "@openacp/slack"];
|
|
25736
26099
|
for (const name of adapters) {
|
|
25737
26100
|
if (plugins.installed?.[name] && plugins.installed[name].enabled !== false) {
|
|
@@ -25742,15 +26105,15 @@ function readInstanceInfo(root2) {
|
|
|
25742
26105
|
}
|
|
25743
26106
|
return result;
|
|
25744
26107
|
}
|
|
25745
|
-
function formatInstanceStatus(
|
|
25746
|
-
const info = readInstanceInfo(
|
|
26108
|
+
function formatInstanceStatus(root) {
|
|
26109
|
+
const info = readInstanceInfo(root);
|
|
25747
26110
|
if (!info.pid) return null;
|
|
25748
|
-
const
|
|
25749
|
-
const
|
|
26111
|
+
const isGlobal = root === getGlobalRoot();
|
|
26112
|
+
const displayPath = root.replace(os27.homedir(), "~");
|
|
25750
26113
|
const label = isGlobal ? "global" : "local";
|
|
25751
26114
|
const lines = [];
|
|
25752
26115
|
lines.push(` PID: ${info.pid}`);
|
|
25753
|
-
lines.push(`
|
|
26116
|
+
lines.push(` Workspace: ${info.name ?? "unknown"} (${label} \u2014 ${displayPath})`);
|
|
25754
26117
|
lines.push(` Mode: ${info.runMode ?? "unknown"}`);
|
|
25755
26118
|
if (info.channels.length > 0) lines.push(` Channels: ${info.channels.join(", ")}`);
|
|
25756
26119
|
if (info.apiPort) lines.push(` API: port ${info.apiPort}`);
|
|
@@ -25814,7 +26177,7 @@ var config_editor_exports = {};
|
|
|
25814
26177
|
__export(config_editor_exports, {
|
|
25815
26178
|
runConfigEditor: () => runConfigEditor
|
|
25816
26179
|
});
|
|
25817
|
-
import * as
|
|
26180
|
+
import * as path57 from "path";
|
|
25818
26181
|
import * as clack9 from "@clack/prompts";
|
|
25819
26182
|
async function select8(opts) {
|
|
25820
26183
|
const result = await clack9.select({
|
|
@@ -25974,14 +26337,14 @@ async function editDiscord(_config, _updates) {
|
|
|
25974
26337
|
const { SettingsManager: SettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), settings_manager_exports));
|
|
25975
26338
|
const { createInstallContext: createInstallContext2 } = await Promise.resolve().then(() => (init_install_context(), install_context_exports));
|
|
25976
26339
|
const { getGlobalRoot: getGlobalRoot2 } = await Promise.resolve().then(() => (init_instance_context(), instance_context_exports));
|
|
25977
|
-
const
|
|
25978
|
-
const basePath =
|
|
26340
|
+
const root = getGlobalRoot2();
|
|
26341
|
+
const basePath = path57.join(root, "plugins");
|
|
25979
26342
|
const settingsManager = new SettingsManager2(basePath);
|
|
25980
26343
|
const ctx = createInstallContext2({
|
|
25981
26344
|
pluginName: plugin2.name,
|
|
25982
26345
|
settingsManager,
|
|
25983
26346
|
basePath,
|
|
25984
|
-
instanceRoot:
|
|
26347
|
+
instanceRoot: root
|
|
25985
26348
|
});
|
|
25986
26349
|
await plugin2.configure(ctx);
|
|
25987
26350
|
} else {
|
|
@@ -26438,17 +26801,17 @@ ${c2.cyan}${c2.bold}OpenACP Config Editor${c2.reset}`);
|
|
|
26438
26801
|
async function sendConfigViaApi(port, updates) {
|
|
26439
26802
|
const { apiCall: call } = await Promise.resolve().then(() => (init_api_client(), api_client_exports));
|
|
26440
26803
|
const paths = flattenToPaths(updates);
|
|
26441
|
-
for (const { path:
|
|
26804
|
+
for (const { path: path65, value } of paths) {
|
|
26442
26805
|
const res = await call(port, "/api/config", {
|
|
26443
26806
|
method: "PATCH",
|
|
26444
26807
|
headers: { "Content-Type": "application/json" },
|
|
26445
|
-
body: JSON.stringify({ path:
|
|
26808
|
+
body: JSON.stringify({ path: path65, value })
|
|
26446
26809
|
});
|
|
26447
26810
|
const data = await res.json();
|
|
26448
26811
|
if (!res.ok) {
|
|
26449
|
-
console.log(warn2(`Failed to update ${
|
|
26812
|
+
console.log(warn2(`Failed to update ${path65}: ${data.error}`));
|
|
26450
26813
|
} else if (data.needsRestart) {
|
|
26451
|
-
console.log(warn2(`${
|
|
26814
|
+
console.log(warn2(`${path65} updated \u2014 restart required`));
|
|
26452
26815
|
}
|
|
26453
26816
|
}
|
|
26454
26817
|
}
|
|
@@ -26551,9 +26914,78 @@ var init_interactive_menu = __esm({
|
|
|
26551
26914
|
}
|
|
26552
26915
|
});
|
|
26553
26916
|
|
|
26917
|
+
// src/cli/instance-prompt.ts
|
|
26918
|
+
var instance_prompt_exports = {};
|
|
26919
|
+
__export(instance_prompt_exports, {
|
|
26920
|
+
promptForInstance: () => promptForInstance
|
|
26921
|
+
});
|
|
26922
|
+
import fs52 from "fs";
|
|
26923
|
+
import path63 from "path";
|
|
26924
|
+
import os31 from "os";
|
|
26925
|
+
async function promptForInstance(opts) {
|
|
26926
|
+
const globalRoot = getGlobalRoot();
|
|
26927
|
+
const globalConfigExists = fs52.existsSync(path63.join(globalRoot, "config.json"));
|
|
26928
|
+
const cwd = process.cwd();
|
|
26929
|
+
const localRoot = path63.join(cwd, ".openacp");
|
|
26930
|
+
if (!globalConfigExists) return globalRoot;
|
|
26931
|
+
const isTTY = process.stdin.isTTY && process.stdout.isTTY;
|
|
26932
|
+
if (!isTTY) return globalRoot;
|
|
26933
|
+
const registryPath = path63.join(globalRoot, "instances.json");
|
|
26934
|
+
const registry = new InstanceRegistry(registryPath);
|
|
26935
|
+
registry.load();
|
|
26936
|
+
const instances = registry.list().filter((e) => fs52.existsSync(e.root));
|
|
26937
|
+
const instanceOptions = instances.map((e) => {
|
|
26938
|
+
let name = e.id;
|
|
26939
|
+
try {
|
|
26940
|
+
const raw = fs52.readFileSync(path63.join(e.root, "config.json"), "utf-8");
|
|
26941
|
+
const parsed = JSON.parse(raw);
|
|
26942
|
+
if (parsed.instanceName) name = parsed.instanceName;
|
|
26943
|
+
} catch {
|
|
26944
|
+
}
|
|
26945
|
+
const isGlobal = e.root === globalRoot;
|
|
26946
|
+
const displayPath = e.root.replace(os31.homedir(), "~");
|
|
26947
|
+
const type = isGlobal ? "global" : "local";
|
|
26948
|
+
return { value: e.root, label: `${name} workspace (${type} \u2014 ${displayPath})` };
|
|
26949
|
+
});
|
|
26950
|
+
if (instanceOptions.length === 0) {
|
|
26951
|
+
const globalDisplay = globalRoot.replace(os31.homedir(), "~");
|
|
26952
|
+
instanceOptions.push({ value: globalRoot, label: `Global workspace (${globalDisplay})` });
|
|
26953
|
+
}
|
|
26954
|
+
if (instanceOptions.length === 1 && !opts.allowCreate) {
|
|
26955
|
+
return instanceOptions[0].value;
|
|
26956
|
+
}
|
|
26957
|
+
const options = instanceOptions.map((o) => ({
|
|
26958
|
+
value: o.value,
|
|
26959
|
+
label: o.label
|
|
26960
|
+
}));
|
|
26961
|
+
if (opts.allowCreate) {
|
|
26962
|
+
const localDisplay = localRoot.replace(os31.homedir(), "~");
|
|
26963
|
+
options.push({ value: localRoot, label: `New local workspace (${localDisplay})` });
|
|
26964
|
+
}
|
|
26965
|
+
const clack10 = await import("@clack/prompts");
|
|
26966
|
+
const choice = await clack10.select({
|
|
26967
|
+
message: "How would you like to run OpenACP?",
|
|
26968
|
+
options
|
|
26969
|
+
});
|
|
26970
|
+
if (clack10.isCancel(choice)) {
|
|
26971
|
+
process.exit(0);
|
|
26972
|
+
}
|
|
26973
|
+
if (choice === localRoot) {
|
|
26974
|
+
console.log(`\x1B[2mTip: next time use \`openacp --local\`\x1B[0m`);
|
|
26975
|
+
}
|
|
26976
|
+
return choice;
|
|
26977
|
+
}
|
|
26978
|
+
var init_instance_prompt = __esm({
|
|
26979
|
+
"src/cli/instance-prompt.ts"() {
|
|
26980
|
+
"use strict";
|
|
26981
|
+
init_instance_context();
|
|
26982
|
+
init_instance_registry();
|
|
26983
|
+
}
|
|
26984
|
+
});
|
|
26985
|
+
|
|
26554
26986
|
// src/cli.ts
|
|
26555
26987
|
import { setDefaultAutoSelectFamily } from "net";
|
|
26556
|
-
import
|
|
26988
|
+
import path64 from "path";
|
|
26557
26989
|
|
|
26558
26990
|
// src/cli/commands/help.ts
|
|
26559
26991
|
function printHelp() {
|
|
@@ -26633,12 +27065,12 @@ Connect messaging platforms (Telegram, Discord) to 28+ AI coding agents via ACP
|
|
|
26633
27065
|
openacp api health System health check
|
|
26634
27066
|
openacp api restart Restart daemon
|
|
26635
27067
|
|
|
26636
|
-
\x1B[
|
|
26637
|
-
--local Use
|
|
26638
|
-
--global Use
|
|
26639
|
-
--dir <path> Use
|
|
26640
|
-
--from <path> Copy settings from existing
|
|
26641
|
-
--name <name> Set
|
|
27068
|
+
\x1B[1mWorkspace Flags:\x1B[0m
|
|
27069
|
+
--local Use workspace in current directory
|
|
27070
|
+
--global Use global workspace (~/.openacp)
|
|
27071
|
+
--dir <path> Use workspace at specified directory
|
|
27072
|
+
--from <path> Copy settings from existing workspace (on create)
|
|
27073
|
+
--name <name> Set workspace name (on create)
|
|
26642
27074
|
|
|
26643
27075
|
\x1B[2mMore info: https://github.com/Open-ACP/OpenACP\x1B[0m
|
|
26644
27076
|
`);
|
|
@@ -26657,8 +27089,8 @@ import * as fs from "fs";
|
|
|
26657
27089
|
import * as path from "path";
|
|
26658
27090
|
import * as os from "os";
|
|
26659
27091
|
async function cmdInstall(args2, instanceRoot) {
|
|
26660
|
-
const
|
|
26661
|
-
const pluginsDir = path.join(
|
|
27092
|
+
const root = instanceRoot ?? path.join(os.homedir(), ".openacp");
|
|
27093
|
+
const pluginsDir = path.join(root, "plugins");
|
|
26662
27094
|
if (wantsHelp(args2)) {
|
|
26663
27095
|
console.log(`
|
|
26664
27096
|
\x1B[1mopenacp install\x1B[0m \u2014 Install a plugin adapter
|
|
@@ -26698,8 +27130,8 @@ import * as fs2 from "fs";
|
|
|
26698
27130
|
import * as path2 from "path";
|
|
26699
27131
|
import * as os2 from "os";
|
|
26700
27132
|
async function cmdUninstall(args2, instanceRoot) {
|
|
26701
|
-
const
|
|
26702
|
-
const pluginsDir = path2.join(
|
|
27133
|
+
const root = instanceRoot ?? path2.join(os2.homedir(), ".openacp");
|
|
27134
|
+
const pluginsDir = path2.join(root, "plugins");
|
|
26703
27135
|
if (wantsHelp(args2)) {
|
|
26704
27136
|
console.log(`
|
|
26705
27137
|
\x1B[1mopenacp uninstall\x1B[0m \u2014 Remove a plugin adapter
|
|
@@ -26744,11 +27176,11 @@ Shows all plugins registered in the plugin registry.
|
|
|
26744
27176
|
`);
|
|
26745
27177
|
return;
|
|
26746
27178
|
}
|
|
26747
|
-
const
|
|
26748
|
-
const
|
|
27179
|
+
const os32 = await import("os");
|
|
27180
|
+
const path65 = await import("path");
|
|
26749
27181
|
const { PluginRegistry: PluginRegistry2 } = await Promise.resolve().then(() => (init_plugin_registry(), plugin_registry_exports));
|
|
26750
|
-
const
|
|
26751
|
-
const registryPath =
|
|
27182
|
+
const root = instanceRoot ?? path65.join(os32.homedir(), ".openacp");
|
|
27183
|
+
const registryPath = path65.join(root, "plugins.json");
|
|
26752
27184
|
const registry = new PluginRegistry2(registryPath);
|
|
26753
27185
|
await registry.load();
|
|
26754
27186
|
const plugins = registry.list();
|
|
@@ -26763,7 +27195,7 @@ Shows all plugins registered in the plugin registry.
|
|
|
26763
27195
|
}
|
|
26764
27196
|
}
|
|
26765
27197
|
async function cmdPlugin(args2 = [], instanceRoot) {
|
|
26766
|
-
const subcommand = args2[
|
|
27198
|
+
const subcommand = args2[0];
|
|
26767
27199
|
if (wantsHelp(args2) || !subcommand) {
|
|
26768
27200
|
console.log(`
|
|
26769
27201
|
\x1B[1mopenacp plugin\x1B[0m \u2014 Plugin management
|
|
@@ -26771,7 +27203,8 @@ async function cmdPlugin(args2 = [], instanceRoot) {
|
|
|
26771
27203
|
\x1B[1mUsage:\x1B[0m
|
|
26772
27204
|
openacp plugin list List all plugins with status
|
|
26773
27205
|
openacp plugin search <query> Search the plugin registry
|
|
26774
|
-
openacp plugin add <package>[@version] Install a plugin
|
|
27206
|
+
openacp plugin add <package>[@version] Install a plugin from npm
|
|
27207
|
+
openacp plugin add <dir> Install a plugin from local directory
|
|
26775
27208
|
openacp plugin install <package> Alias for add
|
|
26776
27209
|
openacp plugin remove <package> Remove a plugin package
|
|
26777
27210
|
openacp plugin uninstall <package> Alias for remove (--purge to delete data)
|
|
@@ -26785,6 +27218,7 @@ async function cmdPlugin(args2 = [], instanceRoot) {
|
|
|
26785
27218
|
openacp plugin search telegram
|
|
26786
27219
|
openacp plugin add @openacp/adapter-discord
|
|
26787
27220
|
openacp plugin add translator@1.2.0
|
|
27221
|
+
openacp plugin add ./my-plugin Install from local directory
|
|
26788
27222
|
openacp plugin enable @openacp/adapter-discord
|
|
26789
27223
|
openacp plugin configure @openacp/adapter-discord
|
|
26790
27224
|
openacp plugin remove @openacp/adapter-discord --purge
|
|
@@ -26793,15 +27227,15 @@ async function cmdPlugin(args2 = [], instanceRoot) {
|
|
|
26793
27227
|
}
|
|
26794
27228
|
switch (subcommand) {
|
|
26795
27229
|
case "list":
|
|
26796
|
-
return cmdPlugins(
|
|
27230
|
+
return cmdPlugins([], instanceRoot);
|
|
26797
27231
|
case "search": {
|
|
26798
27232
|
const { cmdPluginSearch: cmdPluginSearch2 } = await Promise.resolve().then(() => (init_plugin_search(), plugin_search_exports));
|
|
26799
|
-
await cmdPluginSearch2(args2.slice(
|
|
27233
|
+
await cmdPluginSearch2(args2.slice(1));
|
|
26800
27234
|
return;
|
|
26801
27235
|
}
|
|
26802
27236
|
case "add":
|
|
26803
27237
|
case "install": {
|
|
26804
|
-
const pkg = args2[
|
|
27238
|
+
const pkg = args2[1];
|
|
26805
27239
|
if (!pkg) {
|
|
26806
27240
|
console.error("Error: missing package name. Usage: openacp plugin add <package>");
|
|
26807
27241
|
process.exit(1);
|
|
@@ -26811,7 +27245,7 @@ async function cmdPlugin(args2 = [], instanceRoot) {
|
|
|
26811
27245
|
}
|
|
26812
27246
|
case "remove":
|
|
26813
27247
|
case "uninstall": {
|
|
26814
|
-
const pkg = args2[
|
|
27248
|
+
const pkg = args2[1];
|
|
26815
27249
|
if (!pkg) {
|
|
26816
27250
|
console.error("Error: missing package name. Usage: openacp plugin remove <package> [--purge]");
|
|
26817
27251
|
process.exit(1);
|
|
@@ -26821,7 +27255,7 @@ async function cmdPlugin(args2 = [], instanceRoot) {
|
|
|
26821
27255
|
return;
|
|
26822
27256
|
}
|
|
26823
27257
|
case "enable": {
|
|
26824
|
-
const name = args2[
|
|
27258
|
+
const name = args2[1];
|
|
26825
27259
|
if (!name) {
|
|
26826
27260
|
console.error("Error: missing plugin name. Usage: openacp plugin enable <name>");
|
|
26827
27261
|
process.exit(1);
|
|
@@ -26830,7 +27264,7 @@ async function cmdPlugin(args2 = [], instanceRoot) {
|
|
|
26830
27264
|
return;
|
|
26831
27265
|
}
|
|
26832
27266
|
case "disable": {
|
|
26833
|
-
const name = args2[
|
|
27267
|
+
const name = args2[1];
|
|
26834
27268
|
if (!name) {
|
|
26835
27269
|
console.error("Error: missing plugin name. Usage: openacp plugin disable <name>");
|
|
26836
27270
|
process.exit(1);
|
|
@@ -26839,7 +27273,7 @@ async function cmdPlugin(args2 = [], instanceRoot) {
|
|
|
26839
27273
|
return;
|
|
26840
27274
|
}
|
|
26841
27275
|
case "configure": {
|
|
26842
|
-
const name = args2[
|
|
27276
|
+
const name = args2[1];
|
|
26843
27277
|
if (!name) {
|
|
26844
27278
|
console.error("Error: missing plugin name. Usage: openacp plugin configure <name>");
|
|
26845
27279
|
process.exit(1);
|
|
@@ -26859,11 +27293,11 @@ async function cmdPlugin(args2 = [], instanceRoot) {
|
|
|
26859
27293
|
}
|
|
26860
27294
|
}
|
|
26861
27295
|
async function setPluginEnabled(name, enabled, instanceRoot) {
|
|
26862
|
-
const
|
|
26863
|
-
const
|
|
27296
|
+
const os32 = await import("os");
|
|
27297
|
+
const path65 = await import("path");
|
|
26864
27298
|
const { PluginRegistry: PluginRegistry2 } = await Promise.resolve().then(() => (init_plugin_registry(), plugin_registry_exports));
|
|
26865
|
-
const
|
|
26866
|
-
const registryPath =
|
|
27299
|
+
const root = instanceRoot ?? path65.join(os32.homedir(), ".openacp");
|
|
27300
|
+
const registryPath = path65.join(root, "plugins.json");
|
|
26867
27301
|
const registry = new PluginRegistry2(registryPath);
|
|
26868
27302
|
await registry.load();
|
|
26869
27303
|
const entry = registry.get(name);
|
|
@@ -26876,8 +27310,8 @@ async function setPluginEnabled(name, enabled, instanceRoot) {
|
|
|
26876
27310
|
console.log(`Plugin ${name} ${enabled ? "enabled" : "disabled"}. Restart to apply.`);
|
|
26877
27311
|
}
|
|
26878
27312
|
async function configurePlugin(name, instanceRoot) {
|
|
26879
|
-
const
|
|
26880
|
-
const
|
|
27313
|
+
const os32 = await import("os");
|
|
27314
|
+
const path65 = await import("path");
|
|
26881
27315
|
const { corePlugins: corePlugins2 } = await Promise.resolve().then(() => (init_core_plugins(), core_plugins_exports));
|
|
26882
27316
|
const { SettingsManager: SettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), settings_manager_exports));
|
|
26883
27317
|
const { createInstallContext: createInstallContext2 } = await Promise.resolve().then(() => (init_install_context(), install_context_exports));
|
|
@@ -26886,8 +27320,8 @@ async function configurePlugin(name, instanceRoot) {
|
|
|
26886
27320
|
console.error(`Plugin "${name}" not found.`);
|
|
26887
27321
|
process.exit(1);
|
|
26888
27322
|
}
|
|
26889
|
-
const
|
|
26890
|
-
const basePath =
|
|
27323
|
+
const root = instanceRoot ?? path65.join(os32.homedir(), ".openacp");
|
|
27324
|
+
const basePath = path65.join(root, "plugins", "data");
|
|
26891
27325
|
const settingsManager = new SettingsManager2(basePath);
|
|
26892
27326
|
const ctx = createInstallContext2({ pluginName: name, settingsManager, basePath });
|
|
26893
27327
|
if (plugin2.configure) {
|
|
@@ -26899,14 +27333,14 @@ async function configurePlugin(name, instanceRoot) {
|
|
|
26899
27333
|
}
|
|
26900
27334
|
}
|
|
26901
27335
|
async function installPlugin(input2, instanceRoot) {
|
|
26902
|
-
const
|
|
26903
|
-
const
|
|
27336
|
+
const os32 = await import("os");
|
|
27337
|
+
const path65 = await import("path");
|
|
26904
27338
|
const { execFileSync: execFileSync8 } = await import("child_process");
|
|
26905
27339
|
const { getCurrentVersion: getCurrentVersion2 } = await Promise.resolve().then(() => (init_version(), version_exports));
|
|
26906
27340
|
const { SettingsManager: SettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), settings_manager_exports));
|
|
26907
27341
|
const { createInstallContext: createInstallContext2 } = await Promise.resolve().then(() => (init_install_context(), install_context_exports));
|
|
26908
27342
|
const { PluginRegistry: PluginRegistry2 } = await Promise.resolve().then(() => (init_plugin_registry(), plugin_registry_exports));
|
|
26909
|
-
const
|
|
27343
|
+
const root = instanceRoot ?? path65.join(os32.homedir(), ".openacp");
|
|
26910
27344
|
let pkgName;
|
|
26911
27345
|
let pkgVersion;
|
|
26912
27346
|
if (input2.startsWith("@")) {
|
|
@@ -26951,9 +27385,9 @@ async function installPlugin(input2, instanceRoot) {
|
|
|
26951
27385
|
console.log(`Installing ${installSpec}...`);
|
|
26952
27386
|
const { corePlugins: corePlugins2 } = await Promise.resolve().then(() => (init_core_plugins(), core_plugins_exports));
|
|
26953
27387
|
const builtinPlugin = corePlugins2.find((p2) => p2.name === pkgName);
|
|
26954
|
-
const basePath =
|
|
27388
|
+
const basePath = path65.join(root, "plugins", "data");
|
|
26955
27389
|
const settingsManager = new SettingsManager2(basePath);
|
|
26956
|
-
const registryPath =
|
|
27390
|
+
const registryPath = path65.join(root, "plugins.json");
|
|
26957
27391
|
const pluginRegistry = new PluginRegistry2(registryPath);
|
|
26958
27392
|
await pluginRegistry.load();
|
|
26959
27393
|
if (builtinPlugin) {
|
|
@@ -26972,8 +27406,8 @@ async function installPlugin(input2, instanceRoot) {
|
|
|
26972
27406
|
console.log(`\u2713 ${builtinPlugin.name} installed! Restart to activate.`);
|
|
26973
27407
|
return;
|
|
26974
27408
|
}
|
|
26975
|
-
const pluginsDir =
|
|
26976
|
-
const nodeModulesDir =
|
|
27409
|
+
const pluginsDir = path65.join(root, "plugins");
|
|
27410
|
+
const nodeModulesDir = path65.join(pluginsDir, "node_modules");
|
|
26977
27411
|
try {
|
|
26978
27412
|
execFileSync8("npm", ["install", installSpec, "--prefix", pluginsDir, "--save"], {
|
|
26979
27413
|
stdio: "inherit",
|
|
@@ -26986,8 +27420,8 @@ async function installPlugin(input2, instanceRoot) {
|
|
|
26986
27420
|
const cliVersion = getCurrentVersion2();
|
|
26987
27421
|
const isLocalPath = pkgName.startsWith("/") || pkgName.startsWith(".");
|
|
26988
27422
|
try {
|
|
26989
|
-
const pluginRoot = isLocalPath ?
|
|
26990
|
-
const installedPkgPath =
|
|
27423
|
+
const pluginRoot = isLocalPath ? path65.resolve(pkgName) : path65.join(nodeModulesDir, pkgName);
|
|
27424
|
+
const installedPkgPath = path65.join(pluginRoot, "package.json");
|
|
26991
27425
|
const { readFileSync: readFileSync18 } = await import("fs");
|
|
26992
27426
|
const installedPkg = JSON.parse(readFileSync18(installedPkgPath, "utf-8"));
|
|
26993
27427
|
const minVersion = installedPkg.engines?.openacp?.replace(/[>=^~\s]/g, "");
|
|
@@ -27000,7 +27434,7 @@ async function installPlugin(input2, instanceRoot) {
|
|
|
27000
27434
|
`);
|
|
27001
27435
|
}
|
|
27002
27436
|
}
|
|
27003
|
-
const pluginModule = await import(
|
|
27437
|
+
const pluginModule = await import(path65.join(pluginRoot, installedPkg.main ?? "dist/index.js"));
|
|
27004
27438
|
const plugin2 = pluginModule.default;
|
|
27005
27439
|
if (plugin2?.install) {
|
|
27006
27440
|
const ctx = createInstallContext2({ pluginName: plugin2.name ?? pkgName, settingsManager, basePath });
|
|
@@ -27027,12 +27461,12 @@ async function installPlugin(input2, instanceRoot) {
|
|
|
27027
27461
|
}
|
|
27028
27462
|
}
|
|
27029
27463
|
async function uninstallPlugin(name, purge, instanceRoot) {
|
|
27030
|
-
const
|
|
27031
|
-
const
|
|
27032
|
-
const
|
|
27464
|
+
const os32 = await import("os");
|
|
27465
|
+
const path65 = await import("path");
|
|
27466
|
+
const fs53 = await import("fs");
|
|
27033
27467
|
const { PluginRegistry: PluginRegistry2 } = await Promise.resolve().then(() => (init_plugin_registry(), plugin_registry_exports));
|
|
27034
|
-
const
|
|
27035
|
-
const registryPath =
|
|
27468
|
+
const root = instanceRoot ?? path65.join(os32.homedir(), ".openacp");
|
|
27469
|
+
const registryPath = path65.join(root, "plugins.json");
|
|
27036
27470
|
const registry = new PluginRegistry2(registryPath);
|
|
27037
27471
|
await registry.load();
|
|
27038
27472
|
const entry = registry.get(name);
|
|
@@ -27050,7 +27484,7 @@ async function uninstallPlugin(name, purge, instanceRoot) {
|
|
|
27050
27484
|
if (plugin2?.uninstall) {
|
|
27051
27485
|
const { SettingsManager: SettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), settings_manager_exports));
|
|
27052
27486
|
const { createInstallContext: createInstallContext2 } = await Promise.resolve().then(() => (init_install_context(), install_context_exports));
|
|
27053
|
-
const basePath =
|
|
27487
|
+
const basePath = path65.join(root, "plugins", "data");
|
|
27054
27488
|
const settingsManager = new SettingsManager2(basePath);
|
|
27055
27489
|
const ctx = createInstallContext2({ pluginName: name, settingsManager, basePath });
|
|
27056
27490
|
await plugin2.uninstall(ctx, { purge });
|
|
@@ -27058,8 +27492,8 @@ async function uninstallPlugin(name, purge, instanceRoot) {
|
|
|
27058
27492
|
} catch {
|
|
27059
27493
|
}
|
|
27060
27494
|
if (purge) {
|
|
27061
|
-
const pluginDir =
|
|
27062
|
-
|
|
27495
|
+
const pluginDir = path65.join(root, "plugins", name);
|
|
27496
|
+
fs53.rmSync(pluginDir, { recursive: true, force: true });
|
|
27063
27497
|
}
|
|
27064
27498
|
registry.remove(name);
|
|
27065
27499
|
await registry.save();
|
|
@@ -27087,6 +27521,12 @@ function printApiHelp() {
|
|
|
27087
27521
|
openacp api cancel <id> Cancel a session
|
|
27088
27522
|
openacp api dangerous <id> on|off Toggle dangerous mode
|
|
27089
27523
|
|
|
27524
|
+
\x1B[1mSession Config Commands:\x1B[0m
|
|
27525
|
+
openacp api session-config <id> List all config options
|
|
27526
|
+
openacp api session-config <id> set <opt> <value> Set a config option
|
|
27527
|
+
openacp api session-config <id> overrides Show clientOverrides
|
|
27528
|
+
openacp api session-config <id> dangerous [on|off] Toggle bypassPermissions
|
|
27529
|
+
|
|
27090
27530
|
\x1B[1mTopic Commands:\x1B[0m
|
|
27091
27531
|
openacp api topics [--status s1,s2] List topics
|
|
27092
27532
|
openacp api delete-topic <id> [--force] Delete a topic
|
|
@@ -27298,6 +27738,26 @@ Sends a restart signal to the running daemon.
|
|
|
27298
27738
|
openacp api version
|
|
27299
27739
|
|
|
27300
27740
|
Shows the version of the currently running daemon process.
|
|
27741
|
+
`,
|
|
27742
|
+
"session-config": `
|
|
27743
|
+
\x1B[1mopenacp api session-config\x1B[0m \u2014 Manage session config options
|
|
27744
|
+
|
|
27745
|
+
\x1B[1mUsage:\x1B[0m
|
|
27746
|
+
openacp api session-config <id> List all config options
|
|
27747
|
+
openacp api session-config <id> set <opt> <value> Set a config option
|
|
27748
|
+
openacp api session-config <id> overrides Show clientOverrides
|
|
27749
|
+
openacp api session-config <id> dangerous [on|off] Toggle bypassPermissions
|
|
27750
|
+
|
|
27751
|
+
\x1B[1mArguments:\x1B[0m
|
|
27752
|
+
<id> Session ID
|
|
27753
|
+
<opt> Config option ID (from list)
|
|
27754
|
+
<value> New value for the config option
|
|
27755
|
+
|
|
27756
|
+
\x1B[1mExamples:\x1B[0m
|
|
27757
|
+
openacp api session-config abc123
|
|
27758
|
+
openacp api session-config abc123 set model claude-opus-4-5
|
|
27759
|
+
openacp api session-config abc123 overrides
|
|
27760
|
+
openacp api session-config abc123 dangerous on
|
|
27301
27761
|
`
|
|
27302
27762
|
};
|
|
27303
27763
|
const help = apiSubHelp[subCmd];
|
|
@@ -27627,6 +28087,126 @@ Shows the version of the currently running daemon process.
|
|
|
27627
28087
|
process.exit(1);
|
|
27628
28088
|
}
|
|
27629
28089
|
console.log(`Daemon version: ${data.version}`);
|
|
28090
|
+
} else if (subCmd === "session-config") {
|
|
28091
|
+
const sessionId = args2[2];
|
|
28092
|
+
if (!sessionId) {
|
|
28093
|
+
console.error("Usage: openacp api session-config <session-id> [set <opt> <value> | overrides | dangerous [on|off]]");
|
|
28094
|
+
process.exit(1);
|
|
28095
|
+
}
|
|
28096
|
+
const configSubCmd = args2[3];
|
|
28097
|
+
if (!configSubCmd || configSubCmd === "list") {
|
|
28098
|
+
const res = await call(`/api/sessions/${encodeURIComponent(sessionId)}/config`);
|
|
28099
|
+
const data = await res.json();
|
|
28100
|
+
if (!res.ok) {
|
|
28101
|
+
console.error(`Error: ${data.error}`);
|
|
28102
|
+
process.exit(1);
|
|
28103
|
+
}
|
|
28104
|
+
const configOptions = data.configOptions;
|
|
28105
|
+
const clientOverrides = data.clientOverrides;
|
|
28106
|
+
if (!configOptions || configOptions.length === 0) {
|
|
28107
|
+
console.log("No config options available for this session.");
|
|
28108
|
+
} else {
|
|
28109
|
+
console.log(`Config options for session ${sessionId}:
|
|
28110
|
+
`);
|
|
28111
|
+
for (const opt of configOptions) {
|
|
28112
|
+
const desc = opt.description ? ` ${opt.description}` : "";
|
|
28113
|
+
console.log(` [${opt.id}] ${opt.name} (${opt.type}) current: ${opt.currentValue}${desc}`);
|
|
28114
|
+
if (opt.type === "select") {
|
|
28115
|
+
const options = opt.options;
|
|
28116
|
+
if (options && options.length > 0) {
|
|
28117
|
+
const choices = options.flatMap((o) => {
|
|
28118
|
+
if ("group" in o) {
|
|
28119
|
+
const groupOpts = o.options;
|
|
28120
|
+
return groupOpts?.map((c3) => `${c3.value} (${c3.name})`) ?? [];
|
|
28121
|
+
}
|
|
28122
|
+
return [`${o.value} (${o.name})`];
|
|
28123
|
+
});
|
|
28124
|
+
console.log(` choices: ${choices.join(", ")}`);
|
|
28125
|
+
}
|
|
28126
|
+
}
|
|
28127
|
+
}
|
|
28128
|
+
}
|
|
28129
|
+
if (clientOverrides && Object.keys(clientOverrides).length > 0) {
|
|
28130
|
+
console.log(`
|
|
28131
|
+
Client overrides: ${JSON.stringify(clientOverrides)}`);
|
|
28132
|
+
}
|
|
28133
|
+
} else if (configSubCmd === "set") {
|
|
28134
|
+
const configId = args2[4];
|
|
28135
|
+
const value = args2[5];
|
|
28136
|
+
if (!configId || value === void 0) {
|
|
28137
|
+
console.error("Usage: openacp api session-config <session-id> set <config-id> <value>");
|
|
28138
|
+
process.exit(1);
|
|
28139
|
+
}
|
|
28140
|
+
const res = await call(`/api/sessions/${encodeURIComponent(sessionId)}/config/${encodeURIComponent(configId)}`, {
|
|
28141
|
+
method: "PUT",
|
|
28142
|
+
headers: { "Content-Type": "application/json" },
|
|
28143
|
+
body: JSON.stringify({ value })
|
|
28144
|
+
});
|
|
28145
|
+
const data = await res.json();
|
|
28146
|
+
if (!res.ok) {
|
|
28147
|
+
console.error(`Error: ${data.error}`);
|
|
28148
|
+
process.exit(1);
|
|
28149
|
+
}
|
|
28150
|
+
console.log(`Config option "${configId}" updated to "${value}"`);
|
|
28151
|
+
const configOptions = data.configOptions;
|
|
28152
|
+
const updated = configOptions?.find((o) => o.id === configId);
|
|
28153
|
+
if (updated) {
|
|
28154
|
+
console.log(` Current value: ${updated.currentValue}`);
|
|
28155
|
+
}
|
|
28156
|
+
} else if (configSubCmd === "overrides") {
|
|
28157
|
+
const res = await call(`/api/sessions/${encodeURIComponent(sessionId)}/config/overrides`);
|
|
28158
|
+
const data = await res.json();
|
|
28159
|
+
if (!res.ok) {
|
|
28160
|
+
console.error(`Error: ${data.error}`);
|
|
28161
|
+
process.exit(1);
|
|
28162
|
+
}
|
|
28163
|
+
const overrides = data.clientOverrides;
|
|
28164
|
+
if (!overrides || Object.keys(overrides).length === 0) {
|
|
28165
|
+
console.log("No client overrides set.");
|
|
28166
|
+
} else {
|
|
28167
|
+
console.log(`Client overrides for session ${sessionId}:`);
|
|
28168
|
+
for (const [key, val] of Object.entries(overrides)) {
|
|
28169
|
+
console.log(` ${key}: ${val}`);
|
|
28170
|
+
}
|
|
28171
|
+
}
|
|
28172
|
+
} else if (configSubCmd === "dangerous") {
|
|
28173
|
+
const toggle = args2[4];
|
|
28174
|
+
if (toggle && toggle !== "on" && toggle !== "off") {
|
|
28175
|
+
console.error("Usage: openacp api session-config <session-id> dangerous [on|off]");
|
|
28176
|
+
process.exit(1);
|
|
28177
|
+
}
|
|
28178
|
+
if (toggle) {
|
|
28179
|
+
const res = await call(`/api/sessions/${encodeURIComponent(sessionId)}/config/overrides`, {
|
|
28180
|
+
method: "PUT",
|
|
28181
|
+
headers: { "Content-Type": "application/json" },
|
|
28182
|
+
body: JSON.stringify({ bypassPermissions: toggle === "on" })
|
|
28183
|
+
});
|
|
28184
|
+
const data = await res.json();
|
|
28185
|
+
if (!res.ok) {
|
|
28186
|
+
console.error(`Error: ${data.error}`);
|
|
28187
|
+
process.exit(1);
|
|
28188
|
+
}
|
|
28189
|
+
const state = toggle === "on" ? "enabled" : "disabled";
|
|
28190
|
+
console.log(`bypassPermissions ${state} for session ${sessionId}`);
|
|
28191
|
+
} else {
|
|
28192
|
+
const res = await call(`/api/sessions/${encodeURIComponent(sessionId)}/config/overrides`);
|
|
28193
|
+
const data = await res.json();
|
|
28194
|
+
if (!res.ok) {
|
|
28195
|
+
console.error(`Error: ${data.error}`);
|
|
28196
|
+
process.exit(1);
|
|
28197
|
+
}
|
|
28198
|
+
const overrides = data.clientOverrides;
|
|
28199
|
+
const bypass = overrides?.bypassPermissions;
|
|
28200
|
+
console.log(`bypassPermissions: ${bypass ?? false}`);
|
|
28201
|
+
}
|
|
28202
|
+
} else {
|
|
28203
|
+
console.error(`Unknown session-config subcommand: ${configSubCmd}`);
|
|
28204
|
+
console.log(" openacp api session-config <id> List config options");
|
|
28205
|
+
console.log(" openacp api session-config <id> set <opt> <value> Set a config option");
|
|
28206
|
+
console.log(" openacp api session-config <id> overrides Show clientOverrides");
|
|
28207
|
+
console.log(" openacp api session-config <id> dangerous [on|off] Toggle bypassPermissions");
|
|
28208
|
+
process.exit(1);
|
|
28209
|
+
}
|
|
27630
28210
|
} else {
|
|
27631
28211
|
const { suggestMatch: suggestMatch2 } = await Promise.resolve().then(() => (init_suggest(), suggest_exports));
|
|
27632
28212
|
const apiSubcommands = [
|
|
@@ -27646,7 +28226,8 @@ Shows the version of the currently running daemon process.
|
|
|
27646
28226
|
"adapters",
|
|
27647
28227
|
"tunnel",
|
|
27648
28228
|
"notify",
|
|
27649
|
-
"version"
|
|
28229
|
+
"version",
|
|
28230
|
+
"session-config"
|
|
27650
28231
|
];
|
|
27651
28232
|
const suggestion = suggestMatch2(subCmd ?? "", apiSubcommands);
|
|
27652
28233
|
console.error(`Unknown api command: ${subCmd || "(none)"}
|
|
@@ -27673,7 +28254,7 @@ init_instance_hint();
|
|
|
27673
28254
|
import path36 from "path";
|
|
27674
28255
|
import os17 from "os";
|
|
27675
28256
|
async function cmdStart(args2 = [], instanceRoot) {
|
|
27676
|
-
const
|
|
28257
|
+
const root = instanceRoot ?? path36.join(os17.homedir(), ".openacp");
|
|
27677
28258
|
if (wantsHelp(args2)) {
|
|
27678
28259
|
console.log(`
|
|
27679
28260
|
\x1B[1mopenacp start\x1B[0m \u2014 Start OpenACP as a background daemon
|
|
@@ -27695,16 +28276,16 @@ Requires an existing config \u2014 run 'openacp' first to set up.
|
|
|
27695
28276
|
await checkAndPromptUpdate();
|
|
27696
28277
|
const { startDaemon: startDaemon2, getPidPath: getPidPath2 } = await Promise.resolve().then(() => (init_daemon2(), daemon_exports));
|
|
27697
28278
|
const { ConfigManager: ConfigManager2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
27698
|
-
const cm = new ConfigManager2(path36.join(
|
|
28279
|
+
const cm = new ConfigManager2(path36.join(root, "config.json"));
|
|
27699
28280
|
if (await cm.exists()) {
|
|
27700
28281
|
await cm.load();
|
|
27701
28282
|
const config = cm.get();
|
|
27702
|
-
const result = startDaemon2(getPidPath2(
|
|
28283
|
+
const result = startDaemon2(getPidPath2(root), config.logging.logDir, root);
|
|
27703
28284
|
if ("error" in result) {
|
|
27704
28285
|
console.error(result.error);
|
|
27705
28286
|
process.exit(1);
|
|
27706
28287
|
}
|
|
27707
|
-
printInstanceHint(
|
|
28288
|
+
printInstanceHint(root);
|
|
27708
28289
|
console.log(`OpenACP daemon started (PID ${result.pid})`);
|
|
27709
28290
|
} else {
|
|
27710
28291
|
console.error('No config found. Run "openacp" first to set up.');
|
|
@@ -27854,18 +28435,18 @@ start fresh with the setup wizard. The daemon must be stopped first.
|
|
|
27854
28435
|
`);
|
|
27855
28436
|
return;
|
|
27856
28437
|
}
|
|
27857
|
-
const
|
|
27858
|
-
const
|
|
27859
|
-
const
|
|
28438
|
+
const os32 = await import("os");
|
|
28439
|
+
const path65 = await import("path");
|
|
28440
|
+
const root = instanceRoot ?? path65.join(os32.homedir(), ".openacp");
|
|
27860
28441
|
const { getStatus: getStatus2, getPidPath: getPidPath2 } = await Promise.resolve().then(() => (init_daemon2(), daemon_exports));
|
|
27861
|
-
const status = getStatus2(getPidPath2(
|
|
28442
|
+
const status = getStatus2(getPidPath2(root));
|
|
27862
28443
|
if (status.running) {
|
|
27863
28444
|
console.error("OpenACP is running. Stop it first: openacp stop");
|
|
27864
28445
|
process.exit(1);
|
|
27865
28446
|
}
|
|
27866
28447
|
const clack10 = await import("@clack/prompts");
|
|
27867
28448
|
const yes = await clack10.confirm({
|
|
27868
|
-
message: `This will delete all OpenACP data (${
|
|
28449
|
+
message: `This will delete all OpenACP data (${root}). You will need to set up again. Continue?`,
|
|
27869
28450
|
initialValue: false
|
|
27870
28451
|
});
|
|
27871
28452
|
if (clack10.isCancel(yes) || !yes) {
|
|
@@ -27874,8 +28455,8 @@ start fresh with the setup wizard. The daemon must be stopped first.
|
|
|
27874
28455
|
}
|
|
27875
28456
|
const { uninstallAutoStart: uninstallAutoStart2 } = await Promise.resolve().then(() => (init_autostart(), autostart_exports));
|
|
27876
28457
|
uninstallAutoStart2();
|
|
27877
|
-
const
|
|
27878
|
-
|
|
28458
|
+
const fs53 = await import("fs");
|
|
28459
|
+
fs53.rmSync(root, { recursive: true, force: true });
|
|
27879
28460
|
console.log("Reset complete. Run `openacp` to set up again.");
|
|
27880
28461
|
}
|
|
27881
28462
|
|
|
@@ -28620,16 +29201,16 @@ Tunnel Management:
|
|
|
28620
29201
|
}
|
|
28621
29202
|
|
|
28622
29203
|
// src/cli/commands/onboard.ts
|
|
28623
|
-
import * as
|
|
29204
|
+
import * as path58 from "path";
|
|
28624
29205
|
async function cmdOnboard(instanceRoot) {
|
|
28625
29206
|
const { ConfigManager: ConfigManager2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
28626
29207
|
const { SettingsManager: SettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), settings_manager_exports));
|
|
28627
29208
|
const { PluginRegistry: PluginRegistry2 } = await Promise.resolve().then(() => (init_plugin_registry(), plugin_registry_exports));
|
|
28628
29209
|
const { getGlobalRoot: getGlobalRoot2 } = await Promise.resolve().then(() => (init_instance_context(), instance_context_exports));
|
|
28629
29210
|
const OPENACP_DIR = instanceRoot ?? getGlobalRoot2();
|
|
28630
|
-
const PLUGINS_DATA_DIR =
|
|
28631
|
-
const REGISTRY_PATH =
|
|
28632
|
-
const cm = new ConfigManager2(
|
|
29211
|
+
const PLUGINS_DATA_DIR = path58.join(OPENACP_DIR, "plugins", "data");
|
|
29212
|
+
const REGISTRY_PATH = path58.join(OPENACP_DIR, "plugins.json");
|
|
29213
|
+
const cm = new ConfigManager2(path58.join(OPENACP_DIR, "config.json"));
|
|
28633
29214
|
const settingsManager = new SettingsManager2(PLUGINS_DATA_DIR);
|
|
28634
29215
|
const pluginRegistry = new PluginRegistry2(REGISTRY_PATH);
|
|
28635
29216
|
await pluginRegistry.load();
|
|
@@ -28646,12 +29227,12 @@ async function cmdOnboard(instanceRoot) {
|
|
|
28646
29227
|
init_version();
|
|
28647
29228
|
init_instance_context();
|
|
28648
29229
|
init_instance_hint();
|
|
28649
|
-
import
|
|
28650
|
-
import
|
|
29230
|
+
import path59 from "path";
|
|
29231
|
+
import os28 from "os";
|
|
28651
29232
|
async function cmdDefault(command2, instanceRoot) {
|
|
28652
|
-
const
|
|
28653
|
-
const pluginsDataDir =
|
|
28654
|
-
const registryPath =
|
|
29233
|
+
const root = instanceRoot ?? path59.join(os28.homedir(), ".openacp");
|
|
29234
|
+
const pluginsDataDir = path59.join(root, "plugins", "data");
|
|
29235
|
+
const registryPath = path59.join(root, "plugins.json");
|
|
28655
29236
|
const forceForeground = command2 === "--foreground";
|
|
28656
29237
|
if (command2 && !command2.startsWith("-")) {
|
|
28657
29238
|
const { suggestMatch: suggestMatch2 } = await Promise.resolve().then(() => (init_suggest(), suggest_exports));
|
|
@@ -28683,7 +29264,7 @@ async function cmdDefault(command2, instanceRoot) {
|
|
|
28683
29264
|
}
|
|
28684
29265
|
await checkAndPromptUpdate();
|
|
28685
29266
|
const { ConfigManager: ConfigManager2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
28686
|
-
const configPath =
|
|
29267
|
+
const configPath = path59.join(root, "config.json");
|
|
28687
29268
|
const cm = new ConfigManager2(configPath);
|
|
28688
29269
|
if (!await cm.exists()) {
|
|
28689
29270
|
const { SettingsManager: SettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), settings_manager_exports));
|
|
@@ -28692,44 +29273,44 @@ async function cmdDefault(command2, instanceRoot) {
|
|
|
28692
29273
|
const pluginRegistry = new PluginRegistry2(registryPath);
|
|
28693
29274
|
await pluginRegistry.load();
|
|
28694
29275
|
const { runSetup: runSetup2 } = await Promise.resolve().then(() => (init_setup(), setup_exports));
|
|
28695
|
-
const shouldStart = await runSetup2(cm, { settingsManager, pluginRegistry, instanceRoot:
|
|
29276
|
+
const shouldStart = await runSetup2(cm, { settingsManager, pluginRegistry, instanceRoot: root });
|
|
28696
29277
|
if (!shouldStart) process.exit(0);
|
|
28697
29278
|
}
|
|
28698
29279
|
await cm.load();
|
|
28699
29280
|
const config = cm.get();
|
|
28700
29281
|
if (!forceForeground && config.runMode === "daemon") {
|
|
28701
29282
|
const { isProcessRunning: isProcessRunning2, getPidPath: getPidPath2, startDaemon: startDaemon2 } = await Promise.resolve().then(() => (init_daemon2(), daemon_exports));
|
|
28702
|
-
const pidPath = getPidPath2(
|
|
29283
|
+
const pidPath = getPidPath2(root);
|
|
28703
29284
|
if (isProcessRunning2(pidPath)) {
|
|
28704
|
-
await showAlreadyRunningMenu(
|
|
29285
|
+
await showAlreadyRunningMenu(root);
|
|
28705
29286
|
return;
|
|
28706
29287
|
}
|
|
28707
|
-
const result = startDaemon2(pidPath, config.logging.logDir,
|
|
29288
|
+
const result = startDaemon2(pidPath, config.logging.logDir, root);
|
|
28708
29289
|
if ("error" in result) {
|
|
28709
29290
|
console.error(result.error);
|
|
28710
29291
|
process.exit(1);
|
|
28711
29292
|
}
|
|
28712
|
-
printInstanceHint(
|
|
29293
|
+
printInstanceHint(root);
|
|
28713
29294
|
console.log(`OpenACP daemon started (PID ${result.pid})`);
|
|
28714
29295
|
return;
|
|
28715
29296
|
}
|
|
28716
29297
|
const { markRunning: markRunning2 } = await Promise.resolve().then(() => (init_daemon2(), daemon_exports));
|
|
28717
|
-
markRunning2(
|
|
28718
|
-
printInstanceHint(
|
|
29298
|
+
markRunning2(root);
|
|
29299
|
+
printInstanceHint(root);
|
|
28719
29300
|
const { startServer: startServer2 } = await Promise.resolve().then(() => (init_main(), main_exports));
|
|
28720
29301
|
const ctx = createInstanceContext({
|
|
28721
29302
|
id: "default",
|
|
28722
|
-
root
|
|
28723
|
-
isGlobal:
|
|
29303
|
+
root,
|
|
29304
|
+
isGlobal: root === getGlobalRoot()
|
|
28724
29305
|
});
|
|
28725
29306
|
await startServer2({ instanceContext: ctx });
|
|
28726
29307
|
}
|
|
28727
|
-
async function showAlreadyRunningMenu(
|
|
29308
|
+
async function showAlreadyRunningMenu(root) {
|
|
28728
29309
|
const { formatInstanceStatus: formatInstanceStatus2 } = await Promise.resolve().then(() => (init_status(), status_exports));
|
|
28729
29310
|
console.log("");
|
|
28730
29311
|
console.log("\x1B[1mOpenACP is already running\x1B[0m");
|
|
28731
29312
|
console.log("");
|
|
28732
|
-
const status = formatInstanceStatus2(
|
|
29313
|
+
const status = formatInstanceStatus2(root);
|
|
28733
29314
|
if (status) {
|
|
28734
29315
|
for (const line of status.lines) {
|
|
28735
29316
|
console.log(line);
|
|
@@ -28743,7 +29324,7 @@ async function showAlreadyRunningMenu(root2) {
|
|
|
28743
29324
|
label: "Restart",
|
|
28744
29325
|
action: async () => {
|
|
28745
29326
|
const { cmdRestart: cmdRestart2 } = await Promise.resolve().then(() => (init_restart(), restart_exports));
|
|
28746
|
-
await cmdRestart2([],
|
|
29327
|
+
await cmdRestart2([], root);
|
|
28747
29328
|
}
|
|
28748
29329
|
},
|
|
28749
29330
|
{
|
|
@@ -28751,7 +29332,7 @@ async function showAlreadyRunningMenu(root2) {
|
|
|
28751
29332
|
label: "Stop",
|
|
28752
29333
|
action: async () => {
|
|
28753
29334
|
const { cmdStop: cmdStop2 } = await Promise.resolve().then(() => (init_stop(), stop_exports));
|
|
28754
|
-
await cmdStop2([],
|
|
29335
|
+
await cmdStop2([], root);
|
|
28755
29336
|
}
|
|
28756
29337
|
},
|
|
28757
29338
|
{
|
|
@@ -28765,7 +29346,7 @@ async function showAlreadyRunningMenu(root2) {
|
|
|
28765
29346
|
label: "Restart in foreground",
|
|
28766
29347
|
action: async () => {
|
|
28767
29348
|
const { cmdRestart: cmdRestart2 } = await Promise.resolve().then(() => (init_restart(), restart_exports));
|
|
28768
|
-
await cmdRestart2(["--foreground"],
|
|
29349
|
+
await cmdRestart2(["--foreground"], root);
|
|
28769
29350
|
}
|
|
28770
29351
|
},
|
|
28771
29352
|
{
|
|
@@ -28773,7 +29354,7 @@ async function showAlreadyRunningMenu(root2) {
|
|
|
28773
29354
|
label: "View logs",
|
|
28774
29355
|
action: async () => {
|
|
28775
29356
|
const { cmdLogs: cmdLogs2 } = await Promise.resolve().then(() => (init_logs(), logs_exports));
|
|
28776
|
-
await cmdLogs2([],
|
|
29357
|
+
await cmdLogs2([], root);
|
|
28777
29358
|
}
|
|
28778
29359
|
}
|
|
28779
29360
|
]);
|
|
@@ -28785,8 +29366,8 @@ async function showAlreadyRunningMenu(root2) {
|
|
|
28785
29366
|
|
|
28786
29367
|
// src/cli/commands/dev.ts
|
|
28787
29368
|
init_helpers();
|
|
28788
|
-
import
|
|
28789
|
-
import
|
|
29369
|
+
import fs51 from "fs";
|
|
29370
|
+
import path60 from "path";
|
|
28790
29371
|
async function cmdDev(args2 = []) {
|
|
28791
29372
|
if (wantsHelp(args2)) {
|
|
28792
29373
|
console.log(`
|
|
@@ -28813,13 +29394,13 @@ async function cmdDev(args2 = []) {
|
|
|
28813
29394
|
console.error("Error: missing plugin path. Usage: openacp dev <plugin-path>");
|
|
28814
29395
|
process.exit(1);
|
|
28815
29396
|
}
|
|
28816
|
-
const pluginPath =
|
|
28817
|
-
if (!
|
|
29397
|
+
const pluginPath = path60.resolve(pluginPathArg);
|
|
29398
|
+
if (!fs51.existsSync(pluginPath)) {
|
|
28818
29399
|
console.error(`Error: plugin path does not exist: ${pluginPath}`);
|
|
28819
29400
|
process.exit(1);
|
|
28820
29401
|
}
|
|
28821
|
-
const tsconfigPath =
|
|
28822
|
-
const hasTsconfig =
|
|
29402
|
+
const tsconfigPath = path60.join(pluginPath, "tsconfig.json");
|
|
29403
|
+
const hasTsconfig = fs51.existsSync(tsconfigPath);
|
|
28823
29404
|
if (hasTsconfig) {
|
|
28824
29405
|
console.log("Compiling plugin TypeScript...");
|
|
28825
29406
|
const { execSync: execSync5 } = await import("child_process");
|
|
@@ -28860,10 +29441,10 @@ async function cmdDev(args2 = []) {
|
|
|
28860
29441
|
|
|
28861
29442
|
// src/cli/commands/attach.ts
|
|
28862
29443
|
init_helpers();
|
|
28863
|
-
import
|
|
28864
|
-
import
|
|
29444
|
+
import path61 from "path";
|
|
29445
|
+
import os29 from "os";
|
|
28865
29446
|
async function cmdAttach(args2 = [], instanceRoot) {
|
|
28866
|
-
const
|
|
29447
|
+
const root = instanceRoot ?? path61.join(os29.homedir(), ".openacp");
|
|
28867
29448
|
if (wantsHelp(args2)) {
|
|
28868
29449
|
console.log(`
|
|
28869
29450
|
\x1B[1mopenacp attach\x1B[0m \u2014 Attach to a running daemon
|
|
@@ -28881,7 +29462,7 @@ Press Ctrl+C to detach.
|
|
|
28881
29462
|
return;
|
|
28882
29463
|
}
|
|
28883
29464
|
const { formatInstanceStatus: formatInstanceStatus2 } = await Promise.resolve().then(() => (init_status(), status_exports));
|
|
28884
|
-
const status = formatInstanceStatus2(
|
|
29465
|
+
const status = formatInstanceStatus2(root);
|
|
28885
29466
|
if (!status) {
|
|
28886
29467
|
console.log("OpenACP is not running.");
|
|
28887
29468
|
process.exit(1);
|
|
@@ -28897,15 +29478,15 @@ Press Ctrl+C to detach.
|
|
|
28897
29478
|
console.log("");
|
|
28898
29479
|
const { spawn: spawn8 } = await import("child_process");
|
|
28899
29480
|
const { expandHome: expandHome4 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
28900
|
-
let logDir2 =
|
|
29481
|
+
let logDir2 = path61.join(root, "logs");
|
|
28901
29482
|
try {
|
|
28902
|
-
const configPath =
|
|
29483
|
+
const configPath = path61.join(root, "config.json");
|
|
28903
29484
|
const { readFileSync: readFileSync18 } = await import("fs");
|
|
28904
29485
|
const config = JSON.parse(readFileSync18(configPath, "utf-8"));
|
|
28905
29486
|
if (config.logging?.logDir) logDir2 = expandHome4(config.logging.logDir);
|
|
28906
29487
|
} catch {
|
|
28907
29488
|
}
|
|
28908
|
-
const logFile =
|
|
29489
|
+
const logFile = path61.join(logDir2, "openacp.log");
|
|
28909
29490
|
const tail = spawn8("tail", ["-f", "-n", "50", logFile], { stdio: "inherit" });
|
|
28910
29491
|
tail.on("error", (err) => {
|
|
28911
29492
|
console.error(`Cannot tail log file: ${err.message}`);
|
|
@@ -28916,8 +29497,8 @@ Press Ctrl+C to detach.
|
|
|
28916
29497
|
// src/cli/commands/remote.ts
|
|
28917
29498
|
init_api_client();
|
|
28918
29499
|
init_instance_registry();
|
|
28919
|
-
import
|
|
28920
|
-
import
|
|
29500
|
+
import path62 from "path";
|
|
29501
|
+
import os30 from "os";
|
|
28921
29502
|
import qrcode from "qrcode-terminal";
|
|
28922
29503
|
async function cmdRemote(args2, instanceRoot) {
|
|
28923
29504
|
const role = extractFlag(args2, "--role") ?? "admin";
|
|
@@ -28930,12 +29511,12 @@ async function cmdRemote(args2, instanceRoot) {
|
|
|
28930
29511
|
const scopes = scopesRaw ? scopesRaw.split(",").map((s) => s.trim()) : void 0;
|
|
28931
29512
|
let resolvedInstanceRoot2 = instanceRoot;
|
|
28932
29513
|
if (instanceId) {
|
|
28933
|
-
const registryPath =
|
|
29514
|
+
const registryPath = path62.join(os30.homedir(), ".openacp", "instances.json");
|
|
28934
29515
|
const registry = new InstanceRegistry(registryPath);
|
|
28935
29516
|
await registry.load();
|
|
28936
29517
|
const entry = registry.get(instanceId);
|
|
28937
29518
|
if (!entry) {
|
|
28938
|
-
console.error(`
|
|
29519
|
+
console.error(`Workspace "${instanceId}" not found. Run "openacp status" to see workspaces.`);
|
|
28939
29520
|
process.exit(1);
|
|
28940
29521
|
}
|
|
28941
29522
|
resolvedInstanceRoot2 = entry.root;
|
|
@@ -29105,41 +29686,34 @@ resolvedInstanceRoot = resolveInstanceRoot({
|
|
|
29105
29686
|
global: flags.global,
|
|
29106
29687
|
cwd: process.cwd()
|
|
29107
29688
|
});
|
|
29108
|
-
var
|
|
29109
|
-
var commands = {
|
|
29689
|
+
var noInstanceCommands = {
|
|
29110
29690
|
"--help": async () => printHelp(),
|
|
29111
29691
|
"-h": async () => printHelp(),
|
|
29112
29692
|
"--version": () => cmdVersion(),
|
|
29113
29693
|
"-v": () => cmdVersion(),
|
|
29114
|
-
"install": () => cmdInstall(args, root),
|
|
29115
|
-
"uninstall": () => cmdUninstall(args, root),
|
|
29116
|
-
"plugins": () => cmdPlugins(args, root),
|
|
29117
|
-
"plugin": () => cmdPlugin(args, root),
|
|
29118
|
-
"api": () => cmdApi(args, root),
|
|
29119
|
-
"start": () => cmdStart(args, root),
|
|
29120
|
-
"stop": () => cmdStop(args, root),
|
|
29121
|
-
"restart": () => cmdRestart(args, root),
|
|
29122
|
-
"status": () => cmdStatus(args, root),
|
|
29123
|
-
"logs": () => cmdLogs(args, root),
|
|
29124
|
-
"config": () => cmdConfig(args, root),
|
|
29125
|
-
"reset": () => cmdReset(args, root),
|
|
29126
29694
|
"update": () => cmdUpdate(args),
|
|
29127
29695
|
"adopt": () => cmdAdopt(args),
|
|
29128
29696
|
"integrate": () => cmdIntegrate(args),
|
|
29129
|
-
"
|
|
29130
|
-
|
|
29131
|
-
|
|
29132
|
-
|
|
29133
|
-
|
|
29134
|
-
|
|
29135
|
-
|
|
29136
|
-
|
|
29697
|
+
"dev": () => cmdDev(args)
|
|
29698
|
+
};
|
|
29699
|
+
async function resolveRoot(allowCreate) {
|
|
29700
|
+
if (resolvedInstanceRoot) return resolvedInstanceRoot;
|
|
29701
|
+
const { promptForInstance: promptForInstance2 } = await Promise.resolve().then(() => (init_instance_prompt(), instance_prompt_exports));
|
|
29702
|
+
return promptForInstance2({ allowCreate });
|
|
29703
|
+
}
|
|
29704
|
+
async function main() {
|
|
29705
|
+
const noInstance = command ? noInstanceCommands[command] : void 0;
|
|
29706
|
+
if (noInstance) {
|
|
29707
|
+
await noInstance();
|
|
29708
|
+
return;
|
|
29709
|
+
}
|
|
29710
|
+
if (command === "--daemon-child") {
|
|
29137
29711
|
const { startServer: startServer2 } = await Promise.resolve().then(() => (init_main(), main_exports));
|
|
29138
29712
|
const envRoot = process.env.OPENACP_INSTANCE_ROOT;
|
|
29139
29713
|
if (envRoot) {
|
|
29140
29714
|
const { createInstanceContext: createInstanceContext2, getGlobalRoot: getGlobal } = await Promise.resolve().then(() => (init_instance_context(), instance_context_exports));
|
|
29141
29715
|
const { InstanceRegistry: InstanceRegistry2 } = await Promise.resolve().then(() => (init_instance_registry(), instance_registry_exports));
|
|
29142
|
-
const registry = new InstanceRegistry2(
|
|
29716
|
+
const registry = new InstanceRegistry2(path64.join(getGlobal(), "instances.json"));
|
|
29143
29717
|
await registry.load();
|
|
29144
29718
|
const entry = registry.getByRoot(envRoot);
|
|
29145
29719
|
const id = entry?.id ?? "unknown";
|
|
@@ -29152,13 +29726,34 @@ var commands = {
|
|
|
29152
29726
|
} else {
|
|
29153
29727
|
await startServer2();
|
|
29154
29728
|
}
|
|
29729
|
+
return;
|
|
29155
29730
|
}
|
|
29156
|
-
|
|
29157
|
-
|
|
29158
|
-
|
|
29731
|
+
const instanceCommands = {
|
|
29732
|
+
"install": (r) => cmdInstall(args, r),
|
|
29733
|
+
"uninstall": (r) => cmdUninstall(args, r),
|
|
29734
|
+
"plugins": (r) => cmdPlugins(args, r),
|
|
29735
|
+
"plugin": (r) => cmdPlugin(args, r),
|
|
29736
|
+
"api": (r) => cmdApi(args, r),
|
|
29737
|
+
"start": (r) => cmdStart(args, r),
|
|
29738
|
+
"stop": (r) => cmdStop(args, r),
|
|
29739
|
+
"restart": (r) => cmdRestart(args, r),
|
|
29740
|
+
"status": (r) => cmdStatus(args, r),
|
|
29741
|
+
"logs": (r) => cmdLogs(args, r),
|
|
29742
|
+
"config": (r) => cmdConfig(args, r),
|
|
29743
|
+
"reset": (r) => cmdReset(args, r),
|
|
29744
|
+
"doctor": (r) => cmdDoctor(args, r),
|
|
29745
|
+
"agents": (r) => cmdAgents(args, r),
|
|
29746
|
+
"tunnel": (r) => cmdTunnel(args, r),
|
|
29747
|
+
"onboard": (r) => cmdOnboard(r),
|
|
29748
|
+
"attach": (r) => cmdAttach(args, r),
|
|
29749
|
+
"remote": (r) => cmdRemote(args, r)
|
|
29750
|
+
};
|
|
29751
|
+
const handler = command ? instanceCommands[command] : void 0;
|
|
29159
29752
|
if (handler) {
|
|
29160
|
-
await
|
|
29753
|
+
const root = await resolveRoot(false);
|
|
29754
|
+
await handler(root);
|
|
29161
29755
|
} else {
|
|
29756
|
+
const root = await resolveRoot(true);
|
|
29162
29757
|
await cmdDefault(command, root);
|
|
29163
29758
|
}
|
|
29164
29759
|
}
|