diffact 0.1.0 → 0.2.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.
Files changed (52) hide show
  1. package/dist/cli.mjs +2 -0
  2. package/dist/index-node-bKTmbwGt.mjs +1 -0
  3. package/dist/src-CPKE75x0.mjs +11 -0
  4. package/dist/src-Ceryd8j5.mjs +1 -0
  5. package/package.json +4 -5
  6. package/web/dist/assets/{code-block-37QAKDTI-C97XC0lL.js → code-block-37QAKDTI-yDNOZoY4.js} +1 -1
  7. package/web/dist/assets/{index-DWCfDth4.js → index-BlaXWu6U.js} +30 -30
  8. package/web/dist/assets/index-DMEToi1s.css +1 -0
  9. package/web/dist/index.html +2 -2
  10. package/dist/agent-manager.d.ts +0 -32
  11. package/dist/agent-manager.js +0 -502
  12. package/dist/app-server-client.d.ts +0 -38
  13. package/dist/app-server-client.js +0 -249
  14. package/dist/capabilities.d.ts +0 -2
  15. package/dist/capabilities.js +0 -27
  16. package/dist/cli.d.ts +0 -6
  17. package/dist/cli.js +0 -13
  18. package/dist/command-runner.d.ts +0 -83
  19. package/dist/command-runner.js +0 -427
  20. package/dist/editors.d.ts +0 -26
  21. package/dist/editors.js +0 -144
  22. package/dist/gh.d.ts +0 -61
  23. package/dist/gh.js +0 -185
  24. package/dist/git.d.ts +0 -57
  25. package/dist/git.js +0 -482
  26. package/dist/http.d.ts +0 -7
  27. package/dist/http.js +0 -98
  28. package/dist/index-node.d.ts +0 -5
  29. package/dist/index-node.js +0 -51
  30. package/dist/index.d.ts +0 -6
  31. package/dist/index.js +0 -1011
  32. package/dist/list-directories.d.ts +0 -8
  33. package/dist/list-directories.js +0 -32
  34. package/dist/log.d.ts +0 -2
  35. package/dist/log.js +0 -2
  36. package/dist/open-browser.d.ts +0 -5
  37. package/dist/open-browser.js +0 -23
  38. package/dist/project-commands.d.ts +0 -17
  39. package/dist/project-commands.js +0 -152
  40. package/dist/project-path.d.ts +0 -5
  41. package/dist/project-path.js +0 -33
  42. package/dist/runtime.d.ts +0 -65
  43. package/dist/runtime.js +0 -235
  44. package/dist/static.d.ts +0 -10
  45. package/dist/static.js +0 -127
  46. package/dist/types.d.ts +0 -17
  47. package/dist/types.js +0 -1
  48. package/dist/utils.d.ts +0 -3
  49. package/dist/utils.js +0 -26
  50. package/dist/ws-hub.d.ts +0 -20
  51. package/dist/ws-hub.js +0 -123
  52. package/web/dist/assets/index-CRDz04kv.css +0 -1
