pi-archimedes 1.7.1 → 1.8.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-archimedes",
3
- "version": "1.7.1",
3
+ "version": "1.8.0",
4
4
  "type": "module",
5
5
  "keywords": [
6
6
  "pi-package"
@@ -11,14 +11,14 @@
11
11
  ],
12
12
  "main": "./src/index.ts",
13
13
  "dependencies": {
14
- "@pi-archimedes/core": "1.7.1",
15
- "@pi-archimedes/diff": "1.7.1",
16
- "@pi-archimedes/footer": "1.7.1",
17
- "@pi-archimedes/image-paste": "1.7.1",
18
- "@pi-archimedes/ask": "1.7.1",
19
- "@pi-archimedes/subagent": "1.7.1",
20
- "@pi-archimedes/todo": "1.7.1",
21
- "@pi-archimedes/notify": "1.7.1"
14
+ "@pi-archimedes/core": "1.8.0",
15
+ "@pi-archimedes/diff": "1.8.0",
16
+ "@pi-archimedes/ask": "1.8.0",
17
+ "@pi-archimedes/image-paste": "1.8.0",
18
+ "@pi-archimedes/subagent": "1.8.0",
19
+ "@pi-archimedes/todo": "1.8.0",
20
+ "@pi-archimedes/notify": "1.8.0",
21
+ "@pi-archimedes/footer": "1.8.0"
22
22
  },
