@axiom-lattice/core 2.1.73 → 2.1.74
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/dist/index.d.mts +31 -6
- package/dist/index.d.ts +31 -6
- package/dist/index.js +352 -30
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +350 -30
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -79,6 +79,7 @@ __export(index_exports, {
|
|
|
79
79
|
MicrosandboxRemoteProvider: () => MicrosandboxRemoteProvider,
|
|
80
80
|
MicrosandboxServiceClient: () => MicrosandboxServiceClient,
|
|
81
81
|
ModelLatticeManager: () => ModelLatticeManager,
|
|
82
|
+
MysqlDatabase: () => MysqlDatabase,
|
|
82
83
|
PinoLoggerClient: () => PinoLoggerClient,
|
|
83
84
|
PostgresDatabase: () => PostgresDatabase,
|
|
84
85
|
PrometheusClient: () => PrometheusClient,
|
|
@@ -143,6 +144,7 @@ __export(index_exports, {
|
|
|
143
144
|
ensureBuiltinAgentsForTenant: () => ensureBuiltinAgentsForTenant,
|
|
144
145
|
eventBus: () => eventBus,
|
|
145
146
|
eventBusDefault: () => event_bus_default,
|
|
147
|
+
extractFetcherError: () => extractFetcherError,
|
|
146
148
|
fileDataToString: () => fileDataToString,
|
|
147
149
|
formatContentWithLineNumbers: () => formatContentWithLineNumbers,
|
|
148
150
|
formatGrepMatches: () => formatGrepMatches,
|
|
@@ -3284,6 +3286,168 @@ var PostgresDatabase = class {
|
|
|
3284
3286
|
}
|
|
3285
3287
|
}
|
|
3286
3288
|
};
|
|
3289
|
+
var MysqlDatabase = class {
|
|
3290
|
+
constructor(config) {
|
|
3291
|
+
// mysql2.Pool
|
|
3292
|
+
this.connected = false;
|
|
3293
|
+
this.config = config;
|
|
3294
|
+
}
|
|
3295
|
+
async connect() {
|
|
3296
|
+
if (this.connected && this.pool) return;
|
|
3297
|
+
try {
|
|
3298
|
+
const mysql = await import("mysql2/promise");
|
|
3299
|
+
const poolConfig = this.config.connectionString ? { uri: this.config.connectionString } : {
|
|
3300
|
+
host: this.config.host || "localhost",
|
|
3301
|
+
port: this.config.port || 3306,
|
|
3302
|
+
database: this.config.database,
|
|
3303
|
+
user: this.config.user,
|
|
3304
|
+
password: this.config.password,
|
|
3305
|
+
ssl: this.config.ssl ? { rejectUnauthorized: false } : void 0
|
|
3306
|
+
};
|
|
3307
|
+
this.pool = mysql.createPool({
|
|
3308
|
+
...poolConfig,
|
|
3309
|
+
waitForConnections: true,
|
|
3310
|
+
connectionLimit: 10,
|
|
3311
|
+
maxIdle: 10,
|
|
3312
|
+
idleTimeout: 6e4,
|
|
3313
|
+
queueLimit: 0,
|
|
3314
|
+
enableKeepAlive: true,
|
|
3315
|
+
keepAliveInitialDelay: 0
|
|
3316
|
+
});
|
|
3317
|
+
const connection = await this.pool.getConnection();
|
|
3318
|
+
try {
|
|
3319
|
+
await connection.query("SELECT 1");
|
|
3320
|
+
} finally {
|
|
3321
|
+
connection.release();
|
|
3322
|
+
}
|
|
3323
|
+
this.connected = true;
|
|
3324
|
+
} catch (error) {
|
|
3325
|
+
this.connected = false;
|
|
3326
|
+
throw new Error(`Failed to connect to MySQL: ${error}`);
|
|
3327
|
+
}
|
|
3328
|
+
}
|
|
3329
|
+
async disconnect() {
|
|
3330
|
+
if (this.pool) {
|
|
3331
|
+
try {
|
|
3332
|
+
await this.pool.end();
|
|
3333
|
+
} catch (error) {
|
|
3334
|
+
console.warn("Warning: Error closing MySQL pool:", error);
|
|
3335
|
+
} finally {
|
|
3336
|
+
this.pool = null;
|
|
3337
|
+
this.connected = false;
|
|
3338
|
+
}
|
|
3339
|
+
}
|
|
3340
|
+
}
|
|
3341
|
+
async listTables() {
|
|
3342
|
+
await this.ensureConnected();
|
|
3343
|
+
const query = `
|
|
3344
|
+
SELECT TABLE_NAME, TABLE_SCHEMA
|
|
3345
|
+
FROM information_schema.TABLES
|
|
3346
|
+
WHERE TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
|
|
3347
|
+
AND TABLE_SCHEMA = DATABASE()
|
|
3348
|
+
AND TABLE_TYPE = 'BASE TABLE'
|
|
3349
|
+
ORDER BY TABLE_SCHEMA, TABLE_NAME
|
|
3350
|
+
`;
|
|
3351
|
+
const [rows] = await this.pool.query(query);
|
|
3352
|
+
return rows.map((row) => ({
|
|
3353
|
+
name: row.TABLE_NAME,
|
|
3354
|
+
schema: row.TABLE_SCHEMA
|
|
3355
|
+
}));
|
|
3356
|
+
}
|
|
3357
|
+
async getTableInfo(tables) {
|
|
3358
|
+
await this.ensureConnected();
|
|
3359
|
+
const schemas = [];
|
|
3360
|
+
for (const tableName of tables) {
|
|
3361
|
+
const rawName = tableName.includes(".") ? tableName.split(".").pop() : tableName;
|
|
3362
|
+
const columnQuery = `
|
|
3363
|
+
SELECT
|
|
3364
|
+
c.COLUMN_NAME,
|
|
3365
|
+
c.DATA_TYPE,
|
|
3366
|
+
c.IS_NULLABLE,
|
|
3367
|
+
c.COLUMN_DEFAULT
|
|
3368
|
+
FROM information_schema.COLUMNS c
|
|
3369
|
+
WHERE c.TABLE_NAME = ?
|
|
3370
|
+
AND c.TABLE_SCHEMA = DATABASE()
|
|
3371
|
+
ORDER BY c.ORDINAL_POSITION
|
|
3372
|
+
`;
|
|
3373
|
+
const pkQuery = `
|
|
3374
|
+
SELECT k.COLUMN_NAME
|
|
3375
|
+
FROM information_schema.TABLE_CONSTRAINTS t
|
|
3376
|
+
JOIN information_schema.KEY_COLUMN_USAGE k
|
|
3377
|
+
ON t.CONSTRAINT_NAME = k.CONSTRAINT_NAME
|
|
3378
|
+
AND t.TABLE_SCHEMA = k.TABLE_SCHEMA
|
|
3379
|
+
AND t.TABLE_NAME = k.TABLE_NAME
|
|
3380
|
+
WHERE t.CONSTRAINT_TYPE = 'PRIMARY KEY'
|
|
3381
|
+
AND t.TABLE_NAME = ?
|
|
3382
|
+
AND t.TABLE_SCHEMA = DATABASE()
|
|
3383
|
+
`;
|
|
3384
|
+
const fkQuery = `
|
|
3385
|
+
SELECT
|
|
3386
|
+
k.COLUMN_NAME,
|
|
3387
|
+
k.REFERENCED_TABLE_NAME,
|
|
3388
|
+
k.REFERENCED_COLUMN_NAME
|
|
3389
|
+
FROM information_schema.KEY_COLUMN_USAGE k
|
|
3390
|
+
WHERE k.TABLE_NAME = ?
|
|
3391
|
+
AND k.TABLE_SCHEMA = DATABASE()
|
|
3392
|
+
AND k.REFERENCED_TABLE_NAME IS NOT NULL
|
|
3393
|
+
`;
|
|
3394
|
+
const [columnRows] = await this.pool.query(columnQuery, [rawName]);
|
|
3395
|
+
const [pkRows] = await this.pool.query(pkQuery, [rawName]);
|
|
3396
|
+
const [fkRows] = await this.pool.query(fkQuery, [rawName]);
|
|
3397
|
+
const pkColumns = new Set(pkRows.map((r) => r.COLUMN_NAME));
|
|
3398
|
+
const fkMap = /* @__PURE__ */ new Map();
|
|
3399
|
+
for (const row of fkRows) {
|
|
3400
|
+
fkMap.set(row.COLUMN_NAME, {
|
|
3401
|
+
foreignTable: row.REFERENCED_TABLE_NAME,
|
|
3402
|
+
foreignColumn: row.REFERENCED_COLUMN_NAME
|
|
3403
|
+
});
|
|
3404
|
+
}
|
|
3405
|
+
const columns = columnRows.map((row) => {
|
|
3406
|
+
const fkRef = fkMap.get(row.COLUMN_NAME);
|
|
3407
|
+
return {
|
|
3408
|
+
name: row.COLUMN_NAME,
|
|
3409
|
+
type: row.DATA_TYPE,
|
|
3410
|
+
nullable: row.IS_NULLABLE === "YES",
|
|
3411
|
+
default: row.COLUMN_DEFAULT,
|
|
3412
|
+
isPrimaryKey: pkColumns.has(row.COLUMN_NAME),
|
|
3413
|
+
isForeignKey: fkRef !== void 0,
|
|
3414
|
+
foreignKeyRef: fkRef ? `${fkRef.foreignTable}.${fkRef.foreignColumn}` : void 0
|
|
3415
|
+
};
|
|
3416
|
+
});
|
|
3417
|
+
let sampleRows = [];
|
|
3418
|
+
try {
|
|
3419
|
+
const sampleQuery = `SELECT * FROM \`${rawName}\` LIMIT 3`;
|
|
3420
|
+
const [sampleResult] = await this.pool.query(sampleQuery);
|
|
3421
|
+
sampleRows = sampleResult;
|
|
3422
|
+
} catch {
|
|
3423
|
+
}
|
|
3424
|
+
schemas.push({
|
|
3425
|
+
tableName,
|
|
3426
|
+
columns,
|
|
3427
|
+
sampleRows
|
|
3428
|
+
});
|
|
3429
|
+
}
|
|
3430
|
+
return schemas;
|
|
3431
|
+
}
|
|
3432
|
+
async executeQuery(query) {
|
|
3433
|
+
await this.ensureConnected();
|
|
3434
|
+
const [rows, fields] = await this.pool.query(query);
|
|
3435
|
+
const isSelectResult = Array.isArray(rows);
|
|
3436
|
+
return {
|
|
3437
|
+
rows: isSelectResult ? rows : [],
|
|
3438
|
+
rowCount: isSelectResult ? rows.length : rows.affectedRows || 0,
|
|
3439
|
+
fields: fields?.map((f) => f.name)
|
|
3440
|
+
};
|
|
3441
|
+
}
|
|
3442
|
+
getDatabaseType() {
|
|
3443
|
+
return "mysql";
|
|
3444
|
+
}
|
|
3445
|
+
async ensureConnected() {
|
|
3446
|
+
if (!this.connected) {
|
|
3447
|
+
await this.connect();
|
|
3448
|
+
}
|
|
3449
|
+
}
|
|
3450
|
+
};
|
|
3287
3451
|
var SqlDatabaseManager = class _SqlDatabaseManager {
|
|
3288
3452
|
constructor() {
|
|
3289
3453
|
this.databases = /* @__PURE__ */ new Map();
|
|
@@ -3323,7 +3487,8 @@ var SqlDatabaseManager = class _SqlDatabaseManager {
|
|
|
3323
3487
|
database = new PostgresDatabase(config);
|
|
3324
3488
|
break;
|
|
3325
3489
|
case "mysql":
|
|
3326
|
-
|
|
3490
|
+
database = new MysqlDatabase(config);
|
|
3491
|
+
break;
|
|
3327
3492
|
case "sqlite":
|
|
3328
3493
|
throw new Error("SQLite support not yet implemented");
|
|
3329
3494
|
default:
|
|
@@ -5858,7 +6023,7 @@ var SandboxLatticeManager = class _SandboxLatticeManager extends BaseLatticeMana
|
|
|
5858
6023
|
const tenantId = config.tenantId ?? "default";
|
|
5859
6024
|
const mapping = this._resolveVolumeForPath(config, tenantId, filePath);
|
|
5860
6025
|
if (!mapping) return null;
|
|
5861
|
-
const client = provider.createVolumeFsClient(mapping.volumeName);
|
|
6026
|
+
const client = provider.createVolumeFsClient(mapping.volumeName, mapping.pathPrefix);
|
|
5862
6027
|
return new VolumeFilesystem(stripPrefixClient(client, mapping.pathPrefix), mapping.pathPrefix);
|
|
5863
6028
|
}
|
|
5864
6029
|
_resolveVolumeForPath(config, tenantId, filePath) {
|
|
@@ -21471,7 +21636,7 @@ var MicrosandboxRemoteProvider = class {
|
|
|
21471
21636
|
this.instances.delete(name);
|
|
21472
21637
|
await this.client.deleteSandbox(name);
|
|
21473
21638
|
}
|
|
21474
|
-
createVolumeFsClient(volumeName) {
|
|
21639
|
+
createVolumeFsClient(volumeName, _pathPrefix) {
|
|
21475
21640
|
return {
|
|
21476
21641
|
read: (path3) => this.client.volumeFsRead(volumeName, path3),
|
|
21477
21642
|
write: (path3, content) => this.client.volumeFsWrite(volumeName, path3, content),
|
|
@@ -21528,50 +21693,84 @@ var MicrosandboxRemoteProvider = class {
|
|
|
21528
21693
|
var import_sandbox23 = require("@agent-infra/sandbox");
|
|
21529
21694
|
|
|
21530
21695
|
// src/sandbox_lattice/RemoteSandboxInstance.ts
|
|
21696
|
+
function extractFetcherError(error) {
|
|
21697
|
+
if (typeof error === "string") {
|
|
21698
|
+
return error;
|
|
21699
|
+
}
|
|
21700
|
+
if (error && typeof error === "object") {
|
|
21701
|
+
const e = error;
|
|
21702
|
+
if (typeof e.reason === "string") {
|
|
21703
|
+
switch (e.reason) {
|
|
21704
|
+
case "status-code":
|
|
21705
|
+
return `HTTP ${e.statusCode}: ${JSON.stringify(e.body)}`;
|
|
21706
|
+
case "non-json":
|
|
21707
|
+
return `HTTP ${e.statusCode}: ${e.rawBody}`;
|
|
21708
|
+
case "timeout":
|
|
21709
|
+
return "Request timed out";
|
|
21710
|
+
case "unknown":
|
|
21711
|
+
return typeof e.errorMessage === "string" ? e.errorMessage : "Unknown error";
|
|
21712
|
+
}
|
|
21713
|
+
}
|
|
21714
|
+
if (typeof e.message === "string") {
|
|
21715
|
+
return e.message;
|
|
21716
|
+
}
|
|
21717
|
+
if (typeof e.error === "string") {
|
|
21718
|
+
return e.error;
|
|
21719
|
+
}
|
|
21720
|
+
return JSON.stringify(error);
|
|
21721
|
+
}
|
|
21722
|
+
return String(error);
|
|
21723
|
+
}
|
|
21531
21724
|
var RemoteSandboxInstance = class {
|
|
21532
|
-
constructor(name, client) {
|
|
21725
|
+
constructor(name, client, workspace) {
|
|
21533
21726
|
this.client = client;
|
|
21727
|
+
this.workspace = workspace;
|
|
21534
21728
|
this.file = {
|
|
21535
21729
|
readFile: async (file) => {
|
|
21536
|
-
const
|
|
21730
|
+
const resolved = this.resolvePath(file);
|
|
21731
|
+
const result = await this.client.file.readFile({ file: resolved });
|
|
21537
21732
|
if (!result.ok) {
|
|
21538
|
-
throw new Error(
|
|
21733
|
+
throw new Error(`readFile failed: ${extractFetcherError(result.error)}`);
|
|
21539
21734
|
}
|
|
21540
21735
|
return { content: result.body.data?.content ?? "" };
|
|
21541
21736
|
},
|
|
21542
21737
|
writeFile: async (file, content) => {
|
|
21543
|
-
const
|
|
21738
|
+
const resolved = this.resolvePath(file);
|
|
21739
|
+
const result = await this.client.file.writeFile({ file: resolved, content });
|
|
21544
21740
|
if (!result.ok) {
|
|
21545
|
-
throw new Error(
|
|
21741
|
+
throw new Error(`writeFile failed: ${extractFetcherError(result.error)}`);
|
|
21546
21742
|
}
|
|
21547
21743
|
},
|
|
21548
21744
|
listPath: async (path3, options) => {
|
|
21745
|
+
const resolved = this.resolvePath(path3);
|
|
21549
21746
|
const result = await this.client.file.listPath({
|
|
21550
|
-
path:
|
|
21747
|
+
path: resolved,
|
|
21551
21748
|
recursive: options?.recursive ?? false
|
|
21552
21749
|
});
|
|
21553
21750
|
if (!result.ok) {
|
|
21554
|
-
throw new Error(
|
|
21751
|
+
throw new Error(`listPath failed: ${extractFetcherError(result.error)}`);
|
|
21555
21752
|
}
|
|
21556
21753
|
const files = (result.body.data?.files || []).map((f) => ({
|
|
21557
21754
|
path: f.path,
|
|
21558
|
-
is_dir: f.is_dir
|
|
21559
|
-
size: f.size,
|
|
21755
|
+
is_dir: f.is_dir === true || f.size === null,
|
|
21756
|
+
size: f.size ?? void 0,
|
|
21560
21757
|
modified_at: f.modified_at
|
|
21561
21758
|
}));
|
|
21562
21759
|
return { files };
|
|
21563
21760
|
},
|
|
21564
21761
|
findFiles: async (path3, glob) => {
|
|
21565
|
-
const
|
|
21762
|
+
const resolved = this.resolvePath(path3);
|
|
21763
|
+
const result = await this.client.file.findFiles({ path: resolved, glob });
|
|
21566
21764
|
if (!result.ok) {
|
|
21567
|
-
throw new Error(
|
|
21765
|
+
throw new Error(`findFiles failed: ${extractFetcherError(result.error)}`);
|
|
21568
21766
|
}
|
|
21569
21767
|
return { files: result.body.data?.files || [] };
|
|
21570
21768
|
},
|
|
21571
21769
|
searchInFile: async (file, regex) => {
|
|
21572
|
-
const
|
|
21770
|
+
const resolved = this.resolvePath(file);
|
|
21771
|
+
const result = await this.client.file.searchInFile({ file: resolved, regex });
|
|
21573
21772
|
if (!result.ok) {
|
|
21574
|
-
throw new Error(
|
|
21773
|
+
throw new Error(`searchInFile failed: ${extractFetcherError(result.error)}`);
|
|
21575
21774
|
}
|
|
21576
21775
|
return {
|
|
21577
21776
|
matches: result.body.data?.matches || [],
|
|
@@ -21579,30 +21778,33 @@ var RemoteSandboxInstance = class {
|
|
|
21579
21778
|
};
|
|
21580
21779
|
},
|
|
21581
21780
|
strReplaceEditor: async (params) => {
|
|
21781
|
+
const resolved = this.resolvePath(params.path);
|
|
21582
21782
|
const result = await this.client.file.strReplaceEditor({
|
|
21583
21783
|
command: params.command,
|
|
21584
|
-
path:
|
|
21784
|
+
path: resolved,
|
|
21585
21785
|
old_str: params.old_str,
|
|
21586
21786
|
new_str: params.new_str,
|
|
21587
21787
|
replace_mode: params.replace_mode
|
|
21588
21788
|
});
|
|
21589
21789
|
if (!result.ok) {
|
|
21590
|
-
throw new Error(
|
|
21790
|
+
throw new Error(`strReplaceEditor failed: ${extractFetcherError(result.error)}`);
|
|
21591
21791
|
}
|
|
21592
21792
|
},
|
|
21593
21793
|
uploadFile: async (params) => {
|
|
21794
|
+
const resolved = this.resolvePath(params.file);
|
|
21594
21795
|
const result = await this.client.file.uploadFile({
|
|
21595
21796
|
file: params.data,
|
|
21596
|
-
path:
|
|
21797
|
+
path: resolved
|
|
21597
21798
|
});
|
|
21598
21799
|
if (!result.ok) {
|
|
21599
|
-
throw new Error(
|
|
21800
|
+
throw new Error(`uploadFile failed: ${extractFetcherError(result.error)}`);
|
|
21600
21801
|
}
|
|
21601
21802
|
},
|
|
21602
21803
|
downloadFile: async (params) => {
|
|
21603
|
-
const
|
|
21804
|
+
const resolved = this.resolvePath(params.file);
|
|
21805
|
+
const result = await this.client.file.downloadFile({ path: resolved });
|
|
21604
21806
|
if (!result.ok) {
|
|
21605
|
-
throw new Error(
|
|
21807
|
+
throw new Error(`downloadFile failed: ${extractFetcherError(result.error)}`);
|
|
21606
21808
|
}
|
|
21607
21809
|
const buffer2 = await result.body.arrayBuffer();
|
|
21608
21810
|
return Buffer.from(buffer2);
|
|
@@ -21612,11 +21814,11 @@ var RemoteSandboxInstance = class {
|
|
|
21612
21814
|
execCommand: async (params) => {
|
|
21613
21815
|
const result = await this.client.shell.execCommand({
|
|
21614
21816
|
command: params.command,
|
|
21615
|
-
exec_dir: params.exec_dir,
|
|
21817
|
+
exec_dir: params.exec_dir ? this.resolvePath(params.exec_dir) : void 0,
|
|
21616
21818
|
timeout: params.timeout
|
|
21617
21819
|
});
|
|
21618
21820
|
if (!result.ok) {
|
|
21619
|
-
throw new Error(
|
|
21821
|
+
throw new Error(`execCommand failed: ${extractFetcherError(result.error)}`);
|
|
21620
21822
|
}
|
|
21621
21823
|
return {
|
|
21622
21824
|
output: result.body.data?.output ?? "",
|
|
@@ -21626,6 +21828,15 @@ var RemoteSandboxInstance = class {
|
|
|
21626
21828
|
};
|
|
21627
21829
|
this.name = name;
|
|
21628
21830
|
}
|
|
21831
|
+
resolvePath(file) {
|
|
21832
|
+
if (file.startsWith(this.workspace)) {
|
|
21833
|
+
return file;
|
|
21834
|
+
}
|
|
21835
|
+
if (!file.startsWith("/")) {
|
|
21836
|
+
return `${this.workspace}/${file}`;
|
|
21837
|
+
}
|
|
21838
|
+
return `${this.workspace}${file}`;
|
|
21839
|
+
}
|
|
21629
21840
|
async start() {
|
|
21630
21841
|
}
|
|
21631
21842
|
async stop() {
|
|
@@ -21646,23 +21857,58 @@ var RemoteSandboxInstance = class {
|
|
|
21646
21857
|
};
|
|
21647
21858
|
|
|
21648
21859
|
// src/sandbox_lattice/providers/RemoteSandboxProvider.ts
|
|
21860
|
+
var DEFAULT_WORKSPACE = "/home/gem";
|
|
21649
21861
|
var RemoteSandboxProvider = class {
|
|
21650
21862
|
constructor(config) {
|
|
21651
21863
|
this.config = config;
|
|
21652
21864
|
this.instances = /* @__PURE__ */ new Map();
|
|
21865
|
+
this.creating = /* @__PURE__ */ new Map();
|
|
21866
|
+
this.workspace = DEFAULT_WORKSPACE;
|
|
21867
|
+
this.workspaceResolved = false;
|
|
21653
21868
|
this.client = new import_sandbox23.SandboxClient({
|
|
21654
21869
|
baseUrl: config.baseURL,
|
|
21655
21870
|
environment: ""
|
|
21656
21871
|
});
|
|
21657
21872
|
}
|
|
21873
|
+
async resolveWorkspace() {
|
|
21874
|
+
if (this.workspaceResolved) {
|
|
21875
|
+
return this.workspace;
|
|
21876
|
+
}
|
|
21877
|
+
try {
|
|
21878
|
+
const result = await this.client.sandbox.getContext();
|
|
21879
|
+
if (result.ok && result.body.home_dir) {
|
|
21880
|
+
this.workspace = result.body.home_dir;
|
|
21881
|
+
}
|
|
21882
|
+
} catch {
|
|
21883
|
+
}
|
|
21884
|
+
this.workspaceResolved = true;
|
|
21885
|
+
return this.workspace;
|
|
21886
|
+
}
|
|
21658
21887
|
async createSandbox(name, _config) {
|
|
21659
21888
|
const existing = this.instances.get(name);
|
|
21660
21889
|
if (existing) {
|
|
21661
21890
|
return existing;
|
|
21662
21891
|
}
|
|
21663
|
-
const
|
|
21664
|
-
|
|
21665
|
-
|
|
21892
|
+
const inFlight = this.creating.get(name);
|
|
21893
|
+
if (inFlight) {
|
|
21894
|
+
return inFlight;
|
|
21895
|
+
}
|
|
21896
|
+
const creation = (async () => {
|
|
21897
|
+
const workspace = await this.resolveWorkspace();
|
|
21898
|
+
const instance = new RemoteSandboxInstance(name, this.client, workspace);
|
|
21899
|
+
this.instances.set(name, instance);
|
|
21900
|
+
return instance;
|
|
21901
|
+
})();
|
|
21902
|
+
this.creating.set(name, creation);
|
|
21903
|
+
creation.then(
|
|
21904
|
+
() => {
|
|
21905
|
+
this.creating.delete(name);
|
|
21906
|
+
},
|
|
21907
|
+
() => {
|
|
21908
|
+
this.creating.delete(name);
|
|
21909
|
+
}
|
|
21910
|
+
);
|
|
21911
|
+
return creation;
|
|
21666
21912
|
}
|
|
21667
21913
|
async getSandbox(name) {
|
|
21668
21914
|
const instance = this.instances.get(name);
|
|
@@ -21672,9 +21918,7 @@ var RemoteSandboxProvider = class {
|
|
|
21672
21918
|
return instance;
|
|
21673
21919
|
}
|
|
21674
21920
|
async stopSandbox(name) {
|
|
21675
|
-
|
|
21676
|
-
if (instance) {
|
|
21677
|
-
}
|
|
21921
|
+
this.instances.delete(name);
|
|
21678
21922
|
}
|
|
21679
21923
|
async deleteSandbox(name) {
|
|
21680
21924
|
this.instances.delete(name);
|
|
@@ -21682,6 +21926,82 @@ var RemoteSandboxProvider = class {
|
|
|
21682
21926
|
async listSandboxes() {
|
|
21683
21927
|
return Array.from(this.instances.values());
|
|
21684
21928
|
}
|
|
21929
|
+
createVolumeFsClient(_volumeName, pathPrefix) {
|
|
21930
|
+
const workspace = this.workspace;
|
|
21931
|
+
const resolve3 = (p) => {
|
|
21932
|
+
if (!p || p === "/") {
|
|
21933
|
+
if (pathPrefix) {
|
|
21934
|
+
return `${workspace}${pathPrefix}`;
|
|
21935
|
+
}
|
|
21936
|
+
return workspace;
|
|
21937
|
+
}
|
|
21938
|
+
if (p.startsWith(workspace)) {
|
|
21939
|
+
return p;
|
|
21940
|
+
}
|
|
21941
|
+
if (p.startsWith("/")) {
|
|
21942
|
+
return `${workspace}${p}`;
|
|
21943
|
+
}
|
|
21944
|
+
if (pathPrefix) {
|
|
21945
|
+
const mountDir = pathPrefix.replace(/^\//, "");
|
|
21946
|
+
return `${workspace}/${mountDir}/${p}`;
|
|
21947
|
+
}
|
|
21948
|
+
return `${workspace}/${p}`;
|
|
21949
|
+
};
|
|
21950
|
+
return {
|
|
21951
|
+
read: async (path3) => {
|
|
21952
|
+
const resolved = resolve3(path3);
|
|
21953
|
+
const result = await this.client.file.readFile({ file: resolved });
|
|
21954
|
+
if (!result.ok) {
|
|
21955
|
+
throw new Error(`Volume read failed: ${extractFetcherError(result.error)}`);
|
|
21956
|
+
}
|
|
21957
|
+
return result.body.data?.content ?? "";
|
|
21958
|
+
},
|
|
21959
|
+
write: async (path3, content) => {
|
|
21960
|
+
const resolved = resolve3(path3);
|
|
21961
|
+
const result = await this.client.file.writeFile({ file: resolved, content });
|
|
21962
|
+
if (!result.ok) {
|
|
21963
|
+
throw new Error(`Volume write failed: ${extractFetcherError(result.error)}`);
|
|
21964
|
+
}
|
|
21965
|
+
},
|
|
21966
|
+
list: async (path3) => {
|
|
21967
|
+
const resolved = resolve3(path3);
|
|
21968
|
+
const result = await this.client.file.listPath({
|
|
21969
|
+
path: resolved,
|
|
21970
|
+
recursive: false
|
|
21971
|
+
});
|
|
21972
|
+
if (!result.ok) {
|
|
21973
|
+
throw new Error(`Volume list failed: ${extractFetcherError(result.error)}`);
|
|
21974
|
+
}
|
|
21975
|
+
const entries = (result.body.data?.files || []).map((f) => ({
|
|
21976
|
+
path: f.path.startsWith(workspace) ? f.path.slice(workspace.length) : f.path,
|
|
21977
|
+
kind: f.is_dir === true || f.size === null ? "directory" : "file",
|
|
21978
|
+
size: f.size ?? 0,
|
|
21979
|
+
mode: 0,
|
|
21980
|
+
modified: f.modified_at ?? null
|
|
21981
|
+
}));
|
|
21982
|
+
return entries;
|
|
21983
|
+
},
|
|
21984
|
+
readRaw: async (path3) => {
|
|
21985
|
+
const resolved = resolve3(path3);
|
|
21986
|
+
const result = await this.client.file.downloadFile({ path: resolved });
|
|
21987
|
+
if (!result.ok) {
|
|
21988
|
+
throw new Error(`Volume download failed: ${extractFetcherError(result.error)}`);
|
|
21989
|
+
}
|
|
21990
|
+
const buffer2 = await result.body.arrayBuffer();
|
|
21991
|
+
return Buffer.from(buffer2);
|
|
21992
|
+
},
|
|
21993
|
+
writeRaw: async (path3, data) => {
|
|
21994
|
+
const resolved = resolve3(path3);
|
|
21995
|
+
const result = await this.client.file.uploadFile({
|
|
21996
|
+
file: data,
|
|
21997
|
+
path: resolved
|
|
21998
|
+
});
|
|
21999
|
+
if (!result.ok) {
|
|
22000
|
+
throw new Error(`Volume upload failed: ${extractFetcherError(result.error)}`);
|
|
22001
|
+
}
|
|
22002
|
+
}
|
|
22003
|
+
};
|
|
22004
|
+
}
|
|
21685
22005
|
};
|
|
21686
22006
|
|
|
21687
22007
|
// src/sandbox_lattice/providers/E2BProvider.ts
|
|
@@ -22323,6 +22643,7 @@ function clearEncryptionKeyCache() {
|
|
|
22323
22643
|
MicrosandboxRemoteProvider,
|
|
22324
22644
|
MicrosandboxServiceClient,
|
|
22325
22645
|
ModelLatticeManager,
|
|
22646
|
+
MysqlDatabase,
|
|
22326
22647
|
PinoLoggerClient,
|
|
22327
22648
|
PostgresDatabase,
|
|
22328
22649
|
PrometheusClient,
|
|
@@ -22387,6 +22708,7 @@ function clearEncryptionKeyCache() {
|
|
|
22387
22708
|
ensureBuiltinAgentsForTenant,
|
|
22388
22709
|
eventBus,
|
|
22389
22710
|
eventBusDefault,
|
|
22711
|
+
extractFetcherError,
|
|
22390
22712
|
fileDataToString,
|
|
22391
22713
|
formatContentWithLineNumbers,
|
|
22392
22714
|
formatGrepMatches,
|