@cephalization/phoenix-insight 0.4.0 → 1.0.2

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 (76) hide show
  1. package/README.md +195 -1
  2. package/dist/chunk-KEQDYZIE.js +237 -0
  3. package/dist/chunk-KEQDYZIE.js.map +1 -0
  4. package/dist/cli.d.ts +1 -0
  5. package/dist/cli.js +3950 -642
  6. package/dist/cli.js.map +1 -0
  7. package/dist/index.d.ts +108 -0
  8. package/dist/index.js +13 -1
  9. package/dist/index.js.map +1 -0
  10. package/dist/ui/assets/code-block-F6WJLWQG-BTdTzfvl.js +154 -0
  11. package/dist/ui/assets/code-block-F6WJLWQG-BTdTzfvl.js.map +1 -0
  12. package/dist/ui/assets/index-CX8aDatf.css +1 -0
  13. package/dist/ui/assets/index-DjZuAW6Y.js +63 -0
  14. package/dist/ui/assets/index-DjZuAW6Y.js.map +1 -0
  15. package/dist/ui/assets/vendor-data-r1ZEkUds.js +40 -0
  16. package/dist/ui/assets/vendor-data-r1ZEkUds.js.map +1 -0
  17. package/dist/ui/assets/vendor-react-Cgg2GOmP.js +2 -0
  18. package/dist/ui/assets/vendor-react-Cgg2GOmP.js.map +1 -0
  19. package/dist/ui/assets/vendor-render-DoMl5bum.js +381 -0
  20. package/dist/ui/assets/vendor-render-DoMl5bum.js.map +1 -0
  21. package/dist/ui/assets/vendor-ui-Cg-YC4hK.js +46 -0
  22. package/dist/ui/assets/vendor-ui-Cg-YC4hK.js.map +1 -0
  23. package/dist/ui/index.html +18 -0
  24. package/dist/ui/vite.svg +1 -0
  25. package/package.json +14 -15
  26. package/dist/agent/index.js +0 -230
  27. package/dist/commands/index.js +0 -2
  28. package/dist/commands/px-fetch-more-spans.js +0 -98
  29. package/dist/commands/px-fetch-more-trace.js +0 -110
  30. package/dist/config/index.js +0 -165
  31. package/dist/config/loader.js +0 -141
  32. package/dist/config/schema.js +0 -53
  33. package/dist/modes/index.js +0 -17
  34. package/dist/modes/local.js +0 -134
  35. package/dist/modes/sandbox.js +0 -121
  36. package/dist/modes/types.js +0 -1
  37. package/dist/observability/index.js +0 -65
  38. package/dist/progress.js +0 -209
  39. package/dist/prompts/index.js +0 -1
  40. package/dist/prompts/system.js +0 -30
  41. package/dist/snapshot/client.js +0 -74
  42. package/dist/snapshot/context.js +0 -441
  43. package/dist/snapshot/datasets.js +0 -68
  44. package/dist/snapshot/experiments.js +0 -135
  45. package/dist/snapshot/index.js +0 -262
  46. package/dist/snapshot/projects.js +0 -44
  47. package/dist/snapshot/prompts.js +0 -199
  48. package/dist/snapshot/spans.js +0 -104
  49. package/dist/snapshot/utils.js +0 -112
  50. package/dist/tsconfig.esm.tsbuildinfo +0 -1
  51. package/src/agent/index.ts +0 -323
  52. package/src/cli.ts +0 -854
  53. package/src/commands/index.ts +0 -8
  54. package/src/commands/px-fetch-more-spans.ts +0 -174
  55. package/src/commands/px-fetch-more-trace.ts +0 -183
  56. package/src/config/index.ts +0 -225
  57. package/src/config/loader.ts +0 -173
  58. package/src/config/schema.ts +0 -66
  59. package/src/index.ts +0 -1
  60. package/src/modes/index.ts +0 -21
  61. package/src/modes/local.ts +0 -163
  62. package/src/modes/sandbox.ts +0 -144
  63. package/src/modes/types.ts +0 -31
  64. package/src/observability/index.ts +0 -90
  65. package/src/progress.ts +0 -239
  66. package/src/prompts/index.ts +0 -1
  67. package/src/prompts/system.ts +0 -31
  68. package/src/snapshot/client.ts +0 -129
  69. package/src/snapshot/context.ts +0 -587
  70. package/src/snapshot/datasets.ts +0 -132
  71. package/src/snapshot/experiments.ts +0 -246
  72. package/src/snapshot/index.ts +0 -403
  73. package/src/snapshot/projects.ts +0 -58
  74. package/src/snapshot/prompts.ts +0 -267
  75. package/src/snapshot/spans.ts +0 -163
  76. package/src/snapshot/utils.ts +0 -140
