@songsid/agend 2.1.12-beta.9 → 2.2.0-alpha.1
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 +2 -2
- package/README.zh-TW.md +2 -2
- package/dist/auth/one-time-code.d.ts +19 -0
- package/dist/auth/one-time-code.js +49 -0
- package/dist/auth/one-time-code.js.map +1 -0
- package/dist/auth-api.d.ts +52 -0
- package/dist/auth-api.js +346 -0
- package/dist/auth-api.js.map +1 -0
- package/dist/backend/claude-code.d.ts +4 -0
- package/dist/backend/claude-code.js +97 -0
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/codex.js +59 -30
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/kiro-agent.d.ts +66 -0
- package/dist/backend/kiro-agent.js +302 -0
- package/dist/backend/kiro-agent.js.map +1 -0
- package/dist/backend/kiro-identity.d.ts +80 -0
- package/dist/backend/kiro-identity.js +537 -0
- package/dist/backend/kiro-identity.js.map +1 -0
- package/dist/backend/kiro-v2-store-worker.d.ts +1 -0
- package/dist/backend/kiro-v2-store-worker.js +87 -0
- package/dist/backend/kiro-v2-store-worker.js.map +1 -0
- package/dist/backend/kiro-v2-store.d.ts +54 -0
- package/dist/backend/kiro-v2-store.js +131 -0
- package/dist/backend/kiro-v2-store.js.map +1 -0
- package/dist/backend/kiro-v3-identity.d.ts +5 -0
- package/dist/backend/kiro-v3-identity.js +22 -0
- package/dist/backend/kiro-v3-identity.js.map +1 -1
- package/dist/backend/kiro.d.ts +83 -7
- package/dist/backend/kiro.js +418 -91
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/types.d.ts +45 -3
- package/dist/backend/types.js.map +1 -1
- package/dist/channel/adapters/discord.d.ts +1 -0
- package/dist/channel/adapters/discord.js +29 -10
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +1 -0
- package/dist/channel/adapters/telegram.js +13 -1
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/types.d.ts +9 -1
- package/dist/classic-channel-manager.d.ts +18 -10
- package/dist/classic-channel-manager.js +45 -18
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/cli.js +225 -127
- package/dist/cli.js.map +1 -1
- package/dist/command-table.d.ts +5 -3
- package/dist/command-table.js +29 -27
- package/dist/command-table.js.map +1 -1
- package/dist/config-validator.js +46 -0
- package/dist/config-validator.js.map +1 -1
- package/dist/config.js +12 -0
- package/dist/config.js.map +1 -1
- package/dist/connection-secrets.d.ts +6 -0
- package/dist/connection-secrets.js +4 -0
- package/dist/connection-secrets.js.map +1 -1
- package/dist/daemon.d.ts +89 -4
- package/dist/daemon.js +661 -77
- package/dist/daemon.js.map +1 -1
- package/dist/darwin-memory.d.ts +6 -1
- package/dist/darwin-memory.js +17 -6
- package/dist/darwin-memory.js.map +1 -1
- package/dist/delivery-consumed-watch.d.ts +85 -0
- package/dist/delivery-consumed-watch.js +244 -0
- package/dist/delivery-consumed-watch.js.map +1 -0
- package/dist/delivery-outbox.d.ts +61 -0
- package/dist/delivery-outbox.js +120 -2
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/delivery-reconciliation.d.ts +14 -5
- package/dist/delivery-reconciliation.js +27 -4
- package/dist/delivery-reconciliation.js.map +1 -1
- package/dist/delivery-reconciliation.test.js +35 -1
- package/dist/delivery-reconciliation.test.js.map +1 -1
- package/dist/event-loop-watch.d.ts +28 -0
- package/dist/event-loop-watch.js +75 -3
- package/dist/event-loop-watch.js.map +1 -1
- package/dist/fleet-context.d.ts +22 -2
- package/dist/fleet-level-config.d.ts +2 -2
- package/dist/fleet-level-config.js +6 -1
- package/dist/fleet-level-config.js.map +1 -1
- package/dist/fleet-manager.d.ts +293 -12
- package/dist/fleet-manager.js +2364 -449
- package/dist/fleet-manager.js.map +1 -1
- package/dist/host-memory.d.ts +4 -0
- package/dist/host-memory.js.map +1 -1
- package/dist/instance-config-impact.js +5 -0
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.d.ts +10 -5
- package/dist/instance-lifecycle.js +162 -53
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/locale.js +150 -16
- package/dist/locale.js.map +1 -1
- package/dist/login-controller.d.ts +2 -0
- package/dist/login-controller.js +17 -5
- package/dist/login-controller.js.map +1 -1
- package/dist/memory-pressure.d.ts +7 -8
- package/dist/memory-pressure.js +76 -15
- package/dist/memory-pressure.js.map +1 -1
- package/dist/monotonic-budget.d.ts +2 -0
- package/dist/monotonic-budget.js +28 -0
- package/dist/monotonic-budget.js.map +1 -0
- package/dist/needs-you-hub.d.ts +114 -0
- package/dist/needs-you-hub.js +370 -0
- package/dist/needs-you-hub.js.map +1 -0
- package/dist/needs-you-live.d.ts +116 -0
- package/dist/needs-you-live.js +228 -0
- package/dist/needs-you-live.js.map +1 -0
- package/dist/needs-you.d.ts +132 -0
- package/dist/needs-you.js +164 -0
- package/dist/needs-you.js.map +1 -0
- package/dist/node-version-guard.d.ts +30 -0
- package/dist/node-version-guard.js +50 -0
- package/dist/node-version-guard.js.map +1 -0
- package/dist/operator-control-paths.d.ts +4 -0
- package/dist/operator-control-paths.js +24 -0
- package/dist/operator-control-paths.js.map +1 -0
- package/dist/outbound-handlers.d.ts +2 -0
- package/dist/outbound-handlers.js +9 -2
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +5 -5
- package/dist/profile-control.js +4 -20
- package/dist/profile-control.js.map +1 -1
- package/dist/public-web-gateway.d.ts +18 -0
- package/dist/public-web-gateway.js +141 -0
- package/dist/public-web-gateway.js.map +1 -0
- package/dist/public-web-link.d.ts +53 -0
- package/dist/public-web-link.js +175 -0
- package/dist/public-web-link.js.map +1 -0
- package/dist/quickstart-api.d.ts +8 -1
- package/dist/quickstart-api.js +86 -48
- package/dist/quickstart-api.js.map +1 -1
- package/dist/quickstart.d.ts +1 -0
- package/dist/quickstart.js +6 -2
- package/dist/quickstart.js.map +1 -1
- package/dist/scheduler/db.d.ts +7 -1
- package/dist/scheduler/db.js +38 -0
- package/dist/scheduler/db.js.map +1 -1
- package/dist/scheduler/index.d.ts +1 -1
- package/dist/scheduler/retry-label.d.ts +11 -0
- package/dist/scheduler/retry-label.js +24 -0
- package/dist/scheduler/retry-label.js.map +1 -0
- package/dist/scheduler/scheduler.d.ts +55 -2
- package/dist/scheduler/scheduler.js +220 -8
- package/dist/scheduler/scheduler.js.map +1 -1
- package/dist/scheduler/types.d.ts +22 -0
- package/dist/scheduler/types.js.map +1 -1
- package/dist/secret-store.d.ts +5 -0
- package/dist/secret-store.js +20 -0
- package/dist/secret-store.js.map +1 -1
- package/dist/service-activation.d.ts +110 -0
- package/dist/service-activation.js +302 -0
- package/dist/service-activation.js.map +1 -0
- package/dist/service-installer.d.ts +7 -0
- package/dist/service-installer.js +7 -4
- package/dist/service-installer.js.map +1 -1
- package/dist/service-restart-selection.d.ts +6 -5
- package/dist/service-restart-selection.js +6 -5
- package/dist/service-restart-selection.js.map +1 -1
- package/dist/settings-api.d.ts +10 -2
- package/dist/settings-api.js +175 -72
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-baseline.d.ts +20 -0
- package/dist/settings-baseline.js +104 -0
- package/dist/settings-baseline.js.map +1 -0
- package/dist/settings-change.d.ts +21 -0
- package/dist/settings-change.js +133 -0
- package/dist/settings-change.js.map +1 -0
- package/dist/settings-confirmation.d.ts +105 -0
- package/dist/settings-confirmation.js +232 -0
- package/dist/settings-confirmation.js.map +1 -0
- package/dist/settings-control.d.ts +41 -0
- package/dist/settings-control.js +294 -0
- package/dist/settings-control.js.map +1 -0
- package/dist/settings-effect.d.ts +24 -0
- package/dist/settings-effect.js +169 -0
- package/dist/settings-effect.js.map +1 -0
- package/dist/settings-http-confirmation.d.ts +29 -0
- package/dist/settings-http-confirmation.js +123 -0
- package/dist/settings-http-confirmation.js.map +1 -0
- package/dist/settings-instance-patch.d.ts +4 -0
- package/dist/settings-instance-patch.js +26 -0
- package/dist/settings-instance-patch.js.map +1 -0
- package/dist/settings-request-capability.d.ts +16 -0
- package/dist/settings-request-capability.js +32 -0
- package/dist/settings-request-capability.js.map +1 -0
- package/dist/settings-transaction.d.ts +65 -0
- package/dist/settings-transaction.js +223 -0
- package/dist/settings-transaction.js.map +1 -0
- package/dist/setup-auth.d.ts +10 -18
- package/dist/setup-auth.js +14 -38
- package/dist/setup-auth.js.map +1 -1
- package/dist/setup-form.d.ts +1 -1
- package/dist/setup-form.js +75 -18
- package/dist/setup-form.js.map +1 -1
- package/dist/setup-guide.d.ts +13 -0
- package/dist/setup-guide.js +25 -0
- package/dist/setup-guide.js.map +1 -0
- package/dist/setup-host.d.ts +16 -0
- package/dist/setup-host.js +197 -32
- package/dist/setup-host.js.map +1 -1
- package/dist/setup-wizard.js +3 -0
- package/dist/setup-wizard.js.map +1 -1
- package/dist/slash-authz.d.ts +17 -3
- package/dist/slash-authz.js +5 -0
- package/dist/slash-authz.js.map +1 -1
- package/dist/spawn-gate.js +3 -3
- package/dist/spawn-gate.js.map +1 -1
- package/dist/statusline-watcher.d.ts +5 -0
- package/dist/statusline-watcher.js +2 -0
- package/dist/statusline-watcher.js.map +1 -1
- package/dist/steer-capability.d.ts +6 -0
- package/dist/steer-capability.js +8 -0
- package/dist/steer-capability.js.map +1 -1
- package/dist/sync-work-attribution.d.ts +14 -0
- package/dist/sync-work-attribution.js +43 -8
- package/dist/sync-work-attribution.js.map +1 -1
- package/dist/tips.js +10 -5
- package/dist/tips.js.map +1 -1
- package/dist/tmux-control.d.ts +35 -5
- package/dist/tmux-control.js +291 -57
- package/dist/tmux-control.js.map +1 -1
- package/dist/tmux-manager.d.ts +20 -6
- package/dist/tmux-manager.js +90 -47
- package/dist/tmux-manager.js.map +1 -1
- package/dist/tmux-read.d.ts +59 -0
- package/dist/tmux-read.js +213 -0
- package/dist/tmux-read.js.map +1 -0
- package/dist/topic-commands.d.ts +21 -10
- package/dist/topic-commands.js +191 -58
- package/dist/topic-commands.js.map +1 -1
- package/dist/transcript-delta-reader.js +2 -1
- package/dist/transcript-delta-reader.js.map +1 -1
- package/dist/tunnel/cloudflared-install.d.ts +2 -0
- package/dist/tunnel/cloudflared-install.js +1 -1
- package/dist/tunnel/cloudflared-install.js.map +1 -1
- package/dist/tunnel/purpose-lane.d.ts +14 -0
- package/dist/tunnel/purpose-lane.js +43 -0
- package/dist/tunnel/purpose-lane.js.map +1 -0
- package/dist/turn-reply-guard.d.ts +2 -0
- package/dist/turn-reply-guard.js +10 -1
- package/dist/turn-reply-guard.js.map +1 -1
- package/dist/types.d.ts +33 -0
- package/dist/ui/app.html +18 -0
- package/dist/ui/chat-render.js +478 -0
- package/dist/ui/chat-store.js +289 -0
- package/dist/ui/chat-strings.js +69 -0
- package/dist/ui/chat-thread.js +209 -0
- package/dist/ui/chat-tour.js +116 -0
- package/dist/ui/fleet-org.js +142 -0
- package/dist/ui/panel-chat.js +418 -0
- package/dist/ui/panel-fleet.js +413 -0
- package/dist/ui/panel-needs.js +202 -0
- package/dist/ui/panel-settings.js +750 -0
- package/dist/ui/preview.js +266 -0
- package/dist/ui/settings-apply.js +239 -0
- package/dist/ui/settings-confirm.js +186 -0
- package/dist/ui/settings-dialogs.js +546 -0
- package/dist/ui/settings-model.js +277 -0
- package/dist/ui/settings-strings.js +652 -0
- package/dist/ui/settings-wizard.js +140 -0
- package/dist/ui/shared/agend-auth.js +93 -0
- package/dist/ui/shared/app-ctx.js +80 -0
- package/dist/ui/shared/app-html.js +9 -0
- package/dist/ui/shared/app-i18n.js +95 -0
- package/dist/ui/shared/app-nav.js +73 -0
- package/dist/ui/shared/app-needs.js +114 -0
- package/dist/ui/shared/app-route.js +73 -0
- package/dist/ui/shared/app-session.js +66 -0
- package/dist/ui/shared/app-shell.js +344 -0
- package/dist/ui/shared/app-store.js +51 -0
- package/dist/ui/shared/app-stream.js +201 -0
- package/dist/ui/shared/app.css +676 -0
- package/dist/ui/shared/app.js +88 -0
- package/dist/ui/shared/fonts/OFL.txt +92 -0
- package/dist/ui/shared/fonts/README.md +21 -0
- package/dist/ui/shared/fonts/inter.woff2 +0 -0
- package/dist/ui/shared/htm.module.js +1 -0
- package/dist/ui/shared/panel-view.js +655 -0
- package/dist/ui/shared/preact-hooks.module.js +2 -0
- package/dist/ui/shared/preact.module.js +2 -0
- package/dist/ui/shared/signin.js +130 -0
- package/dist/ui/shared/theme.js +29 -0
- package/dist/ui/shared/tokens.css +153 -0
- package/dist/ui/shared/ui-confirm.js +43 -0
- package/dist/ui/shared/ui-dialog.js +45 -0
- package/dist/ui/shared/ui-icons.js +61 -0
- package/dist/ui/shared/ui-menu.js +39 -0
- package/dist/ui/shared/ui-states.js +20 -0
- package/dist/ui/shared/ui-toast.js +18 -0
- package/dist/ui/shared/vendor/htm.LICENSE +202 -0
- package/dist/ui/shared/vendor/preact.LICENSE +21 -0
- package/dist/ui/shared/vendor/vendor.json +39 -0
- package/dist/ui/shared/view-strings.js +309 -0
- package/dist/ui/signin.html +51 -0
- package/dist/update-check.d.ts +6 -2
- package/dist/update-check.js +12 -3
- package/dist/update-check.js.map +1 -1
- package/dist/update-install.d.ts +71 -0
- package/dist/update-install.js +162 -0
- package/dist/update-install.js.map +1 -0
- package/dist/upgrade-notices.d.ts +17 -0
- package/dist/upgrade-notices.js +93 -0
- package/dist/upgrade-notices.js.map +1 -0
- package/dist/usage/statusline-usage.d.ts +2 -0
- package/dist/usage/statusline-usage.js +14 -10
- package/dist/usage/statusline-usage.js.map +1 -1
- package/dist/view-api.d.ts +6 -1
- package/dist/view-api.js +62 -51
- package/dist/view-api.js.map +1 -1
- package/dist/web-api.d.ts +71 -14
- package/dist/web-api.js +492 -77
- package/dist/web-api.js.map +1 -1
- package/dist/web-auth.d.ts +71 -27
- package/dist/web-auth.js +169 -69
- package/dist/web-auth.js.map +1 -1
- package/dist/web-body.d.ts +3 -0
- package/dist/web-body.js +55 -0
- package/dist/web-body.js.map +1 -0
- package/dist/web-channel-echo.d.ts +9 -0
- package/dist/web-channel-echo.js +55 -0
- package/dist/web-channel-echo.js.map +1 -0
- package/dist/web-chat-history.d.ts +125 -0
- package/dist/web-chat-history.js +184 -0
- package/dist/web-chat-history.js.map +1 -0
- package/dist/web-continuation.d.ts +7 -0
- package/dist/web-continuation.js +22 -0
- package/dist/web-continuation.js.map +1 -0
- package/dist/web-host-guard.d.ts +34 -0
- package/dist/web-host-guard.js +57 -1
- package/dist/web-host-guard.js.map +1 -1
- package/dist/web-login.d.ts +72 -0
- package/dist/web-login.js +132 -0
- package/dist/web-login.js.map +1 -0
- package/dist/web-org.d.ts +55 -0
- package/dist/web-org.js +67 -0
- package/dist/web-org.js.map +1 -0
- package/dist/web-preview.d.ts +77 -0
- package/dist/web-preview.js +240 -0
- package/dist/web-preview.js.map +1 -0
- package/dist/web-request-context.d.ts +10 -0
- package/dist/web-request-context.js +13 -0
- package/dist/web-request-context.js.map +1 -0
- package/dist/web-session.d.ts +167 -0
- package/dist/web-session.js +389 -0
- package/dist/web-session.js.map +1 -0
- package/dist/web-shell-routes.d.ts +59 -0
- package/dist/web-shell-routes.js +96 -0
- package/dist/web-shell-routes.js.map +1 -0
- package/dist/web-upload.d.ts +183 -0
- package/dist/web-upload.js +468 -0
- package/dist/web-upload.js.map +1 -0
- package/dist/website-tips-renderer.d.ts +2 -2
- package/dist/website-tips-renderer.js +3 -3
- package/dist/website-tips-renderer.js.map +1 -1
- package/package.json +8 -5
- package/scripts/preinstall-guard.cjs +36 -0
- package/dist/ui/dashboard.html +0 -774
- package/dist/ui/settings.html +0 -2165
- package/dist/ui/view.html +0 -1139
package/dist/host-memory.d.ts
CHANGED
|
@@ -4,6 +4,10 @@ export interface HostMemory {
|
|
|
4
4
|
availableKind: "available" | "free" | "unknown";
|
|
5
5
|
swapTotalBytes: number | null;
|
|
6
6
|
swapFreeBytes: number | null;
|
|
7
|
+
/** Darwin kernel alarm, independent of the diagnostic RAM/swap estimates. */
|
|
8
|
+
darwinPressureLevel?: 1 | 2 | 4 | null;
|
|
9
|
+
/** Bounded diagnostic output; null when unavailable or not requested. */
|
|
10
|
+
darwinPressureRaw?: string | null;
|
|
7
11
|
}
|
|
8
12
|
interface HostMemoryDeps {
|
|
9
13
|
platform: NodeJS.Platform;
|
package/dist/host-memory.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host-memory.js","sourceRoot":"","sources":["../src/host-memory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"host-memory.js","sourceRoot":"","sources":["../src/host-memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -71,12 +71,17 @@ const INSTANCE_FIELDS = [
|
|
|
71
71
|
const CLASSIC_FIELDS = [
|
|
72
72
|
"backend", "model", "auto_pause_after", "tool_progress",
|
|
73
73
|
"reply_completion_guard", "collab", "context_lines", "pre_task_command",
|
|
74
|
+
"web_echo",
|
|
74
75
|
];
|
|
75
76
|
/**
|
|
76
77
|
* Fleet-level fields, which no per-key rule can derive: they belong to the
|
|
77
78
|
* fleet process or the channel binding rather than to an instance's config.
|
|
78
79
|
*/
|
|
79
80
|
const FLEET_FIELD_IMPACTS = {
|
|
81
|
+
"web.echo_to_channel": "now",
|
|
82
|
+
"web.public_link.allow_public": "now",
|
|
83
|
+
"web.public_link.ttl_minutes": "now",
|
|
84
|
+
"web.public_link.protocol": "now",
|
|
80
85
|
"defaults.locale": "now",
|
|
81
86
|
"fleet.channels": "fleet",
|
|
82
87
|
"fleet.channel.access.mode": "fleet",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instance-config-impact.js","sourceRoot":"","sources":["../src/instance-config-impact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAM9C,0EAA0E;AAC1E,MAAM,CAAC,MAAM,YAAY,GAA4B,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;AAElF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAsC,IAAI,GAAG,CAAuB;IACvG,eAAe;IACf,wBAAwB;IACxB,iBAAiB;IACjB,kBAAkB;IAClB,UAAU;IACV,cAAc;IACd,aAAa;IACb,MAAM;IACN,WAAW;IACX,sFAAsF;IACtF,2BAA2B;CAC5B,CAAC,CAAC;AAEH;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAwB,IAAI,GAAG,CAChE,CAAC,eAAe,EAAE,wBAAwB,CAAW;KACnD,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,wBAAwB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CACpD,CAAC;AAEF;;;GAGG;AACH,MAAM,0BAA0B,GAAwB,IAAI,GAAG,CAAC;IAC9D,UAAU;IACV,YAAY;IACZ,eAAe;CAChB,CAAC,CAAC;AAEH,wDAAwD;AACxD,MAAM,eAAe,GAAG;IACtB,cAAc,EAAE,aAAa,EAAE,SAAS,EAAE,OAAO,EAAE,mBAAmB;IACtE,kBAAkB,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,eAAe;IACzE,eAAe,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,WAAW;IACzE,cAAc,EAAE,MAAM,EAAE,eAAe,EAAE,YAAY,EAAE,UAAU;IACjE,aAAa,EAAE,gBAAgB,EAAE,QAAQ,EAAE,kBAAkB;IAC7D,0EAA0E;IAC1E,kEAAkE;IAClE,eAAe;IACf,2BAA2B;CACnB,CAAC;AAEX,2DAA2D;AAC3D,MAAM,cAAc,GAAG;IACrB,SAAS,EAAE,OAAO,EAAE,kBAAkB,EAAE,eAAe;IACvD,wBAAwB,EAAE,QAAQ,EAAE,eAAe,EAAE,kBAAkB;
|
|
1
|
+
{"version":3,"file":"instance-config-impact.js","sourceRoot":"","sources":["../src/instance-config-impact.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SettingsExecution } from "./settings-transaction.js";
|
|
1
2
|
import type { InstanceConfig, FleetConfig } from "./types.js";
|
|
2
3
|
import { RoutingEngine } from "./routing-engine.js";
|
|
3
4
|
import type { Logger } from "./logger.js";
|
|
@@ -45,6 +46,7 @@ export interface LifecycleContext {
|
|
|
45
46
|
readonly fleetConfig: FleetConfig | null;
|
|
46
47
|
readonly logger: Logger;
|
|
47
48
|
readonly dataDir: string;
|
|
49
|
+
getSettingsConfigPath?(): string;
|
|
48
50
|
readonly routing: RoutingEngine;
|
|
49
51
|
readonly instanceIpcClients: Map<string, IpcClient>;
|
|
50
52
|
readonly ipcStoppingInstances: Set<string>;
|
|
@@ -97,6 +99,8 @@ export interface LifecycleContext {
|
|
|
97
99
|
notifyInstanceTopic(name: string, text: string): boolean | void;
|
|
98
100
|
/** Notify the blocked instance and offer an interactive assist action in General. */
|
|
99
101
|
notifyInteractivePrompt(name: string, kind: string): Promise<void>;
|
|
102
|
+
/** #1386: an instance's interaction observation, pause or wake changed ("Needs you" recomputes at once, not at its tick). */
|
|
103
|
+
onAttentionChanged?(name: string): void;
|
|
100
104
|
/**
|
|
101
105
|
* Offer a one-tap re-login beside an auth alert. Optional: contexts without
|
|
102
106
|
* it (tests, lightweight fleets) still get the alert's written remedy.
|
|
@@ -159,6 +163,7 @@ export declare class SupersededStartError extends Error {
|
|
|
159
163
|
* cross-instance idle gate (60s) plus a 60s grace.
|
|
160
164
|
*/
|
|
161
165
|
export declare const PRECLAIM_LEASE_MS = 120000;
|
|
166
|
+
type Daemon = InstanceType<typeof import("./daemon.js").Daemon>;
|
|
162
167
|
/**
|
|
163
168
|
* Working directories of the fleet's other instances on `backendName` (#984):
|
|
164
169
|
* Codex consults them only to decide whether `resume --last` could take a
|
|
@@ -433,7 +438,7 @@ export declare class InstanceLifecycle {
|
|
|
433
438
|
* never an auth-deferred or operator pause.
|
|
434
439
|
*/
|
|
435
440
|
hasWorkLease(name: string, now?: number): boolean;
|
|
436
|
-
start(name: string, config: InstanceConfig, topicMode: boolean, runtimeIdentity?: FleetInstructionsParams["runtimeIdentity"], transition?: TransitionHandle): Promise<void>;
|
|
441
|
+
start(name: string, config: InstanceConfig, topicMode: boolean, runtimeIdentity?: FleetInstructionsParams["runtimeIdentity"], transition?: TransitionHandle, execution?: SettingsExecution, published?: (daemon: Daemon) => void): Promise<void>;
|
|
437
442
|
private startInTransition;
|
|
438
443
|
isPaused(name: string): boolean;
|
|
439
444
|
getLastPausedAt(name: string): number | null;
|
|
@@ -452,16 +457,16 @@ export declare class InstanceLifecycle {
|
|
|
452
457
|
* surface.
|
|
453
458
|
*/
|
|
454
459
|
static startOrDispose(daemon: {
|
|
455
|
-
start(): Promise<void>;
|
|
460
|
+
start(admission?: () => void): Promise<void>;
|
|
456
461
|
abortStartup(): Promise<void>;
|
|
457
|
-
}, name: string, logger: Logger): Promise<void>;
|
|
462
|
+
}, name: string, logger: Logger, admission?: () => void): Promise<void>;
|
|
458
463
|
/** Stop the registered daemon only if it is still `daemon` (a concurrent restart may have replaced it). */
|
|
459
464
|
stopIfCurrent(name: string, daemon: unknown): Promise<boolean>;
|
|
460
465
|
stop(name: string, transition?: TransitionHandle): Promise<void>;
|
|
461
466
|
private stopInTransition;
|
|
462
|
-
remove(name: string, authorization: ExplicitInstanceRemoval): Promise<void>;
|
|
467
|
+
remove(name: string, authorization: ExplicitInstanceRemoval, execution?: SettingsExecution, transition?: TransitionHandle): Promise<void>;
|
|
463
468
|
/** Handle create_instance tool call from a daemon. */
|
|
464
|
-
handleCreate(args: LifecycleCreateArgs, respond: (result: unknown, error?: string) => void, adapterId?: string): Promise<void>;
|
|
469
|
+
handleCreate(args: LifecycleCreateArgs, respond: (result: unknown, error?: string) => void, adapterId?: string, execution?: SettingsExecution): Promise<void>;
|
|
465
470
|
/** Handle delete_instance tool call from a daemon. */
|
|
466
471
|
handleDelete(args: LifecycleDeleteArgs, respond: (result: unknown, error?: string) => void): Promise<void>;
|
|
467
472
|
has(name: string): boolean;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { settingsUndo, undoSettingsPaths } from "./settings-transaction.js";
|
|
1
2
|
import { measureSyncWork } from "./sync-work-attribution.js";
|
|
2
3
|
import { REMOVED_BACKENDS, isRemovedBackend, removedBackendMessage } from "./backend/removed.js";
|
|
3
|
-
import { existsSync, readFileSync, mkdirSync, realpathSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { existsSync, readFileSync, mkdirSync, realpathSync, writeFileSync, statSync } from "node:fs";
|
|
4
5
|
import { ensureInstanceDir } from "./private-dir.js";
|
|
5
6
|
import { execFileSync } from "node:child_process";
|
|
6
7
|
import { join, basename, dirname, resolve, sep as pathSep } from "node:path";
|
|
@@ -822,6 +823,7 @@ export class InstanceLifecycle {
|
|
|
822
823
|
this.notifyIncident(name, "dialog_answer_ignored", text);
|
|
823
824
|
this.ctx.notifyFleetError?.(t("fleet.dialog_answer_ignored", name, data.description, String(data.attempts)));
|
|
824
825
|
}, this.ctx.logger, `daemon.dialog_answer_ignored[${name}]`));
|
|
826
|
+
daemon.on("instance_interaction", () => this.ctx.onAttentionChanged?.(name));
|
|
825
827
|
daemon.on("interactive_prompt", safeHandler(async (data) => {
|
|
826
828
|
this.ctx.eventLog?.insert(name, "interactive_prompt", { kind: data.kind });
|
|
827
829
|
this.ctx.logger.warn({ name, kind: data.kind, prompt: data.prompt }, "Instance is waiting for interactive terminal input");
|
|
@@ -1159,11 +1161,14 @@ export class InstanceLifecycle {
|
|
|
1159
1161
|
return false;
|
|
1160
1162
|
return outbox.countForTarget(name, ["queued", "retry_wait"]) > 0;
|
|
1161
1163
|
}
|
|
1162
|
-
async start(name, config, topicMode, runtimeIdentity, transition) {
|
|
1163
|
-
return this.runTransition(name, () => this.startInTransition(name, config, topicMode, runtimeIdentity), transition);
|
|
1164
|
+
async start(name, config, topicMode, runtimeIdentity, transition, execution, published) {
|
|
1165
|
+
return this.runTransition(name, () => this.startInTransition(name, config, topicMode, runtimeIdentity, execution, published), transition);
|
|
1164
1166
|
}
|
|
1165
|
-
async startInTransition(name, config, topicMode, runtimeIdentity) {
|
|
1167
|
+
async startInTransition(name, config, topicMode, runtimeIdentity, execution, published) {
|
|
1166
1168
|
const epoch = this.epochOf(name);
|
|
1169
|
+
const check = () => { execution?.assert(); if (this.epochOf(name) !== epoch)
|
|
1170
|
+
throw new SupersededStartError(name); };
|
|
1171
|
+
check();
|
|
1167
1172
|
const seedNow = this.activitySeedNow.delete(name);
|
|
1168
1173
|
if (this.daemons.has(name)) {
|
|
1169
1174
|
this.ctx.logger.info({ name }, "Instance already running, skipping");
|
|
@@ -1179,6 +1184,7 @@ export class InstanceLifecycle {
|
|
|
1179
1184
|
// that fails before reaching the daemon must leave that intent intact.
|
|
1180
1185
|
const { Daemon } = await import("./daemon.js");
|
|
1181
1186
|
const { createBackend } = await import("./backend/factory.js");
|
|
1187
|
+
check();
|
|
1182
1188
|
const backendName = config.backend ?? this.ctx.fleetConfig?.defaults?.backend ?? "claude-code";
|
|
1183
1189
|
// A removed backend (#1280): this instance refuses to start, says why and what to use instead, and the rest of
|
|
1184
1190
|
// the fleet is unaffected. Never a fallback to another backend.
|
|
@@ -1258,7 +1264,7 @@ export class InstanceLifecycle {
|
|
|
1258
1264
|
throw new Error(message);
|
|
1259
1265
|
}
|
|
1260
1266
|
}
|
|
1261
|
-
if (this.epochOf(name) !== epoch) {
|
|
1267
|
+
if (this.epochOf(name) !== epoch || execution && !execution.current()) {
|
|
1262
1268
|
// A stop/restart arrived while this start was reconciling: do not spawn.
|
|
1263
1269
|
await daemon.abortStartup().catch(() => { });
|
|
1264
1270
|
throw new SupersededStartError(name);
|
|
@@ -1267,16 +1273,17 @@ export class InstanceLifecycle {
|
|
|
1267
1273
|
// before the handlers below exist and before this daemon is registered;
|
|
1268
1274
|
// hold it and deliver it once both are true.
|
|
1269
1275
|
daemon.holdStartupIncidents?.();
|
|
1270
|
-
await InstanceLifecycle.startOrDispose(daemon, name, this.ctx.logger);
|
|
1276
|
+
await InstanceLifecycle.startOrDispose(daemon, name, this.ctx.logger, execution ? check : undefined);
|
|
1271
1277
|
// Publication fence (Phase 2a): the spawn cannot be cancelled, so a stop or
|
|
1272
1278
|
// restart requested meanwhile has been waiting behind this transition. A
|
|
1273
1279
|
// superseded start must not register, signal ready, or keep its window.
|
|
1274
|
-
if (this.epochOf(name) !== epoch) {
|
|
1280
|
+
if (this.epochOf(name) !== epoch || execution && !execution.current()) {
|
|
1275
1281
|
await daemon.abortStartup().catch(err => this.ctx.logger.warn({ err, name }, "Failed to dispose a superseded start"));
|
|
1276
1282
|
throw new SupersededStartError(name);
|
|
1277
1283
|
}
|
|
1278
1284
|
this.capacityBackoffBaselines.delete(name);
|
|
1279
1285
|
this.daemons.set(name, daemon);
|
|
1286
|
+
published?.(daemon); // Exact publication, synchronously after the ownership fence.
|
|
1280
1287
|
if (seedNow)
|
|
1281
1288
|
this.noteWokeForWork(name);
|
|
1282
1289
|
this.ctx.onDaemonReady?.(name, daemon.bootId);
|
|
@@ -1287,8 +1294,10 @@ export class InstanceLifecycle {
|
|
|
1287
1294
|
this.ctx.eventLog?.insert(name, "instance_paused", { reason: "idle", paused_at: data.pausedAt });
|
|
1288
1295
|
this.ctx.logger.info({ name, pausedAt: data.pausedAt }, "Instance auto-paused after idle timeout");
|
|
1289
1296
|
this.ctx.setTopicIcon(name, "remove");
|
|
1297
|
+
this.ctx.onAttentionChanged?.(name);
|
|
1290
1298
|
});
|
|
1291
1299
|
daemon.on("auto_woke", () => {
|
|
1300
|
+
this.ctx.onAttentionChanged?.(name);
|
|
1292
1301
|
this.ctx.eventLog?.insert(name, "instance_resumed", { reason: "message" });
|
|
1293
1302
|
this.ctx.logger.info({ name }, "Instance auto-woke for delivery");
|
|
1294
1303
|
this.ctx.setTopicIcon(name, "green");
|
|
@@ -1349,6 +1358,7 @@ export class InstanceLifecycle {
|
|
|
1349
1358
|
// its fleet-level statusline watcher in the frozen state.
|
|
1350
1359
|
if (!daemon.isPaused)
|
|
1351
1360
|
this.ctx.startStatuslineWatcher(name);
|
|
1361
|
+
this.ctx.onAttentionChanged?.(name);
|
|
1352
1362
|
}
|
|
1353
1363
|
}
|
|
1354
1364
|
/** When `name` was last woken or (re)started for work, if recorded. */
|
|
@@ -1356,7 +1366,7 @@ export class InstanceLifecycle {
|
|
|
1356
1366
|
return this.wokeAt.get(name);
|
|
1357
1367
|
}
|
|
1358
1368
|
async wake(name, timeoutMs = 30_000, transition, opts = {}) {
|
|
1359
|
-
const woke = await this.wakeInner(name, timeoutMs, transition);
|
|
1369
|
+
const woke = await this.wakeInner(name, timeoutMs, transition).finally(() => this.ctx.onAttentionChanged?.(name));
|
|
1360
1370
|
// Only a successful operator/user wake lifts the coordinator's park.
|
|
1361
1371
|
if (opts.source !== "coordinator")
|
|
1362
1372
|
this.ctx.onExternalWake?.(name);
|
|
@@ -1418,9 +1428,12 @@ export class InstanceLifecycle {
|
|
|
1418
1428
|
* rethrowing. The abort is best-effort — the start error is the one to
|
|
1419
1429
|
* surface.
|
|
1420
1430
|
*/
|
|
1421
|
-
static async startOrDispose(daemon, name, logger) {
|
|
1431
|
+
static async startOrDispose(daemon, name, logger, admission) {
|
|
1422
1432
|
try {
|
|
1423
|
-
|
|
1433
|
+
if (admission)
|
|
1434
|
+
await daemon.start(admission);
|
|
1435
|
+
else
|
|
1436
|
+
await daemon.start();
|
|
1424
1437
|
}
|
|
1425
1438
|
catch (err) {
|
|
1426
1439
|
await daemon.abortStartup().catch(abortErr => logger.warn({ err: abortErr, name }, "Failed to dispose a daemon whose start() rejected"));
|
|
@@ -1551,12 +1564,15 @@ export class InstanceLifecycle {
|
|
|
1551
1564
|
this.ctx.sessionRegistry.delete(session);
|
|
1552
1565
|
}
|
|
1553
1566
|
}
|
|
1554
|
-
async remove(name, authorization) {
|
|
1567
|
+
async remove(name, authorization, execution, transition) {
|
|
1555
1568
|
// Automatic topology reconciliation must never reach the destructive path.
|
|
1556
1569
|
assertExplicitInstanceRemoval(authorization);
|
|
1557
1570
|
const config = this.ctx.fleetConfig?.instances[name];
|
|
1558
1571
|
if (!config)
|
|
1559
1572
|
return;
|
|
1573
|
+
const check = () => { execution?.assert(); if (this.ctx.fleetConfig?.instances[name] !== config)
|
|
1574
|
+
throw new Error("instance removal superseded"); };
|
|
1575
|
+
check();
|
|
1560
1576
|
// Never remove the General instance
|
|
1561
1577
|
if (config.general_topic) {
|
|
1562
1578
|
this.ctx.logger.warn({ name }, "Refusing to remove General instance");
|
|
@@ -1566,16 +1582,21 @@ export class InstanceLifecycle {
|
|
|
1566
1582
|
// Access scheduler through fleetConfig — scheduler is managed by FleetManager
|
|
1567
1583
|
// We just clean up instance-related data here
|
|
1568
1584
|
// Stop daemon and clean up tmux window (handles both in-memory and orphaned cases)
|
|
1569
|
-
await this.stop(name);
|
|
1585
|
+
await this.stop(name, transition);
|
|
1586
|
+
check();
|
|
1570
1587
|
// Clean up backend config files (MCP config, instructions, etc.)
|
|
1571
1588
|
// This is needed even when daemon is not in memory — stop() only calls
|
|
1572
1589
|
// backend.cleanup() when daemon object exists. Without this, stale MCP
|
|
1573
1590
|
// entries remain in the working directory and crash new instances.
|
|
1574
|
-
|
|
1591
|
+
// By the effective backend: an instance on the fleet default backend (no per-instance `backend`) has the same
|
|
1592
|
+
// files to clean up (#906 review: an inherited kiro left its agent, steering and shared entry behind).
|
|
1593
|
+
const effectiveBackend = config.backend ?? this.ctx.fleetConfig?.defaults?.backend;
|
|
1594
|
+
if (config.working_directory && effectiveBackend) {
|
|
1575
1595
|
try {
|
|
1576
1596
|
const { createBackend } = await import("./backend/factory.js");
|
|
1597
|
+
check();
|
|
1577
1598
|
const instanceDir = this.ctx.getInstanceDir(name);
|
|
1578
|
-
const backend = createBackend(
|
|
1599
|
+
const backend = createBackend(effectiveBackend, instanceDir);
|
|
1579
1600
|
if (backend?.cleanup) {
|
|
1580
1601
|
const backendConfig = {
|
|
1581
1602
|
workingDirectory: config.working_directory,
|
|
@@ -1593,6 +1614,15 @@ export class InstanceLifecycle {
|
|
|
1593
1614
|
this.ctx.logger.debug({ err, name }, "Backend cleanup failed (best effort)");
|
|
1594
1615
|
}
|
|
1595
1616
|
}
|
|
1617
|
+
// State a backend keeps outside the instance directory (kiro: which conversations it owns, #906) — by the
|
|
1618
|
+
// effective backend, so an instance on the fleet default is forgotten too.
|
|
1619
|
+
try {
|
|
1620
|
+
const { createBackend } = await import("./backend/factory.js");
|
|
1621
|
+
check();
|
|
1622
|
+
const effective = config.backend ?? this.ctx.fleetConfig?.defaults?.backend ?? "claude-code";
|
|
1623
|
+
createBackend(effective, this.ctx.getInstanceDir(name))?.forget?.(name);
|
|
1624
|
+
}
|
|
1625
|
+
catch { /* best effort */ }
|
|
1596
1626
|
// Clean up git worktree if applicable
|
|
1597
1627
|
if (config.worktree_source && config.working_directory) {
|
|
1598
1628
|
if (!existsSync(config.working_directory)) {
|
|
@@ -1602,20 +1632,24 @@ export class InstanceLifecycle {
|
|
|
1602
1632
|
try {
|
|
1603
1633
|
const { execFile: execFileCb } = await import("node:child_process");
|
|
1604
1634
|
const { promisify } = await import("node:util");
|
|
1635
|
+
check();
|
|
1605
1636
|
const execFileAsync = promisify(execFileCb);
|
|
1606
1637
|
await execFileAsync("git", ["worktree", "remove", "--force", config.working_directory], {
|
|
1607
1638
|
cwd: config.worktree_source,
|
|
1608
1639
|
});
|
|
1640
|
+
check();
|
|
1609
1641
|
this.ctx.logger.info({ worktree: config.working_directory }, "Removed git worktree");
|
|
1610
1642
|
}
|
|
1611
1643
|
catch {
|
|
1612
|
-
// worktree remove failed — directory exists but isn't a valid worktree.
|
|
1644
|
+
check(); // worktree remove failed — directory exists but isn't a valid worktree.
|
|
1613
1645
|
// Only rm if directory is in the expected location (sibling of source repo or under ~/.agend/).
|
|
1614
1646
|
const expectedParent = dirname(config.working_directory);
|
|
1615
1647
|
const sourceParent = dirname(config.worktree_source);
|
|
1616
1648
|
if (expectedParent === sourceParent || config.working_directory.startsWith(getAgendHome())) {
|
|
1617
1649
|
const { rm } = await import("node:fs/promises");
|
|
1650
|
+
check();
|
|
1618
1651
|
await rm(config.working_directory, { recursive: true, force: true });
|
|
1652
|
+
check();
|
|
1619
1653
|
this.ctx.logger.info({ worktree: config.working_directory }, "Removed orphaned worktree directory");
|
|
1620
1654
|
}
|
|
1621
1655
|
else {
|
|
@@ -1627,16 +1661,22 @@ export class InstanceLifecycle {
|
|
|
1627
1661
|
try {
|
|
1628
1662
|
const { execFile: execFileCb } = await import("node:child_process");
|
|
1629
1663
|
const { promisify } = await import("node:util");
|
|
1664
|
+
check();
|
|
1630
1665
|
const execFileAsync = promisify(execFileCb);
|
|
1631
1666
|
await execFileAsync("git", ["worktree", "prune"], { cwd: config.worktree_source });
|
|
1632
1667
|
}
|
|
1633
|
-
catch {
|
|
1668
|
+
catch {
|
|
1669
|
+
check(); /* best effort */
|
|
1670
|
+
}
|
|
1634
1671
|
}
|
|
1672
|
+
check();
|
|
1635
1673
|
// Clean up IPC
|
|
1636
1674
|
const ipc = this.ctx.instanceIpcClients.get(name);
|
|
1637
1675
|
if (ipc) {
|
|
1638
1676
|
await ipc.close();
|
|
1639
|
-
|
|
1677
|
+
check();
|
|
1678
|
+
if (this.ctx.instanceIpcClients.get(name) === ipc)
|
|
1679
|
+
this.ctx.instanceIpcClients.delete(name);
|
|
1640
1680
|
}
|
|
1641
1681
|
// Remove from routing table (this instance only: #1085, another Telegram
|
|
1642
1682
|
// world may own the same topic number)
|
|
@@ -1644,13 +1684,20 @@ export class InstanceLifecycle {
|
|
|
1644
1684
|
this.ctx.routing.unregister(config.topic_id, name);
|
|
1645
1685
|
}
|
|
1646
1686
|
// Remove from fleet config and save
|
|
1647
|
-
delete this.ctx.fleetConfig.instances[name];
|
|
1648
|
-
|
|
1687
|
+
const persist = () => { delete this.ctx.fleetConfig.instances[name]; this.ctx.saveFleetConfig(); };
|
|
1688
|
+
if (execution)
|
|
1689
|
+
execution.mutate(persist);
|
|
1690
|
+
else {
|
|
1691
|
+
check();
|
|
1692
|
+
persist();
|
|
1693
|
+
}
|
|
1649
1694
|
clearPausedMarker(this.ctx.getInstanceDir(name));
|
|
1650
1695
|
this.ctx.logger.info({ name }, "Instance removed");
|
|
1651
1696
|
}
|
|
1652
1697
|
/** Handle create_instance tool call from a daemon. */
|
|
1653
|
-
async handleCreate(args, respond, adapterId) {
|
|
1698
|
+
async handleCreate(args, respond, adapterId, execution) {
|
|
1699
|
+
const check = () => execution?.assert();
|
|
1700
|
+
check();
|
|
1654
1701
|
const rawDirectory = args.directory;
|
|
1655
1702
|
const directory = rawDirectory ? rawDirectory.replace(/^~/, process.env.HOME || "~") : undefined;
|
|
1656
1703
|
const topicName = args.topic_name || (directory ? basename(directory) : undefined);
|
|
@@ -1666,6 +1713,7 @@ export class InstanceLifecycle {
|
|
|
1666
1713
|
if (directory) {
|
|
1667
1714
|
try {
|
|
1668
1715
|
await access(directory);
|
|
1716
|
+
check();
|
|
1669
1717
|
}
|
|
1670
1718
|
catch {
|
|
1671
1719
|
respond(null, `Directory does not exist: ${directory}`);
|
|
@@ -1723,6 +1771,36 @@ export class InstanceLifecycle {
|
|
|
1723
1771
|
// If branch specified, create git worktree (requires directory)
|
|
1724
1772
|
let workDir = directory ?? "";
|
|
1725
1773
|
let worktreePath;
|
|
1774
|
+
let acquiredWorktree = false;
|
|
1775
|
+
let acquiredDirectory;
|
|
1776
|
+
const directoryReferenced = () => Object.values(this.ctx.fleetConfig?.instances ?? {}).some(config => config.working_directory === workDir);
|
|
1777
|
+
const cleanupDirectory = async () => {
|
|
1778
|
+
if (!acquiredDirectory || !workDir || directoryReferenced())
|
|
1779
|
+
return;
|
|
1780
|
+
const ownsPath = () => {
|
|
1781
|
+
if (directoryReferenced())
|
|
1782
|
+
return false;
|
|
1783
|
+
try {
|
|
1784
|
+
const current = statSync(workDir);
|
|
1785
|
+
return current.dev === acquiredDirectory.dev && current.ino === acquiredDirectory.ino;
|
|
1786
|
+
}
|
|
1787
|
+
catch {
|
|
1788
|
+
return false;
|
|
1789
|
+
}
|
|
1790
|
+
};
|
|
1791
|
+
if (acquiredWorktree) {
|
|
1792
|
+
const { execFile } = await import("node:child_process");
|
|
1793
|
+
const { promisify } = await import("node:util");
|
|
1794
|
+
if (!ownsPath())
|
|
1795
|
+
return;
|
|
1796
|
+
await promisify(execFile)("git", ["worktree", "remove", "--force", workDir], { cwd: directory });
|
|
1797
|
+
}
|
|
1798
|
+
else {
|
|
1799
|
+
const { rm } = await import("node:fs/promises");
|
|
1800
|
+
if (ownsPath())
|
|
1801
|
+
await rm(workDir, { recursive: true, force: true });
|
|
1802
|
+
}
|
|
1803
|
+
};
|
|
1726
1804
|
if (branch && !directory) {
|
|
1727
1805
|
respond(null, "directory is required when branch is specified");
|
|
1728
1806
|
return;
|
|
@@ -1731,7 +1809,14 @@ export class InstanceLifecycle {
|
|
|
1731
1809
|
try {
|
|
1732
1810
|
const { execFile: execFileCb } = await import("node:child_process");
|
|
1733
1811
|
const { promisify } = await import("node:util");
|
|
1734
|
-
const
|
|
1812
|
+
const nativeExec = promisify(execFileCb);
|
|
1813
|
+
const execFileAsync = async (file, args, options, acquired) => {
|
|
1814
|
+
check();
|
|
1815
|
+
const result = await nativeExec(file, args, options);
|
|
1816
|
+
acquired?.();
|
|
1817
|
+
check();
|
|
1818
|
+
return result;
|
|
1819
|
+
};
|
|
1735
1820
|
await execFileAsync("git", ["rev-parse", "--git-dir"], { cwd: directory });
|
|
1736
1821
|
const customPath = args.worktree_path;
|
|
1737
1822
|
if (customPath) {
|
|
@@ -1767,23 +1852,25 @@ export class InstanceLifecycle {
|
|
|
1767
1852
|
respond(null, EMBEDDED_CREDENTIAL_REMOTE_REPAIR_FAILED);
|
|
1768
1853
|
return;
|
|
1769
1854
|
}
|
|
1855
|
+
const acquired = () => { acquiredWorktree = true; workDir = worktreePath; acquiredDirectory = statSync(workDir); };
|
|
1770
1856
|
if (detach) {
|
|
1771
|
-
await execFileAsync("git", ["worktree", "add", "--detach", worktreePath, branch], { cwd: directory });
|
|
1857
|
+
await execFileAsync("git", ["worktree", "add", "--detach", worktreePath, branch], { cwd: directory }, acquired);
|
|
1772
1858
|
}
|
|
1773
1859
|
else if (branchExists) {
|
|
1774
|
-
await execFileAsync("git", ["worktree", "add", worktreePath, branch], { cwd: directory });
|
|
1860
|
+
await execFileAsync("git", ["worktree", "add", worktreePath, branch], { cwd: directory }, acquired);
|
|
1775
1861
|
}
|
|
1776
1862
|
else {
|
|
1777
1863
|
const startPoint = args.start_point;
|
|
1778
1864
|
const worktreeArgs = ["worktree", "add", worktreePath, "-b", branch];
|
|
1779
1865
|
if (startPoint)
|
|
1780
1866
|
worktreeArgs.push(startPoint);
|
|
1781
|
-
await execFileAsync("git", worktreeArgs, { cwd: directory });
|
|
1867
|
+
await execFileAsync("git", worktreeArgs, { cwd: directory }, acquired);
|
|
1782
1868
|
}
|
|
1783
1869
|
this.ctx.logger.info({ worktreePath, branch, repo: directory }, "Created git worktree for instance");
|
|
1784
1870
|
workDir = worktreePath;
|
|
1785
1871
|
}
|
|
1786
1872
|
catch (err) {
|
|
1873
|
+
await cleanupDirectory().catch(e => this.ctx.logger.warn({ err: e }, "Owned worktree cleanup failed"));
|
|
1787
1874
|
respond(null, `Failed to create worktree: ${err.message}`);
|
|
1788
1875
|
return;
|
|
1789
1876
|
}
|
|
@@ -1808,13 +1895,18 @@ export class InstanceLifecycle {
|
|
|
1808
1895
|
// Sequential steps with rollback
|
|
1809
1896
|
let createdTopicId;
|
|
1810
1897
|
let newInstanceName;
|
|
1898
|
+
let createdConfig;
|
|
1899
|
+
let createdDaemon;
|
|
1900
|
+
let createUndo = [];
|
|
1811
1901
|
// Capture the creating world's delete capability BEFORE the create await:
|
|
1812
1902
|
// rollback must use exactly this adapter even if the world is removed or
|
|
1813
1903
|
// replaced while creating. Never re-resolve (that would substitute the
|
|
1814
1904
|
// primary or a new world). Null means fail closed at rollback.
|
|
1815
1905
|
const topicDeleter = this.ctx.getForumTopicDeleter?.(adapterId) ?? null;
|
|
1816
1906
|
try {
|
|
1907
|
+
check();
|
|
1817
1908
|
createdTopicId = await this.ctx.createForumTopic(topicName, adapterId);
|
|
1909
|
+
check();
|
|
1818
1910
|
// Use explicit topic_name as name base when provided; fall back to directory basename
|
|
1819
1911
|
const explicitTopicName = args.topic_name;
|
|
1820
1912
|
const nameBase = explicitTopicName ?? (worktreePath ? topicName : (directory ? basename(workDir) : topicName));
|
|
@@ -1842,7 +1934,10 @@ export class InstanceLifecycle {
|
|
|
1842
1934
|
// If no directory was provided, auto-create default workspace
|
|
1843
1935
|
if (!directory) {
|
|
1844
1936
|
workDir = join(getAgendHome(), "workspaces", newInstanceName);
|
|
1937
|
+
const existed = existsSync(workDir);
|
|
1845
1938
|
mkdirSync(workDir, { recursive: true });
|
|
1939
|
+
if (!existed)
|
|
1940
|
+
acquiredDirectory = statSync(workDir);
|
|
1846
1941
|
ensureWorkspaceGit(workDir);
|
|
1847
1942
|
}
|
|
1848
1943
|
const instanceConfig = {
|
|
@@ -1872,11 +1967,31 @@ export class InstanceLifecycle {
|
|
|
1872
1967
|
&& !isModelCompatible(instanceConfig.backend, instanceConfig.model)) {
|
|
1873
1968
|
delete instanceConfig.model;
|
|
1874
1969
|
}
|
|
1875
|
-
|
|
1876
|
-
this.ctx.
|
|
1877
|
-
|
|
1878
|
-
|
|
1970
|
+
createdConfig = instanceConfig;
|
|
1971
|
+
const beforeCreate = structuredClone(this.ctx.fleetConfig);
|
|
1972
|
+
const persist = () => {
|
|
1973
|
+
this.ctx.fleetConfig.instances[newInstanceName] = instanceConfig;
|
|
1974
|
+
this.ctx.routing.register(createdTopicId, { kind: "instance", name: newInstanceName });
|
|
1975
|
+
try {
|
|
1976
|
+
this.ctx.saveFleetConfig();
|
|
1977
|
+
}
|
|
1978
|
+
finally {
|
|
1979
|
+
createUndo = settingsUndo((this.ctx.getSettingsConfigPath?.() ?? join(this.ctx.dataDir, "fleet.yaml")), beforeCreate, this.ctx.fleetConfig, [["instances", newInstanceName]]);
|
|
1980
|
+
}
|
|
1981
|
+
};
|
|
1982
|
+
if (execution)
|
|
1983
|
+
execution.mutate(persist);
|
|
1984
|
+
else
|
|
1985
|
+
persist();
|
|
1986
|
+
if (execution)
|
|
1987
|
+
await this.start(newInstanceName, instanceConfig, true, undefined, undefined, execution);
|
|
1988
|
+
else
|
|
1989
|
+
await this.start(newInstanceName, instanceConfig, true);
|
|
1990
|
+
createdDaemon = this.daemons.get(newInstanceName);
|
|
1991
|
+
check();
|
|
1879
1992
|
await this.ctx.connectIpcToInstance(newInstanceName);
|
|
1993
|
+
check();
|
|
1994
|
+
execution?.complete();
|
|
1880
1995
|
respond({
|
|
1881
1996
|
success: true,
|
|
1882
1997
|
name: newInstanceName,
|
|
@@ -1886,16 +2001,20 @@ export class InstanceLifecycle {
|
|
|
1886
2001
|
}
|
|
1887
2002
|
catch (err) {
|
|
1888
2003
|
// Rollback in reverse order
|
|
1889
|
-
if (newInstanceName && this.daemons.
|
|
2004
|
+
if (newInstanceName && createdDaemon && this.daemons.get(newInstanceName) === createdDaemon) {
|
|
1890
2005
|
await this.stop(newInstanceName).catch(e => this.ctx.logger.error({ err: e, name: newInstanceName }, "Failed to stop instance during rollback"));
|
|
1891
2006
|
}
|
|
1892
|
-
if (newInstanceName && this.ctx.fleetConfig?.instances[newInstanceName]) {
|
|
1893
|
-
|
|
1894
|
-
if (
|
|
1895
|
-
this.ctx.
|
|
1896
|
-
|
|
2007
|
+
if (newInstanceName && createdConfig && this.ctx.fleetConfig?.instances[newInstanceName] === createdConfig && createUndo.length) {
|
|
2008
|
+
const retained = undoSettingsPaths((this.ctx.getSettingsConfigPath?.() ?? join(this.ctx.dataDir, "fleet.yaml")), this.ctx.fleetConfig, createUndo);
|
|
2009
|
+
if (!retained.conflicts) {
|
|
2010
|
+
this.ctx.fleetConfig.instances = retained.value.instances;
|
|
2011
|
+
if (createdTopicId && !this.ctx.fleetConfig.instances[newInstanceName])
|
|
2012
|
+
this.ctx.routing.unregister(createdTopicId, newInstanceName);
|
|
2013
|
+
this.ctx.saveFleetConfig();
|
|
2014
|
+
}
|
|
1897
2015
|
}
|
|
1898
|
-
|
|
2016
|
+
const topicReferenced = createdTopicId != null && Object.values(this.ctx.fleetConfig?.instances ?? {}).some(config => String(config.topic_id) === String(createdTopicId) && (adapterId == null || config.channel_id == null || config.channel_id === adapterId));
|
|
2017
|
+
if (createdTopicId && !topicReferenced) {
|
|
1899
2018
|
// Delete through the captured creating adapter only (#1305 P2-4/r4).
|
|
1900
2019
|
// If the world went away, fail closed: log and leave the topic for
|
|
1901
2020
|
// manual cleanup rather than deleting through a substituted adapter.
|
|
@@ -1911,24 +2030,7 @@ export class InstanceLifecycle {
|
|
|
1911
2030
|
this.ctx.logger.warn({ topicId: createdTopicId }, "Creating world has no delete capability; leaving topic for manual cleanup");
|
|
1912
2031
|
}
|
|
1913
2032
|
}
|
|
1914
|
-
|
|
1915
|
-
try {
|
|
1916
|
-
const { execFile: execFileCb } = await import("node:child_process");
|
|
1917
|
-
const { promisify } = await import("node:util");
|
|
1918
|
-
const execFileAsync = promisify(execFileCb);
|
|
1919
|
-
await execFileAsync("git", ["worktree", "remove", "--force", worktreePath], { cwd: directory });
|
|
1920
|
-
await execFileAsync("git", ["worktree", "prune"], { cwd: directory });
|
|
1921
|
-
}
|
|
1922
|
-
catch { /* best-effort worktree cleanup */ }
|
|
1923
|
-
}
|
|
1924
|
-
else if (!directory && workDir) {
|
|
1925
|
-
// Remove auto-created workspace directory
|
|
1926
|
-
try {
|
|
1927
|
-
const { rm } = await import("node:fs/promises");
|
|
1928
|
-
await rm(workDir, { recursive: true, force: true });
|
|
1929
|
-
}
|
|
1930
|
-
catch { /* best-effort cleanup */ }
|
|
1931
|
-
}
|
|
2033
|
+
await cleanupDirectory().catch(e => this.ctx.logger.warn({ err: e }, "Owned instance directory cleanup failed"));
|
|
1932
2034
|
respond(null, `Failed to create instance: ${err.message}`);
|
|
1933
2035
|
}
|
|
1934
2036
|
}
|
|
@@ -1992,6 +2094,13 @@ export class InstanceLifecycle {
|
|
|
1992
2094
|
this.ctx.saveFleetConfig();
|
|
1993
2095
|
// 5. Clean instanceDir to avoid stale rotation-state.json / crash-history
|
|
1994
2096
|
const instanceDir = this.ctx.getInstanceDir(instanceName);
|
|
2097
|
+
// The replacement starts a fresh context: forget the conversations the old one owned (kiro, #906).
|
|
2098
|
+
try {
|
|
2099
|
+
const { createBackend } = await import("./backend/factory.js");
|
|
2100
|
+
const effective = savedConfig.backend ?? this.ctx.fleetConfig?.defaults?.backend ?? "claude-code";
|
|
2101
|
+
createBackend(effective, instanceDir)?.forget?.(instanceName);
|
|
2102
|
+
}
|
|
2103
|
+
catch { /* best effort */ }
|
|
1995
2104
|
try {
|
|
1996
2105
|
const { rm } = await import("node:fs/promises");
|
|
1997
2106
|
await rm(instanceDir, { recursive: true, force: true });
|