aimux-cli 0.1.18 → 0.1.20
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/README.md +13 -4
- package/bin/aimux +4 -0
- package/bin/aimux-dev +2 -6
- package/dist/agent-events.js +0 -1
- package/dist/agent-output-parser-audit.d.ts +23 -0
- package/dist/agent-output-parser-audit.js +187 -0
- package/dist/agent-output-parser-contract.d.ts +9 -0
- package/dist/agent-output-parser-contract.js +33 -0
- package/dist/agent-output-parser-fixtures.d.ts +15 -0
- package/dist/agent-output-parser-fixtures.js +593 -0
- package/dist/agent-output-parser-harness.d.ts +21 -0
- package/dist/agent-output-parser-harness.js +43 -0
- package/dist/agent-output-parser-test-utils.d.ts +1 -0
- package/dist/agent-output-parser-test-utils.js +7 -0
- package/dist/agent-output-parser.js +215 -36
- package/dist/agent-prompt-delivery.js +0 -1
- package/dist/agent-tracker.js +0 -1
- package/dist/agent-watcher.js +0 -1
- package/dist/alert-display.js +0 -1
- package/dist/atomic-write.d.ts +15 -0
- package/dist/atomic-write.js +69 -5
- package/dist/attachment-store.d.ts +7 -0
- package/dist/attachment-store.js +64 -6
- package/dist/backend-session-discovery.d.ts +17 -0
- package/dist/backend-session-discovery.js +57 -0
- package/dist/builtin-metadata-watchers.js +0 -1
- package/dist/claude-hooks.js +0 -1
- package/dist/config.js +9 -5
- package/dist/connection-targets.js +20 -2
- package/dist/context/compactor.js +0 -1
- package/dist/context/context-bridge.js +4 -2
- package/dist/context/context-file.js +0 -1
- package/dist/context/history.js +0 -1
- package/dist/credentials.js +3 -7
- package/dist/daemon.d.ts +1 -0
- package/dist/daemon.js +16 -1
- package/dist/dashboard/command-spec.js +0 -1
- package/dist/dashboard/feedback.js +0 -1
- package/dist/dashboard/index.d.ts +1 -0
- package/dist/dashboard/index.js +1 -1
- package/dist/dashboard/operation-failures.js +0 -1
- package/dist/dashboard/order.js +0 -1
- package/dist/dashboard/pending-actions.js +0 -1
- package/dist/dashboard/quick-jump.js +0 -1
- package/dist/dashboard/runtime-evidence.js +0 -1
- package/dist/dashboard/session-actions.js +0 -1
- package/dist/dashboard/session-registry.js +0 -1
- package/dist/dashboard/sort.js +0 -1
- package/dist/dashboard/state.js +0 -1
- package/dist/dashboard/targets.js +14 -3
- package/dist/dashboard/ui-state-store.js +4 -4
- package/dist/debug-state.js +0 -1
- package/dist/debug.js +0 -1
- package/dist/default-plugins/gh-pr-context.js +0 -1
- package/dist/default-plugins/transcript-length.js +0 -1
- package/dist/fast-control.js +0 -1
- package/dist/hotkeys.js +0 -1
- package/dist/http-client.js +0 -1
- package/dist/key-parser.js +0 -1
- package/dist/last-used.js +3 -3
- package/dist/launcher-env.d.ts +4 -0
- package/dist/launcher-env.js +70 -0
- package/dist/local-ui-server.js +0 -1
- package/dist/login-flow.js +0 -1
- package/dist/main.js +16 -2
- package/dist/managed-launch-env.js +0 -1
- package/dist/metadata-server.d.ts +13 -2
- package/dist/metadata-server.js +60 -5
- package/dist/metadata-store.js +4 -4
- package/dist/mobile-push-bridge.d.ts +8 -0
- package/dist/mobile-push-bridge.js +22 -0
- package/dist/mobile-push-throttle.d.ts +23 -0
- package/dist/mobile-push-throttle.js +53 -0
- package/dist/multiplexer/agent-io-methods.js +0 -1
- package/dist/multiplexer/archives.js +0 -1
- package/dist/multiplexer/dashboard-actions-methods.js +0 -1
- package/dist/multiplexer/dashboard-control.js +0 -1
- package/dist/multiplexer/dashboard-interaction.js +0 -1
- package/dist/multiplexer/dashboard-model.js +3 -3
- package/dist/multiplexer/dashboard-ops.d.ts +3 -2
- package/dist/multiplexer/dashboard-ops.js +2 -3
- package/dist/multiplexer/dashboard-state-methods.js +0 -1
- package/dist/multiplexer/dashboard-tail-methods.d.ts +3 -2
- package/dist/multiplexer/dashboard-tail-methods.js +2 -3
- package/dist/multiplexer/dashboard-view-methods.js +2 -1
- package/dist/multiplexer/graveyard-view-model.js +0 -1
- package/dist/multiplexer/index.d.ts +1 -1
- package/dist/multiplexer/index.js +4 -5
- package/dist/multiplexer/navigation.js +0 -1
- package/dist/multiplexer/notifications.js +0 -1
- package/dist/multiplexer/persistence-methods.js +2 -2
- package/dist/multiplexer/runtime-lifecycle-methods.js +6 -3
- package/dist/multiplexer/runtime-state.js +13 -2
- package/dist/multiplexer/runtime-sync.js +0 -1
- package/dist/multiplexer/service-state-snapshot.js +4 -3
- package/dist/multiplexer/services.js +5 -5
- package/dist/multiplexer/session-capture.js +0 -1
- package/dist/multiplexer/session-launch.d.ts +1 -1
- package/dist/multiplexer/session-launch.js +18 -7
- package/dist/multiplexer/session-runtime-core.js +9 -3
- package/dist/multiplexer/subscreens.js +0 -1
- package/dist/multiplexer/tool-picker.d.ts +2 -1
- package/dist/multiplexer/tool-picker.js +29 -22
- package/dist/multiplexer/worktree-graveyard.js +0 -1
- package/dist/multiplexer/worktrees.js +0 -1
- package/dist/notification-context.js +0 -1
- package/dist/notifications.js +0 -1
- package/dist/notify.d.ts +1 -1
- package/dist/notify.js +8 -6
- package/dist/orchestration-actions.js +0 -1
- package/dist/orchestration-routing.js +0 -1
- package/dist/orchestration.js +0 -1
- package/dist/osc-notifications.js +0 -1
- package/dist/paths.js +50 -5
- package/dist/pending-actions.js +0 -1
- package/dist/plugin-runtime.js +0 -1
- package/dist/project-events.js +0 -1
- package/dist/project-scanner.js +0 -1
- package/dist/project-service-manifest.js +0 -1
- package/dist/project-takeover.d.ts +1 -0
- package/dist/project-takeover.js +117 -0
- package/dist/recency.js +0 -1
- package/dist/recorder.js +0 -1
- package/dist/relay-client.d.ts +10 -0
- package/dist/relay-client.js +5 -1
- package/dist/remote-access.js +0 -1
- package/dist/runtime-core/backend-id-reconcile.d.ts +13 -0
- package/dist/runtime-core/backend-id-reconcile.js +23 -0
- package/dist/runtime-core/exchange-derived.js +0 -1
- package/dist/runtime-core/exchange-import.js +0 -1
- package/dist/runtime-core/exchange-store.js +3 -9
- package/dist/runtime-core/topology-services.js +0 -1
- package/dist/runtime-core/topology-sessions.js +0 -1
- package/dist/runtime-core/topology-store.js +3 -9
- package/dist/runtime-core/topology-worktrees.js +0 -1
- package/dist/runtime-migration.js +0 -1
- package/dist/runtime-owner.d.ts +3 -0
- package/dist/runtime-owner.js +10 -0
- package/dist/session-bootstrap.js +0 -1
- package/dist/session-runtime.js +0 -1
- package/dist/session-semantics.js +0 -1
- package/dist/shell-args.d.ts +13 -0
- package/dist/shell-args.js +25 -1
- package/dist/shell-hooks.d.ts +1 -0
- package/dist/shell-hooks.js +1 -1
- package/dist/shell-state.js +0 -1
- package/dist/status-detector.js +0 -1
- package/dist/statusline-model.js +0 -1
- package/dist/task-workflow.js +0 -1
- package/dist/tasks.js +0 -1
- package/dist/team.js +4 -4
- package/dist/terminal-host.js +0 -1
- package/dist/threads.js +0 -1
- package/dist/tmux/doctor.js +0 -1
- package/dist/tmux/inbox-popup.js +0 -1
- package/dist/tmux/runtime-manager.js +2 -1
- package/dist/tmux/session-transport.js +0 -1
- package/dist/tmux/statusline-cache.js +0 -1
- package/dist/tmux/statusline.js +0 -1
- package/dist/tmux/switcher.js +0 -1
- package/dist/tmux/window-open.js +0 -1
- package/dist/tool-output-watchers.js +0 -1
- package/dist/tui/render/box.js +0 -1
- package/dist/tui/render/text.js +0 -1
- package/dist/tui/screens/dashboard-renderers.js +6 -7
- package/dist/tui/screens/overlay-renderers.js +0 -1
- package/dist/tui/screens/subscreen-renderers.js +0 -1
- package/dist/vitest.setup.d.ts +1 -0
- package/dist/vitest.setup.js +9 -0
- package/dist/workflow.js +0 -1
- package/dist/worktree.js +0 -1
- package/dist-ui/_expo/static/css/web-8782287775683e5a944b821b854d0f60.css +1 -0
- package/dist-ui/_expo/static/js/web/{entry-477c745b2adc79367a4380ecf07d9ff6.js → entry-90d00d223eefabe5cc21e4329b274fa5.js} +260 -252
- package/dist-ui/index.html +2 -2
- package/package.json +5 -2
- package/dist/agent-events.js.map +0 -1
- package/dist/agent-output-parser.js.map +0 -1
- package/dist/agent-prompt-delivery.js.map +0 -1
- package/dist/agent-tracker.js.map +0 -1
- package/dist/agent-watcher.js.map +0 -1
- package/dist/alert-display.js.map +0 -1
- package/dist/atomic-write.js.map +0 -1
- package/dist/attachment-store.js.map +0 -1
- package/dist/builtin-metadata-watchers.js.map +0 -1
- package/dist/claude-hooks.js.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/connection-targets.js.map +0 -1
- package/dist/context/compactor.js.map +0 -1
- package/dist/context/context-bridge.js.map +0 -1
- package/dist/context/context-file.js.map +0 -1
- package/dist/context/history.js.map +0 -1
- package/dist/credentials.js.map +0 -1
- package/dist/daemon.js.map +0 -1
- package/dist/dashboard/command-spec.js.map +0 -1
- package/dist/dashboard/feedback.js.map +0 -1
- package/dist/dashboard/index.js.map +0 -1
- package/dist/dashboard/operation-failures.js.map +0 -1
- package/dist/dashboard/order.js.map +0 -1
- package/dist/dashboard/pending-actions.js.map +0 -1
- package/dist/dashboard/quick-jump.js.map +0 -1
- package/dist/dashboard/runtime-evidence.js.map +0 -1
- package/dist/dashboard/session-actions.js.map +0 -1
- package/dist/dashboard/session-registry.js.map +0 -1
- package/dist/dashboard/sort.js.map +0 -1
- package/dist/dashboard/state.js.map +0 -1
- package/dist/dashboard/targets.js.map +0 -1
- package/dist/dashboard/ui-state-store.js.map +0 -1
- package/dist/debug-state.js.map +0 -1
- package/dist/debug.js.map +0 -1
- package/dist/default-plugins/gh-pr-context.js.map +0 -1
- package/dist/default-plugins/transcript-length.js.map +0 -1
- package/dist/fast-control.js.map +0 -1
- package/dist/hotkeys.js.map +0 -1
- package/dist/http-client.js.map +0 -1
- package/dist/key-parser.js.map +0 -1
- package/dist/last-used.js.map +0 -1
- package/dist/local-ui-server.js.map +0 -1
- package/dist/login-flow.js.map +0 -1
- package/dist/main.js.map +0 -1
- package/dist/managed-launch-env.js.map +0 -1
- package/dist/metadata-server.js.map +0 -1
- package/dist/metadata-store.js.map +0 -1
- package/dist/multiplexer/agent-io-methods.js.map +0 -1
- package/dist/multiplexer/archives.js.map +0 -1
- package/dist/multiplexer/dashboard-actions-methods.js.map +0 -1
- package/dist/multiplexer/dashboard-control.js.map +0 -1
- package/dist/multiplexer/dashboard-interaction.js.map +0 -1
- package/dist/multiplexer/dashboard-model.js.map +0 -1
- package/dist/multiplexer/dashboard-ops.js.map +0 -1
- package/dist/multiplexer/dashboard-state-methods.js.map +0 -1
- package/dist/multiplexer/dashboard-tail-methods.js.map +0 -1
- package/dist/multiplexer/dashboard-view-methods.js.map +0 -1
- package/dist/multiplexer/graveyard-view-model.js.map +0 -1
- package/dist/multiplexer/index.js.map +0 -1
- package/dist/multiplexer/navigation.js.map +0 -1
- package/dist/multiplexer/notifications.js.map +0 -1
- package/dist/multiplexer/persistence-methods.js.map +0 -1
- package/dist/multiplexer/runtime-lifecycle-methods.js.map +0 -1
- package/dist/multiplexer/runtime-state.js.map +0 -1
- package/dist/multiplexer/runtime-sync.js.map +0 -1
- package/dist/multiplexer/service-state-snapshot.js.map +0 -1
- package/dist/multiplexer/services.js.map +0 -1
- package/dist/multiplexer/session-capture.js.map +0 -1
- package/dist/multiplexer/session-launch.js.map +0 -1
- package/dist/multiplexer/session-runtime-core.js.map +0 -1
- package/dist/multiplexer/subscreens.js.map +0 -1
- package/dist/multiplexer/tool-picker.js.map +0 -1
- package/dist/multiplexer/worktree-graveyard.js.map +0 -1
- package/dist/multiplexer/worktrees.js.map +0 -1
- package/dist/notification-context.js.map +0 -1
- package/dist/notifications.js.map +0 -1
- package/dist/notify.js.map +0 -1
- package/dist/orchestration-actions.js.map +0 -1
- package/dist/orchestration-routing.js.map +0 -1
- package/dist/orchestration.js.map +0 -1
- package/dist/osc-notifications.js.map +0 -1
- package/dist/paths.js.map +0 -1
- package/dist/pending-actions.js.map +0 -1
- package/dist/plugin-runtime.js.map +0 -1
- package/dist/project-events.js.map +0 -1
- package/dist/project-scanner.js.map +0 -1
- package/dist/project-service-manifest.js.map +0 -1
- package/dist/recency.js.map +0 -1
- package/dist/recorder.js.map +0 -1
- package/dist/relay-client.js.map +0 -1
- package/dist/remote-access.js.map +0 -1
- package/dist/runtime-core/exchange-derived.js.map +0 -1
- package/dist/runtime-core/exchange-import.js.map +0 -1
- package/dist/runtime-core/exchange-store.js.map +0 -1
- package/dist/runtime-core/topology-services.js.map +0 -1
- package/dist/runtime-core/topology-sessions.js.map +0 -1
- package/dist/runtime-core/topology-store.js.map +0 -1
- package/dist/runtime-core/topology-worktrees.js.map +0 -1
- package/dist/runtime-migration.js.map +0 -1
- package/dist/session-bootstrap.js.map +0 -1
- package/dist/session-runtime.js.map +0 -1
- package/dist/session-semantics.js.map +0 -1
- package/dist/shell-args.js.map +0 -1
- package/dist/shell-hooks.js.map +0 -1
- package/dist/shell-state.js.map +0 -1
- package/dist/status-detector.js.map +0 -1
- package/dist/statusline-model.js.map +0 -1
- package/dist/task-workflow.js.map +0 -1
- package/dist/tasks.js.map +0 -1
- package/dist/team.js.map +0 -1
- package/dist/terminal-host.js.map +0 -1
- package/dist/threads.js.map +0 -1
- package/dist/tmux/doctor.js.map +0 -1
- package/dist/tmux/inbox-popup.js.map +0 -1
- package/dist/tmux/runtime-manager.js.map +0 -1
- package/dist/tmux/session-transport.js.map +0 -1
- package/dist/tmux/statusline-cache.js.map +0 -1
- package/dist/tmux/statusline.js.map +0 -1
- package/dist/tmux/switcher.js.map +0 -1
- package/dist/tmux/window-open.js.map +0 -1
- package/dist/tool-output-watchers.js.map +0 -1
- package/dist/tui/render/box.js.map +0 -1
- package/dist/tui/render/text.js.map +0 -1
- package/dist/tui/screens/dashboard-renderers.js.map +0 -1
- package/dist/tui/screens/overlay-renderers.js.map +0 -1
- package/dist/tui/screens/subscreen-renderers.js.map +0 -1
- package/dist/workflow.js.map +0 -1
- package/dist/worktree.js.map +0 -1
- package/dist-ui/_expo/static/css/web-30453ede1678c16acb08b97e83e8646d.css +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type SessionAlertDisplayContext } from "./alert-display.js";
|
|
2
2
|
import { type MessageKind } from "./threads.js";
|
|
3
3
|
import { type TaskLifecycleResult } from "./orchestration-actions.js";
|
|
4
|
+
import type { LaunchOverride } from "./shell-args.js";
|
|
4
5
|
import type { ParsedAgentOutput } from "./agent-output-parser.js";
|
|
5
6
|
import { ProjectEventBus } from "./project-events.js";
|
|
6
7
|
interface MetadataServerOptions {
|
|
@@ -204,7 +205,7 @@ interface MetadataServerOptions {
|
|
|
204
205
|
sessionId?: string;
|
|
205
206
|
worktreePath?: string;
|
|
206
207
|
open?: boolean;
|
|
207
|
-
|
|
208
|
+
launchOverride?: LaunchOverride;
|
|
208
209
|
}) => Promise<{
|
|
209
210
|
sessionId: string;
|
|
210
211
|
}> | {
|
|
@@ -242,7 +243,7 @@ interface MetadataServerOptions {
|
|
|
242
243
|
instruction?: string;
|
|
243
244
|
worktreePath?: string;
|
|
244
245
|
open?: boolean;
|
|
245
|
-
|
|
246
|
+
launchOverride?: LaunchOverride;
|
|
246
247
|
}) => Promise<{
|
|
247
248
|
sessionId: string;
|
|
248
249
|
threadId: string;
|
|
@@ -297,6 +298,16 @@ interface MetadataServerOptions {
|
|
|
297
298
|
status: "graveyard";
|
|
298
299
|
previousStatus: "running" | "offline";
|
|
299
300
|
};
|
|
301
|
+
recordBackendSessionId?: (input: {
|
|
302
|
+
sessionId: string;
|
|
303
|
+
backendSessionId: string;
|
|
304
|
+
}) => Promise<{
|
|
305
|
+
sessionId: string;
|
|
306
|
+
backendSessionId: string;
|
|
307
|
+
}> | {
|
|
308
|
+
sessionId: string;
|
|
309
|
+
backendSessionId: string;
|
|
310
|
+
};
|
|
300
311
|
sendAgentInput?: (input: {
|
|
301
312
|
sessionId: string;
|
|
302
313
|
text: string;
|
package/dist/metadata-server.js
CHANGED
|
@@ -3,6 +3,7 @@ import { createHash, randomUUID } from "node:crypto";
|
|
|
3
3
|
import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import { getDashboardClientUiStatePath, getPlansDir, getProjectId, getProjectStateDir } from "./paths.js";
|
|
6
|
+
import { writeJsonAtomic } from "./atomic-write.js";
|
|
6
7
|
import { updateSessionMetadata, clearSessionLogs, saveMetadataEndpoint, loadMetadataState, } from "./metadata-store.js";
|
|
7
8
|
import { contextualizeAlertInput, mergeDisplayContext, metadataDisplayContext, } from "./alert-display.js";
|
|
8
9
|
import { notifyAlert } from "./notify.js";
|
|
@@ -16,7 +17,7 @@ import { readAllTasks, readTask } from "./tasks.js";
|
|
|
16
17
|
import { buildWorkflowEntries } from "./workflow.js";
|
|
17
18
|
import { markLastUsed } from "./last-used.js";
|
|
18
19
|
import { formatRelativeRecency } from "./recency.js";
|
|
19
|
-
import { getAttachment, getAttachmentContent } from "./attachment-store.js";
|
|
20
|
+
import { createUploadedAttachment, getAttachment, getAttachmentContent, getAttachmentRecord, } from "./attachment-store.js";
|
|
20
21
|
import { ProjectEventBus } from "./project-events.js";
|
|
21
22
|
import { getProjectServiceManifest } from "./project-service-manifest.js";
|
|
22
23
|
import { applyShellStateTransition } from "./shell-state.js";
|
|
@@ -78,7 +79,7 @@ function persistDashboardClientPreference(clientSession, update) {
|
|
|
78
79
|
}
|
|
79
80
|
catch { }
|
|
80
81
|
update(snapshot);
|
|
81
|
-
|
|
82
|
+
writeJsonAtomic(path, snapshot);
|
|
82
83
|
}
|
|
83
84
|
function persistDashboardReturnSelection(tmux, projectRoot, currentClientSession, currentWindowId) {
|
|
84
85
|
persistDashboardClientPreference(currentClientSession, (snapshot) => {
|
|
@@ -177,6 +178,16 @@ function sendBytes(res, status, body, mimeType) {
|
|
|
177
178
|
res.setHeader("connection", "close");
|
|
178
179
|
res.end(body);
|
|
179
180
|
}
|
|
181
|
+
function formatAgentInputWithAttachments(text, attachments) {
|
|
182
|
+
const trimmedText = text.trim();
|
|
183
|
+
if (attachments.length === 0)
|
|
184
|
+
return text;
|
|
185
|
+
const body = trimmedText || "Please review the attached image file(s).";
|
|
186
|
+
const attachmentLines = attachments.map((attachment) => {
|
|
187
|
+
return `- ${attachment.filename} (${attachment.mimeType}, ${attachment.sizeBytes} bytes): ${attachment.contentPath}`;
|
|
188
|
+
});
|
|
189
|
+
return `${body}\n\nAttached image files:\n${attachmentLines.join("\n")}`;
|
|
190
|
+
}
|
|
180
191
|
function sendSseEvent(res, event, data) {
|
|
181
192
|
res.write(`event: ${event}\n`);
|
|
182
193
|
res.write(`data: ${JSON.stringify(data)}\n\n`);
|
|
@@ -1937,6 +1948,17 @@ export class MetadataServer {
|
|
|
1937
1948
|
send(res, 200, { ok: true, ...result });
|
|
1938
1949
|
return;
|
|
1939
1950
|
}
|
|
1951
|
+
if (req.method === "POST" && url.pathname === "/agents/record-backend-session") {
|
|
1952
|
+
const body = (await readJson(req));
|
|
1953
|
+
if (!this.options.lifecycle?.recordBackendSessionId) {
|
|
1954
|
+
send(res, 501, { ok: false, error: "backend session recording not supported by this service" });
|
|
1955
|
+
return;
|
|
1956
|
+
}
|
|
1957
|
+
const result = await this.options.lifecycle.recordBackendSessionId(body);
|
|
1958
|
+
this.options.onChange?.();
|
|
1959
|
+
send(res, 200, { ok: true, ...result });
|
|
1960
|
+
return;
|
|
1961
|
+
}
|
|
1940
1962
|
if (req.method === "POST" && url.pathname === "/agents/interrupt") {
|
|
1941
1963
|
const body = (await readJson(req));
|
|
1942
1964
|
if (!this.options.lifecycle?.interruptAgent) {
|
|
@@ -1989,19 +2011,53 @@ export class MetadataServer {
|
|
|
1989
2011
|
return;
|
|
1990
2012
|
}
|
|
1991
2013
|
const text = typeof body.text === "string" ? body.text : "";
|
|
1992
|
-
|
|
2014
|
+
const attachmentIds = Array.isArray(body.attachmentIds)
|
|
2015
|
+
? body.attachmentIds
|
|
2016
|
+
.filter((id) => typeof id === "string")
|
|
2017
|
+
.map((id) => id.trim())
|
|
2018
|
+
.filter(Boolean)
|
|
2019
|
+
: [];
|
|
2020
|
+
if (!text.trim() && attachmentIds.length === 0) {
|
|
1993
2021
|
send(res, 400, { ok: false, error: "text is required" });
|
|
1994
2022
|
return;
|
|
1995
2023
|
}
|
|
2024
|
+
const attachments = attachmentIds.map((id) => getAttachmentRecord(id));
|
|
2025
|
+
const missingAttachmentId = attachmentIds.find((_, index) => attachments[index] === null);
|
|
2026
|
+
if (missingAttachmentId) {
|
|
2027
|
+
send(res, 400, { ok: false, error: `attachment not found: ${missingAttachmentId}` });
|
|
2028
|
+
return;
|
|
2029
|
+
}
|
|
1996
2030
|
if (!this.options.lifecycle?.sendAgentInput) {
|
|
1997
2031
|
send(res, 501, { ok: false, error: "agent input not supported by this service" });
|
|
1998
2032
|
return;
|
|
1999
2033
|
}
|
|
2000
|
-
const
|
|
2034
|
+
const formattedText = formatAgentInputWithAttachments(text, attachments.filter((entry) => !!entry));
|
|
2035
|
+
const result = await this.options.lifecycle.sendAgentInput({ sessionId, text: formattedText });
|
|
2001
2036
|
this.options.onChange?.();
|
|
2002
2037
|
send(res, 200, { ok: true, ...result });
|
|
2003
2038
|
return;
|
|
2004
2039
|
}
|
|
2040
|
+
if (req.method === "POST" && url.pathname === "/attachments") {
|
|
2041
|
+
const body = (await readJson(req));
|
|
2042
|
+
if (typeof body.filename !== "string" ||
|
|
2043
|
+
typeof body.mimeType !== "string" ||
|
|
2044
|
+
typeof body.dataBase64 !== "string") {
|
|
2045
|
+
send(res, 400, { ok: false, error: "filename, mimeType, and dataBase64 are required" });
|
|
2046
|
+
return;
|
|
2047
|
+
}
|
|
2048
|
+
try {
|
|
2049
|
+
const attachment = createUploadedAttachment({
|
|
2050
|
+
filename: body.filename,
|
|
2051
|
+
mimeType: body.mimeType,
|
|
2052
|
+
dataBase64: body.dataBase64,
|
|
2053
|
+
});
|
|
2054
|
+
send(res, 200, { ok: true, attachment });
|
|
2055
|
+
}
|
|
2056
|
+
catch (error) {
|
|
2057
|
+
send(res, 400, { ok: false, error: error instanceof Error ? error.message : "invalid attachment" });
|
|
2058
|
+
}
|
|
2059
|
+
return;
|
|
2060
|
+
}
|
|
2005
2061
|
const attachmentContentMatch = url.pathname.match(/^\/attachments\/([^/]+)\/content$/);
|
|
2006
2062
|
if (req.method === "GET" && attachmentContentMatch) {
|
|
2007
2063
|
const content = getAttachmentContent(decodeURIComponent(attachmentContentMatch[1] || ""));
|
|
@@ -2254,4 +2310,3 @@ export class MetadataServer {
|
|
|
2254
2310
|
send(res, 404, { ok: false, error: "not found" });
|
|
2255
2311
|
}
|
|
2256
2312
|
}
|
|
2257
|
-
//# sourceMappingURL=metadata-server.js.map
|
package/dist/metadata-store.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, rmSync
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, rmSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
|
-
import { writeJsonAtomic } from "./atomic-write.js";
|
|
3
|
+
import { quarantineCorruptFile, writeJsonAtomic, writeTextAtomic } from "./atomic-write.js";
|
|
4
4
|
import { getProjectStateDir, getProjectStateDirFor } from "./paths.js";
|
|
5
5
|
function ensureParent(path) {
|
|
6
6
|
mkdirSync(dirname(path), { recursive: true });
|
|
@@ -21,6 +21,7 @@ function loadJson(path, fallback) {
|
|
|
21
21
|
return JSON.parse(readFileSync(path, "utf-8"));
|
|
22
22
|
}
|
|
23
23
|
catch {
|
|
24
|
+
quarantineCorruptFile(path);
|
|
24
25
|
return fallback;
|
|
25
26
|
}
|
|
26
27
|
}
|
|
@@ -94,7 +95,7 @@ export function saveMetadataEndpoint(endpoint, projectRoot) {
|
|
|
94
95
|
saveJson(endpointPathFor(projectRoot), endpoint);
|
|
95
96
|
const textPath = endpointTextPathFor(projectRoot);
|
|
96
97
|
ensureParent(textPath);
|
|
97
|
-
|
|
98
|
+
writeTextAtomic(textPath, `http://${endpoint.host}:${endpoint.port}\n`);
|
|
98
99
|
}
|
|
99
100
|
export function removeMetadataEndpoint(projectRoot) {
|
|
100
101
|
try {
|
|
@@ -110,4 +111,3 @@ export function removeMetadataEndpoint(projectRoot) {
|
|
|
110
111
|
}
|
|
111
112
|
catch { }
|
|
112
113
|
}
|
|
113
|
-
//# sourceMappingURL=metadata-store.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AlertEvent } from "./project-events.js";
|
|
2
|
+
/**
|
|
3
|
+
* Forwards an alert that already passed desktop notification gating to the
|
|
4
|
+
* daemon, which relays it to the owner's mobile devices. Fire-and-forget: the
|
|
5
|
+
* daemon owns the single relay connection, so the project service hands off and
|
|
6
|
+
* never blocks the alert path on push delivery.
|
|
7
|
+
*/
|
|
8
|
+
export declare function forwardAlertToMobilePush(event: AlertEvent): void;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { requestDaemonJson } from "./daemon.js";
|
|
2
|
+
/**
|
|
3
|
+
* Forwards an alert that already passed desktop notification gating to the
|
|
4
|
+
* daemon, which relays it to the owner's mobile devices. Fire-and-forget: the
|
|
5
|
+
* daemon owns the single relay connection, so the project service hands off and
|
|
6
|
+
* never blocks the alert path on push delivery.
|
|
7
|
+
*/
|
|
8
|
+
export function forwardAlertToMobilePush(event) {
|
|
9
|
+
void requestDaemonJson("/internal/push", {
|
|
10
|
+
method: "POST",
|
|
11
|
+
body: JSON.stringify({
|
|
12
|
+
title: event.title || "aimux",
|
|
13
|
+
body: event.message || event.sessionId || event.kind,
|
|
14
|
+
kind: event.kind,
|
|
15
|
+
sessionId: event.sessionId,
|
|
16
|
+
projectId: event.projectId,
|
|
17
|
+
projectRoot: process.cwd(),
|
|
18
|
+
dedupeKey: event.dedupeKey,
|
|
19
|
+
}),
|
|
20
|
+
headers: { "content-type": "application/json" },
|
|
21
|
+
}).catch(() => { });
|
|
22
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface ThrottleInput {
|
|
2
|
+
dedupeKey?: string;
|
|
3
|
+
sessionId?: string;
|
|
4
|
+
kind?: string;
|
|
5
|
+
title?: string;
|
|
6
|
+
body?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* In-memory guard for outbound mobile pushes. Collapses identical alerts
|
|
10
|
+
* re-emitted within a TTL window (chatty idle/needs_input polling) and caps the
|
|
11
|
+
* push rate per session so one runaway agent cannot flood the device.
|
|
12
|
+
*/
|
|
13
|
+
export declare class MobilePushThrottle {
|
|
14
|
+
private readonly dedupeTtlMs;
|
|
15
|
+
private readonly sessionLimit;
|
|
16
|
+
private readonly sessionWindowMs;
|
|
17
|
+
private readonly now;
|
|
18
|
+
private readonly lastByKey;
|
|
19
|
+
private readonly sessionHits;
|
|
20
|
+
constructor(dedupeTtlMs?: number, sessionLimit?: number, sessionWindowMs?: number, now?: () => number);
|
|
21
|
+
allow(input: ThrottleInput): boolean;
|
|
22
|
+
private prune;
|
|
23
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const DEDUPE_TTL_MS = 60_000;
|
|
2
|
+
const SESSION_WINDOW_MS = 60_000;
|
|
3
|
+
const SESSION_LIMIT = 5;
|
|
4
|
+
/**
|
|
5
|
+
* In-memory guard for outbound mobile pushes. Collapses identical alerts
|
|
6
|
+
* re-emitted within a TTL window (chatty idle/needs_input polling) and caps the
|
|
7
|
+
* push rate per session so one runaway agent cannot flood the device.
|
|
8
|
+
*/
|
|
9
|
+
export class MobilePushThrottle {
|
|
10
|
+
dedupeTtlMs;
|
|
11
|
+
sessionLimit;
|
|
12
|
+
sessionWindowMs;
|
|
13
|
+
now;
|
|
14
|
+
lastByKey = new Map();
|
|
15
|
+
sessionHits = new Map();
|
|
16
|
+
constructor(dedupeTtlMs = DEDUPE_TTL_MS, sessionLimit = SESSION_LIMIT, sessionWindowMs = SESSION_WINDOW_MS, now = () => Date.now()) {
|
|
17
|
+
this.dedupeTtlMs = dedupeTtlMs;
|
|
18
|
+
this.sessionLimit = sessionLimit;
|
|
19
|
+
this.sessionWindowMs = sessionWindowMs;
|
|
20
|
+
this.now = now;
|
|
21
|
+
}
|
|
22
|
+
allow(input) {
|
|
23
|
+
const ts = this.now();
|
|
24
|
+
this.prune(ts);
|
|
25
|
+
const key = input.dedupeKey?.trim() || [input.sessionId, input.kind, input.title, input.body].map((p) => p ?? "").join("|");
|
|
26
|
+
const last = this.lastByKey.get(key);
|
|
27
|
+
if (last !== undefined && ts - last < this.dedupeTtlMs)
|
|
28
|
+
return false;
|
|
29
|
+
const session = input.sessionId?.trim() || "_global";
|
|
30
|
+
const hits = (this.sessionHits.get(session) ?? []).filter((t) => ts - t < this.sessionWindowMs);
|
|
31
|
+
if (hits.length >= this.sessionLimit) {
|
|
32
|
+
this.sessionHits.set(session, hits);
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
hits.push(ts);
|
|
36
|
+
this.sessionHits.set(session, hits);
|
|
37
|
+
this.lastByKey.set(key, ts);
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
prune(ts) {
|
|
41
|
+
for (const [key, t] of this.lastByKey) {
|
|
42
|
+
if (ts - t >= this.dedupeTtlMs)
|
|
43
|
+
this.lastByKey.delete(key);
|
|
44
|
+
}
|
|
45
|
+
for (const [session, hits] of this.sessionHits) {
|
|
46
|
+
const fresh = hits.filter((t) => ts - t < this.sessionWindowMs);
|
|
47
|
+
if (fresh.length === 0)
|
|
48
|
+
this.sessionHits.delete(session);
|
|
49
|
+
else
|
|
50
|
+
this.sessionHits.set(session, fresh);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -819,7 +819,7 @@ export async function startProjectServices(host) {
|
|
|
819
819
|
targetSessionId: input.sessionId,
|
|
820
820
|
targetWorktreePath: input.worktreePath,
|
|
821
821
|
open: input.open ?? false,
|
|
822
|
-
|
|
822
|
+
launchOverride: input.launchOverride,
|
|
823
823
|
}), input.sessionId
|
|
824
824
|
? buildMetadataPendingSessionSeed({
|
|
825
825
|
sessionId: input.sessionId,
|
|
@@ -862,7 +862,7 @@ export async function startProjectServices(host) {
|
|
|
862
862
|
instruction: input.instruction,
|
|
863
863
|
targetWorktreePath: input.worktreePath,
|
|
864
864
|
open: input.open ?? false,
|
|
865
|
-
|
|
865
|
+
launchOverride: input.launchOverride,
|
|
866
866
|
}), input.targetSessionId
|
|
867
867
|
? buildMetadataPendingSessionSeed({
|
|
868
868
|
sessionId: input.targetSessionId,
|
|
@@ -876,6 +876,7 @@ export async function startProjectServices(host) {
|
|
|
876
876
|
renameAgent: (input) => host.renameAgent(input.sessionId, input.label),
|
|
877
877
|
migrateAgent: (input) => withMetadataSessionPending(host, input.sessionId, "migrating", () => host.migrateAgent(input.sessionId, input.worktreePath), findDashboardSessionSeed(host, input.sessionId)),
|
|
878
878
|
killAgent: (input) => withMetadataSessionPending(host, input.sessionId, "graveyarding", () => host.sendAgentToGraveyard(input.sessionId), findDashboardSessionSeed(host, input.sessionId)),
|
|
879
|
+
recordBackendSessionId: (input) => host.recordSessionBackendSessionId(input.sessionId, input.backendSessionId),
|
|
879
880
|
sendAgentInput: (input) => host.sendAgentInput(input.sessionId, input.text),
|
|
880
881
|
readAgentOutput: (input) => host.readAgentOutput(input.sessionId, input.startLine),
|
|
881
882
|
},
|
|
@@ -935,4 +936,3 @@ async function ensureDashboardControlPlane(host) {
|
|
|
935
936
|
host.dashboardServiceRecovery = null;
|
|
936
937
|
}
|
|
937
938
|
}
|
|
938
|
-
//# sourceMappingURL=dashboard-model.js.map
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { DashboardService, DashboardSession } from "../dashboard/index.js";
|
|
2
2
|
import type { PendingServiceActionKind, PendingSessionActionKind } from "../pending-actions.js";
|
|
3
|
+
import type { LaunchOverride } from "../shell-args.js";
|
|
3
4
|
type DashboardOpsHost = any;
|
|
4
5
|
export declare function runDashboardOperation<T>(host: DashboardOpsHost, title: string, lines: string[], work: () => Promise<T> | T, errorTitle?: string): Promise<T | undefined>;
|
|
5
6
|
export declare function spawnDashboardAgentWithFeedback(host: DashboardOpsHost, input: {
|
|
6
7
|
sessionId: string;
|
|
7
8
|
tool: string;
|
|
8
9
|
worktreePath?: string;
|
|
9
|
-
|
|
10
|
+
launchOverride?: LaunchOverride;
|
|
10
11
|
}): Promise<void>;
|
|
11
12
|
export declare function forkDashboardAgentWithFeedback(host: DashboardOpsHost, input: {
|
|
12
13
|
sourceSessionId: string;
|
|
@@ -14,7 +15,7 @@ export declare function forkDashboardAgentWithFeedback(host: DashboardOpsHost, i
|
|
|
14
15
|
tool: string;
|
|
15
16
|
instruction?: string;
|
|
16
17
|
worktreePath?: string;
|
|
17
|
-
|
|
18
|
+
launchOverride?: LaunchOverride;
|
|
18
19
|
}): Promise<void>;
|
|
19
20
|
export declare function setPendingDashboardSessionAction(host: DashboardOpsHost, sessionId: string, kind: PendingSessionActionKind | null, opts?: {
|
|
20
21
|
sessionSeed?: DashboardSession;
|
|
@@ -300,7 +300,7 @@ export async function spawnDashboardAgentWithFeedback(host, input) {
|
|
|
300
300
|
tool: input.tool,
|
|
301
301
|
sessionId: input.sessionId,
|
|
302
302
|
worktreePath: input.worktreePath,
|
|
303
|
-
|
|
303
|
+
launchOverride: input.launchOverride,
|
|
304
304
|
open: false,
|
|
305
305
|
}, { timeoutMs: 10_000 });
|
|
306
306
|
},
|
|
@@ -330,7 +330,7 @@ export async function forkDashboardAgentWithFeedback(host, input) {
|
|
|
330
330
|
tool: input.tool,
|
|
331
331
|
instruction: input.instruction,
|
|
332
332
|
worktreePath: input.worktreePath,
|
|
333
|
-
|
|
333
|
+
launchOverride: input.launchOverride,
|
|
334
334
|
open: false,
|
|
335
335
|
}, { timeoutMs: 10_000 });
|
|
336
336
|
},
|
|
@@ -778,4 +778,3 @@ export async function migrateSessionWithFeedback(host, session, targetPath, targ
|
|
|
778
778
|
errorTitle: `Failed to migrate "${label}"`,
|
|
779
779
|
});
|
|
780
780
|
}
|
|
781
|
-
//# sourceMappingURL=dashboard-ops.js.map
|
|
@@ -3,6 +3,7 @@ import type { Multiplexer, SessionState } from "./index.js";
|
|
|
3
3
|
import { dashboardSessionActionDeps as dashboardSessionActionDepsImpl } from "./dashboard-ops.js";
|
|
4
4
|
import type { PendingServiceActionKind, PendingSessionActionKind } from "../pending-actions.js";
|
|
5
5
|
import type { SessionRuntime } from "../session-runtime.js";
|
|
6
|
+
import type { LaunchOverride } from "../shell-args.js";
|
|
6
7
|
export type DashboardTailMethods = {
|
|
7
8
|
forkAgent(this: Multiplexer, opts: {
|
|
8
9
|
sourceSessionId: string;
|
|
@@ -11,7 +12,7 @@ export type DashboardTailMethods = {
|
|
|
11
12
|
instruction?: string;
|
|
12
13
|
targetWorktreePath?: string;
|
|
13
14
|
open?: boolean;
|
|
14
|
-
|
|
15
|
+
launchOverride?: LaunchOverride;
|
|
15
16
|
}): Promise<{
|
|
16
17
|
sessionId: string;
|
|
17
18
|
threadId: string;
|
|
@@ -21,7 +22,7 @@ export type DashboardTailMethods = {
|
|
|
21
22
|
targetSessionId?: string;
|
|
22
23
|
targetWorktreePath?: string;
|
|
23
24
|
open?: boolean;
|
|
24
|
-
|
|
25
|
+
launchOverride?: LaunchOverride;
|
|
25
26
|
}): Promise<{
|
|
26
27
|
sessionId: string;
|
|
27
28
|
}>;
|
|
@@ -55,7 +55,7 @@ function refreshLifecycleViews(host) {
|
|
|
55
55
|
}
|
|
56
56
|
export const dashboardTailMethods = {
|
|
57
57
|
async forkAgent(opts) {
|
|
58
|
-
const result = await this.forkSessionFromSource(opts.sourceSessionId, opts.targetToolConfigKey, opts.targetSessionId, opts.instruction, opts.targetWorktreePath, opts.
|
|
58
|
+
const result = await this.forkSessionFromSource(opts.sourceSessionId, opts.targetToolConfigKey, opts.targetSessionId, opts.instruction, opts.targetWorktreePath, opts.launchOverride);
|
|
59
59
|
if (!result) {
|
|
60
60
|
throw new Error(`Unable to fork agent "${opts.sourceSessionId}"`);
|
|
61
61
|
}
|
|
@@ -71,7 +71,7 @@ export const dashboardTailMethods = {
|
|
|
71
71
|
throw new Error(`Unknown tool config: ${opts.toolConfigKey}`);
|
|
72
72
|
}
|
|
73
73
|
const sessionId = opts.targetSessionId ?? this.generateDashboardSessionId?.(tool.command);
|
|
74
|
-
const transport = this.createSession(
|
|
74
|
+
const transport = this.createSession(opts.launchOverride?.command ?? tool.command, opts.launchOverride?.args ?? tool.args, tool.preambleFlag, opts.toolConfigKey, undefined, tool.sessionIdFlag, opts.targetWorktreePath, undefined, sessionId, !opts.open, false, undefined, opts.launchOverride?.env);
|
|
75
75
|
if (opts.open) {
|
|
76
76
|
this.openLiveTmuxWindowForEntry({ id: transport.id });
|
|
77
77
|
}
|
|
@@ -378,4 +378,3 @@ export const dashboardTailMethods = {
|
|
|
378
378
|
return orderDashboardSessionsByVisualWorktree(allDash, worktreePaths, mainRepoPath);
|
|
379
379
|
},
|
|
380
380
|
};
|
|
381
|
-
//# sourceMappingURL=dashboard-tail-methods.js.map
|
|
@@ -2,6 +2,7 @@ import { closeNotificationPanel as closeNotificationPanelImpl, handleNotificatio
|
|
|
2
2
|
import { beginWorktreeRemoval as beginWorktreeRemovalImpl, finishWorktreeRemoval as finishWorktreeRemovalImpl, handleWorktreeInputKey as handleWorktreeInputKeyImpl, handleWorktreeRemoveConfirmKey as handleWorktreeRemoveConfirmKeyImpl, handleWorktreeListKey as handleWorktreeListKeyImpl, renderWorktreeInput as renderWorktreeInputImpl, renderWorktreeList as renderWorktreeListImpl, renderWorktreeRemoveConfirm as renderWorktreeRemoveConfirmImpl, showWorktreeCreatePrompt as showWorktreeCreatePromptImpl, showWorktreeList as showWorktreeListImpl, } from "./worktrees.js";
|
|
3
3
|
import { createService as createServiceImpl, removeOfflineService as removeOfflineServiceImpl, resumeOfflineService as resumeOfflineServiceImpl, resumeOfflineServiceById as resumeOfflineServiceByIdImpl, serviceLabelForCommand as serviceLabelForCommandImpl, stopService as stopServiceImpl, } from "./services.js";
|
|
4
4
|
import { derivedStatusLabel } from "../dashboard/index.js";
|
|
5
|
+
import { isDevelopmentRuntime } from "../connection-targets.js";
|
|
5
6
|
import { selectDashboardTeammates } from "../dashboard/session-registry.js";
|
|
6
7
|
import { hasRuntimeEvidence, isAttachableDashboardSessionEntry } from "../dashboard/runtime-evidence.js";
|
|
7
8
|
export const dashboardViewMethods = {
|
|
@@ -113,6 +114,7 @@ export const dashboardViewMethods = {
|
|
|
113
114
|
selectedServiceId: selectedService,
|
|
114
115
|
selectedTeammates: selectDashboardTeammates(dashTeammates, selectedSessionEntry),
|
|
115
116
|
runtimeLabel: "tmux",
|
|
117
|
+
isDevRuntime: isDevelopmentRuntime(),
|
|
116
118
|
mainCheckout: mainCheckoutInfo,
|
|
117
119
|
operationFailures: this.dashboardOperationFailuresCache ?? [],
|
|
118
120
|
worktreeRemoval: this.worktreeRemovalJob
|
|
@@ -214,4 +216,3 @@ export const dashboardViewMethods = {
|
|
|
214
216
|
handleWorktreeListKeyImpl(this, data);
|
|
215
217
|
},
|
|
216
218
|
};
|
|
217
|
-
//# sourceMappingURL=dashboard-view-methods.js.map
|
|
@@ -221,4 +221,3 @@ function compareRecencyOrCreated(left, leftLastUsedAt, right, rightLastUsedAt) {
|
|
|
221
221
|
const rightCreated = parseRecencyTimestamp(right.createdAt) ?? 0;
|
|
222
222
|
return rightCreated - leftCreated || left.id.localeCompare(right.id);
|
|
223
223
|
}
|
|
224
|
-
//# sourceMappingURL=graveyard-view-model.js.map
|
|
@@ -185,7 +185,7 @@ export declare class Multiplexer {
|
|
|
185
185
|
* Starts fresh sessions but with context from the previous conversation.
|
|
186
186
|
*/
|
|
187
187
|
restoreSessions(toolFilter?: string): Promise<number>;
|
|
188
|
-
createSession(command: string, args: string[], preambleFlag?: string[], toolConfigKey?: string, extraPreamble?: string, sessionIdFlag?: string[], worktreePath?: string, backendSessionIdOverride?: string, sessionIdOverride?: string, detachedInTmux?: boolean, suppressStartupPreamble?: boolean, team?: SessionTeamMetadata): SessionTransport;
|
|
188
|
+
createSession(command: string, args: string[], preambleFlag?: string[], toolConfigKey?: string, extraPreamble?: string, sessionIdFlag?: string[], worktreePath?: string, backendSessionIdOverride?: string, sessionIdOverride?: string, detachedInTmux?: boolean, suppressStartupPreamble?: boolean, team?: SessionTeamMetadata, launchEnv?: Record<string, string>): SessionTransport;
|
|
189
189
|
recordSessionBackendSessionId(sessionId: string, backendSessionId: string): {
|
|
190
190
|
sessionId: string;
|
|
191
191
|
backendSessionId: string;
|
|
@@ -317,8 +317,8 @@ export class Multiplexer {
|
|
|
317
317
|
async restoreSessions(toolFilter) {
|
|
318
318
|
return restoreSessionsImpl(this, toolFilter);
|
|
319
319
|
}
|
|
320
|
-
createSession(command, args, preambleFlag, toolConfigKey, extraPreamble, sessionIdFlag, worktreePath, backendSessionIdOverride, sessionIdOverride, detachedInTmux = false, suppressStartupPreamble = false, team) {
|
|
321
|
-
return createSessionImpl(this, command, args, preambleFlag, toolConfigKey, extraPreamble, sessionIdFlag, worktreePath, backendSessionIdOverride, sessionIdOverride, detachedInTmux, suppressStartupPreamble, team);
|
|
320
|
+
createSession(command, args, preambleFlag, toolConfigKey, extraPreamble, sessionIdFlag, worktreePath, backendSessionIdOverride, sessionIdOverride, detachedInTmux = false, suppressStartupPreamble = false, team, launchEnv) {
|
|
321
|
+
return createSessionImpl(this, command, args, preambleFlag, toolConfigKey, extraPreamble, sessionIdFlag, worktreePath, backendSessionIdOverride, sessionIdOverride, detachedInTmux, suppressStartupPreamble, team, launchEnv);
|
|
322
322
|
}
|
|
323
323
|
recordSessionBackendSessionId(sessionId, backendSessionId) {
|
|
324
324
|
return runtimeLifecycleMethods.recordSessionBackendSessionId.call(this, sessionId, backendSessionId);
|
|
@@ -348,7 +348,7 @@ export class Multiplexer {
|
|
|
348
348
|
handleAction(action) {
|
|
349
349
|
handleActionImpl(this, action);
|
|
350
350
|
}
|
|
351
|
-
async forkSessionFromSource(sourceSessionId, targetToolConfigKey, requestedTargetSessionId, instruction, targetWorktreePath,
|
|
351
|
+
async forkSessionFromSource(sourceSessionId, targetToolConfigKey, requestedTargetSessionId, instruction, targetWorktreePath, launchOverride) {
|
|
352
352
|
const sourceSession = this.sessions.find((session) => session.id === sourceSessionId);
|
|
353
353
|
if (!sourceSession) {
|
|
354
354
|
this.showDashboardError("Cannot fork missing session", [`Source session ${sourceSessionId} not found.`]);
|
|
@@ -402,7 +402,7 @@ export class Multiplexer {
|
|
|
402
402
|
]
|
|
403
403
|
.filter(Boolean)
|
|
404
404
|
.join("\n\n");
|
|
405
|
-
const transport = this.createSession(toolCfg.command,
|
|
405
|
+
const transport = this.createSession(launchOverride?.command ?? toolCfg.command, launchOverride?.args ?? toolCfg.args, toolCfg.preambleFlag, targetToolConfigKey, extraPreamble, toolCfg.sessionIdFlag, targetWorktree, undefined, targetSessionId, !toolCfg.preambleFlag, false, undefined, launchOverride?.env);
|
|
406
406
|
this.agentTracker.emit(sourceSessionId, {
|
|
407
407
|
kind: "status",
|
|
408
408
|
message: `Forked ${targetSessionId} from this session`,
|
|
@@ -460,4 +460,3 @@ export class Multiplexer {
|
|
|
460
460
|
}
|
|
461
461
|
}
|
|
462
462
|
Object.assign(Multiplexer.prototype, dashboardInteractionMethods, dashboardViewMethods, dashboardActionMethods, dashboardTailMethods, persistenceMethods, dashboardStateMethods, agentIoMethods, runtimeLifecycleMethods);
|
|
463
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -5,6 +5,7 @@ import { addDashboardOperationFailure, clearDashboardOperationFailures, listDash
|
|
|
5
5
|
import { composeDashboardWorktreeGroups } from "./dashboard-model.js";
|
|
6
6
|
import { loadDaemonInfo } from "../daemon.js";
|
|
7
7
|
import { getProjectStateDir, getStatePath } from "../paths.js";
|
|
8
|
+
import { writeJsonAtomic } from "../atomic-write.js";
|
|
8
9
|
import { loadMetadataState } from "../metadata-store.js";
|
|
9
10
|
import { createRuntimeExchangeStore } from "../runtime-core/exchange-store.js";
|
|
10
11
|
import { renderCurrentDashboardView as renderCurrentDashboardViewImpl } from "./runtime-state.js";
|
|
@@ -855,7 +856,7 @@ function removePersistedServicesForWorktree(path) {
|
|
|
855
856
|
const nextServices = (state.services ?? []).filter((service) => service.worktreePath !== path);
|
|
856
857
|
if (nextServices.length === (state.services ?? []).length)
|
|
857
858
|
return;
|
|
858
|
-
|
|
859
|
+
writeJsonAtomic(statePath, { ...state, services: nextServices });
|
|
859
860
|
}
|
|
860
861
|
catch { }
|
|
861
862
|
}
|
|
@@ -874,4 +875,3 @@ function markLifecycleUsed(host, itemId) {
|
|
|
874
875
|
}
|
|
875
876
|
catch { }
|
|
876
877
|
}
|
|
877
|
-
//# sourceMappingURL=persistence-methods.js.map
|
|
@@ -4,6 +4,7 @@ import { join } from "node:path";
|
|
|
4
4
|
import { closeDebug, debug } from "../debug.js";
|
|
5
5
|
import { loadConfig } from "../config.js";
|
|
6
6
|
import { getStatePath } from "../paths.js";
|
|
7
|
+
import { quarantineCorruptFile, writeJsonAtomic } from "../atomic-write.js";
|
|
7
8
|
import { buildAimuxAgentInstructions } from "../session-bootstrap.js";
|
|
8
9
|
import { listTopologySessionStates, saveRuntimeTopologySessions } from "../runtime-core/topology-sessions.js";
|
|
9
10
|
import { adjustAfterRemove as adjustAfterRemoveImpl, buildLiveServiceStates as buildLiveServiceStatesImpl, evictZombieSession as evictZombieSessionImpl, graveyardSession as graveyardSessionImpl, isSessionRuntimeLive as isSessionRuntimeLiveImpl, loadOfflineServices as loadOfflineServicesImpl, loadOfflineTopologySessions as loadOfflineTopologySessionsImpl, restoreTmuxSessionsFromTopology as restoreTmuxSessionsFromTopologyImpl, recordSessionBackendSessionId as recordSessionBackendSessionIdImpl, resumeOfflineSession as resumeOfflineSessionImpl, startHeartbeat as startHeartbeatImpl, startProjectServiceRefresh as startProjectServiceRefreshImpl, startStatusRefresh as startStatusRefreshImpl, stopHeartbeat as stopHeartbeatImpl, stopProjectServiceRefresh as stopProjectServiceRefreshImpl, stopSessionToOffline as stopSessionToOfflineImpl, stopStatusRefresh as stopStatusRefreshImpl, syncSessionsFromTopology as syncSessionsFromTopologyImpl, } from "./runtime-state.js";
|
|
@@ -92,6 +93,7 @@ export function loadStateStatic() {
|
|
|
92
93
|
};
|
|
93
94
|
}
|
|
94
95
|
catch {
|
|
96
|
+
quarantineCorruptFile(statePath);
|
|
95
97
|
return null;
|
|
96
98
|
}
|
|
97
99
|
}
|
|
@@ -261,7 +263,9 @@ export const runtimeLifecycleMethods = {
|
|
|
261
263
|
});
|
|
262
264
|
mergedServices = [...otherServices, ...myServices];
|
|
263
265
|
}
|
|
264
|
-
catch {
|
|
266
|
+
catch {
|
|
267
|
+
quarantineCorruptFile(statePath);
|
|
268
|
+
}
|
|
265
269
|
}
|
|
266
270
|
saveRuntimeTopologySessions({ sessions: mergedSessions });
|
|
267
271
|
unpreservedExitedIds.clear();
|
|
@@ -270,7 +274,7 @@ export const runtimeLifecycleMethods = {
|
|
|
270
274
|
cwd: process.cwd(),
|
|
271
275
|
services: mergedServices,
|
|
272
276
|
};
|
|
273
|
-
|
|
277
|
+
writeJsonAtomic(statePath, state);
|
|
274
278
|
this.invalidateDesktopStateSnapshot();
|
|
275
279
|
},
|
|
276
280
|
teardown() {
|
|
@@ -324,4 +328,3 @@ export const runtimeLifecycleMethods = {
|
|
|
324
328
|
process.exit(0);
|
|
325
329
|
},
|
|
326
330
|
};
|
|
327
|
-
//# sourceMappingURL=runtime-lifecycle-methods.js.map
|