@@ -1,165 +0,0 @@
1
- /**
2
- * Config singleton module for Phoenix Insight CLI
3
- *
4
- * Provides centralized configuration management with priority-based merging:
5
- * 1. Config file (lowest priority)
6
- * 2. Environment variables
7
- * 3. CLI arguments (highest priority)
8
- */
9
- import { configSchema, getDefaultConfig } from "./schema.js";
10
- import { getConfigPath, loadConfigFile, validateConfig, createDefaultConfig, setCliConfigPath, } from "./loader.js";
11
- /**
12
- * Module-level storage for the initialized config singleton
13
- */
14
- let configInstance = null;
15
- /**
16
- * Environment variable mappings to config keys
17
- */
18
- const ENV_VAR_MAPPINGS = {
19
- PHOENIX_BASE_URL: "baseUrl",
20
- PHOENIX_API_KEY: "apiKey",
21
- PHOENIX_INSIGHT_LIMIT: "limit",
22
- PHOENIX_INSIGHT_STREAM: "stream",
23
- PHOENIX_INSIGHT_MODE: "mode",
24
- PHOENIX_INSIGHT_REFRESH: "refresh",
25
- PHOENIX_INSIGHT_TRACE: "trace",
26
- };
27
- /**
28
- * Parse environment variable value to appropriate type
29
- */
30
- function parseEnvValue(key, value) {
31
- switch (key) {
32
- case "baseUrl":
33
- case "apiKey":
34
- return value;
35
- case "limit":
36
- const num = parseInt(value, 10);
37
- return isNaN(num) ? undefined : num;
38
- case "stream":
39
- case "refresh":
40
- case "trace":
41
- return value.toLowerCase() === "true" || value === "1";
42
- case "mode":
43
- if (value === "sandbox" || value === "local") {
44
- return value;
45
- }
46
- return undefined;
47
- default:
48
- return value;
49
- }
50
- }
51
- /**
52
- * Get config values from environment variables
53
- */
54
- function getEnvConfig() {
55
- const envConfig = {};
56
- for (const [envVar, configKey] of Object.entries(ENV_VAR_MAPPINGS)) {
57
- const value = process.env[envVar];
58
- if (value !== undefined) {
59
- const parsed = parseEnvValue(configKey, value);
60
- if (parsed !== undefined) {
61
- envConfig[configKey] = parsed;
62
- }
63
- }
64
- }
65
- return envConfig;
66
- }
67
- /**
68
- * Convert CLI args to config format
69
- */
70
- function cliArgsToConfig(cliArgs) {
71
- const config = {};
72
- if (cliArgs.baseUrl !== undefined) {
73
- config.baseUrl = cliArgs.baseUrl;
74
- }
75
- if (cliArgs.apiKey !== undefined) {
76
- config.apiKey = cliArgs.apiKey;
77
- }
78
- if (cliArgs.limit !== undefined) {
79
- config.limit = cliArgs.limit;
80
- }
81
- if (cliArgs.stream !== undefined) {
82
- config.stream = cliArgs.stream;
83
- }
84
- if (cliArgs.local !== undefined) {
85
- // CLI uses --local flag, config uses mode
86
- config.mode = cliArgs.local ? "local" : "sandbox";
87
- }
88
- if (cliArgs.refresh !== undefined) {
89
- config.refresh = cliArgs.refresh;
90
- }
91
- if (cliArgs.trace !== undefined) {
92
- config.trace = cliArgs.trace;
93
- }
94
- return config;
95
- }
96
- /**
97
- * Initialize the configuration singleton
98
- *
99
- * Merges configuration from multiple sources with the following priority:
100
- * 1. Config file (lowest priority)
101
- * 2. Environment variables
102
- * 3. CLI arguments (highest priority)
103
- *
104
- * @param cliArgs - CLI arguments from Commander
105
- * @returns The initialized configuration
106
- */
107
- export async function initializeConfig(cliArgs = {}) {
108
- // Set CLI config path if provided (for getConfigPath to use)
109
- if (cliArgs.config) {
110
- setCliConfigPath(cliArgs.config);
111
- }
112
- // Get config file path
113
- const { path: configPath, isDefault } = getConfigPath();
114
- // Try to create default config if it doesn't exist (only for default path)
115
- if (isDefault) {
116
- await createDefaultConfig(configPath, isDefault);
117
- }
118
- // Load config file
119
- const fileConfig = await loadConfigFile(configPath);
120
- // Validate file config (returns defaults if null/invalid)
121
- const validatedFileConfig = validateConfig(fileConfig);
122
- // Get environment config
123
- const envConfig = getEnvConfig();
124
- // Get CLI config
125
- const cliConfig = cliArgsToConfig(cliArgs);
126
- // Merge configs: file < env < cli
127
- const mergedConfig = {
128
- ...validatedFileConfig,
129
- ...envConfig,
130
- ...cliConfig,
131
- };
132
- // Final validation with Zod
133
- const result = configSchema.safeParse(mergedConfig);
134
- if (result.success) {
135
- configInstance = result.data;
136
- }
137
- else {
138
- // Log validation issues as warnings
139
- result.error.issues.forEach((issue) => {
140
- console.warn(`Warning: Config validation error at '${issue.path.join(".")}': ${issue.message}`);
141
- });
142
- // Fall back to defaults
143
- configInstance = getDefaultConfig();
144
- }
145
- return configInstance;
146
- }
147
- /**
148
- * Get the initialized configuration
149
- *
150
- * @throws Error if config has not been initialized via initializeConfig()
151
- * @returns The configuration object
152
- */
153
- export function getConfig() {
154
- if (configInstance === null) {
155
- throw new Error("Config not initialized. Call initializeConfig() first before using getConfig().");
156
- }
157
- return configInstance;
158
- }
159
- /**
160
- * Reset the config singleton (useful for testing)
161
- */
162
- export function resetConfig() {
163
- configInstance = null;
164
- setCliConfigPath(undefined);
165
- }
@@ -1,141 +0,0 @@
1
- import * as fs from "node:fs/promises";
2
- import * as path from "node:path";
3
- import * as os from "node:os";
4
- import { configSchema, getDefaultConfig } from "./schema.js";
5
- /**
6
- * Default config directory and file path
7
- */
8
- const DEFAULT_CONFIG_DIR = path.join(os.homedir(), ".phoenix-insight");
9
- const DEFAULT_CONFIG_FILE = path.join(DEFAULT_CONFIG_DIR, "config.json");
10
- /**
11
- * Module-level storage for CLI args passed from commander
12
- * This is set externally before getConfigPath is called
13
- */
14
- let cliConfigPath;
15
- /**
16
- * Set the CLI config path (called from CLI parsing)
17
- */
18
- export function setCliConfigPath(configPath) {
19
- cliConfigPath = configPath;
20
- }
21
- /**
22
- * Get the config file path based on priority:
23
- * 1. CLI argument (--config)
24
- * 2. Environment variable (PHOENIX_INSIGHT_CONFIG)
25
- * 3. Default path (~/.phoenix-insight/config.json)
26
- *
27
- * @returns The path to the config file and whether it's the default path
28
- */
29
- export function getConfigPath() {
30
- // Priority 1: CLI argument
31
- if (cliConfigPath) {
32
- return { path: cliConfigPath, isDefault: false };
33
- }
34
- // Priority 2: Environment variable
35
- const envConfigPath = process.env.PHOENIX_INSIGHT_CONFIG;
36
- if (envConfigPath) {
37
- return { path: envConfigPath, isDefault: false };
38
- }
39
- // Priority 3: Default path
40
- return { path: DEFAULT_CONFIG_FILE, isDefault: true };
41
- }
42
- /**
43
- * Load and parse a config file from disk
44
- *
45
- * @param configPath - Path to the config file
46
- * @returns Parsed JSON object or null if file not found
47
- * @throws Error if file exists but cannot be parsed as JSON
48
- */
49
- export async function loadConfigFile(configPath) {
50
- try {
51
- const content = await fs.readFile(configPath, "utf-8");
52
- return JSON.parse(content);
53
- }
54
- catch (error) {
55
- // File not found is expected - return null
56
- if (error instanceof Error && "code" in error && error.code === "ENOENT") {
57
- return null;
58
- }
59
- // JSON parse errors should be reported
60
- if (error instanceof SyntaxError) {
61
- console.warn(`Warning: Config file at ${configPath} contains invalid JSON: ${error.message}`);
62
- return null;
63
- }
64
- // Other errors (permissions, etc.) - warn and return null
65
- console.warn(`Warning: Could not read config file at ${configPath}: ${error instanceof Error ? error.message : String(error)}`);
66
- return null;
67
- }
68
- }
69
- /**
70
- * Validate a raw config object against the schema
71
- * Returns validated config or defaults if validation fails
72
- *
73
- * @param raw - Raw config object (or null/undefined)
74
- * @returns Validated config with defaults applied
75
- */
76
- export function validateConfig(raw) {
77
- // If no raw config, return defaults
78
- if (!raw) {
79
- return getDefaultConfig();
80
- }
81
- try {
82
- // Parse with Zod schema - this applies defaults for missing fields
83
- return configSchema.parse(raw);
84
- }
85
- catch (error) {
86
- // Log validation errors as warnings
87
- if (error instanceof Error && "issues" in error) {
88
- // Zod error with issues array
89
- const zodError = error;
90
- zodError.issues.forEach((issue) => {
91
- console.warn(`Warning: Config validation error at '${issue.path.join(".")}': ${issue.message}`);
92
- });
93
- }
94
- else {
95
- console.warn(`Warning: Config validation failed: ${error instanceof Error ? error.message : String(error)}`);
96
- }
97
- // Return defaults on validation failure
98
- return getDefaultConfig();
99
- }
100
- }
101
- /**
102
- * Create a default config file at the given path
103
- * Only creates the file if it doesn't already exist
104
- * Only triggers for the default path, not custom paths
105
- *
106
- * @param configPath - Path where to create the config file
107
- * @param isDefault - Whether this is the default path (only create if true)
108
- * @returns true if file was created, false otherwise
109
- */
110
- export async function createDefaultConfig(configPath, isDefault) {
111
- // Only create default config for the default path
112
- if (!isDefault) {
113
- return false;
114
- }
115
- try {
116
- // Check if file already exists
117
- await fs.access(configPath);
118
- // File exists, don't overwrite
119
- return false;
120
- }
121
- catch {
122
- // File doesn't exist, create it
123
- }
124
- try {
125
- // Create directory if needed
126
- const configDir = path.dirname(configPath);
127
- await fs.mkdir(configDir, { recursive: true });
128
- // Get default config and write it
129
- const defaultConfig = getDefaultConfig();
130
- const content = JSON.stringify(defaultConfig, null, 2);
131
- await fs.writeFile(configPath, content, "utf-8");
132
- // Log informational message to stderr
133
- console.error(`Created default config at ${configPath}`);
134
- return true;
135
- }
136
- catch (error) {
137
- // Log warning but don't fail - config will use defaults
138
- console.warn(`Warning: Could not create default config at ${configPath}: ${error instanceof Error ? error.message : String(error)}`);
139
- return false;
140
- }
141
- }
@@ -1,53 +0,0 @@
1
- import { z } from "zod";
2
- /**
3
- * Zod schema for Phoenix Insight CLI configuration
4
- *
5
- * Configuration values can be set via:
6
- * 1. Config file (~/.phoenix-insight/config.json or custom path)
7
- * 2. Environment variables (PHOENIX_BASE_URL, PHOENIX_API_KEY, etc.)
8
- * 3. CLI arguments (--base-url, --api-key, etc.)
9
- *
10
- * Priority: config file < env vars < CLI args
11
- */
12
- export const configSchema = z.object({
13
- /**
14
- * Phoenix server base URL
15
- * @default "http://localhost:6006"
16
- */
17
- baseUrl: z.string().default("http://localhost:6006"),
18
- /**
19
- * Phoenix API key for authentication (optional)
20
- */
21
- apiKey: z.string().optional(),
22
- /**
23
- * Maximum number of spans to fetch per project
24
- * @default 1000
25
- */
26
- limit: z.number().int().positive().default(1000),
27
- /**
28
- * Enable streaming responses from the agent
29
- * @default true
30
- */
31
- stream: z.boolean().default(true),
32
- /**
33
- * Execution mode: "sandbox" for in-memory filesystem, "local" for real filesystem
34
- * @default "sandbox"
35
- */
36
- mode: z.enum(["sandbox", "local"]).default("sandbox"),
37
- /**
38
- * Force refresh of snapshot data
39
- * @default false
40
- */
41
- refresh: z.boolean().default(false),
42
- /**
43
- * Enable tracing of the agent to Phoenix
44
- * @default false
45
- */
46
- trace: z.boolean().default(false),
47
- });
48
- /**
49
- * Get default configuration values
50
- */
51
- export function getDefaultConfig() {
52
- return configSchema.parse({});
53
- }
@@ -1,17 +0,0 @@
1
- export * from "./types.js";
2
- export * from "./sandbox.js";
3
- export * from "./local.js";
4
- import { SandboxMode } from "./sandbox.js";
5
- import { LocalMode } from "./local.js";
6
- /**
7
- * Creates a new sandbox execution mode
8
- */
9
- export function createSandboxMode() {
10
- return new SandboxMode();
11
- }
12
- /**
13
- * Creates a new local execution mode
14
- */
15
- export async function createLocalMode() {
16
- return new LocalMode();
17
- }
@@ -1,134 +0,0 @@
1
- import { exec as execCallback } from "node:child_process";
2
- import { promisify } from "node:util";
3
- import * as fs from "node:fs/promises";
4
- import * as path from "node:path";
5
- import * as os from "node:os";
6
- import { tool } from "ai";
7
- import { z } from "zod";
8
- const execAsync = promisify(execCallback);
9
- /**
10
- * Local execution mode using real bash and persistent filesystem
11
- * - Real bash execution via child_process
12
- * - Persistent storage in ~/.phoenix-insight/
13
- * - Full system access
14
- */
15
- export class LocalMode {
16
- workDir;
17
- toolCreated = false;
18
- bashToolPromise = null;
19
- constructor() {
20
- // Create a timestamped directory for this snapshot
21
- // Add a small random component to ensure uniqueness even if created at the same millisecond
22
- const timestamp = Date.now().toString() + "-" + Math.random().toString(36).substring(7);
23
- this.workDir = path.join(os.homedir(), ".phoenix-insight", "snapshots", timestamp, "phoenix");
24
- }
25
- /**
26
- * Initialize the working directory
27
- */
28
- async init() {
29
- try {
30
- // Create the directory structure if it doesn't exist
31
- await fs.mkdir(this.workDir, { recursive: true });
32
- }
33
- catch (error) {
34
- throw new Error(`Failed to initialize local mode directory at ${this.workDir}: ${error instanceof Error ? error.message : String(error)}`);
35
- }
36
- }
37
- async writeFile(filePath, content) {
38
- await this.init();
39
- // Ensure the path is relative to phoenix root
40
- const cleanPath = filePath.startsWith("/phoenix")
41
- ? filePath.substring(8) // Remove /phoenix prefix
42
- : filePath.startsWith("/")
43
- ? filePath.substring(1) // Remove leading slash
44
- : filePath;
45
- const fullPath = path.join(this.workDir, cleanPath);
46
- // Create parent directories if they don't exist
47
- const dirname = path.dirname(fullPath);
48
- await fs.mkdir(dirname, { recursive: true });
49
- // Write the file
50
- await fs.writeFile(fullPath, content, "utf-8");
51
- }
52
- async exec(command) {
53
- await this.init();
54
- try {
55
- // Execute the command in the phoenix directory with a timeout
56
- const { stdout, stderr } = await execAsync(command, {
57
- cwd: this.workDir,
58
- shell: "/bin/bash",
59
- encoding: "utf-8",
60
- timeout: 60000, // 60 second timeout for bash commands
61
- });
62
- return {
63
- stdout: stdout || "",
64
- stderr: stderr || "",
65
- exitCode: 0,
66
- };
67
- }
68
- catch (error) {
69
- // Handle command execution errors
70
- if (error.code !== undefined) {
71
- return {
72
- stdout: error.stdout || "",
73
- stderr: error.stderr || error.message || "Command failed",
74
- exitCode: error.code || 1,
75
- };
76
- }
77
- // Handle other errors
78
- return {
79
- stdout: "",
80
- stderr: error.message || "Unknown error",
81
- exitCode: 1,
82
- };
83
- }
84
- }
85
- async getBashTool() {
86
- // Only create the tool once and cache it
87
- if (!this.bashToolPromise) {
88
- this.bashToolPromise = this.createBashTool();
89
- }
90
- return this.bashToolPromise;
91
- }
92
- async createBashTool() {
93
- // We can't use bash-tool directly for local mode since it's designed for just-bash
94
- // Instead, we'll create a tool using the AI SDK's tool function
95
- // This ensures compatibility with the AI SDK
96
- // Return a bash tool that executes real bash commands
97
- return tool({
98
- description: "Execute bash commands in the local filesystem",
99
- inputSchema: z.object({
100
- command: z.string().describe("The bash command to execute"),
101
- }),
102
- execute: async ({ command }) => {
103
- const result = await this.exec(command);
104
- // Return result in a format similar to bash-tool
105
- if (result.exitCode !== 0) {
106
- // Include error details in the response
107
- return {
108
- success: false,
109
- stdout: result.stdout,
110
- stderr: result.stderr,
111
- exitCode: result.exitCode,
112
- error: `Command failed with exit code ${result.exitCode}`,
113
- };
114
- }
115
- return {
116
- success: true,
117
- stdout: result.stdout,
118
- stderr: result.stderr,
119
- exitCode: result.exitCode,
120
- };
121
- },
122
- });
123
- }
124
- async cleanup() {
125
- // Optional: Clean up old snapshots
126
- // For now, we'll keep all snapshots for user reference
127
- // Users can manually clean ~/.phoenix-insight/ if needed
128
- // We could implement logic to:
129
- // 1. Keep only the last N snapshots
130
- // 2. Delete snapshots older than X days
131
- // 3. Provide a separate cleanup command
132
- // For this implementation, we do nothing
133
- }
134
- }
@@ -1,121 +0,0 @@
1
- import { tool } from "ai";
2
- import { z } from "zod";
3
- /**
4
- * Sandbox execution mode using just-bash for isolated execution
5
- * - In-memory filesystem
6
- * - Simulated bash commands
7
- * - No disk or network access
8
- */
9
- export class SandboxMode {
10
- bash; // Will be typed as Bash from just-bash
11
- initialized = false;
12
- bashToolPromise = null;
13
- constructor() {
14
- // We'll initialize in the init method since we need async imports
15
- }
16
- async init() {
17
- if (this.initialized)
18
- return;
19
- try {
20
- // Dynamic imports for ESM modules
21
- const { Bash } = await import("just-bash");
22
- // Initialize just-bash with /phoenix as the working directory
23
- this.bash = new Bash({ cwd: "/phoenix" });
24
- this.initialized = true;
25
- }
26
- catch (error) {
27
- throw new Error(`Failed to initialize sandbox mode: ${error instanceof Error ? error.message : String(error)}`);
28
- }
29
- }
30
- async writeFile(path, content) {
31
- await this.init();
32
- try {
33
- // Ensure the path starts with /phoenix
34
- const fullPath = path.startsWith("/phoenix")
35
- ? path
36
- : `/phoenix${path.startsWith("/") ? "" : "/"}${path}`;
37
- // Create parent directories if they don't exist
38
- const dirname = fullPath.substring(0, fullPath.lastIndexOf("/"));
39
- if (dirname) {
40
- await this.bash.exec(`mkdir -p ${dirname}`);
41
- }
42
- // Write the file using just-bash's filesystem
43
- // We'll use the InMemoryFs directly for better performance
44
- this.bash.fs.writeFileSync(fullPath, content);
45
- }
46
- catch (error) {
47
- throw new Error(`Failed to write file ${path}: ${error instanceof Error ? error.message : String(error)}`);
48
- }
49
- }
50
- async exec(command) {
51
- await this.init();
52
- try {
53
- const result = await this.bash.exec(command);
54
- // just-bash returns a different structure, so we need to normalize it
55
- return {
56
- stdout: result.stdout || "",
57
- stderr: result.stderr || "",
58
- exitCode: result.exitCode || 0,
59
- };
60
- }
61
- catch (error) {
62
- // If the command fails, just-bash throws an error
63
- // Extract what we can from the error
64
- if (error && typeof error === "object" && "exitCode" in error) {
65
- return {
66
- stdout: error.stdout || "",
67
- stderr: error.stderr || error.toString(),
68
- exitCode: error.exitCode || 1,
69
- };
70
- }
71
- // Fallback for unexpected errors
72
- return {
73
- stdout: "",
74
- stderr: error?.toString() || "Unknown error",
75
- exitCode: 1,
76
- };
77
- }
78
- }
79
- async getBashTool() {
80
- // Only create the tool once and cache it
81
- if (!this.bashToolPromise) {
82
- this.bashToolPromise = this.createBashTool();
83
- }
84
- return this.bashToolPromise;
85
- }
86
- async createBashTool() {
87
- await this.init();
88
- // Create a bash tool compatible with the AI SDK
89
- // Similar to local mode, we'll create it directly using the tool function
90
- return tool({
91
- description: "Execute bash commands in the sandbox filesystem",
92
- inputSchema: z.object({
93
- command: z.string().describe("The bash command to execute"),
94
- }),
95
- execute: async ({ command }) => {
96
- const result = await this.exec(command);
97
- // Return result in a format similar to bash-tool
98
- if (result.exitCode !== 0) {
99
- // Include error details in the response
100
- return {
101
- success: false,
102
- stdout: result.stdout,
103
- stderr: result.stderr,
104
- exitCode: result.exitCode,
105
- error: `Command failed with exit code ${result.exitCode}`,
106
- };
107
- }
108
- return {
109
- success: true,
110
- stdout: result.stdout,
111
- stderr: result.stderr,
112
- exitCode: result.exitCode,
113
- };
114
- },
115
- });
116
- }
117
- async cleanup() {
118
- // No-op for in-memory mode - garbage collection will handle cleanup
119
- // We could optionally clear the filesystem here if needed
120
- }
121
- }
@@ -1 +0,0 @@
1
- export {};