@cydm/happy-elves 0.1.0-beta.31 → 0.1.0-beta.310
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/apps/cli/dist/commands/app.js +10 -0
- package/apps/cli/dist/commands/daemon.js +92 -4
- package/apps/cli/dist/commands/gateway.d.ts +2 -0
- package/apps/cli/dist/commands/gateway.js +429 -0
- package/apps/cli/dist/commands/lib/args.js +49 -0
- package/apps/cli/dist/commands/lib/bootstrap-daemon.d.ts +2 -2
- package/apps/cli/dist/commands/lib/bootstrap-daemon.js +2 -2
- package/apps/cli/dist/commands/lib/doctor.d.ts +11 -0
- package/apps/cli/dist/commands/lib/doctor.js +276 -11
- package/apps/cli/dist/commands/lib/gateway-store.d.ts +38 -0
- package/apps/cli/dist/commands/lib/gateway-store.js +33 -0
- package/apps/cli/dist/commands/lib/index.d.ts +4 -2
- package/apps/cli/dist/commands/lib/index.js +2 -0
- package/apps/cli/dist/commands/lib/json.d.ts +2 -2
- package/apps/cli/dist/commands/lib/json.js +5 -2
- package/apps/cli/dist/commands/lib/local-daemon.d.ts +1 -0
- package/apps/cli/dist/commands/lib/local-daemon.js +14 -0
- package/apps/cli/dist/commands/lib/paths.d.ts +2 -0
- package/apps/cli/dist/commands/lib/paths.js +2 -0
- package/apps/cli/dist/commands/lib/relay-db-audit.d.ts +37 -0
- package/apps/cli/dist/commands/lib/relay-db-audit.js +300 -0
- package/apps/cli/dist/commands/lib/relay-http.d.ts +1 -1
- package/apps/cli/dist/commands/lib/scope.d.ts +1 -1
- package/apps/cli/dist/commands/lib/session-output.d.ts +15 -1
- package/apps/cli/dist/commands/lib/session-output.js +214 -6
- package/apps/cli/dist/commands/lib/session-view.d.ts +2 -2
- package/apps/cli/dist/commands/lib/status.js +5 -1
- package/apps/cli/dist/commands/lib/types.d.ts +4 -2
- package/apps/cli/dist/commands/lib/usage.js +123 -10
- package/apps/cli/dist/commands/lib/workspace.d.ts +2 -2
- package/apps/cli/dist/commands/lib/workspace.js +63 -10
- package/apps/cli/dist/commands/machine.js +50 -9
- package/apps/cli/dist/commands/memory.d.ts +2 -0
- package/apps/cli/dist/commands/memory.js +179 -0
- package/apps/cli/dist/commands/relay.js +29 -2
- package/apps/cli/dist/commands/release.d.ts +2 -0
- package/apps/cli/dist/commands/release.js +197 -0
- package/apps/cli/dist/commands/remote.js +10 -2
- package/apps/cli/dist/commands/schedule.d.ts +2 -0
- package/apps/cli/dist/commands/schedule.js +273 -0
- package/apps/cli/dist/commands/session.js +517 -5
- package/apps/cli/dist/commands/turn.js +225 -9
- package/apps/cli/dist/commands/workspace.d.ts +2 -0
- package/apps/cli/dist/commands/workspace.js +68 -0
- package/apps/cli/package.json +6 -0
- package/apps/daemon/dist/gateway/adapters.d.ts +38 -0
- package/apps/daemon/dist/gateway/adapters.js +2 -0
- package/apps/daemon/dist/gateway/feishu.d.ts +65 -0
- package/apps/daemon/dist/gateway/feishu.js +493 -0
- package/apps/daemon/dist/gateway/format.d.ts +2 -0
- package/apps/daemon/dist/gateway/format.js +19 -0
- package/apps/daemon/dist/gateway/handler.d.ts +7 -0
- package/apps/daemon/dist/gateway/handler.js +151 -0
- package/apps/daemon/dist/gateway/runtime.d.ts +33 -0
- package/apps/daemon/dist/gateway/runtime.js +850 -0
- package/apps/daemon/dist/gateway/store.d.ts +92 -0
- package/apps/daemon/dist/gateway/store.js +268 -0
- package/apps/daemon/dist/memory/handler.d.ts +7 -0
- package/apps/daemon/dist/memory/handler.js +105 -0
- package/apps/daemon/dist/memory/manager.d.ts +44 -0
- package/apps/daemon/dist/memory/manager.js +359 -0
- package/apps/daemon/dist/paths.d.ts +3 -0
- package/apps/daemon/dist/paths.js +3 -0
- package/apps/daemon/dist/relay/admission.d.ts +30 -0
- package/apps/daemon/dist/relay/admission.js +31 -0
- package/apps/daemon/dist/relay/connection.js +37 -1
- package/apps/daemon/dist/relay/devtools.d.ts +1 -1
- package/apps/daemon/dist/relay/register.js +2 -0
- package/apps/daemon/dist/relay/send.d.ts +2 -2
- package/apps/daemon/dist/relay/send.js +2 -0
- package/apps/daemon/dist/relay-http.d.ts +1 -1
- package/apps/daemon/dist/runtime/external-provider.d.ts +1 -1
- package/apps/daemon/dist/runtime/external-provider.js +187 -17
- package/apps/daemon/dist/runtime.d.ts +1 -2
- package/apps/daemon/dist/runtime.js +0 -3
- package/apps/daemon/dist/schedule/handler.d.ts +9 -0
- package/apps/daemon/dist/schedule/handler.js +148 -0
- package/apps/daemon/dist/schedule/runner.d.ts +21 -0
- package/apps/daemon/dist/schedule/runner.js +547 -0
- package/apps/daemon/dist/schedule/store.d.ts +9 -0
- package/apps/daemon/dist/schedule/store.js +143 -0
- package/apps/daemon/dist/session/create-session.d.ts +1 -1
- package/apps/daemon/dist/session/directory.d.ts +1 -1
- package/apps/daemon/dist/session/events.d.ts +15 -2
- package/apps/daemon/dist/session/events.js +76 -24
- package/apps/daemon/dist/session/file-preview.d.ts +1 -1
- package/apps/daemon/dist/session/lifecycle.d.ts +26 -3
- package/apps/daemon/dist/session/lifecycle.js +161 -22
- package/apps/daemon/dist/session/metadata.d.ts +2 -2
- package/apps/daemon/dist/session/metadata.js +42 -1
- package/apps/daemon/dist/session/primitives.d.ts +1 -1
- package/apps/daemon/dist/session/primitives.js +37 -6
- package/apps/daemon/dist/session/prompt.d.ts +28 -1
- package/apps/daemon/dist/session/prompt.js +340 -5
- package/apps/daemon/dist/session/reconcile.d.ts +3 -0
- package/apps/daemon/dist/session/reconcile.js +235 -0
- package/apps/daemon/dist/session/runtime-handle.d.ts +1 -1
- package/apps/daemon/dist/start.js +5 -1
- package/apps/daemon/dist/state.d.ts +2 -2
- package/apps/daemon/dist/turn-coordinator.d.ts +1 -0
- package/apps/daemon/dist/turn-coordinator.js +4 -0
- package/apps/daemon/dist/types.d.ts +16 -1
- package/apps/daemon/package.json +3 -25
- package/apps/relay/dist/connections.d.ts +2 -0
- package/apps/relay/dist/controller-handlers.d.ts +42 -2
- package/apps/relay/dist/controller-handlers.js +349 -37
- package/apps/relay/dist/db.js +296 -2
- package/apps/relay/dist/errors.d.ts +2 -1
- package/apps/relay/dist/errors.js +3 -1
- package/apps/relay/dist/http-routes.js +659 -33
- package/apps/relay/dist/http-schemas.d.ts +156 -0
- package/apps/relay/dist/http-schemas.js +85 -0
- package/apps/relay/dist/index.js +31 -1
- package/apps/relay/dist/machine-handlers.d.ts +15 -7
- package/apps/relay/dist/machine-handlers.js +567 -27
- package/apps/relay/dist/projections.d.ts +1 -1
- package/apps/relay/dist/projections.js +13 -0
- package/apps/relay/dist/relay-context.d.ts +41 -3
- package/apps/relay/dist/relay-context.js +244 -19
- package/apps/relay/dist/repositories.d.ts +2 -2
- package/apps/relay/dist/repositories.js +28 -1
- package/apps/relay/dist/runtime-bindings.d.ts +25 -0
- package/apps/relay/dist/runtime-bindings.js +49 -0
- package/apps/relay/dist/scope.d.ts +1 -1
- package/apps/relay/dist/types.d.ts +71 -1
- package/apps/relay/dist/websocket.js +2 -0
- package/package.json +5 -11
- package/packages/agent-sdk/dist/index.d.ts +80 -0
- package/packages/agent-sdk/dist/index.js +16 -0
- package/packages/client/dist/account.d.ts +35 -2
- package/packages/client/dist/account.js +98 -1
- package/packages/client/dist/client.d.ts +59 -6
- package/packages/client/dist/client.js +312 -58
- package/packages/client/dist/index.d.ts +1 -1
- package/packages/client/dist/parsers.d.ts +28 -2
- package/packages/client/dist/parsers.js +167 -0
- package/packages/client/dist/transport.d.ts +21 -1
- package/packages/client/dist/transport.js +69 -6
- package/packages/client/dist/types.d.ts +177 -1
- package/packages/client/dist/validation.d.ts +1 -1
- package/packages/runtime/dist/index.d.ts +66 -0
- package/packages/runtime-acpx/dist/index.d.ts +1 -1
- package/packages/runtime-acpx/dist/index.js +8 -0
- package/packages/runtime-cli/dist/claude-history.d.ts +1 -2
- package/packages/runtime-cli/dist/claude-history.js +0 -3
- package/packages/runtime-cli/dist/claude-session-store.d.ts +0 -1
- package/packages/runtime-cli/dist/claude-session-store.js +1 -1
- package/packages/runtime-cli/dist/claude-turn.d.ts +2 -1
- package/packages/runtime-cli/dist/claude-turn.js +29 -9
- package/packages/runtime-cli/dist/codex-app-server.d.ts +8 -3
- package/packages/runtime-cli/dist/codex-app-server.js +122 -25
- package/packages/runtime-cli/dist/codex-history.d.ts +1 -2
- package/packages/runtime-cli/dist/codex-history.js +11 -5
- package/packages/runtime-cli/dist/codex-protocol.d.ts +2 -2
- package/packages/runtime-cli/dist/codex-protocol.js +4 -4
- package/packages/runtime-cli/dist/history-merge.d.ts +1 -1
- package/packages/runtime-cli/dist/index.d.ts +1 -1
- package/packages/runtime-cli/dist/index.js +108 -2
- package/packages/runtime-cli/dist/permissions.d.ts +1 -1
- package/packages/runtime-cli/dist/session-store.d.ts +2 -1
- package/packages/runtime-cli/dist/session-store.js +9 -8
- package/packages/shared/dist/index.d.ts +2 -0
- package/packages/shared/dist/index.js +2 -0
- package/packages/shared/dist/protocol-schemas.d.ts +1077 -0
- package/packages/shared/dist/protocol-schemas.js +273 -0
- package/packages/shared/dist/protocol-types.d.ts +371 -3
- package/packages/shared/dist/protocol.d.ts +181 -2
- package/packages/shared/dist/protocol.js +197 -1
- package/packages/shared/dist/session-tags.d.ts +12 -0
- package/packages/shared/dist/session-tags.js +50 -0
- package/apps/cli/dist/commands/account.js.map +0 -1
- package/apps/cli/dist/commands/app.js.map +0 -1
- package/apps/cli/dist/commands/collect.js.map +0 -1
- package/apps/cli/dist/commands/command.js.map +0 -1
- package/apps/cli/dist/commands/config.js.map +0 -1
- package/apps/cli/dist/commands/daemon.js.map +0 -1
- package/apps/cli/dist/commands/lib/args.js.map +0 -1
- package/apps/cli/dist/commands/lib/audit.js.map +0 -1
- package/apps/cli/dist/commands/lib/bootstrap-config.js.map +0 -1
- package/apps/cli/dist/commands/lib/bootstrap-daemon.js.map +0 -1
- package/apps/cli/dist/commands/lib/bootstrap-output.js.map +0 -1
- package/apps/cli/dist/commands/lib/bootstrap.js.map +0 -1
- package/apps/cli/dist/commands/lib/config.js.map +0 -1
- package/apps/cli/dist/commands/lib/doctor.js.map +0 -1
- package/apps/cli/dist/commands/lib/exit.js.map +0 -1
- package/apps/cli/dist/commands/lib/index.js.map +0 -1
- package/apps/cli/dist/commands/lib/json.js.map +0 -1
- package/apps/cli/dist/commands/lib/local-daemon.js.map +0 -1
- package/apps/cli/dist/commands/lib/loop-store.js.map +0 -1
- package/apps/cli/dist/commands/lib/paths.js.map +0 -1
- package/apps/cli/dist/commands/lib/relay-http.js.map +0 -1
- package/apps/cli/dist/commands/lib/scope.js.map +0 -1
- package/apps/cli/dist/commands/lib/session-output.js.map +0 -1
- package/apps/cli/dist/commands/lib/session-view.js.map +0 -1
- package/apps/cli/dist/commands/lib/status.js.map +0 -1
- package/apps/cli/dist/commands/lib/types.js.map +0 -1
- package/apps/cli/dist/commands/lib/usage.js.map +0 -1
- package/apps/cli/dist/commands/lib/workspace.js.map +0 -1
- package/apps/cli/dist/commands/loop.js.map +0 -1
- package/apps/cli/dist/commands/machine.js.map +0 -1
- package/apps/cli/dist/commands/relay.js.map +0 -1
- package/apps/cli/dist/commands/remote.js.map +0 -1
- package/apps/cli/dist/commands/session.js.map +0 -1
- package/apps/cli/dist/commands/token.js.map +0 -1
- package/apps/cli/dist/commands/turn.js.map +0 -1
- package/apps/cli/dist/errors.js.map +0 -1
- package/apps/cli/dist/index.js.map +0 -1
- package/apps/daemon/dist/app.js.map +0 -1
- package/apps/daemon/dist/args.js.map +0 -1
- package/apps/daemon/dist/audit.js.map +0 -1
- package/apps/daemon/dist/cli.js.map +0 -1
- package/apps/daemon/dist/config.js.map +0 -1
- package/apps/daemon/dist/errors.js.map +0 -1
- package/apps/daemon/dist/loop/runner.js.map +0 -1
- package/apps/daemon/dist/loop/store.js.map +0 -1
- package/apps/daemon/dist/pair.js.map +0 -1
- package/apps/daemon/dist/paths.js.map +0 -1
- package/apps/daemon/dist/process.js.map +0 -1
- package/apps/daemon/dist/relay/connection.js.map +0 -1
- package/apps/daemon/dist/relay/devtools.js.map +0 -1
- package/apps/daemon/dist/relay/register.js.map +0 -1
- package/apps/daemon/dist/relay/send.js.map +0 -1
- package/apps/daemon/dist/relay-http.js.map +0 -1
- package/apps/daemon/dist/runtime/external-provider.js.map +0 -1
- package/apps/daemon/dist/runtime.js.map +0 -1
- package/apps/daemon/dist/session/create-session.js.map +0 -1
- package/apps/daemon/dist/session/directory.js.map +0 -1
- package/apps/daemon/dist/session/events.js.map +0 -1
- package/apps/daemon/dist/session/file-preview.js.map +0 -1
- package/apps/daemon/dist/session/lifecycle.js.map +0 -1
- package/apps/daemon/dist/session/metadata.js.map +0 -1
- package/apps/daemon/dist/session/primitives.js.map +0 -1
- package/apps/daemon/dist/session/prompt.js.map +0 -1
- package/apps/daemon/dist/session/runtime-handle.js.map +0 -1
- package/apps/daemon/dist/start.js.map +0 -1
- package/apps/daemon/dist/state.js.map +0 -1
- package/apps/daemon/dist/turn-coordinator.js.map +0 -1
- package/apps/daemon/dist/types.js.map +0 -1
- package/apps/daemon/dist/utils.js.map +0 -1
- package/apps/relay/dist/auth.js.map +0 -1
- package/apps/relay/dist/connections.js.map +0 -1
- package/apps/relay/dist/controller-handlers.js.map +0 -1
- package/apps/relay/dist/db.js.map +0 -1
- package/apps/relay/dist/errors.js.map +0 -1
- package/apps/relay/dist/http-routes.js.map +0 -1
- package/apps/relay/dist/http-schemas.js.map +0 -1
- package/apps/relay/dist/index.js.map +0 -1
- package/apps/relay/dist/machine-handlers.js.map +0 -1
- package/apps/relay/dist/projections.js.map +0 -1
- package/apps/relay/dist/relay-context.js.map +0 -1
- package/apps/relay/dist/repositories.js.map +0 -1
- package/apps/relay/dist/retention.js.map +0 -1
- package/apps/relay/dist/scope.js.map +0 -1
- package/apps/relay/dist/security.js.map +0 -1
- package/apps/relay/dist/types.js.map +0 -1
- package/apps/relay/dist/websocket.js.map +0 -1
- package/apps/relay/package.json +0 -29
- package/packages/agent-sdk/dist/index.d.ts.map +0 -1
- package/packages/agent-sdk/dist/index.js.map +0 -1
- package/packages/agent-sdk/package.json +0 -20
- package/packages/client/dist/account.d.ts.map +0 -1
- package/packages/client/dist/account.js.map +0 -1
- package/packages/client/dist/client.d.ts.map +0 -1
- package/packages/client/dist/client.js.map +0 -1
- package/packages/client/dist/errors.d.ts.map +0 -1
- package/packages/client/dist/errors.js.map +0 -1
- package/packages/client/dist/http.d.ts.map +0 -1
- package/packages/client/dist/http.js.map +0 -1
- package/packages/client/dist/index.d.ts.map +0 -1
- package/packages/client/dist/index.js.map +0 -1
- package/packages/client/dist/parsers.d.ts.map +0 -1
- package/packages/client/dist/parsers.js.map +0 -1
- package/packages/client/dist/transport.d.ts.map +0 -1
- package/packages/client/dist/transport.js.map +0 -1
- package/packages/client/dist/types.d.ts.map +0 -1
- package/packages/client/dist/types.js.map +0 -1
- package/packages/client/dist/validation.d.ts.map +0 -1
- package/packages/client/dist/validation.js.map +0 -1
- package/packages/client/package.json +0 -22
- package/packages/pie-provider/dist/index.d.ts.map +0 -1
- package/packages/pie-provider/dist/index.js.map +0 -1
- package/packages/pie-provider/package.json +0 -26
- package/packages/runtime/dist/index.d.ts.map +0 -1
- package/packages/runtime/dist/index.js.map +0 -1
- package/packages/runtime/package.json +0 -19
- package/packages/runtime-acpx/dist/index.d.ts.map +0 -1
- package/packages/runtime-acpx/dist/index.js.map +0 -1
- package/packages/runtime-acpx/package.json +0 -23
- package/packages/runtime-cli/dist/async-queue.d.ts.map +0 -1
- package/packages/runtime-cli/dist/async-queue.js.map +0 -1
- package/packages/runtime-cli/dist/claude-history.d.ts.map +0 -1
- package/packages/runtime-cli/dist/claude-history.js.map +0 -1
- package/packages/runtime-cli/dist/claude-json.d.ts.map +0 -1
- package/packages/runtime-cli/dist/claude-json.js.map +0 -1
- package/packages/runtime-cli/dist/claude-rename.d.ts.map +0 -1
- package/packages/runtime-cli/dist/claude-rename.js.map +0 -1
- package/packages/runtime-cli/dist/claude-session-store.d.ts.map +0 -1
- package/packages/runtime-cli/dist/claude-session-store.js.map +0 -1
- package/packages/runtime-cli/dist/claude-turn.d.ts.map +0 -1
- package/packages/runtime-cli/dist/claude-turn.js.map +0 -1
- package/packages/runtime-cli/dist/codex-app-server.d.ts.map +0 -1
- package/packages/runtime-cli/dist/codex-app-server.js.map +0 -1
- package/packages/runtime-cli/dist/codex-approvals.d.ts.map +0 -1
- package/packages/runtime-cli/dist/codex-approvals.js.map +0 -1
- package/packages/runtime-cli/dist/codex-history.d.ts.map +0 -1
- package/packages/runtime-cli/dist/codex-history.js.map +0 -1
- package/packages/runtime-cli/dist/codex-json-rpc.d.ts.map +0 -1
- package/packages/runtime-cli/dist/codex-json-rpc.js.map +0 -1
- package/packages/runtime-cli/dist/codex-lifecycle.d.ts.map +0 -1
- package/packages/runtime-cli/dist/codex-lifecycle.js.map +0 -1
- package/packages/runtime-cli/dist/codex-protocol.d.ts.map +0 -1
- package/packages/runtime-cli/dist/codex-protocol.js.map +0 -1
- package/packages/runtime-cli/dist/command-resolver.d.ts.map +0 -1
- package/packages/runtime-cli/dist/command-resolver.js.map +0 -1
- package/packages/runtime-cli/dist/history-merge.d.ts.map +0 -1
- package/packages/runtime-cli/dist/history-merge.js.map +0 -1
- package/packages/runtime-cli/dist/index.d.ts.map +0 -1
- package/packages/runtime-cli/dist/index.js.map +0 -1
- package/packages/runtime-cli/dist/permissions.d.ts.map +0 -1
- package/packages/runtime-cli/dist/permissions.js.map +0 -1
- package/packages/runtime-cli/dist/session-store.d.ts.map +0 -1
- package/packages/runtime-cli/dist/session-store.js.map +0 -1
- package/packages/runtime-cli/package.json +0 -22
- package/packages/shared/dist/args.d.ts.map +0 -1
- package/packages/shared/dist/args.js.map +0 -1
- package/packages/shared/dist/crypto.d.ts.map +0 -1
- package/packages/shared/dist/crypto.js.map +0 -1
- package/packages/shared/dist/ids.d.ts.map +0 -1
- package/packages/shared/dist/ids.js.map +0 -1
- package/packages/shared/dist/index.d.ts.map +0 -1
- package/packages/shared/dist/index.js.map +0 -1
- package/packages/shared/dist/protocol-schemas.d.ts.map +0 -1
- package/packages/shared/dist/protocol-schemas.js.map +0 -1
- package/packages/shared/dist/protocol-types.d.ts.map +0 -1
- package/packages/shared/dist/protocol-types.js.map +0 -1
- package/packages/shared/dist/protocol.d.ts.map +0 -1
- package/packages/shared/dist/protocol.js.map +0 -1
- package/packages/shared/dist/session-name.d.ts.map +0 -1
- package/packages/shared/dist/session-name.js.map +0 -1
- package/packages/shared/dist/session-state.d.ts.map +0 -1
- package/packages/shared/dist/session-state.js.map +0 -1
- package/packages/shared/package.json +0 -24
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { normalizeSessionTags, sessionTagKeys } from "../../../../packages/shared/dist/index.js";
|
|
2
|
+
import { CliError, ControllerClient, compareSessionEventLogicalOrder, compactSessionListItem, compactText, conciseSessionSummary, deriveOrchestration, listWorkspaceHistoricalSessions, ok, parsePermissionMode, readConfig, readStoredTurnOutput, requirePositional, requireString, showSession, structuredSessionProjection, summarizeTurns, wantsJson, wantsVerbose } from "./lib/index.js";
|
|
2
3
|
function formatTurnTimestamp(value) {
|
|
3
4
|
return value === undefined ? "-" : new Date(value).toISOString();
|
|
4
5
|
}
|
|
@@ -26,6 +27,14 @@ function parsePositiveIntFlag(flags, name) {
|
|
|
26
27
|
}
|
|
27
28
|
return parsed;
|
|
28
29
|
}
|
|
30
|
+
function tagsFromFlagValue(value) {
|
|
31
|
+
if (typeof value !== "string")
|
|
32
|
+
return [];
|
|
33
|
+
return value.split(",").map((item) => item.trim()).filter(Boolean);
|
|
34
|
+
}
|
|
35
|
+
function tagsFromFlags(flags, names = ["tag", "tags"]) {
|
|
36
|
+
return normalizeSessionTags(names.flatMap((name) => tagsFromFlagValue(flags[name])));
|
|
37
|
+
}
|
|
29
38
|
function selectWindow(items, flags, defaultLimit) {
|
|
30
39
|
const limit = parsePositiveIntFlag(flags, "limit");
|
|
31
40
|
const tail = parsePositiveIntFlag(flags, "tail");
|
|
@@ -53,8 +62,298 @@ function compactTurnRef(turn) {
|
|
|
53
62
|
status: turn.status,
|
|
54
63
|
...(turn.prompt ? { promptPreview: compactText(turn.prompt, 180) } : {}),
|
|
55
64
|
time: turn.completedAt ?? turn.updatedAt,
|
|
65
|
+
...(turn.turnSeq !== undefined ? { turnSeq: turn.turnSeq } : {}),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function countBy(values) {
|
|
69
|
+
const counts = {};
|
|
70
|
+
for (const value of values)
|
|
71
|
+
counts[value] = (counts[value] ?? 0) + 1;
|
|
72
|
+
return counts;
|
|
73
|
+
}
|
|
74
|
+
function messagePrefix(messageId) {
|
|
75
|
+
if (!messageId)
|
|
76
|
+
return "none";
|
|
77
|
+
const index = messageId.indexOf("_");
|
|
78
|
+
return index > 0 ? messageId.slice(0, index) : "other";
|
|
79
|
+
}
|
|
80
|
+
function eventPayloadText(event) {
|
|
81
|
+
const payload = event.decoded;
|
|
82
|
+
if (!payload)
|
|
83
|
+
return event.decryptError ?? "";
|
|
84
|
+
if (payload.type === "user_prompt")
|
|
85
|
+
return payload.text;
|
|
86
|
+
if (payload.type === "text_delta")
|
|
87
|
+
return payload.text;
|
|
88
|
+
if (payload.type === "tool_call")
|
|
89
|
+
return `${payload.title ?? "tool"} ${payload.status ?? ""} ${payload.text ?? ""}`;
|
|
90
|
+
if (payload.type === "status" || payload.type === "control")
|
|
91
|
+
return payload.text;
|
|
92
|
+
if (payload.type === "done")
|
|
93
|
+
return payload.error ?? payload.stopReason ?? payload.status;
|
|
94
|
+
return "";
|
|
95
|
+
}
|
|
96
|
+
function isVisibleTranscriptPayloadEvent(event) {
|
|
97
|
+
const payload = event.decoded;
|
|
98
|
+
if (!payload)
|
|
99
|
+
return false;
|
|
100
|
+
return payload.type === "user_prompt" ||
|
|
101
|
+
(payload.type === "text_delta" && payload.stream !== "thought" && payload.text.trim().length > 0) ||
|
|
102
|
+
payload.type === "tool_call";
|
|
103
|
+
}
|
|
104
|
+
function compactEventDiagnostic(event) {
|
|
105
|
+
const text = compactText(eventPayloadText(event), 120);
|
|
106
|
+
return {
|
|
107
|
+
id: event.id,
|
|
108
|
+
...(event.messageId ? { messageId: event.messageId } : {}),
|
|
109
|
+
payloadType: event.decoded?.type ?? (event.decryptError ? "decrypt_error" : "encrypted"),
|
|
110
|
+
seq: event.seq,
|
|
111
|
+
...(text ? { textPreview: text } : {}),
|
|
112
|
+
turnId: event.turnId,
|
|
113
|
+
...(event.turnSeq !== undefined ? { turnSeq: event.turnSeq } : {}),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
function repairHeadInputForLatestCompletedEvent(events) {
|
|
117
|
+
const doneEvent = [...events]
|
|
118
|
+
.sort(compareSessionEventLogicalOrder)
|
|
119
|
+
.reverse()
|
|
120
|
+
.find((event) => event.decoded?.type === "done" && event.decoded.status === "completed");
|
|
121
|
+
const done = doneEvent?.decoded;
|
|
122
|
+
if (!doneEvent || done?.type !== "done") {
|
|
123
|
+
throw new CliError("No completed done event is available for head repair", "SESSION_HEAD_REPAIR_UNAVAILABLE");
|
|
124
|
+
}
|
|
125
|
+
if (!doneEvent.messageId) {
|
|
126
|
+
throw new CliError("Latest completed done event has no messageId basis", "SESSION_HEAD_REPAIR_UNAVAILABLE");
|
|
127
|
+
}
|
|
128
|
+
const turnSeq = doneEvent.turnSeq;
|
|
129
|
+
if (turnSeq === undefined) {
|
|
130
|
+
throw new CliError("Latest completed done event has no turnSeq basis", "SESSION_HEAD_REPAIR_UNAVAILABLE");
|
|
131
|
+
}
|
|
132
|
+
const currentHead = done.currentHead ?? done.lastTurnId ?? doneEvent.turnId;
|
|
133
|
+
const lastTurnId = done.lastTurnId ?? done.currentHead ?? doneEvent.turnId;
|
|
134
|
+
return {
|
|
135
|
+
currentHead,
|
|
136
|
+
lastTurnId,
|
|
137
|
+
status: "completed",
|
|
138
|
+
basis: {
|
|
139
|
+
turnId: doneEvent.turnId,
|
|
140
|
+
eventMessageId: doneEvent.messageId,
|
|
141
|
+
turnSeq,
|
|
142
|
+
...(doneEvent.occurredAt === undefined ? {} : { occurredAt: doneEvent.occurredAt }),
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
function eventCollectionDiagnostics(events) {
|
|
147
|
+
return {
|
|
148
|
+
decryptErrors: events.filter((event) => event.decryptError).length,
|
|
149
|
+
first: events.slice(0, 5).map(compactEventDiagnostic),
|
|
150
|
+
last: events.slice(-5).map(compactEventDiagnostic),
|
|
151
|
+
messagePrefixes: countBy(events.map((event) => messagePrefix(event.messageId))),
|
|
152
|
+
payloadTypes: countBy(events.map((event) => event.decoded?.type ?? (event.decryptError ? "decrypt_error" : "encrypted"))),
|
|
153
|
+
total: events.length,
|
|
154
|
+
visiblePayloads: events.filter(isVisibleTranscriptPayloadEvent).length,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function headMatchesTurn(session, turn) {
|
|
158
|
+
if (!turn)
|
|
159
|
+
return false;
|
|
160
|
+
const turnHeads = new Set([
|
|
161
|
+
turn.checkpointId,
|
|
162
|
+
turn.runtimeTurnId,
|
|
163
|
+
turn.turnId,
|
|
164
|
+
].filter((value) => typeof value === "string" && value.length > 0));
|
|
165
|
+
if (session.currentHead?.startsWith("event:")) {
|
|
166
|
+
const eventId = Number(/^event:(\d+)$/.exec(session.currentHead)?.[1]);
|
|
167
|
+
if (Number.isFinite(eventId) && eventId >= turn.firstEventId && eventId <= turn.lastEventId)
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
if (session.headBasis?.eventId !== undefined && session.headBasis.eventId >= turn.firstEventId && session.headBasis.eventId <= turn.lastEventId) {
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
return (session.currentHead !== undefined && turnHeads.has(session.currentHead)) ||
|
|
174
|
+
(session.lastTurnId !== undefined && turnHeads.has(session.lastTurnId));
|
|
175
|
+
}
|
|
176
|
+
function staleHeadSuspected(session, latestCompletedTurn) {
|
|
177
|
+
if (!latestCompletedTurn)
|
|
178
|
+
return false;
|
|
179
|
+
if (headMatchesTurn(session, latestCompletedTurn))
|
|
180
|
+
return false;
|
|
181
|
+
const basisTime = session.headBasis?.logicalTime;
|
|
182
|
+
const latestTime = latestCompletedTurn.completedAt ?? latestCompletedTurn.updatedAt;
|
|
183
|
+
if (basisTime !== undefined) {
|
|
184
|
+
if (latestTime !== basisTime)
|
|
185
|
+
return latestTime > basisTime;
|
|
186
|
+
if (session.headBasis?.turnSeq !== undefined && latestCompletedTurn.turnSeq !== undefined) {
|
|
187
|
+
return latestCompletedTurn.turnSeq > session.headBasis.turnSeq;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return Boolean(session.currentHead || session.lastTurnId);
|
|
191
|
+
}
|
|
192
|
+
function stringMetadata(metadata, key) {
|
|
193
|
+
const value = metadata[key];
|
|
194
|
+
return typeof value === "string" ? value : undefined;
|
|
195
|
+
}
|
|
196
|
+
function numberMetadata(metadata, key) {
|
|
197
|
+
const value = metadata[key];
|
|
198
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
199
|
+
}
|
|
200
|
+
function isRecord(value) {
|
|
201
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
202
|
+
}
|
|
203
|
+
function diagnosticSessionMetadata(metadata) {
|
|
204
|
+
const runtime = isRecord(metadata.runtime) ? metadata.runtime : {};
|
|
205
|
+
return {
|
|
206
|
+
agent: stringMetadata(metadata, "agent"),
|
|
207
|
+
cwd: stringMetadata(metadata, "cwd"),
|
|
208
|
+
name: stringMetadata(metadata, "name"),
|
|
209
|
+
providerName: stringMetadata(metadata, "providerName"),
|
|
210
|
+
importedFromRuntimeSessionId: stringMetadata(metadata, "importedFromRuntimeSessionId"),
|
|
211
|
+
runtime: {
|
|
212
|
+
backend: stringMetadata(runtime, "backend"),
|
|
213
|
+
runtimeSessionName: stringMetadata(runtime, "runtimeSessionName"),
|
|
214
|
+
acpxRecordId: stringMetadata(runtime, "acpxRecordId"),
|
|
215
|
+
backendSessionId: stringMetadata(runtime, "backendSessionId"),
|
|
216
|
+
agentSessionId: stringMetadata(runtime, "agentSessionId"),
|
|
217
|
+
externalProviderId: stringMetadata(runtime, "externalProviderId"),
|
|
218
|
+
externalHandleSessionId: isRecord(runtime.externalHandle) ? stringMetadata(runtime.externalHandle, "sessionId") : undefined,
|
|
219
|
+
},
|
|
220
|
+
historicalBackfillStatus: stringMetadata(metadata, "historicalBackfillStatus") ?? stringMetadata(metadata, "historicalBackfill"),
|
|
221
|
+
historicalBackfillCursor: numberMetadata(metadata, "historicalBackfillCursor"),
|
|
222
|
+
historicalBackfillTotalEvents: numberMetadata(metadata, "historicalBackfillTotalEvents"),
|
|
223
|
+
availableHistoricalEvents: numberMetadata(metadata, "availableHistoricalEvents"),
|
|
224
|
+
backfilledEvents: numberMetadata(metadata, "backfilledEvents"),
|
|
225
|
+
historicalOlderBackfilledEvents: numberMetadata(metadata, "historicalOlderBackfilledEvents"),
|
|
226
|
+
historicalTailRepairedEvents: numberMetadata(metadata, "historicalTailRepairedEvents"),
|
|
227
|
+
truncatedHistoricalBackfill: metadata.truncatedHistoricalBackfill === true,
|
|
228
|
+
importRequestId: stringMetadata(metadata, "importRequestId"),
|
|
229
|
+
currentHead: stringMetadata(metadata, "currentHead"),
|
|
230
|
+
emptyRuntimeSession: metadata.emptyRuntimeSession === true,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
function addRuntimeSessionId(ids, value) {
|
|
234
|
+
if (typeof value === "string" && value.trim())
|
|
235
|
+
ids.add(value.trim());
|
|
236
|
+
}
|
|
237
|
+
function metadataRuntimeSessionIds(metadata) {
|
|
238
|
+
const ids = new Set();
|
|
239
|
+
addRuntimeSessionId(ids, stringMetadata(metadata, "importedFromRuntimeSessionId"));
|
|
240
|
+
const runtime = isRecord(metadata.runtime) ? metadata.runtime : {};
|
|
241
|
+
addRuntimeSessionId(ids, runtime.backendSessionId);
|
|
242
|
+
addRuntimeSessionId(ids, runtime.agentSessionId);
|
|
243
|
+
addRuntimeSessionId(ids, runtime.acpxRecordId);
|
|
244
|
+
if (isRecord(runtime.externalHandle))
|
|
245
|
+
addRuntimeSessionId(ids, runtime.externalHandle.sessionId);
|
|
246
|
+
return ids;
|
|
247
|
+
}
|
|
248
|
+
function normalizedMatchValue(value) {
|
|
249
|
+
return typeof value === "string" && value.trim() ? value.trim().toLocaleLowerCase() : undefined;
|
|
250
|
+
}
|
|
251
|
+
function runtimeBindingCandidates(session, metadata, historicalSessions) {
|
|
252
|
+
const knownRuntimeIds = metadataRuntimeSessionIds(metadata);
|
|
253
|
+
const expectedAgent = stringMetadata(metadata, "agent") ?? session.agent;
|
|
254
|
+
const expectedCwd = stringMetadata(metadata, "cwd") ?? session.cwd;
|
|
255
|
+
const names = new Set([
|
|
256
|
+
normalizedMatchValue(stringMetadata(metadata, "name")),
|
|
257
|
+
normalizedMatchValue(stringMetadata(metadata, "providerName")),
|
|
258
|
+
normalizedMatchValue(session.name),
|
|
259
|
+
].filter((value) => Boolean(value)));
|
|
260
|
+
const summaries = new Set([
|
|
261
|
+
normalizedMatchValue(stringMetadata(metadata, "importedSummary")),
|
|
262
|
+
normalizedMatchValue(session.name),
|
|
263
|
+
].filter((value) => Boolean(value)));
|
|
264
|
+
return historicalSessions
|
|
265
|
+
.filter((historical) => historical.agent === expectedAgent &&
|
|
266
|
+
historical.cwd === expectedCwd &&
|
|
267
|
+
!knownRuntimeIds.has(historical.runtimeSessionId))
|
|
268
|
+
.map((historical) => {
|
|
269
|
+
const reasons = [];
|
|
270
|
+
let score = 0;
|
|
271
|
+
const historicalName = normalizedMatchValue(historical.name ?? historical.runtimeSessionName);
|
|
272
|
+
const historicalSummary = normalizedMatchValue(historical.summary);
|
|
273
|
+
if (historicalName && names.has(historicalName)) {
|
|
274
|
+
score += 100;
|
|
275
|
+
reasons.push("name");
|
|
276
|
+
}
|
|
277
|
+
if (historicalSummary && summaries.has(historicalSummary)) {
|
|
278
|
+
score += 30;
|
|
279
|
+
reasons.push("summary");
|
|
280
|
+
}
|
|
281
|
+
if (historical.loadedSessionId) {
|
|
282
|
+
score -= 20;
|
|
283
|
+
reasons.push("already-loaded");
|
|
284
|
+
}
|
|
285
|
+
if (score <= 0)
|
|
286
|
+
return undefined;
|
|
287
|
+
return {
|
|
288
|
+
runtimeSessionId: historical.runtimeSessionId,
|
|
289
|
+
agent: historical.agent,
|
|
290
|
+
cwd: historical.cwd,
|
|
291
|
+
name: historical.name ?? historical.runtimeSessionName,
|
|
292
|
+
summary: historical.summary,
|
|
293
|
+
updatedAt: historical.updatedAt,
|
|
294
|
+
score,
|
|
295
|
+
reasons,
|
|
296
|
+
...(historical.runtimeState === "archived" ? { runtimeState: "archived" } : {}),
|
|
297
|
+
};
|
|
298
|
+
})
|
|
299
|
+
.filter((candidate) => Boolean(candidate))
|
|
300
|
+
.sort((left, right) => right.score - left.score || right.updatedAt - left.updatedAt || left.runtimeSessionId.localeCompare(right.runtimeSessionId));
|
|
301
|
+
}
|
|
302
|
+
function shouldSearchRuntimeBindingCandidates(latestEvents, metadata) {
|
|
303
|
+
const available = numberMetadata(metadata, "availableHistoricalEvents");
|
|
304
|
+
const emitted = numberMetadata(metadata, "backfilledEvents");
|
|
305
|
+
return latestEvents.length === 0 &&
|
|
306
|
+
(available === undefined || available === 0) &&
|
|
307
|
+
(emitted === undefined || emitted === 0);
|
|
308
|
+
}
|
|
309
|
+
function runtimeBindingSuspected(candidates) {
|
|
310
|
+
return candidates.some((candidate) => candidate.reasons.includes("name") && !candidate.reasons.includes("already-loaded"));
|
|
311
|
+
}
|
|
312
|
+
async function findRuntimeBindingCandidates(client, session, metadata, flags) {
|
|
313
|
+
const limit = parsePositiveIntFlag(flags, "runtime-limit") ?? 500;
|
|
314
|
+
const result = await listWorkspaceHistoricalSessions(client, {
|
|
315
|
+
machineId: session.machineId,
|
|
316
|
+
cwd: stringMetadata(metadata, "cwd") ?? session.cwd,
|
|
317
|
+
agent: stringMetadata(metadata, "agent") ?? session.agent,
|
|
318
|
+
includeArchived: true,
|
|
319
|
+
limit,
|
|
320
|
+
});
|
|
321
|
+
return {
|
|
322
|
+
candidates: runtimeBindingCandidates(session, metadata, result.sessions).slice(0, 8),
|
|
323
|
+
searched: true,
|
|
324
|
+
limit,
|
|
56
325
|
};
|
|
57
326
|
}
|
|
327
|
+
async function resolveRuntimeBindingRepairTarget(client, session, metadata, flags) {
|
|
328
|
+
const runtimeSessionId = typeof flags["runtime-session"] === "string" ? flags["runtime-session"].trim() : undefined;
|
|
329
|
+
const limit = parsePositiveIntFlag(flags, "runtime-limit") ?? 500;
|
|
330
|
+
const result = await listWorkspaceHistoricalSessions(client, {
|
|
331
|
+
machineId: session.machineId,
|
|
332
|
+
cwd: stringMetadata(metadata, "cwd") ?? session.cwd,
|
|
333
|
+
agent: stringMetadata(metadata, "agent") ?? session.agent,
|
|
334
|
+
includeArchived: true,
|
|
335
|
+
limit,
|
|
336
|
+
});
|
|
337
|
+
const candidateDiagnostics = runtimeBindingCandidates(session, metadata, result.sessions);
|
|
338
|
+
if (runtimeSessionId) {
|
|
339
|
+
const explicit = result.sessions.find((item) => item.runtimeSessionId === runtimeSessionId);
|
|
340
|
+
if (!explicit)
|
|
341
|
+
throw new CliError(`Runtime session not found in the first ${limit} historical rows: ${runtimeSessionId}`, "RUNTIME_SESSION_NOT_FOUND");
|
|
342
|
+
return { candidate: explicit, candidates: candidateDiagnostics.slice(0, 8) };
|
|
343
|
+
}
|
|
344
|
+
const usableCandidates = candidateDiagnostics.filter((candidate) => !candidate.reasons.includes("already-loaded"));
|
|
345
|
+
if (usableCandidates.length === 0) {
|
|
346
|
+
throw new CliError("No unambiguous runtime binding repair candidate found. Re-run with --runtime-session <id>.", "SESSION_BINDING_REPAIR_UNAVAILABLE");
|
|
347
|
+
}
|
|
348
|
+
const [first, second] = usableCandidates;
|
|
349
|
+
if (second && second.score === first.score) {
|
|
350
|
+
throw new CliError("Multiple runtime binding repair candidates found. Re-run with --runtime-session <id>.", "SESSION_BINDING_REPAIR_AMBIGUOUS");
|
|
351
|
+
}
|
|
352
|
+
const selected = result.sessions.find((item) => item.runtimeSessionId === first.runtimeSessionId);
|
|
353
|
+
if (!selected)
|
|
354
|
+
throw new CliError("Selected repair candidate disappeared from runtime history", "SESSION_BINDING_REPAIR_UNAVAILABLE");
|
|
355
|
+
return { candidate: selected, candidates: candidateDiagnostics.slice(0, 8) };
|
|
356
|
+
}
|
|
58
357
|
export async function handleSession({ domain, action, positional, flags }) {
|
|
59
358
|
if (domain !== "session")
|
|
60
359
|
return false;
|
|
@@ -66,8 +365,21 @@ export async function handleSession({ domain, action, positional, flags }) {
|
|
|
66
365
|
const requestedRuntimeName = typeof flags.name === "string" ? flags.name : undefined;
|
|
67
366
|
const name = "main";
|
|
68
367
|
const permissionMode = parsePermissionMode(flags["permission-mode"] ?? flags.permission);
|
|
368
|
+
const model = typeof flags.model === "string" && flags.model.trim() ? flags.model.trim() : undefined;
|
|
369
|
+
const tags = tagsFromFlags(flags);
|
|
69
370
|
const client = await makeClient();
|
|
70
|
-
const result = await client.createSession({
|
|
371
|
+
const result = await client.createSession({
|
|
372
|
+
machineId,
|
|
373
|
+
agent,
|
|
374
|
+
cwd,
|
|
375
|
+
name,
|
|
376
|
+
runtimeName: requestedRuntimeName,
|
|
377
|
+
permissionMode,
|
|
378
|
+
model,
|
|
379
|
+
...(tags.length > 0 ? { tags } : {}),
|
|
380
|
+
...(flags.hidden === true ? { hiddenFromWorkspace: true } : {}),
|
|
381
|
+
...(typeof flags.source === "string" ? { source: flags.source } : {}),
|
|
382
|
+
});
|
|
71
383
|
const session = result.sessionId ? await client.getSession(result.sessionId) : undefined;
|
|
72
384
|
const projectedSession = session
|
|
73
385
|
? wantsVerbose(flags)
|
|
@@ -89,8 +401,13 @@ export async function handleSession({ domain, action, positional, flags }) {
|
|
|
89
401
|
agent: typeof flags.agent === "string" ? flags.agent : undefined,
|
|
90
402
|
cwd: cwdFilter,
|
|
91
403
|
name: typeof flags.name === "string" ? flags.name : undefined,
|
|
404
|
+
tags: tagsFromFlags(flags),
|
|
92
405
|
});
|
|
93
|
-
const visibleSessions = flags.all === true
|
|
406
|
+
const visibleSessions = flags.all === true
|
|
407
|
+
? allSessions
|
|
408
|
+
: (await Promise.all(allSessions.map(async (session) => ({ session, metadata: await client.decodeSessionMetadata(session) }))))
|
|
409
|
+
.filter(({ session, metadata }) => session.status !== "closed" && metadata.hiddenFromWorkspace !== true)
|
|
410
|
+
.map(({ session }) => session);
|
|
94
411
|
const { items: sessions, page } = selectWindow(visibleSessions, flags, 20);
|
|
95
412
|
if (wantsJson(flags) || wantsVerbose(flags)) {
|
|
96
413
|
const machinesById = new Map();
|
|
@@ -126,6 +443,37 @@ export async function handleSession({ domain, action, positional, flags }) {
|
|
|
126
443
|
}
|
|
127
444
|
return true;
|
|
128
445
|
}
|
|
446
|
+
if (action === "tag") {
|
|
447
|
+
const subaction = requirePositional(positional[0], "tag action");
|
|
448
|
+
const sessionId = requirePositional(positional[1], "sessionId");
|
|
449
|
+
const client = await makeClient();
|
|
450
|
+
const session = await client.getSession(sessionId);
|
|
451
|
+
if (!session)
|
|
452
|
+
throw new CliError("Session not found", "SESSION_NOT_FOUND");
|
|
453
|
+
const metadata = await client.decodeSessionMetadata(session);
|
|
454
|
+
const currentTags = normalizeSessionTags(metadata.tags);
|
|
455
|
+
if (subaction === "list") {
|
|
456
|
+
ok("session.tag.list", { sessionId, tags: currentTags, tagKeys: sessionTagKeys(currentTags) }, { sessionId });
|
|
457
|
+
return true;
|
|
458
|
+
}
|
|
459
|
+
const requested = tagsFromFlags(flags);
|
|
460
|
+
if (requested.length === 0)
|
|
461
|
+
throw new CliError("Missing --tag", "MISSING_ARGUMENT");
|
|
462
|
+
if (subaction === "add") {
|
|
463
|
+
const tags = normalizeSessionTags([...currentTags, ...requested]);
|
|
464
|
+
const result = await client.setSessionTags(sessionId, tags);
|
|
465
|
+
ok("session.tag.add", { sessionId, tags: result.tags, tagKeys: sessionTagKeys(result.tags) }, { sessionId });
|
|
466
|
+
return true;
|
|
467
|
+
}
|
|
468
|
+
if (subaction === "remove") {
|
|
469
|
+
const removeKeys = new Set(sessionTagKeys(requested));
|
|
470
|
+
const tags = currentTags.filter((tag) => !removeKeys.has(sessionTagKeys([tag])[0]));
|
|
471
|
+
const result = await client.setSessionTags(sessionId, tags);
|
|
472
|
+
ok("session.tag.remove", { sessionId, tags: result.tags, tagKeys: sessionTagKeys(result.tags) }, { sessionId });
|
|
473
|
+
return true;
|
|
474
|
+
}
|
|
475
|
+
throw new CliError(`Unsupported session tag action: ${subaction}`, "USAGE");
|
|
476
|
+
}
|
|
129
477
|
if (action === "status") {
|
|
130
478
|
const sessionId = requirePositional(positional[0], "sessionId");
|
|
131
479
|
const client = await makeClient();
|
|
@@ -140,7 +488,7 @@ export async function handleSession({ domain, action, positional, flags }) {
|
|
|
140
488
|
const latestCompletedTurn = turns.find((turn) => turn.status === "completed");
|
|
141
489
|
const latestTerminalTurn = turns.find((turn) => turn.status !== "running");
|
|
142
490
|
const orchestration = deriveOrchestration(session, recentEvents);
|
|
143
|
-
const latestOutput = await readStoredTurnOutput(session.id).catch(() => undefined);
|
|
491
|
+
const latestOutput = await readStoredTurnOutput(session.id, latestCompletedTurn?.turnId).catch(async () => await readStoredTurnOutput(session.id).catch(() => undefined));
|
|
144
492
|
const terminalOutput = latestCompletedTurn?.output || latestCompletedTurn?.terminalText || latestTerminalTurn?.output || latestTerminalTurn?.terminalText || undefined;
|
|
145
493
|
const data = {
|
|
146
494
|
state: orchestration.state,
|
|
@@ -192,6 +540,170 @@ export async function handleSession({ domain, action, positional, flags }) {
|
|
|
192
540
|
}
|
|
193
541
|
return true;
|
|
194
542
|
}
|
|
543
|
+
if (action === "diagnose") {
|
|
544
|
+
const sessionId = requirePositional(positional[0], "sessionId");
|
|
545
|
+
const limit = parsePositiveIntFlag(flags, "limit") ?? 200;
|
|
546
|
+
const client = await makeClient();
|
|
547
|
+
const snapshot = await client.snapshot();
|
|
548
|
+
const initialSession = snapshot.sessions.find((item) => item.id === sessionId);
|
|
549
|
+
if (!initialSession)
|
|
550
|
+
throw new CliError("Session not found", "SESSION_NOT_FOUND");
|
|
551
|
+
let session = initialSession;
|
|
552
|
+
const machine = snapshot.machines.find((item) => item.id === session.machineId);
|
|
553
|
+
const metadata = await client.decodeSessionMetadata(session);
|
|
554
|
+
const latestPage = await client.collectPage(session.id, { limit });
|
|
555
|
+
const turns = summarizeTurns(latestPage.events);
|
|
556
|
+
const latestCompletedTurn = turns.find((turn) => turn.status === "completed");
|
|
557
|
+
const latestTerminalTurn = turns.find((turn) => turn.status !== "running");
|
|
558
|
+
const runtimeBinding = shouldSearchRuntimeBindingCandidates(latestPage.events, metadata)
|
|
559
|
+
? await findRuntimeBindingCandidates(client, session, metadata, flags)
|
|
560
|
+
: { candidates: [], searched: false, limit: parsePositiveIntFlag(flags, "runtime-limit") ?? 500 };
|
|
561
|
+
const repair = flags["repair-head"] === true
|
|
562
|
+
? await client.repairSessionHead(session.id, repairHeadInputForLatestCompletedEvent(latestPage.events))
|
|
563
|
+
: undefined;
|
|
564
|
+
if (repair)
|
|
565
|
+
session = repair.session;
|
|
566
|
+
const data = {
|
|
567
|
+
generatedAt: new Date().toISOString(),
|
|
568
|
+
session: {
|
|
569
|
+
id: session.id,
|
|
570
|
+
machineId: session.machineId,
|
|
571
|
+
agent: session.agent,
|
|
572
|
+
status: session.status,
|
|
573
|
+
name: session.name,
|
|
574
|
+
cwd: session.cwd,
|
|
575
|
+
historyModel: session.historyModel ?? "append-only",
|
|
576
|
+
currentHead: session.currentHead,
|
|
577
|
+
lastTurnId: session.lastTurnId,
|
|
578
|
+
headBasis: session.headBasis,
|
|
579
|
+
sourceSessionId: session.sourceSessionId,
|
|
580
|
+
sourceCheckpointId: session.sourceCheckpointId,
|
|
581
|
+
updatedAt: session.updatedAt,
|
|
582
|
+
capabilities: session.capabilities,
|
|
583
|
+
},
|
|
584
|
+
machine: machine ? {
|
|
585
|
+
id: machine.id,
|
|
586
|
+
name: machine.name,
|
|
587
|
+
online: machine.online,
|
|
588
|
+
agents: machine.capabilities.agents.map((agent) => ({
|
|
589
|
+
id: agent.id,
|
|
590
|
+
historyModel: agent.historyModel,
|
|
591
|
+
sessionPrimitives: agent.sessionPrimitives,
|
|
592
|
+
})),
|
|
593
|
+
} : undefined,
|
|
594
|
+
metadata: diagnosticSessionMetadata(metadata),
|
|
595
|
+
latestPage: {
|
|
596
|
+
limit,
|
|
597
|
+
hasMoreBefore: latestPage.hasMoreBefore,
|
|
598
|
+
newestCursor: latestPage.newestCursor,
|
|
599
|
+
newestEventId: latestPage.newestEventId,
|
|
600
|
+
oldestCursor: latestPage.oldestCursor,
|
|
601
|
+
oldestEventId: latestPage.oldestEventId,
|
|
602
|
+
events: eventCollectionDiagnostics(latestPage.events),
|
|
603
|
+
},
|
|
604
|
+
turns: {
|
|
605
|
+
count: turns.length,
|
|
606
|
+
latestCompletedTurn: compactTurnRef(latestCompletedTurn),
|
|
607
|
+
latestTerminalTurn: compactTurnRef(latestTerminalTurn),
|
|
608
|
+
first: turns.slice(0, 4).map(compactTurnRef),
|
|
609
|
+
last: turns.slice(-4).map(compactTurnRef),
|
|
610
|
+
},
|
|
611
|
+
diagnosis: {
|
|
612
|
+
importedRuntimeSessionId: stringMetadata(metadata, "importedFromRuntimeSessionId"),
|
|
613
|
+
latestPageEmpty: latestPage.events.length === 0,
|
|
614
|
+
latestPageHasVisibleTranscript: latestPage.events.some(isVisibleTranscriptPayloadEvent),
|
|
615
|
+
metadataReportsEmptyRuntimeSession: metadata.emptyRuntimeSession === true,
|
|
616
|
+
backfillAvailableEvents: numberMetadata(metadata, "availableHistoricalEvents"),
|
|
617
|
+
backfillEmittedEvents: numberMetadata(metadata, "backfilledEvents"),
|
|
618
|
+
backfillStatus: stringMetadata(metadata, "historicalBackfillStatus") ?? stringMetadata(metadata, "historicalBackfill"),
|
|
619
|
+
wrongRuntimeBindingSuspected: runtimeBindingSuspected(runtimeBinding.candidates),
|
|
620
|
+
runtimeBindingCandidateCount: runtimeBinding.candidates.length,
|
|
621
|
+
staleHeadSuspected: staleHeadSuspected(session, latestCompletedTurn),
|
|
622
|
+
headMatchesLatestCompletedTurn: headMatchesTurn(session, latestCompletedTurn),
|
|
623
|
+
},
|
|
624
|
+
runtimeBinding: {
|
|
625
|
+
searched: runtimeBinding.searched,
|
|
626
|
+
searchLimit: runtimeBinding.limit,
|
|
627
|
+
suspected: runtimeBindingSuspected(runtimeBinding.candidates),
|
|
628
|
+
candidates: runtimeBinding.candidates,
|
|
629
|
+
repairCommand: runtimeBinding.candidates[0]
|
|
630
|
+
? `happy-elves session repair-binding ${session.id} --runtime-session ${runtimeBinding.candidates[0].runtimeSessionId} --json`
|
|
631
|
+
: undefined,
|
|
632
|
+
},
|
|
633
|
+
repair: repair ? {
|
|
634
|
+
advanced: repair.advanced,
|
|
635
|
+
settled: repair.settled,
|
|
636
|
+
basis: repair.basis,
|
|
637
|
+
status: repair.session.status,
|
|
638
|
+
currentHead: repair.session.currentHead,
|
|
639
|
+
lastTurnId: repair.session.lastTurnId,
|
|
640
|
+
reason: repair.reason,
|
|
641
|
+
} : undefined,
|
|
642
|
+
};
|
|
643
|
+
if (wantsJson(flags) || wantsVerbose(flags)) {
|
|
644
|
+
ok("session.diagnose", data, { machineId: session.machineId, sessionId: session.id });
|
|
645
|
+
}
|
|
646
|
+
else {
|
|
647
|
+
console.log(`Session: ${session.id} ${session.status} ${session.agent}`);
|
|
648
|
+
console.log(`Machine: ${session.machineId}${machine ? ` ${machine.online ? "online" : "offline"}` : ""}`);
|
|
649
|
+
const runtime = isRecord(metadata.runtime) ? metadata.runtime : {};
|
|
650
|
+
console.log(`Runtime: ${stringMetadata(metadata, "importedFromRuntimeSessionId") ?? stringMetadata(runtime, "backendSessionId") ?? stringMetadata(runtime, "agentSessionId") ?? "-"}`);
|
|
651
|
+
console.log(`Backfill: ${data.diagnosis.backfillStatus ?? "-"} available=${data.diagnosis.backfillAvailableEvents ?? "-"} emitted=${data.diagnosis.backfillEmittedEvents ?? "-"}`);
|
|
652
|
+
console.log(`Head: ${session.currentHead ?? "-"} lastTurn=${session.lastTurnId ?? "-"} stale=${data.diagnosis.staleHeadSuspected ? "yes" : "no"}`);
|
|
653
|
+
console.log(`Latest page: ${latestPage.events.length} events, visible=${latestPage.events.filter(isVisibleTranscriptPayloadEvent).length}, hasMore=${latestPage.hasMoreBefore}`);
|
|
654
|
+
if (data.runtimeBinding.suspected && data.runtimeBinding.candidates[0]) {
|
|
655
|
+
console.log(`Runtime binding: suspected wrong binding; candidate=${data.runtimeBinding.candidates[0].runtimeSessionId}`);
|
|
656
|
+
console.log(`Repair: ${data.runtimeBinding.repairCommand}`);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
return true;
|
|
660
|
+
}
|
|
661
|
+
if (action === "repair-binding") {
|
|
662
|
+
const sessionId = requirePositional(positional[0], "sessionId");
|
|
663
|
+
const client = await makeClient();
|
|
664
|
+
const session = await client.getSession(sessionId);
|
|
665
|
+
if (!session)
|
|
666
|
+
throw new CliError("Session not found", "SESSION_NOT_FOUND");
|
|
667
|
+
if (session.status === "running")
|
|
668
|
+
throw new CliError("Cannot repair binding for a running session", "SESSION_BINDING_REPAIR_RUNNING");
|
|
669
|
+
const metadata = await client.decodeSessionMetadata(session);
|
|
670
|
+
const { candidate, candidates } = await resolveRuntimeBindingRepairTarget(client, session, metadata, flags);
|
|
671
|
+
const name = typeof flags.name === "string" && flags.name.trim()
|
|
672
|
+
? flags.name.trim()
|
|
673
|
+
: stringMetadata(metadata, "name") ?? session.name ?? candidate.name ?? candidate.summary ?? candidate.runtimeSessionId;
|
|
674
|
+
const imported = await client.importHistoricalSession({
|
|
675
|
+
machineId: session.machineId,
|
|
676
|
+
agent: candidate.agent,
|
|
677
|
+
cwd: candidate.cwd,
|
|
678
|
+
runtimeSessionId: candidate.runtimeSessionId,
|
|
679
|
+
name,
|
|
680
|
+
summary: candidate.summary,
|
|
681
|
+
runtimeState: candidate.runtimeState,
|
|
682
|
+
...(candidate.name ? { providerName: candidate.name } : {}),
|
|
683
|
+
});
|
|
684
|
+
const closeSource = flags["keep-source"] !== true;
|
|
685
|
+
let sourceClosed = false;
|
|
686
|
+
if (closeSource) {
|
|
687
|
+
await client.close(session.id, `replaced by runtime session ${candidate.runtimeSessionId}`);
|
|
688
|
+
sourceClosed = true;
|
|
689
|
+
}
|
|
690
|
+
ok("session.repair-binding", {
|
|
691
|
+
sourceSessionId: session.id,
|
|
692
|
+
sessionId: imported.sessionId,
|
|
693
|
+
runtimeSessionId: candidate.runtimeSessionId,
|
|
694
|
+
mode: imported.mode === "existing" ? "existing" : "created",
|
|
695
|
+
sourceClosed,
|
|
696
|
+
candidate: {
|
|
697
|
+
runtimeSessionId: candidate.runtimeSessionId,
|
|
698
|
+
name: candidate.name ?? candidate.runtimeSessionName,
|
|
699
|
+
summary: candidate.summary,
|
|
700
|
+
updatedAt: candidate.updatedAt,
|
|
701
|
+
...(candidate.runtimeState === "archived" ? { runtimeState: "archived" } : {}),
|
|
702
|
+
},
|
|
703
|
+
candidates,
|
|
704
|
+
}, { requestId: imported.requestId, machineId: session.machineId, sessionId: imported.sessionId });
|
|
705
|
+
return true;
|
|
706
|
+
}
|
|
195
707
|
if (action === "history") {
|
|
196
708
|
const machineId = requireString(flags, "machine");
|
|
197
709
|
const limit = parsePositiveIntFlag(flags, "limit") ?? 20;
|
|
@@ -280,7 +792,7 @@ export async function handleSession({ domain, action, positional, flags }) {
|
|
|
280
792
|
ok("session.continue", {
|
|
281
793
|
sessionId: continued.sessionId,
|
|
282
794
|
runtimeSessionId,
|
|
283
|
-
mode: "created",
|
|
795
|
+
mode: continued.mode === "existing" ? "existing" : "created",
|
|
284
796
|
...(historical.runtimeState === "archived" ? { runtimeState: "archived" } : {}),
|
|
285
797
|
}, { requestId: continued.requestId, machineId, sessionId: continued.sessionId });
|
|
286
798
|
return true;
|