aimux-cli 0.1.16 → 0.1.19
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 +184 -67
- package/bin/aimux-dev +10 -0
- package/dist/agent-events.js +0 -1
- package/dist/agent-output-parser.js +0 -1
- 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.d.ts +21 -0
- package/dist/alert-display.js +85 -0
- package/dist/atomic-write.js +0 -1
- package/dist/attachment-store.d.ts +0 -7
- package/dist/attachment-store.js +2 -87
- package/dist/builtin-metadata-watchers.js +4 -5
- package/dist/claude-hooks.d.ts +1 -0
- package/dist/claude-hooks.js +25 -1
- package/dist/config.d.ts +19 -13
- package/dist/config.js +28 -15
- package/dist/connection-targets.d.ts +8 -0
- package/dist/connection-targets.js +27 -0
- package/dist/context/compactor.js +0 -1
- package/dist/context/context-bridge.js +0 -1
- package/dist/context/context-file.js +0 -1
- package/dist/context/history.js +0 -1
- package/dist/credentials.d.ts +12 -0
- package/dist/credentials.js +48 -0
- package/dist/daemon.d.ts +23 -0
- package/dist/daemon.js +391 -67
- package/dist/dashboard/command-spec.js +0 -1
- package/dist/dashboard/feedback.js +0 -1
- package/dist/dashboard/index.d.ts +13 -10
- package/dist/dashboard/index.js +3 -27
- package/dist/dashboard/operation-failures.js +0 -1
- package/dist/dashboard/order.d.ts +22 -0
- package/dist/dashboard/order.js +54 -0
- package/dist/dashboard/pending-actions.d.ts +39 -10
- package/dist/dashboard/pending-actions.js +166 -37
- package/dist/dashboard/quick-jump.d.ts +2 -1
- package/dist/dashboard/quick-jump.js +7 -5
- package/dist/dashboard/runtime-evidence.js +0 -1
- package/dist/dashboard/session-actions.d.ts +4 -4
- package/dist/dashboard/session-actions.js +1 -2
- package/dist/dashboard/session-registry.d.ts +4 -3
- package/dist/dashboard/session-registry.js +16 -51
- package/dist/dashboard/sort.js +0 -1
- package/dist/dashboard/state.d.ts +1 -1
- package/dist/dashboard/state.js +0 -1
- package/dist/dashboard/targets.js +0 -1
- package/dist/dashboard/ui-state-store.d.ts +16 -1
- package/dist/dashboard/ui-state-store.js +73 -3
- package/dist/debug-state.d.ts +97 -0
- package/dist/debug-state.js +540 -0
- package/dist/debug.d.ts +38 -0
- package/dist/debug.js +219 -16
- package/dist/default-plugins/gh-pr-context.d.ts +2 -1
- package/dist/default-plugins/gh-pr-context.js +17 -12
- package/dist/default-plugins/transcript-length.js +15 -3
- package/dist/fast-control.js +37 -20
- package/dist/hotkeys.js +0 -1
- package/dist/http-client.js +31 -3
- package/dist/key-parser.js +0 -1
- package/dist/last-used.js +0 -1
- package/dist/local-ui-server.d.ts +22 -0
- package/dist/local-ui-server.js +185 -0
- package/dist/login-flow.d.ts +7 -0
- package/dist/login-flow.js +119 -0
- package/dist/main.js +821 -152
- package/dist/managed-launch-env.js +14 -1
- package/dist/metadata-server.d.ts +36 -36
- package/dist/metadata-server.js +638 -138
- package/dist/metadata-store.d.ts +4 -1
- package/dist/metadata-store.js +30 -3
- package/dist/multiplexer/agent-io-methods.d.ts +2 -10
- package/dist/multiplexer/agent-io-methods.js +12 -44
- package/dist/multiplexer/archives.js +8 -10
- package/dist/multiplexer/dashboard-actions-methods.js +0 -1
- package/dist/multiplexer/dashboard-control.js +45 -14
- package/dist/multiplexer/dashboard-interaction.d.ts +8 -2
- package/dist/multiplexer/dashboard-interaction.js +187 -29
- package/dist/multiplexer/dashboard-model.d.ts +10 -3
- package/dist/multiplexer/dashboard-model.js +417 -36
- package/dist/multiplexer/dashboard-ops.d.ts +9 -7
- package/dist/multiplexer/dashboard-ops.js +178 -69
- package/dist/multiplexer/dashboard-state-methods.d.ts +2 -1
- package/dist/multiplexer/dashboard-state-methods.js +3 -3
- package/dist/multiplexer/dashboard-tail-methods.d.ts +22 -10
- package/dist/multiplexer/dashboard-tail-methods.js +164 -48
- package/dist/multiplexer/dashboard-view-methods.d.ts +1 -1
- package/dist/multiplexer/dashboard-view-methods.js +23 -9
- package/dist/multiplexer/graveyard-view-model.d.ts +9 -1
- package/dist/multiplexer/graveyard-view-model.js +39 -1
- package/dist/multiplexer/index.d.ts +15 -12
- package/dist/multiplexer/index.js +64 -44
- package/dist/multiplexer/navigation.js +0 -1
- package/dist/multiplexer/notifications.js +107 -25
- package/dist/multiplexer/persistence-methods.d.ts +31 -4
- package/dist/multiplexer/persistence-methods.js +304 -309
- package/dist/multiplexer/runtime-lifecycle-methods.d.ts +8 -10
- package/dist/multiplexer/runtime-lifecycle-methods.js +104 -87
- package/dist/multiplexer/runtime-state.d.ts +8 -10
- package/dist/multiplexer/runtime-state.js +82 -146
- package/dist/multiplexer/runtime-sync.d.ts +2 -10
- package/dist/multiplexer/runtime-sync.js +3 -19
- package/dist/multiplexer/service-state-snapshot.d.ts +2 -4
- package/dist/multiplexer/service-state-snapshot.js +4 -52
- package/dist/multiplexer/services.d.ts +1 -0
- package/dist/multiplexer/services.js +55 -6
- package/dist/multiplexer/session-capture.d.ts +1 -0
- package/dist/multiplexer/session-capture.js +23 -0
- package/dist/multiplexer/session-launch.d.ts +4 -1
- package/dist/multiplexer/session-launch.js +152 -64
- package/dist/multiplexer/session-runtime-core.d.ts +8 -20
- package/dist/multiplexer/session-runtime-core.js +40 -136
- package/dist/multiplexer/subscreens.js +10 -4
- package/dist/multiplexer/tool-picker.js +0 -1
- package/dist/multiplexer/worktree-graveyard.d.ts +0 -1
- package/dist/multiplexer/worktree-graveyard.js +15 -17
- package/dist/multiplexer/worktrees.js +96 -41
- package/dist/notification-context.js +8 -5
- package/dist/notifications.js +163 -102
- package/dist/notify.d.ts +4 -0
- package/dist/notify.js +14 -1
- 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.d.ts +32 -7
- package/dist/paths.js +82 -59
- package/dist/pending-actions.d.ts +5 -0
- package/dist/pending-actions.js +13 -0
- package/dist/plugin-runtime.js +9 -3
- package/dist/project-events.d.ts +1 -10
- package/dist/project-events.js +0 -11
- package/dist/project-scanner.d.ts +2 -3
- package/dist/project-scanner.js +58 -130
- package/dist/project-service-manifest.d.ts +1 -3
- package/dist/project-service-manifest.js +1 -4
- package/dist/recency.js +0 -1
- package/dist/recorder.js +0 -1
- package/dist/relay-client.d.ts +30 -0
- package/dist/relay-client.js +190 -0
- package/dist/remote-access.d.ts +16 -0
- package/dist/remote-access.js +90 -0
- package/dist/runtime-core/exchange-derived.d.ts +2 -0
- package/dist/runtime-core/exchange-derived.js +153 -0
- package/dist/runtime-core/exchange-import.d.ts +24 -0
- package/dist/runtime-core/exchange-import.js +317 -0
- package/dist/runtime-core/exchange-store.d.ts +157 -0
- package/dist/runtime-core/exchange-store.js +452 -0
- package/dist/runtime-core/topology-services.d.ts +38 -0
- package/dist/runtime-core/topology-services.js +170 -0
- package/dist/runtime-core/topology-sessions.d.ts +52 -0
- package/dist/runtime-core/topology-sessions.js +238 -0
- package/dist/runtime-core/topology-store.d.ts +171 -0
- package/dist/runtime-core/topology-store.js +419 -0
- package/dist/runtime-core/topology-worktrees.d.ts +60 -0
- package/dist/runtime-core/topology-worktrees.js +199 -0
- package/dist/runtime-migration.d.ts +69 -0
- package/dist/runtime-migration.js +398 -0
- package/dist/session-bootstrap.d.ts +8 -6
- package/dist/session-bootstrap.js +51 -159
- package/dist/session-runtime.d.ts +2 -0
- package/dist/session-runtime.js +1 -1
- package/dist/session-semantics.d.ts +12 -4
- package/dist/session-semantics.js +14 -1
- package/dist/shell-args.js +0 -1
- package/dist/shell-hooks.js +32 -11
- package/dist/shell-state.d.ts +2 -0
- package/dist/shell-state.js +26 -2
- package/dist/status-detector.js +0 -1
- package/dist/statusline-model.d.ts +10 -2
- package/dist/statusline-model.js +106 -31
- package/dist/task-workflow.d.ts +6 -9
- package/dist/task-workflow.js +37 -85
- package/dist/tasks.d.ts +6 -33
- package/dist/tasks.js +46 -89
- package/dist/team.d.ts +29 -0
- package/dist/team.js +40 -1
- package/dist/terminal-host.js +0 -1
- package/dist/threads.d.ts +6 -35
- package/dist/threads.js +89 -99
- package/dist/tmux/doctor.js +0 -1
- package/dist/tmux/inbox-popup.js +37 -16
- package/dist/tmux/runtime-manager.d.ts +3 -0
- package/dist/tmux/runtime-manager.js +21 -5
- package/dist/tmux/session-transport.js +0 -1
- package/dist/tmux/statusline-cache.js +0 -1
- package/dist/tmux/statusline.js +49 -10
- package/dist/tmux/switcher.js +0 -1
- package/dist/tmux/window-open.js +1 -3
- package/dist/tool-output-watchers.d.ts +0 -18
- package/dist/tool-output-watchers.js +0 -323
- package/dist/tui/render/box.js +0 -1
- package/dist/tui/render/text.js +0 -1
- package/dist/tui/screens/dashboard-renderers.js +37 -26
- package/dist/tui/screens/overlay-renderers.d.ts +2 -0
- package/dist/tui/screens/overlay-renderers.js +37 -2
- package/dist/tui/screens/subscreen-renderers.js +7 -1
- package/dist/workflow.js +0 -1
- package/dist/worktree.js +17 -1
- package/dist-ui/_expo/static/css/web-30453ede1678c16acb08b97e83e8646d.css +1 -0
- package/dist-ui/_expo/static/js/web/entry-477c745b2adc79367a4380ecf07d9ff6.js +14620 -0
- package/dist-ui/assets/assets/images/icon.a5413dcd2e811c9f2317d01a28118d8a.png +0 -0
- package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/back-icon-mask.0a328cd9c1afd0afe8e3b1ec5165b1b4.png +0 -0
- package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/back-icon.35ba0eaec5a4f5ed12ca16fabeae451d.png +0 -0
- package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55.png +0 -0
- package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@2x.png +0 -0
- package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@3x.png +0 -0
- package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@4x.png +0 -0
- package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7.png +0 -0
- package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@2x.png +0 -0
- package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@3x.png +0 -0
- package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@4x.png +0 -0
- package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/search-icon.286d67d3f74808a60a78d3ebf1a5fb57.png +0 -0
- package/dist-ui/assets/node_modules/expo-router/assets/arrow_down.017bc6ba3fc25503e5eb5e53826d48a8.png +0 -0
- package/dist-ui/assets/node_modules/expo-router/assets/error.d1ea1496f9057eb392d5bbf3732a61b7.png +0 -0
- package/dist-ui/assets/node_modules/expo-router/assets/file.19eeb73b9593a38f8e9f418337fc7d10.png +0 -0
- package/dist-ui/assets/node_modules/expo-router/assets/forward.d8b800c443b8972542883e0b9de2bdc6.png +0 -0
- package/dist-ui/assets/node_modules/expo-router/assets/pkg.ab19f4cbc543357183a20571f68380a3.png +0 -0
- package/dist-ui/assets/node_modules/expo-router/assets/sitemap.412dd9275b6b48ad28f5e3d81bb1f626.png +0 -0
- package/dist-ui/assets/node_modules/expo-router/assets/unmatched.20e71bdf79e3a97bf55fd9e164041578.png +0 -0
- package/dist-ui/favicon.ico +0 -0
- package/dist-ui/index.html +38 -0
- package/dist-ui/metadata.json +1 -0
- package/package.json +29 -12
- package/dist/agent-events.js.map +0 -1
- package/dist/agent-message-parts.d.ts +0 -17
- package/dist/agent-message-parts.js +0 -31
- package/dist/agent-message-parts.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/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/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/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/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.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/instance-directory.d.ts +0 -32
- package/dist/instance-directory.js +0 -82
- package/dist/instance-directory.js.map +0 -1
- package/dist/instance-registry.d.ts +0 -39
- package/dist/instance-registry.js +0 -208
- package/dist/instance-registry.js.map +0 -1
- package/dist/key-parser.js.map +0 -1
- package/dist/last-used.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-actions.d.ts +0 -40
- package/dist/multiplexer/session-actions.js +0 -110
- package/dist/multiplexer/session-actions.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-dispatcher.d.ts +0 -25
- package/dist/orchestration-dispatcher.js +0 -59
- package/dist/orchestration-dispatcher.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/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/session-bootstrap.js.map +0 -1
- package/dist/session-input-operations.d.ts +0 -19
- package/dist/session-input-operations.js +0 -46
- package/dist/session-input-operations.js.map +0 -1
- package/dist/session-message-history.d.ts +0 -27
- package/dist/session-message-history.js +0 -105
- package/dist/session-message-history.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-dispatcher.d.ts +0 -64
- package/dist/task-dispatcher.js +0 -213
- package/dist/task-dispatcher.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/statusline-model.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { basename } from "node:path";
|
|
2
2
|
import { sessionSemanticCompactHint } from "./session-semantics.js";
|
|
3
|
+
import { compareTeammateSessions, isTeammateSession } from "./team.js";
|
|
3
4
|
function isAutogeneratedSessionLabel(session) {
|
|
4
5
|
const label = session.label?.trim().toLowerCase();
|
|
5
6
|
const tool = session.tool?.trim().toLowerCase();
|
|
@@ -8,6 +9,11 @@ function isAutogeneratedSessionLabel(session) {
|
|
|
8
9
|
return label === tool || label.startsWith(`${tool}-`);
|
|
9
10
|
}
|
|
10
11
|
export function compactSessionTitle(session) {
|
|
12
|
+
if (session.kind === "service") {
|
|
13
|
+
const command = session.launchCommandLine?.trim();
|
|
14
|
+
if (command)
|
|
15
|
+
return command;
|
|
16
|
+
}
|
|
11
17
|
const base = session.kind === "service"
|
|
12
18
|
? session.label?.trim() || session.tool || "service"
|
|
13
19
|
: !isAutogeneratedSessionLabel(session) && session.label?.trim()
|
|
@@ -42,12 +48,27 @@ function isWithinPath(path, root) {
|
|
|
42
48
|
}
|
|
43
49
|
function resolveScopedWorktreePath(data, projectRoot, currentPath) {
|
|
44
50
|
const normalizedCurrentPath = normalizePath(currentPath, projectRoot);
|
|
45
|
-
const candidates = (data.sessions ?? [])
|
|
51
|
+
const candidates = [...(data.sessions ?? []), ...(data.teammates ?? [])]
|
|
46
52
|
.map((session) => normalizePath(session.worktreePath, projectRoot))
|
|
47
53
|
.filter((worktreePath) => isWithinPath(normalizedCurrentPath, worktreePath))
|
|
48
54
|
.sort((left, right) => right.length - left.length);
|
|
49
55
|
return candidates[0] ?? normalizedCurrentPath;
|
|
50
56
|
}
|
|
57
|
+
function allStatuslineSessions(data) {
|
|
58
|
+
return [...(data.sessions ?? []), ...(data.teammates ?? [])];
|
|
59
|
+
}
|
|
60
|
+
export function findStatuslineSession(data, sessionId) {
|
|
61
|
+
if (!sessionId)
|
|
62
|
+
return undefined;
|
|
63
|
+
return allStatuslineSessions(data).find((session) => session.id === sessionId);
|
|
64
|
+
}
|
|
65
|
+
function sessionsMatchingScopedWindow(sessions, scopedWorktreePath, currentWindow, projectRoot) {
|
|
66
|
+
return sessions.filter((session) => {
|
|
67
|
+
if (normalizePath(session.worktreePath, projectRoot) !== scopedWorktreePath)
|
|
68
|
+
return false;
|
|
69
|
+
return session.windowName === currentWindow || session.label === currentWindow || session.tool === currentWindow;
|
|
70
|
+
});
|
|
71
|
+
}
|
|
51
72
|
export function sessionIdentity(session) {
|
|
52
73
|
return compactSessionTitle(session);
|
|
53
74
|
}
|
|
@@ -87,7 +108,7 @@ export function currentPathContext(currentPath) {
|
|
|
87
108
|
};
|
|
88
109
|
}
|
|
89
110
|
export function resolveCurrentSessionId(data, currentSession, currentWindow, currentWindowId, currentPath, projectRoot) {
|
|
90
|
-
const sessions = data
|
|
111
|
+
const sessions = allStatuslineSessions(data);
|
|
91
112
|
if (currentWindowId) {
|
|
92
113
|
const byWindow = sessions.find((session) => session.tmuxWindowId === currentWindowId);
|
|
93
114
|
if (byWindow?.id)
|
|
@@ -95,18 +116,17 @@ export function resolveCurrentSessionId(data, currentSession, currentWindow, cur
|
|
|
95
116
|
}
|
|
96
117
|
if (currentWindow && projectRoot) {
|
|
97
118
|
const scopedWorktreePath = resolveScopedWorktreePath(data, projectRoot, currentPath);
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
return byScopedWindow.id;
|
|
119
|
+
const visibleMatch = sessionsMatchingScopedWindow(data.sessions ?? [], scopedWorktreePath, currentWindow, projectRoot)[0];
|
|
120
|
+
if (visibleMatch?.id)
|
|
121
|
+
return visibleMatch.id;
|
|
122
|
+
const teammateMatch = sessionsMatchingScopedWindow(data.teammates ?? [], scopedWorktreePath, currentWindow, projectRoot)[0];
|
|
123
|
+
if (teammateMatch?.id)
|
|
124
|
+
return teammateMatch.id;
|
|
105
125
|
}
|
|
106
126
|
return data.sessions?.find((session) => session.active)?.id;
|
|
107
127
|
}
|
|
108
128
|
export function resolveExactCurrentSessionId(data, currentSession, currentWindow, currentWindowId, currentPath, projectRoot) {
|
|
109
|
-
const sessions = data
|
|
129
|
+
const sessions = allStatuslineSessions(data);
|
|
110
130
|
if (currentWindowId) {
|
|
111
131
|
const byWindow = sessions.find((session) => session.tmuxWindowId === currentWindowId);
|
|
112
132
|
if (byWindow?.id)
|
|
@@ -114,33 +134,29 @@ export function resolveExactCurrentSessionId(data, currentSession, currentWindow
|
|
|
114
134
|
}
|
|
115
135
|
if (currentWindow && projectRoot) {
|
|
116
136
|
const scopedWorktreePath = resolveScopedWorktreePath(data, projectRoot, currentPath);
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
137
|
+
const visibleMatches = sessionsMatchingScopedWindow(data.sessions ?? [], scopedWorktreePath, currentWindow, projectRoot);
|
|
138
|
+
if (visibleMatches.length === 1) {
|
|
139
|
+
return visibleMatches[0]?.id;
|
|
140
|
+
}
|
|
141
|
+
if (visibleMatches.length > 1) {
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
const teammateMatches = sessionsMatchingScopedWindow(data.teammates ?? [], scopedWorktreePath, currentWindow, projectRoot);
|
|
145
|
+
if (teammateMatches.length === 1) {
|
|
146
|
+
return teammateMatches[0]?.id;
|
|
124
147
|
}
|
|
125
148
|
}
|
|
126
149
|
return undefined;
|
|
127
150
|
}
|
|
128
151
|
export function resolveScopedSessions(data, projectRoot, currentSession, currentWindow, currentWindowId, currentPath) {
|
|
129
152
|
const scopedWorktreePath = resolveScopedWorktreePath(data, projectRoot, currentPath);
|
|
130
|
-
|
|
153
|
+
const scopedSessions = (data.sessions ?? [])
|
|
131
154
|
.filter((session) => session.status !== "offline" && session.status !== "exited")
|
|
132
|
-
.filter((session) => normalizePath(session.worktreePath, projectRoot) === scopedWorktreePath)
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return leftKind - rightKind;
|
|
138
|
-
const leftIndex = left.tmuxWindowIndex ?? Number.MAX_SAFE_INTEGER;
|
|
139
|
-
const rightIndex = right.tmuxWindowIndex ?? Number.MAX_SAFE_INTEGER;
|
|
140
|
-
if (leftIndex !== rightIndex)
|
|
141
|
-
return leftIndex - rightIndex;
|
|
142
|
-
return compactSessionTitle(left).localeCompare(compactSessionTitle(right));
|
|
143
|
-
})
|
|
155
|
+
.filter((session) => normalizePath(session.worktreePath, projectRoot) === scopedWorktreePath);
|
|
156
|
+
return [
|
|
157
|
+
...scopedSessions.filter((session) => session.kind !== "service"),
|
|
158
|
+
...scopedSessions.filter((session) => session.kind === "service"),
|
|
159
|
+
]
|
|
144
160
|
.slice(0, 5)
|
|
145
161
|
.map((session) => {
|
|
146
162
|
const resolvedMetadata = data.metadata?.[session.id];
|
|
@@ -153,6 +169,66 @@ export function resolveScopedSessions(data, projectRoot, currentSession, current
|
|
|
153
169
|
};
|
|
154
170
|
});
|
|
155
171
|
}
|
|
172
|
+
export function resolveFocusedTeammate(data, projectRoot, currentSession, currentWindow, currentWindowId, currentPath) {
|
|
173
|
+
const exactCurrentSessionId = resolveExactCurrentSessionId(data, currentSession, currentWindow, currentWindowId, currentPath, projectRoot);
|
|
174
|
+
if (!exactCurrentSessionId)
|
|
175
|
+
return null;
|
|
176
|
+
const teammate = (data.teammates ?? []).find((session) => session.id === exactCurrentSessionId);
|
|
177
|
+
if (!teammate || teammate.status === "offline" || teammate.status === "exited")
|
|
178
|
+
return null;
|
|
179
|
+
const resolvedMetadata = data.metadata?.[teammate.id];
|
|
180
|
+
return {
|
|
181
|
+
...teammate,
|
|
182
|
+
derived: resolvedMetadata?.derived,
|
|
183
|
+
semantic: teammate.semantic,
|
|
184
|
+
metadata: resolvedMetadata,
|
|
185
|
+
isCurrent: true,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
export function resolveFocusedTeammateGroup(data, projectRoot, currentSession, currentWindow, currentWindowId, currentPath) {
|
|
189
|
+
const focusedTeammate = resolveFocusedTeammate(data, projectRoot, currentSession, currentWindow, currentWindowId, currentPath);
|
|
190
|
+
const parentSessionId = focusedTeammate?.team?.parentSessionId;
|
|
191
|
+
if (!focusedTeammate || !parentSessionId)
|
|
192
|
+
return [];
|
|
193
|
+
return (data.teammates ?? [])
|
|
194
|
+
.filter((session) => session.team?.parentSessionId === parentSessionId)
|
|
195
|
+
.filter((session) => session.status !== "offline" && session.status !== "exited")
|
|
196
|
+
.sort(compareTeammateSessions)
|
|
197
|
+
.slice(0, 5)
|
|
198
|
+
.map((session) => {
|
|
199
|
+
const resolvedMetadata = data.metadata?.[session.id];
|
|
200
|
+
return {
|
|
201
|
+
...session,
|
|
202
|
+
derived: resolvedMetadata?.derived,
|
|
203
|
+
semantic: session.semantic,
|
|
204
|
+
metadata: resolvedMetadata,
|
|
205
|
+
isCurrent: session.id === focusedTeammate.id,
|
|
206
|
+
};
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
export function resolveCurrentTeammates(data, projectRoot, currentSession, currentWindow, currentWindowId, currentPath) {
|
|
210
|
+
const parentSessionId = resolveExactCurrentSessionId(data, currentSession, currentWindow, currentWindowId, currentPath, projectRoot);
|
|
211
|
+
if (!parentSessionId)
|
|
212
|
+
return [];
|
|
213
|
+
const parentSession = (data.sessions ?? []).find((session) => session.id === parentSessionId);
|
|
214
|
+
if (!parentSession || isTeammateSession(parentSession))
|
|
215
|
+
return [];
|
|
216
|
+
return (data.teammates ?? [])
|
|
217
|
+
.filter((session) => session.team?.parentSessionId === parentSessionId)
|
|
218
|
+
.filter((session) => session.status !== "offline" && session.status !== "exited")
|
|
219
|
+
.sort(compareTeammateSessions)
|
|
220
|
+
.slice(0, 5)
|
|
221
|
+
.map((session) => {
|
|
222
|
+
const resolvedMetadata = data.metadata?.[session.id];
|
|
223
|
+
return {
|
|
224
|
+
...session,
|
|
225
|
+
derived: resolvedMetadata?.derived,
|
|
226
|
+
semantic: session.semantic,
|
|
227
|
+
metadata: resolvedMetadata,
|
|
228
|
+
isCurrent: false,
|
|
229
|
+
};
|
|
230
|
+
});
|
|
231
|
+
}
|
|
156
232
|
export function resolveSessionMetadata(data, projectRoot, currentSession, currentWindow, currentWindowId, currentPath) {
|
|
157
233
|
const activeSessionId = resolveCurrentSessionId(data, currentSession, currentWindow, currentWindowId, currentPath, projectRoot);
|
|
158
234
|
if (!activeSessionId)
|
|
@@ -165,4 +241,3 @@ export function resolveExactSessionMetadata(data, projectRoot, currentSession, c
|
|
|
165
241
|
return undefined;
|
|
166
242
|
return data.metadata?.[activeSessionId];
|
|
167
243
|
}
|
|
168
|
-
//# sourceMappingURL=statusline-model.js.map
|
package/dist/task-workflow.d.ts
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { type Task } from "./tasks.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
export interface TaskEvent {
|
|
3
|
+
type: "assigned" | "completed" | "failed" | "review_created" | "review_approved" | "changes_requested";
|
|
4
|
+
taskId: string;
|
|
5
|
+
sessionId: string;
|
|
6
|
+
description: string;
|
|
6
7
|
}
|
|
7
8
|
export declare class TaskWorkflow {
|
|
8
|
-
private readonly deliverPrompt;
|
|
9
|
-
constructor(deliverPrompt?: (session: DispatchSession, prompt: string) => void);
|
|
10
|
-
injectIntoSession(session: DispatchSession, task: Task): TaskEvent;
|
|
11
|
-
notifyAssigner(session: DispatchSession, task: Task): void;
|
|
12
9
|
handleCompletion(task: Task): TaskEvent[];
|
|
13
10
|
private handleReviewCompletion;
|
|
14
11
|
}
|
|
15
|
-
export
|
|
12
|
+
export declare function requestReview(agentSessionId: string, agentRole: string, diff: string | undefined, summary: string): Promise<Task | null>;
|
package/dist/task-workflow.js
CHANGED
|
@@ -1,87 +1,6 @@
|
|
|
1
1
|
import { normalizeReviewStatus, writeTask } from "./tasks.js";
|
|
2
2
|
import { loadTeamConfig } from "./team.js";
|
|
3
|
-
import { markMessageDelivered, openTaskThread, updateThread } from "./threads.js";
|
|
4
|
-
import { sendThreadMessage } from "./orchestration.js";
|
|
5
3
|
export class TaskWorkflow {
|
|
6
|
-
deliverPrompt;
|
|
7
|
-
constructor(deliverPrompt = defaultDeliverPrompt) {
|
|
8
|
-
this.deliverPrompt = deliverPrompt;
|
|
9
|
-
}
|
|
10
|
-
injectIntoSession(session, task) {
|
|
11
|
-
const thread = openTaskThread(task.id, {
|
|
12
|
-
title: `${task.type === "review" ? "Review" : "Task"}: ${task.description}`,
|
|
13
|
-
createdBy: task.assignedBy,
|
|
14
|
-
participants: [task.assignedBy, session.id],
|
|
15
|
-
kind: task.type === "review" ? "review" : "task",
|
|
16
|
-
});
|
|
17
|
-
task.threadId = thread.id;
|
|
18
|
-
const initialMessage = sendThreadMessage({
|
|
19
|
-
threadId: thread.id,
|
|
20
|
-
from: task.assignedBy,
|
|
21
|
-
to: [session.id],
|
|
22
|
-
kind: "request",
|
|
23
|
-
body: task.description,
|
|
24
|
-
metadata: { taskId: task.id },
|
|
25
|
-
});
|
|
26
|
-
markMessageDelivered(thread.id, initialMessage.message.id, session.id);
|
|
27
|
-
const prefix = task.type === "review"
|
|
28
|
-
? `[AIMUX REVIEW ${task.id} from ${task.assignedBy}]`
|
|
29
|
-
: `[AIMUX TASK ${task.id} from ${task.assignedBy}]`;
|
|
30
|
-
let prompt = `${prefix} ${task.description}\n\n`;
|
|
31
|
-
if (task.type === "review" && task.diff) {
|
|
32
|
-
prompt += `Diff to review:\n${task.diff.slice(0, 3000)}\n\n`;
|
|
33
|
-
}
|
|
34
|
-
prompt +=
|
|
35
|
-
`Run:\n` +
|
|
36
|
-
` aimux task show ${task.id}\n` +
|
|
37
|
-
` aimux thread show ${thread.id}\n\n` +
|
|
38
|
-
`Acknowledge with:\n` +
|
|
39
|
-
` aimux task accept ${task.id} --from ${session.id}\n\n` +
|
|
40
|
-
`When done, complete with:\n` +
|
|
41
|
-
` aimux task complete ${task.id} --from ${session.id} --body "<summary>"`;
|
|
42
|
-
if (task.type === "review") {
|
|
43
|
-
prompt +=
|
|
44
|
-
`\n\nFor review verdicts use:\n` +
|
|
45
|
-
` aimux review approve ${task.id} --from ${session.id} --body "<notes>"\n` +
|
|
46
|
-
` aimux review request-changes ${task.id} --from ${session.id} --body "<requested changes>"`;
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
prompt += `\n\nIf blocked, use:\n aimux task block ${task.id} --from ${session.id} --body "<reason>"`;
|
|
50
|
-
}
|
|
51
|
-
this.deliverPrompt(session, prompt);
|
|
52
|
-
task.status = "assigned";
|
|
53
|
-
task.assignedTo = session.id;
|
|
54
|
-
writeTask(task);
|
|
55
|
-
return {
|
|
56
|
-
type: "assigned",
|
|
57
|
-
taskId: task.id,
|
|
58
|
-
sessionId: session.id,
|
|
59
|
-
description: task.description,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
notifyAssigner(session, task) {
|
|
63
|
-
if (task.threadId) {
|
|
64
|
-
sendThreadMessage({
|
|
65
|
-
threadId: task.threadId,
|
|
66
|
-
from: task.assignedTo ?? task.assignedBy,
|
|
67
|
-
to: [task.assignedBy],
|
|
68
|
-
kind: task.status === "done" ? "status" : "reply",
|
|
69
|
-
body: task.status === "done"
|
|
70
|
-
? `Completed: ${task.description}${task.result ? `\n\n${task.result}` : ""}`
|
|
71
|
-
: `Failed: ${task.description}${task.error ? `\n\n${task.error}` : ""}`,
|
|
72
|
-
metadata: { taskId: task.id, status: task.status },
|
|
73
|
-
});
|
|
74
|
-
updateThread(task.threadId, (current) => ({
|
|
75
|
-
...current,
|
|
76
|
-
status: task.status === "done" ? "done" : "blocked",
|
|
77
|
-
owner: task.assignedBy,
|
|
78
|
-
waitingOn: [],
|
|
79
|
-
}));
|
|
80
|
-
}
|
|
81
|
-
this.deliverPrompt(session, `[AIMUX TASK COMPLETE ${task.id}] Agent ${task.assignedTo} finished: ${task.result ?? task.error ?? "no details"}`);
|
|
82
|
-
task.notifiedAt = new Date().toISOString();
|
|
83
|
-
writeTask(task);
|
|
84
|
-
}
|
|
85
4
|
handleCompletion(task) {
|
|
86
5
|
if (task.type === "review") {
|
|
87
6
|
return this.handleReviewCompletion(task);
|
|
@@ -164,8 +83,41 @@ export class TaskWorkflow {
|
|
|
164
83
|
];
|
|
165
84
|
}
|
|
166
85
|
}
|
|
167
|
-
function
|
|
168
|
-
|
|
169
|
-
|
|
86
|
+
export async function requestReview(agentSessionId, agentRole, diff, summary) {
|
|
87
|
+
const config = loadTeamConfig();
|
|
88
|
+
const roleConfig = config.roles[agentRole];
|
|
89
|
+
let reviewerRole = roleConfig?.reviewedBy;
|
|
90
|
+
if (!reviewerRole) {
|
|
91
|
+
const roles = Object.entries(config.roles).filter(([roleKey]) => roleKey !== agentRole);
|
|
92
|
+
const fallback = roles.find(([, role]) => role.description.toLowerCase().includes("review")) ??
|
|
93
|
+
roles.find(([, role]) => role.canEdit);
|
|
94
|
+
if (!fallback)
|
|
95
|
+
return null;
|
|
96
|
+
reviewerRole = fallback[0];
|
|
97
|
+
}
|
|
98
|
+
if (reviewerRole === agentRole) {
|
|
99
|
+
const roles = Object.entries(config.roles).filter(([roleKey]) => roleKey !== agentRole);
|
|
100
|
+
const fallback = roles.find(([, role]) => role.description.toLowerCase().includes("review")) ??
|
|
101
|
+
roles.find(([, role]) => role.canEdit);
|
|
102
|
+
if (!fallback)
|
|
103
|
+
return null;
|
|
104
|
+
reviewerRole = fallback[0];
|
|
105
|
+
}
|
|
106
|
+
const reviewTask = {
|
|
107
|
+
id: `review-manual-${Date.now().toString(36)}`,
|
|
108
|
+
status: "pending",
|
|
109
|
+
assignedBy: agentSessionId,
|
|
110
|
+
description: `Review: ${summary.slice(0, 100)}`,
|
|
111
|
+
prompt: summary,
|
|
112
|
+
createdAt: new Date().toISOString(),
|
|
113
|
+
updatedAt: new Date().toISOString(),
|
|
114
|
+
assignee: reviewerRole,
|
|
115
|
+
assigner: agentRole,
|
|
116
|
+
type: "review",
|
|
117
|
+
reviewStatus: "pending",
|
|
118
|
+
diff,
|
|
119
|
+
iteration: 1,
|
|
120
|
+
};
|
|
121
|
+
await writeTask(reviewTask);
|
|
122
|
+
return reviewTask;
|
|
170
123
|
}
|
|
171
|
-
//# sourceMappingURL=task-workflow.js.map
|
package/dist/tasks.d.ts
CHANGED
|
@@ -1,36 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import { type RuntimeExchangeTask } from "./runtime-core/exchange-store.js";
|
|
2
|
+
export type TaskStatus = RuntimeExchangeTask["status"];
|
|
2
3
|
export type ReviewStatus = "pending" | "approved" | "changes_requested";
|
|
3
4
|
export type ReviewStatusInput = ReviewStatus | "approve" | "request-changes" | "request_changes" | "changes-requested" | "changes requested";
|
|
4
|
-
export interface Task {
|
|
5
|
-
id: string;
|
|
6
|
-
status: TaskStatus;
|
|
7
|
-
assignedBy: string;
|
|
8
|
-
assignedTo?: string;
|
|
9
|
-
threadId?: string;
|
|
10
|
-
tool?: string;
|
|
11
|
-
description: string;
|
|
12
|
-
prompt: string;
|
|
13
|
-
result?: string;
|
|
14
|
-
error?: string;
|
|
15
|
-
createdAt: string;
|
|
16
|
-
updatedAt: string;
|
|
17
|
-
notifiedAt?: string;
|
|
18
|
-
/** Role name of the intended assignee (e.g. "coder", "reviewer") */
|
|
19
|
-
assignee?: string;
|
|
20
|
-
/** Role name of the task creator */
|
|
21
|
-
assigner?: string;
|
|
22
|
-
/** Task type: regular task or code review */
|
|
23
|
-
type?: "task" | "review";
|
|
24
|
-
/** Review verdict */
|
|
5
|
+
export interface Task extends Omit<RuntimeExchangeTask, "reviewStatus"> {
|
|
25
6
|
reviewStatus?: ReviewStatusInput;
|
|
26
|
-
/** Reviewer feedback text */
|
|
27
|
-
reviewFeedback?: string;
|
|
28
|
-
/** Git diff associated with the task */
|
|
29
|
-
diff?: string;
|
|
30
|
-
/** Revision iteration count (incremented on each review round-trip) */
|
|
31
|
-
iteration?: number;
|
|
32
|
-
/** ID of the task this review refers to */
|
|
33
|
-
reviewOf?: string;
|
|
34
7
|
}
|
|
35
8
|
export declare function normalizeReviewStatus(status: unknown): ReviewStatus | undefined;
|
|
36
9
|
/**
|
|
@@ -38,13 +11,13 @@ export declare function normalizeReviewStatus(status: unknown): ReviewStatus | u
|
|
|
38
11
|
*/
|
|
39
12
|
export declare function readTask(id: string): Task | undefined;
|
|
40
13
|
/**
|
|
41
|
-
* Read all tasks from the
|
|
14
|
+
* Read all tasks from the runtime exchange.
|
|
42
15
|
*/
|
|
43
16
|
export declare function readAllTasks(): Task[];
|
|
44
17
|
/**
|
|
45
|
-
* Write a task to
|
|
18
|
+
* Write a task to the runtime exchange.
|
|
46
19
|
*/
|
|
47
|
-
export declare function writeTask(task: Task):
|
|
20
|
+
export declare function writeTask(task: Task): void;
|
|
48
21
|
/**
|
|
49
22
|
* Returns true if the session has an active (assigned) task.
|
|
50
23
|
*/
|
package/dist/tasks.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import * as lockfile from "proper-lockfile";
|
|
4
|
-
import { getTasksDir } from "./paths.js";
|
|
1
|
+
import { deriveRuntimeExchangeIndexes } from "./runtime-core/exchange-derived.js";
|
|
2
|
+
import { createRuntimeExchangeStore } from "./runtime-core/exchange-store.js";
|
|
5
3
|
export function normalizeReviewStatus(status) {
|
|
6
4
|
if (!status)
|
|
7
5
|
return undefined;
|
|
@@ -17,122 +15,81 @@ export function normalizeReviewStatus(status) {
|
|
|
17
15
|
return "changes_requested";
|
|
18
16
|
return undefined;
|
|
19
17
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
|
|
18
|
+
function nowIso() {
|
|
19
|
+
return new Date().toISOString();
|
|
20
|
+
}
|
|
21
|
+
function toExchangeTask(task, updatedAt) {
|
|
22
|
+
return {
|
|
23
|
+
...task,
|
|
24
|
+
updatedAt,
|
|
25
|
+
reviewStatus: normalizeReviewStatus(task.reviewStatus),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function fromExchangeTask(task) {
|
|
29
|
+
return { ...task };
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
32
|
* Read a single task by ID.
|
|
33
33
|
*/
|
|
34
34
|
export function readTask(id) {
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return JSON.parse(readFileSync(filePath, "utf-8"));
|
|
40
|
-
}
|
|
41
|
-
catch {
|
|
42
|
-
return undefined;
|
|
43
|
-
}
|
|
35
|
+
const task = createRuntimeExchangeStore()
|
|
36
|
+
.read()
|
|
37
|
+
.tasks.find((entry) => entry.id === id);
|
|
38
|
+
return task ? fromExchangeTask(task) : undefined;
|
|
44
39
|
}
|
|
45
40
|
/**
|
|
46
|
-
* Read all tasks from the
|
|
41
|
+
* Read all tasks from the runtime exchange.
|
|
47
42
|
*/
|
|
48
43
|
export function readAllTasks() {
|
|
49
|
-
|
|
50
|
-
const tasks = [];
|
|
51
|
-
let files;
|
|
52
|
-
try {
|
|
53
|
-
files = readdirSync(dir).filter((f) => f.endsWith(".json"));
|
|
54
|
-
}
|
|
55
|
-
catch {
|
|
56
|
-
return tasks;
|
|
57
|
-
}
|
|
58
|
-
for (const file of files) {
|
|
59
|
-
try {
|
|
60
|
-
const data = readFileSync(join(dir, file), "utf-8");
|
|
61
|
-
tasks.push(JSON.parse(data));
|
|
62
|
-
}
|
|
63
|
-
catch {
|
|
64
|
-
// skip corrupt files
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return tasks;
|
|
44
|
+
return createRuntimeExchangeStore().read().tasks.map(fromExchangeTask);
|
|
68
45
|
}
|
|
69
46
|
/**
|
|
70
|
-
* Write a task to
|
|
47
|
+
* Write a task to the runtime exchange.
|
|
71
48
|
*/
|
|
72
|
-
export
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
release = await lockfile.lock(filePath, { retries: LOCK_RETRIES });
|
|
82
|
-
task.updatedAt = new Date().toISOString();
|
|
83
|
-
writeFileSync(filePath, JSON.stringify(task, null, 2) + "\n");
|
|
84
|
-
}
|
|
85
|
-
finally {
|
|
86
|
-
if (release)
|
|
87
|
-
await release();
|
|
88
|
-
}
|
|
49
|
+
export function writeTask(task) {
|
|
50
|
+
const updatedAt = nowIso();
|
|
51
|
+
createRuntimeExchangeStore().update((exchange) => deriveRuntimeExchangeIndexes({
|
|
52
|
+
...exchange,
|
|
53
|
+
generatedAt: updatedAt,
|
|
54
|
+
tasks: [...exchange.tasks.filter((existing) => existing.id !== task.id), toExchangeTask(task, updatedAt)],
|
|
55
|
+
}));
|
|
56
|
+
task.updatedAt = updatedAt;
|
|
57
|
+
task.reviewStatus = normalizeReviewStatus(task.reviewStatus);
|
|
89
58
|
}
|
|
90
59
|
/**
|
|
91
60
|
* Returns true if the session has an active (assigned) task.
|
|
92
61
|
*/
|
|
93
62
|
export function hasActiveTask(sessionId) {
|
|
94
|
-
|
|
95
|
-
return all.some((t) => ["assigned", "in_progress", "blocked"].includes(t.status) && t.assignedTo === sessionId);
|
|
63
|
+
return readAllTasks().some((task) => ["assigned", "in_progress", "blocked"].includes(task.status) && task.assignedTo === sessionId);
|
|
96
64
|
}
|
|
97
65
|
/**
|
|
98
66
|
* Remove done/failed tasks older than maxAgeMs.
|
|
99
67
|
*/
|
|
100
68
|
export function cleanupTasks(maxAgeMs) {
|
|
101
|
-
const dir = ensureTasksDir();
|
|
102
69
|
const now = Date.now();
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const task = JSON.parse(data);
|
|
114
|
-
if ((task.status === "done" || task.status === "failed") && now - new Date(task.updatedAt).getTime() > maxAgeMs) {
|
|
115
|
-
unlinkSync(join(dir, file));
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
catch {
|
|
119
|
-
// skip
|
|
120
|
-
}
|
|
121
|
-
}
|
|
70
|
+
const generatedAt = nowIso();
|
|
71
|
+
createRuntimeExchangeStore().update((exchange) => deriveRuntimeExchangeIndexes({
|
|
72
|
+
...exchange,
|
|
73
|
+
generatedAt,
|
|
74
|
+
tasks: exchange.tasks.filter((task) => {
|
|
75
|
+
if (task.status !== "done" && task.status !== "failed")
|
|
76
|
+
return true;
|
|
77
|
+
return now - new Date(task.updatedAt).getTime() <= maxAgeMs;
|
|
78
|
+
}),
|
|
79
|
+
}));
|
|
122
80
|
}
|
|
123
81
|
/**
|
|
124
82
|
* List pending review tasks assigned to a given role.
|
|
125
83
|
*/
|
|
126
84
|
export function listPendingReviews(role) {
|
|
127
|
-
return readAllTasks().filter((
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
normalizeReviewStatus(
|
|
85
|
+
return readAllTasks().filter((task) => task.type === "review" &&
|
|
86
|
+
task.assignee === role &&
|
|
87
|
+
task.status === "pending" &&
|
|
88
|
+
normalizeReviewStatus(task.reviewStatus) === "pending");
|
|
131
89
|
}
|
|
132
90
|
/**
|
|
133
91
|
* List active tasks assigned to a given role (pending or assigned, not done/failed).
|
|
134
92
|
*/
|
|
135
93
|
export function listTasksForRole(role) {
|
|
136
|
-
return readAllTasks().filter((
|
|
94
|
+
return readAllTasks().filter((task) => task.assignee === role && task.status !== "done" && task.status !== "failed");
|
|
137
95
|
}
|
|
138
|
-
//# sourceMappingURL=tasks.js.map
|
package/dist/team.d.ts
CHANGED
|
@@ -9,6 +9,35 @@ export interface TeamConfig {
|
|
|
9
9
|
roles: Record<string, RoleConfig>;
|
|
10
10
|
defaultRole: string;
|
|
11
11
|
}
|
|
12
|
+
export interface SessionTeamMetadata {
|
|
13
|
+
teamId: string;
|
|
14
|
+
parentSessionId: string;
|
|
15
|
+
role?: string;
|
|
16
|
+
label?: string;
|
|
17
|
+
order?: number;
|
|
18
|
+
}
|
|
19
|
+
export declare function isTeammateSession(session: {
|
|
20
|
+
team?: SessionTeamMetadata;
|
|
21
|
+
} | undefined): boolean;
|
|
22
|
+
export declare function compareTeammateSessions(left: {
|
|
23
|
+
id: string;
|
|
24
|
+
createdAt?: string;
|
|
25
|
+
team?: SessionTeamMetadata;
|
|
26
|
+
}, right: {
|
|
27
|
+
id: string;
|
|
28
|
+
createdAt?: string;
|
|
29
|
+
team?: SessionTeamMetadata;
|
|
30
|
+
}): number;
|
|
31
|
+
export declare function selectDirectTeammates<T extends {
|
|
32
|
+
id: string;
|
|
33
|
+
createdAt?: string;
|
|
34
|
+
team?: SessionTeamMetadata;
|
|
35
|
+
}>(sessions: T[], parentSessionId: string): T[];
|
|
36
|
+
export declare function selectOrphanTeammates<T extends {
|
|
37
|
+
id: string;
|
|
38
|
+
createdAt?: string;
|
|
39
|
+
team?: SessionTeamMetadata;
|
|
40
|
+
}>(sessions: T[], knownParentIds: Iterable<string>): T[];
|
|
12
41
|
export declare function getDefaultTeamConfig(): TeamConfig;
|
|
13
42
|
/**
|
|
14
43
|
* Load team config: project .aimux/team.json → global ~/.aimux/team.json → built-in defaults.
|