@@ -1,8 +0,0 @@
1
- export declare function listDirectories(inputPath?: string | null): Promise<{
2
- path: string;
3
- parent: string | null;
4
- entries: Array<{
5
- name: string;
6
- path: string;
7
- }>;
8
- }>;
@@ -1,32 +0,0 @@
1
- import fs from "node:fs/promises";
2
- import os from "node:os";
3
- import path from "node:path";
4
- export async function listDirectories(inputPath) {
5
- const resolved = inputPath ? path.resolve(inputPath) : os.homedir();
6
- let stat;
7
- try {
8
- stat = await fs.stat(resolved);
9
- }
10
- catch (error) {
11
- if (error && typeof error === "object" && "code" in error) {
12
- if (error.code === "ENOENT") {
13
- throw new Error("invalid_path");
14
- }
15
- }
16
- throw error;
17
- }
18
- if (!stat.isDirectory()) {
19
- throw new Error("invalid_path");
20
- }
21
- const dirents = await fs.readdir(resolved, { withFileTypes: true });
22
- const entries = dirents
23
- .filter((entry) => entry.isDirectory())
24
- .map((entry) => ({
25
- name: entry.name,
26
- path: path.join(resolved, entry.name),
27
- }))
28
- .sort((a, b) => a.name.localeCompare(b.name));
29
- const root = path.parse(resolved).root;
30
- const parent = resolved === root ? null : path.dirname(resolved);
31
- return { path: resolved, parent, entries };
32
- }
package/dist/log.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import pino from "pino";
2
- export declare const log: pino.Logger<never, boolean>;
package/dist/log.js DELETED
@@ -1,2 +0,0 @@
1
- import pino from "pino";
2
- export const log = pino({ level: process.env.LOG_LEVEL || "info" });
@@ -1,5 +0,0 @@
1
- /**
2
- * Cross-platform browser opener.
3
- * Works on macOS, Linux, and Windows.
4
- */
5
- export declare function openBrowser(url: string): void;
@@ -1,23 +0,0 @@
1
- /**
2
- * Cross-platform browser opener.
3
- * Works on macOS, Linux, and Windows.
4
- */
5
- import { runtime } from "./runtime.js";
6
- export function openBrowser(url) {
7
- const platform = process.platform;
8
- let cmd;
9
- switch (platform) {
10
- case "darwin":
11
- cmd = ["open", url];
12
- break;
13
- case "win32":
14
- cmd = ["cmd", "/c", "start", "", url];
15
- break;
16
- default:
17
- // Linux and others - try xdg-open
18
- cmd = ["xdg-open", url];
19
- break;
20
- }
21
- // Fire and forget - don't wait for browser to close
22
- runtime.spawn(cmd);
23
- }
@@ -1,17 +0,0 @@
1
- export type CommandSource = "package.json" | "makefile" | "custom";
2
- export type ProjectCommand = {
3
- id: string;
4
- name: string;
5
- label: string;
6
- source: CommandSource;
7
- detail?: string;
8
- };
9
- export type CommandExecutionPlan = {
10
- command: string;
11
- args: string[];
12
- cwd: string;
13
- env?: NodeJS.ProcessEnv;
14
- commandLine?: string;
15
- };
16
- export declare const listProjectCommands: (rootPath: string) => Promise<ProjectCommand[]>;
17
- export declare const resolveCommandPlan: (rootPath: string, source: CommandSource, name: string) => CommandExecutionPlan | null;
@@ -1,152 +0,0 @@
1
- import fs from "node:fs/promises";
2
- import path from "node:path";
3
- import { runtime } from "./runtime.js";
4
- const createCommandId = (source, name) => `${source}:${name}`;
5
- const readTextFile = async (filePath) => {
6
- try {
7
- return await fs.readFile(filePath, "utf8");
8
- }
9
- catch (error) {
10
- if (error && typeof error === "object" && "code" in error) {
11
- if (error.code === "ENOENT") {
12
- return null;
13
- }
14
- }
15
- throw error;
16
- }
17
- };
18
- const parseMakefileTargets = (contents) => {
19
- const targets = [];
20
- const seen = new Set();
21
- const lines = contents.split(/\r?\n/);
22
- for (const line of lines) {
23
- if (!line || line.startsWith("\t")) {
24
- continue;
25
- }
26
- const trimmed = line.trim();
27
- if (!trimmed || trimmed.startsWith("#")) {
28
- continue;
29
- }
30
- const match = /^([^:=]+)\s*:(?!\s*=)/.exec(trimmed);
31
- if (!match) {
32
- continue;
33
- }
34
- const names = match[1]?.trim().split(/\s+/) ?? [];
35
- for (const name of names) {
36
- if (!name || name.startsWith(".") || name.includes("%")) {
37
- continue;
38
- }
39
- if (seen.has(name)) {
40
- continue;
41
- }
42
- seen.add(name);
43
- targets.push(name);
44
- }
45
- }
46
- return targets;
47
- };
48
- const packageJsonProvider = {
49
- type: "package.json",
50
- listCommands: async (rootPath) => {
51
- const filePath = path.join(rootPath, "package.json");
52
- const contents = await readTextFile(filePath);
53
- if (!contents) {
54
- return [];
55
- }
56
- let parsed;
57
- try {
58
- parsed = JSON.parse(contents);
59
- }
60
- catch {
61
- return [];
62
- }
63
- if (!parsed || typeof parsed !== "object") {
64
- return [];
65
- }
66
- const scripts = parsed.scripts;
67
- if (!scripts || typeof scripts !== "object") {
68
- return [];
69
- }
70
- const commands = [];
71
- for (const [name, value] of Object.entries(scripts)) {
72
- const trimmedName = name.trim();
73
- if (!trimmedName || typeof value !== "string") {
74
- continue;
75
- }
76
- commands.push({
77
- id: createCommandId("package.json", trimmedName),
78
- name: trimmedName,
79
- label: trimmedName,
80
- source: "package.json",
81
- detail: value.trim(),
82
- });
83
- }
84
- return commands;
85
- },
86
- buildExecution: (rootPath, name) => {
87
- const bunPath = runtime.which("bun");
88
- if (!bunPath) {
89
- return null;
90
- }
91
- return {
92
- command: bunPath,
93
- args: ["run", name],
94
- cwd: rootPath,
95
- };
96
- },
97
- };
98
- const makefileProvider = {
99
- type: "makefile",
100
- listCommands: async (rootPath) => {
101
- const makefileNames = ["Makefile", "makefile", "GNUmakefile"];
102
- const commands = [];
103
- const seen = new Set();
104
- for (const name of makefileNames) {
105
- const filePath = path.join(rootPath, name);
106
- const contents = await readTextFile(filePath);
107
- if (!contents) {
108
- continue;
109
- }
110
- const targets = parseMakefileTargets(contents);
111
- for (const target of targets) {
112
- if (seen.has(target)) {
113
- continue;
114
- }
115
- seen.add(target);
116
- commands.push({
117
- id: createCommandId("makefile", target),
118
- name: target,
119
- label: target,
120
- source: "makefile",
121
- });
122
- }
123
- }
124
- return commands;
125
- },
126
- buildExecution: (rootPath, name) => {
127
- const makePath = runtime.which("make");
128
- if (!makePath) {
129
- return null;
130
- }
131
- return {
132
- command: makePath,
133
- args: [name],
134
- cwd: rootPath,
135
- };
136
- },
137
- };
138
- const COMMAND_PROVIDERS = [
139
- packageJsonProvider,
140
- makefileProvider,
141
- ];
142
- export const listProjectCommands = async (rootPath) => {
143
- const results = await Promise.all(COMMAND_PROVIDERS.map((provider) => provider.listCommands(rootPath)));
144
- return results.flat();
145
- };
146
- export const resolveCommandPlan = (rootPath, source, name) => {
147
- const provider = COMMAND_PROVIDERS.find((item) => item.type === source);
148
- if (!provider) {
149
- return null;
150
- }
151
- return provider.buildExecution(rootPath, name);
152
- };
@@ -1,5 +0,0 @@
1
- export type ProjectRoot = {
2
- rootPath: string;
3
- isGit: boolean;
4
- };
5
- export declare function resolveProjectRoot(projectPath: string): Promise<ProjectRoot>;
@@ -1,33 +0,0 @@
1
- import fs from "node:fs/promises";
2
- import path from "node:path";
3
- export async function resolveProjectRoot(projectPath) {
4
- const resolved = path.resolve(projectPath);
5
- let stat;
6
- try {
7
- stat = await fs.stat(resolved);
8
- }
9
- catch (error) {
10
- if (error && typeof error === "object" && "code" in error) {
11
- if (error.code === "ENOENT") {
12
- throw new Error("invalid_path");
13
- }
14
- }
15
- throw error;
16
- }
17
- if (!stat.isDirectory()) {
18
- throw new Error("not_a_directory");
19
- }
20
- const gitPath = path.join(resolved, ".git");
21
- const isGit = await fs
22
- .stat(gitPath)
23
- .then(() => true)
24
- .catch((error) => {
25
- if (error && typeof error === "object" && "code" in error) {
26
- if (error.code === "ENOENT") {
27
- return false;
28
- }
29
- }
30
- throw error;
31
- });
32
- return { rootPath: resolved, isGit };
33
- }
package/dist/runtime.d.ts DELETED
@@ -1,65 +0,0 @@
1
- /**
2
- * Runtime abstraction layer for Bun/Node.js compatibility.
3
- * Wraps Bun-specific APIs with cross-runtime implementations.
4
- *
5
- * Usage:
6
- * import { runtime } from "./runtime.js";
7
- * runtime.which("gh");
8
- * runtime.spawn(["ls", "-la"]);
9
- * runtime.file("/path/to/file");
10
- * runtime.createTerminal({ cols: 80, rows: 24, data: ... });
11
- */
12
- export type RuntimeFile = {
13
- stream(): ReadableStream<Uint8Array>;
14
- size: number;
15
- type: string;
16
- };
17
- export type TerminalOptions = {
18
- cols: number;
19
- rows: number;
20
- data: (terminal: RuntimeTerminal, data: Uint8Array) => void;
21
- };
22
- export interface RuntimeTerminal {
23
- resize(cols: number, rows: number): void;
24
- write(data: string | Uint8Array): void;
25
- }
26
- export type SpawnOptions = {
27
- cwd?: string;
28
- env?: Record<string, string | undefined>;
29
- terminal?: RuntimeTerminal;
30
- onExit?: (subprocess: unknown, exitCode: number | null, signalCode: string | null, error?: Error) => void;
31
- };
32
- export type SpawnedProcess = {
33
- exited: Promise<number>;
34
- exitCode: number | null;
35
- signalCode: NodeJS.Signals | null;
36
- stdout: ReadableStream<Uint8Array> | null | undefined;
37
- stderr: ReadableStream<Uint8Array> | null | undefined;
38
- kill: (signal?: number | NodeJS.Signals) => void;
39
- };
40
- export declare const runtime: {
41
- /** Runtime name: "bun" or "node" */
42
- readonly name: "bun" | "node";
43
- /** Runtime version */
44
- readonly version: string;
45
- /** True if running on Bun */
46
- readonly isBun: boolean;
47
- /** True if running on Node.js */
48
- readonly isNode: boolean;
49
- /**
50
- * Find executable path (like `which` command)
51
- */
52
- readonly which: (command: string) => string | null;
53
- /**
54
- * Create file handle for streaming responses
55
- */
56
- readonly file: (filePath: string) => RuntimeFile;
57
- /**
58
- * Create PTY terminal
59
- */
60
- readonly createTerminal: (options: TerminalOptions) => RuntimeTerminal;
61
- /**
62
- * Spawn a process with optional terminal support
63
- */
64
- readonly spawn: (cmd: string[], options?: SpawnOptions) => SpawnedProcess;
65
- };
package/dist/runtime.js DELETED
@@ -1,235 +0,0 @@
1
- /**
2
- * Runtime abstraction layer for Bun/Node.js compatibility.
3
- * Wraps Bun-specific APIs with cross-runtime implementations.
4
- *
5
- * Usage:
6
- * import { runtime } from "./runtime.js";
7
- * runtime.which("gh");
8
- * runtime.spawn(["ls", "-la"]);
9
- * runtime.file("/path/to/file");
10
- * runtime.createTerminal({ cols: 80, rows: 24, data: ... });
11
- */
12
- import { execSync, spawn as nodeSpawn, } from "node:child_process";
13
- import fs from "node:fs";
14
- import path from "node:path";
15
- // -----------------------------------------------------------------------------
16
- // Runtime detection
17
- // -----------------------------------------------------------------------------
18
- const isBun = typeof globalThis.Bun !== "undefined";
19
- const isNode = !isBun;
20
- let nodePty = null;
21
- function getNodePty() {
22
- if (!nodePty) {
23
- try {
24
- nodePty = require("node-pty");
25
- }
26
- catch {
27
- throw new Error("node-pty is required for terminal support in Node.js. Install it with: npm install node-pty");
28
- }
29
- }
30
- return nodePty;
31
- }
32
- // -----------------------------------------------------------------------------
33
- // Node Terminal implementation
34
- // -----------------------------------------------------------------------------
35
- class NodeTerminal {
36
- pty = null;
37
- cols;
38
- rows;
39
- dataCallback;
40
- encoder = new TextEncoder();
41
- constructor(options) {
42
- this.cols = options.cols;
43
- this.rows = options.rows;
44
- this.dataCallback = options.data;
45
- }
46
- ensurePty() {
47
- if (this.pty)
48
- return this.pty;
49
- const pty = getNodePty();
50
- const shell = process.env.SHELL || "/bin/sh";
51
- this.pty = pty.spawn(shell, [], {
52
- name: "xterm-256color",
53
- cols: this.cols,
54
- rows: this.rows,
55
- cwd: process.cwd(),
56
- env: process.env,
57
- });
58
- this.pty.onData((data) => {
59
- this.dataCallback(this, this.encoder.encode(data));
60
- });
61
- return this.pty;
62
- }
63
- resize(cols, rows) {
64
- this.cols = cols;
65
- this.rows = rows;
66
- this.pty?.resize(cols, rows);
67
- }
68
- write(data) {
69
- const pty = this.ensurePty();
70
- if (typeof data === "string") {
71
- pty.write(data);
72
- }
73
- else {
74
- pty.write(new TextDecoder().decode(data));
75
- }
76
- }
77
- }
78
- // -----------------------------------------------------------------------------
79
- // Runtime object - unified API
80
- // -----------------------------------------------------------------------------
81
- export const runtime = {
82
- /** Runtime name: "bun" or "node" */
83
- name: isBun ? "bun" : "node",
84
- /** Runtime version */
85
- version: isBun ? Bun.version : process.version,
86
- /** True if running on Bun */
87
- isBun,
88
- /** True if running on Node.js */
89
- isNode,
90
- /**
91
- * Find executable path (like `which` command)
92
- */
93
- which(command) {
94
- if (isBun) {
95
- return Bun.which(command);
96
- }
97
- try {
98
- const result = execSync(`which ${command}`, {
99
- encoding: "utf8",
100
- stdio: ["pipe", "pipe", "ignore"],
101
- });
102
- return result.trim() || null;
103
- }
104
- catch {
105
- return null;
106
- }
107
- },
108
- /**
109
- * Create file handle for streaming responses
110
- */
111
- file(filePath) {
112
- if (isBun) {
113
- return Bun.file(filePath);
114
- }
115
- const stat = fs.statSync(filePath);
116
- const ext = path.extname(filePath).toLowerCase();
117
- const mimeTypes = {
118
- ".html": "text/html",
119
- ".css": "text/css",
120
- ".js": "application/javascript",
121
- ".json": "application/json",
122
- ".png": "image/png",
123
- ".jpg": "image/jpeg",
124
- ".jpeg": "image/jpeg",
125
- ".gif": "image/gif",
126
- ".svg": "image/svg+xml",
127
- ".txt": "text/plain",
128
- };
129
- return {
130
- stream() {
131
- const nodeStream = fs.createReadStream(filePath);
132
- return new ReadableStream({
133
- start(controller) {
134
- nodeStream.on("data", (chunk) => {
135
- controller.enqueue(new Uint8Array(chunk));
136
- });
137
- nodeStream.on("end", () => {
138
- controller.close();
139
- });
140
- nodeStream.on("error", (err) => {
141
- controller.error(err);
142
- });
143
- },
144
- cancel() {
145
- nodeStream.destroy();
146
- },
147
- });
148
- },
149
- size: stat.size,
150
- type: mimeTypes[ext] || "application/octet-stream",
151
- };
152
- },
153
- /**
154
- * Create PTY terminal
155
- */
156
- createTerminal(options) {
157
- if (isBun) {
158
- return new Bun.Terminal({
159
- cols: options.cols,
160
- rows: options.rows,
161
- data: options.data,
162
- });
163
- }
164
- return new NodeTerminal(options);
165
- },
166
- /**
167
- * Spawn a process with optional terminal support
168
- */
169
- spawn(cmd, options = {}) {
170
- if (isBun) {
171
- const bunOnExit = options.onExit
172
- ? (subprocess, exitCode, signalCode, error) => {
173
- options.onExit?.(subprocess, exitCode, signalCode !== null ? String(signalCode) : null, error);
174
- }
175
- : undefined;
176
- const bunOptions = {
177
- cwd: options.cwd,
178
- env: options.env,
179
- onExit: bunOnExit,
180
- };
181
- if (options.terminal) {
182
- bunOptions.terminal = options.terminal;
183
- }
184
- return Bun.spawn(cmd, bunOptions);
185
- }
186
- const command = cmd[0];
187
- if (!command) {
188
- throw new Error("Command array must not be empty");
189
- }
190
- const child = nodeSpawn(command, cmd.slice(1), {
191
- cwd: options.cwd,
192
- env: options.env,
193
- stdio: ["pipe", "pipe", "pipe"],
194
- });
195
- let exitCode = null;
196
- let signalCode = null;
197
- const exited = new Promise((resolve) => {
198
- child.on("exit", (code, signal) => {
199
- exitCode = code;
200
- signalCode = signal;
201
- options.onExit?.(child, code, signal, undefined);
202
- resolve(code ?? 1);
203
- });
204
- child.on("error", (error) => {
205
- options.onExit?.(child, null, null, error);
206
- resolve(1);
207
- });
208
- });
209
- const toReadableStream = (nodeStream) => {
210
- if (!nodeStream)
211
- return null;
212
- return new ReadableStream({
213
- start(controller) {
214
- nodeStream.on("data", (chunk) => {
215
- controller.enqueue(new Uint8Array(chunk));
216
- });
217
- nodeStream.on("end", () => controller.close());
218
- nodeStream.on("error", (err) => controller.error(err));
219
- },
220
- });
221
- };
222
- return {
223
- exited,
224
- get exitCode() {
225
- return exitCode;
226
- },
227
- get signalCode() {
228
- return signalCode;
229
- },
230
- stdout: toReadableStream(child.stdout),
231
- stderr: toReadableStream(child.stderr),
232
- kill: (signal) => child.kill(signal),
233
- };
234
- },
235
- };
package/dist/static.d.ts DELETED
@@ -1,10 +0,0 @@
1
- /**
2
- * Static file serving for bundled frontend assets.
3
- * Resolves web/dist relative to the package root or source location.
4
- */
5
- export declare function isStaticEnabled(): boolean;
6
- export declare function getStaticDir(): string | null;
7
- /**
8
- * Serve a static file. Returns null if file not found or static serving disabled.
9
- */
10
- export declare function serveStatic(reqPath: string): Promise<Response | null>;