@geminixiang/mikan 1.0.0-beta.84 → 1.0.0-beta.86
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/CHANGELOG.md +57 -0
- package/README.md +10 -10
- package/dist/adapters/commands/session-view.js +1 -1
- package/dist/adapters/commands/session-view.js.map +1 -1
- package/dist/adapters/discord/bot.d.ts.map +1 -1
- package/dist/adapters/discord/bot.js +1 -8
- package/dist/adapters/discord/bot.js.map +1 -1
- package/dist/adapters/github/activity.d.ts +3 -0
- package/dist/adapters/github/activity.d.ts.map +1 -0
- package/dist/adapters/github/activity.js +154 -0
- package/dist/adapters/github/activity.js.map +1 -0
- package/dist/adapters/github/bot.d.ts +10 -20
- package/dist/adapters/github/bot.d.ts.map +1 -1
- package/dist/adapters/github/bot.js +119 -342
- package/dist/adapters/github/bot.js.map +1 -1
- package/dist/adapters/github/client.d.ts +9 -19
- package/dist/adapters/github/client.d.ts.map +1 -1
- package/dist/adapters/github/client.js +28 -104
- package/dist/adapters/github/client.js.map +1 -1
- package/dist/adapters/github/context.d.ts.map +1 -1
- package/dist/adapters/github/context.js +29 -20
- package/dist/adapters/github/context.js.map +1 -1
- package/dist/adapters/github/github-ops.d.ts +2 -10
- package/dist/adapters/github/github-ops.d.ts.map +1 -1
- package/dist/adapters/github/github-ops.js +28 -91
- package/dist/adapters/github/github-ops.js.map +1 -1
- package/dist/adapters/github/policy.d.ts +19 -0
- package/dist/adapters/github/policy.d.ts.map +1 -0
- package/dist/adapters/github/policy.js +79 -0
- package/dist/adapters/github/policy.js.map +1 -0
- package/dist/adapters/github/tool-pack.d.ts +2 -2
- package/dist/adapters/github/tool-pack.d.ts.map +1 -1
- package/dist/adapters/github/tool-pack.js +4 -9
- package/dist/adapters/github/tool-pack.js.map +1 -1
- package/dist/adapters/github/tools/checks.d.ts.map +1 -1
- package/dist/adapters/github/tools/checks.js +6 -8
- package/dist/adapters/github/tools/checks.js.map +1 -1
- package/dist/adapters/github/tools/pr.d.ts.map +1 -1
- package/dist/adapters/github/tools/pr.js +7 -9
- package/dist/adapters/github/tools/pr.js.map +1 -1
- package/dist/adapters/github/types.d.ts +66 -67
- package/dist/adapters/github/types.d.ts.map +1 -1
- package/dist/adapters/github/types.js.map +1 -1
- package/dist/adapters/github/webhook.d.ts +2 -1
- package/dist/adapters/github/webhook.d.ts.map +1 -1
- package/dist/adapters/github/webhook.js +46 -4
- package/dist/adapters/github/webhook.js.map +1 -1
- package/dist/adapters/progressive-renderer.d.ts.map +1 -1
- package/dist/adapters/progressive-renderer.js +3 -0
- package/dist/adapters/progressive-renderer.js.map +1 -1
- package/dist/adapters/shared.d.ts +3 -1
- package/dist/adapters/shared.d.ts.map +1 -1
- package/dist/adapters/shared.js +45 -23
- package/dist/adapters/shared.js.map +1 -1
- package/dist/adapters/slack/blocks.d.ts.map +1 -1
- package/dist/adapters/slack/blocks.js +65 -2
- package/dist/adapters/slack/blocks.js.map +1 -1
- package/dist/adapters/slack/bot.d.ts +4 -0
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +84 -36
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/slack/jev-context.js +2 -2
- package/dist/adapters/slack/jev-context.js.map +1 -1
- package/dist/adapters/slack/response-lifecycle.js +2 -2
- package/dist/adapters/slack/response-lifecycle.js.map +1 -1
- package/dist/adapters/slack/task-status.d.ts +3 -2
- package/dist/adapters/slack/task-status.d.ts.map +1 -1
- package/dist/adapters/slack/task-status.js +12 -15
- package/dist/adapters/slack/task-status.js.map +1 -1
- package/dist/adapters/telegram/bot.d.ts.map +1 -1
- package/dist/adapters/telegram/bot.js +1 -8
- package/dist/adapters/telegram/bot.js.map +1 -1
- package/dist/adapters/web/admin/portal.js +1 -1
- package/dist/adapters/web/admin/portal.js.map +1 -1
- package/dist/adapters/web/admin/provider-models.d.ts.map +1 -1
- package/dist/adapters/web/admin/provider-models.js +10 -3
- package/dist/adapters/web/admin/provider-models.js.map +1 -1
- package/dist/adapters/web/login/portal.js +6 -1
- package/dist/adapters/web/login/portal.js.map +1 -1
- package/dist/adapters/web/server.d.ts.map +1 -1
- package/dist/adapters/web/server.js +5 -3
- package/dist/adapters/web/server.js.map +1 -1
- package/dist/adapters/web/session-view/portal.d.ts +2 -1
- package/dist/adapters/web/session-view/portal.d.ts.map +1 -1
- package/dist/adapters/web/session-view/portal.js +18 -27
- package/dist/adapters/web/session-view/portal.js.map +1 -1
- package/dist/cli/boot.d.ts.map +1 -1
- package/dist/cli/boot.js +4 -6
- package/dist/cli/boot.js.map +1 -1
- package/dist/cli/migrate.d.ts +3 -0
- package/dist/cli/migrate.d.ts.map +1 -0
- package/dist/cli/migrate.js +74 -0
- package/dist/cli/migrate.js.map +1 -0
- package/dist/cli/office.d.ts.map +1 -1
- package/dist/cli/office.js +8 -129
- package/dist/cli/office.js.map +1 -1
- package/dist/cli/onboard.d.ts +0 -1
- package/dist/cli/onboard.d.ts.map +1 -1
- package/dist/cli/onboard.js +4 -7
- package/dist/cli/onboard.js.map +1 -1
- package/dist/cli/types.d.ts +2 -3
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/cli/types.js.map +1 -1
- package/dist/env-manifest.d.ts.map +1 -1
- package/dist/env-manifest.js +24 -22
- package/dist/env-manifest.js.map +1 -1
- package/dist/events/index.d.ts +3 -13
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +12 -58
- package/dist/events/index.js.map +1 -1
- package/dist/events/scheduler.d.ts.map +1 -1
- package/dist/events/scheduler.js +3 -0
- package/dist/events/scheduler.js.map +1 -1
- package/dist/file-guards.d.ts +7 -0
- package/dist/file-guards.d.ts.map +1 -1
- package/dist/file-guards.js +63 -1
- package/dist/file-guards.js.map +1 -1
- package/dist/harness/budget-stop.d.ts +3 -0
- package/dist/harness/budget-stop.d.ts.map +1 -0
- package/dist/harness/budget-stop.js +36 -0
- package/dist/harness/budget-stop.js.map +1 -0
- package/dist/harness/execution-resolver.d.ts.map +1 -1
- package/dist/harness/execution-resolver.js +5 -9
- package/dist/harness/execution-resolver.js.map +1 -1
- package/dist/harness/mcp.d.ts.map +1 -1
- package/dist/harness/mcp.js +75 -31
- package/dist/harness/mcp.js.map +1 -1
- package/dist/harness/models.js +2 -2
- package/dist/harness/models.js.map +1 -1
- package/dist/harness/open-connector.d.ts +0 -9
- package/dist/harness/open-connector.d.ts.map +1 -1
- package/dist/harness/open-connector.js +15 -69
- package/dist/harness/open-connector.js.map +1 -1
- package/dist/harness/presenter.d.ts.map +1 -1
- package/dist/harness/presenter.js +33 -2
- package/dist/harness/presenter.js.map +1 -1
- package/dist/harness/prompt.d.ts +1 -1
- package/dist/harness/prompt.d.ts.map +1 -1
- package/dist/harness/prompt.js +14 -32
- package/dist/harness/prompt.js.map +1 -1
- package/dist/harness/run-events.d.ts.map +1 -1
- package/dist/harness/run-events.js +6 -1
- package/dist/harness/run-events.js.map +1 -1
- package/dist/harness/runner.d.ts.map +1 -1
- package/dist/harness/runner.js +6 -9
- package/dist/harness/runner.js.map +1 -1
- package/dist/harness/session.d.ts.map +1 -1
- package/dist/harness/session.js +6 -0
- package/dist/harness/session.js.map +1 -1
- package/dist/harness/tools/event.d.ts.map +1 -1
- package/dist/harness/tools/event.js +19 -2
- package/dist/harness/tools/event.js.map +1 -1
- package/dist/harness/tools/generate-image.d.ts.map +1 -1
- package/dist/harness/tools/generate-image.js +17 -3
- package/dist/harness/tools/generate-image.js.map +1 -1
- package/dist/harness/tools/jev-browser.d.ts +1 -2
- package/dist/harness/tools/jev-browser.d.ts.map +1 -1
- package/dist/harness/tools/jev-browser.js +75 -50
- package/dist/harness/tools/jev-browser.js.map +1 -1
- package/dist/harness/types.d.ts +16 -0
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -3
- package/dist/index.js.map +1 -1
- package/dist/main.js +40 -93
- package/dist/main.js.map +1 -1
- package/dist/memory-capture/index.d.ts.map +1 -1
- package/dist/memory-capture/index.js +3 -3
- package/dist/memory-capture/index.js.map +1 -1
- package/dist/migrations/actor-vaults.d.ts +3 -0
- package/dist/migrations/actor-vaults.d.ts.map +1 -0
- package/dist/migrations/actor-vaults.js +43 -0
- package/dist/migrations/actor-vaults.js.map +1 -0
- package/dist/migrations/conversation-settings.d.ts +3 -0
- package/dist/migrations/conversation-settings.d.ts.map +1 -0
- package/dist/migrations/conversation-settings.js +31 -0
- package/dist/migrations/conversation-settings.js.map +1 -0
- package/dist/migrations/index.d.ts +14 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +99 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/migrations/models-json.d.ts +3 -0
- package/dist/migrations/models-json.d.ts.map +1 -0
- package/dist/migrations/models-json.js +18 -0
- package/dist/migrations/models-json.js.map +1 -0
- package/dist/migrations/office-layout.d.ts +4 -0
- package/dist/migrations/office-layout.d.ts.map +1 -0
- package/dist/migrations/office-layout.js +94 -0
- package/dist/migrations/office-layout.js.map +1 -0
- package/dist/migrations/office-sessions.d.ts +3 -0
- package/dist/migrations/office-sessions.d.ts.map +1 -0
- package/dist/migrations/office-sessions.js +70 -0
- package/dist/migrations/office-sessions.js.map +1 -0
- package/dist/migrations/sandbox-containers.d.ts +3 -0
- package/dist/migrations/sandbox-containers.d.ts.map +1 -0
- package/dist/migrations/sandbox-containers.js +36 -0
- package/dist/migrations/sandbox-containers.js.map +1 -0
- package/dist/{sessions/migrate-common.d.ts → migrations/session-files.d.ts} +1 -2
- package/dist/migrations/session-files.d.ts.map +1 -0
- package/dist/{sessions/migrate-common.js → migrations/session-files.js} +2 -2
- package/dist/migrations/session-files.js.map +1 -0
- package/dist/{sessions/migrate-v3.d.ts → migrations/sessions-v3.d.ts} +4 -3
- package/dist/migrations/sessions-v3.d.ts.map +1 -0
- package/dist/{sessions/migrate-v3.js → migrations/sessions-v3.js} +14 -4
- package/dist/migrations/sessions-v3.js.map +1 -0
- package/dist/migrations/types.d.ts +30 -0
- package/dist/migrations/types.d.ts.map +1 -0
- package/dist/migrations/types.js +2 -0
- package/dist/migrations/types.js.map +1 -0
- package/dist/migrations/workspace-events.d.ts +3 -0
- package/dist/migrations/workspace-events.d.ts.map +1 -0
- package/dist/migrations/workspace-events.js +43 -0
- package/dist/migrations/workspace-events.js.map +1 -0
- package/dist/office/index.d.ts +2 -24
- package/dist/office/index.d.ts.map +1 -1
- package/dist/office/index.js +15 -579
- package/dist/office/index.js.map +1 -1
- package/dist/office/types.d.ts +0 -10
- package/dist/office/types.d.ts.map +1 -1
- package/dist/office/types.js.map +1 -1
- package/dist/runtime/conversation-runtime.js +12 -12
- package/dist/runtime/conversation-runtime.js.map +1 -1
- package/dist/sandbox/identity.d.ts +2 -3
- package/dist/sandbox/identity.d.ts.map +1 -1
- package/dist/sandbox/identity.js +6 -13
- package/dist/sandbox/identity.js.map +1 -1
- package/dist/sandbox/layout.d.ts +0 -2
- package/dist/sandbox/layout.d.ts.map +1 -1
- package/dist/sandbox/layout.js +2 -2
- package/dist/sandbox/layout.js.map +1 -1
- package/dist/sandbox/provisioner.d.ts +4 -38
- package/dist/sandbox/provisioner.d.ts.map +1 -1
- package/dist/sandbox/provisioner.js +32 -456
- package/dist/sandbox/provisioner.js.map +1 -1
- package/dist/sessions/chat-history-sync.d.ts.map +1 -1
- package/dist/sessions/chat-history-sync.js +28 -40
- package/dist/sessions/chat-history-sync.js.map +1 -1
- package/dist/sessions/session-store.d.ts.map +1 -1
- package/dist/sessions/session-store.js +1 -8
- package/dist/sessions/session-store.js.map +1 -1
- package/dist/sessions/store.d.ts +2 -3
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js +8 -14
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/types.d.ts +6 -15
- package/dist/sessions/types.d.ts.map +1 -1
- package/dist/sessions/types.js.map +1 -1
- package/dist/settings/index.d.ts +0 -48
- package/dist/settings/index.d.ts.map +1 -1
- package/dist/settings/index.js +6 -37
- package/dist/settings/index.js.map +1 -1
- package/dist/types.d.ts +0 -29
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vault/index.d.ts +0 -7
- package/dist/vault/index.d.ts.map +1 -1
- package/dist/vault/index.js +1 -36
- package/dist/vault/index.js.map +1 -1
- package/package.json +8 -6
- package/dist/adapters/github/repo.d.ts +0 -8
- package/dist/adapters/github/repo.d.ts.map +0 -1
- package/dist/adapters/github/repo.js +0 -92
- package/dist/adapters/github/repo.js.map +0 -1
- package/dist/adapters/github/tools/sync.d.ts +0 -13
- package/dist/adapters/github/tools/sync.d.ts.map +0 -1
- package/dist/adapters/github/tools/sync.js +0 -29
- package/dist/adapters/github/tools/sync.js.map +0 -1
- package/dist/cli/sandbox.d.ts +0 -3
- package/dist/cli/sandbox.d.ts.map +0 -1
- package/dist/cli/sandbox.js +0 -80
- package/dist/cli/sandbox.js.map +0 -1
- package/dist/cli/sessions.d.ts +0 -2
- package/dist/cli/sessions.d.ts.map +0 -1
- package/dist/cli/sessions.js +0 -78
- package/dist/cli/sessions.js.map +0 -1
- package/dist/sessions/migrate-common.d.ts.map +0 -1
- package/dist/sessions/migrate-common.js.map +0 -1
- package/dist/sessions/migrate-pi-084.d.ts +0 -7
- package/dist/sessions/migrate-pi-084.d.ts.map +0 -1
- package/dist/sessions/migrate-pi-084.js +0 -293
- package/dist/sessions/migrate-pi-084.js.map +0 -1
- package/dist/sessions/migrate-v3.d.ts.map +0 -1
- package/dist/sessions/migrate-v3.js.map +0 -1
- package/dist/settings/migrate.d.ts +0 -16
- package/dist/settings/migrate.d.ts.map +0 -1
- package/dist/settings/migrate.js +0 -70
- package/dist/settings/migrate.js.map +0 -1
package/dist/cli/sandbox.js
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { DockerContainerManager } from "../sandbox/provisioner.js";
|
|
2
|
-
import { cliCommand, commandExitCode, nonEmptyValue } from "./arg-grammar.js";
|
|
3
|
-
import { errorMessage } from "../unknown-values.js";
|
|
4
|
-
export async function runSandboxCommand(argv, createManager = (image) => new DockerContainerManager(image)) {
|
|
5
|
-
const command = cliCommand("mikan sandbox")
|
|
6
|
-
.description("Inspect and upgrade managed image:* sandbox containers")
|
|
7
|
-
.requiredOption("--image <image>", "The image the daemon runs with (image:<image>)", nonEmptyValue);
|
|
8
|
-
let result = 1;
|
|
9
|
-
const manager = () => createManager(command.opts().image ?? "");
|
|
10
|
-
command
|
|
11
|
-
.command("status")
|
|
12
|
-
.description("List managed containers with home-volume and image-drift state")
|
|
13
|
-
.action(async () => {
|
|
14
|
-
result = await printStatus(manager());
|
|
15
|
-
});
|
|
16
|
-
command
|
|
17
|
-
.command("diff <containerKey>")
|
|
18
|
-
.description("Show system changes outside /root that an upgrade will discard")
|
|
19
|
-
.action(async (containerKey) => {
|
|
20
|
-
result = await printSystemChanges(manager(), containerKey);
|
|
21
|
-
});
|
|
22
|
-
command
|
|
23
|
-
.command("migrate <containerKeys...>")
|
|
24
|
-
.description("Move legacy containers onto a home volume and the current image")
|
|
25
|
-
.action(async (containerKeys) => {
|
|
26
|
-
result = await migrateContainers(manager(), containerKeys);
|
|
27
|
-
});
|
|
28
|
-
try {
|
|
29
|
-
await command.parseAsync(argv, { from: "user" });
|
|
30
|
-
return result;
|
|
31
|
-
}
|
|
32
|
-
catch (error) {
|
|
33
|
-
return commandExitCode(error, command);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
async function printStatus(manager) {
|
|
37
|
-
const entries = await manager.inventory();
|
|
38
|
-
if (entries.length === 0) {
|
|
39
|
-
console.log("No managed sandbox containers.");
|
|
40
|
-
return 0;
|
|
41
|
-
}
|
|
42
|
-
for (const entry of entries) {
|
|
43
|
-
const state = entry.running ? "running" : "stopped";
|
|
44
|
-
const layout = entry.homeVolume ? "home-volume" : "legacy";
|
|
45
|
-
const image = entry.imageStale ? "stale-image" : "current-image";
|
|
46
|
-
console.log(`${entry.containerKey ?? entry.containerName}\t${state}\t${layout}\t${image}`);
|
|
47
|
-
}
|
|
48
|
-
const legacy = entries.filter((entry) => !entry.homeVolume).length;
|
|
49
|
-
const stale = entries.filter((entry) => entry.homeVolume && entry.imageStale).length;
|
|
50
|
-
console.log(`${entries.length} container(s): ${legacy} legacy (run \`mikan sandbox migrate\`), ${stale} home-volume on a stale image (replaced on next start after idle stop).`);
|
|
51
|
-
return 0;
|
|
52
|
-
}
|
|
53
|
-
async function printSystemChanges(manager, containerKey) {
|
|
54
|
-
const changes = await manager.systemChanges(DockerContainerManager.containerName(containerKey));
|
|
55
|
-
if (changes.length === 0) {
|
|
56
|
-
console.log("No system changes outside /root and /workspace.");
|
|
57
|
-
return 0;
|
|
58
|
-
}
|
|
59
|
-
for (const line of changes)
|
|
60
|
-
console.log(line);
|
|
61
|
-
console.log(`${changes.length} path(s) outside /root will be discarded by an upgrade.`);
|
|
62
|
-
return 0;
|
|
63
|
-
}
|
|
64
|
-
async function migrateContainers(manager, containerKeys) {
|
|
65
|
-
let failed = 0;
|
|
66
|
-
for (const containerKey of containerKeys) {
|
|
67
|
-
try {
|
|
68
|
-
const outcome = await manager.migrateToHomeVolume(containerKey);
|
|
69
|
-
console.log(`${containerKey}\t${outcome}`);
|
|
70
|
-
if (outcome === "missing")
|
|
71
|
-
failed++;
|
|
72
|
-
}
|
|
73
|
-
catch (error) {
|
|
74
|
-
failed++;
|
|
75
|
-
console.error(`${containerKey}\tfailed\t${errorMessage(error)}`);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return failed === 0 ? 0 : 1;
|
|
79
|
-
}
|
|
80
|
-
//# sourceMappingURL=sandbox.js.map
|
package/dist/cli/sandbox.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/cli/sandbox.ts"],"names":[],"mappings":"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","sourcesContent":["import { DockerContainerManager } from \"../sandbox/provisioner.js\";\nimport { cliCommand, commandExitCode, nonEmptyValue } from \"./arg-grammar.js\";\nimport { errorMessage } from \"../unknown-values.js\";\n\ninterface SandboxCommandOptions {\n image?: string;\n}\n\nexport async function runSandboxCommand(\n argv: string[],\n createManager: (image: string) => DockerContainerManager = (image) =>\n new DockerContainerManager(image),\n): Promise<number> {\n const command = cliCommand(\"mikan sandbox\")\n .description(\"Inspect and upgrade managed image:* sandbox containers\")\n .requiredOption(\n \"--image <image>\",\n \"The image the daemon runs with (image:<image>)\",\n nonEmptyValue,\n );\n let result = 1;\n const manager = (): DockerContainerManager =>\n createManager(command.opts<SandboxCommandOptions>().image ?? \"\");\n command\n .command(\"status\")\n .description(\"List managed containers with home-volume and image-drift state\")\n .action(async () => {\n result = await printStatus(manager());\n });\n command\n .command(\"diff <containerKey>\")\n .description(\"Show system changes outside /root that an upgrade will discard\")\n .action(async (containerKey: string) => {\n result = await printSystemChanges(manager(), containerKey);\n });\n command\n .command(\"migrate <containerKeys...>\")\n .description(\"Move legacy containers onto a home volume and the current image\")\n .action(async (containerKeys: string[]) => {\n result = await migrateContainers(manager(), containerKeys);\n });\n try {\n await command.parseAsync(argv, { from: \"user\" });\n return result;\n } catch (error) {\n return commandExitCode(error, command);\n }\n}\n\nasync function printStatus(manager: DockerContainerManager): Promise<number> {\n const entries = await manager.inventory();\n if (entries.length === 0) {\n console.log(\"No managed sandbox containers.\");\n return 0;\n }\n for (const entry of entries) {\n const state = entry.running ? \"running\" : \"stopped\";\n const layout = entry.homeVolume ? \"home-volume\" : \"legacy\";\n const image = entry.imageStale ? \"stale-image\" : \"current-image\";\n console.log(`${entry.containerKey ?? entry.containerName}\\t${state}\\t${layout}\\t${image}`);\n }\n const legacy = entries.filter((entry) => !entry.homeVolume).length;\n const stale = entries.filter((entry) => entry.homeVolume && entry.imageStale).length;\n console.log(\n `${entries.length} container(s): ${legacy} legacy (run \\`mikan sandbox migrate\\`), ${stale} home-volume on a stale image (replaced on next start after idle stop).`,\n );\n return 0;\n}\n\nasync function printSystemChanges(\n manager: DockerContainerManager,\n containerKey: string,\n): Promise<number> {\n const changes = await manager.systemChanges(DockerContainerManager.containerName(containerKey));\n if (changes.length === 0) {\n console.log(\"No system changes outside /root and /workspace.\");\n return 0;\n }\n for (const line of changes) console.log(line);\n console.log(`${changes.length} path(s) outside /root will be discarded by an upgrade.`);\n return 0;\n}\n\nasync function migrateContainers(\n manager: DockerContainerManager,\n containerKeys: readonly string[],\n): Promise<number> {\n let failed = 0;\n for (const containerKey of containerKeys) {\n try {\n const outcome = await manager.migrateToHomeVolume(containerKey);\n console.log(`${containerKey}\\t${outcome}`);\n if (outcome === \"missing\") failed++;\n } catch (error) {\n failed++;\n console.error(`${containerKey}\\tfailed\\t${errorMessage(error)}`);\n }\n }\n return failed === 0 ? 0 : 1;\n}\n"]}
|
package/dist/cli/sessions.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/cli/sessions.ts"],"names":[],"mappings":"AAWA,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBxE"}
|
package/dist/cli/sessions.js
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { join, resolve } from "node:path";
|
|
2
|
-
import { findPi084SessionFiles, migratePi084SessionFile } from "../sessions/migrate-pi-084.js";
|
|
3
|
-
import { findV3SessionFiles, migrateSessionFile } from "../sessions/migrate-v3.js";
|
|
4
|
-
import { cliCommand, commandExitCode, nonEmptyValue, resolveStateDir } from "./arg-grammar.js";
|
|
5
|
-
import { errorMessage } from "../unknown-values.js";
|
|
6
|
-
export async function runSessionsCommand(argv) {
|
|
7
|
-
const command = cliCommand("mikan sessions")
|
|
8
|
-
.description("Session-file maintenance (stop the daemon first)")
|
|
9
|
-
.option("--state-dir <dir>", "State directory", nonEmptyValue)
|
|
10
|
-
.option("--workspace <dir>", "Workspace directory", nonEmptyValue);
|
|
11
|
-
let result = 1;
|
|
12
|
-
command
|
|
13
|
-
.command("migrate")
|
|
14
|
-
.description("Migrate legacy sessions, preserving backups")
|
|
15
|
-
.option("--dry-run", "Preview migration without writing")
|
|
16
|
-
.action(async (options) => {
|
|
17
|
-
const { workspace } = command.opts();
|
|
18
|
-
const workspaceRoot = workspace
|
|
19
|
-
? resolve(workspace)
|
|
20
|
-
: join(resolveStateDir(argv), "workspace");
|
|
21
|
-
result = await migrateWorkspace(workspaceRoot, options.dryRun ?? false);
|
|
22
|
-
});
|
|
23
|
-
try {
|
|
24
|
-
await command.parseAsync(argv, { from: "user" });
|
|
25
|
-
return result;
|
|
26
|
-
}
|
|
27
|
-
catch (error) {
|
|
28
|
-
return commandExitCode(error, command);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
async function migrateWorkspace(workspaceRoot, dryRun) {
|
|
32
|
-
const candidates = findCandidates(workspaceRoot);
|
|
33
|
-
if (candidates.length === 0) {
|
|
34
|
-
console.log(`No legacy session files found under ${workspaceRoot}`);
|
|
35
|
-
return 0;
|
|
36
|
-
}
|
|
37
|
-
console.log(`Found ${candidates.length} legacy session file(s) under ${workspaceRoot}`);
|
|
38
|
-
const { migrated, failed } = await migrateCandidates(candidates, dryRun);
|
|
39
|
-
console.log(dryRun
|
|
40
|
-
? `Dry run: ${migrated} file(s) would be migrated, ${failed} failed to read.`
|
|
41
|
-
: `Migrated ${migrated} file(s), ${failed} failure(s). Originals kept as *.v3.bak or *.pi-084.bak.`);
|
|
42
|
-
return failed === 0 ? 0 : 1;
|
|
43
|
-
}
|
|
44
|
-
function findCandidates(workspaceRoot) {
|
|
45
|
-
return [
|
|
46
|
-
...findV3SessionFiles(workspaceRoot).map((file) => ({ file, format: "v3" })),
|
|
47
|
-
...findPi084SessionFiles(workspaceRoot).map((file) => ({ file, format: "pi-084" })),
|
|
48
|
-
].toSorted((left, right) => left.file.localeCompare(right.file));
|
|
49
|
-
}
|
|
50
|
-
async function migrateCandidates(candidates, dryRun) {
|
|
51
|
-
let migrated = 0;
|
|
52
|
-
let failed = 0;
|
|
53
|
-
for (const candidate of candidates) {
|
|
54
|
-
const outcome = await migrateCandidate(candidate, dryRun);
|
|
55
|
-
if (outcome === "migrated")
|
|
56
|
-
migrated++;
|
|
57
|
-
if (outcome === "failed")
|
|
58
|
-
failed++;
|
|
59
|
-
}
|
|
60
|
-
return { migrated, failed };
|
|
61
|
-
}
|
|
62
|
-
async function migrateCandidate({ file, format }, dryRun) {
|
|
63
|
-
try {
|
|
64
|
-
const result = format === "v3"
|
|
65
|
-
? await migrateSessionFile(file, { dryRun })
|
|
66
|
-
: await migratePi084SessionFile(file, { dryRun });
|
|
67
|
-
if (result.status !== "migrated")
|
|
68
|
-
return "skipped";
|
|
69
|
-
console.log(`${dryRun ? "would migrate" : "migrated"} ${file}`);
|
|
70
|
-
return "migrated";
|
|
71
|
-
}
|
|
72
|
-
catch (error) {
|
|
73
|
-
const cause = error instanceof Error && error.cause ? ` (${String(error.cause)})` : "";
|
|
74
|
-
console.error(`FAILED ${file}: ${errorMessage(error)}${cause}`);
|
|
75
|
-
return "failed";
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
//# sourceMappingURL=sessions.js.map
|
package/dist/cli/sessions.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/cli/sessions.ts"],"names":[],"mappings":"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","sourcesContent":["import { join, resolve } from \"node:path\";\nimport { findPi084SessionFiles, migratePi084SessionFile } from \"../sessions/migrate-pi-084.js\";\nimport { findV3SessionFiles, migrateSessionFile } from \"../sessions/migrate-v3.js\";\nimport { cliCommand, commandExitCode, nonEmptyValue, resolveStateDir } from \"./arg-grammar.js\";\nimport { errorMessage } from \"../unknown-values.js\";\n\ninterface Candidate {\n file: string;\n format: \"v3\" | \"pi-084\";\n}\n\nexport async function runSessionsCommand(argv: string[]): Promise<number> {\n const command = cliCommand(\"mikan sessions\")\n .description(\"Session-file maintenance (stop the daemon first)\")\n .option(\"--state-dir <dir>\", \"State directory\", nonEmptyValue)\n .option(\"--workspace <dir>\", \"Workspace directory\", nonEmptyValue);\n let result = 1;\n command\n .command(\"migrate\")\n .description(\"Migrate legacy sessions, preserving backups\")\n .option(\"--dry-run\", \"Preview migration without writing\")\n .action(async (options: { dryRun?: boolean }) => {\n const { workspace } = command.opts<{ workspace?: string }>();\n const workspaceRoot = workspace\n ? resolve(workspace)\n : join(resolveStateDir(argv), \"workspace\");\n result = await migrateWorkspace(workspaceRoot, options.dryRun ?? false);\n });\n try {\n await command.parseAsync(argv, { from: \"user\" });\n return result;\n } catch (error) {\n return commandExitCode(error, command);\n }\n}\n\nasync function migrateWorkspace(workspaceRoot: string, dryRun: boolean): Promise<number> {\n const candidates = findCandidates(workspaceRoot);\n if (candidates.length === 0) {\n console.log(`No legacy session files found under ${workspaceRoot}`);\n return 0;\n }\n\n console.log(`Found ${candidates.length} legacy session file(s) under ${workspaceRoot}`);\n const { migrated, failed } = await migrateCandidates(candidates, dryRun);\n console.log(\n dryRun\n ? `Dry run: ${migrated} file(s) would be migrated, ${failed} failed to read.`\n : `Migrated ${migrated} file(s), ${failed} failure(s). Originals kept as *.v3.bak or *.pi-084.bak.`,\n );\n return failed === 0 ? 0 : 1;\n}\n\nfunction findCandidates(workspaceRoot: string): Candidate[] {\n return [\n ...findV3SessionFiles(workspaceRoot).map((file) => ({ file, format: \"v3\" as const })),\n ...findPi084SessionFiles(workspaceRoot).map((file) => ({ file, format: \"pi-084\" as const })),\n ].toSorted((left, right) => left.file.localeCompare(right.file));\n}\n\nasync function migrateCandidates(\n candidates: readonly Candidate[],\n dryRun: boolean,\n): Promise<{ migrated: number; failed: number }> {\n let migrated = 0;\n let failed = 0;\n for (const candidate of candidates) {\n const outcome = await migrateCandidate(candidate, dryRun);\n if (outcome === \"migrated\") migrated++;\n if (outcome === \"failed\") failed++;\n }\n return { migrated, failed };\n}\n\nasync function migrateCandidate(\n { file, format }: Candidate,\n dryRun: boolean,\n): Promise<\"migrated\" | \"skipped\" | \"failed\"> {\n try {\n const result =\n format === \"v3\"\n ? await migrateSessionFile(file, { dryRun })\n : await migratePi084SessionFile(file, { dryRun });\n if (result.status !== \"migrated\") return \"skipped\";\n console.log(`${dryRun ? \"would migrate\" : \"migrated\"} ${file}`);\n return \"migrated\";\n } catch (error) {\n const cause = error instanceof Error && error.cause ? ` (${String(error.cause)})` : \"\";\n console.error(`FAILED ${file}: ${errorMessage(error)}${cause}`);\n return \"failed\";\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"migrate-common.d.ts","sourceRoot":"","sources":["../../src/sessions/migrate-common.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,KAAK,IAAI,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AACjF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAGnD,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAEnD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG;IACnF,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,CAKA;AAED,qBAAa,YAAY;;IAIvB,YAAY,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAE1C;IAED,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAE1B;IAED,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAExD;IAED,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAE3D;IAMD,QAAQ,IAAI,MAAM,CAEjB;CACF;AAeD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAAG,MAAM,EAAE,CAK/F;AAUD,wBAAsB,eAAe,CAAC,OAAO,EAAE;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAClD,GAAG,OAAO,CAAC,IAAI,CAAC,CAehB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"migrate-common.js","sourceRoot":"","sources":["../../src/sessions/migrate-common.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n existsSync,\n linkSync,\n readFileSync,\n readdirSync,\n renameSync,\n rmSync,\n statSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Entry as PiEntry, JsonValue } from \"@earendil-works/pi-agent-core\";\nimport type { Usage } from \"@earendil-works/pi-ai\";\nimport { atomicWritePrivateFile } from \"../file-guards.js\";\n\nexport function jsonValue(value: unknown): JsonValue {\n return JSON.parse(JSON.stringify(value)) as JsonValue;\n}\n\nexport function optionalAnnotations(source: { details?: unknown; usage?: unknown }): {\n details?: JsonValue;\n usage?: Usage;\n} {\n return {\n details: source.details !== undefined ? jsonValue(source.details) : undefined,\n usage: source.usage as Usage | undefined,\n };\n}\n\nexport class V4FileWriter {\n readonly #lines: string[];\n #seq = 0;\n\n constructor(header: Record<string, unknown>) {\n this.#lines = [JSON.stringify(header)];\n }\n\n entry(entry: PiEntry): void {\n this.#lines.push(JSON.stringify({ kind: \"entry\", ...entry, seq: ++this.#seq }));\n }\n\n set(namespace: string, key: string, value: unknown): void {\n this.#write(\"value\", \"set\", namespace, key, value);\n }\n\n append(namespace: string, key: string, value: unknown): void {\n this.#write(\"list\", \"append\", namespace, key, value);\n }\n\n #write(kind: string, op: string, namespace: string, key: string, value: unknown): void {\n this.#lines.push(JSON.stringify({ kind, op, seq: ++this.#seq, namespace, key, value }));\n }\n\n toString(): string {\n return `${this.#lines.join(\"\\n\")}\\n`;\n }\n}\n\nfunction collectSessionFiles(\n dir: string,\n isCandidate: (path: string) => boolean,\n found: string[],\n): void {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const path = join(dir, entry.name);\n if (entry.isSymbolicLink()) continue;\n if (entry.isDirectory()) collectSessionFiles(path, isCandidate, found);\n else if (entry.name.endsWith(\".jsonl\") && isCandidate(path)) found.push(path);\n }\n}\n\nexport function findSessionFiles(root: string, isCandidate: (path: string) => boolean): string[] {\n if (!existsSync(root)) return [];\n const found: string[] = [];\n collectSessionFiles(root, isCandidate, found);\n return found;\n}\n\nfunction backupAlreadyLinked(sourcePath: string, backupPath: string): boolean {\n if (!existsSync(backupPath)) return false;\n const source = statSync(sourcePath);\n const backup = statSync(backupPath);\n if (source.dev === backup.dev && source.ino === backup.ino) return true;\n throw new Error(`Backup already exists: ${backupPath}`);\n}\n\nexport async function commitMigration(options: {\n filePath: string;\n sourceBytes: Buffer;\n encoded: string;\n tempPath: string;\n backupPath: string;\n verify: (candidatePath: string) => Promise<void>;\n}): Promise<void> {\n const { filePath, tempPath, backupPath } = options;\n const backupLinked = backupAlreadyLinked(filePath, backupPath);\n atomicWritePrivateFile(tempPath, options.encoded);\n try {\n await options.verify(tempPath);\n if (!readFileSync(filePath).equals(options.sourceBytes)) {\n throw new Error(\"source changed during migration\");\n }\n if (!backupLinked) linkSync(filePath, backupPath);\n renameSync(tempPath, filePath);\n } catch (error) {\n rmSync(tempPath, { force: true });\n throw new Error(`Migration failed for ${filePath}`, { cause: error });\n }\n}\n"]}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { Pi084MigrationResult } from "./types.js";
|
|
2
|
-
export declare function isPi084SessionFile(filePath: string): boolean;
|
|
3
|
-
export declare function migratePi084SessionFile(filePath: string, options?: {
|
|
4
|
-
dryRun?: boolean;
|
|
5
|
-
}): Promise<Pi084MigrationResult>;
|
|
6
|
-
export declare function findPi084SessionFiles(root: string): string[];
|
|
7
|
-
//# sourceMappingURL=migrate-pi-084.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"migrate-pi-084.d.ts","sourceRoot":"","sources":["../../src/sessions/migrate-pi-084.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAsDvD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAO5D;AAuPD,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAsB/B;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAE5D"}
|
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
2
|
-
import { SessionStore } from "./session-store.js";
|
|
3
|
-
import { commitMigration, findSessionFiles, jsonValue, optionalAnnotations, V4FileWriter, } from "./migrate-common.js";
|
|
4
|
-
import { isRecord } from "../unknown-values.js";
|
|
5
|
-
function firstLine(filePath) {
|
|
6
|
-
return readFileSync(filePath, "utf8").split("\n", 1)[0]?.trim() ?? "";
|
|
7
|
-
}
|
|
8
|
-
function parseHeader(value, filePath) {
|
|
9
|
-
if (!isRecord(value) ||
|
|
10
|
-
value.kind !== "header" ||
|
|
11
|
-
value.version !== 4 ||
|
|
12
|
-
typeof value.id !== "string" ||
|
|
13
|
-
typeof value.createdAt !== "number" ||
|
|
14
|
-
typeof value.cwd !== "string") {
|
|
15
|
-
throw new Error(`Invalid Pi 0.84 session header: ${filePath}`);
|
|
16
|
-
}
|
|
17
|
-
return value;
|
|
18
|
-
}
|
|
19
|
-
function isCurrentHeader(value) {
|
|
20
|
-
return (isRecord(value) &&
|
|
21
|
-
value.kind === "header" &&
|
|
22
|
-
value.v === 4 &&
|
|
23
|
-
typeof value.storageVersion === "number");
|
|
24
|
-
}
|
|
25
|
-
export function isPi084SessionFile(filePath) {
|
|
26
|
-
try {
|
|
27
|
-
const value = JSON.parse(firstLine(filePath));
|
|
28
|
-
return isRecord(value) && value.kind === "header" && value.version === 4;
|
|
29
|
-
}
|
|
30
|
-
catch {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
function convertEntry(record) {
|
|
35
|
-
const { kind: _kind, lane: _lane, ...raw } = record;
|
|
36
|
-
const base = {
|
|
37
|
-
id: String(raw.id),
|
|
38
|
-
parentId: typeof raw.parentId === "string" ? raw.parentId : null,
|
|
39
|
-
seq: Number(raw.seq),
|
|
40
|
-
timestamp: Number(raw.timestamp),
|
|
41
|
-
};
|
|
42
|
-
switch (raw.type) {
|
|
43
|
-
case "message":
|
|
44
|
-
return { ...base, type: "message", message: raw.message };
|
|
45
|
-
case "compaction":
|
|
46
|
-
return {
|
|
47
|
-
...base,
|
|
48
|
-
type: "compaction",
|
|
49
|
-
summary: String(raw.summary ?? ""),
|
|
50
|
-
retainedTail: jsonValue(raw.retainedTail ?? []),
|
|
51
|
-
tokensBefore: Number(raw.tokensBefore ?? 0),
|
|
52
|
-
fromHook: false,
|
|
53
|
-
...optionalAnnotations(raw),
|
|
54
|
-
};
|
|
55
|
-
case "branch_summary":
|
|
56
|
-
return {
|
|
57
|
-
...base,
|
|
58
|
-
type: "branch_summary",
|
|
59
|
-
fromId: typeof raw.fromId === "string" ? raw.fromId : null,
|
|
60
|
-
summary: String(raw.summary ?? ""),
|
|
61
|
-
fromHook: false,
|
|
62
|
-
...optionalAnnotations(raw),
|
|
63
|
-
};
|
|
64
|
-
case "custom":
|
|
65
|
-
return {
|
|
66
|
-
...base,
|
|
67
|
-
type: "custom",
|
|
68
|
-
customType: String(raw.customType ?? "legacy"),
|
|
69
|
-
data: raw.data !== undefined ? jsonValue(raw.data) : undefined,
|
|
70
|
-
};
|
|
71
|
-
case "model_change":
|
|
72
|
-
case "thinking_level_change":
|
|
73
|
-
case "active_tools_change": {
|
|
74
|
-
const { id: _id, parentId: _parentId, seq: _seq, timestamp: _timestamp, type, ...data } = raw;
|
|
75
|
-
return {
|
|
76
|
-
...base,
|
|
77
|
-
type: "custom",
|
|
78
|
-
customType: `mikan.pi084.${String(type)}`,
|
|
79
|
-
data: jsonValue(data),
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
default:
|
|
83
|
-
throw new Error(`Unsupported Pi 0.84 entry type: ${String(raw.type)}`);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
function applyFact(state, value) {
|
|
87
|
-
if (value.fact === "name") {
|
|
88
|
-
state.name = typeof value.name === "string" ? value.name : undefined;
|
|
89
|
-
return true;
|
|
90
|
-
}
|
|
91
|
-
if (value.fact !== "label" || typeof value.targetId !== "string")
|
|
92
|
-
return false;
|
|
93
|
-
if (typeof value.label === "string")
|
|
94
|
-
state.labels.set(value.targetId, value.label);
|
|
95
|
-
else
|
|
96
|
-
state.labels.delete(value.targetId);
|
|
97
|
-
return true;
|
|
98
|
-
}
|
|
99
|
-
function applyMutation(state, value) {
|
|
100
|
-
switch (value.kind) {
|
|
101
|
-
case "entry": {
|
|
102
|
-
const entry = convertEntry(value);
|
|
103
|
-
state.entries.push(entry);
|
|
104
|
-
if (typeof value.lane === "string")
|
|
105
|
-
state.branchTips.set(value.lane, entry.id);
|
|
106
|
-
return true;
|
|
107
|
-
}
|
|
108
|
-
case "lane": {
|
|
109
|
-
if (typeof value.lane !== "string")
|
|
110
|
-
return false;
|
|
111
|
-
state.branchTips.set(value.lane, typeof value.leafId === "string" ? value.leafId : null);
|
|
112
|
-
return true;
|
|
113
|
-
}
|
|
114
|
-
case "fact":
|
|
115
|
-
return applyFact(state, value);
|
|
116
|
-
case "record":
|
|
117
|
-
state.records.push(jsonValue(value));
|
|
118
|
-
return true;
|
|
119
|
-
default:
|
|
120
|
-
return false;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
function sessionMetadata(header) {
|
|
124
|
-
const metadata = header.metadata ? structuredClone(header.metadata) : undefined;
|
|
125
|
-
if (!header.legacyParentSessionPath || metadata?.parentSessionPath !== undefined)
|
|
126
|
-
return metadata;
|
|
127
|
-
const withParent = metadata ?? {};
|
|
128
|
-
withParent.parentSessionPath = header.legacyParentSessionPath;
|
|
129
|
-
return withParent;
|
|
130
|
-
}
|
|
131
|
-
function readLines(filePath) {
|
|
132
|
-
const source = readFileSync(filePath, "utf8");
|
|
133
|
-
const lines = source.split("\n");
|
|
134
|
-
if (lines.at(-1) === "")
|
|
135
|
-
lines.pop();
|
|
136
|
-
return { lines, torn: !source.endsWith("\n"), filePath };
|
|
137
|
-
}
|
|
138
|
-
function parseLine({ lines, torn, filePath }, index) {
|
|
139
|
-
try {
|
|
140
|
-
return JSON.parse(lines[index] ?? "");
|
|
141
|
-
}
|
|
142
|
-
catch (error) {
|
|
143
|
-
if (index === lines.length - 1 && torn)
|
|
144
|
-
return undefined;
|
|
145
|
-
throw new Error(`Invalid JSON on line ${index + 1}: ${filePath}`, { cause: error });
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
function replayMutations(state, file) {
|
|
149
|
-
for (let index = 1; index < file.lines.length; index++) {
|
|
150
|
-
const value = parseLine(file, index);
|
|
151
|
-
if (value === undefined)
|
|
152
|
-
return;
|
|
153
|
-
const where = `line ${index + 1}: ${file.filePath}`;
|
|
154
|
-
if (!isRecord(value))
|
|
155
|
-
throw new Error(`Invalid mutation on ${where}`);
|
|
156
|
-
if (!applyMutation(state, value))
|
|
157
|
-
throw new Error(`Unknown Pi 0.84 mutation on ${where}`);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
function parsePi084Session(filePath) {
|
|
161
|
-
const file = readLines(filePath);
|
|
162
|
-
const headerValue = file.lines.length === 0 ? undefined : parseLine(file, 0);
|
|
163
|
-
if (headerValue === undefined)
|
|
164
|
-
throw new Error(`Missing Pi 0.84 session header: ${filePath}`);
|
|
165
|
-
const header = parseHeader(headerValue, filePath);
|
|
166
|
-
const state = {
|
|
167
|
-
entries: [],
|
|
168
|
-
branchTips: new Map([["main", null]]),
|
|
169
|
-
labels: new Map(),
|
|
170
|
-
records: [],
|
|
171
|
-
};
|
|
172
|
-
replayMutations(state, file);
|
|
173
|
-
return { ...state, header, metadata: sessionMetadata(header) };
|
|
174
|
-
}
|
|
175
|
-
function encodeCurrentSession(source) {
|
|
176
|
-
const { header } = source;
|
|
177
|
-
const writer = new V4FileWriter({
|
|
178
|
-
v: 4,
|
|
179
|
-
kind: "header",
|
|
180
|
-
id: header.id,
|
|
181
|
-
storageVersion: 1,
|
|
182
|
-
createdAt: header.createdAt,
|
|
183
|
-
cwd: header.cwd,
|
|
184
|
-
parentSessionId: header.parentSessionId,
|
|
185
|
-
legacyParentSessionPath: header.legacyParentSessionPath,
|
|
186
|
-
});
|
|
187
|
-
for (const entry of source.entries)
|
|
188
|
-
writer.entry(entry);
|
|
189
|
-
for (const [branch, tip] of source.branchTips)
|
|
190
|
-
writer.set("pi.branch.tip", branch, tip);
|
|
191
|
-
if (source.name !== undefined)
|
|
192
|
-
writer.set("pi.session.name", "", source.name);
|
|
193
|
-
for (const [targetId, label] of source.labels)
|
|
194
|
-
writer.set("pi.entry.label", targetId, label);
|
|
195
|
-
if (source.metadata !== undefined)
|
|
196
|
-
writer.set("mikan", "metadata", source.metadata);
|
|
197
|
-
for (const record of source.records)
|
|
198
|
-
writer.append("mikan.pi084.records", "", record);
|
|
199
|
-
return writer.toString();
|
|
200
|
-
}
|
|
201
|
-
function currentWrites(path) {
|
|
202
|
-
return readFileSync(path, "utf8")
|
|
203
|
-
.split("\n")
|
|
204
|
-
.slice(1)
|
|
205
|
-
.filter(Boolean)
|
|
206
|
-
.flatMap((line) => {
|
|
207
|
-
const parsed = JSON.parse(line);
|
|
208
|
-
return Array.isArray(parsed) ? parsed : [parsed];
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
function valueWritten(writes, namespace, key) {
|
|
212
|
-
return writes.findLast((write) => write.kind === "value" &&
|
|
213
|
-
write.op === "set" &&
|
|
214
|
-
write.namespace === namespace &&
|
|
215
|
-
write.key === key)?.value;
|
|
216
|
-
}
|
|
217
|
-
function verifyEntries(entries, source) {
|
|
218
|
-
if (entries.length !== source.length)
|
|
219
|
-
throw new Error("entry count changed");
|
|
220
|
-
for (const [index, entry] of entries.entries()) {
|
|
221
|
-
const original = source[index];
|
|
222
|
-
if (!original)
|
|
223
|
-
throw new Error(`entry ${index + 1} changed`);
|
|
224
|
-
const { seq: _entrySeq, ...entryData } = entry;
|
|
225
|
-
const { seq: _originalSeq, ...originalData } = original;
|
|
226
|
-
if (JSON.stringify(entryData) !== JSON.stringify(originalData)) {
|
|
227
|
-
throw new Error(`entry ${index + 1} changed`);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
function verifyValues(writes, namespace, expected, describe) {
|
|
232
|
-
for (const [key, value] of expected) {
|
|
233
|
-
if (valueWritten(writes, namespace, key) !== value)
|
|
234
|
-
throw new Error(describe(key));
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
function verifyValueWrites(path, source) {
|
|
238
|
-
const writes = currentWrites(path);
|
|
239
|
-
verifyValues(writes, "pi.branch.tip", source.branchTips, (key) => `branch ${key} tip changed`);
|
|
240
|
-
verifyValues(writes, "pi.entry.label", source.labels, (key) => `label ${key} changed`);
|
|
241
|
-
if (JSON.stringify(valueWritten(writes, "mikan", "metadata")) !== JSON.stringify(source.metadata)) {
|
|
242
|
-
throw new Error("mikan metadata changed");
|
|
243
|
-
}
|
|
244
|
-
const auditRecords = writes.filter((write) => write.kind === "list" && write.namespace === "mikan.pi084.records");
|
|
245
|
-
if (auditRecords.length !== source.records.length)
|
|
246
|
-
throw new Error("audit records changed");
|
|
247
|
-
}
|
|
248
|
-
async function verifyCandidate(path, source) {
|
|
249
|
-
const inspection = await SessionStore.inspect(path);
|
|
250
|
-
verifyEntries(await inspection.getEntries(), source.entries);
|
|
251
|
-
const branch = await inspection.getBranch();
|
|
252
|
-
if ((branch.at(-1)?.id ?? null) !== (source.branchTips.get("main") ?? null)) {
|
|
253
|
-
throw new Error("main branch tip changed");
|
|
254
|
-
}
|
|
255
|
-
if ((await inspection.getSessionName()) !== source.name)
|
|
256
|
-
throw new Error("session name changed");
|
|
257
|
-
const header = inspection.getHeader();
|
|
258
|
-
if (header.id !== source.header.id ||
|
|
259
|
-
header.timestamp !== new Date(source.header.createdAt).toISOString()) {
|
|
260
|
-
throw new Error("session identity changed");
|
|
261
|
-
}
|
|
262
|
-
verifyValueWrites(path, source);
|
|
263
|
-
}
|
|
264
|
-
export async function migratePi084SessionFile(filePath, options) {
|
|
265
|
-
let headerValue;
|
|
266
|
-
try {
|
|
267
|
-
headerValue = JSON.parse(firstLine(filePath));
|
|
268
|
-
}
|
|
269
|
-
catch {
|
|
270
|
-
return { file: filePath, status: "not-pi-084" };
|
|
271
|
-
}
|
|
272
|
-
if (isCurrentHeader(headerValue))
|
|
273
|
-
return { file: filePath, status: "already-current" };
|
|
274
|
-
if (!isPi084SessionFile(filePath))
|
|
275
|
-
return { file: filePath, status: "not-pi-084" };
|
|
276
|
-
const sourceBytes = readFileSync(filePath);
|
|
277
|
-
const source = parsePi084Session(filePath);
|
|
278
|
-
if (options?.dryRun)
|
|
279
|
-
return { file: filePath, status: "migrated", detail: "dry run" };
|
|
280
|
-
await commitMigration({
|
|
281
|
-
filePath,
|
|
282
|
-
sourceBytes,
|
|
283
|
-
encoded: encodeCurrentSession(source),
|
|
284
|
-
tempPath: `${filePath}.pi-085.tmp`,
|
|
285
|
-
backupPath: `${filePath}.pi-084.bak`,
|
|
286
|
-
verify: (candidatePath) => verifyCandidate(candidatePath, source),
|
|
287
|
-
});
|
|
288
|
-
return { file: filePath, status: "migrated" };
|
|
289
|
-
}
|
|
290
|
-
export function findPi084SessionFiles(root) {
|
|
291
|
-
return findSessionFiles(root, isPi084SessionFile);
|
|
292
|
-
}
|
|
293
|
-
//# sourceMappingURL=migrate-pi-084.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"migrate-pi-084.js","sourceRoot":"","sources":["../../src/sessions/migrate-pi-084.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync } from \"node:fs\";\nimport type { AgentMessage, Entry, JsonValue } from \"@earendil-works/pi-agent-core\";\nimport { SessionStore } from \"./session-store.js\";\n\nimport {\n commitMigration,\n findSessionFiles,\n jsonValue,\n optionalAnnotations,\n V4FileWriter,\n} from \"./migrate-common.js\";\nimport type { Pi084MigrationResult } from \"./types.js\";\nimport { isRecord } from \"../unknown-values.js\";\n\ninterface Pi084Header {\n kind: \"header\";\n version: 4;\n id: string;\n createdAt: number;\n cwd: string;\n parentSessionId?: string;\n legacyParentSessionPath?: string;\n metadata?: Record<string, JsonValue>;\n}\n\ninterface Pi084Mutations {\n entries: Entry[];\n branchTips: Map<string, string | null>;\n labels: Map<string, string>;\n records: JsonValue[];\n name?: string;\n}\n\ninterface ParsedPi084Session extends Pi084Mutations {\n header: Pi084Header;\n metadata?: Record<string, JsonValue>;\n}\n\nfunction firstLine(filePath: string): string {\n return readFileSync(filePath, \"utf8\").split(\"\\n\", 1)[0]?.trim() ?? \"\";\n}\n\nfunction parseHeader(value: unknown, filePath: string): Pi084Header {\n if (\n !isRecord(value) ||\n value.kind !== \"header\" ||\n value.version !== 4 ||\n typeof value.id !== \"string\" ||\n typeof value.createdAt !== \"number\" ||\n typeof value.cwd !== \"string\"\n ) {\n throw new Error(`Invalid Pi 0.84 session header: ${filePath}`);\n }\n return value as unknown as Pi084Header;\n}\n\nfunction isCurrentHeader(value: unknown): boolean {\n return (\n isRecord(value) &&\n value.kind === \"header\" &&\n value.v === 4 &&\n typeof value.storageVersion === \"number\"\n );\n}\n\nexport function isPi084SessionFile(filePath: string): boolean {\n try {\n const value: unknown = JSON.parse(firstLine(filePath));\n return isRecord(value) && value.kind === \"header\" && value.version === 4;\n } catch {\n return false;\n }\n}\n\nfunction convertEntry(record: Record<string, unknown>): Entry {\n const { kind: _kind, lane: _lane, ...raw } = record;\n const base = {\n id: String(raw.id),\n parentId: typeof raw.parentId === \"string\" ? raw.parentId : null,\n seq: Number(raw.seq),\n timestamp: Number(raw.timestamp),\n };\n switch (raw.type) {\n case \"message\":\n return { ...base, type: \"message\", message: raw.message as AgentMessage };\n case \"compaction\":\n return {\n ...base,\n type: \"compaction\",\n summary: String(raw.summary ?? \"\"),\n retainedTail: jsonValue(raw.retainedTail ?? []) as unknown as AgentMessage[],\n tokensBefore: Number(raw.tokensBefore ?? 0),\n fromHook: false,\n ...optionalAnnotations(raw),\n };\n case \"branch_summary\":\n return {\n ...base,\n type: \"branch_summary\",\n fromId: typeof raw.fromId === \"string\" ? raw.fromId : null,\n summary: String(raw.summary ?? \"\"),\n fromHook: false,\n ...optionalAnnotations(raw),\n };\n case \"custom\":\n return {\n ...base,\n type: \"custom\",\n customType: String(raw.customType ?? \"legacy\"),\n data: raw.data !== undefined ? jsonValue(raw.data) : undefined,\n };\n case \"model_change\":\n case \"thinking_level_change\":\n case \"active_tools_change\": {\n const { id: _id, parentId: _parentId, seq: _seq, timestamp: _timestamp, type, ...data } = raw;\n return {\n ...base,\n type: \"custom\",\n customType: `mikan.pi084.${String(type)}`,\n data: jsonValue(data),\n };\n }\n default:\n throw new Error(`Unsupported Pi 0.84 entry type: ${String(raw.type)}`);\n }\n}\n\nfunction applyFact(state: Pi084Mutations, value: Record<string, unknown>): boolean {\n if (value.fact === \"name\") {\n state.name = typeof value.name === \"string\" ? value.name : undefined;\n return true;\n }\n if (value.fact !== \"label\" || typeof value.targetId !== \"string\") return false;\n if (typeof value.label === \"string\") state.labels.set(value.targetId, value.label);\n else state.labels.delete(value.targetId);\n return true;\n}\n\nfunction applyMutation(state: Pi084Mutations, value: Record<string, unknown>): boolean {\n switch (value.kind) {\n case \"entry\": {\n const entry = convertEntry(value);\n state.entries.push(entry);\n if (typeof value.lane === \"string\") state.branchTips.set(value.lane, entry.id);\n return true;\n }\n case \"lane\": {\n if (typeof value.lane !== \"string\") return false;\n state.branchTips.set(value.lane, typeof value.leafId === \"string\" ? value.leafId : null);\n return true;\n }\n case \"fact\":\n return applyFact(state, value);\n case \"record\":\n state.records.push(jsonValue(value));\n return true;\n default:\n return false;\n }\n}\n\nfunction sessionMetadata(header: Pi084Header): Record<string, JsonValue> | undefined {\n const metadata = header.metadata ? structuredClone(header.metadata) : undefined;\n if (!header.legacyParentSessionPath || metadata?.parentSessionPath !== undefined) return metadata;\n const withParent = metadata ?? {};\n withParent.parentSessionPath = header.legacyParentSessionPath;\n return withParent;\n}\n\ninterface Pi084Lines {\n lines: string[];\n torn: boolean;\n filePath: string;\n}\n\nfunction readLines(filePath: string): Pi084Lines {\n const source = readFileSync(filePath, \"utf8\");\n const lines = source.split(\"\\n\");\n if (lines.at(-1) === \"\") lines.pop();\n return { lines, torn: !source.endsWith(\"\\n\"), filePath };\n}\n\nfunction parseLine({ lines, torn, filePath }: Pi084Lines, index: number): unknown {\n try {\n return JSON.parse(lines[index] ?? \"\");\n } catch (error) {\n if (index === lines.length - 1 && torn) return undefined;\n throw new Error(`Invalid JSON on line ${index + 1}: ${filePath}`, { cause: error });\n }\n}\n\nfunction replayMutations(state: Pi084Mutations, file: Pi084Lines): void {\n for (let index = 1; index < file.lines.length; index++) {\n const value = parseLine(file, index);\n if (value === undefined) return;\n const where = `line ${index + 1}: ${file.filePath}`;\n if (!isRecord(value)) throw new Error(`Invalid mutation on ${where}`);\n if (!applyMutation(state, value)) throw new Error(`Unknown Pi 0.84 mutation on ${where}`);\n }\n}\n\nfunction parsePi084Session(filePath: string): ParsedPi084Session {\n const file = readLines(filePath);\n const headerValue = file.lines.length === 0 ? undefined : parseLine(file, 0);\n if (headerValue === undefined) throw new Error(`Missing Pi 0.84 session header: ${filePath}`);\n const header = parseHeader(headerValue, filePath);\n const state: Pi084Mutations = {\n entries: [],\n branchTips: new Map([[\"main\", null]]),\n labels: new Map(),\n records: [],\n };\n replayMutations(state, file);\n return { ...state, header, metadata: sessionMetadata(header) };\n}\n\nfunction encodeCurrentSession(source: ParsedPi084Session): string {\n const { header } = source;\n const writer = new V4FileWriter({\n v: 4,\n kind: \"header\",\n id: header.id,\n storageVersion: 1,\n createdAt: header.createdAt,\n cwd: header.cwd,\n parentSessionId: header.parentSessionId,\n legacyParentSessionPath: header.legacyParentSessionPath,\n });\n for (const entry of source.entries) writer.entry(entry);\n for (const [branch, tip] of source.branchTips) writer.set(\"pi.branch.tip\", branch, tip);\n if (source.name !== undefined) writer.set(\"pi.session.name\", \"\", source.name);\n for (const [targetId, label] of source.labels) writer.set(\"pi.entry.label\", targetId, label);\n if (source.metadata !== undefined) writer.set(\"mikan\", \"metadata\", source.metadata);\n for (const record of source.records) writer.append(\"mikan.pi084.records\", \"\", record);\n return writer.toString();\n}\n\nfunction currentWrites(path: string): Array<Record<string, unknown>> {\n return readFileSync(path, \"utf8\")\n .split(\"\\n\")\n .slice(1)\n .filter(Boolean)\n .flatMap((line) => {\n const parsed = JSON.parse(line) as Record<string, unknown> | Array<Record<string, unknown>>;\n return Array.isArray(parsed) ? parsed : [parsed];\n });\n}\n\nfunction valueWritten(\n writes: Array<Record<string, unknown>>,\n namespace: string,\n key: string,\n): unknown {\n return writes.findLast(\n (write) =>\n write.kind === \"value\" &&\n write.op === \"set\" &&\n write.namespace === namespace &&\n write.key === key,\n )?.value;\n}\n\nfunction verifyEntries(entries: Entry[], source: Entry[]): void {\n if (entries.length !== source.length) throw new Error(\"entry count changed\");\n for (const [index, entry] of entries.entries()) {\n const original = source[index];\n if (!original) throw new Error(`entry ${index + 1} changed`);\n const { seq: _entrySeq, ...entryData } = entry;\n const { seq: _originalSeq, ...originalData } = original;\n if (JSON.stringify(entryData) !== JSON.stringify(originalData)) {\n throw new Error(`entry ${index + 1} changed`);\n }\n }\n}\n\nfunction verifyValues(\n writes: Array<Record<string, unknown>>,\n namespace: string,\n expected: ReadonlyMap<string, string | null>,\n describe: (key: string) => string,\n): void {\n for (const [key, value] of expected) {\n if (valueWritten(writes, namespace, key) !== value) throw new Error(describe(key));\n }\n}\n\nfunction verifyValueWrites(path: string, source: ParsedPi084Session): void {\n const writes = currentWrites(path);\n verifyValues(writes, \"pi.branch.tip\", source.branchTips, (key) => `branch ${key} tip changed`);\n verifyValues(writes, \"pi.entry.label\", source.labels, (key) => `label ${key} changed`);\n if (\n JSON.stringify(valueWritten(writes, \"mikan\", \"metadata\")) !== JSON.stringify(source.metadata)\n ) {\n throw new Error(\"mikan metadata changed\");\n }\n const auditRecords = writes.filter(\n (write) => write.kind === \"list\" && write.namespace === \"mikan.pi084.records\",\n );\n if (auditRecords.length !== source.records.length) throw new Error(\"audit records changed\");\n}\n\nasync function verifyCandidate(path: string, source: ParsedPi084Session): Promise<void> {\n const inspection = await SessionStore.inspect(path);\n verifyEntries(await inspection.getEntries(), source.entries);\n const branch = await inspection.getBranch();\n if ((branch.at(-1)?.id ?? null) !== (source.branchTips.get(\"main\") ?? null)) {\n throw new Error(\"main branch tip changed\");\n }\n if ((await inspection.getSessionName()) !== source.name) throw new Error(\"session name changed\");\n const header = inspection.getHeader();\n if (\n header.id !== source.header.id ||\n header.timestamp !== new Date(source.header.createdAt).toISOString()\n ) {\n throw new Error(\"session identity changed\");\n }\n verifyValueWrites(path, source);\n}\n\nexport async function migratePi084SessionFile(\n filePath: string,\n options?: { dryRun?: boolean },\n): Promise<Pi084MigrationResult> {\n let headerValue: unknown;\n try {\n headerValue = JSON.parse(firstLine(filePath));\n } catch {\n return { file: filePath, status: \"not-pi-084\" };\n }\n if (isCurrentHeader(headerValue)) return { file: filePath, status: \"already-current\" };\n if (!isPi084SessionFile(filePath)) return { file: filePath, status: \"not-pi-084\" };\n const sourceBytes = readFileSync(filePath);\n const source = parsePi084Session(filePath);\n if (options?.dryRun) return { file: filePath, status: \"migrated\", detail: \"dry run\" };\n\n await commitMigration({\n filePath,\n sourceBytes,\n encoded: encodeCurrentSession(source),\n tempPath: `${filePath}.pi-085.tmp`,\n backupPath: `${filePath}.pi-084.bak`,\n verify: (candidatePath) => verifyCandidate(candidatePath, source),\n });\n return { file: filePath, status: \"migrated\" };\n}\n\nexport function findPi084SessionFiles(root: string): string[] {\n return findSessionFiles(root, isPi084SessionFile);\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"migrate-v3.d.ts","sourceRoot":"","sources":["../../src/sessions/migrate-v3.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAmEhD,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAUzD;AAoVD,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7B,OAAO,CAAC,aAAa,CAAC,CAexB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAEzD"}
|