@jaggerxtrm/pi-extensions 0.7.8

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.
Files changed (61) hide show
  1. package/MIGRATION_NOTES.md +39 -0
  2. package/README.md +43 -0
  3. package/extensions/README.md +5 -0
  4. package/extensions/auto-session-name/index.ts +29 -0
  5. package/extensions/auto-session-name/package.json +16 -0
  6. package/extensions/auto-update/index.ts +71 -0
  7. package/extensions/auto-update/package.json +16 -0
  8. package/extensions/beads/index.ts +232 -0
  9. package/extensions/beads/package.json +16 -0
  10. package/extensions/compact-header/index.ts +69 -0
  11. package/extensions/compact-header/package.json +16 -0
  12. package/extensions/custom-footer/index.ts +398 -0
  13. package/extensions/custom-footer/package.json +16 -0
  14. package/extensions/custom-provider-qwen-cli/index.ts +363 -0
  15. package/extensions/custom-provider-qwen-cli/package.json +16 -0
  16. package/extensions/git-checkpoint/index.ts +53 -0
  17. package/extensions/git-checkpoint/package.json +16 -0
  18. package/extensions/lsp-bootstrap/index.ts +134 -0
  19. package/extensions/lsp-bootstrap/package.json +17 -0
  20. package/extensions/pi-serena-compact/index.ts +121 -0
  21. package/extensions/pi-serena-compact/package.json +23 -0
  22. package/extensions/quality-gates/index.ts +66 -0
  23. package/extensions/quality-gates/package.json +16 -0
  24. package/extensions/service-skills/index.ts +108 -0
  25. package/extensions/service-skills/package.json +16 -0
  26. package/extensions/session-flow/index.ts +96 -0
  27. package/extensions/session-flow/package.json +16 -0
  28. package/extensions/xtrm-loader/index.ts +152 -0
  29. package/extensions/xtrm-loader/package.json +16 -0
  30. package/extensions/xtrm-ui/format.ts +282 -0
  31. package/extensions/xtrm-ui/index.ts +1112 -0
  32. package/extensions/xtrm-ui/package.json +21 -0
  33. package/package.json +46 -0
  34. package/src/core/README.md +9 -0
  35. package/src/core/adapter.ts +52 -0
  36. package/src/core/guard-rules.ts +100 -0
  37. package/src/core/index.ts +5 -0
  38. package/src/core/lib.ts +3 -0
  39. package/src/core/logger.ts +45 -0
  40. package/src/core/runner.ts +71 -0
  41. package/src/core/session-state.ts +59 -0
  42. package/src/extensions/auto-session-name.ts +3 -0
  43. package/src/extensions/auto-update.ts +3 -0
  44. package/src/extensions/beads.ts +3 -0
  45. package/src/extensions/compact-header.ts +3 -0
  46. package/src/extensions/custom-footer.ts +3 -0
  47. package/src/extensions/custom-provider-qwen-cli.ts +3 -0
  48. package/src/extensions/git-checkpoint.ts +3 -0
  49. package/src/extensions/lsp-bootstrap.ts +3 -0
  50. package/src/extensions/pi-serena-compact.ts +3 -0
  51. package/src/extensions/quality-gates.ts +3 -0
  52. package/src/extensions/service-skills.ts +3 -0
  53. package/src/extensions/session-flow.ts +3 -0
  54. package/src/extensions/xtrm-loader.ts +3 -0
  55. package/src/extensions/xtrm-ui.ts +3 -0
  56. package/src/index.ts +9 -0
  57. package/src/registry.ts +52 -0
  58. package/src/shared/index.ts +1 -0
  59. package/src/shared/legacy-path-map.ts +23 -0
  60. package/themes/xtrm-ui/pidex-dark.json +85 -0
  61. package/themes/xtrm-ui/pidex-light.json +85 -0
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@xtrm/pi-xtrm-ui",
3
+ "version": "1.1.0",
4
+ "description": "XTRM UI: pi-dex chrome + pi-diff style write/edit rendering with custom-footer-safe ownership",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": "./index.ts"
8
+ },
9
+ "license": "MIT",
10
+ "dependencies": {
11
+ "@heyhuynhgiabuu/pi-diff": "^0.2.1"
12
+ },
13
+ "pi": {
14
+ "extensions": [
15
+ "./index.ts"
16
+ ],
17
+ "themes": [
18
+ "./themes"
19
+ ]
20
+ }
21
+ }
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@jaggerxtrm/pi-extensions",
3
+ "version": "0.7.8",
4
+ "description": "Unified Pi extension entrypoint for xtrm-managed extensions",
5
+ "type": "module",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "keywords": [
10
+ "pi-package",
11
+ "pi",
12
+ "extension",
13
+ "xtrm"
14
+ ],
15
+ "exports": {
16
+ ".": "./src/index.ts",
17
+ "./registry": "./src/registry.ts"
18
+ },
19
+ "pi": {
20
+ "extensions": [
21
+ "./src/index.ts"
22
+ ]
23
+ },
24
+ "author": "xtrm",
25
+ "license": "MIT",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/Jaggerxtrm/xtrm-tools.git",
29
+ "directory": "packages/pi-extensions"
30
+ },
31
+ "homepage": "https://github.com/Jaggerxtrm/xtrm-tools/tree/main/packages/pi-extensions",
32
+ "bugs": {
33
+ "url": "https://github.com/Jaggerxtrm/xtrm-tools/issues"
34
+ },
35
+ "scripts": {
36
+ "prepublishOnly": "npm run verify:runtime",
37
+ "verify:runtime": "node -e \"const fs=require('fs');const required=['src/index.ts','src/registry.ts','extensions','themes'];const missing=required.filter((entry)=>!fs.existsSync(entry));if(missing.length){console.error('Missing publish runtime assets: '+missing.join(', '));process.exit(1);}console.log('Runtime assets present for npm publish.');\""
38
+ },
39
+ "files": [
40
+ "src",
41
+ "extensions",
42
+ "themes",
43
+ "MIGRATION_NOTES.md",
44
+ "README.md"
45
+ ]
46
+ }
@@ -0,0 +1,9 @@
1
+ # Internal core module layout
2
+
3
+ This directory is the internal home for shared code that previously lived in the published `@xtrm/pi-core` package.
4
+
5
+ ## Contract for follow-up phases
6
+
7
+ - Keep all shared runtime helpers under `src/core/**`.
8
+ - Import from relative paths inside `@jaggerxtrm/pi-extensions`; do not publish or depend on `@xtrm/pi-core`.
9
+ - Delegate concrete extension entrypoints from `extensions/**` through the package root `src/index.ts`.
@@ -0,0 +1,52 @@
1
+ import * as fs from "node:fs";
2
+ import * as nodePath from "node:path";
3
+
4
+ import type { ExtensionAPI, ToolCallEvent } from "@mariozechner/pi-coding-agent";
5
+ import { PI_MUTATING_FILE_TOOLS } from "./guard-rules";
6
+
7
+ export class EventAdapter {
8
+ /**
9
+ * Checks if the tool event is a mutating file operation (write, edit, etc).
10
+ */
11
+ static isMutatingFileTool(event: ToolCallEvent<any, any>): boolean {
12
+ return PI_MUTATING_FILE_TOOLS.includes(event.toolName);
13
+ }
14
+
15
+ /**
16
+ * Extracts the target path from a tool input, resolving against the current working directory.
17
+ */
18
+ static extractPathFromToolInput(event: ToolCallEvent<any, any>, cwd: string): string | null {
19
+ const input = event.input;
20
+ if (!input) return null;
21
+
22
+ const pathRaw = input.path || input.file || input.filePath;
23
+ if (typeof pathRaw === "string") {
24
+ return pathRaw; // Usually Pi passes absolute paths anyway or paths relative to root
25
+ }
26
+
27
+ return null;
28
+ }
29
+
30
+ /**
31
+ * Safely formats a block reason string to ensure UI readiness.
32
+ */
33
+ static formatBlockReason(prefix: string, details: string): string {
34
+ return `${prefix}: ${details}`;
35
+ }
36
+ /**
37
+ * Returns true if the given directory is a beads project (has a .beads directory).
38
+ */
39
+ static isBeadsProject(cwd: string): boolean {
40
+ return fs.existsSync(nodePath.join(cwd, ".beads"));
41
+ }
42
+
43
+ /**
44
+ * Parses the summary line from `bd list` output.
45
+ * Returns { open, inProgress } or null if the line is absent.
46
+ */
47
+ static parseBdCounts(output: string): { open: number; inProgress: number } | null {
48
+ const m = output.match(/Total:\s*\d+\s+issues?\s*\((\d+)\s+open,\s*(\d+)\s+in progress\)/);
49
+ if (!m) return null;
50
+ return { open: parseInt(m[1], 10), inProgress: parseInt(m[2], 10) };
51
+ }
52
+ }
@@ -0,0 +1,100 @@
1
+ // Canonical guard-rule constants for Pi extensions.
2
+ // Mirrors hooks/guard-rules.mjs with Pi-specific tool naming where needed.
3
+
4
+ export const PI_MUTATING_FILE_TOOLS = [
5
+ "write",
6
+ "edit",
7
+ "replace_content",
8
+ "replace_lines",
9
+ "delete_lines",
10
+ "insert_at_line",
11
+ "create_text_file",
12
+ "rename_symbol",
13
+ "replace_symbol_body",
14
+ "insert_after_symbol",
15
+ "insert_before_symbol",
16
+ ];
17
+
18
+ export const SAFE_BASH_PREFIXES = [
19
+ // Git read-only
20
+ "git status",
21
+ "git log",
22
+ "git diff",
23
+ "git show",
24
+ "git blame",
25
+ "git branch",
26
+ "git fetch",
27
+ "git remote",
28
+ "git config",
29
+ "git pull",
30
+ "git stash",
31
+ "git worktree",
32
+ "git checkout -b",
33
+ "git switch -c",
34
+ // Tools
35
+ "gh",
36
+ "bd",
37
+ "npx gitnexus",
38
+ "xtrm finish",
39
+ // Read-only filesystem
40
+ "cat",
41
+ "ls",
42
+ "head",
43
+ "tail",
44
+ "pwd",
45
+ "which",
46
+ "type",
47
+ "env",
48
+ "printenv",
49
+ "find",
50
+ "grep",
51
+ "rg",
52
+ "fd",
53
+ "wc",
54
+ "sort",
55
+ "uniq",
56
+ "cut",
57
+ "awk",
58
+ "jq",
59
+ "yq",
60
+ "bat",
61
+ "less",
62
+ "more",
63
+ "file",
64
+ "stat",
65
+ "du",
66
+ "tree",
67
+ ];
68
+
69
+ export const DANGEROUS_BASH_PATTERNS = [
70
+ "sed\\s+-i",
71
+ "echo\\s+[^\\n]*>",
72
+ "printf\\s+[^\\n]*>",
73
+ "cat\\s+[^\\n]*>",
74
+ "tee\\b",
75
+ "(?:^|\\s)(?:vim|nano|vi)\\b",
76
+ "(?:^|\\s)mv\\b",
77
+ "(?:^|\\s)cp\\b",
78
+ "(?:^|\\s)rm\\b",
79
+ "(?:^|\\s)mkdir\\b",
80
+ "(?:^|\\s)touch\\b",
81
+ "(?:^|\\s)chmod\\b",
82
+ "(?:^|\\s)chown\\b",
83
+ ">>",
84
+ "(?:^|\\s)git\\s+add\\b",
85
+ "(?:^|\\s)git\\s+commit\\b",
86
+ "(?:^|\\s)git\\s+merge\\b",
87
+ "(?:^|\\s)git\\s+push\\b",
88
+ "(?:^|\\s)git\\s+reset\\b",
89
+ "(?:^|\\s)git\\s+checkout\\b",
90
+ "(?:^|\\s)git\\s+rebase\\b",
91
+ "(?:^|\\s)git\\s+stash\\b",
92
+ "(?:^|\\s)npm\\s+install\\b",
93
+ "(?:^|\\s)bun\\s+install\\b",
94
+ "(?:^|\\s)bun\\s+add\\b",
95
+ "(?:^|\\s)node\\s+(?:-e|--eval)\\b",
96
+ "(?:^|\\s)bun\\s+(?:-e|--eval)\\b",
97
+ "(?:^|\\s)python\\s+-c\\b",
98
+ "(?:^|\\s)perl\\s+-e\\b",
99
+ "(?:^|\\s)ruby\\s+-e\\b",
100
+ ];
@@ -0,0 +1,5 @@
1
+ export * from "./adapter";
2
+ export * from "./guard-rules";
3
+ export * from "./logger";
4
+ export * from "./runner";
5
+ export * from "./session-state";
@@ -0,0 +1,3 @@
1
+ export * from "./logger";
2
+ export * from "./runner";
3
+ export * from "./adapter";
@@ -0,0 +1,45 @@
1
+ export type LogLevel = "debug" | "info" | "warn" | "error";
2
+
3
+ export interface LoggerOptions {
4
+ namespace: string;
5
+ level?: LogLevel;
6
+ }
7
+
8
+ export class Logger {
9
+ private namespace: string;
10
+ private level: LogLevel;
11
+
12
+ constructor(options: LoggerOptions) {
13
+ this.namespace = options.namespace;
14
+ this.level = options.level || "info";
15
+ }
16
+
17
+ private shouldLog(level: LogLevel): boolean {
18
+ const levels: LogLevel[] = ["debug", "info", "warn", "error"];
19
+ return levels.indexOf(level) >= levels.indexOf(this.level);
20
+ }
21
+
22
+ debug(message: string, ...args: any[]) {
23
+ if (this.shouldLog("debug")) {
24
+ console.debug(`[${this.namespace}] DEBUG: ${message}`, ...args);
25
+ }
26
+ }
27
+
28
+ info(message: string, ...args: any[]) {
29
+ if (this.shouldLog("info")) {
30
+ console.info(`[${this.namespace}] INFO: ${message}`, ...args);
31
+ }
32
+ }
33
+
34
+ warn(message: string, ...args: any[]) {
35
+ if (this.shouldLog("warn")) {
36
+ console.warn(`[${this.namespace}] WARN: ${message}`, ...args);
37
+ }
38
+ }
39
+
40
+ error(message: string, ...args: any[]) {
41
+ if (this.shouldLog("error")) {
42
+ console.error(`[${this.namespace}] ERROR: ${message}`, ...args);
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,71 @@
1
+ import { execFile, spawnSync } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+
4
+ const execFileAsync = promisify(execFile);
5
+
6
+ export interface RunOptions {
7
+ timeoutMs?: number;
8
+ cwd?: string;
9
+ env?: Record<string, string>;
10
+ input?: string; // Standard input
11
+ }
12
+
13
+ export interface RunResult {
14
+ code: number;
15
+ stdout: string;
16
+ stderr: string;
17
+ }
18
+
19
+ export class SubprocessRunner {
20
+ /**
21
+ * Run a command deterministically with a timeout and optional stdin.
22
+ */
23
+ static async run(
24
+ command: string,
25
+ args: string[],
26
+ options: RunOptions = {}
27
+ ): Promise<RunResult> {
28
+ const timeout = options.timeoutMs ?? 10000;
29
+ const cwd = options.cwd ?? process.cwd();
30
+ const env = { ...process.env, ...options.env };
31
+
32
+ if (options.input !== undefined) {
33
+ // Use spawnSync for stdin support if input is provided
34
+ const result = spawnSync(command, args, {
35
+ cwd,
36
+ env,
37
+ input: options.input,
38
+ encoding: "utf8",
39
+ timeout,
40
+ maxBuffer: 1024 * 1024 * 10,
41
+ });
42
+
43
+ return {
44
+ code: result.status ?? 1,
45
+ stdout: (result.stdout ?? "").trim(),
46
+ stderr: (result.stderr ?? "").trim(),
47
+ };
48
+ }
49
+
50
+ try {
51
+ const result = await execFileAsync(command, args, {
52
+ timeout,
53
+ cwd,
54
+ env,
55
+ maxBuffer: 1024 * 1024 * 10,
56
+ });
57
+
58
+ return {
59
+ code: 0,
60
+ stdout: result.stdout.trim(),
61
+ stderr: result.stderr.trim(),
62
+ };
63
+ } catch (error: any) {
64
+ return {
65
+ code: error.code ?? 1,
66
+ stdout: (error.stdout ?? "").trim(),
67
+ stderr: (error.stderr ?? error.message ?? "").trim(),
68
+ };
69
+ }
70
+ }
71
+ }
@@ -0,0 +1,59 @@
1
+ import path from 'node:path';
2
+ import fs from 'node:fs';
3
+
4
+ export type SessionPhase =
5
+ | 'claimed'
6
+ | 'phase1-done'
7
+ | 'waiting-merge'
8
+ | 'conflicting'
9
+ | 'pending-cleanup'
10
+ | 'merged'
11
+ | 'cleanup-done';
12
+
13
+ export interface SessionState {
14
+ issueId: string;
15
+ branch: string;
16
+ worktreePath: string;
17
+ prNumber: number | null;
18
+ prUrl: string | null;
19
+ phase: SessionPhase;
20
+ conflictFiles: string[];
21
+ startedAt: string;
22
+ lastChecked: string;
23
+ }
24
+
25
+ const SESSION_STATE_FILE = '.xtrm-session-state.json';
26
+
27
+ export function findSessionStateFile(startCwd: string): string | null {
28
+ let current = path.resolve(startCwd || process.cwd());
29
+ for (;;) {
30
+ const candidate = path.join(current, SESSION_STATE_FILE);
31
+ if (fs.existsSync(candidate)) return candidate;
32
+ const parent = path.dirname(current);
33
+ if (parent === current) return null;
34
+ current = parent;
35
+ }
36
+ }
37
+
38
+ export function readSessionState(startCwd: string): SessionState | null {
39
+ const filePath = findSessionStateFile(startCwd);
40
+ if (!filePath) return null;
41
+ try {
42
+ const parsed = JSON.parse(fs.readFileSync(filePath, 'utf8'));
43
+ if (!parsed || typeof parsed !== 'object') return null;
44
+ if (!parsed.issueId || !parsed.branch || !parsed.worktreePath || !parsed.phase) return null;
45
+ return {
46
+ issueId: String(parsed.issueId),
47
+ branch: String(parsed.branch),
48
+ worktreePath: String(parsed.worktreePath),
49
+ prNumber: parsed.prNumber ?? null,
50
+ prUrl: parsed.prUrl ?? null,
51
+ phase: parsed.phase,
52
+ conflictFiles: Array.isArray(parsed.conflictFiles) ? parsed.conflictFiles.map(String) : [],
53
+ startedAt: String(parsed.startedAt || ''),
54
+ lastChecked: String(parsed.lastChecked || ''),
55
+ } as SessionState;
56
+ } catch {
57
+ return null;
58
+ }
59
+ }
@@ -0,0 +1,3 @@
1
+ import registerExtension from "../../extensions/auto-session-name/index.ts";
2
+
3
+ export default registerExtension;
@@ -0,0 +1,3 @@
1
+ import registerExtension from "../../extensions/auto-update/index.ts";
2
+
3
+ export default registerExtension;
@@ -0,0 +1,3 @@
1
+ import registerExtension from "../../extensions/beads/index.ts";
2
+
3
+ export default registerExtension;
@@ -0,0 +1,3 @@
1
+ import registerExtension from "../../extensions/compact-header/index.ts";
2
+
3
+ export default registerExtension;
@@ -0,0 +1,3 @@
1
+ import registerExtension from "../../extensions/custom-footer/index.ts";
2
+
3
+ export default registerExtension;
@@ -0,0 +1,3 @@
1
+ import registerExtension from "../../extensions/custom-provider-qwen-cli/index.ts";
2
+
3
+ export default registerExtension;
@@ -0,0 +1,3 @@
1
+ import registerExtension from "../../extensions/git-checkpoint/index.ts";
2
+
3
+ export default registerExtension;
@@ -0,0 +1,3 @@
1
+ import registerExtension from "../../extensions/lsp-bootstrap/index.ts";
2
+
3
+ export default registerExtension;
@@ -0,0 +1,3 @@
1
+ import registerExtension from "../../extensions/pi-serena-compact/index.ts";
2
+
3
+ export default registerExtension;
@@ -0,0 +1,3 @@
1
+ import registerExtension from "../../extensions/quality-gates/index.ts";
2
+
3
+ export default registerExtension;
@@ -0,0 +1,3 @@
1
+ import registerExtension from "../../extensions/service-skills/index.ts";
2
+
3
+ export default registerExtension;
@@ -0,0 +1,3 @@
1
+ import registerExtension from "../../extensions/session-flow/index.ts";
2
+
3
+ export default registerExtension;
@@ -0,0 +1,3 @@
1
+ import registerExtension from "../../extensions/xtrm-loader/index.ts";
2
+
3
+ export default registerExtension;
@@ -0,0 +1,3 @@
1
+ import registerExtension from "../../extensions/xtrm-ui/index.ts";
2
+
3
+ export default registerExtension;
package/src/index.ts ADDED
@@ -0,0 +1,9 @@
1
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
+
3
+ import { registerManagedPiExtensions } from "./registry.ts";
4
+
5
+ export { managedPiExtensions, registerManagedPiExtensions } from "./registry.ts";
6
+
7
+ export default function registerXtrmPiExtensions(pi: ExtensionAPI): void {
8
+ registerManagedPiExtensions(pi);
9
+ }
@@ -0,0 +1,52 @@
1
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
+
3
+ import autoSessionNameExtension from "./extensions/auto-session-name.ts";
4
+ import autoUpdateExtension from "./extensions/auto-update.ts";
5
+ import beadsExtension from "./extensions/beads.ts";
6
+ import compactHeaderExtension from "./extensions/compact-header.ts";
7
+ import customFooterExtension from "./extensions/custom-footer.ts";
8
+ import customProviderQwenCliExtension from "./extensions/custom-provider-qwen-cli.ts";
9
+ import gitCheckpointExtension from "./extensions/git-checkpoint.ts";
10
+ import lspBootstrapExtension from "./extensions/lsp-bootstrap.ts";
11
+ import piSerenaCompactExtension from "./extensions/pi-serena-compact.ts";
12
+ import qualityGatesExtension from "./extensions/quality-gates.ts";
13
+ import serviceSkillsExtension from "./extensions/service-skills.ts";
14
+ import sessionFlowExtension from "./extensions/session-flow.ts";
15
+ import xtrmLoaderExtension from "./extensions/xtrm-loader.ts";
16
+ import xtrmUiExtension from "./extensions/xtrm-ui.ts";
17
+
18
+ export type ManagedPiExtension = {
19
+ readonly id: string;
20
+ readonly register: (pi: ExtensionAPI) => void;
21
+ };
22
+
23
+ export const managedPiExtensions: readonly ManagedPiExtension[] = [
24
+ { id: "auto-session-name", register: autoSessionNameExtension },
25
+ { id: "auto-update", register: autoUpdateExtension },
26
+ { id: "beads", register: beadsExtension },
27
+ { id: "compact-header", register: compactHeaderExtension },
28
+ { id: "custom-footer", register: customFooterExtension },
29
+ { id: "custom-provider-qwen-cli", register: customProviderQwenCliExtension },
30
+ { id: "git-checkpoint", register: gitCheckpointExtension },
31
+ { id: "lsp-bootstrap", register: lspBootstrapExtension },
32
+ { id: "pi-serena-compact", register: piSerenaCompactExtension },
33
+ { id: "quality-gates", register: qualityGatesExtension },
34
+ { id: "service-skills", register: serviceSkillsExtension },
35
+ { id: "session-flow", register: sessionFlowExtension },
36
+ { id: "xtrm-loader", register: xtrmLoaderExtension },
37
+ { id: "xtrm-ui", register: xtrmUiExtension },
38
+ ];
39
+
40
+ function registerManagedExtension(pi: ExtensionAPI, extension: ManagedPiExtension): void {
41
+ try {
42
+ extension.register(pi);
43
+ } catch (error) {
44
+ console.warn(`[pi-extensions] Failed to register '${extension.id}':`, error);
45
+ }
46
+ }
47
+
48
+ export function registerManagedPiExtensions(pi: ExtensionAPI): void {
49
+ for (const extension of managedPiExtensions) {
50
+ registerManagedExtension(pi, extension);
51
+ }
52
+ }
@@ -0,0 +1 @@
1
+ export * from "./legacy-path-map";
@@ -0,0 +1,23 @@
1
+ export interface ExtensionPathMapping {
2
+ readonly extensionId: string;
3
+ readonly legacyPath: string;
4
+ readonly newPath: string;
5
+ }
6
+
7
+ export const LEGACY_PATH_MAPPINGS: readonly ExtensionPathMapping[] = [
8
+ { extensionId: "auto-session-name", legacyPath: ".xtrm/ext-src/auto-session-name", newPath: "packages/pi-extensions/extensions/auto-session-name" },
9
+ { extensionId: "auto-update", legacyPath: ".xtrm/ext-src/auto-update", newPath: "packages/pi-extensions/extensions/auto-update" },
10
+ { extensionId: "beads", legacyPath: ".xtrm/ext-src/beads", newPath: "packages/pi-extensions/extensions/beads" },
11
+ { extensionId: "compact-header", legacyPath: ".xtrm/ext-src/compact-header", newPath: "packages/pi-extensions/extensions/compact-header" },
12
+ { extensionId: "custom-footer", legacyPath: ".xtrm/ext-src/custom-footer", newPath: "packages/pi-extensions/extensions/custom-footer" },
13
+ { extensionId: "custom-provider-qwen-cli", legacyPath: ".xtrm/ext-src/custom-provider-qwen-cli", newPath: "packages/pi-extensions/extensions/custom-provider-qwen-cli" },
14
+ { extensionId: "git-checkpoint", legacyPath: ".xtrm/ext-src/git-checkpoint", newPath: "packages/pi-extensions/extensions/git-checkpoint" },
15
+ { extensionId: "lsp-bootstrap", legacyPath: ".xtrm/ext-src/lsp-bootstrap", newPath: "packages/pi-extensions/extensions/lsp-bootstrap" },
16
+ { extensionId: "pi-serena-compact", legacyPath: ".xtrm/ext-src/pi-serena-compact", newPath: "packages/pi-extensions/extensions/pi-serena-compact" },
17
+ { extensionId: "quality-gates", legacyPath: ".xtrm/ext-src/quality-gates", newPath: "packages/pi-extensions/extensions/quality-gates" },
18
+ { extensionId: "service-skills", legacyPath: ".xtrm/ext-src/service-skills", newPath: "packages/pi-extensions/extensions/service-skills" },
19
+ { extensionId: "session-flow", legacyPath: ".xtrm/ext-src/session-flow", newPath: "packages/pi-extensions/extensions/session-flow" },
20
+ { extensionId: "xtrm-loader", legacyPath: ".xtrm/ext-src/xtrm-loader", newPath: "packages/pi-extensions/extensions/xtrm-loader" },
21
+ { extensionId: "xtrm-ui", legacyPath: ".xtrm/ext-src/xtrm-ui", newPath: "packages/pi-extensions/extensions/xtrm-ui" },
22
+ { extensionId: "pi-core-internal", legacyPath: ".xtrm/ext-src/core", newPath: "packages/pi-extensions/src/core" },
23
+ ] as const;
@@ -0,0 +1,85 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/badlogic/pi-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
3
+ "name": "pidex-dark",
4
+ "vars": {
5
+ "accentBlue": "#b8d3ff",
6
+ "accentCyan": "#b8d3ff",
7
+ "accentTeal": "#c7d2e0",
8
+ "successGreen": "#9fd59f",
9
+ "errorRed": "#ff9a9a",
10
+ "warningAmber": "#d2b48c",
11
+ "surface": "#000000",
12
+ "surfaceAlt": "#111111",
13
+ "surfaceMuted": "#1a1a1a",
14
+ "surfaceUser": "#1f1f1f",
15
+ "surfaceCustom": "#161616",
16
+ "gray": "#a7a7a7",
17
+ "dimGray": "#8a8a8a",
18
+ "borderGray": "#666666",
19
+ "borderBright": "#9a9a9a"
20
+ },
21
+ "colors": {
22
+ "accent": "accentBlue",
23
+ "border": "borderGray",
24
+ "borderAccent": "borderBright",
25
+ "borderMuted": "borderGray",
26
+ "success": "successGreen",
27
+ "error": "errorRed",
28
+ "warning": "warningAmber",
29
+ "muted": "gray",
30
+ "dim": "dimGray",
31
+ "text": "",
32
+ "thinkingText": "gray",
33
+
34
+ "selectedBg": "surfaceMuted",
35
+ "userMessageBg": "surfaceUser",
36
+ "userMessageText": "",
37
+ "customMessageBg": "surfaceCustom",
38
+ "customMessageText": "",
39
+ "customMessageLabel": "accentBlue",
40
+ "toolPendingBg": "surfaceAlt",
41
+ "toolSuccessBg": "surfaceAlt",
42
+ "toolErrorBg": "surfaceAlt",
43
+ "toolTitle": "",
44
+ "toolOutput": "gray",
45
+
46
+ "mdHeading": "warningAmber",
47
+ "mdLink": "accentBlue",
48
+ "mdLinkUrl": "dimGray",
49
+ "mdCode": "accentCyan",
50
+ "mdCodeBlock": "gray",
51
+ "mdCodeBlockBorder": "borderGray",
52
+ "mdQuote": "gray",
53
+ "mdQuoteBorder": "borderGray",
54
+ "mdHr": "borderGray",
55
+ "mdListBullet": "accentTeal",
56
+
57
+ "toolDiffAdded": "successGreen",
58
+ "toolDiffRemoved": "errorRed",
59
+ "toolDiffContext": "gray",
60
+
61
+ "syntaxComment": "#6b7280",
62
+ "syntaxKeyword": "#7aa2f7",
63
+ "syntaxFunction": "#c0caf5",
64
+ "syntaxVariable": "#a9b1d6",
65
+ "syntaxString": "#9ece6a",
66
+ "syntaxNumber": "#ff9e64",
67
+ "syntaxType": "#73daca",
68
+ "syntaxOperator": "#c0caf5",
69
+ "syntaxPunctuation": "#8f9bb3",
70
+
71
+ "thinkingOff": "borderGray",
72
+ "thinkingMinimal": "#707070",
73
+ "thinkingLow": "#7a7a7a",
74
+ "thinkingMedium": "#858585",
75
+ "thinkingHigh": "#8f8f8f",
76
+ "thinkingXhigh": "#999999",
77
+
78
+ "bashMode": "accentTeal"
79
+ },
80
+ "export": {
81
+ "pageBg": "#12161d",
82
+ "cardBg": "#171b22",
83
+ "infoBg": "#28230f"
84
+ }
85
+ }