23
23
  "peerDependencies": {
24
24
  "@earendil-works/pi-coding-agent": ">=0.1.0",
package/src/index.ts CHANGED
@@ -1,58 +1,99 @@
1
1
  import type { ExtensionAPI, ExtensionContext, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
2
2
 
3
+ import { time as archTime, print as archPrintTimings, reset as archResetTimings } from "@pi-archimedes/core/profiler";
3
4
  import { registerCore, unpatchConsoleLog } from "@pi-archimedes/core";
4
5
  import { registerFooter } from "@pi-archimedes/footer";
5
- import { registerDiffTools } from "@pi-archimedes/diff";
6
- import { registerImagePaste, initImagePasteSession, shutdownImagePaste } from "@pi-archimedes/image-paste";
7
- import { registerSubagent, registerAgentsCommand } from "@pi-archimedes/subagent";
6
+
7
+ // Mark when module finishes evaluating (before factory runs) for gap analysis
8
+ const _moduleEvalAt = Date.now();
9
+ // diff — lazy-loaded in session_start to avoid pulling @shikijs/cli at startup
10
+ // image-paste & subagent — also lazy-loaded below (heavy deps, only needed on use)
8
11
  import { registerTodo } from "@pi-archimedes/todo";
9
12
  import { registerAsk } from "@pi-archimedes/ask";
10
13
  import { registerNotify } from "@pi-archimedes/notify";
11
14
  import { loadDiffConfig } from "./config.js";
12
- import { openSettings } from "./settings.js";
15
+ import { openSettings } from "./settings.js"
16
+
17
+ // Module-level refs for shutdown (survive hot-reloads)
18
+ let imagePasteShutdown: (() => void) | undefined;
19
+ // Guard: tracks which lazy-loaded packages have been registered.
20
+ // session_start fires for /new, /resume, /fork, /reload — each tears down the
21
+ // old runtime and rebuilds, but pi itself stays loaded, so this module is
22
+ // evaluated once and these guards prevent handler accumulation on reload.
23
+ const registeredLazy = new Set<string>();
13
24
 
14
25
  export default function (pi: ExtensionAPI): void {
15
- // Register all component extensions
26
+ archResetTimings();
27
+ archTime(`factory start (module eval was ${Date.now() - _moduleEvalAt}ms ago)`);
28
+
29
+ // Register all component extensions (static imports already compiled by jiti above)
16
30
  registerCore(pi);
31
+ archTime("registerCore");
17
32
  registerFooter(pi);
33
+ archTime("registerFooter");
18
34
 
19
- // Register image paste (shortcuts, input handler, preview renderer)
20
- registerImagePaste(pi);
35
+ // image-paste & subagent lazy-loaded in session_start below — not here
21
36
 
22
- // Register subagent tool
23
- registerSubagent(pi);
24
-
25
- // Register todo
37
+ // Register todo (lightweight, registers tool + bus listener)
26
38
  registerTodo(pi);
39
+ archTime("registerTodo");
27
40
 
28
41
  // Register ask tool
29
42
  registerAsk(pi);
43
+ archTime("registerAsk");
30
44
 
31
45
  // Register notify
32
46
  registerNotify(pi);
47
+ archTime("registerNotify");
33
48
 
34
- // Register /agents command
35
- registerAgentsCommand(pi);
49
+ archTime("factory end");
36
50
 
37
51
  // session_shutdown handler (top-level to prevent accumulation on /reload)
38
52
  pi.on("session_shutdown", (_event, _ctx) => {
39
- shutdownImagePaste();
53
+ imagePasteShutdown?.();
40
54
  unpatchConsoleLog();
55
+ archPrintTimings();
41
56
  });
42
57
 
43
- pi.on("session_start", (_event, ctx: ExtensionContext) => {
44
- // Register diff tools (needs getTheme + readConfig callbacks)
45
- registerDiffTools(pi, () => ctx.ui.theme, () => loadDiffConfig());
58
+ pi.on("session_start", async (_event, ctx: ExtensionContext) => {
59
+ archTime(`session_start (factory was ${Date.now() - _moduleEvalAt}ms ago)`);
60
+
61
+ // ── Parallel lazy-load all three packages (saves ~100ms vs sequential) ──
62
+ const [diffMod, ipMod, saMod] = await Promise.all([
63
+ import("@pi-archimedes/diff").catch((e) => { console.error("[archimedes] diff load failed:", e); return null; }),
64
+ import("@pi-archimedes/image-paste").catch((e) => { console.error("[archimedes] image-paste load failed:", e); return null; }),
65
+ import("@pi-archimedes/subagent").catch((e) => { console.error("[archimedes] subagent load failed:", e); return null; }),
66
+ ]);
67
+ archTime("3 packages loaded in parallel");
46
68
 
47
- // Initialize image paste for this session
48
- initImagePasteSession(ctx);
69
+ if (diffMod && !registeredLazy.has("diff")) {
70
+ diffMod.registerDiffTools(pi, () => ctx.ui.theme, () => loadDiffConfig());
71
+ registeredLazy.add("diff");
72
+ }
73
+ if (ipMod) {
74
+ // initImagePasteSession must run every session_start (it captures the new ctx)
75
+ // but the actual handler registration via pi.on("input", ...) must only happen once.
76
+ if (!registeredLazy.has("image-paste")) {
77
+ ipMod.registerImagePaste(pi);
78
+ imagePasteShutdown = ipMod.shutdownImagePaste;
79
+ registeredLazy.add("image-paste");
80
+ }
81
+ ipMod.initImagePasteSession(ctx);
82
+ }
83
+ if (saMod) {
84
+ if (!registeredLazy.has("subagent")) {
85
+ saMod.registerSubagent(pi);
86
+ saMod.registerAgentsCommand(pi);
87
+ registeredLazy.add("subagent");
88
+ }
89
+ }
49
90
  });
50
91
 
51
92
  // Register /archimedes command
52
93
  pi.registerCommand("archimedes", {
53
94
  description: "Open Archimedes settings",
54
95
  handler: async (_args: string, ctx: ExtensionCommandContext) => {
55
- openSettings(pi, ctx);
96
+ await openSettings(pi, ctx);
56
97
  },
57
98
  });
58
99
  }
package/src/settings.ts CHANGED
@@ -5,7 +5,7 @@ import { SettingsList, type SettingItem, TUI } from "@earendil-works/pi-tui";
5
5
 
6
6
  import { getCoreSettingsItems } from "@pi-archimedes/core";
7
7
  import { getFooterSettingsItems } from "@pi-archimedes/footer/config";
8
- import { getDiffSettingsItems } from "@pi-archimedes/diff";
8
+ // diff (shiki) is lazy-loaded below to keep shiki out of the startup import chain
9
9
  import { getNotifySettingsItems } from "@pi-archimedes/notify";
10
10
  import {
11
11
  loadAllConfig,
@@ -94,7 +94,9 @@ function createNumberSubmenu(opts: {
94
94
 
95
95
  // ── Settings UI ─────────────────────────────────────────────────────────
96
96
 
97
- export function openSettings(pi: ExtensionAPI, ctx: ExtensionContext): void {
97
+ export async function openSettings(pi: ExtensionAPI, ctx: ExtensionContext): Promise<void> {
98
+ // Lazy-load diff (pulls in shiki) — only needed when /archimedes is opened
99
+ const { getDiffSettingsItems } = await import("@pi-archimedes/diff");
98
100
  const allConfig = loadAllConfig();
99
101
 
100
102
  const coreConfig: CoreConfig = { ...allConfig.core };