@openacp/cli 2026.406.1 → 2026.406.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/{channel-DstweC6V.d.ts → channel-CKXNnTy4.d.ts} +1 -0
- package/dist/cli.js +538 -278
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +29 -14
- package/dist/index.js +432 -201
- package/dist/index.js.map +1 -1
- package/dist/testing.d.ts +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1104,7 +1104,7 @@ Declare in \`permissions\` array. Only request what you need.
|
|
|
1104
1104
|
|
|
1105
1105
|
Calling a method without the required permission throws \`PluginPermissionError\`.
|
|
1106
1106
|
|
|
1107
|
-
## Middleware Hooks (
|
|
1107
|
+
## Middleware Hooks (19 total)
|
|
1108
1108
|
|
|
1109
1109
|
Register with \`ctx.registerMiddleware(hook, { priority?, handler })\`. Return \`null\` to block the flow, call \`next()\` to continue.
|
|
1110
1110
|
|
|
@@ -1757,6 +1757,104 @@ var init_security_guard = __esm({
|
|
|
1757
1757
|
}
|
|
1758
1758
|
});
|
|
1759
1759
|
|
|
1760
|
+
// src/core/events.ts
|
|
1761
|
+
var Hook, BusEvent, SessionEv;
|
|
1762
|
+
var init_events = __esm({
|
|
1763
|
+
"src/core/events.ts"() {
|
|
1764
|
+
"use strict";
|
|
1765
|
+
Hook = {
|
|
1766
|
+
// --- Message flow ---
|
|
1767
|
+
/** Incoming message from any adapter — modifiable, can block. */
|
|
1768
|
+
MESSAGE_INCOMING: "message:incoming",
|
|
1769
|
+
/** Outgoing message before it reaches the adapter — modifiable, can block. */
|
|
1770
|
+
MESSAGE_OUTGOING: "message:outgoing",
|
|
1771
|
+
// --- Agent / turn lifecycle ---
|
|
1772
|
+
/** Before a user prompt is sent to the agent — modifiable, can block. */
|
|
1773
|
+
AGENT_BEFORE_PROMPT: "agent:beforePrompt",
|
|
1774
|
+
/** Before an agent event is dispatched — modifiable, can block. */
|
|
1775
|
+
AGENT_BEFORE_EVENT: "agent:beforeEvent",
|
|
1776
|
+
/** After an agent event is dispatched — read-only, fire-and-forget. */
|
|
1777
|
+
AGENT_AFTER_EVENT: "agent:afterEvent",
|
|
1778
|
+
/** Before the current prompt is cancelled — modifiable, can block. */
|
|
1779
|
+
AGENT_BEFORE_CANCEL: "agent:beforeCancel",
|
|
1780
|
+
/** Before the agent is switched — modifiable, can block. */
|
|
1781
|
+
AGENT_BEFORE_SWITCH: "agent:beforeSwitch",
|
|
1782
|
+
/** After the agent has been switched — read-only, fire-and-forget. */
|
|
1783
|
+
AGENT_AFTER_SWITCH: "agent:afterSwitch",
|
|
1784
|
+
// --- Turn boundaries ---
|
|
1785
|
+
/** Turn started — read-only, fire-and-forget. */
|
|
1786
|
+
TURN_START: "turn:start",
|
|
1787
|
+
/** Turn ended (always fires, even on error) — read-only, fire-and-forget. */
|
|
1788
|
+
TURN_END: "turn:end",
|
|
1789
|
+
// --- Session lifecycle ---
|
|
1790
|
+
/** Before a new session is created — modifiable, can block. */
|
|
1791
|
+
SESSION_BEFORE_CREATE: "session:beforeCreate",
|
|
1792
|
+
/** After a session is destroyed — read-only, fire-and-forget. */
|
|
1793
|
+
SESSION_AFTER_DESTROY: "session:afterDestroy",
|
|
1794
|
+
// --- Permissions ---
|
|
1795
|
+
/** Before a permission request is shown to the user — modifiable, can block. */
|
|
1796
|
+
PERMISSION_BEFORE_REQUEST: "permission:beforeRequest",
|
|
1797
|
+
/** After a permission request is resolved — read-only, fire-and-forget. */
|
|
1798
|
+
PERMISSION_AFTER_RESOLVE: "permission:afterResolve",
|
|
1799
|
+
// --- Config ---
|
|
1800
|
+
/** Before config options change — modifiable, can block. */
|
|
1801
|
+
CONFIG_BEFORE_CHANGE: "config:beforeChange",
|
|
1802
|
+
// --- Filesystem (agent-level) ---
|
|
1803
|
+
/** Before a file read operation — modifiable. */
|
|
1804
|
+
FS_BEFORE_READ: "fs:beforeRead",
|
|
1805
|
+
/** Before a file write operation — modifiable. */
|
|
1806
|
+
FS_BEFORE_WRITE: "fs:beforeWrite",
|
|
1807
|
+
// --- Terminal ---
|
|
1808
|
+
/** Before a terminal session is created — modifiable, can block. */
|
|
1809
|
+
TERMINAL_BEFORE_CREATE: "terminal:beforeCreate",
|
|
1810
|
+
/** After a terminal session exits — read-only, fire-and-forget. */
|
|
1811
|
+
TERMINAL_AFTER_EXIT: "terminal:afterExit"
|
|
1812
|
+
};
|
|
1813
|
+
BusEvent = {
|
|
1814
|
+
// --- Session lifecycle ---
|
|
1815
|
+
SESSION_CREATED: "session:created",
|
|
1816
|
+
SESSION_UPDATED: "session:updated",
|
|
1817
|
+
SESSION_DELETED: "session:deleted",
|
|
1818
|
+
SESSION_ENDED: "session:ended",
|
|
1819
|
+
SESSION_NAMED: "session:named",
|
|
1820
|
+
SESSION_THREAD_READY: "session:threadReady",
|
|
1821
|
+
SESSION_CONFIG_CHANGED: "session:configChanged",
|
|
1822
|
+
SESSION_AGENT_SWITCH: "session:agentSwitch",
|
|
1823
|
+
// --- Agent ---
|
|
1824
|
+
AGENT_EVENT: "agent:event",
|
|
1825
|
+
AGENT_PROMPT: "agent:prompt",
|
|
1826
|
+
// --- Permissions ---
|
|
1827
|
+
PERMISSION_REQUEST: "permission:request",
|
|
1828
|
+
PERMISSION_RESOLVED: "permission:resolved",
|
|
1829
|
+
// --- Message visibility ---
|
|
1830
|
+
MESSAGE_QUEUED: "message:queued",
|
|
1831
|
+
MESSAGE_PROCESSING: "message:processing",
|
|
1832
|
+
// --- System lifecycle ---
|
|
1833
|
+
KERNEL_BOOTED: "kernel:booted",
|
|
1834
|
+
SYSTEM_READY: "system:ready",
|
|
1835
|
+
SYSTEM_SHUTDOWN: "system:shutdown",
|
|
1836
|
+
SYSTEM_COMMANDS_READY: "system:commands-ready",
|
|
1837
|
+
// --- Plugin lifecycle ---
|
|
1838
|
+
PLUGIN_LOADED: "plugin:loaded",
|
|
1839
|
+
PLUGIN_FAILED: "plugin:failed",
|
|
1840
|
+
PLUGIN_DISABLED: "plugin:disabled",
|
|
1841
|
+
PLUGIN_UNLOADED: "plugin:unloaded",
|
|
1842
|
+
// --- Usage ---
|
|
1843
|
+
USAGE_RECORDED: "usage:recorded"
|
|
1844
|
+
};
|
|
1845
|
+
SessionEv = {
|
|
1846
|
+
AGENT_EVENT: "agent_event",
|
|
1847
|
+
PERMISSION_REQUEST: "permission_request",
|
|
1848
|
+
SESSION_END: "session_end",
|
|
1849
|
+
STATUS_CHANGE: "status_change",
|
|
1850
|
+
NAMED: "named",
|
|
1851
|
+
ERROR: "error",
|
|
1852
|
+
PROMPT_COUNT_CHANGED: "prompt_count_changed",
|
|
1853
|
+
TURN_STARTED: "turn_started"
|
|
1854
|
+
};
|
|
1855
|
+
}
|
|
1856
|
+
});
|
|
1857
|
+
|
|
1760
1858
|
// src/plugins/security/index.ts
|
|
1761
1859
|
var security_exports = {};
|
|
1762
1860
|
__export(security_exports, {
|
|
@@ -1855,7 +1953,7 @@ function createSecurityPlugin() {
|
|
|
1855
1953
|
};
|
|
1856
1954
|
};
|
|
1857
1955
|
const guard = new SecurityGuard(getSecurityConfig, core.sessionManager);
|
|
1858
|
-
ctx.registerMiddleware(
|
|
1956
|
+
ctx.registerMiddleware(Hook.MESSAGE_INCOMING, {
|
|
1859
1957
|
handler: async (payload, next) => {
|
|
1860
1958
|
const access2 = await guard.checkAccess(payload);
|
|
1861
1959
|
if (!access2.allowed) {
|
|
@@ -1875,6 +1973,7 @@ var init_security = __esm({
|
|
|
1875
1973
|
"src/plugins/security/index.ts"() {
|
|
1876
1974
|
"use strict";
|
|
1877
1975
|
init_security_guard();
|
|
1976
|
+
init_events();
|
|
1878
1977
|
security_default = createSecurityPlugin();
|
|
1879
1978
|
}
|
|
1880
1979
|
});
|
|
@@ -3427,7 +3526,7 @@ var init_history_recorder = __esm({
|
|
|
3427
3526
|
}
|
|
3428
3527
|
states = /* @__PURE__ */ new Map();
|
|
3429
3528
|
debounceTimers = /* @__PURE__ */ new Map();
|
|
3430
|
-
onBeforePrompt(sessionId, text6, attachments) {
|
|
3529
|
+
onBeforePrompt(sessionId, text6, attachments, sourceAdapterId) {
|
|
3431
3530
|
let state = this.states.get(sessionId);
|
|
3432
3531
|
if (!state) {
|
|
3433
3532
|
state = {
|
|
@@ -3445,6 +3544,9 @@ var init_history_recorder = __esm({
|
|
|
3445
3544
|
if (attachments && attachments.length > 0) {
|
|
3446
3545
|
userTurn.attachments = attachments.map(toHistoryAttachment);
|
|
3447
3546
|
}
|
|
3547
|
+
if (sourceAdapterId) {
|
|
3548
|
+
userTurn.sourceAdapterId = sourceAdapterId;
|
|
3549
|
+
}
|
|
3448
3550
|
state.history.turns.push(userTurn);
|
|
3449
3551
|
const assistantTurn = {
|
|
3450
3552
|
index: state.history.turns.length,
|
|
@@ -3729,6 +3831,7 @@ var init_context = __esm({
|
|
|
3729
3831
|
init_history_provider();
|
|
3730
3832
|
init_history_recorder();
|
|
3731
3833
|
init_history_store();
|
|
3834
|
+
init_events();
|
|
3732
3835
|
contextPlugin = {
|
|
3733
3836
|
name: "@openacp/context",
|
|
3734
3837
|
version: "1.0.0",
|
|
@@ -3772,35 +3875,35 @@ var init_context = __esm({
|
|
|
3772
3875
|
manager.setHistoryStore(store);
|
|
3773
3876
|
manager.registerFlusher((sessionId) => recorder.flush(sessionId));
|
|
3774
3877
|
ctx.registerService("context", manager);
|
|
3775
|
-
ctx.registerMiddleware(
|
|
3878
|
+
ctx.registerMiddleware(Hook.AGENT_BEFORE_PROMPT, {
|
|
3776
3879
|
priority: 200,
|
|
3777
3880
|
handler: async (payload, next) => {
|
|
3778
|
-
recorder.onBeforePrompt(payload.sessionId, payload.text, payload.attachments);
|
|
3881
|
+
recorder.onBeforePrompt(payload.sessionId, payload.text, payload.attachments, payload.sourceAdapterId);
|
|
3779
3882
|
return next();
|
|
3780
3883
|
}
|
|
3781
3884
|
});
|
|
3782
|
-
ctx.registerMiddleware(
|
|
3885
|
+
ctx.registerMiddleware(Hook.AGENT_AFTER_EVENT, {
|
|
3783
3886
|
priority: 200,
|
|
3784
3887
|
handler: async (payload, next) => {
|
|
3785
3888
|
recorder.onAfterEvent(payload.sessionId, payload.event);
|
|
3786
3889
|
return next();
|
|
3787
3890
|
}
|
|
3788
3891
|
});
|
|
3789
|
-
ctx.registerMiddleware(
|
|
3892
|
+
ctx.registerMiddleware(Hook.TURN_END, {
|
|
3790
3893
|
priority: 200,
|
|
3791
3894
|
handler: async (payload, next) => {
|
|
3792
3895
|
await recorder.onTurnEnd(payload.sessionId, payload.stopReason);
|
|
3793
3896
|
return next();
|
|
3794
3897
|
}
|
|
3795
3898
|
});
|
|
3796
|
-
ctx.registerMiddleware(
|
|
3899
|
+
ctx.registerMiddleware(Hook.PERMISSION_AFTER_RESOLVE, {
|
|
3797
3900
|
priority: 200,
|
|
3798
3901
|
handler: async (payload, next) => {
|
|
3799
3902
|
recorder.onPermissionResolved(payload.sessionId, payload.requestId, payload.decision);
|
|
3800
3903
|
return next();
|
|
3801
3904
|
}
|
|
3802
3905
|
});
|
|
3803
|
-
ctx.registerMiddleware(
|
|
3906
|
+
ctx.registerMiddleware(Hook.SESSION_AFTER_DESTROY, {
|
|
3804
3907
|
priority: 200,
|
|
3805
3908
|
handler: async (payload, next) => {
|
|
3806
3909
|
await recorder.onSessionDestroy(payload.sessionId);
|
|
@@ -7886,6 +7989,7 @@ var MAX_SSE_CONNECTIONS, SSEManager;
|
|
|
7886
7989
|
var init_sse_manager = __esm({
|
|
7887
7990
|
"src/plugins/api-server/sse-manager.ts"() {
|
|
7888
7991
|
"use strict";
|
|
7992
|
+
init_events();
|
|
7889
7993
|
MAX_SSE_CONNECTIONS = 50;
|
|
7890
7994
|
SSEManager = class {
|
|
7891
7995
|
constructor(eventBus, getSessionStats, startedAt) {
|
|
@@ -7900,14 +8004,14 @@ var init_sse_manager = __esm({
|
|
|
7900
8004
|
setup() {
|
|
7901
8005
|
if (!this.eventBus) return;
|
|
7902
8006
|
const events = [
|
|
7903
|
-
|
|
7904
|
-
|
|
7905
|
-
|
|
7906
|
-
|
|
7907
|
-
|
|
7908
|
-
|
|
7909
|
-
|
|
7910
|
-
|
|
8007
|
+
BusEvent.SESSION_CREATED,
|
|
8008
|
+
BusEvent.SESSION_UPDATED,
|
|
8009
|
+
BusEvent.SESSION_DELETED,
|
|
8010
|
+
BusEvent.AGENT_EVENT,
|
|
8011
|
+
BusEvent.PERMISSION_REQUEST,
|
|
8012
|
+
BusEvent.PERMISSION_RESOLVED,
|
|
8013
|
+
BusEvent.MESSAGE_QUEUED,
|
|
8014
|
+
BusEvent.MESSAGE_PROCESSING
|
|
7911
8015
|
];
|
|
7912
8016
|
for (const eventName of events) {
|
|
7913
8017
|
const handler = (data) => {
|
|
@@ -7970,12 +8074,12 @@ data: ${JSON.stringify(data)}
|
|
|
7970
8074
|
|
|
7971
8075
|
`;
|
|
7972
8076
|
const sessionEvents = [
|
|
7973
|
-
|
|
7974
|
-
|
|
7975
|
-
|
|
7976
|
-
|
|
7977
|
-
|
|
7978
|
-
|
|
8077
|
+
BusEvent.AGENT_EVENT,
|
|
8078
|
+
BusEvent.PERMISSION_REQUEST,
|
|
8079
|
+
BusEvent.PERMISSION_RESOLVED,
|
|
8080
|
+
BusEvent.SESSION_UPDATED,
|
|
8081
|
+
BusEvent.MESSAGE_QUEUED,
|
|
8082
|
+
BusEvent.MESSAGE_PROCESSING
|
|
7979
8083
|
];
|
|
7980
8084
|
for (const res of this.sseConnections) {
|
|
7981
8085
|
const filter = res.sessionFilter;
|
|
@@ -8167,10 +8271,7 @@ var init_sessions = __esm({
|
|
|
8167
8271
|
limit: z.coerce.number().int().min(1).max(100).default(50),
|
|
8168
8272
|
offset: z.coerce.number().int().min(0).default(0)
|
|
8169
8273
|
});
|
|
8170
|
-
WorkspaceNameSchema = z.string().optional()
|
|
8171
|
-
(v) => v === void 0 || !v.startsWith("/") && !v.startsWith("~"),
|
|
8172
|
-
{ message: "workspace must be a relative name, not an absolute path" }
|
|
8173
|
-
);
|
|
8274
|
+
WorkspaceNameSchema = z.string().optional();
|
|
8174
8275
|
CreateSessionBodySchema = z.object({
|
|
8175
8276
|
agent: z.string().max(200).optional(),
|
|
8176
8277
|
workspace: WorkspaceNameSchema,
|
|
@@ -8185,7 +8286,7 @@ var init_sessions = __esm({
|
|
|
8185
8286
|
channel: z.string().max(200).optional()
|
|
8186
8287
|
});
|
|
8187
8288
|
AttachmentInputSchema = z.object({
|
|
8188
|
-
fileName: z.string().
|
|
8289
|
+
fileName: z.string().min(1).max(255),
|
|
8189
8290
|
mimeType: z.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9!#$&\-^_]*\/[a-zA-Z0-9][a-zA-Z0-9!#$&\-^_.+]*$/, "mimeType must be a valid MIME type").max(200),
|
|
8190
8291
|
data: z.string().max(15e6)
|
|
8191
8292
|
// ~10 MB base64 ≈ 13.3 MB string
|
|
@@ -8317,15 +8418,22 @@ async function sessionRoutes(app, deps) {
|
|
|
8317
8418
|
const channelId = adapterId ?? "api";
|
|
8318
8419
|
const resolvedAgent = body.agent || deps.core.configManager.get().defaultAgent;
|
|
8319
8420
|
const agentDef = deps.core.agentCatalog.resolve(resolvedAgent);
|
|
8320
|
-
|
|
8321
|
-
|
|
8322
|
-
|
|
8421
|
+
let resolvedWorkspace;
|
|
8422
|
+
try {
|
|
8423
|
+
resolvedWorkspace = deps.core.configManager.resolveWorkspace(
|
|
8424
|
+
body.workspace || agentDef?.workingDirectory
|
|
8425
|
+
);
|
|
8426
|
+
} catch (err) {
|
|
8427
|
+
throw new BadRequestError(
|
|
8428
|
+
"INVALID_WORKSPACE",
|
|
8429
|
+
err instanceof Error ? err.message : "Invalid workspace path"
|
|
8430
|
+
);
|
|
8431
|
+
}
|
|
8323
8432
|
const session = await deps.core.createSession({
|
|
8324
8433
|
channelId,
|
|
8325
8434
|
agentName: resolvedAgent,
|
|
8326
8435
|
workingDirectory: resolvedWorkspace,
|
|
8327
|
-
createThread: !!adapter
|
|
8328
|
-
initialName: `\u{1F504} ${resolvedAgent} \u2014 New Session`
|
|
8436
|
+
createThread: !!adapter
|
|
8329
8437
|
});
|
|
8330
8438
|
return {
|
|
8331
8439
|
sessionId: session.id,
|
|
@@ -8833,6 +8941,7 @@ var init_config2 = __esm({
|
|
|
8833
8941
|
defaultAgent: z4.string(),
|
|
8834
8942
|
workspace: z4.object({
|
|
8835
8943
|
baseDir: z4.string().default("~/openacp-workspace"),
|
|
8944
|
+
allowExternalWorkspaces: z4.boolean().default(true),
|
|
8836
8945
|
security: z4.object({
|
|
8837
8946
|
allowedPaths: z4.array(z4.string()).default([]),
|
|
8838
8947
|
envWhitelist: z4.array(z4.string()).default([])
|
|
@@ -8953,13 +9062,22 @@ var init_config2 = __esm({
|
|
|
8953
9062
|
if (input2.startsWith("/") || input2.startsWith("~")) {
|
|
8954
9063
|
const resolved2 = expandHome3(input2);
|
|
8955
9064
|
const base = expandHome3(this.config.workspace.baseDir);
|
|
8956
|
-
|
|
8957
|
-
|
|
9065
|
+
const isInternal = resolved2 === base || resolved2.startsWith(base + path26.sep);
|
|
9066
|
+
if (!isInternal) {
|
|
9067
|
+
if (!this.config.workspace.allowExternalWorkspaces) {
|
|
9068
|
+
throw new Error(
|
|
9069
|
+
`Workspace path "${input2}" is outside base directory "${this.config.workspace.baseDir}". Set allowExternalWorkspaces: true to allow this.`
|
|
9070
|
+
);
|
|
9071
|
+
}
|
|
9072
|
+
if (!fs22.existsSync(resolved2)) {
|
|
9073
|
+
throw new Error(
|
|
9074
|
+
`Workspace path "${input2}" does not exist.`
|
|
9075
|
+
);
|
|
9076
|
+
}
|
|
8958
9077
|
return resolved2;
|
|
8959
9078
|
}
|
|
8960
|
-
|
|
8961
|
-
|
|
8962
|
-
);
|
|
9079
|
+
fs22.mkdirSync(resolved2, { recursive: true });
|
|
9080
|
+
return resolved2;
|
|
8963
9081
|
}
|
|
8964
9082
|
const name = input2.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
8965
9083
|
if (name !== input2) {
|
|
@@ -10183,7 +10301,7 @@ function createApiServerPlugin() {
|
|
|
10183
10301
|
);
|
|
10184
10302
|
ctx.registerService("api-server", apiService);
|
|
10185
10303
|
cleanupInterval = setInterval(() => tokenStore.cleanup(), 60 * 60 * 1e3);
|
|
10186
|
-
ctx.on(
|
|
10304
|
+
ctx.on(BusEvent.SYSTEM_READY, async () => {
|
|
10187
10305
|
log15.info(
|
|
10188
10306
|
{ configPort: apiConfig.port, configHost: apiConfig.host },
|
|
10189
10307
|
"API server starting..."
|
|
@@ -10235,6 +10353,7 @@ var log15, cachedVersion, api_server_default;
|
|
|
10235
10353
|
var init_api_server = __esm({
|
|
10236
10354
|
"src/plugins/api-server/index.ts"() {
|
|
10237
10355
|
"use strict";
|
|
10356
|
+
init_events();
|
|
10238
10357
|
init_log();
|
|
10239
10358
|
log15 = createChildLogger({ module: "api-server" });
|
|
10240
10359
|
api_server_default = createApiServerPlugin();
|
|
@@ -10679,6 +10798,7 @@ var init_sse_adapter = __esm({
|
|
|
10679
10798
|
init_event_buffer();
|
|
10680
10799
|
init_adapter();
|
|
10681
10800
|
init_routes();
|
|
10801
|
+
init_events();
|
|
10682
10802
|
_adapter = null;
|
|
10683
10803
|
_connectionManager = null;
|
|
10684
10804
|
plugin = {
|
|
@@ -10705,11 +10825,11 @@ var init_sse_adapter = __esm({
|
|
|
10705
10825
|
_connectionManager = connectionManager;
|
|
10706
10826
|
ctx.registerService("adapter:sse", adapter);
|
|
10707
10827
|
const commandRegistry = ctx.getService("command-registry");
|
|
10708
|
-
ctx.on(
|
|
10828
|
+
ctx.on(BusEvent.SESSION_DELETED, (data) => {
|
|
10709
10829
|
const { sessionId } = data;
|
|
10710
10830
|
eventBuffer.cleanup(sessionId);
|
|
10711
10831
|
});
|
|
10712
|
-
ctx.on(
|
|
10832
|
+
ctx.on(BusEvent.SESSION_ENDED, (data) => {
|
|
10713
10833
|
const { sessionId } = data;
|
|
10714
10834
|
eventBuffer.cleanup(sessionId);
|
|
10715
10835
|
});
|
|
@@ -12968,7 +13088,6 @@ var menu_exports = {};
|
|
|
12968
13088
|
__export(menu_exports, {
|
|
12969
13089
|
buildMenuKeyboard: () => buildMenuKeyboard,
|
|
12970
13090
|
buildSkillMessages: () => buildSkillMessages,
|
|
12971
|
-
handleClear: () => handleClear,
|
|
12972
13091
|
handleHelp: () => handleHelp,
|
|
12973
13092
|
handleMenu: () => handleMenu
|
|
12974
13093
|
});
|
|
@@ -13029,31 +13148,11 @@ Each session gets its own topic \u2014 chat there to work with the agent.
|
|
|
13029
13148
|
/bypass_permissions \u2014 Toggle bypass permissions
|
|
13030
13149
|
/handoff \u2014 Continue session in terminal
|
|
13031
13150
|
/archive \u2014 Archive session topic
|
|
13032
|
-
/clear \u2014 Clear assistant history
|
|
13033
13151
|
|
|
13034
13152
|
\u{1F4AC} Need help? Just ask me in this topic!`,
|
|
13035
13153
|
{ parse_mode: "HTML" }
|
|
13036
13154
|
);
|
|
13037
13155
|
}
|
|
13038
|
-
async function handleClear(ctx, assistant) {
|
|
13039
|
-
if (!assistant) {
|
|
13040
|
-
await ctx.reply("\u26A0\uFE0F Assistant is not available.", { parse_mode: "HTML" });
|
|
13041
|
-
return;
|
|
13042
|
-
}
|
|
13043
|
-
const threadId = ctx.message?.message_thread_id;
|
|
13044
|
-
if (threadId !== assistant.topicId) {
|
|
13045
|
-
await ctx.reply("\u2139\uFE0F /clear only works in the Assistant topic.", { parse_mode: "HTML" });
|
|
13046
|
-
return;
|
|
13047
|
-
}
|
|
13048
|
-
await ctx.reply("\u{1F504} Clearing assistant history...", { parse_mode: "HTML" });
|
|
13049
|
-
try {
|
|
13050
|
-
await assistant.respawn();
|
|
13051
|
-
await ctx.reply("\u2705 Assistant history cleared.", { parse_mode: "HTML" });
|
|
13052
|
-
} catch (err) {
|
|
13053
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
13054
|
-
await ctx.reply(`\u274C Failed to clear: <code>${message}</code>`, { parse_mode: "HTML" });
|
|
13055
|
-
}
|
|
13056
|
-
}
|
|
13057
13156
|
function buildSkillMessages(commands) {
|
|
13058
13157
|
const sorted = [...commands].sort((a, b) => a.name.localeCompare(b.name));
|
|
13059
13158
|
const header2 = "\u{1F6E0} <b>Available Skills</b>\n";
|
|
@@ -14703,7 +14802,6 @@ var init_commands3 = __esm({
|
|
|
14703
14802
|
{ command: "menu", description: "Show menu" },
|
|
14704
14803
|
{ command: "integrate", description: "Manage agent integrations" },
|
|
14705
14804
|
{ command: "handoff", description: "Continue this session in your terminal" },
|
|
14706
|
-
{ command: "clear", description: "Clear assistant history" },
|
|
14707
14805
|
{ command: "restart", description: "Restart OpenACP" },
|
|
14708
14806
|
{ command: "update", description: "Update to latest version and restart" },
|
|
14709
14807
|
{ command: "doctor", description: "Run system diagnostics" },
|
|
@@ -16467,6 +16565,7 @@ var log29, TelegramAdapter;
|
|
|
16467
16565
|
var init_adapter2 = __esm({
|
|
16468
16566
|
"src/plugins/telegram/adapter.ts"() {
|
|
16469
16567
|
"use strict";
|
|
16568
|
+
init_events();
|
|
16470
16569
|
init_log();
|
|
16471
16570
|
init_topics2();
|
|
16472
16571
|
init_commands3();
|
|
@@ -16936,7 +17035,7 @@ ${p2}` : p2;
|
|
|
16936
17035
|
log29.warn({ err, sessionId }, "Failed to send initial messages for new session");
|
|
16937
17036
|
});
|
|
16938
17037
|
};
|
|
16939
|
-
this.core.eventBus.on(
|
|
17038
|
+
this.core.eventBus.on(BusEvent.SESSION_THREAD_READY, this._threadReadyHandler);
|
|
16940
17039
|
this._configChangedHandler = ({ sessionId }) => {
|
|
16941
17040
|
this.updateControlMessage(sessionId).catch(() => {
|
|
16942
17041
|
});
|
|
@@ -16969,7 +17068,7 @@ ${p2}` : p2;
|
|
|
16969
17068
|
log29.warn({ err }, "Failed to send welcome message");
|
|
16970
17069
|
}
|
|
16971
17070
|
try {
|
|
16972
|
-
await this.core.assistantManager.
|
|
17071
|
+
await this.core.assistantManager.getOrSpawn("telegram", String(this.assistantTopicId));
|
|
16973
17072
|
} catch (err) {
|
|
16974
17073
|
log29.error({ err }, "Failed to spawn assistant");
|
|
16975
17074
|
}
|
|
@@ -17028,7 +17127,7 @@ OpenACP will automatically retry until this is resolved.`;
|
|
|
17028
17127
|
}
|
|
17029
17128
|
this.sessionTrackers.clear();
|
|
17030
17129
|
if (this._threadReadyHandler) {
|
|
17031
|
-
this.core.eventBus.off(
|
|
17130
|
+
this.core.eventBus.off(BusEvent.SESSION_THREAD_READY, this._threadReadyHandler);
|
|
17032
17131
|
this._threadReadyHandler = void 0;
|
|
17033
17132
|
}
|
|
17034
17133
|
if (this._configChangedHandler) {
|
|
@@ -18832,6 +18931,47 @@ var init_typed_emitter = __esm({
|
|
|
18832
18931
|
}
|
|
18833
18932
|
});
|
|
18834
18933
|
|
|
18934
|
+
// src/core/agents/attachment-blocks.ts
|
|
18935
|
+
function buildAttachmentNote(att, capabilities) {
|
|
18936
|
+
const tooLarge = att.size > MAX_ATTACHMENT_SIZE;
|
|
18937
|
+
if (tooLarge) {
|
|
18938
|
+
const sizeMB = Math.round(att.size / 1024 / 1024);
|
|
18939
|
+
return `[Attachment skipped: "${att.fileName}" is too large (${sizeMB}MB > 10MB limit)]`;
|
|
18940
|
+
}
|
|
18941
|
+
if (att.type === "image") {
|
|
18942
|
+
if (!capabilities.image) {
|
|
18943
|
+
return null;
|
|
18944
|
+
}
|
|
18945
|
+
if (!SUPPORTED_IMAGE_MIMES.has(att.mimeType)) {
|
|
18946
|
+
return `[Attachment skipped: image format not supported (${att.mimeType})]`;
|
|
18947
|
+
}
|
|
18948
|
+
return null;
|
|
18949
|
+
}
|
|
18950
|
+
if (att.type === "audio") {
|
|
18951
|
+
if (!capabilities.audio) {
|
|
18952
|
+
return null;
|
|
18953
|
+
}
|
|
18954
|
+
return null;
|
|
18955
|
+
}
|
|
18956
|
+
return null;
|
|
18957
|
+
}
|
|
18958
|
+
var SUPPORTED_IMAGE_MIMES, MAX_ATTACHMENT_SIZE;
|
|
18959
|
+
var init_attachment_blocks = __esm({
|
|
18960
|
+
"src/core/agents/attachment-blocks.ts"() {
|
|
18961
|
+
"use strict";
|
|
18962
|
+
SUPPORTED_IMAGE_MIMES = /* @__PURE__ */ new Set([
|
|
18963
|
+
"image/jpeg",
|
|
18964
|
+
"image/png",
|
|
18965
|
+
"image/gif",
|
|
18966
|
+
"image/webp",
|
|
18967
|
+
"image/avif",
|
|
18968
|
+
"image/heic",
|
|
18969
|
+
"image/heif"
|
|
18970
|
+
]);
|
|
18971
|
+
MAX_ATTACHMENT_SIZE = 10 * 1024 * 1024;
|
|
18972
|
+
}
|
|
18973
|
+
});
|
|
18974
|
+
|
|
18835
18975
|
// src/core/sessions/terminal-manager.ts
|
|
18836
18976
|
import { spawn as spawn7 } from "child_process";
|
|
18837
18977
|
import { randomUUID } from "crypto";
|
|
@@ -18840,6 +18980,7 @@ var init_terminal_manager = __esm({
|
|
|
18840
18980
|
"src/core/sessions/terminal-manager.ts"() {
|
|
18841
18981
|
"use strict";
|
|
18842
18982
|
init_env_filter();
|
|
18983
|
+
init_events();
|
|
18843
18984
|
TerminalManager = class {
|
|
18844
18985
|
terminals = /* @__PURE__ */ new Map();
|
|
18845
18986
|
maxOutputBytes;
|
|
@@ -18856,7 +18997,7 @@ var init_terminal_manager = __esm({
|
|
|
18856
18997
|
for (const ev of termEnvArr) {
|
|
18857
18998
|
envRecord[ev.name] = ev.value;
|
|
18858
18999
|
}
|
|
18859
|
-
const result = await middlewareChain.execute(
|
|
19000
|
+
const result = await middlewareChain.execute(Hook.TERMINAL_BEFORE_CREATE, {
|
|
18860
19001
|
sessionId,
|
|
18861
19002
|
command: termCommand,
|
|
18862
19003
|
args: termArgs,
|
|
@@ -18910,7 +19051,7 @@ var init_terminal_manager = __esm({
|
|
|
18910
19051
|
childProcess.on("exit", (code, signal) => {
|
|
18911
19052
|
state.exitStatus = { exitCode: code, signal };
|
|
18912
19053
|
if (middlewareChain) {
|
|
18913
|
-
middlewareChain.execute(
|
|
19054
|
+
middlewareChain.execute(Hook.TERMINAL_AFTER_EXIT, {
|
|
18914
19055
|
sessionId,
|
|
18915
19056
|
terminalId,
|
|
18916
19057
|
command: state.command,
|
|
@@ -19124,10 +19265,12 @@ var init_agent_instance = __esm({
|
|
|
19124
19265
|
init_stderr_capture();
|
|
19125
19266
|
init_typed_emitter();
|
|
19126
19267
|
init_read_text_file();
|
|
19268
|
+
init_attachment_blocks();
|
|
19127
19269
|
init_terminal_manager();
|
|
19128
19270
|
init_mcp_manager();
|
|
19129
19271
|
init_debug_tracer();
|
|
19130
19272
|
init_log();
|
|
19273
|
+
init_events();
|
|
19131
19274
|
log31 = createChildLogger({ module: "agent-instance" });
|
|
19132
19275
|
AgentInstance = class _AgentInstance extends TypedEmitter {
|
|
19133
19276
|
connection;
|
|
@@ -19155,7 +19298,7 @@ var init_agent_instance = __esm({
|
|
|
19155
19298
|
super();
|
|
19156
19299
|
this.agentName = agentName;
|
|
19157
19300
|
}
|
|
19158
|
-
static async spawnSubprocess(agentDef, workingDirectory) {
|
|
19301
|
+
static async spawnSubprocess(agentDef, workingDirectory, allowedPaths = []) {
|
|
19159
19302
|
const instance = new _AgentInstance(agentDef.name);
|
|
19160
19303
|
const resolved = resolveAgentCommand(agentDef.command);
|
|
19161
19304
|
log31.debug(
|
|
@@ -19169,10 +19312,7 @@ var init_agent_instance = __esm({
|
|
|
19169
19312
|
const ignorePatterns = PathGuard.loadIgnoreFile(workingDirectory);
|
|
19170
19313
|
instance.pathGuard = new PathGuard({
|
|
19171
19314
|
cwd: workingDirectory,
|
|
19172
|
-
|
|
19173
|
-
// spawnSubprocess would need to receive a SecurityConfig param to use it.
|
|
19174
|
-
// Tracked as follow-up: pass workspace security config through spawn/resume call chain.
|
|
19175
|
-
allowedPaths: [],
|
|
19315
|
+
allowedPaths,
|
|
19176
19316
|
ignorePatterns
|
|
19177
19317
|
});
|
|
19178
19318
|
instance.child = spawn8(
|
|
@@ -19266,7 +19406,7 @@ var init_agent_instance = __esm({
|
|
|
19266
19406
|
if (signal === "SIGINT" || signal === "SIGTERM") return;
|
|
19267
19407
|
if (code !== 0 && code !== null || signal) {
|
|
19268
19408
|
const stderr = this.stderrCapture.getLastLines();
|
|
19269
|
-
this.emit(
|
|
19409
|
+
this.emit(SessionEv.AGENT_EVENT, {
|
|
19270
19410
|
type: "error",
|
|
19271
19411
|
message: signal ? `Agent killed by signal ${signal}
|
|
19272
19412
|
${stderr}` : `Agent crashed (exit code ${code})
|
|
@@ -19278,7 +19418,7 @@ ${stderr}`
|
|
|
19278
19418
|
log31.debug({ sessionId: this.sessionId }, "ACP connection closed");
|
|
19279
19419
|
});
|
|
19280
19420
|
}
|
|
19281
|
-
static async spawn(agentDef, workingDirectory, mcpServers) {
|
|
19421
|
+
static async spawn(agentDef, workingDirectory, mcpServers, allowedPaths) {
|
|
19282
19422
|
log31.debug(
|
|
19283
19423
|
{ agentName: agentDef.name, command: agentDef.command },
|
|
19284
19424
|
"Spawning agent"
|
|
@@ -19286,7 +19426,8 @@ ${stderr}`
|
|
|
19286
19426
|
const spawnStart = Date.now();
|
|
19287
19427
|
const instance = await _AgentInstance.spawnSubprocess(
|
|
19288
19428
|
agentDef,
|
|
19289
|
-
workingDirectory
|
|
19429
|
+
workingDirectory,
|
|
19430
|
+
allowedPaths
|
|
19290
19431
|
);
|
|
19291
19432
|
const resolvedMcp = _AgentInstance.mcpManager.resolve(mcpServers);
|
|
19292
19433
|
const response = await instance.connection.newSession({
|
|
@@ -19309,12 +19450,13 @@ ${stderr}`
|
|
|
19309
19450
|
);
|
|
19310
19451
|
return instance;
|
|
19311
19452
|
}
|
|
19312
|
-
static async resume(agentDef, workingDirectory, agentSessionId, mcpServers) {
|
|
19453
|
+
static async resume(agentDef, workingDirectory, agentSessionId, mcpServers, allowedPaths) {
|
|
19313
19454
|
log31.debug({ agentName: agentDef.name, agentSessionId }, "Resuming agent");
|
|
19314
19455
|
const spawnStart = Date.now();
|
|
19315
19456
|
const instance = await _AgentInstance.spawnSubprocess(
|
|
19316
19457
|
agentDef,
|
|
19317
|
-
workingDirectory
|
|
19458
|
+
workingDirectory,
|
|
19459
|
+
allowedPaths
|
|
19318
19460
|
);
|
|
19319
19461
|
const resolvedMcp = _AgentInstance.mcpManager.resolve(mcpServers);
|
|
19320
19462
|
try {
|
|
@@ -19502,7 +19644,7 @@ ${stderr}`
|
|
|
19502
19644
|
return;
|
|
19503
19645
|
}
|
|
19504
19646
|
if (event !== null) {
|
|
19505
|
-
self.emit(
|
|
19647
|
+
self.emit(SessionEv.AGENT_EVENT, event);
|
|
19506
19648
|
}
|
|
19507
19649
|
},
|
|
19508
19650
|
// ── Permission requests ──────────────────────────────────────────────
|
|
@@ -19529,7 +19671,7 @@ ${stderr}`
|
|
|
19529
19671
|
throw new Error(`[Access denied] ${pathCheck.reason}`);
|
|
19530
19672
|
}
|
|
19531
19673
|
if (self.middlewareChain) {
|
|
19532
|
-
const result = await self.middlewareChain.execute(
|
|
19674
|
+
const result = await self.middlewareChain.execute(Hook.FS_BEFORE_READ, { sessionId: self.sessionId, path: p2.path, line: p2.line, limit: p2.limit }, async (r) => r);
|
|
19533
19675
|
if (!result) return { content: "" };
|
|
19534
19676
|
p2.path = result.path;
|
|
19535
19677
|
}
|
|
@@ -19547,7 +19689,7 @@ ${stderr}`
|
|
|
19547
19689
|
throw new Error(`[Access denied] ${pathCheck.reason}`);
|
|
19548
19690
|
}
|
|
19549
19691
|
if (self.middlewareChain) {
|
|
19550
|
-
const result = await self.middlewareChain.execute(
|
|
19692
|
+
const result = await self.middlewareChain.execute(Hook.FS_BEFORE_WRITE, { sessionId: self.sessionId, path: writePath, content: writeContent }, async (r) => r);
|
|
19551
19693
|
if (!result) return {};
|
|
19552
19694
|
writePath = result.path;
|
|
19553
19695
|
writeContent = result.content;
|
|
@@ -19644,10 +19786,16 @@ ${stderr}`
|
|
|
19644
19786
|
// ── Prompt & lifecycle ──────────────────────────────────────────────
|
|
19645
19787
|
async prompt(text6, attachments) {
|
|
19646
19788
|
const contentBlocks = [{ type: "text", text: text6 }];
|
|
19647
|
-
const
|
|
19789
|
+
const capabilities = this.promptCapabilities ?? {};
|
|
19648
19790
|
for (const att of attachments ?? []) {
|
|
19649
|
-
const
|
|
19650
|
-
if (
|
|
19791
|
+
const skipNote = buildAttachmentNote(att, capabilities);
|
|
19792
|
+
if (skipNote !== null) {
|
|
19793
|
+
contentBlocks[0].text += `
|
|
19794
|
+
|
|
19795
|
+
${skipNote}`;
|
|
19796
|
+
continue;
|
|
19797
|
+
}
|
|
19798
|
+
if (att.type === "image" && capabilities.image && SUPPORTED_IMAGE_MIMES.has(att.mimeType)) {
|
|
19651
19799
|
const attCheck = this.pathGuard.validatePath(att.filePath, "read");
|
|
19652
19800
|
if (!attCheck.allowed) {
|
|
19653
19801
|
contentBlocks[0].text += `
|
|
@@ -19657,7 +19805,7 @@ ${stderr}`
|
|
|
19657
19805
|
}
|
|
19658
19806
|
const data = await fs40.promises.readFile(att.filePath);
|
|
19659
19807
|
contentBlocks.push({ type: "image", data: data.toString("base64"), mimeType: att.mimeType });
|
|
19660
|
-
} else if (att.type === "audio" &&
|
|
19808
|
+
} else if (att.type === "audio" && capabilities.audio) {
|
|
19661
19809
|
const attCheck = this.pathGuard.validatePath(att.filePath, "read");
|
|
19662
19810
|
if (!attCheck.allowed) {
|
|
19663
19811
|
contentBlocks[0].text += `
|
|
@@ -19668,9 +19816,9 @@ ${stderr}`
|
|
|
19668
19816
|
const data = await fs40.promises.readFile(att.filePath);
|
|
19669
19817
|
contentBlocks.push({ type: "audio", data: data.toString("base64"), mimeType: att.mimeType });
|
|
19670
19818
|
} else {
|
|
19671
|
-
if (
|
|
19819
|
+
if (att.type === "image" || att.type === "audio") {
|
|
19672
19820
|
log31.debug(
|
|
19673
|
-
{ type: att.type, capabilities
|
|
19821
|
+
{ type: att.type, capabilities },
|
|
19674
19822
|
"Agent does not support %s content, falling back to file path",
|
|
19675
19823
|
att.type
|
|
19676
19824
|
);
|
|
@@ -19733,15 +19881,15 @@ var init_agent_manager = __esm({
|
|
|
19733
19881
|
getAgent(name) {
|
|
19734
19882
|
return this.catalog.resolve(name);
|
|
19735
19883
|
}
|
|
19736
|
-
async spawn(agentName, workingDirectory) {
|
|
19884
|
+
async spawn(agentName, workingDirectory, allowedPaths) {
|
|
19737
19885
|
const agentDef = this.getAgent(agentName);
|
|
19738
19886
|
if (!agentDef) throw new Error(`Agent "${agentName}" is not installed. Run "openacp agents install ${agentName}" to add it.`);
|
|
19739
|
-
return AgentInstance.spawn(agentDef, workingDirectory);
|
|
19887
|
+
return AgentInstance.spawn(agentDef, workingDirectory, void 0, allowedPaths);
|
|
19740
19888
|
}
|
|
19741
|
-
async resume(agentName, workingDirectory, agentSessionId) {
|
|
19889
|
+
async resume(agentName, workingDirectory, agentSessionId, allowedPaths) {
|
|
19742
19890
|
const agentDef = this.getAgent(agentName);
|
|
19743
19891
|
if (!agentDef) throw new Error(`Agent "${agentName}" is not installed. Run "openacp agents install ${agentName}" to add it.`);
|
|
19744
|
-
return AgentInstance.resume(agentDef, workingDirectory, agentSessionId);
|
|
19892
|
+
return AgentInstance.resume(agentDef, workingDirectory, agentSessionId, void 0, allowedPaths);
|
|
19745
19893
|
}
|
|
19746
19894
|
};
|
|
19747
19895
|
}
|
|
@@ -19938,6 +20086,7 @@ var init_session2 = __esm({
|
|
|
19938
20086
|
init_permission_gate();
|
|
19939
20087
|
init_log();
|
|
19940
20088
|
init_turn_context();
|
|
20089
|
+
init_events();
|
|
19941
20090
|
moduleLog = createChildLogger({ module: "session" });
|
|
19942
20091
|
TTS_PROMPT_INSTRUCTION = `
|
|
19943
20092
|
|
|
@@ -19966,7 +20115,15 @@ Additionally, include a [TTS]...[/TTS] block with a spoken-friendly summary of y
|
|
|
19966
20115
|
}
|
|
19967
20116
|
agentName;
|
|
19968
20117
|
workingDirectory;
|
|
19969
|
-
|
|
20118
|
+
_agentInstance;
|
|
20119
|
+
get agentInstance() {
|
|
20120
|
+
return this._agentInstance;
|
|
20121
|
+
}
|
|
20122
|
+
set agentInstance(agent) {
|
|
20123
|
+
this._agentInstance = agent;
|
|
20124
|
+
this.wireAgentRelay();
|
|
20125
|
+
this.wireCommandsBuffer();
|
|
20126
|
+
}
|
|
19970
20127
|
agentSessionId = "";
|
|
19971
20128
|
_status = "initializing";
|
|
19972
20129
|
name;
|
|
@@ -19990,9 +20147,6 @@ Additionally, include a [TTS]...[/TTS] block with a spoken-friendly summary of y
|
|
|
19990
20147
|
threadIds = /* @__PURE__ */ new Map();
|
|
19991
20148
|
/** Active turn context — sealed on prompt dequeue, cleared on turn end */
|
|
19992
20149
|
activeTurnContext = null;
|
|
19993
|
-
/** The agentInstance for which the agent→session event relay is wired (prevents duplicate relays from multiple bridges).
|
|
19994
|
-
* When the agent is swapped, the relay must be re-wired to the new instance. */
|
|
19995
|
-
agentRelaySource = null;
|
|
19996
20150
|
permissionGate = new PermissionGate();
|
|
19997
20151
|
queue;
|
|
19998
20152
|
speechService;
|
|
@@ -20016,23 +20170,37 @@ Additionally, include a [TTS]...[/TTS] block with a spoken-friendly summary of y
|
|
|
20016
20170
|
this.log.error({ err }, "Prompt execution failed");
|
|
20017
20171
|
const message = err instanceof Error ? err.message : String(err);
|
|
20018
20172
|
this.fail(message);
|
|
20019
|
-
this.emit(
|
|
20173
|
+
this.emit(SessionEv.AGENT_EVENT, { type: "error", message: `Prompt execution failed: ${message}` });
|
|
20020
20174
|
}
|
|
20021
20175
|
);
|
|
20022
|
-
|
|
20176
|
+
}
|
|
20177
|
+
/** Wire the agent→session event relay on the current agentInstance.
|
|
20178
|
+
* Removes any previous relay first to avoid duplicates on agent switch.
|
|
20179
|
+
* This relay ensures session.emit("agent_event") fires for ALL sessions,
|
|
20180
|
+
* including headless API sessions that have no SessionBridge attached. */
|
|
20181
|
+
agentRelayCleanup;
|
|
20182
|
+
wireAgentRelay() {
|
|
20183
|
+
this.agentRelayCleanup?.();
|
|
20184
|
+
const instance = this._agentInstance;
|
|
20185
|
+
const handler = (event) => {
|
|
20186
|
+
this.emit(SessionEv.AGENT_EVENT, event);
|
|
20187
|
+
};
|
|
20188
|
+
instance.on(SessionEv.AGENT_EVENT, handler);
|
|
20189
|
+
this.agentRelayCleanup = () => instance.off(SessionEv.AGENT_EVENT, handler);
|
|
20023
20190
|
}
|
|
20024
20191
|
/** Wire a listener on the current agentInstance to buffer commands_update events.
|
|
20025
20192
|
* Must be called after every agentInstance replacement (constructor + switchAgent). */
|
|
20026
20193
|
commandsBufferCleanup;
|
|
20027
20194
|
wireCommandsBuffer() {
|
|
20028
20195
|
this.commandsBufferCleanup?.();
|
|
20196
|
+
const instance = this._agentInstance;
|
|
20029
20197
|
const handler = (event) => {
|
|
20030
20198
|
if (event.type === "commands_update") {
|
|
20031
20199
|
this.latestCommands = event.commands;
|
|
20032
20200
|
}
|
|
20033
20201
|
};
|
|
20034
|
-
|
|
20035
|
-
this.commandsBufferCleanup = () =>
|
|
20202
|
+
instance.on(SessionEv.AGENT_EVENT, handler);
|
|
20203
|
+
this.commandsBufferCleanup = () => instance.off(SessionEv.AGENT_EVENT, handler);
|
|
20036
20204
|
}
|
|
20037
20205
|
// --- State Machine ---
|
|
20038
20206
|
get status() {
|
|
@@ -20046,12 +20214,12 @@ Additionally, include a [TTS]...[/TTS] block with a spoken-friendly summary of y
|
|
|
20046
20214
|
fail(reason) {
|
|
20047
20215
|
if (this._status === "error") return;
|
|
20048
20216
|
this.transition("error");
|
|
20049
|
-
this.emit(
|
|
20217
|
+
this.emit(SessionEv.ERROR, new Error(reason));
|
|
20050
20218
|
}
|
|
20051
20219
|
/** Transition to finished — from active only. Emits session_end for backward compat. */
|
|
20052
20220
|
finish(reason) {
|
|
20053
20221
|
this.transition("finished");
|
|
20054
|
-
this.emit(
|
|
20222
|
+
this.emit(SessionEv.SESSION_END, reason ?? "completed");
|
|
20055
20223
|
}
|
|
20056
20224
|
/** Transition to cancelled — from active only (terminal session cancel) */
|
|
20057
20225
|
markCancelled() {
|
|
@@ -20067,7 +20235,7 @@ Additionally, include a [TTS]...[/TTS] block with a spoken-friendly summary of y
|
|
|
20067
20235
|
}
|
|
20068
20236
|
this._status = to;
|
|
20069
20237
|
this.log.debug({ from, to }, "Session status transition");
|
|
20070
|
-
this.emit(
|
|
20238
|
+
this.emit(SessionEv.STATUS_CHANGE, from, to);
|
|
20071
20239
|
}
|
|
20072
20240
|
/** Number of prompts waiting in queue */
|
|
20073
20241
|
get queueDepth() {
|
|
@@ -20089,8 +20257,8 @@ Additionally, include a [TTS]...[/TTS] block with a spoken-friendly summary of y
|
|
|
20089
20257
|
async enqueuePrompt(text6, attachments, routing, externalTurnId) {
|
|
20090
20258
|
const turnId = externalTurnId ?? nanoid4(8);
|
|
20091
20259
|
if (this.middlewareChain) {
|
|
20092
|
-
const payload = { text: text6, attachments, sessionId: this.id };
|
|
20093
|
-
const result = await this.middlewareChain.execute(
|
|
20260
|
+
const payload = { text: text6, attachments, sessionId: this.id, sourceAdapterId: routing?.sourceAdapterId };
|
|
20261
|
+
const result = await this.middlewareChain.execute(Hook.AGENT_BEFORE_PROMPT, payload, async (p2) => p2);
|
|
20094
20262
|
if (!result) return turnId;
|
|
20095
20263
|
text6 = result.text;
|
|
20096
20264
|
attachments = result.attachments;
|
|
@@ -20105,9 +20273,9 @@ Additionally, include a [TTS]...[/TTS] block with a spoken-friendly summary of y
|
|
|
20105
20273
|
routing?.responseAdapterId,
|
|
20106
20274
|
turnId
|
|
20107
20275
|
);
|
|
20108
|
-
this.emit(
|
|
20276
|
+
this.emit(SessionEv.TURN_STARTED, this.activeTurnContext);
|
|
20109
20277
|
this.promptCount++;
|
|
20110
|
-
this.emit(
|
|
20278
|
+
this.emit(SessionEv.PROMPT_COUNT_CHANGED, this.promptCount);
|
|
20111
20279
|
if (this._status === "initializing" || this._status === "cancelled" || this._status === "error") {
|
|
20112
20280
|
this.activate();
|
|
20113
20281
|
}
|
|
@@ -20136,10 +20304,18 @@ ${text6}`;
|
|
|
20136
20304
|
}
|
|
20137
20305
|
} : null;
|
|
20138
20306
|
if (accumulatorListener) {
|
|
20139
|
-
this.on(
|
|
20307
|
+
this.on(SessionEv.AGENT_EVENT, accumulatorListener);
|
|
20308
|
+
}
|
|
20309
|
+
const mw = this.middlewareChain;
|
|
20310
|
+
const afterEventListener = mw ? (event) => {
|
|
20311
|
+
mw.execute(Hook.AGENT_AFTER_EVENT, { sessionId: this.id, event, outgoingMessage: { type: "text", text: "" } }, async (e) => e).catch(() => {
|
|
20312
|
+
});
|
|
20313
|
+
} : null;
|
|
20314
|
+
if (afterEventListener) {
|
|
20315
|
+
this.agentInstance.on(SessionEv.AGENT_EVENT, afterEventListener);
|
|
20140
20316
|
}
|
|
20141
20317
|
if (this.middlewareChain) {
|
|
20142
|
-
this.middlewareChain.execute(
|
|
20318
|
+
this.middlewareChain.execute(Hook.TURN_START, { sessionId: this.id, promptText: processed.text, promptNumber: this.promptCount }, async (p2) => p2).catch(() => {
|
|
20143
20319
|
});
|
|
20144
20320
|
}
|
|
20145
20321
|
let stopReason = "end_turn";
|
|
@@ -20160,10 +20336,13 @@ ${text6}`;
|
|
|
20160
20336
|
promptError = err;
|
|
20161
20337
|
} finally {
|
|
20162
20338
|
if (accumulatorListener) {
|
|
20163
|
-
this.off(
|
|
20339
|
+
this.off(SessionEv.AGENT_EVENT, accumulatorListener);
|
|
20340
|
+
}
|
|
20341
|
+
if (afterEventListener) {
|
|
20342
|
+
this.agentInstance.off(SessionEv.AGENT_EVENT, afterEventListener);
|
|
20164
20343
|
}
|
|
20165
20344
|
if (this.middlewareChain) {
|
|
20166
|
-
this.middlewareChain.execute(
|
|
20345
|
+
this.middlewareChain.execute(Hook.TURN_END, { sessionId: this.id, stopReason, durationMs: Date.now() - promptStart }, async (p2) => p2).catch(() => {
|
|
20167
20346
|
});
|
|
20168
20347
|
}
|
|
20169
20348
|
this.activeTurnContext = null;
|
|
@@ -20208,7 +20387,7 @@ ${text6}`;
|
|
|
20208
20387
|
const audioBuffer = await fs41.promises.readFile(audioPath);
|
|
20209
20388
|
const result = await this.speechService.transcribe(audioBuffer, audioMime);
|
|
20210
20389
|
this.log.info({ provider: "stt", duration: result.duration }, "Voice transcribed");
|
|
20211
|
-
this.emit(
|
|
20390
|
+
this.emit(SessionEv.AGENT_EVENT, {
|
|
20212
20391
|
type: "system_message",
|
|
20213
20392
|
message: `\u{1F3A4} You said: ${result.text}`
|
|
20214
20393
|
});
|
|
@@ -20217,7 +20396,7 @@ ${text6}`;
|
|
|
20217
20396
|
${result.text}` : result.text;
|
|
20218
20397
|
} catch (err) {
|
|
20219
20398
|
this.log.warn({ err }, "STT transcription failed, keeping audio attachment");
|
|
20220
|
-
this.emit(
|
|
20399
|
+
this.emit(SessionEv.AGENT_EVENT, {
|
|
20221
20400
|
type: "error",
|
|
20222
20401
|
message: `Voice transcription failed: ${err.message}`
|
|
20223
20402
|
});
|
|
@@ -20251,12 +20430,12 @@ ${result.text}` : result.text;
|
|
|
20251
20430
|
timeoutPromise
|
|
20252
20431
|
]);
|
|
20253
20432
|
const base64 = result.audioBuffer.toString("base64");
|
|
20254
|
-
this.emit(
|
|
20433
|
+
this.emit(SessionEv.AGENT_EVENT, {
|
|
20255
20434
|
type: "audio_content",
|
|
20256
20435
|
data: base64,
|
|
20257
20436
|
mimeType: result.mimeType
|
|
20258
20437
|
});
|
|
20259
|
-
this.emit(
|
|
20438
|
+
this.emit(SessionEv.AGENT_EVENT, { type: "tts_strip" });
|
|
20260
20439
|
this.log.info("TTS synthesis completed");
|
|
20261
20440
|
} finally {
|
|
20262
20441
|
clearTimeout(ttsTimer);
|
|
@@ -20271,19 +20450,19 @@ ${result.text}` : result.text;
|
|
|
20271
20450
|
const captureHandler = (event) => {
|
|
20272
20451
|
if (event.type === "text") title += event.content;
|
|
20273
20452
|
};
|
|
20274
|
-
this.pause((event) => event !==
|
|
20275
|
-
this.agentInstance.on(
|
|
20453
|
+
this.pause((event) => event !== SessionEv.AGENT_EVENT);
|
|
20454
|
+
this.agentInstance.on(SessionEv.AGENT_EVENT, captureHandler);
|
|
20276
20455
|
try {
|
|
20277
20456
|
await this.agentInstance.prompt(
|
|
20278
20457
|
"Summarize this conversation in max 5 words for a topic title. Reply ONLY with the title, nothing else."
|
|
20279
20458
|
);
|
|
20280
20459
|
this.name = title.trim().slice(0, 50) || `Session ${this.id.slice(0, 6)}`;
|
|
20281
20460
|
this.log.info({ name: this.name }, "Session auto-named");
|
|
20282
|
-
this.emit(
|
|
20461
|
+
this.emit(SessionEv.NAMED, this.name);
|
|
20283
20462
|
} catch {
|
|
20284
20463
|
this.name = `Session ${this.id.slice(0, 6)}`;
|
|
20285
20464
|
} finally {
|
|
20286
|
-
this.agentInstance.off(
|
|
20465
|
+
this.agentInstance.off(SessionEv.AGENT_EVENT, captureHandler);
|
|
20287
20466
|
this.clearBuffer();
|
|
20288
20467
|
this.resume();
|
|
20289
20468
|
}
|
|
@@ -20345,7 +20524,7 @@ ${result.text}` : result.text;
|
|
|
20345
20524
|
/** Set session name explicitly and emit 'named' event */
|
|
20346
20525
|
setName(name) {
|
|
20347
20526
|
this.name = name;
|
|
20348
|
-
this.emit(
|
|
20527
|
+
this.emit(SessionEv.NAMED, name);
|
|
20349
20528
|
}
|
|
20350
20529
|
/** Send a config option change to the agent and update local state from the response. */
|
|
20351
20530
|
async setConfigOption(configId, value) {
|
|
@@ -20361,7 +20540,7 @@ ${result.text}` : result.text;
|
|
|
20361
20540
|
}
|
|
20362
20541
|
async updateConfigOptions(options) {
|
|
20363
20542
|
if (this.middlewareChain) {
|
|
20364
|
-
const result = await this.middlewareChain.execute(
|
|
20543
|
+
const result = await this.middlewareChain.execute(Hook.CONFIG_BEFORE_CHANGE, { sessionId: this.id, configId: "options", oldValue: this.configOptions, newValue: options }, async (p2) => p2);
|
|
20365
20544
|
if (!result) return;
|
|
20366
20545
|
}
|
|
20367
20546
|
this.configOptions = options;
|
|
@@ -20381,7 +20560,7 @@ ${result.text}` : result.text;
|
|
|
20381
20560
|
/** Cancel the current prompt and clear the queue. Stays in active state. */
|
|
20382
20561
|
async abortPrompt() {
|
|
20383
20562
|
if (this.middlewareChain) {
|
|
20384
|
-
const result = await this.middlewareChain.execute(
|
|
20563
|
+
const result = await this.middlewareChain.execute(Hook.AGENT_BEFORE_CANCEL, { sessionId: this.id }, async (p2) => p2);
|
|
20385
20564
|
if (!result) return;
|
|
20386
20565
|
}
|
|
20387
20566
|
this.queue.clear();
|
|
@@ -20422,7 +20601,6 @@ ${result.text}` : result.text;
|
|
|
20422
20601
|
this.configOptions = [];
|
|
20423
20602
|
this.latestCommands = null;
|
|
20424
20603
|
this.applySpawnResponse(newAgent.initialSessionResponse, newAgent.agentCapabilities);
|
|
20425
|
-
this.wireCommandsBuffer();
|
|
20426
20604
|
this.log.info({ from: this.agentSwitchHistory.at(-1).agentName, to: agentName }, "Agent switched");
|
|
20427
20605
|
}
|
|
20428
20606
|
async destroy() {
|
|
@@ -20444,6 +20622,7 @@ var init_session_manager = __esm({
|
|
|
20444
20622
|
"src/core/sessions/session-manager.ts"() {
|
|
20445
20623
|
"use strict";
|
|
20446
20624
|
init_session2();
|
|
20625
|
+
init_events();
|
|
20447
20626
|
SessionManager = class {
|
|
20448
20627
|
sessions = /* @__PURE__ */ new Map();
|
|
20449
20628
|
store;
|
|
@@ -20548,18 +20727,18 @@ var init_session_manager = __esm({
|
|
|
20548
20727
|
}
|
|
20549
20728
|
}
|
|
20550
20729
|
if (this.middlewareChain) {
|
|
20551
|
-
this.middlewareChain.execute(
|
|
20730
|
+
this.middlewareChain.execute(Hook.SESSION_AFTER_DESTROY, { sessionId }, async (p2) => p2).catch(() => {
|
|
20552
20731
|
});
|
|
20553
20732
|
}
|
|
20554
20733
|
}
|
|
20555
20734
|
listSessions(channelId) {
|
|
20556
|
-
const all = Array.from(this.sessions.values());
|
|
20735
|
+
const all = Array.from(this.sessions.values()).filter((s) => !s.isAssistant);
|
|
20557
20736
|
if (channelId) return all.filter((s) => s.channelId === channelId);
|
|
20558
20737
|
return all;
|
|
20559
20738
|
}
|
|
20560
20739
|
listAllSessions(channelId) {
|
|
20561
20740
|
if (this.store) {
|
|
20562
|
-
let records = this.store.list();
|
|
20741
|
+
let records = this.store.list().filter((r) => !r.isAssistant);
|
|
20563
20742
|
if (channelId) records = records.filter((r) => r.channelId === channelId);
|
|
20564
20743
|
return records.map((record) => {
|
|
20565
20744
|
const live2 = this.sessions.get(record.sessionId);
|
|
@@ -20599,7 +20778,7 @@ var init_session_manager = __esm({
|
|
|
20599
20778
|
};
|
|
20600
20779
|
});
|
|
20601
20780
|
}
|
|
20602
|
-
let live = Array.from(this.sessions.values());
|
|
20781
|
+
let live = Array.from(this.sessions.values()).filter((s) => !s.isAssistant);
|
|
20603
20782
|
if (channelId) live = live.filter((s) => s.channelId === channelId);
|
|
20604
20783
|
return live.map((s) => ({
|
|
20605
20784
|
id: s.id,
|
|
@@ -20620,7 +20799,7 @@ var init_session_manager = __esm({
|
|
|
20620
20799
|
}
|
|
20621
20800
|
listRecords(filter) {
|
|
20622
20801
|
if (!this.store) return [];
|
|
20623
|
-
let records = this.store.list();
|
|
20802
|
+
let records = this.store.list().filter((r) => !r.isAssistant);
|
|
20624
20803
|
if (filter?.statuses?.length) {
|
|
20625
20804
|
records = records.filter((r) => filter.statuses.includes(r.status));
|
|
20626
20805
|
}
|
|
@@ -20629,7 +20808,7 @@ var init_session_manager = __esm({
|
|
|
20629
20808
|
async removeRecord(sessionId) {
|
|
20630
20809
|
if (!this.store) return;
|
|
20631
20810
|
await this.store.remove(sessionId);
|
|
20632
|
-
this.eventBus?.emit(
|
|
20811
|
+
this.eventBus?.emit(BusEvent.SESSION_DELETED, { sessionId });
|
|
20633
20812
|
}
|
|
20634
20813
|
/**
|
|
20635
20814
|
* Graceful shutdown: persist session state without killing agent subprocesses.
|
|
@@ -20677,7 +20856,7 @@ var init_session_manager = __esm({
|
|
|
20677
20856
|
this.sessions.clear();
|
|
20678
20857
|
if (this.middlewareChain) {
|
|
20679
20858
|
for (const sessionId of sessionIds) {
|
|
20680
|
-
this.middlewareChain.execute(
|
|
20859
|
+
this.middlewareChain.execute(Hook.SESSION_AFTER_DESTROY, { sessionId }, async (p2) => p2).catch(() => {
|
|
20681
20860
|
});
|
|
20682
20861
|
}
|
|
20683
20862
|
}
|
|
@@ -20694,6 +20873,7 @@ var init_session_bridge = __esm({
|
|
|
20694
20873
|
init_log();
|
|
20695
20874
|
init_bypass_detection();
|
|
20696
20875
|
init_turn_context();
|
|
20876
|
+
init_events();
|
|
20697
20877
|
log32 = createChildLogger({ module: "session-bridge" });
|
|
20698
20878
|
SessionBridge = class {
|
|
20699
20879
|
constructor(session, adapter, deps, adapterId) {
|
|
@@ -20718,7 +20898,7 @@ var init_session_bridge = __esm({
|
|
|
20718
20898
|
try {
|
|
20719
20899
|
const mw = this.deps.middlewareChain;
|
|
20720
20900
|
if (mw) {
|
|
20721
|
-
const result = await mw.execute(
|
|
20901
|
+
const result = await mw.execute(Hook.MESSAGE_OUTGOING, { sessionId, message }, async (m) => m);
|
|
20722
20902
|
this.tracer?.log("core", { step: "middleware:outgoing", sessionId, hook: "message:outgoing", blocked: !result });
|
|
20723
20903
|
if (!result) return;
|
|
20724
20904
|
this.tracer?.log("core", { step: "dispatch", sessionId, message: result.message });
|
|
@@ -20747,17 +20927,11 @@ var init_session_bridge = __esm({
|
|
|
20747
20927
|
connect() {
|
|
20748
20928
|
if (this.connected) return;
|
|
20749
20929
|
this.connected = true;
|
|
20750
|
-
|
|
20751
|
-
this.listen(this.session.agentInstance, "agent_event", (event) => {
|
|
20752
|
-
this.session.emit("agent_event", event);
|
|
20753
|
-
});
|
|
20754
|
-
this.session.agentRelaySource = this.session.agentInstance;
|
|
20755
|
-
}
|
|
20756
|
-
this.listen(this.session, "agent_event", (event) => {
|
|
20930
|
+
this.listen(this.session, SessionEv.AGENT_EVENT, (event) => {
|
|
20757
20931
|
if (this.shouldForward(event)) {
|
|
20758
20932
|
this.dispatchAgentEvent(event);
|
|
20759
20933
|
} else {
|
|
20760
|
-
this.deps.eventBus?.emit(
|
|
20934
|
+
this.deps.eventBus?.emit(BusEvent.AGENT_EVENT, { sessionId: this.session.id, event });
|
|
20761
20935
|
}
|
|
20762
20936
|
});
|
|
20763
20937
|
if (!this.session.agentInstance.onPermissionRequest || this.session.agentInstance.onPermissionRequest.__bridgeId === void 0) {
|
|
@@ -20767,7 +20941,7 @@ var init_session_bridge = __esm({
|
|
|
20767
20941
|
handler.__bridgeId = this.adapterId;
|
|
20768
20942
|
this.session.agentInstance.onPermissionRequest = handler;
|
|
20769
20943
|
}
|
|
20770
|
-
this.listen(this.session,
|
|
20944
|
+
this.listen(this.session, SessionEv.PERMISSION_REQUEST, async (request) => {
|
|
20771
20945
|
const current = this.session.agentInstance.onPermissionRequest;
|
|
20772
20946
|
if (current?.__bridgeId === this.adapterId) return;
|
|
20773
20947
|
if (!this.session.permissionGate.isPending) return;
|
|
@@ -20777,37 +20951,41 @@ var init_session_bridge = __esm({
|
|
|
20777
20951
|
log32.error({ err, sessionId: this.session.id, adapterId: this.adapterId }, "Failed to send permission request to adapter");
|
|
20778
20952
|
}
|
|
20779
20953
|
});
|
|
20780
|
-
this.listen(this.session,
|
|
20954
|
+
this.listen(this.session, SessionEv.STATUS_CHANGE, (from, to) => {
|
|
20781
20955
|
this.deps.sessionManager.patchRecord(this.session.id, {
|
|
20782
20956
|
status: to,
|
|
20783
20957
|
lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
20784
20958
|
});
|
|
20785
|
-
this.
|
|
20786
|
-
|
|
20787
|
-
|
|
20788
|
-
|
|
20959
|
+
if (!this.session.isAssistant) {
|
|
20960
|
+
this.deps.eventBus?.emit(BusEvent.SESSION_UPDATED, {
|
|
20961
|
+
sessionId: this.session.id,
|
|
20962
|
+
status: to
|
|
20963
|
+
});
|
|
20964
|
+
}
|
|
20789
20965
|
if (to === "finished") {
|
|
20790
20966
|
queueMicrotask(() => this.disconnect());
|
|
20791
20967
|
}
|
|
20792
20968
|
});
|
|
20793
|
-
this.listen(this.session,
|
|
20969
|
+
this.listen(this.session, SessionEv.NAMED, async (name) => {
|
|
20794
20970
|
const record = this.deps.sessionManager.getSessionRecord(this.session.id);
|
|
20795
20971
|
const alreadyNamed = !!record?.name;
|
|
20796
20972
|
await this.deps.sessionManager.patchRecord(this.session.id, { name });
|
|
20797
|
-
this.
|
|
20798
|
-
|
|
20799
|
-
|
|
20800
|
-
|
|
20973
|
+
if (!this.session.isAssistant) {
|
|
20974
|
+
this.deps.eventBus?.emit(BusEvent.SESSION_UPDATED, {
|
|
20975
|
+
sessionId: this.session.id,
|
|
20976
|
+
name
|
|
20977
|
+
});
|
|
20978
|
+
}
|
|
20801
20979
|
if (!alreadyNamed) {
|
|
20802
20980
|
await this.adapter.renameSessionThread(this.session.id, name);
|
|
20803
20981
|
}
|
|
20804
20982
|
});
|
|
20805
|
-
this.listen(this.session,
|
|
20983
|
+
this.listen(this.session, SessionEv.PROMPT_COUNT_CHANGED, (count) => {
|
|
20806
20984
|
this.deps.sessionManager.patchRecord(this.session.id, { currentPromptCount: count });
|
|
20807
20985
|
});
|
|
20808
|
-
this.listen(this.session,
|
|
20986
|
+
this.listen(this.session, SessionEv.TURN_STARTED, (ctx) => {
|
|
20809
20987
|
if (ctx.sourceAdapterId !== "sse" && ctx.sourceAdapterId !== "api") {
|
|
20810
|
-
this.deps.eventBus?.emit(
|
|
20988
|
+
this.deps.eventBus?.emit(BusEvent.MESSAGE_PROCESSING, {
|
|
20811
20989
|
sessionId: this.session.id,
|
|
20812
20990
|
turnId: ctx.turnId,
|
|
20813
20991
|
sourceAdapterId: ctx.sourceAdapterId,
|
|
@@ -20816,10 +20994,10 @@ var init_session_bridge = __esm({
|
|
|
20816
20994
|
}
|
|
20817
20995
|
});
|
|
20818
20996
|
if (this.session.latestCommands !== null) {
|
|
20819
|
-
this.session.emit(
|
|
20997
|
+
this.session.emit(SessionEv.AGENT_EVENT, { type: "commands_update", commands: this.session.latestCommands });
|
|
20820
20998
|
}
|
|
20821
20999
|
if (this.session.configOptions.length > 0) {
|
|
20822
|
-
this.session.emit(
|
|
21000
|
+
this.session.emit(SessionEv.AGENT_EVENT, { type: "config_option_update", options: this.session.configOptions });
|
|
20823
21001
|
}
|
|
20824
21002
|
}
|
|
20825
21003
|
disconnect() {
|
|
@@ -20839,17 +21017,11 @@ var init_session_bridge = __esm({
|
|
|
20839
21017
|
const mw = this.deps.middlewareChain;
|
|
20840
21018
|
if (mw) {
|
|
20841
21019
|
try {
|
|
20842
|
-
const result = await mw.execute(
|
|
21020
|
+
const result = await mw.execute(Hook.AGENT_BEFORE_EVENT, { sessionId: this.session.id, event }, async (e) => e);
|
|
20843
21021
|
this.tracer?.log("core", { step: "middleware:before", sessionId: this.session.id, hook: "agent:beforeEvent", blocked: !result });
|
|
20844
21022
|
if (!result) return;
|
|
20845
21023
|
const transformedEvent = result.event;
|
|
20846
|
-
|
|
20847
|
-
mw.execute("agent:afterEvent", {
|
|
20848
|
-
sessionId: this.session.id,
|
|
20849
|
-
event: transformedEvent,
|
|
20850
|
-
outgoingMessage: outgoing ?? { type: "text", text: "" }
|
|
20851
|
-
}, async (e) => e).catch(() => {
|
|
20852
|
-
});
|
|
21024
|
+
this.handleAgentEvent(transformedEvent);
|
|
20853
21025
|
} catch {
|
|
20854
21026
|
try {
|
|
20855
21027
|
this.handleAgentEvent(event);
|
|
@@ -20982,7 +21154,7 @@ var init_session_bridge = __esm({
|
|
|
20982
21154
|
this.adapter.stripTTSBlock?.(this.session.id);
|
|
20983
21155
|
break;
|
|
20984
21156
|
}
|
|
20985
|
-
this.deps.eventBus?.emit(
|
|
21157
|
+
this.deps.eventBus?.emit(BusEvent.AGENT_EVENT, {
|
|
20986
21158
|
sessionId: this.session.id,
|
|
20987
21159
|
event
|
|
20988
21160
|
});
|
|
@@ -21001,7 +21173,7 @@ var init_session_bridge = __esm({
|
|
|
21001
21173
|
let permReq = request;
|
|
21002
21174
|
if (mw) {
|
|
21003
21175
|
const payload = { sessionId: this.session.id, request, autoResolve: void 0 };
|
|
21004
|
-
const result = await mw.execute(
|
|
21176
|
+
const result = await mw.execute(Hook.PERMISSION_BEFORE_REQUEST, payload, async (r) => r);
|
|
21005
21177
|
if (!result) return "";
|
|
21006
21178
|
permReq = result.request;
|
|
21007
21179
|
if (result.autoResolve) {
|
|
@@ -21009,21 +21181,21 @@ var init_session_bridge = __esm({
|
|
|
21009
21181
|
return result.autoResolve;
|
|
21010
21182
|
}
|
|
21011
21183
|
}
|
|
21012
|
-
this.deps.eventBus?.emit(
|
|
21184
|
+
this.deps.eventBus?.emit(BusEvent.PERMISSION_REQUEST, {
|
|
21013
21185
|
sessionId: this.session.id,
|
|
21014
21186
|
permission: permReq
|
|
21015
21187
|
});
|
|
21016
21188
|
const autoDecision = this.checkAutoApprove(permReq);
|
|
21017
21189
|
if (autoDecision) {
|
|
21018
|
-
this.session.emit(
|
|
21190
|
+
this.session.emit(SessionEv.PERMISSION_REQUEST, permReq);
|
|
21019
21191
|
this.emitAfterResolve(mw, permReq.id, autoDecision, "system", startTime);
|
|
21020
21192
|
return autoDecision;
|
|
21021
21193
|
}
|
|
21022
21194
|
const promise = this.session.permissionGate.setPending(permReq);
|
|
21023
|
-
this.session.emit(
|
|
21195
|
+
this.session.emit(SessionEv.PERMISSION_REQUEST, permReq);
|
|
21024
21196
|
await this.adapter.sendPermissionRequest(this.session.id, permReq);
|
|
21025
21197
|
const optionId = await promise;
|
|
21026
|
-
this.deps.eventBus?.emit(
|
|
21198
|
+
this.deps.eventBus?.emit(BusEvent.PERMISSION_RESOLVED, {
|
|
21027
21199
|
sessionId: this.session.id,
|
|
21028
21200
|
requestId: permReq.id,
|
|
21029
21201
|
decision: optionId,
|
|
@@ -21055,7 +21227,7 @@ var init_session_bridge = __esm({
|
|
|
21055
21227
|
/** Emit permission:afterResolve middleware hook (fire-and-forget) */
|
|
21056
21228
|
emitAfterResolve(mw, requestId, decision, userId, startTime) {
|
|
21057
21229
|
if (mw) {
|
|
21058
|
-
mw.execute(
|
|
21230
|
+
mw.execute(Hook.PERMISSION_AFTER_RESOLVE, {
|
|
21059
21231
|
sessionId: this.session.id,
|
|
21060
21232
|
requestId,
|
|
21061
21233
|
decision,
|
|
@@ -21563,6 +21735,14 @@ var init_session_store = __esm({
|
|
|
21563
21735
|
}
|
|
21564
21736
|
return void 0;
|
|
21565
21737
|
}
|
|
21738
|
+
findAssistant(channelId) {
|
|
21739
|
+
for (const record of this.records.values()) {
|
|
21740
|
+
if (record.isAssistant === true && record.channelId === channelId) {
|
|
21741
|
+
return record;
|
|
21742
|
+
}
|
|
21743
|
+
}
|
|
21744
|
+
return void 0;
|
|
21745
|
+
}
|
|
21566
21746
|
list(channelId) {
|
|
21567
21747
|
const all = [...this.records.values()];
|
|
21568
21748
|
if (channelId) return all.filter((r) => r.channelId === channelId);
|
|
@@ -21642,6 +21822,8 @@ var init_session_store = __esm({
|
|
|
21642
21822
|
for (const [id, record] of this.records) {
|
|
21643
21823
|
if (record.status === "active" || record.status === "initializing")
|
|
21644
21824
|
continue;
|
|
21825
|
+
if (record.isAssistant === true)
|
|
21826
|
+
continue;
|
|
21645
21827
|
const raw = record.lastActiveAt;
|
|
21646
21828
|
if (!raw) continue;
|
|
21647
21829
|
const lastActive = new Date(raw).getTime();
|
|
@@ -21673,6 +21855,7 @@ var init_session_factory = __esm({
|
|
|
21673
21855
|
"use strict";
|
|
21674
21856
|
init_session2();
|
|
21675
21857
|
init_log();
|
|
21858
|
+
init_events();
|
|
21676
21859
|
log35 = createChildLogger({ module: "session-factory" });
|
|
21677
21860
|
SessionFactory = class {
|
|
21678
21861
|
constructor(agentManager, sessionManager, speechServiceAccessor, eventBus, instanceRoot) {
|
|
@@ -21715,7 +21898,7 @@ var init_session_factory = __esm({
|
|
|
21715
21898
|
threadId: ""
|
|
21716
21899
|
// threadId is assigned after session creation
|
|
21717
21900
|
};
|
|
21718
|
-
const result = await this.middlewareChain.execute(
|
|
21901
|
+
const result = await this.middlewareChain.execute(Hook.SESSION_BEFORE_CREATE, payload, async (p2) => p2);
|
|
21719
21902
|
if (!result) throw new Error("Session creation blocked by middleware");
|
|
21720
21903
|
createParams = {
|
|
21721
21904
|
...params,
|
|
@@ -21724,6 +21907,7 @@ var init_session_factory = __esm({
|
|
|
21724
21907
|
channelId: result.channelId
|
|
21725
21908
|
};
|
|
21726
21909
|
}
|
|
21910
|
+
const configAllowedPaths = this.configManager?.get().workspace?.security?.allowedPaths ?? [];
|
|
21727
21911
|
let agentInstance;
|
|
21728
21912
|
try {
|
|
21729
21913
|
if (createParams.resumeAgentSessionId) {
|
|
@@ -21731,7 +21915,8 @@ var init_session_factory = __esm({
|
|
|
21731
21915
|
agentInstance = await this.agentManager.resume(
|
|
21732
21916
|
createParams.agentName,
|
|
21733
21917
|
createParams.workingDirectory,
|
|
21734
|
-
createParams.resumeAgentSessionId
|
|
21918
|
+
createParams.resumeAgentSessionId,
|
|
21919
|
+
configAllowedPaths
|
|
21735
21920
|
);
|
|
21736
21921
|
} catch (resumeErr) {
|
|
21737
21922
|
log35.warn(
|
|
@@ -21740,13 +21925,15 @@ var init_session_factory = __esm({
|
|
|
21740
21925
|
);
|
|
21741
21926
|
agentInstance = await this.agentManager.spawn(
|
|
21742
21927
|
createParams.agentName,
|
|
21743
|
-
createParams.workingDirectory
|
|
21928
|
+
createParams.workingDirectory,
|
|
21929
|
+
configAllowedPaths
|
|
21744
21930
|
);
|
|
21745
21931
|
}
|
|
21746
21932
|
} else {
|
|
21747
21933
|
agentInstance = await this.agentManager.spawn(
|
|
21748
21934
|
createParams.agentName,
|
|
21749
|
-
createParams.workingDirectory
|
|
21935
|
+
createParams.workingDirectory,
|
|
21936
|
+
configAllowedPaths
|
|
21750
21937
|
);
|
|
21751
21938
|
}
|
|
21752
21939
|
} catch (err) {
|
|
@@ -21778,7 +21965,7 @@ var init_session_factory = __esm({
|
|
|
21778
21965
|
message: guidanceLines.join("\n")
|
|
21779
21966
|
};
|
|
21780
21967
|
const failedSessionId = createParams.existingSessionId ?? `failed-${Date.now()}`;
|
|
21781
|
-
this.eventBus.emit(
|
|
21968
|
+
this.eventBus.emit(BusEvent.AGENT_EVENT, {
|
|
21782
21969
|
sessionId: failedSessionId,
|
|
21783
21970
|
event: guidance
|
|
21784
21971
|
});
|
|
@@ -21804,11 +21991,13 @@ var init_session_factory = __esm({
|
|
|
21804
21991
|
}
|
|
21805
21992
|
session.applySpawnResponse(agentInstance.initialSessionResponse, agentInstance.agentCapabilities);
|
|
21806
21993
|
this.sessionManager.registerSession(session);
|
|
21807
|
-
|
|
21808
|
-
|
|
21809
|
-
|
|
21810
|
-
|
|
21811
|
-
|
|
21994
|
+
if (!session.isAssistant) {
|
|
21995
|
+
this.eventBus.emit(BusEvent.SESSION_CREATED, {
|
|
21996
|
+
sessionId: session.id,
|
|
21997
|
+
agent: session.agentName,
|
|
21998
|
+
status: session.status
|
|
21999
|
+
});
|
|
22000
|
+
}
|
|
21812
22001
|
return session;
|
|
21813
22002
|
}
|
|
21814
22003
|
/**
|
|
@@ -21826,6 +22015,7 @@ var init_session_factory = __esm({
|
|
|
21826
22015
|
if (!this.sessionStore || !this.createFullSession) return null;
|
|
21827
22016
|
const record = this.sessionStore.get(sessionId);
|
|
21828
22017
|
if (!record) return null;
|
|
22018
|
+
if (record.isAssistant) return null;
|
|
21829
22019
|
if (record.status === "error" || record.status === "cancelled") return null;
|
|
21830
22020
|
const existing = this.resumeLocks.get(sessionId);
|
|
21831
22021
|
if (existing) return existing;
|
|
@@ -21893,6 +22083,7 @@ var init_session_factory = __esm({
|
|
|
21893
22083
|
log35.debug({ threadId, channelId }, "No session record found for thread");
|
|
21894
22084
|
return null;
|
|
21895
22085
|
}
|
|
22086
|
+
if (record.isAssistant) return null;
|
|
21896
22087
|
if (record.status === "error" || record.status === "cancelled") {
|
|
21897
22088
|
log35.warn(
|
|
21898
22089
|
{ threadId, sessionId: record.sessionId, status: record.status },
|
|
@@ -22052,9 +22243,9 @@ var init_session_factory = __esm({
|
|
|
22052
22243
|
return { session, contextResult };
|
|
22053
22244
|
}
|
|
22054
22245
|
wireSideEffects(session, deps) {
|
|
22055
|
-
session.on(
|
|
22246
|
+
session.on(SessionEv.AGENT_EVENT, (event) => {
|
|
22056
22247
|
if (event.type !== "usage") return;
|
|
22057
|
-
deps.eventBus.emit(
|
|
22248
|
+
deps.eventBus.emit(BusEvent.USAGE_RECORDED, {
|
|
22058
22249
|
sessionId: session.id,
|
|
22059
22250
|
agentName: session.agentName,
|
|
22060
22251
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -22063,7 +22254,7 @@ var init_session_factory = __esm({
|
|
|
22063
22254
|
cost: event.cost
|
|
22064
22255
|
});
|
|
22065
22256
|
});
|
|
22066
|
-
session.on(
|
|
22257
|
+
session.on(SessionEv.STATUS_CHANGE, (_from, to) => {
|
|
22067
22258
|
if ((to === "finished" || to === "cancelled") && deps.tunnelService) {
|
|
22068
22259
|
deps.tunnelService.stopBySession(session.id).then((stopped) => {
|
|
22069
22260
|
for (const entry of stopped) {
|
|
@@ -22091,6 +22282,7 @@ var init_agent_switch_handler = __esm({
|
|
|
22091
22282
|
"use strict";
|
|
22092
22283
|
init_agent_registry();
|
|
22093
22284
|
init_log();
|
|
22285
|
+
init_events();
|
|
22094
22286
|
log36 = createChildLogger({ module: "agent-switch" });
|
|
22095
22287
|
AgentSwitchHandler = class {
|
|
22096
22288
|
constructor(deps) {
|
|
@@ -22116,7 +22308,7 @@ var init_agent_switch_handler = __esm({
|
|
|
22116
22308
|
if (!agentDef) throw new Error(`Agent "${toAgent}" is not installed`);
|
|
22117
22309
|
const fromAgent = session.agentName;
|
|
22118
22310
|
const middlewareChain = this.deps.getMiddlewareChain();
|
|
22119
|
-
const result = await middlewareChain?.execute(
|
|
22311
|
+
const result = await middlewareChain?.execute(Hook.AGENT_BEFORE_SWITCH, {
|
|
22120
22312
|
sessionId,
|
|
22121
22313
|
fromAgent,
|
|
22122
22314
|
toAgent
|
|
@@ -22130,9 +22322,9 @@ var init_agent_switch_handler = __esm({
|
|
|
22130
22322
|
type: "system_message",
|
|
22131
22323
|
message: `Switching from ${fromAgent} to ${toAgent}...`
|
|
22132
22324
|
};
|
|
22133
|
-
session.emit(
|
|
22134
|
-
eventBus.emit(
|
|
22135
|
-
eventBus.emit(
|
|
22325
|
+
session.emit(SessionEv.AGENT_EVENT, startEvent);
|
|
22326
|
+
eventBus.emit(BusEvent.AGENT_EVENT, { sessionId, event: startEvent });
|
|
22327
|
+
eventBus.emit(BusEvent.SESSION_AGENT_SWITCH, {
|
|
22136
22328
|
sessionId,
|
|
22137
22329
|
fromAgent,
|
|
22138
22330
|
toAgent,
|
|
@@ -22156,11 +22348,12 @@ var init_agent_switch_handler = __esm({
|
|
|
22156
22348
|
}
|
|
22157
22349
|
const fromAgentSessionId = session.agentSessionId;
|
|
22158
22350
|
const fileService = this.deps.getService("file-service");
|
|
22351
|
+
const configAllowedPaths = configManager.get().workspace?.security?.allowedPaths ?? [];
|
|
22159
22352
|
try {
|
|
22160
22353
|
await session.switchAgent(toAgent, async () => {
|
|
22161
22354
|
if (canResume) {
|
|
22162
22355
|
try {
|
|
22163
|
-
const instance2 = await agentManager.resume(toAgent, session.workingDirectory, lastEntry.agentSessionId);
|
|
22356
|
+
const instance2 = await agentManager.resume(toAgent, session.workingDirectory, lastEntry.agentSessionId, configAllowedPaths);
|
|
22164
22357
|
if (fileService) instance2.addAllowedPath(fileService.baseDir);
|
|
22165
22358
|
resumed = true;
|
|
22166
22359
|
return instance2;
|
|
@@ -22168,7 +22361,7 @@ var init_agent_switch_handler = __esm({
|
|
|
22168
22361
|
log36.warn({ sessionId, toAgent }, "Resume failed, falling back to new agent with context injection");
|
|
22169
22362
|
}
|
|
22170
22363
|
}
|
|
22171
|
-
const instance = await agentManager.spawn(toAgent, session.workingDirectory);
|
|
22364
|
+
const instance = await agentManager.spawn(toAgent, session.workingDirectory, configAllowedPaths);
|
|
22172
22365
|
if (fileService) instance.addAllowedPath(fileService.baseDir);
|
|
22173
22366
|
try {
|
|
22174
22367
|
const contextService = this.deps.getService("context");
|
|
@@ -22192,9 +22385,9 @@ var init_agent_switch_handler = __esm({
|
|
|
22192
22385
|
type: "system_message",
|
|
22193
22386
|
message: resumed ? `Switched to ${toAgent} (resumed previous session).` : `Switched to ${toAgent} (new session).`
|
|
22194
22387
|
};
|
|
22195
|
-
session.emit(
|
|
22196
|
-
eventBus.emit(
|
|
22197
|
-
eventBus.emit(
|
|
22388
|
+
session.emit(SessionEv.AGENT_EVENT, successEvent);
|
|
22389
|
+
eventBus.emit(BusEvent.AGENT_EVENT, { sessionId, event: successEvent });
|
|
22390
|
+
eventBus.emit(BusEvent.SESSION_AGENT_SWITCH, {
|
|
22198
22391
|
sessionId,
|
|
22199
22392
|
fromAgent,
|
|
22200
22393
|
toAgent,
|
|
@@ -22207,9 +22400,9 @@ var init_agent_switch_handler = __esm({
|
|
|
22207
22400
|
type: "system_message",
|
|
22208
22401
|
message: `Failed to switch to ${toAgent}: ${errorMessage}`
|
|
22209
22402
|
};
|
|
22210
|
-
session.emit(
|
|
22211
|
-
eventBus.emit(
|
|
22212
|
-
eventBus.emit(
|
|
22403
|
+
session.emit(SessionEv.AGENT_EVENT, failedEvent);
|
|
22404
|
+
eventBus.emit(BusEvent.AGENT_EVENT, { sessionId, event: failedEvent });
|
|
22405
|
+
eventBus.emit(BusEvent.SESSION_AGENT_SWITCH, {
|
|
22213
22406
|
sessionId,
|
|
22214
22407
|
fromAgent,
|
|
22215
22408
|
toAgent,
|
|
@@ -22258,7 +22451,7 @@ var init_agent_switch_handler = __esm({
|
|
|
22258
22451
|
currentPromptCount: 0,
|
|
22259
22452
|
agentSwitchHistory: session.agentSwitchHistory
|
|
22260
22453
|
});
|
|
22261
|
-
middlewareChain?.execute(
|
|
22454
|
+
middlewareChain?.execute(Hook.AGENT_AFTER_SWITCH, {
|
|
22262
22455
|
sessionId,
|
|
22263
22456
|
fromAgent,
|
|
22264
22457
|
toAgent,
|
|
@@ -23209,6 +23402,7 @@ var init_lifecycle_manager = __esm({
|
|
|
23209
23402
|
init_middleware_chain();
|
|
23210
23403
|
init_error_tracker();
|
|
23211
23404
|
init_plugin_context();
|
|
23405
|
+
init_events();
|
|
23212
23406
|
SETUP_TIMEOUT_MS = 3e4;
|
|
23213
23407
|
TEARDOWN_TIMEOUT_MS = 1e4;
|
|
23214
23408
|
LifecycleManager = class {
|
|
@@ -23315,7 +23509,7 @@ var init_lifecycle_manager = __esm({
|
|
|
23315
23509
|
}
|
|
23316
23510
|
const registryEntry = this.pluginRegistry?.get(plugin2.name);
|
|
23317
23511
|
if (registryEntry && registryEntry.enabled === false) {
|
|
23318
|
-
this.eventBus?.emit(
|
|
23512
|
+
this.eventBus?.emit(BusEvent.PLUGIN_DISABLED, { name: plugin2.name });
|
|
23319
23513
|
continue;
|
|
23320
23514
|
}
|
|
23321
23515
|
if (registryEntry && plugin2.migrate && registryEntry.version !== plugin2.version && this.settingsManager) {
|
|
@@ -23358,7 +23552,7 @@ var init_lifecycle_manager = __esm({
|
|
|
23358
23552
|
if (!validation.valid) {
|
|
23359
23553
|
this._failed.add(plugin2.name);
|
|
23360
23554
|
this.getPluginLogger(plugin2.name).error(`Settings validation failed: ${validation.errors?.join("; ")}`);
|
|
23361
|
-
this.eventBus?.emit(
|
|
23555
|
+
this.eventBus?.emit(BusEvent.PLUGIN_FAILED, { name: plugin2.name, error: `Settings validation failed: ${validation.errors?.join("; ")}` });
|
|
23362
23556
|
continue;
|
|
23363
23557
|
}
|
|
23364
23558
|
}
|
|
@@ -23381,13 +23575,13 @@ var init_lifecycle_manager = __esm({
|
|
|
23381
23575
|
await withTimeout(plugin2.setup(ctx), SETUP_TIMEOUT_MS, `${plugin2.name}.setup()`);
|
|
23382
23576
|
this.contexts.set(plugin2.name, ctx);
|
|
23383
23577
|
this._loaded.add(plugin2.name);
|
|
23384
|
-
this.eventBus?.emit(
|
|
23578
|
+
this.eventBus?.emit(BusEvent.PLUGIN_LOADED, { name: plugin2.name, version: plugin2.version });
|
|
23385
23579
|
} catch (err) {
|
|
23386
23580
|
this._failed.add(plugin2.name);
|
|
23387
23581
|
ctx.cleanup();
|
|
23388
23582
|
console.error(`[lifecycle] Plugin ${plugin2.name} setup() FAILED:`, err);
|
|
23389
23583
|
this.getPluginLogger(plugin2.name).error(`setup() failed: ${err}`);
|
|
23390
|
-
this.eventBus?.emit(
|
|
23584
|
+
this.eventBus?.emit(BusEvent.PLUGIN_FAILED, { name: plugin2.name, error: String(err) });
|
|
23391
23585
|
}
|
|
23392
23586
|
}
|
|
23393
23587
|
}
|
|
@@ -23408,7 +23602,7 @@ var init_lifecycle_manager = __esm({
|
|
|
23408
23602
|
this._loaded.delete(name);
|
|
23409
23603
|
this._failed.delete(name);
|
|
23410
23604
|
this.loadOrder = this.loadOrder.filter((p2) => p2.name !== name);
|
|
23411
|
-
this.eventBus?.emit(
|
|
23605
|
+
this.eventBus?.emit(BusEvent.PLUGIN_UNLOADED, { name });
|
|
23412
23606
|
}
|
|
23413
23607
|
async shutdown() {
|
|
23414
23608
|
const reversed = [...this.loadOrder].reverse();
|
|
@@ -23425,7 +23619,7 @@ var init_lifecycle_manager = __esm({
|
|
|
23425
23619
|
ctx.cleanup();
|
|
23426
23620
|
this.contexts.delete(plugin2.name);
|
|
23427
23621
|
}
|
|
23428
|
-
this.eventBus?.emit(
|
|
23622
|
+
this.eventBus?.emit(BusEvent.PLUGIN_UNLOADED, { name: plugin2.name });
|
|
23429
23623
|
}
|
|
23430
23624
|
this._loaded.clear();
|
|
23431
23625
|
this.loadOrder = [];
|
|
@@ -23596,21 +23790,25 @@ var init_assistant_manager = __esm({
|
|
|
23596
23790
|
this.registry = registry;
|
|
23597
23791
|
}
|
|
23598
23792
|
sessions = /* @__PURE__ */ new Map();
|
|
23599
|
-
respawning = /* @__PURE__ */ new Set();
|
|
23600
23793
|
pendingSystemPrompts = /* @__PURE__ */ new Map();
|
|
23601
|
-
async
|
|
23794
|
+
async getOrSpawn(channelId, threadId) {
|
|
23795
|
+
const existing = this.core.sessionStore?.findAssistant(channelId);
|
|
23602
23796
|
const session = await this.core.createSession({
|
|
23603
23797
|
channelId,
|
|
23604
23798
|
agentName: this.core.configManager.get().defaultAgent,
|
|
23605
23799
|
workingDirectory: this.core.configManager.resolveWorkspace(),
|
|
23606
23800
|
initialName: "Assistant",
|
|
23607
23801
|
isAssistant: true,
|
|
23608
|
-
threadId
|
|
23802
|
+
threadId,
|
|
23803
|
+
existingSessionId: existing?.sessionId
|
|
23609
23804
|
});
|
|
23610
23805
|
this.sessions.set(channelId, session);
|
|
23611
23806
|
const systemPrompt = this.registry.buildSystemPrompt(channelId);
|
|
23612
23807
|
this.pendingSystemPrompts.set(channelId, systemPrompt);
|
|
23613
|
-
log41.info(
|
|
23808
|
+
log41.info(
|
|
23809
|
+
{ sessionId: session.id, channelId, reused: !!existing },
|
|
23810
|
+
existing ? "Assistant session reused (system prompt deferred)" : "Assistant spawned (system prompt deferred)"
|
|
23811
|
+
);
|
|
23614
23812
|
return session;
|
|
23615
23813
|
}
|
|
23616
23814
|
get(channelId) {
|
|
@@ -23631,19 +23829,6 @@ var init_assistant_manager = __esm({
|
|
|
23631
23829
|
}
|
|
23632
23830
|
return false;
|
|
23633
23831
|
}
|
|
23634
|
-
async respawn(channelId, threadId) {
|
|
23635
|
-
if (this.respawning.has(channelId)) {
|
|
23636
|
-
return this.sessions.get(channelId);
|
|
23637
|
-
}
|
|
23638
|
-
this.respawning.add(channelId);
|
|
23639
|
-
try {
|
|
23640
|
-
const old = this.sessions.get(channelId);
|
|
23641
|
-
if (old) await old.destroy();
|
|
23642
|
-
return await this.spawn(channelId, threadId);
|
|
23643
|
-
} finally {
|
|
23644
|
-
this.respawning.delete(channelId);
|
|
23645
|
-
}
|
|
23646
|
-
}
|
|
23647
23832
|
};
|
|
23648
23833
|
}
|
|
23649
23834
|
});
|
|
@@ -23759,6 +23944,39 @@ var init_system = __esm({
|
|
|
23759
23944
|
}
|
|
23760
23945
|
});
|
|
23761
23946
|
|
|
23947
|
+
// src/core/assistant/sections/remote.ts
|
|
23948
|
+
function createRemoteSection() {
|
|
23949
|
+
return {
|
|
23950
|
+
id: "core:remote",
|
|
23951
|
+
title: "Remote Access",
|
|
23952
|
+
priority: 35,
|
|
23953
|
+
buildContext: () => {
|
|
23954
|
+
return `Generate a one-time remote access link so the user can connect to this OpenACP instance from the app or a browser.
|
|
23955
|
+
|
|
23956
|
+
The link contains a short-lived code (expires in 30 minutes, single-use) that exchanges for a long-lived token.
|
|
23957
|
+
|
|
23958
|
+
Roles:
|
|
23959
|
+
admin \u2014 full control (default)
|
|
23960
|
+
viewer \u2014 read-only access
|
|
23961
|
+
|
|
23962
|
+
The command automatically includes the tunnel URL if a tunnel is active. Without a tunnel, the local link only works on the same machine.
|
|
23963
|
+
|
|
23964
|
+
Always show both the link and QR code when available so the user can choose how to open it.`;
|
|
23965
|
+
},
|
|
23966
|
+
commands: [
|
|
23967
|
+
{ command: "openacp remote", description: "Generate remote access link (admin role, 24h expiry)" },
|
|
23968
|
+
{ command: "openacp remote --role viewer", description: "Generate read-only access link" },
|
|
23969
|
+
{ command: "openacp remote --expire 48h", description: "Generate link with custom expiry" },
|
|
23970
|
+
{ command: "openacp remote --no-qr", description: "Skip QR code output" }
|
|
23971
|
+
]
|
|
23972
|
+
};
|
|
23973
|
+
}
|
|
23974
|
+
var init_remote = __esm({
|
|
23975
|
+
"src/core/assistant/sections/remote.ts"() {
|
|
23976
|
+
"use strict";
|
|
23977
|
+
}
|
|
23978
|
+
});
|
|
23979
|
+
|
|
23762
23980
|
// src/core/assistant/index.ts
|
|
23763
23981
|
var init_assistant2 = __esm({
|
|
23764
23982
|
"src/core/assistant/index.ts"() {
|
|
@@ -23770,6 +23988,7 @@ var init_assistant2 = __esm({
|
|
|
23770
23988
|
init_agents4();
|
|
23771
23989
|
init_config5();
|
|
23772
23990
|
init_system();
|
|
23991
|
+
init_remote();
|
|
23773
23992
|
}
|
|
23774
23993
|
});
|
|
23775
23994
|
|
|
@@ -23880,6 +24099,7 @@ var init_core = __esm({
|
|
|
23880
24099
|
init_middleware_chain();
|
|
23881
24100
|
init_error_tracker();
|
|
23882
24101
|
init_log();
|
|
24102
|
+
init_events();
|
|
23883
24103
|
log42 = createChildLogger({ module: "core" });
|
|
23884
24104
|
OpenACPCore = class {
|
|
23885
24105
|
configManager;
|
|
@@ -24033,6 +24253,7 @@ var init_core = __esm({
|
|
|
24033
24253
|
this.assistantRegistry.register(createAgentsSection(this));
|
|
24034
24254
|
this.assistantRegistry.register(createConfigSection(this));
|
|
24035
24255
|
this.assistantRegistry.register(createSystemSection());
|
|
24256
|
+
this.assistantRegistry.register(createRemoteSection());
|
|
24036
24257
|
this.assistantManager = new AssistantManager(this, this.assistantRegistry);
|
|
24037
24258
|
this.lifecycleManager.serviceRegistry.register("menu-registry", this.menuRegistry, "core");
|
|
24038
24259
|
this.lifecycleManager.serviceRegistry.register("assistant-registry", this.assistantRegistry, "core");
|
|
@@ -24114,7 +24335,7 @@ var init_core = __esm({
|
|
|
24114
24335
|
);
|
|
24115
24336
|
if (this.lifecycleManager?.middlewareChain) {
|
|
24116
24337
|
const result = await this.lifecycleManager.middlewareChain.execute(
|
|
24117
|
-
|
|
24338
|
+
Hook.MESSAGE_INCOMING,
|
|
24118
24339
|
message,
|
|
24119
24340
|
async (msg) => msg
|
|
24120
24341
|
);
|
|
@@ -24166,9 +24387,10 @@ ${text6}`;
|
|
|
24166
24387
|
}
|
|
24167
24388
|
}
|
|
24168
24389
|
const sourceAdapterId = message.routing?.sourceAdapterId ?? message.channelId;
|
|
24390
|
+
const routing = sourceAdapterId !== message.routing?.sourceAdapterId ? { ...message.routing, sourceAdapterId } : message.routing;
|
|
24169
24391
|
if (sourceAdapterId && sourceAdapterId !== "sse" && sourceAdapterId !== "api") {
|
|
24170
24392
|
const turnId = nanoid5(8);
|
|
24171
|
-
this.eventBus.emit(
|
|
24393
|
+
this.eventBus.emit(BusEvent.MESSAGE_QUEUED, {
|
|
24172
24394
|
sessionId: session.id,
|
|
24173
24395
|
turnId,
|
|
24174
24396
|
text: text6,
|
|
@@ -24177,9 +24399,9 @@ ${text6}`;
|
|
|
24177
24399
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24178
24400
|
queueDepth: session.queueDepth
|
|
24179
24401
|
});
|
|
24180
|
-
await session.enqueuePrompt(text6, message.attachments,
|
|
24402
|
+
await session.enqueuePrompt(text6, message.attachments, routing, turnId);
|
|
24181
24403
|
} else {
|
|
24182
|
-
await session.enqueuePrompt(text6, message.attachments,
|
|
24404
|
+
await session.enqueuePrompt(text6, message.attachments, routing);
|
|
24183
24405
|
}
|
|
24184
24406
|
}
|
|
24185
24407
|
// --- Unified Session Creation Pipeline ---
|
|
@@ -24223,6 +24445,7 @@ ${text6}`;
|
|
|
24223
24445
|
createdAt: session.createdAt.toISOString(),
|
|
24224
24446
|
lastActiveAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24225
24447
|
name: session.name,
|
|
24448
|
+
isAssistant: params.isAssistant,
|
|
24226
24449
|
platform: platform2,
|
|
24227
24450
|
platforms,
|
|
24228
24451
|
firstAgent: session.firstAgent,
|
|
@@ -24238,7 +24461,7 @@ ${text6}`;
|
|
|
24238
24461
|
log42.warn({ err, sessionId: session.id }, "Failed to flush pending skill commands");
|
|
24239
24462
|
});
|
|
24240
24463
|
if (params.createThread && session.threadId) {
|
|
24241
|
-
this.eventBus.emit(
|
|
24464
|
+
this.eventBus.emit(BusEvent.SESSION_THREAD_READY, {
|
|
24242
24465
|
sessionId: session.id,
|
|
24243
24466
|
channelId: params.channelId,
|
|
24244
24467
|
threadId: session.threadId
|
|
@@ -24262,6 +24485,36 @@ ${text6}`;
|
|
|
24262
24485
|
);
|
|
24263
24486
|
return allowOption.id;
|
|
24264
24487
|
};
|
|
24488
|
+
session.on(SessionEv.NAMED, async (name) => {
|
|
24489
|
+
await this.sessionManager.patchRecord(session.id, { name });
|
|
24490
|
+
this.eventBus.emit(BusEvent.SESSION_UPDATED, { sessionId: session.id, name });
|
|
24491
|
+
});
|
|
24492
|
+
const mw = () => this.lifecycleManager?.middlewareChain;
|
|
24493
|
+
session.on(SessionEv.AGENT_EVENT, async (event) => {
|
|
24494
|
+
let processedEvent = event;
|
|
24495
|
+
const chain = mw();
|
|
24496
|
+
if (chain) {
|
|
24497
|
+
const result = await chain.execute(Hook.AGENT_BEFORE_EVENT, { sessionId: session.id, event }, async (e) => e);
|
|
24498
|
+
if (!result) return;
|
|
24499
|
+
processedEvent = result.event;
|
|
24500
|
+
}
|
|
24501
|
+
if (processedEvent.type === "session_end") {
|
|
24502
|
+
session.finish(processedEvent.reason);
|
|
24503
|
+
} else if (processedEvent.type === "error") {
|
|
24504
|
+
session.fail(processedEvent.message);
|
|
24505
|
+
}
|
|
24506
|
+
this.eventBus.emit(BusEvent.AGENT_EVENT, { sessionId: session.id, event: processedEvent });
|
|
24507
|
+
});
|
|
24508
|
+
session.on(SessionEv.STATUS_CHANGE, (_from, to) => {
|
|
24509
|
+
this.sessionManager.patchRecord(session.id, {
|
|
24510
|
+
status: to,
|
|
24511
|
+
lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
24512
|
+
});
|
|
24513
|
+
this.eventBus.emit(BusEvent.SESSION_UPDATED, { sessionId: session.id, status: to });
|
|
24514
|
+
});
|
|
24515
|
+
session.on(SessionEv.PROMPT_COUNT_CHANGED, (count) => {
|
|
24516
|
+
this.sessionManager.patchRecord(session.id, { currentPromptCount: count });
|
|
24517
|
+
});
|
|
24265
24518
|
}
|
|
24266
24519
|
this.sessionFactory.wireSideEffects(session, {
|
|
24267
24520
|
eventBus: this.eventBus,
|
|
@@ -24718,18 +24971,6 @@ Prompts: ${session.promptCount}` };
|
|
|
24718
24971
|
return { type: "list", title: "\u{1F4CB} Sessions", items };
|
|
24719
24972
|
}
|
|
24720
24973
|
});
|
|
24721
|
-
registry.register({
|
|
24722
|
-
name: "clear",
|
|
24723
|
-
description: "Clear session history",
|
|
24724
|
-
category: "system",
|
|
24725
|
-
handler: async (args2) => {
|
|
24726
|
-
if (!core.assistantManager) return { type: "error", message: "Assistant not available" };
|
|
24727
|
-
const assistant = core.assistantManager.get(args2.channelId);
|
|
24728
|
-
if (!assistant) return { type: "error", message: "No assistant session for this channel." };
|
|
24729
|
-
await core.assistantManager.respawn(args2.channelId, assistant.threadId);
|
|
24730
|
-
return { type: "text", text: "\u2705 Assistant history cleared." };
|
|
24731
|
-
}
|
|
24732
|
-
});
|
|
24733
24974
|
registry.register({
|
|
24734
24975
|
name: "newchat",
|
|
24735
24976
|
description: "New chat, same agent & workspace",
|
|
@@ -25256,7 +25497,7 @@ function registerCategoryCommand(registry, core, category, commandName) {
|
|
|
25256
25497
|
}
|
|
25257
25498
|
try {
|
|
25258
25499
|
await session.setConfigOption(configOption.id, { type: "select", value: raw });
|
|
25259
|
-
core.eventBus.emit(
|
|
25500
|
+
core.eventBus.emit(BusEvent.SESSION_CONFIG_CHANGED, { sessionId: session.id });
|
|
25260
25501
|
return { type: "text", text: labels.successMsg(match.name, configOption.name) };
|
|
25261
25502
|
} catch (err) {
|
|
25262
25503
|
log43.error({ err, commandName, configId: configOption.id }, "setConfigOption failed");
|
|
@@ -25318,7 +25559,7 @@ function registerDangerousCommand(registry, core) {
|
|
|
25318
25559
|
try {
|
|
25319
25560
|
const targetValue = wantOn ? bypassValue : nonBypassDefault;
|
|
25320
25561
|
await session.setConfigOption(modeConfig.id, { type: "select", value: targetValue });
|
|
25321
|
-
core.eventBus.emit(
|
|
25562
|
+
core.eventBus.emit(BusEvent.SESSION_CONFIG_CHANGED, { sessionId: session.id });
|
|
25322
25563
|
return {
|
|
25323
25564
|
type: "text",
|
|
25324
25565
|
text: wantOn ? "\u2620\uFE0F **Bypass Permissions enabled** \u2014 all permission requests will be auto-approved. The agent can run any action without asking." : "\u{1F510} **Bypass Permissions disabled** \u2014 you will be asked to approve risky actions."
|
|
@@ -25333,7 +25574,7 @@ function registerDangerousCommand(registry, core) {
|
|
|
25333
25574
|
await core.sessionManager.patchRecord(session.id, {
|
|
25334
25575
|
clientOverrides: { ...session.clientOverrides }
|
|
25335
25576
|
});
|
|
25336
|
-
core.eventBus.emit(
|
|
25577
|
+
core.eventBus.emit(BusEvent.SESSION_CONFIG_CHANGED, { sessionId: session.id });
|
|
25337
25578
|
return {
|
|
25338
25579
|
type: "text",
|
|
25339
25580
|
text: wantOn ? "\u2620\uFE0F **Bypass Permissions enabled** (client-side) \u2014 all permission requests will be auto-approved.\n\n_Note: This agent doesn't natively support bypass mode, so OpenACP will auto-approve on your behalf._" : "\u{1F510} **Bypass Permissions disabled** \u2014 you will be asked to approve risky actions."
|
|
@@ -25353,6 +25594,7 @@ var init_config6 = __esm({
|
|
|
25353
25594
|
"src/core/commands/config.ts"() {
|
|
25354
25595
|
"use strict";
|
|
25355
25596
|
init_log();
|
|
25597
|
+
init_events();
|
|
25356
25598
|
init_bypass_detection();
|
|
25357
25599
|
init_bypass_detection();
|
|
25358
25600
|
log43 = createChildLogger({ module: "commands/config" });
|
|
@@ -26632,7 +26874,7 @@ async function runSetup(configManager, opts) {
|
|
|
26632
26874
|
const config = {
|
|
26633
26875
|
instanceName,
|
|
26634
26876
|
defaultAgent,
|
|
26635
|
-
workspace: { ...workspace, security: { allowedPaths: [], envWhitelist: [] } },
|
|
26877
|
+
workspace: { ...workspace, allowExternalWorkspaces: true, security: { allowedPaths: [], envWhitelist: [] } },
|
|
26636
26878
|
logging: {
|
|
26637
26879
|
level: "info",
|
|
26638
26880
|
logDir: path56.join(instanceRoot, "logs"),
|
|
@@ -27081,7 +27323,7 @@ async function startServer(opts) {
|
|
|
27081
27323
|
serviceRegistry.register("field-registry", fieldRegistry, "core");
|
|
27082
27324
|
registerSystemCommands(commandRegistry, core);
|
|
27083
27325
|
try {
|
|
27084
|
-
core.eventBus.emit(
|
|
27326
|
+
core.eventBus.emit(BusEvent.KERNEL_BOOTED);
|
|
27085
27327
|
core.lifecycleManager.settingsManager = settingsManager;
|
|
27086
27328
|
core.lifecycleManager.pluginRegistry = pluginRegistry;
|
|
27087
27329
|
await core.lifecycleManager.boot(corePlugins);
|
|
@@ -27194,8 +27436,8 @@ async function startServer(opts) {
|
|
|
27194
27436
|
if (tunnelSvc) {
|
|
27195
27437
|
core.tunnelService = tunnelSvc;
|
|
27196
27438
|
}
|
|
27197
|
-
core.eventBus.emit(
|
|
27198
|
-
core.eventBus.emit(
|
|
27439
|
+
core.eventBus.emit(BusEvent.SYSTEM_COMMANDS_READY, { commands: commandRegistry.getAll() });
|
|
27440
|
+
core.eventBus.emit(BusEvent.SYSTEM_READY);
|
|
27199
27441
|
} catch (err) {
|
|
27200
27442
|
if (spinner4) {
|
|
27201
27443
|
spinner4.fail("Plugin boot failed");
|
|
@@ -27431,6 +27673,7 @@ var init_main = __esm({
|
|
|
27431
27673
|
init_commands4();
|
|
27432
27674
|
init_instance_registry();
|
|
27433
27675
|
init_plugin_field_registry();
|
|
27676
|
+
init_events();
|
|
27434
27677
|
RESTART_EXIT_CODE = 75;
|
|
27435
27678
|
shuttingDown = false;
|
|
27436
27679
|
isDirectExecution = process.argv[1]?.endsWith("main.js");
|
|
@@ -28636,6 +28879,14 @@ Connect messaging platforms (Telegram, Discord) to 28+ AI coding agents via ACP
|
|
|
28636
28879
|
openacp integrate <agent> --uninstall
|
|
28637
28880
|
openacp adopt <agent> <id> Adopt an external session \x1B[2m[--json]\x1B[0m
|
|
28638
28881
|
|
|
28882
|
+
\x1B[1mRemote Access:\x1B[0m
|
|
28883
|
+
openacp remote Generate one-time remote access link \x1B[2m[--json]\x1B[0m
|
|
28884
|
+
openacp remote --role admin Specify role: admin (default) or viewer
|
|
28885
|
+
openacp remote --expire 48h Set expiry duration (default: 24h)
|
|
28886
|
+
openacp remote --no-tunnel Local link only (skip tunnel URL)
|
|
28887
|
+
openacp remote --no-qr Skip QR code output
|
|
28888
|
+
openacp remote --name <label> Custom token name
|
|
28889
|
+
|
|
28639
28890
|
\x1B[1mTunnels:\x1B[0m
|
|
28640
28891
|
openacp tunnel add <port> [--label name] Create tunnel to local port \x1B[2m[--json]\x1B[0m
|
|
28641
28892
|
openacp tunnel list List active tunnels \x1B[2m[--json]\x1B[0m
|
|
@@ -29177,6 +29428,15 @@ async function uninstallPlugin(name, purge, instanceRoot, json = false) {
|
|
|
29177
29428
|
init_api_client();
|
|
29178
29429
|
init_helpers();
|
|
29179
29430
|
init_output();
|
|
29431
|
+
function extractApiError(data, fallback = "API request failed") {
|
|
29432
|
+
const err = data.error;
|
|
29433
|
+
if (!err) return fallback;
|
|
29434
|
+
if (typeof err === "string") return err;
|
|
29435
|
+
if (typeof err === "object" && err !== null && "message" in err) {
|
|
29436
|
+
return String(err.message);
|
|
29437
|
+
}
|
|
29438
|
+
return fallback;
|
|
29439
|
+
}
|
|
29180
29440
|
function printApiHelp() {
|
|
29181
29441
|
console.log(`
|
|
29182
29442
|
\x1B[1mopenacp api\x1B[0m \u2014 Interact with the running OpenACP daemon
|
|
@@ -29470,8 +29730,8 @@ Shows the version of the currently running daemon process.
|
|
|
29470
29730
|
});
|
|
29471
29731
|
const data = await res.json();
|
|
29472
29732
|
if (!res.ok) {
|
|
29473
|
-
if (json) jsonError(ErrorCodes.API_ERROR,
|
|
29474
|
-
console.error(`Error: ${data
|
|
29733
|
+
if (json) jsonError(ErrorCodes.API_ERROR, extractApiError(data));
|
|
29734
|
+
console.error(`Error: ${extractApiError(data)}`);
|
|
29475
29735
|
process.exit(1);
|
|
29476
29736
|
}
|
|
29477
29737
|
if (json) jsonSuccess(data);
|
|
@@ -29494,8 +29754,8 @@ Shows the version of the currently running daemon process.
|
|
|
29494
29754
|
});
|
|
29495
29755
|
const data = await res.json();
|
|
29496
29756
|
if (!res.ok) {
|
|
29497
|
-
if (json) jsonError(ErrorCodes.API_ERROR,
|
|
29498
|
-
console.error(`Error: ${data
|
|
29757
|
+
if (json) jsonError(ErrorCodes.API_ERROR, extractApiError(data));
|
|
29758
|
+
console.error(`Error: ${extractApiError(data)}`);
|
|
29499
29759
|
process.exit(1);
|
|
29500
29760
|
}
|
|
29501
29761
|
if (json) jsonSuccess({ cancelled: true, sessionId });
|
|
@@ -29559,8 +29819,8 @@ Shows the version of the currently running daemon process.
|
|
|
29559
29819
|
process.exit(1);
|
|
29560
29820
|
}
|
|
29561
29821
|
if (!res.ok) {
|
|
29562
|
-
if (json) jsonError(ErrorCodes.API_ERROR,
|
|
29563
|
-
console.error(`Error: ${data
|
|
29822
|
+
if (json) jsonError(ErrorCodes.API_ERROR, extractApiError(data));
|
|
29823
|
+
console.error(`Error: ${extractApiError(data)}`);
|
|
29564
29824
|
process.exit(1);
|
|
29565
29825
|
}
|
|
29566
29826
|
if (json) jsonSuccess(data);
|
|
@@ -29606,8 +29866,8 @@ Shows the version of the currently running daemon process.
|
|
|
29606
29866
|
});
|
|
29607
29867
|
const data = await res.json();
|
|
29608
29868
|
if (!res.ok) {
|
|
29609
|
-
if (json) jsonError(ErrorCodes.API_ERROR,
|
|
29610
|
-
console.error(`Error: ${data
|
|
29869
|
+
if (json) jsonError(ErrorCodes.API_ERROR, extractApiError(data));
|
|
29870
|
+
console.error(`Error: ${extractApiError(data)}`);
|
|
29611
29871
|
process.exit(1);
|
|
29612
29872
|
}
|
|
29613
29873
|
if (json) jsonSuccess(data);
|
|
@@ -29622,8 +29882,8 @@ Shows the version of the currently running daemon process.
|
|
|
29622
29882
|
const res = await call(`/api/sessions/${encodeURIComponent(sessionId)}`);
|
|
29623
29883
|
const data = await res.json();
|
|
29624
29884
|
if (!res.ok) {
|
|
29625
|
-
if (json) jsonError(ErrorCodes.API_ERROR,
|
|
29626
|
-
console.error(`Error: ${data
|
|
29885
|
+
if (json) jsonError(ErrorCodes.API_ERROR, extractApiError(data));
|
|
29886
|
+
console.error(`Error: ${extractApiError(data)}`);
|
|
29627
29887
|
process.exit(1);
|
|
29628
29888
|
}
|
|
29629
29889
|
if (json) jsonSuccess(data);
|
|
@@ -29660,8 +29920,8 @@ Shows the version of the currently running daemon process.
|
|
|
29660
29920
|
});
|
|
29661
29921
|
const data = await res.json();
|
|
29662
29922
|
if (!res.ok) {
|
|
29663
|
-
if (json) jsonError(ErrorCodes.API_ERROR,
|
|
29664
|
-
console.error(`Error: ${data
|
|
29923
|
+
if (json) jsonError(ErrorCodes.API_ERROR, extractApiError(data));
|
|
29924
|
+
console.error(`Error: ${extractApiError(data)}`);
|
|
29665
29925
|
process.exit(1);
|
|
29666
29926
|
}
|
|
29667
29927
|
if (json) jsonSuccess(data);
|
|
@@ -29671,8 +29931,8 @@ Shows the version of the currently running daemon process.
|
|
|
29671
29931
|
const res = await call("/api/health");
|
|
29672
29932
|
const data = await res.json();
|
|
29673
29933
|
if (!res.ok) {
|
|
29674
|
-
if (json) jsonError(ErrorCodes.API_ERROR,
|
|
29675
|
-
console.error(`Error: ${data
|
|
29934
|
+
if (json) jsonError(ErrorCodes.API_ERROR, extractApiError(data));
|
|
29935
|
+
console.error(`Error: ${extractApiError(data)}`);
|
|
29676
29936
|
process.exit(1);
|
|
29677
29937
|
}
|
|
29678
29938
|
if (json) jsonSuccess(data);
|
|
@@ -29697,8 +29957,8 @@ Shows the version of the currently running daemon process.
|
|
|
29697
29957
|
const res = await call("/api/restart", { method: "POST" });
|
|
29698
29958
|
const data = await res.json();
|
|
29699
29959
|
if (!res.ok) {
|
|
29700
|
-
if (json) jsonError(ErrorCodes.API_ERROR,
|
|
29701
|
-
console.error(`Error: ${data
|
|
29960
|
+
if (json) jsonError(ErrorCodes.API_ERROR, extractApiError(data));
|
|
29961
|
+
console.error(`Error: ${extractApiError(data)}`);
|
|
29702
29962
|
process.exit(1);
|
|
29703
29963
|
}
|
|
29704
29964
|
if (json) jsonSuccess({ restarted: true });
|
|
@@ -29710,8 +29970,8 @@ Shows the version of the currently running daemon process.
|
|
|
29710
29970
|
const res = await call("/api/config");
|
|
29711
29971
|
const data = await res.json();
|
|
29712
29972
|
if (!res.ok) {
|
|
29713
|
-
if (json) jsonError(ErrorCodes.API_ERROR,
|
|
29714
|
-
console.error(`Error: ${data
|
|
29973
|
+
if (json) jsonError(ErrorCodes.API_ERROR, extractApiError(data));
|
|
29974
|
+
console.error(`Error: ${extractApiError(data)}`);
|
|
29715
29975
|
process.exit(1);
|
|
29716
29976
|
}
|
|
29717
29977
|
if (json) jsonSuccess(data);
|
|
@@ -29736,8 +29996,8 @@ Shows the version of the currently running daemon process.
|
|
|
29736
29996
|
});
|
|
29737
29997
|
const data = await res.json();
|
|
29738
29998
|
if (!res.ok) {
|
|
29739
|
-
if (json) jsonError(ErrorCodes.API_ERROR,
|
|
29740
|
-
console.error(`Error: ${data
|
|
29999
|
+
if (json) jsonError(ErrorCodes.API_ERROR, extractApiError(data));
|
|
30000
|
+
console.error(`Error: ${extractApiError(data)}`);
|
|
29741
30001
|
process.exit(1);
|
|
29742
30002
|
}
|
|
29743
30003
|
if (json) jsonSuccess(data);
|
|
@@ -29769,8 +30029,8 @@ Shows the version of the currently running daemon process.
|
|
|
29769
30029
|
const res = await call("/api/tunnel");
|
|
29770
30030
|
const data = await res.json();
|
|
29771
30031
|
if (!res.ok) {
|
|
29772
|
-
if (json) jsonError(ErrorCodes.API_ERROR,
|
|
29773
|
-
console.error(`Error: ${data
|
|
30032
|
+
if (json) jsonError(ErrorCodes.API_ERROR, extractApiError(data));
|
|
30033
|
+
console.error(`Error: ${extractApiError(data)}`);
|
|
29774
30034
|
process.exit(1);
|
|
29775
30035
|
}
|
|
29776
30036
|
if (json) jsonSuccess(data);
|
|
@@ -29794,8 +30054,8 @@ Shows the version of the currently running daemon process.
|
|
|
29794
30054
|
});
|
|
29795
30055
|
const data = await res.json();
|
|
29796
30056
|
if (!res.ok) {
|
|
29797
|
-
if (json) jsonError(ErrorCodes.API_ERROR,
|
|
29798
|
-
console.error(`Error: ${data
|
|
30057
|
+
if (json) jsonError(ErrorCodes.API_ERROR, extractApiError(data));
|
|
30058
|
+
console.error(`Error: ${extractApiError(data)}`);
|
|
29799
30059
|
process.exit(1);
|
|
29800
30060
|
}
|
|
29801
30061
|
if (json) jsonSuccess({ sent: true });
|
|
@@ -29804,8 +30064,8 @@ Shows the version of the currently running daemon process.
|
|
|
29804
30064
|
const res = await call("/api/version");
|
|
29805
30065
|
const data = await res.json();
|
|
29806
30066
|
if (!res.ok) {
|
|
29807
|
-
if (json) jsonError(ErrorCodes.API_ERROR,
|
|
29808
|
-
console.error(`Error: ${data
|
|
30067
|
+
if (json) jsonError(ErrorCodes.API_ERROR, extractApiError(data));
|
|
30068
|
+
console.error(`Error: ${extractApiError(data)}`);
|
|
29809
30069
|
process.exit(1);
|
|
29810
30070
|
}
|
|
29811
30071
|
if (json) jsonSuccess(data);
|
|
@@ -29822,8 +30082,8 @@ Shows the version of the currently running daemon process.
|
|
|
29822
30082
|
const res = await call(`/api/sessions/${encodeURIComponent(sessionId)}/config`);
|
|
29823
30083
|
const data = await res.json();
|
|
29824
30084
|
if (!res.ok) {
|
|
29825
|
-
if (json) jsonError(ErrorCodes.API_ERROR,
|
|
29826
|
-
console.error(`Error: ${data
|
|
30085
|
+
if (json) jsonError(ErrorCodes.API_ERROR, extractApiError(data));
|
|
30086
|
+
console.error(`Error: ${extractApiError(data)}`);
|
|
29827
30087
|
process.exit(1);
|
|
29828
30088
|
}
|
|
29829
30089
|
if (json) jsonSuccess(data);
|
|
@@ -29871,8 +30131,8 @@ Client overrides: ${JSON.stringify(clientOverrides)}`);
|
|
|
29871
30131
|
});
|
|
29872
30132
|
const data = await res.json();
|
|
29873
30133
|
if (!res.ok) {
|
|
29874
|
-
if (json) jsonError(ErrorCodes.API_ERROR,
|
|
29875
|
-
console.error(`Error: ${data
|
|
30134
|
+
if (json) jsonError(ErrorCodes.API_ERROR, extractApiError(data));
|
|
30135
|
+
console.error(`Error: ${extractApiError(data)}`);
|
|
29876
30136
|
process.exit(1);
|
|
29877
30137
|
}
|
|
29878
30138
|
if (json) jsonSuccess(data);
|
|
@@ -29886,8 +30146,8 @@ Client overrides: ${JSON.stringify(clientOverrides)}`);
|
|
|
29886
30146
|
const res = await call(`/api/sessions/${encodeURIComponent(sessionId)}/config/overrides`);
|
|
29887
30147
|
const data = await res.json();
|
|
29888
30148
|
if (!res.ok) {
|
|
29889
|
-
if (json) jsonError(ErrorCodes.API_ERROR,
|
|
29890
|
-
console.error(`Error: ${data
|
|
30149
|
+
if (json) jsonError(ErrorCodes.API_ERROR, extractApiError(data));
|
|
30150
|
+
console.error(`Error: ${extractApiError(data)}`);
|
|
29891
30151
|
process.exit(1);
|
|
29892
30152
|
}
|
|
29893
30153
|
if (json) jsonSuccess(data);
|
|
@@ -29915,8 +30175,8 @@ Client overrides: ${JSON.stringify(clientOverrides)}`);
|
|
|
29915
30175
|
});
|
|
29916
30176
|
const data = await res.json();
|
|
29917
30177
|
if (!res.ok) {
|
|
29918
|
-
if (json) jsonError(ErrorCodes.API_ERROR,
|
|
29919
|
-
console.error(`Error: ${data
|
|
30178
|
+
if (json) jsonError(ErrorCodes.API_ERROR, extractApiError(data));
|
|
30179
|
+
console.error(`Error: ${extractApiError(data)}`);
|
|
29920
30180
|
process.exit(1);
|
|
29921
30181
|
}
|
|
29922
30182
|
if (json) jsonSuccess(data);
|
|
@@ -29926,8 +30186,8 @@ Client overrides: ${JSON.stringify(clientOverrides)}`);
|
|
|
29926
30186
|
const res = await call(`/api/sessions/${encodeURIComponent(sessionId)}/config/overrides`);
|
|
29927
30187
|
const data = await res.json();
|
|
29928
30188
|
if (!res.ok) {
|
|
29929
|
-
if (json) jsonError(ErrorCodes.API_ERROR,
|
|
29930
|
-
console.error(`Error: ${data
|
|
30189
|
+
if (json) jsonError(ErrorCodes.API_ERROR, extractApiError(data));
|
|
30190
|
+
console.error(`Error: ${extractApiError(data)}`);
|
|
29931
30191
|
process.exit(1);
|
|
29932
30192
|
}
|
|
29933
30193
|
if (json) jsonSuccess(data);
|