@songsid/agend 2.1.2-beta.5 → 2.1.2-beta.50
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/access-path.js +15 -6
- package/dist/access-path.js.map +1 -1
- package/dist/agent-cli-instructions.md +1 -0
- package/dist/agent-cli.js +14 -0
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.d.ts +2 -0
- package/dist/agent-endpoint.js +25 -1
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/backend/antigravity.d.ts +20 -0
- package/dist/backend/antigravity.js +51 -4
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-code.d.ts +59 -0
- package/dist/backend/claude-code.js +67 -1
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/codex.d.ts +26 -0
- package/dist/backend/codex.js +100 -0
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/grok.d.ts +25 -0
- package/dist/backend/grok.js +51 -0
- package/dist/backend/grok.js.map +1 -1
- package/dist/backend/kiro.d.ts +23 -0
- package/dist/backend/kiro.js +120 -2
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/types.d.ts +58 -0
- package/dist/backend/types.js +13 -1
- package/dist/backend/types.js.map +1 -1
- package/dist/channel/adapters/discord.d.ts +15 -0
- package/dist/channel/adapters/discord.js +120 -8
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +21 -0
- package/dist/channel/adapters/telegram.js +86 -0
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/ipc-bridge.d.ts +9 -1
- package/dist/channel/ipc-bridge.js +12 -3
- package/dist/channel/ipc-bridge.js.map +1 -1
- package/dist/channel/ipc-timeouts.d.ts +46 -0
- package/dist/channel/ipc-timeouts.js +65 -0
- package/dist/channel/ipc-timeouts.js.map +1 -0
- package/dist/channel/mcp-server.js +30 -14
- package/dist/channel/mcp-server.js.map +1 -1
- package/dist/channel/mcp-tools.js +30 -1
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/reconnect-backoff.d.ts +17 -0
- package/dist/channel/reconnect-backoff.js +21 -0
- package/dist/channel/reconnect-backoff.js.map +1 -0
- package/dist/channel/types.d.ts +29 -0
- package/dist/classic-channel-manager.js +1 -5
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/cli.js +242 -91
- package/dist/cli.js.map +1 -1
- package/dist/completion.d.ts +27 -0
- package/dist/completion.js +121 -0
- package/dist/completion.js.map +1 -0
- package/dist/config-validator.js +21 -0
- package/dist/config-validator.js.map +1 -1
- package/dist/config.js +2 -0
- package/dist/config.js.map +1 -1
- package/dist/cost-guard.d.ts +3 -1
- package/dist/cost-guard.js +3 -1
- package/dist/cost-guard.js.map +1 -1
- package/dist/daemon.d.ts +302 -8
- package/dist/daemon.js +1165 -312
- package/dist/daemon.js.map +1 -1
- package/dist/event-log.d.ts +31 -0
- package/dist/event-log.js +96 -0
- package/dist/event-log.js.map +1 -1
- package/dist/fleet-context.d.ts +14 -0
- package/dist/fleet-lock.d.ts +28 -0
- package/dist/fleet-lock.js +130 -0
- package/dist/fleet-lock.js.map +1 -0
- package/dist/fleet-manager.d.ts +347 -6
- package/dist/fleet-manager.js +1794 -215
- package/dist/fleet-manager.js.map +1 -1
- package/dist/general-instance.d.ts +9 -0
- package/dist/general-instance.js +11 -0
- package/dist/general-instance.js.map +1 -0
- package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +22 -0
- package/dist/general-knowledge/skills/model-discovery/SKILL.md +14 -23
- package/dist/general-knowledge/skills/session-management/SKILL.md +15 -34
- package/dist/hang-detector.d.ts +19 -13
- package/dist/hang-detector.js +19 -49
- package/dist/hang-detector.js.map +1 -1
- package/dist/instance-lifecycle.d.ts +60 -3
- package/dist/instance-lifecycle.js +237 -48
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instructions.d.ts +5 -0
- package/dist/instructions.js +9 -11
- package/dist/instructions.js.map +1 -1
- package/dist/locale.js +7 -1
- package/dist/locale.js.map +1 -1
- package/dist/logger.js +14 -0
- package/dist/logger.js.map +1 -1
- package/dist/mcp-liveness.d.ts +21 -0
- package/dist/mcp-liveness.js +27 -0
- package/dist/mcp-liveness.js.map +1 -0
- package/dist/outbound-handlers.d.ts +18 -0
- package/dist/outbound-handlers.js +215 -35
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +11 -3
- package/dist/outbound-schemas.js +16 -2
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/pane-write-lock.d.ts +48 -0
- package/dist/pane-write-lock.js +73 -0
- package/dist/pane-write-lock.js.map +1 -0
- package/dist/process-memory.d.ts +31 -0
- package/dist/process-memory.js +79 -0
- package/dist/process-memory.js.map +1 -0
- package/dist/quickstart.js +17 -16
- package/dist/quickstart.js.map +1 -1
- package/dist/reply-dedup.d.ts +41 -0
- package/dist/reply-dedup.js +0 -0
- package/dist/reply-dedup.js.map +1 -0
- package/dist/restart-progress.d.ts +34 -0
- package/dist/restart-progress.js +87 -0
- package/dist/restart-progress.js.map +1 -0
- package/dist/scheduler/db.js +3 -0
- package/dist/scheduler/db.js.map +1 -1
- package/dist/sd-notify.d.ts +27 -0
- package/dist/sd-notify.js +33 -1
- package/dist/sd-notify.js.map +1 -1
- package/dist/secret-file.d.ts +33 -0
- package/dist/secret-file.js +36 -0
- package/dist/secret-file.js.map +1 -0
- package/dist/service-installer.d.ts +28 -0
- package/dist/service-installer.js +72 -1
- package/dist/service-installer.js.map +1 -1
- package/dist/settings-api.js +5 -3
- package/dist/settings-api.js.map +1 -1
- package/dist/setup-wizard.js +9 -7
- package/dist/setup-wizard.js.map +1 -1
- package/dist/tmux-control.d.ts +58 -5
- package/dist/tmux-control.js +102 -14
- package/dist/tmux-control.js.map +1 -1
- package/dist/tmux-manager.d.ts +31 -1
- package/dist/tmux-manager.js +40 -11
- package/dist/tmux-manager.js.map +1 -1
- package/dist/topic-commands.d.ts +49 -9
- package/dist/topic-commands.js +279 -110
- package/dist/topic-commands.js.map +1 -1
- package/dist/tui-glyphs.d.ts +5 -1
- package/dist/tui-glyphs.js +6 -2
- package/dist/tui-glyphs.js.map +1 -1
- package/dist/types.d.ts +19 -2
- package/dist/ui/settings.html +1 -1
- package/dist/ui/view.html +123 -2
- package/dist/update-marker.d.ts +15 -0
- package/dist/update-marker.js +69 -0
- package/dist/update-marker.js.map +1 -0
- package/dist/usage/format-rich.d.ts +11 -0
- package/dist/usage/format-rich.js +121 -0
- package/dist/usage/format-rich.js.map +1 -0
- package/dist/usage/provider-alerts.d.ts +33 -0
- package/dist/usage/provider-alerts.js +57 -0
- package/dist/usage/provider-alerts.js.map +1 -0
- package/dist/usage/providers.d.ts +130 -0
- package/dist/usage/providers.js +1063 -0
- package/dist/usage/providers.js.map +1 -0
- package/dist/usage/statusline-usage.d.ts +20 -0
- package/dist/usage/statusline-usage.js +120 -0
- package/dist/usage/statusline-usage.js.map +1 -0
- package/dist/usage/usage-api.d.ts +50 -0
- package/dist/usage/usage-api.js +197 -0
- package/dist/usage/usage-api.js.map +1 -0
- package/dist/view-api.d.ts +3 -0
- package/dist/view-api.js +11 -2
- package/dist/view-api.js.map +1 -1
- package/dist/web-api.js +7 -3
- package/dist/web-api.js.map +1 -1
- package/dist/web-auth.d.ts +6 -0
- package/dist/web-auth.js +54 -0
- package/dist/web-auth.js.map +1 -0
- package/package.json +4 -1
- package/dist/channel/tool-tracker.d.ts +0 -13
- package/dist/channel/tool-tracker.js +0 -58
- package/dist/channel/tool-tracker.js.map +0 -1
- package/dist/daemon-entry.d.ts +0 -1
- package/dist/daemon-entry.js +0 -30
- package/dist/daemon-entry.js.map +0 -1
package/dist/locale.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locale.js","sourceRoot":"","sources":["../src/locale.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"locale.js","sourceRoot":"","sources":["../src/locale.ts"],"names":[],"mappings":"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"}
|
package/dist/logger.js
CHANGED
|
@@ -43,6 +43,20 @@ export function rotateLogIfNeeded(logPath, maxSize = MAX_LOG_SIZE, maxFiles = RO
|
|
|
43
43
|
const stat = statSync(logPath);
|
|
44
44
|
if (stat.size < maxSize)
|
|
45
45
|
return;
|
|
46
|
+
// Ballooned far past the limit (e.g. never-rotated TUI animation flood at
|
|
47
|
+
// hundreds of MB): drop content in place. Copying a 700MB+ file to .1 is
|
|
48
|
+
// slow and wasteful; the open writer (pipe-pane `cat >>`, pino) keeps the
|
|
49
|
+
// same inode so truncate is enough.
|
|
50
|
+
if (stat.size > maxSize * 10) {
|
|
51
|
+
for (let i = 1; i <= maxFiles; i++) {
|
|
52
|
+
try {
|
|
53
|
+
unlinkSync(`${logPath}.${i}`);
|
|
54
|
+
}
|
|
55
|
+
catch { /* no rotated file */ }
|
|
56
|
+
}
|
|
57
|
+
truncateSync(logPath, 0);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
46
60
|
// Shift existing rotated files: .2 → .3 (oldest deleted), .1 → .2, …
|
|
47
61
|
for (let i = maxFiles; i >= 2; i--) {
|
|
48
62
|
const src = `${logPath}.${i - 1}`;
|
package/dist/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Liveness of an instance's MCP server, derived from `channel.mcp.pid`.
|
|
3
|
+
*
|
|
4
|
+
* The MCP server writes that file at startup and unlinks it on a clean exit, so:
|
|
5
|
+
* - **dead** → file present but the pid is gone: it died without cleaning up
|
|
6
|
+
* (crash / OOM / SIGKILL). This is the incident worth reporting.
|
|
7
|
+
* - **unknown** → no file, or an unusable value: not started yet, or exited
|
|
8
|
+
* cleanly. Never alarm on this, or every startup would alert.
|
|
9
|
+
* - **alive** → the pid responds to signal 0 (EPERM counts as alive: the
|
|
10
|
+
* process exists but is owned by another user).
|
|
11
|
+
*/
|
|
12
|
+
export type McpServerState = {
|
|
13
|
+
state: "alive";
|
|
14
|
+
pid: number;
|
|
15
|
+
} | {
|
|
16
|
+
state: "dead";
|
|
17
|
+
pid: number;
|
|
18
|
+
} | {
|
|
19
|
+
state: "unknown";
|
|
20
|
+
};
|
|
21
|
+
export declare function mcpServerState(instanceDir: string): McpServerState;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
export function mcpServerState(instanceDir) {
|
|
4
|
+
let raw;
|
|
5
|
+
try {
|
|
6
|
+
raw = readFileSync(join(instanceDir, "channel.mcp.pid"), "utf-8").trim();
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return { state: "unknown" };
|
|
10
|
+
}
|
|
11
|
+
const pid = Number.parseInt(raw, 10);
|
|
12
|
+
// Reject non-numeric, init, and anything unsafe — a bad pid must never be
|
|
13
|
+
// reported as "dead" (that would be a false alarm) nor signalled.
|
|
14
|
+
if (!Number.isSafeInteger(pid) || pid <= 1 || String(pid) !== raw.replace(/^\+/, "")) {
|
|
15
|
+
return { state: "unknown" };
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
process.kill(pid, 0);
|
|
19
|
+
return { state: "alive", pid };
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
if (err.code === "EPERM")
|
|
23
|
+
return { state: "alive", pid };
|
|
24
|
+
return { state: "dead", pid };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=mcp-liveness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-liveness.js","sourceRoot":"","sources":["../src/mcp-liveness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAkBjC,MAAM,UAAU,cAAc,CAAC,WAAmB;IAChD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC9B,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACrC,0EAA0E;IAC1E,kEAAkE;IAClE,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC;QACrF,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC9B,CAAC;IACD,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;IACjC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,OAAO;YAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;QACpF,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IAChC,CAAC;AACH,CAAC"}
|
|
@@ -21,10 +21,13 @@ export interface OutboundContext {
|
|
|
21
21
|
instanceName: string;
|
|
22
22
|
name: string;
|
|
23
23
|
backend?: string;
|
|
24
|
+
model?: string;
|
|
24
25
|
channelId: string;
|
|
26
|
+
adapterId?: string;
|
|
25
27
|
}[];
|
|
26
28
|
getChannelIdByInstance?(name: string): string | undefined;
|
|
27
29
|
getBackendByInstance?(name: string, fleetDefault?: string): string;
|
|
30
|
+
getModel?(channelId: string, adapterId?: string, fleetDefault?: string): string | undefined;
|
|
28
31
|
} | null;
|
|
29
32
|
lastActivityMs(name: string): number;
|
|
30
33
|
startInstance(name: string, config: InstanceConfig, topicMode: boolean): Promise<void>;
|
|
@@ -41,10 +44,20 @@ export interface OutboundContext {
|
|
|
41
44
|
id: string;
|
|
42
45
|
adapter: ChannelAdapter;
|
|
43
46
|
} | undefined;
|
|
47
|
+
/** Post a notice into an instance's own topic (used to report failed deliveries). */
|
|
48
|
+
notifyInstanceTopic?(instanceName: string, text: string): void;
|
|
44
49
|
sendCancelButton?(instanceName: string, correlationId?: string): Promise<void>;
|
|
45
50
|
clearCancelButton?(instanceName: string): void;
|
|
46
51
|
clearCancelButtonByCorrelation?(correlationId: string): void;
|
|
47
52
|
getInstanceExecutionState?(name: string): "idle" | "working" | "stuck" | "paused" | null;
|
|
53
|
+
/** Effective process state used to annotate cross-instance delivery results. */
|
|
54
|
+
getInstanceStatus?(name: string): "running" | "paused" | "stopped" | "crashed";
|
|
55
|
+
resolveInstanceModel?(name: string): {
|
|
56
|
+
model: string;
|
|
57
|
+
source: "instance" | "fleet-default" | "classic" | "cli-default" | "unresolved";
|
|
58
|
+
display: string;
|
|
59
|
+
reason?: string;
|
|
60
|
+
};
|
|
48
61
|
}
|
|
49
62
|
/** Metadata extracted from the raw outbound message. */
|
|
50
63
|
export interface OutboundMeta {
|
|
@@ -55,5 +68,10 @@ export interface OutboundMeta {
|
|
|
55
68
|
}
|
|
56
69
|
type Respond = (result: unknown, error?: string) => void;
|
|
57
70
|
type Handler = (ctx: OutboundContext, args: Record<string, unknown>, respond: Respond, meta: OutboundMeta) => Promise<void> | void;
|
|
71
|
+
/** Test seam: real retry intervals are 30s, far beyond a test's patience. */
|
|
72
|
+
export declare function setCrossInstanceRetryForTests(cfg: {
|
|
73
|
+
retries: number;
|
|
74
|
+
intervalMs: number;
|
|
75
|
+
} | null): void;
|
|
58
76
|
export declare const outboundHandlers: Map<string, Handler>;
|
|
59
77
|
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { resolve as pathResolve, isAbsolute } from "node:path";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
|
-
import {
|
|
3
|
+
import { GENERAL_PAUSE_ERROR, isGeneralInstance } from "./general-instance.js";
|
|
4
|
+
import { BroadcastArgs, CreateInstanceArgs, CreateTeamArgs, DelegateTaskArgs, DeleteInstanceArgs, DeleteTeamArgs, DeployTemplateArgs, DescribeInstanceArgs, ListDeploymentsArgs, ListInstancesArgs, ListTeamsArgs, ReplaceInstanceArgs, ReportResultArgs, RequestInformationArgs, RestartInstanceArgs, SendToInstanceArgs, PauseInstanceArgs, WakeInstanceArgs, StopInstanceArgs, GetInstanceLogsArgs, GetEffortArgs, GetUsageArgs, GetFleetConfigArgs, UpdateInstanceConfigArgs, UpdateFleetDefaultsArgs, StartInstanceArgs, TeardownDeploymentArgs, UpdateTeamArgs, validateArgs, } from "./outbound-schemas.js";
|
|
4
5
|
const HOME_DIR = homedir();
|
|
5
6
|
/**
|
|
6
7
|
* Sanitize an error for inclusion in outbound responses sent to agents.
|
|
@@ -33,6 +34,78 @@ async function deliverToInstance(ctx, instanceName, payload) {
|
|
|
33
34
|
throw new Error(`Instance '${instanceName}' is not connected`);
|
|
34
35
|
ipc.send(payload);
|
|
35
36
|
}
|
|
37
|
+
/** Resolve state before delivery so a paused wake is visible to the sender. */
|
|
38
|
+
function targetState(ctx, name) {
|
|
39
|
+
const daemon = ctx.lifecycle.daemons.get(name);
|
|
40
|
+
// A daemon can still have a live pid while its crash-loop guard has disabled
|
|
41
|
+
// respawn. Surface that as crashed instead of promising a delivery that the
|
|
42
|
+
// pane can never process.
|
|
43
|
+
if (daemon?.isCrashLoop)
|
|
44
|
+
return "crashed";
|
|
45
|
+
if (ctx.getInstanceStatus)
|
|
46
|
+
return ctx.getInstanceStatus(name);
|
|
47
|
+
if (ctx.lifecycle.isPaused?.(name))
|
|
48
|
+
return "paused";
|
|
49
|
+
if (daemon || ctx.instanceIpcClients.has(name))
|
|
50
|
+
return "running";
|
|
51
|
+
return "stopped";
|
|
52
|
+
}
|
|
53
|
+
/** Cross-instance delivery retries: same shape the scheduler already uses. */
|
|
54
|
+
const CROSS_INSTANCE_RETRY_DEFAULTS = { retries: 3, intervalMs: 30_000 };
|
|
55
|
+
let crossInstanceRetry = { ...CROSS_INSTANCE_RETRY_DEFAULTS };
|
|
56
|
+
/** Test seam: real retry intervals are 30s, far beyond a test's patience. */
|
|
57
|
+
export function setCrossInstanceRetryForTests(cfg) {
|
|
58
|
+
crossInstanceRetry = cfg ?? { ...CROSS_INSTANCE_RETRY_DEFAULTS };
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Deliver a cross-instance message with retries, and make a final failure VISIBLE.
|
|
62
|
+
*
|
|
63
|
+
* This path used to be pure fire-and-forget: the handler answered
|
|
64
|
+
* `{sent: true, queued: true}` and a later rejection went to `logger.warn` and
|
|
65
|
+
* nowhere else. The sending agent believed it had delivered, the recipient never
|
|
66
|
+
* got it, and no human was told — the last large hole under "instance messages
|
|
67
|
+
* must not get lost". The failure window is real: `deliverWithIdleGate` throws
|
|
68
|
+
* whenever the target's IPC has gone, which is exactly what happens while a target
|
|
69
|
+
* is restarting or crash-looping.
|
|
70
|
+
*
|
|
71
|
+
* Retries reuse the scheduler's proven numbers (3 attempts, 30s apart). On final
|
|
72
|
+
* failure we log at error, record it in the event log, and post to BOTH the
|
|
73
|
+
* sender's and the target's topic so the agent that sent it and any watching human
|
|
74
|
+
* both find out.
|
|
75
|
+
*/
|
|
76
|
+
async function deliverCrossInstanceWithRetry(ctx, targetInstanceName, targetLabel, senderLabel, correlationId, payload) {
|
|
77
|
+
const attempt = async () => {
|
|
78
|
+
try {
|
|
79
|
+
await deliverToInstance(ctx, targetInstanceName, payload);
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
return err instanceof Error ? err : new Error(String(err));
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
let lastError = await attempt();
|
|
87
|
+
for (let i = 0; lastError && i < crossInstanceRetry.retries; i++) {
|
|
88
|
+
ctx.logger.warn({ err: lastError.message, target: targetLabel, correlation_id: correlationId, attempt: i + 1 }, "Cross-instance delivery failed — retrying");
|
|
89
|
+
await new Promise(r => setTimeout(r, crossInstanceRetry.intervalMs));
|
|
90
|
+
lastError = await attempt();
|
|
91
|
+
}
|
|
92
|
+
if (!lastError)
|
|
93
|
+
return;
|
|
94
|
+
ctx.logger.error({ err: lastError.message, target: targetLabel, correlation_id: correlationId, attempts: crossInstanceRetry.retries + 1 }, "Cross-instance delivery failed after retries — message lost");
|
|
95
|
+
ctx.eventLog?.insert(targetInstanceName, "cross_instance_delivery_failed", {
|
|
96
|
+
from: senderLabel,
|
|
97
|
+
correlation_id: correlationId,
|
|
98
|
+
error: lastError.message,
|
|
99
|
+
});
|
|
100
|
+
const notice = `❌ Message from ${senderLabel} to ${targetLabel} could not be delivered after `
|
|
101
|
+
+ `${crossInstanceRetry.retries + 1} attempts (${lastError.message}). `
|
|
102
|
+
+ `correlation_id: ${correlationId}`;
|
|
103
|
+
// Both topics: the sender's agent needs to know its send did not land, and a human
|
|
104
|
+
// watching the target needs to know something was addressed to it and never arrived.
|
|
105
|
+
ctx.notifyInstanceTopic?.(senderLabel, notice);
|
|
106
|
+
if (targetInstanceName !== senderLabel)
|
|
107
|
+
ctx.notifyInstanceTopic?.(targetInstanceName, notice);
|
|
108
|
+
}
|
|
36
109
|
// ── Handler implementations ─────────────────────────────────────────────
|
|
37
110
|
const sendToInstance = async (ctx, rawArgs, respond, meta) => {
|
|
38
111
|
const v = validateArgs(SendToInstanceArgs, rawArgs, "send_to_instance");
|
|
@@ -54,14 +127,22 @@ const sendToInstance = async (ctx, rawArgs, respond, meta) => {
|
|
|
54
127
|
targetInstanceName = hostInstance;
|
|
55
128
|
}
|
|
56
129
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
130
|
+
const existsInConfig = targetName in (ctx.fleetConfig?.instances ?? {})
|
|
131
|
+
|| targetInstanceName in (ctx.fleetConfig?.instances ?? {});
|
|
132
|
+
if (!existsInConfig && !targetIpc) {
|
|
133
|
+
respond(null, `Instance or session not found: ${targetName}`);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const state = targetState(ctx, targetInstanceName);
|
|
137
|
+
// Paused instances may have no live IPC while their persisted window is being
|
|
138
|
+
// woken. The FleetManager facade can still start them, so let that path run.
|
|
139
|
+
const canWakePersisted = state === "paused" && !!ctx.deliverToInstance;
|
|
140
|
+
if (state === "crashed") {
|
|
141
|
+
respond(null, `Instance '${targetName}' is crashed (target_state=crashed). Restart it before sending.`);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
if (state === "stopped" || (!targetIpc && !canWakePersisted)) {
|
|
145
|
+
respond(null, `Instance '${targetName}' is stopped (target_state=stopped). Use start_instance('${targetName}') to start it first.`);
|
|
65
146
|
return;
|
|
66
147
|
}
|
|
67
148
|
const correlationId = parsedCorrelationId || `cid-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
@@ -90,13 +171,16 @@ const sendToInstance = async (ctx, rawArgs, respond, meta) => {
|
|
|
90
171
|
const senderDisplay = ctx.fleetConfig?.instances[senderLabel]?.display_name;
|
|
91
172
|
if (senderDisplay && senderDisplay !== senderLabel)
|
|
92
173
|
ipcMeta.from_display = senderDisplay;
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
174
|
+
// Fire-and-queue: hand the message to the fleet and respond immediately.
|
|
175
|
+
// deliverToInstance owns waking a paused target, the idle gate and retries;
|
|
176
|
+
// awaiting it here blocked this call for as long as the target stayed busy
|
|
177
|
+
// (up to the idle-gate timeout), which serialized ALL cross-instance traffic
|
|
178
|
+
// and surfaced as "IPC request timed out after 30000ms" on the caller.
|
|
179
|
+
// Unknown/stopped targets already errored synchronously above, so anything
|
|
180
|
+
// failing past this point is a delivery problem to log, not a caller error.
|
|
181
|
+
// Retries and, on final failure, tells both agents' topics — see
|
|
182
|
+
// deliverCrossInstanceWithRetry. It never rejects, so nothing escapes here.
|
|
183
|
+
void deliverCrossInstanceWithRetry(ctx, targetInstanceName, targetName, senderLabel, correlationId, { type: "fleet_inbound", targetSession, content: message, meta: ipcMeta });
|
|
100
184
|
// Show a cancel button on the target's topic so a watching user can interrupt
|
|
101
185
|
// work started by another instance — but only for messages that actually put
|
|
102
186
|
// the recipient to work (task/query). Informational report/update messages
|
|
@@ -155,7 +239,8 @@ const sendToInstance = async (ctx, rawArgs, respond, meta) => {
|
|
|
155
239
|
const taskSummary = ipcMeta.task_summary || (message ?? "").slice(0, 200);
|
|
156
240
|
ctx.eventLog?.logActivity("message", senderLabel, taskSummary, targetName, ipcMeta.request_kind);
|
|
157
241
|
ctx.queueMirrorMessage?.(`${senderLabel} → ${targetName}: ${(message ?? "").slice(0, 500)}${(message ?? "").length > 500 ? " […]" : ""}`);
|
|
158
|
-
respond({ sent: true, target: targetName,
|
|
242
|
+
respond({ sent: true, queued: true, target: targetName, target_state: state,
|
|
243
|
+
...(state === "paused" ? { waking: true } : {}), correlation_id: correlationId,
|
|
159
244
|
...(ctx.lifecycle.daemons.get(targetInstanceName)?.isErrorState && {
|
|
160
245
|
warning: (() => {
|
|
161
246
|
const daemon = ctx.lifecycle.daemons.get(targetInstanceName);
|
|
@@ -191,6 +276,8 @@ const listInstances = (ctx, rawArgs, respond, meta) => {
|
|
|
191
276
|
display_name: config.display_name ?? null,
|
|
192
277
|
description: config.description ?? null,
|
|
193
278
|
backend: config.backend ?? "claude-code",
|
|
279
|
+
model: ctx.resolveInstanceModel?.(name).model ?? config.model ?? "default",
|
|
280
|
+
kind: "fleet-topic",
|
|
194
281
|
tags: config.tags ?? [],
|
|
195
282
|
last_activity: ctx.lastActivityMs(name) ? new Date(ctx.lastActivityMs(name)).toISOString() : null,
|
|
196
283
|
}));
|
|
@@ -212,7 +299,11 @@ const listInstances = (ctx, rawArgs, respond, meta) => {
|
|
|
212
299
|
topic_id: ch.channelId,
|
|
213
300
|
display_name: `classic: ${ch.name}`,
|
|
214
301
|
description: `ClassicBot channel (${ch.name})`,
|
|
215
|
-
backend: ch.backend ?? "claude-code",
|
|
302
|
+
backend: ctx.classicChannels.getBackendByInstance?.(ch.instanceName, ctx.fleetConfig?.defaults?.backend) ?? ch.backend ?? ctx.fleetConfig?.defaults?.backend ?? "claude-code",
|
|
303
|
+
model: ctx.resolveInstanceModel?.(ch.instanceName).model
|
|
304
|
+
?? ctx.classicChannels.getModel?.(ch.channelId, ch.adapterId, ctx.fleetConfig?.defaults?.model)
|
|
305
|
+
?? "default",
|
|
306
|
+
kind: "classic",
|
|
216
307
|
tags: ["classic"],
|
|
217
308
|
last_activity: ctx.lastActivityMs(ch.instanceName) ? new Date(ctx.lastActivityMs(ch.instanceName)).toISOString() : null,
|
|
218
309
|
});
|
|
@@ -232,9 +323,11 @@ const describeInstance = (ctx, rawArgs, respond) => {
|
|
|
232
323
|
const targetName = v.data.name;
|
|
233
324
|
const config = ctx.fleetConfig?.instances[targetName];
|
|
234
325
|
if (config) {
|
|
326
|
+
const model = ctx.resolveInstanceModel?.(targetName);
|
|
235
327
|
respond({
|
|
236
328
|
name: targetName,
|
|
237
329
|
type: "instance",
|
|
330
|
+
kind: "fleet-topic",
|
|
238
331
|
description: config.description ?? null,
|
|
239
332
|
tags: config.tags ?? [],
|
|
240
333
|
working_directory: config.working_directory,
|
|
@@ -245,7 +338,8 @@ const describeInstance = (ctx, rawArgs, respond) => {
|
|
|
245
338
|
: null,
|
|
246
339
|
topic_id: config.topic_id ?? null,
|
|
247
340
|
backend: config.backend ?? "claude-code",
|
|
248
|
-
model: config.model ??
|
|
341
|
+
model: model?.model ?? config.model ?? "default",
|
|
342
|
+
model_source: model?.source ?? (config.model ? "instance" : "unresolved"),
|
|
249
343
|
last_activity: ctx.lastActivityMs(targetName) ? new Date(ctx.lastActivityMs(targetName)).toISOString() : null,
|
|
250
344
|
worktree_source: config.worktree_source ?? null,
|
|
251
345
|
});
|
|
@@ -255,9 +349,12 @@ const describeInstance = (ctx, rawArgs, respond) => {
|
|
|
255
349
|
if (ctx.classicChannels) {
|
|
256
350
|
const channelId = ctx.classicChannels.getChannelIdByInstance?.(targetName);
|
|
257
351
|
if (channelId) {
|
|
352
|
+
const channel = ctx.classicChannels.getAll().find(ch => ch.instanceName === targetName);
|
|
353
|
+
const model = ctx.resolveInstanceModel?.(targetName);
|
|
258
354
|
respond({
|
|
259
355
|
name: targetName,
|
|
260
356
|
type: "instance",
|
|
357
|
+
kind: "classic",
|
|
261
358
|
description: `ClassicBot channel`,
|
|
262
359
|
tags: ["classic"],
|
|
263
360
|
working_directory: "",
|
|
@@ -265,8 +362,13 @@ const describeInstance = (ctx, rawArgs, respond) => {
|
|
|
265
362
|
instance_state: ctx.getInstanceExecutionState?.(targetName) ?? null,
|
|
266
363
|
last_paused_at: null,
|
|
267
364
|
topic_id: channelId,
|
|
268
|
-
backend: ctx.classicChannels.getBackendByInstance?.(targetName) ?? "claude-code",
|
|
269
|
-
model:
|
|
365
|
+
backend: ctx.classicChannels.getBackendByInstance?.(targetName, ctx.fleetConfig?.defaults?.backend) ?? ctx.fleetConfig?.defaults?.backend ?? "claude-code",
|
|
366
|
+
model: model?.model
|
|
367
|
+
?? ctx.classicChannels.getModel?.(channelId, channel?.adapterId, ctx.fleetConfig?.defaults?.model)
|
|
368
|
+
?? "default",
|
|
369
|
+
model_source: model?.source ?? (ctx.classicChannels.getModel?.(channelId, channel?.adapterId, ctx.fleetConfig?.defaults?.model)
|
|
370
|
+
? "classic"
|
|
371
|
+
: "unresolved"),
|
|
270
372
|
last_activity: ctx.lastActivityMs(targetName) ? new Date(ctx.lastActivityMs(targetName)).toISOString() : null,
|
|
271
373
|
worktree_source: null,
|
|
272
374
|
});
|
|
@@ -287,7 +389,33 @@ const startInstance = async (ctx, rawArgs, respond) => {
|
|
|
287
389
|
return;
|
|
288
390
|
}
|
|
289
391
|
const targetName = v.data.name;
|
|
392
|
+
// `start_instance` is an explicit operator request, not the fleet startup
|
|
393
|
+
// reconciliation path. Treat a persisted/daemon pause as wake so the
|
|
394
|
+
// marker is cleared and the next state snapshot is visible to `agend ls`.
|
|
395
|
+
if (ctx.lifecycle.isPaused?.(targetName)) {
|
|
396
|
+
try {
|
|
397
|
+
await ctx.lifecycle.wake(targetName, 30_000);
|
|
398
|
+
respond({ success: true, status: "started" });
|
|
399
|
+
}
|
|
400
|
+
catch (err) {
|
|
401
|
+
respond(null, `Failed to wake instance '${targetName}': ${sanitizeError(err, ctx, `start_instance(${targetName})`)}`);
|
|
402
|
+
}
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
290
405
|
if (ctx.lifecycle.daemons.has(targetName)) {
|
|
406
|
+
// A crash-loop daemon stays in the map while its pane is dead. Do not
|
|
407
|
+
// report it as already running; restart it so its crash marker is consumed.
|
|
408
|
+
const status = ctx.getInstanceStatus?.(targetName);
|
|
409
|
+
if (status === "crashed" || status === "stopped") {
|
|
410
|
+
try {
|
|
411
|
+
await ctx.restartSingleInstance(targetName);
|
|
412
|
+
respond({ success: true, status: "started" });
|
|
413
|
+
}
|
|
414
|
+
catch (err) {
|
|
415
|
+
respond(null, `Failed to restart instance '${targetName}': ${sanitizeError(err, ctx, `start_instance(${targetName})`)}`);
|
|
416
|
+
}
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
291
419
|
respond({ success: true, status: "already_running" });
|
|
292
420
|
return;
|
|
293
421
|
}
|
|
@@ -338,6 +466,10 @@ const pauseInstance = async (ctx, rawArgs, respond) => {
|
|
|
338
466
|
respond(null, v.error);
|
|
339
467
|
return;
|
|
340
468
|
}
|
|
469
|
+
if (isGeneralInstance(ctx.fleetConfig, v.data.name)) {
|
|
470
|
+
respond(null, GENERAL_PAUSE_ERROR);
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
341
473
|
try {
|
|
342
474
|
await ctx.lifecycle.pause(v.data.name);
|
|
343
475
|
respond({ success: true, status: "paused" });
|
|
@@ -388,6 +520,50 @@ const getFleetStatus = (ctx, rawArgs, respond) => {
|
|
|
388
520
|
const stopped = names.length - running - paused;
|
|
389
521
|
respond({ total: names.length, running, paused, stopped });
|
|
390
522
|
};
|
|
523
|
+
const getEffort = (ctx, rawArgs, respond, meta) => {
|
|
524
|
+
const v = validateArgs(GetEffortArgs, rawArgs, "get_effort");
|
|
525
|
+
if (!v.ok) {
|
|
526
|
+
respond(null, v.error);
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
const name = v.data.name ?? meta?.instanceName;
|
|
530
|
+
if (!name) {
|
|
531
|
+
respond(null, "No instance name available");
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
const fm = ctx;
|
|
535
|
+
const strategy = fm.effortStrategyFor?.(name) ?? "unsupported";
|
|
536
|
+
const supported = strategy !== "unsupported";
|
|
537
|
+
const levels = supported ? fm.effortLevelsFor?.(name) ?? [] : [];
|
|
538
|
+
const resolved = fm.resolveInstanceEffort?.(name) ?? { effort: null, source: "unset" };
|
|
539
|
+
respond({
|
|
540
|
+
instance: name,
|
|
541
|
+
backend: fm.backendNameForInstance?.(name) ?? null,
|
|
542
|
+
// null (not "") when the CLI has none, so a caller can branch on it rather
|
|
543
|
+
// than parse a sentinel string.
|
|
544
|
+
effort: supported ? resolved.effort : null,
|
|
545
|
+
source: supported ? resolved.source : "unsupported",
|
|
546
|
+
available_levels: levels,
|
|
547
|
+
// "restart" warns the agent that changing this costs a respawn — worth
|
|
548
|
+
// knowing before it changes its own effort mid-task.
|
|
549
|
+
change_strategy: strategy,
|
|
550
|
+
});
|
|
551
|
+
};
|
|
552
|
+
const getUsage = async (ctx, rawArgs, respond) => {
|
|
553
|
+
const v = validateArgs(GetUsageArgs, rawArgs, "get_usage");
|
|
554
|
+
if (!v.ok) {
|
|
555
|
+
respond(null, v.error);
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
try {
|
|
559
|
+
// Same structure as GET /api/ai-usage, same 5-minute cache behind it.
|
|
560
|
+
const { getUsageSnapshot } = await import("./usage/usage-api.js");
|
|
561
|
+
respond(await getUsageSnapshot(v.data.force === true));
|
|
562
|
+
}
|
|
563
|
+
catch (err) {
|
|
564
|
+
respond(null, `Usage fetch failed: ${err.message}`);
|
|
565
|
+
}
|
|
566
|
+
};
|
|
391
567
|
const getInstanceLogs = async (ctx, rawArgs, respond) => {
|
|
392
568
|
const v = validateArgs(GetInstanceLogsArgs, rawArgs, "get_instance_logs");
|
|
393
569
|
if (!v.ok) {
|
|
@@ -615,10 +791,17 @@ const broadcast = async (ctx, rawArgs, respond, meta) => {
|
|
|
615
791
|
else {
|
|
616
792
|
targetNames = [...ctx.instanceIpcClients.keys()].filter(n => n !== meta.instanceName && n !== senderLabel);
|
|
617
793
|
}
|
|
618
|
-
|
|
794
|
+
// Fire-and-queue, same rationale as send_to_instance: a broadcast awaiting every
|
|
795
|
+
// target's idle gate blocked for as long as the BUSIEST recipient. Connectivity
|
|
796
|
+
// is decided synchronously (that's the real failure), delivery runs in background.
|
|
797
|
+
const sentTo = [];
|
|
798
|
+
const failed = [];
|
|
799
|
+
for (const targetName of targetNames) {
|
|
619
800
|
const hostInstance = ctx.instanceIpcClients.has(targetName) ? targetName : ctx.sessionRegistry.get(targetName);
|
|
620
|
-
if (!hostInstance || !ctx.instanceIpcClients.has(hostInstance))
|
|
621
|
-
|
|
801
|
+
if (!hostInstance || !ctx.instanceIpcClients.has(hostInstance)) {
|
|
802
|
+
failed.push(targetName);
|
|
803
|
+
continue;
|
|
804
|
+
}
|
|
622
805
|
const correlationId = `bcast-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
623
806
|
const ipcMeta = {
|
|
624
807
|
chat_id: "", message_id: `bcast-${Date.now()}`, user: `instance:${senderLabel}`,
|
|
@@ -633,23 +816,18 @@ const broadcast = async (ctx, rawArgs, respond, meta) => {
|
|
|
633
816
|
ipcMeta.task_summary = task_summary;
|
|
634
817
|
if (senderDisplay && senderDisplay !== senderLabel)
|
|
635
818
|
ipcMeta.from_display = senderDisplay;
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
return { targetName, sent: false };
|
|
642
|
-
}
|
|
643
|
-
}));
|
|
644
|
-
const sentTo = deliveryResults.filter(result => result.sent).map(result => result.targetName);
|
|
645
|
-
const failed = deliveryResults.filter(result => !result.sent).map(result => result.targetName);
|
|
819
|
+
// Same at-least-once treatment as send_to_instance: retry, then surface a
|
|
820
|
+
// final failure on both topics instead of dying in a warn-level log line.
|
|
821
|
+
void deliverCrossInstanceWithRetry(ctx, hostInstance, targetName, senderLabel, correlationId, { type: "fleet_inbound", targetSession: targetName, content: message, meta: ipcMeta });
|
|
822
|
+
sentTo.push(targetName);
|
|
823
|
+
}
|
|
646
824
|
ctx.logger.info(`📢 ${senderLabel} broadcast to ${sentTo.length} instances: ${(message).slice(0, 80)}`);
|
|
647
825
|
const summary = task_summary || message.slice(0, 200);
|
|
648
826
|
for (const target of sentTo) {
|
|
649
827
|
ctx.eventLog?.logActivity("message", senderLabel, summary, target);
|
|
650
828
|
}
|
|
651
829
|
ctx.queueMirrorMessage?.(`📢 ${senderLabel} → [${sentTo.join(", ")}]: ${message.slice(0, 500)}${message.length > 500 ? " […]" : ""}`);
|
|
652
|
-
respond({ sent_to: sentTo, failed, count: sentTo.length });
|
|
830
|
+
respond({ sent_to: sentTo, failed, count: sentTo.length, queued: true });
|
|
653
831
|
};
|
|
654
832
|
// ── Teams ────────────────────────────────────────────────────────────────
|
|
655
833
|
const createTeam = (ctx, rawArgs, respond) => {
|
|
@@ -993,6 +1171,8 @@ export const outboundHandlers = new Map([
|
|
|
993
1171
|
["wake_instance", wakeInstance],
|
|
994
1172
|
["stop_instance", stopInstance],
|
|
995
1173
|
["get_fleet_status", getFleetStatus],
|
|
1174
|
+
["get_effort", getEffort],
|
|
1175
|
+
["get_usage", getUsage],
|
|
996
1176
|
["get_instance_logs", getInstanceLogs],
|
|
997
1177
|
["get_fleet_config", getFleetConfig],
|
|
998
1178
|
["update_instance_config", updateInstanceConfig],
|