@platless/axom-cli 0.3.13 → 0.6.36
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 +18 -5
- package/dist/axom-patch/cli/README.md +119 -9
- package/dist/axom-patch/cli/account-limits/README.md +27 -0
- package/dist/axom-patch/cli/account-limits/antigravity-proxy.mjs +47 -0
- package/dist/axom-patch/cli/account-limits/antigravity-read.mjs +90 -0
- package/dist/axom-patch/cli/account-limits/antigravity.mjs +46 -0
- package/dist/axom-patch/cli/account-limits/generate.py +123 -0
- package/dist/axom-patch/cli/account-limits/kimi-proxy.mjs +81 -0
- package/dist/axom-patch/cli/account-limits/normalize.mjs +151 -0
- package/dist/axom-patch/cli/claude-account-limits.json +37 -0
- package/dist/axom-patch/cli/codex-account-limits.json +37 -0
- package/dist/axom-patch/cli/codex-terminal-output.json +16 -0
- package/dist/axom-patch/cli/commandcode-account-limits.json +30 -0
- package/dist/axom-patch/cli/kimi-quota.mjs +12 -0
- package/dist/axom-patch/cli/kimi-subagents.mjs +173 -0
- package/dist/axom-patch/cli/nightly-task.md +194 -0
- package/dist/axom-patch/cli/pi-subagent-subwork.json +23 -0
- package/dist/axom-patch/cli/probes/claude-late-async-terminal.mjs +5 -1
- package/dist/axom-patch/cli/probes/codex-terminal-output.mjs +33 -0
- package/dist/axom-patch/cli/probes/kimi-subagent-subwork.mjs +82 -0
- package/dist/axom-patch/cli/probes/pi-subagent-subwork.mjs +211 -0
- package/dist/axom-patch/cli/probes/zcode-subagent-subwork.mjs +257 -0
- package/dist/axom-patch/cli/qoder/dist/axom-acp-compat.mjs +1591 -0
- package/dist/axom-patch/cli/qoder/releases/1.1.75.json +360 -0
- package/dist/axom-patch/cli/qoder-background-terminal.md +13 -5
- package/dist/axom-patch/cli/qoder-foreground-output.md +14 -7
- package/dist/axom-patch/cli/qoder-native-acp.json +227 -0
- package/dist/axom-patch/cli/qoder-steering.md +20 -25
- package/dist/axom-patch/cli/qoder-subagent-subwork.md +17 -68
- package/dist/axom-patch/cli/runtime.json +39 -15
- package/dist/axom-patch/cli/zcode-account-limits.json +30 -0
- package/dist/axom-patch/cli/zcode-models.json +37 -0
- package/dist/axom-patch/cli/zcode-subagent-subwork.json +72 -0
- package/dist/cli.js +4 -9
- package/dist/commands/knowledge.js +47 -0
- package/dist/commands/update.js +65 -3
- package/dist/commands/workstation.js +73 -7
- package/dist/install/claude/commands.js +13 -13
- package/dist/keepers/acp/keeper.mjs +3083 -0
- package/dist/keepers/acp/manifest.json +9 -0
- package/dist/keepers/terminal/keeper.mjs +8469 -0
- package/dist/keepers/terminal/manifest.json +9 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/conpty_console_list_agent.js +25 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/eventEmitter2.js +47 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/index.js +52 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/interfaces.js +7 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/shared/conout.js +10 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/terminal.js +190 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/types.js +7 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/unixTerminal.js +351 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/utils.js +38 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/windowsConoutConnection.js +131 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/windowsPtyAgent.js +344 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/windowsTerminal.js +209 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/worker/conoutSocketWorker.js +22 -0
- package/dist/keepers/terminal/node_modules/node-pty/package.json +66 -0
- package/dist/keepers/terminal/node_modules/node-pty/prebuilds/darwin-arm64/pty.node +0 -0
- package/dist/keepers/terminal/node_modules/node-pty/prebuilds/darwin-arm64/spawn-helper +0 -0
- package/dist/keepers/terminal/node_modules/node-pty/prebuilds/darwin-x64/pty.node +0 -0
- package/dist/keepers/terminal/node_modules/node-pty/prebuilds/darwin-x64/spawn-helper +0 -0
- package/dist/keepers/terminal/node_modules/node-pty/prebuilds/linux-arm64/pty.node +0 -0
- package/dist/keepers/terminal/node_modules/node-pty/prebuilds/linux-x64/pty.node +0 -0
- package/dist/mcp.js +1 -1
- package/dist/native/darwin-arm64/axom-quic +0 -0
- package/dist/test/keeperKit.js +67 -0
- package/dist/workstation/acp/acpAgents.js +2192 -636
- package/dist/workstation/acp/acpClient.js +84 -495
- package/dist/workstation/acp/adoption.js +10 -396
- package/dist/workstation/acp/binaryInstall.js +100 -27
- package/dist/workstation/acp/builds/gc.js +245 -0
- package/dist/workstation/acp/builds/install/binary.js +28 -0
- package/dist/workstation/acp/builds/install/npm.js +324 -0
- package/dist/workstation/acp/builds/install/uv.js +254 -0
- package/dist/workstation/acp/builds/migrate.js +195 -0
- package/dist/workstation/acp/builds/model.js +128 -0
- package/dist/workstation/acp/builds/nodeGate.js +100 -0
- package/dist/workstation/acp/builds/store.js +352 -0
- package/dist/workstation/acp/commandTableProbe.js +68 -0
- package/dist/workstation/acp/configOptions.js +103 -1
- package/dist/workstation/acp/envSecrets.js +27 -0
- package/dist/workstation/acp/initializeResponse.js +290 -0
- package/dist/workstation/acp/installErrors.js +12 -2
- package/dist/workstation/acp/installProbe.js +1 -1
- package/dist/workstation/acp/managedPatches.js +239 -159
- package/dist/workstation/acp/managedRuntime.js +314 -0
- package/dist/workstation/acp/outbox.js +330 -0
- package/dist/workstation/acp/patchAssets.js +60 -3
- package/dist/workstation/acp/permission.js +42 -10
- package/dist/workstation/acp/processor/checkpoint.js +78 -0
- package/dist/workstation/acp/processor/commands.js +35 -0
- package/dist/workstation/acp/processor/control.js +282 -0
- package/dist/workstation/acp/processor/emit.js +26 -0
- package/dist/workstation/acp/processor/jsonrpc.js +172 -0
- package/dist/workstation/acp/processor/memoryLog.js +49 -0
- package/dist/workstation/acp/processor/origins.js +48 -0
- package/dist/workstation/acp/processor/output.js +67 -0
- package/dist/workstation/acp/processor/projection.js +42 -0
- package/dist/workstation/acp/processor/record.js +128 -0
- package/dist/workstation/acp/processor/runtime.js +105 -0
- package/dist/workstation/acp/processor/sdkSchemas.js +61 -0
- package/dist/workstation/acp/processor/session.js +496 -0
- package/dist/workstation/acp/processor/state.js +67 -0
- package/dist/workstation/acp/processor/step.js +442 -0
- package/dist/workstation/acp/processor/test/fixtureLog.js +58 -0
- package/dist/workstation/acp/processor/test/harness.js +120 -0
- package/dist/workstation/acp/processor/test/largeIdEcho.js +50 -0
- package/dist/workstation/acp/processor/test/rawAgent.js +70 -0
- package/dist/workstation/acp/processor/transport/generations.js +76 -0
- package/dist/workstation/acp/processor/transport/keeper.js +130 -0
- package/dist/workstation/acp/processor/transport/local.js +269 -0
- package/dist/workstation/acp/processor/transport/types.js +78 -0
- package/dist/workstation/acp/processor/updates.js +390 -0
- package/dist/workstation/acp/processorSession.js +1348 -0
- package/dist/workstation/acp/registry/catalog.js +189 -41
- package/dist/workstation/acp/registry/launch.js +76 -119
- package/dist/workstation/acp/sessionUpdateMapper.js +18 -7
- package/dist/workstation/acp/steering.js +58 -0
- package/dist/workstation/acp/switching.js +111 -0
- package/dist/workstation/acp/terminalLogin.js +16 -42
- package/dist/workstation/acp/terminalLoginSpec.js +41 -0
- package/dist/workstation/acp/test/adapterFixtures.js +256 -0
- package/dist/workstation/acp/test/daemonLife.js +106 -0
- package/dist/workstation/acp/test/fakeAgent.js +13 -0
- package/dist/workstation/acp/test/keeperWorld.js +295 -0
- package/dist/workstation/acp/test/memoryOutbox.js +55 -0
- package/dist/workstation/acp/test/raw/fixtures.js +196 -0
- package/dist/workstation/acp/test/raw/sanitize.js +344 -0
- package/dist/workstation/acp/test/raw/sources.js +135 -0
- package/dist/workstation/acp/test/realAdapter.js +331 -0
- package/dist/workstation/acp/test/scriptAgent.js +214 -0
- package/dist/workstation/acp/test/sessionFrames.js +42 -0
- package/dist/workstation/acp/timedCommand.js +4 -2
- package/dist/workstation/acp/uvxInstall.js +72 -122
- package/dist/workstation/agentFlow.js +103 -0
- package/dist/workstation/agentSessions.js +1289 -544
- package/dist/workstation/channels/agent.js +7 -5
- package/dist/workstation/channels/computer.js +69 -21
- package/dist/workstation/channels/computerExecs.js +200 -0
- package/dist/workstation/channels/management.js +172 -8
- package/dist/workstation/channels/url.js +1 -1
- package/dist/workstation/config.js +16 -4
- package/dist/workstation/connection/encryptedChannel.js +4 -1
- package/dist/workstation/control/bindingStore.js +200 -0
- package/dist/workstation/control/commands.js +124 -0
- package/dist/workstation/control/daemonIdentity.js +53 -0
- package/dist/workstation/control/enrollment.js +106 -0
- package/dist/workstation/control/inspect.js +71 -0
- package/dist/workstation/control/locks.js +63 -0
- package/dist/workstation/control/protocol.js +40 -0
- package/dist/workstation/control/restartGuard.js +46 -0
- package/dist/workstation/control/runtimeClient.js +97 -0
- package/dist/workstation/control/runtimeHost.js +148 -0
- package/dist/workstation/control/serverIdentity.js +35 -0
- package/dist/workstation/daemon.js +393 -12
- package/dist/workstation/daemonctl.js +103 -14
- package/dist/workstation/desktopControl/audio.js +99 -0
- package/dist/workstation/desktopControl/capabilities.js +92 -0
- package/dist/workstation/desktopControl/captureModes.js +9 -0
- package/dist/workstation/desktopControl/captureTargetLabel.js +9 -0
- package/dist/workstation/desktopControl/deviceSockets.js +246 -0
- package/dist/workstation/desktopControl/helperProcess.js +353 -0
- package/dist/workstation/desktopControl/lobby.js +129 -0
- package/dist/workstation/desktopControl/macProvider.js +155 -0
- package/dist/workstation/desktopControl/media.js +331 -0
- package/dist/workstation/desktopControl/nativeProvider.js +1018 -0
- package/dist/workstation/desktopControl/networkEvidence.js +43 -0
- package/dist/workstation/desktopControl/overview.js +58 -0
- package/dist/workstation/desktopControl/protocol.js +302 -0
- package/dist/workstation/desktopControl/quicMedia.js +240 -0
- package/dist/workstation/desktopControl/rateController.js +226 -0
- package/dist/workstation/desktopControl/supervisor.js +1681 -0
- package/dist/workstation/desktopControl/transport.js +27 -0
- package/dist/workstation/desktopControl/wallpaper.js +78 -0
- package/dist/workstation/exec/attach.js +126 -0
- package/dist/workstation/exec/command.js +40 -0
- package/dist/workstation/exec/durable.js +517 -0
- package/dist/workstation/exec/fallback.js +106 -0
- package/dist/workstation/exec/policy.js +837 -0
- package/dist/workstation/exec/shaping.js +211 -0
- package/dist/workstation/exec.js +3 -112
- package/dist/workstation/files/adapters/computerFileFrames.js +51 -0
- package/dist/workstation/files/adapters/toolRequests.js +121 -0
- package/dist/workstation/files/client.js +455 -0
- package/dist/workstation/files/credentials.js +142 -0
- package/dist/workstation/files/errors.js +28 -0
- package/dist/workstation/files/fence.js +350 -0
- package/dist/workstation/files/find/fileIndex.js +153 -0
- package/dist/workstation/files/find/fuzzy.js +155 -0
- package/dist/workstation/files/host.js +122 -0
- package/dist/workstation/files/hostProtocol.js +2 -0
- package/dist/workstation/files/media/cache.js +620 -0
- package/dist/workstation/files/media/encoding.js +308 -0
- package/dist/workstation/files/media/estimator.js +100 -0
- package/dist/workstation/files/media/media.js +325 -0
- package/dist/workstation/files/media/packedAudio.js +23 -0
- package/dist/workstation/files/media/scheduler.js +551 -0
- package/dist/workstation/files/media/types.js +5 -0
- package/dist/workstation/files/scope.js +45 -0
- package/dist/workstation/files/structured.js +284 -0
- package/dist/workstation/{fileOps.js → files/text.js} +152 -39
- package/dist/workstation/files/uploads.js +351 -0
- package/dist/workstation/journal.js +65 -236
- package/dist/workstation/keepers/acp/client.js +101 -0
- package/dist/workstation/keepers/acp/envelope.js +62 -0
- package/dist/workstation/keepers/acp/host.js +419 -0
- package/dist/workstation/keepers/acp/main.js +18 -0
- package/dist/workstation/keepers/acp/memoryStream.js +121 -0
- package/dist/workstation/keepers/acp/params.js +137 -0
- package/dist/workstation/keepers/acp/protocol.js +66 -0
- package/dist/workstation/keepers/acp/recover.js +120 -0
- package/dist/workstation/keepers/acp/session.js +584 -0
- package/dist/workstation/keepers/acp/stderr.js +154 -0
- package/dist/workstation/keepers/kit/activity.js +103 -0
- package/dist/workstation/keepers/kit/bootstrap.js +164 -0
- package/dist/workstation/keepers/kit/buildVersion.js +51 -0
- package/dist/workstation/keepers/kit/bundle.js +124 -0
- package/dist/workstation/keepers/kit/client.js +432 -0
- package/dist/workstation/keepers/kit/identity.js +21 -0
- package/dist/workstation/keepers/kit/ipc.js +112 -0
- package/dist/workstation/keepers/kit/launchConfig.js +8 -0
- package/dist/workstation/keepers/kit/launcher.js +289 -0
- package/dist/workstation/keepers/kit/lock.js +123 -0
- package/dist/workstation/keepers/kit/orphanSweep.js +86 -0
- package/dist/workstation/keepers/kit/paths.js +76 -0
- package/dist/workstation/keepers/kit/protocol.js +43 -0
- package/dist/workstation/keepers/kit/server.js +518 -0
- package/dist/workstation/keepers/kit/streamLog.js +697 -0
- package/dist/workstation/keepers/legacy.js +296 -0
- package/dist/workstation/keepers/policy.js +576 -0
- package/dist/workstation/keepers/stop.js +34 -0
- package/dist/workstation/keepers/terminal/client.js +213 -0
- package/dist/workstation/keepers/terminal/exec.js +981 -0
- package/dist/workstation/keepers/terminal/generations.js +129 -0
- package/dist/workstation/keepers/terminal/keeper.js +62 -0
- package/dist/workstation/keepers/terminal/main.js +43 -0
- package/dist/workstation/keepers/terminal/orphanSweep.js +3 -0
- package/dist/workstation/keepers/terminal/params.js +27 -0
- package/dist/workstation/keepers/terminal/protocol.js +56 -0
- package/dist/workstation/keepers/terminal/pty.js +330 -0
- package/dist/workstation/managedInstall.js +57 -0
- package/dist/workstation/protocol/accountLimits.js +47 -0
- package/dist/workstation/protocol/agent.js +50 -19
- package/dist/workstation/protocol/common.js +30 -0
- package/dist/workstation/protocol/computer.js +15 -4
- package/dist/workstation/protocol/management.js +141 -4
- package/dist/workstation/protocol/runtimeDiagnostics.js +15 -0
- package/dist/workstation/rd/artifact.js +119 -0
- package/dist/workstation/rd/control.js +119 -0
- package/dist/workstation/rd/display.js +29 -0
- package/dist/workstation/rd/provider.js +222 -0
- package/dist/workstation/rd/sessions.js +391 -0
- package/dist/workstation/rd/state.js +45 -0
- package/dist/workstation/rd/update.js +171 -0
- package/dist/workstation/rd/upkeep.js +38 -0
- package/dist/workstation/register.js +27 -37
- package/dist/workstation/service/installer.js +104 -13
- package/dist/workstation/service/launchd.js +1 -0
- package/dist/workstation/storageMetrics.js +118 -0
- package/dist/workstation/systemMetrics.js +154 -93
- package/dist/workstation/toolchain.js +94 -0
- package/dist/workstation/tools/browser.js +28 -4
- package/dist/workstation/tools/client.js +9 -1
- package/dist/workstation/tools/info.js +50 -0
- package/dist/workstation/tools/keeperProcess.js +15 -5
- package/dist/workstation/tools/router.js +55 -0
- package/dist/workstation/tools/terminalRouter.js +222 -0
- package/dist/workstation/tools/validation.js +37 -1
- package/dist/workstation/update/artifact.js +2 -1
- package/dist/workstation/update/coordinator.js +3 -0
- package/dist/workstation/update/globalInstall.js +116 -0
- package/dist/workstation/update/npmInstaller.js +49 -23
- package/dist/workstation/update/ptyPreflight.js +21 -0
- package/dist/workstation/update/rdRollback.js +145 -0
- package/dist/workstation/update/runUpdate.js +3 -2
- package/dist/workstation/update/taskRegistry.js +105 -11
- package/dist/workstation/update/watchdog.js +16790 -334
- package/package.json +11 -8
- package/skills/axom/SKILL.md +11 -11
- package/skills/axom-definition/SKILL.md +3 -3
- package/skills/axom-platform/SKILL.md +3 -3
- package/dist/axom-patch/cli/probes/qoder-steering.mjs +0 -89
- package/dist/axom-patch/cli/probes/qoder-subagent-origin.mjs +0 -49
- package/dist/axom-patch/cli/qoder-steering.json +0 -52
- package/dist/axom-patch/cli/qoder-subagent-origin.json +0 -73
- package/dist/commands/guide.js +0 -38
- package/dist/workstation/acp/acpSession.js +0 -1475
- package/dist/workstation/acp/contract.js +0 -499
- package/dist/workstation/acp/delegationMcp.js +0 -24
- package/dist/workstation/acp/draftInterceptor.js +0 -163
- package/dist/workstation/acp/qoderStartup.js +0 -45
- package/dist/workstation/acp/sessionScope.js +0 -19
- package/dist/workstation/filePaths.js +0 -174
- package/dist/workstation/fileWorker.js +0 -81
- package/dist/workstation/fileWorkerClient.js +0 -121
- package/dist/workstation/qoderAdapter/backgroundProcess.js +0 -106
- package/dist/workstation/qoderAdapter/backgroundTerminal.js +0 -262
- package/dist/workstation/qoderAdapter/completedContinuation.js +0 -139
- package/dist/workstation/qoderAdapter/contract.js +0 -78
- package/dist/workstation/qoderAdapter/foregroundOutput.js +0 -30
- package/dist/workstation/qoderAdapter/history.js +0 -87
- package/dist/workstation/qoderAdapter/identityIndex.js +0 -191
- package/dist/workstation/qoderAdapter/inputQueue.js +0 -42
- package/dist/workstation/qoderAdapter/main.js +0 -93
- package/dist/workstation/qoderAdapter/mapper.js +0 -117
- package/dist/workstation/qoderAdapter/observerPlugin.js +0 -245
- package/dist/workstation/qoderAdapter/observerReceiver.js +0 -187
- package/dist/workstation/qoderAdapter/permissions.js +0 -61
- package/dist/workstation/qoderAdapter/profile.js +0 -93
- package/dist/workstation/qoderAdapter/sdkDriver.js +0 -49
- package/dist/workstation/qoderAdapter/session.js +0 -319
- package/dist/workstation/qoderAdapter/subagentMeta.js +0 -28
- package/dist/workstation/qoderAdapter/subwork.js +0 -77
- package/dist/workstation/qoderAdapter/taskControl.js +0 -38
- package/dist/workstation/qoderAdapter/taskEvent.js +0 -26
- package/dist/workstation/qoderAdapter/taskLedger.js +0 -163
- package/dist/workstation/qoderAdapter/usage.js +0 -37
- package/dist/workstation/tools/core.js +0 -50
- package/dist/workstation/tools/files.js +0 -525
- package/dist/workstation/tools/terminal.js +0 -214
- /package/dist/workstation/{qoderAdapter/types.js → desktopControl/provider.js} +0 -0
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
/** Session updates map in log order. Root chunks track streaming message boundaries; diverted and child updates retain their session address. Both feed the permission-origin graph and unfinished async-task state. Load history uses separate mapper scopes and emits unnumbered backfill events. */
|
|
2
|
+
import { DRAFT_SESSION_UPDATE_NAMES } from '../draftSubagents.js';
|
|
3
|
+
import { mapSessionUpdate, newMapperScopeData, SessionMapperState } from '../sessionUpdateMapper.js';
|
|
4
|
+
import { validateWireEvent } from '../validate.js';
|
|
5
|
+
import { emitEvent, isRecord } from './emit.js';
|
|
6
|
+
import { observeSubagentSpawned } from './origins.js';
|
|
7
|
+
import { reportActivity } from './runtime.js';
|
|
8
|
+
import { INBOUND_NOTIFICATION_SCHEMAS } from './sdkSchemas.js';
|
|
9
|
+
import { ASYNC_TASK_LIMIT, getOwn, putOwn } from './state.js';
|
|
10
|
+
const DRAFT_NAMES = new Set(DRAFT_SESSION_UPDATE_NAMES);
|
|
11
|
+
/**
|
|
12
|
+
* Updates that state what the session **is now** (its command table, mode, config, usage, info), not what happened in it (Task 21).
|
|
13
|
+
* One the loaded session sends after the load's response — the root is bound — but before the daemon's `historyEnd` is not history:
|
|
14
|
+
* it is folded live (numbered), or a reopened session would never show its command table (Claude sends `available_commands_update`
|
|
15
|
+
* from a timer right after answering `session/load`). Before the response such an update is part of the replay and stays history.
|
|
16
|
+
*/
|
|
17
|
+
const LEVEL_UPDATES = new Set([
|
|
18
|
+
'available_commands_update', 'current_mode_update', 'config_option_update', 'usage_update', 'session_info_update',
|
|
19
|
+
]);
|
|
20
|
+
const SESSION_NOTIFICATION = INBOUND_NOTIFICATION_SCHEMAS['session/update'];
|
|
21
|
+
function stringField(payload, key) {
|
|
22
|
+
const value = payload[key];
|
|
23
|
+
return typeof value === 'string' ? value : null;
|
|
24
|
+
}
|
|
25
|
+
/** The mapper for `nativeSessionId`, over the checkpointed scope data (created on first use). */
|
|
26
|
+
function liveMapper(state, out, nativeSessionId, t) {
|
|
27
|
+
let data = getOwn(state.mapperScopes, nativeSessionId);
|
|
28
|
+
if (!data)
|
|
29
|
+
putOwn(state.mapperScopes, nativeSessionId, data = newMapperScopeData());
|
|
30
|
+
// Codex's activity rides the root's own `session_info_update` (`AcpSession.scopes`' callback).
|
|
31
|
+
return new SessionMapperState((raw) => {
|
|
32
|
+
if (nativeSessionId === state.rootSessionId)
|
|
33
|
+
reportActivity(state, out, raw, t);
|
|
34
|
+
}, data);
|
|
35
|
+
}
|
|
36
|
+
/** An inbound `session/update` notification (params not yet validated). */
|
|
37
|
+
export function onSessionUpdate(state, params, out, t) {
|
|
38
|
+
if (!isRecord(params) || typeof params.sessionId !== 'string' || params.sessionId.length === 0 || !isRecord(params.update)) {
|
|
39
|
+
state.diagnostics.droppedUpdates += 1;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const { sessionId, update } = params;
|
|
43
|
+
if (state.history && !(LEVEL_UPDATES.has(String(update.sessionUpdate)) && state.rootSessionId !== null && sessionId === state.rootSessionId)) {
|
|
44
|
+
onHistoryUpdate(state, state.history, sessionId, update, out);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const root = state.rootSessionId;
|
|
48
|
+
if (root === null) {
|
|
49
|
+
state.diagnostics.droppedUpdates += 1;
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const variant = update.sessionUpdate;
|
|
53
|
+
const draft = typeof variant === 'string' && DRAFT_NAMES.has(variant);
|
|
54
|
+
if (!draft && sessionId === root) {
|
|
55
|
+
const parsed = SESSION_NOTIFICATION.safeParse(params);
|
|
56
|
+
if (!parsed.success) {
|
|
57
|
+
state.diagnostics.droppedUpdates += 1;
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const stripped = parsed.data.update;
|
|
61
|
+
for (const event of mapSessionUpdate(stripped, liveMapper(state, out, root, t)))
|
|
62
|
+
routeOwnEvent(state, out, event);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
let events;
|
|
66
|
+
try {
|
|
67
|
+
events = mapSessionUpdate(update, liveMapper(state, out, sessionId, t));
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// `applyDivertedUpdate`: an unmapped variant on a diverted update is dropped, the session lives on.
|
|
71
|
+
state.diagnostics.droppedUpdates += 1;
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
for (const event of events)
|
|
75
|
+
emitSessionEvent(state, out, sessionId === root ? event : { ...event, acpSessionId: sessionId });
|
|
76
|
+
}
|
|
77
|
+
const CHUNK_CHURN = new WeakMap();
|
|
78
|
+
const CHUNK_TICKS = new WeakMap();
|
|
79
|
+
const canonical = (value) => { try {
|
|
80
|
+
return JSON.stringify(value) ?? 'undefined';
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return 'unserializable';
|
|
84
|
+
} };
|
|
85
|
+
const isVolatileMetaKey = (key) => key === 'timestamp' || key.endsWith('.timestamp') || key.endsWith('_timestamp');
|
|
86
|
+
/** Every event through the live/history entry points ticks once; a tracker whose last chunk is not the immediately
|
|
87
|
+
* preceding event starts fresh. A tool call or any other update between two chunks therefore keeps their ids
|
|
88
|
+
* meaningful — which also matches the server, where an unrelated event already flushes the pending text. */
|
|
89
|
+
function tickEvent(state) {
|
|
90
|
+
const ticks = CHUNK_TICKS.get(state) ?? { tick: 0 };
|
|
91
|
+
ticks.tick += 1;
|
|
92
|
+
CHUNK_TICKS.set(state, ticks);
|
|
93
|
+
return ticks.tick;
|
|
94
|
+
}
|
|
95
|
+
function churnStateOf(state, key, tick) {
|
|
96
|
+
let perState = CHUNK_CHURN.get(state);
|
|
97
|
+
if (!perState)
|
|
98
|
+
CHUNK_CHURN.set(state, perState = new Map());
|
|
99
|
+
const fresh = state.turns.length;
|
|
100
|
+
let churn = perState.get(key);
|
|
101
|
+
if (!churn || churn.seenTurns !== fresh || churn.lastTick !== tick - 1)
|
|
102
|
+
perState.set(key, churn = { prevId: null, anchorId: null, trusted: false, prevMeta: null, anchorMeta: {}, churnyMetaKeys: new Set(), trustedMetaKeys: new Set(), seenTurns: fresh, lastTick: tick });
|
|
103
|
+
churn.lastTick = tick;
|
|
104
|
+
return churn;
|
|
105
|
+
}
|
|
106
|
+
/** Absorb per-delta id/meta churn on one assistant chunk (see the block comment above); other events pass through. */
|
|
107
|
+
function absorbAssistantChunkChurn(state, tick, event) {
|
|
108
|
+
if (event.eventName !== 'agent_message_chunk' && event.eventName !== 'agent_thought_chunk')
|
|
109
|
+
return event;
|
|
110
|
+
const payload = event.payload;
|
|
111
|
+
const churn = churnStateOf(state, `${event.acpSessionId ?? 'root'}:${event.eventName}`, tick);
|
|
112
|
+
let changed = false;
|
|
113
|
+
const rawId = typeof payload.messageId === 'string' ? payload.messageId : null;
|
|
114
|
+
if (rawId !== null) {
|
|
115
|
+
if (churn.prevId !== null && rawId === churn.prevId)
|
|
116
|
+
churn.trusted = true;
|
|
117
|
+
if (churn.trusted) {
|
|
118
|
+
churn.anchorId = rawId;
|
|
119
|
+
}
|
|
120
|
+
else if (churn.prevId !== null) {
|
|
121
|
+
// A change with no stable pair ever seen: churn — keep the anchor.
|
|
122
|
+
if (churn.anchorId !== null && churn.anchorId !== rawId) {
|
|
123
|
+
payload.messageId = churn.anchorId;
|
|
124
|
+
changed = true;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
churn.anchorId = rawId;
|
|
129
|
+
}
|
|
130
|
+
churn.prevId = rawId;
|
|
131
|
+
}
|
|
132
|
+
const rawMeta = payload._meta;
|
|
133
|
+
if (rawMeta !== null && typeof rawMeta === 'object') {
|
|
134
|
+
const meta = rawMeta;
|
|
135
|
+
const emitted = {};
|
|
136
|
+
let anchored = false;
|
|
137
|
+
for (const [key, value] of Object.entries(meta)) {
|
|
138
|
+
if (!isVolatileMetaKey(key)) {
|
|
139
|
+
emitted[key] = value;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
const previous = churn.prevMeta;
|
|
143
|
+
if (previous !== null && key in previous) {
|
|
144
|
+
if (canonical(value) === canonical(previous[key]))
|
|
145
|
+
churn.trustedMetaKeys.add(key);
|
|
146
|
+
else if (!churn.trustedMetaKeys.has(key)) {
|
|
147
|
+
// First sighting of a change on a never-stable key: anchor it to what the previous chunk
|
|
148
|
+
// already emitted, so every chunk of this stream carries the identical map.
|
|
149
|
+
if (!(key in churn.anchorMeta))
|
|
150
|
+
churn.anchorMeta[key] = previous[key];
|
|
151
|
+
churn.churnyMetaKeys.add(key);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
emitted[key] = churn.churnyMetaKeys.has(key) && key in churn.anchorMeta ? churn.anchorMeta[key] : value;
|
|
155
|
+
if (emitted[key] !== value)
|
|
156
|
+
anchored = true;
|
|
157
|
+
}
|
|
158
|
+
churn.prevMeta = meta;
|
|
159
|
+
if (anchored) {
|
|
160
|
+
payload._meta = emitted;
|
|
161
|
+
changed = true;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return changed ? { ...event, payload } : event;
|
|
165
|
+
}
|
|
166
|
+
function routeOwnEvent(state, out, event) {
|
|
167
|
+
const tick = tickEvent(state);
|
|
168
|
+
event = absorbAssistantChunkChurn(state, tick, event);
|
|
169
|
+
observe(state, event);
|
|
170
|
+
observeBackgroundWriter(state, event);
|
|
171
|
+
if ((!event.acpSessionId || event.acpSessionId === state.rootSessionId) &&
|
|
172
|
+
(event.eventName === 'agent_message_chunk' || event.eventName === 'agent_thought_chunk'))
|
|
173
|
+
trackMessageBoundary(state, out, event);
|
|
174
|
+
emitEvent(state, out, event);
|
|
175
|
+
}
|
|
176
|
+
/** Normalize the root session address, observe the event, then emit. */
|
|
177
|
+
export function emitSessionEvent(state, out, event) {
|
|
178
|
+
const tick = tickEvent(state);
|
|
179
|
+
event = absorbAssistantChunkChurn(state, tick, event);
|
|
180
|
+
// Inside a load's history window the session being loaded is the root (an attached `AcpSession` knows it).
|
|
181
|
+
const normalized = event.acpSessionId === (state.rootSessionId ?? state.history?.rootSessionId)
|
|
182
|
+
? { eventName: event.eventName, payload: event.payload }
|
|
183
|
+
: event;
|
|
184
|
+
observe(state, normalized);
|
|
185
|
+
emitEvent(state, out, normalized);
|
|
186
|
+
}
|
|
187
|
+
/** What every live event feeds besides the outbox: the origin graph and the async-task set. */
|
|
188
|
+
function observe(state, event) {
|
|
189
|
+
if (event.eventName === 'subagent_spawned') {
|
|
190
|
+
observeSubagentSpawned(state, event.acpSessionId ?? state.rootSessionId, event.payload.subagentSessionId);
|
|
191
|
+
}
|
|
192
|
+
trackAsyncTask(state, event);
|
|
193
|
+
trackDraftSubagent(state, event);
|
|
194
|
+
}
|
|
195
|
+
/** `AcpSession.observeBackgroundWriter`: an explicitly detached writer blocks `executionEnded` for good. */
|
|
196
|
+
function observeBackgroundWriter(state, event) {
|
|
197
|
+
const input = event.payload.rawInput;
|
|
198
|
+
if (isRecord(input) && input.run_in_background === true)
|
|
199
|
+
state.backgroundWriterUnconfirmed = true;
|
|
200
|
+
const output = event.payload.rawOutput;
|
|
201
|
+
if (isRecord(output) && output.backgrounded === true && (typeof output.taskId === 'string' || typeof output.pid === 'number')) {
|
|
202
|
+
state.backgroundWriterUnconfirmed = true;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const DRAFT_CHILD_LIMIT = 4096;
|
|
206
|
+
const DRAFT_TERMINALS = new Set(['completed', 'failed', 'cancelled']);
|
|
207
|
+
/** Keep terminal tombstones: duplicated/reordered spawns cannot resurrect completed children.
|
|
208
|
+
* At capacity retain a conservative blocker rather than forget potentially running work. */
|
|
209
|
+
function trackDraftSubagent(state, event) {
|
|
210
|
+
if (event.eventName !== 'subagent_spawned' && event.eventName !== 'subagent_state_update')
|
|
211
|
+
return;
|
|
212
|
+
const id = event.payload.subagentSessionId;
|
|
213
|
+
if (typeof id !== 'string' || !id.length)
|
|
214
|
+
return;
|
|
215
|
+
const data = state.draftSubagents;
|
|
216
|
+
if (id.length > 256) {
|
|
217
|
+
data.overflow = true;
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const terminal = event.eventName === 'subagent_state_update' && DRAFT_TERMINALS.has(String(event.payload.state));
|
|
221
|
+
if (getOwn(data.children, id) === false)
|
|
222
|
+
return;
|
|
223
|
+
if (!Object.hasOwn(data.children, id) && Object.keys(data.children).length >= DRAFT_CHILD_LIMIT) {
|
|
224
|
+
data.overflow = true;
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
putOwn(data.children, id, !terminal);
|
|
228
|
+
}
|
|
229
|
+
export function unfinishedDraftSubagentCount(state) {
|
|
230
|
+
return Object.values(state.draftSubagents.children).filter(Boolean).length + Number(state.draftSubagents.overflow);
|
|
231
|
+
}
|
|
232
|
+
const TERMINAL_ASYNC_STATES = new Set(['completed', 'failed', 'stopped']);
|
|
233
|
+
/**
|
|
234
|
+
* The unfinished async tasks (AIR `async_task_*`), per native session: spawned → running; a state
|
|
235
|
+
* update sets the last non-terminal state or removes the task on a terminal one. Settles on the
|
|
236
|
+
* **last** state — a finished shell sends `stopped` then `completed` (`draftSubagents.ts`), and the
|
|
237
|
+
* second finds nothing left to remove.
|
|
238
|
+
*/
|
|
239
|
+
function trackAsyncTask(state, event) {
|
|
240
|
+
if (event.eventName !== 'async_task_spawned' && event.eventName !== 'async_task_state_update')
|
|
241
|
+
return;
|
|
242
|
+
const taskId = event.payload.asyncTaskId;
|
|
243
|
+
if (typeof taskId !== 'string' || taskId.length === 0)
|
|
244
|
+
return;
|
|
245
|
+
const owner = event.acpSessionId ?? state.rootSessionId;
|
|
246
|
+
if (owner === null)
|
|
247
|
+
return;
|
|
248
|
+
const next = event.eventName === 'async_task_spawned' ? 'running' : event.payload.state;
|
|
249
|
+
let tasks = getOwn(state.asyncTasks, owner);
|
|
250
|
+
if (typeof next === 'string' && TERMINAL_ASYNC_STATES.has(next)) {
|
|
251
|
+
if (tasks && Object.hasOwn(tasks, taskId)) {
|
|
252
|
+
delete tasks[taskId];
|
|
253
|
+
if (Object.keys(tasks).length === 0)
|
|
254
|
+
delete state.asyncTasks[owner];
|
|
255
|
+
}
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
if (next !== 'running' && next !== 'paused')
|
|
259
|
+
return;
|
|
260
|
+
if (!(tasks && Object.hasOwn(tasks, taskId)) && unfinishedAsyncTaskCount(state) >= ASYNC_TASK_LIMIT) {
|
|
261
|
+
state.diagnostics.untrackedAsyncTasks += 1;
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
if (!tasks)
|
|
265
|
+
putOwn(state.asyncTasks, owner, tasks = {});
|
|
266
|
+
putOwn(tasks, taskId, next);
|
|
267
|
+
}
|
|
268
|
+
function unfinishedAsyncTaskCount(state) {
|
|
269
|
+
let count = 0;
|
|
270
|
+
for (const tasks of Object.values(state.asyncTasks))
|
|
271
|
+
count += Object.keys(tasks).length;
|
|
272
|
+
return count;
|
|
273
|
+
}
|
|
274
|
+
/** Every unfinished async task, as `{nativeSessionId, asyncTaskId, state}`, in insertion order. */
|
|
275
|
+
export function unfinishedAsyncTasks(state) {
|
|
276
|
+
return Object.entries(state.asyncTasks).flatMap(([nativeSessionId, tasks]) => Object.entries(tasks).map(([asyncTaskId, status]) => ({ nativeSessionId, asyncTaskId, state: status })));
|
|
277
|
+
}
|
|
278
|
+
// ---- agent_message synthesis --------------------------------------------------------------------
|
|
279
|
+
/** `AcpSession.trackMessageBoundary`, plus remembering whether the message began outside any turn. */
|
|
280
|
+
function trackMessageBoundary(state, out, event) {
|
|
281
|
+
const message = state.message;
|
|
282
|
+
const messageId = stringField(event.payload, 'messageId');
|
|
283
|
+
if (message.open && messageId !== null && message.messageId !== null && messageId !== message.messageId)
|
|
284
|
+
flushMessage(state, out);
|
|
285
|
+
if (!message.open)
|
|
286
|
+
message.outOfTurn = state.turns.length === 0;
|
|
287
|
+
message.open = true;
|
|
288
|
+
if (messageId !== null)
|
|
289
|
+
message.messageId = messageId;
|
|
290
|
+
}
|
|
291
|
+
/** `AcpSession.flushMessageCompleted`: close the streaming message with `agent_message` (no-op if none). */
|
|
292
|
+
export function flushMessage(state, out) {
|
|
293
|
+
const message = state.message;
|
|
294
|
+
if (!message.open)
|
|
295
|
+
return;
|
|
296
|
+
emitEvent(state, out, { eventName: 'agent_message', payload: { messageId: message.messageId ?? 'turn' } });
|
|
297
|
+
message.open = false;
|
|
298
|
+
message.messageId = null;
|
|
299
|
+
message.outOfTurn = false;
|
|
300
|
+
}
|
|
301
|
+
/** A turn is about to start: a message that began outside any turn is closed now, never merged into it. */
|
|
302
|
+
export function flushOutOfTurnMessage(state, out) {
|
|
303
|
+
if (state.message.open && state.message.outOfTurn)
|
|
304
|
+
flushMessage(state, out);
|
|
305
|
+
}
|
|
306
|
+
// ---- load history -----------------------------------------------------------------------------
|
|
307
|
+
/** `foldScopedReplayEvents`, one update at a time. */
|
|
308
|
+
function onHistoryUpdate(state, history, sessionId, update, out) {
|
|
309
|
+
let data = getOwn(history.scopes, sessionId);
|
|
310
|
+
if (!data)
|
|
311
|
+
putOwn(history.scopes, sessionId, data = newMapperScopeData());
|
|
312
|
+
let events;
|
|
313
|
+
try {
|
|
314
|
+
events = mapSessionUpdate(update, new SessionMapperState(() => { }, data));
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
// Today an unmappable update throws out of the whole load (`replayNativeSession`); here one
|
|
318
|
+
// update is lost and the history goes on — counted, and reported on `processor.history_end`.
|
|
319
|
+
state.diagnostics.droppedUpdates += 1;
|
|
320
|
+
history.droppedCount += 1;
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
for (const rawEvent of events) {
|
|
324
|
+
// Same churn absorption as the live path: a replayed CodeBuddy history fragments identically.
|
|
325
|
+
const event = absorbAssistantChunkChurn(state, tickEvent(state), rawEvent);
|
|
326
|
+
if (event.eventName === 'user_message_chunk')
|
|
327
|
+
flushHistoryMessage(state, history, sessionId, out);
|
|
328
|
+
if (event.eventName === 'agent_message_chunk' || event.eventName === 'agent_thought_chunk') {
|
|
329
|
+
const messageId = stringField(event.payload, 'messageId');
|
|
330
|
+
const index = history.messages.findIndex((entry) => entry.nativeSessionId === sessionId);
|
|
331
|
+
const previous = index >= 0 ? history.messages[index] : undefined;
|
|
332
|
+
if (previous && messageId !== null && previous.messageId !== null && messageId !== previous.messageId) {
|
|
333
|
+
flushHistoryMessage(state, history, sessionId, out);
|
|
334
|
+
history.messages.push({ nativeSessionId: sessionId, messageId });
|
|
335
|
+
}
|
|
336
|
+
else if (previous) {
|
|
337
|
+
previous.messageId = messageId ?? previous.messageId;
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
history.messages.push({ nativeSessionId: sessionId, messageId });
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
emitHistory(state, history, out, event, sessionId);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
function flushHistoryMessage(state, history, sessionId, out) {
|
|
347
|
+
const index = history.messages.findIndex((entry) => entry.nativeSessionId === sessionId);
|
|
348
|
+
if (index < 0)
|
|
349
|
+
return;
|
|
350
|
+
const [message] = history.messages.splice(index, 1);
|
|
351
|
+
emitHistory(state, history, out, { eventName: 'agent_message', payload: { messageId: message.messageId ?? 'replay' } }, sessionId);
|
|
352
|
+
}
|
|
353
|
+
function emitHistory(state, history, out, event, sessionId) {
|
|
354
|
+
const scoped = sessionId === history.rootSessionId ? event : { ...event, acpSessionId: sessionId };
|
|
355
|
+
if (validateWireEvent(scoped)) {
|
|
356
|
+
state.diagnostics.invalidEvents += 1;
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
// `AcpSession.observeReplayEvent`: history restores the repair's calls, addresses and background-writer evidence.
|
|
360
|
+
if (scoped.eventName === 'subagent_spawned') {
|
|
361
|
+
observeSubagentSpawned(state, scoped.acpSessionId ?? history.rootSessionId, scoped.payload.subagentSessionId, history.rootSessionId);
|
|
362
|
+
}
|
|
363
|
+
trackDraftSubagent(state, scoped);
|
|
364
|
+
observeBackgroundWriter(state, scoped);
|
|
365
|
+
out.unjournaled({
|
|
366
|
+
t: 'processor.history_event',
|
|
367
|
+
eventName: scoped.eventName,
|
|
368
|
+
payload: scoped.payload,
|
|
369
|
+
...(scoped.acpSessionId ? { acpSessionId: scoped.acpSessionId } : {}),
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Close the history window: flush the open history messages (in first-chunk order, as
|
|
374
|
+
* `foldScopedReplayEvents` does at the end of its list) and report it. `ok: false` when the load
|
|
375
|
+
* failed or the connection closed — the daemon discards what it collected, as today's load does.
|
|
376
|
+
* `droppedCount` (history updates that could not be mapped) lets the daemon report a partial
|
|
377
|
+
* backfill. The `processor.history_event`s are unjournaled: a daemon that crashes inside the window
|
|
378
|
+
* restarts the load rather than resuming from a checkpoint cut inside it.
|
|
379
|
+
*/
|
|
380
|
+
export function endHistory(state, out, ok) {
|
|
381
|
+
const history = state.history;
|
|
382
|
+
if (!history)
|
|
383
|
+
return;
|
|
384
|
+
if (ok) {
|
|
385
|
+
while (history.messages.length > 0)
|
|
386
|
+
flushHistoryMessage(state, history, history.messages[0].nativeSessionId, out);
|
|
387
|
+
}
|
|
388
|
+
state.history = null;
|
|
389
|
+
out.unjournaled({ t: 'processor.history_end', ok, droppedCount: history.droppedCount });
|
|
390
|
+
}
|