@axiom-lattice/core 2.1.72 → 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 +458 -40
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +456 -40
- 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) {
|
|
@@ -19070,10 +19235,105 @@ Use this when the task follows a standard BPO (Business Process Orchestration) p
|
|
|
19070
19235
|
|
|
19071
19236
|
**Business rule \u2014 Draft-then-confirm pattern:** When a workflow creates business objects that require human approval (e.g., draft orders in SAP B1, purchase requisitions, expense reports), the design MUST include a confirmation step AFTER the creation step. The create step must complete successfully before the confirm step runs. The flow is always: **Create draft \u2192 User confirms \u2192 Finalize**. Reason: systems like SAP B1 only expose drafts to users after they are created \u2014 the user cannot see or approve something that doesn't exist yet. The confirm step MUST use the \`ask_user_to_clarify\` middleware.
|
|
19072
19237
|
|
|
19238
|
+
**Business pattern \u2014 SAP B1 Draft SO Creation:** When designing a sub-agent responsible for creating draft Sales Orders in SAP B1, embed the following standards into its system prompt. These ensure consistent data construction, API usage, and user presentation:
|
|
19239
|
+
|
|
19240
|
+
**Step 1: Construct SO Data Structure**
|
|
19241
|
+
Build the JSON payload. For each DocumentLines item:
|
|
19242
|
+
- Include \`WarehouseCode\` ONLY if sku.json provides a value; if missing or empty, OMIT the field entirely
|
|
19243
|
+
- Generate \`Comments\` dynamically based on context (customer name, PO reference, special instructions)
|
|
19244
|
+
|
|
19245
|
+
\`\`\`json
|
|
19246
|
+
{
|
|
19247
|
+
"DocObjectCode": "17",
|
|
19248
|
+
"DocType": "dDocument_Items",
|
|
19249
|
+
"CardCode": "C001",
|
|
19250
|
+
"DocDate": "current date",
|
|
19251
|
+
"DocDueDate": "delivery date",
|
|
19252
|
+
"TaxDate": "current date",
|
|
19253
|
+
"U_YWLX": "Modern Trade",
|
|
19254
|
+
"Comments": "SO for Kaimay Retail - PO ref: PO-2024-001234",
|
|
19255
|
+
"DocumentLines": [
|
|
19256
|
+
{
|
|
19257
|
+
"ItemCode": "SKU001",
|
|
19258
|
+
"Quantity": 240,
|
|
19259
|
+
"UnitPrice": 15.84
|
|
19260
|
+
}
|
|
19261
|
+
]
|
|
19262
|
+
}
|
|
19263
|
+
\`\`\`
|
|
19264
|
+
|
|
19265
|
+
Field mapping rules:
|
|
19266
|
+
| SAP Field | Data Source |
|
|
19267
|
+
|-----------|-------------|
|
|
19268
|
+
| CardCode | customer.json \u2192 CardCode |
|
|
19269
|
+
| DocDate | Current date (yyyy-MM-dd) |
|
|
19270
|
+
| DocDueDate | extracted.json \u2192 delivery_date |
|
|
19271
|
+
| TaxDate | Current date (yyyy-MM-dd) |
|
|
19272
|
+
| U_YWLX | customer.json \u2192 SalesType |
|
|
19273
|
+
| ItemCode | sku.json \u2192 ItemCode |
|
|
19274
|
+
| Quantity | extracted.json \u2192 Quantity |
|
|
19275
|
+
| WarehouseCode | sku.json \u2192 WarehouseCode (OMIT if missing/empty) |
|
|
19276
|
+
| UnitPrice | price.json \u2192 UnitPrice |
|
|
19277
|
+
| Comments | AI-generated based on customer name, PO reference, and context |
|
|
19278
|
+
|
|
19279
|
+
**Step 2: Call SAP API to Create Draft (MUST EXECUTE)**
|
|
19280
|
+
Use the \`sap_api_call\` tool with EXACTLY these parameters:
|
|
19281
|
+
- **Method**: POST
|
|
19282
|
+
- **Endpoint**: \`Drafts\` (ONLY allowed endpoint; do NOT call SalesOrders or any other endpoint)
|
|
19283
|
+
- **Body**: The JSON constructed in Step 1
|
|
19284
|
+
|
|
19285
|
+
CRITICAL: You MUST call sap_api_call BEFORE proceeding to Step 3. This step is NOT optional.
|
|
19286
|
+
|
|
19287
|
+
If the API call fails:
|
|
19288
|
+
- Log the error details
|
|
19289
|
+
- STOP the process
|
|
19290
|
+
- Report the failure to the user with the error message
|
|
19291
|
+
- Do NOT proceed to Step 3
|
|
19292
|
+
|
|
19293
|
+
**Step 3: Present Draft for User Review (MUST EXECUTE AFTER Step 2)**
|
|
19294
|
+
ONLY after the SAP API call in Step 2 succeeds, use the \`ask_user_to_clarify\` tool to present the complete SO summary.
|
|
19295
|
+
|
|
19296
|
+
Message format (STRICT \u2014 no emoji, no summary, field names match Service Layer):
|
|
19297
|
+
|
|
19298
|
+
=== Sales Order Draft ===
|
|
19299
|
+
|
|
19300
|
+
DocEntry: {DocEntry}
|
|
19301
|
+
DocNum: {DocNum}
|
|
19302
|
+
DocDate: {DocDate}
|
|
19303
|
+
DocDueDate: {DocDueDate}
|
|
19304
|
+
CardCode: {CardCode}
|
|
19305
|
+
CardName: {CardName}
|
|
19306
|
+
U_YWLX: {SalesType}
|
|
19307
|
+
Comments: {Comments}
|
|
19308
|
+
|
|
19309
|
+
DocumentLines:
|
|
19310
|
+
LineNum | ItemCode | Quantity | WarehouseCode | UnitPrice | LineTotal
|
|
19311
|
+
0 | {ItemCode} | {Quantity} | {WarehouseCode} | {UnitPrice} | {LineTotal}
|
|
19312
|
+
1 | {ItemCode} | {Quantity} | {WarehouseCode} | {UnitPrice} | {LineTotal}
|
|
19313
|
+
...
|
|
19314
|
+
|
|
19315
|
+
DocTotal: {DocTotal}
|
|
19316
|
+
|
|
19317
|
+
Warnings:
|
|
19318
|
+
- {warning1}
|
|
19319
|
+
- {warning2}
|
|
19320
|
+
|
|
19321
|
+
Options:
|
|
19322
|
+
[Confirm generating draft]
|
|
19323
|
+
[Cancel, do not generate]
|
|
19324
|
+
|
|
19325
|
+
**Data sharing pattern \u2014 File-based handoff:** Every sub-agent in the pipeline MUST persist its work results as files under a shared project directory, never rely on in-memory data passing between steps. Deep agents have built-in file capabilities, so no middleware is needed.
|
|
19326
|
+
|
|
19327
|
+
Rules:
|
|
19328
|
+
1. The **orchestrator** generates a unique project ID at the start (e.g., timestamp-based) and passes it to each sub-agent in the task context
|
|
19329
|
+
2. Each sub-agent reads input from \`/project/{project-id}/\` and writes output files into the same directory
|
|
19330
|
+
3. Establish clear file naming conventions so downstream steps know exactly which files to read (e.g., \`extracted.json\`, \`sku.json\`, \`customer.json\`, \`so_draft.json\`)
|
|
19331
|
+
4. The orchestrator's system prompt MUST specify for each edge: which files the target sub-agent should read and which files it should produce
|
|
19332
|
+
|
|
19073
19333
|
**Step 2: Topology design.** Design the agent topology and use \`show_widget\` to render an interactive diagram showing the flow: Orchestrator \u2192 Stage 1 \u2192 Stage 2 \u2192 ... \u2192 Output. Each edge should be labeled with its business purpose.
|
|
19074
19334
|
|
|
19075
19335
|
**Step 3: Design each sub-agent** as a **deep_agent** type (one at a time). For each:
|
|
19076
|
-
- Responsibility, system prompt, middleware, input/output contract
|
|
19336
|
+
- Responsibility, system prompt, middleware, file input/output contract (which files from \`/project/{project-id}/\` it reads, which files it writes)
|
|
19077
19337
|
- Deep agents have built-in file capabilities (ls, read, write, edit, glob, grep), so do NOT add filesystem middleware.
|
|
19078
19338
|
- **Ask for confirmation before moving to the next sub-agent.**
|
|
19079
19339
|
|
|
@@ -19092,15 +19352,15 @@ Use this when the task follows a standard BPO (Business Process Orchestration) p
|
|
|
19092
19352
|
| Section | Content |
|
|
19093
19353
|
|---------|---------|
|
|
19094
19354
|
| **Overview** | One-sentence summary of the workflow's purpose and business value |
|
|
19095
|
-
| **Steps** | Numbered list of each stage in the pipeline. For each step: which sub-agent handles it, what it does, what tools it uses, and what it
|
|
19096
|
-
| **Data Flow** | How data moves between steps
|
|
19355
|
+
| **Steps** | Numbered list of each stage in the pipeline. For each step: which sub-agent handles it, what it does, what tools it uses, what files it reads from \`/project/{project-id}/\`, and what files it writes. |
|
|
19356
|
+
| **Data Flow** | How data moves between steps via files under \`/project/{project-id}/\`. For each step: which files it reads as input and which files it writes as output. |
|
|
19097
19357
|
| **Logic & Conditions** | Any conditional branching, decision points, retry logic, or exception handling. When does the workflow take path A vs path B? What happens on failure? |
|
|
19098
19358
|
| **Tools Used** | Summary table or list of all tools used across sub-agents, grouped by sub-agent |
|
|
19099
19359
|
| **Expected Input** | What input does the workflow expect from the user? (format, examples) |
|
|
19100
19360
|
| **Expected Output** | What does the workflow produce at the end? (format, examples) |
|
|
19101
19361
|
|
|
19102
19362
|
**Formatting rules:**
|
|
19103
|
-
|
|
19363
|
+
- Write in **English**
|
|
19104
19364
|
- Use **Markdown** for formatting (headings, lists, tables, code blocks)
|
|
19105
19365
|
- Be detailed but concise \u2014 each section should be 1-5 lines
|
|
19106
19366
|
- Avoid placeholder text like "TODO" or "TBD"
|
|
@@ -19112,13 +19372,14 @@ Use this when the task follows a standard BPO (Business Process Orchestration) p
|
|
|
19112
19372
|
\u672C\u5DE5\u4F5C\u6D41\u81EA\u52A8\u4ECE\u591A\u4E2A\u6570\u636E\u6E90\u91C7\u96C6\u7ADE\u54C1\u4EF7\u683C\uFF0C\u751F\u6210\u5BF9\u6BD4\u5206\u6790\u62A5\u544A\u5E76\u63A8\u9001\u901A\u77E5\u3002
|
|
19113
19373
|
|
|
19114
19374
|
## Steps
|
|
19115
|
-
|
|
19116
|
-
|
|
19117
|
-
|
|
19118
|
-
|
|
19375
|
+
1. **\u6570\u636E\u91C7\u96C6 (data-collector)** \u2014 \u4F7F\u7528 browser \u5DE5\u5177\u722C\u53D6\u6307\u5B9AURL\u7684\u7ADE\u54C1\u4EF7\u683C\u6570\u636E\uFF0C\u8C03\u7528 metrics API \u62C9\u53D6\u5386\u53F2\u4EF7\u683C\u3002\u8F93\u51FA \u2192 \`raw_prices.json\`
|
|
19376
|
+
2. **\u6570\u636E\u6E05\u6D17 (data-cleaner)** \u2014 \u8BFB\u53D6 \`raw_prices.json\`\uFF0C\u4F7F\u7528 code_eval \u6267\u884C Python \u811A\u672C\u6E05\u6D17\u5F02\u5E38\u503C\u548C\u7F3A\u5931\u503C\uFF0C\u7EDF\u4E00\u8D27\u5E01\u5355\u4F4D\u3002\u8F93\u51FA \u2192 \`cleaned_prices.json\`
|
|
19377
|
+
3. **\u62A5\u544A\u751F\u6210 (report-generator)** \u2014 \u8BFB\u53D6 \`cleaned_prices.json\` \u548C\u6A21\u677F\u6587\u4EF6\uFF0Ccode_eval \u8BA1\u7B97\u6DA8\u8DCC\u5E45\u548C\u8D8B\u52BF\uFF0C\u751F\u6210 Markdown \u5BF9\u6BD4\u62A5\u544A\u3002\u8F93\u51FA \u2192 \`report.md\`
|
|
19378
|
+
4. **\u901A\u77E5\u63A8\u9001 (notifier)** \u2014 \u8BFB\u53D6 \`report.md\`\uFF0C\u8C03\u7528 scheduler \u5B89\u6392\u5B9A\u65F6\u53D1\u9001\uFF0C\u4F7F\u7528 ask_user_to_clarify \u8BF7\u6C42\u53D1\u9001\u786E\u8BA4\u3002\u8F93\u51FA\u53D1\u9001\u7ED3\u679C\u3002
|
|
19119
19379
|
|
|
19120
19380
|
## Data Flow
|
|
19121
|
-
|
|
19381
|
+
All data is shared via files under \`/project/{project-id}/\`:
|
|
19382
|
+
\`\u7528\u6237\u8F93\u5165\` \u2192 data-collector writes \`raw_prices.json\` \u2192 data-cleaner reads \`raw_prices.json\`, writes \`cleaned_prices.json\` \u2192 report-generator reads \`cleaned_prices.json\`, writes \`report.md\` \u2192 notifier reads \`report.md\`, pushes
|
|
19122
19383
|
|
|
19123
19384
|
## Logic & Conditions
|
|
19124
19385
|
- data-collector \u722C\u53D6\u5931\u8D25\u65F6\u91CD\u8BD5\u6700\u591A3\u6B21\uFF0C\u95F4\u969430\u79D2
|
|
@@ -19279,7 +19540,7 @@ Creates a PROCESSING agent with a business-defined workflow topology. Sub-agents
|
|
|
19279
19540
|
\`\`\`typescript
|
|
19280
19541
|
{
|
|
19281
19542
|
name: string, // Required. Display name for the orchestrator
|
|
19282
|
-
description?: string, // Required for good UX. Comprehensive workflow spec in Markdown (
|
|
19543
|
+
description?: string, // Required for good UX. Comprehensive workflow spec in Markdown (English). Must cover: Overview, Steps (with tools per step), Data Flow, Logic & Conditions, Tools Used, Expected Input, Expected Output. This is the single source of truth displayed in the automation view info popover.
|
|
19283
19544
|
prompt: string, // Required. System prompt \u2014 how to route through the topology
|
|
19284
19545
|
edges: [{ // Required. At least 1 edge defining the serial workflow chain
|
|
19285
19546
|
from: string, // Source agent ID. First edge: use orchestrator name as placeholder (tool auto-replaces). Subsequent edges: previous sub-agent ID
|
|
@@ -21375,7 +21636,7 @@ var MicrosandboxRemoteProvider = class {
|
|
|
21375
21636
|
this.instances.delete(name);
|
|
21376
21637
|
await this.client.deleteSandbox(name);
|
|
21377
21638
|
}
|
|
21378
|
-
createVolumeFsClient(volumeName) {
|
|
21639
|
+
createVolumeFsClient(volumeName, _pathPrefix) {
|
|
21379
21640
|
return {
|
|
21380
21641
|
read: (path3) => this.client.volumeFsRead(volumeName, path3),
|
|
21381
21642
|
write: (path3, content) => this.client.volumeFsWrite(volumeName, path3, content),
|
|
@@ -21432,50 +21693,84 @@ var MicrosandboxRemoteProvider = class {
|
|
|
21432
21693
|
var import_sandbox23 = require("@agent-infra/sandbox");
|
|
21433
21694
|
|
|
21434
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
|
+
}
|
|
21435
21724
|
var RemoteSandboxInstance = class {
|
|
21436
|
-
constructor(name, client) {
|
|
21725
|
+
constructor(name, client, workspace) {
|
|
21437
21726
|
this.client = client;
|
|
21727
|
+
this.workspace = workspace;
|
|
21438
21728
|
this.file = {
|
|
21439
21729
|
readFile: async (file) => {
|
|
21440
|
-
const
|
|
21730
|
+
const resolved = this.resolvePath(file);
|
|
21731
|
+
const result = await this.client.file.readFile({ file: resolved });
|
|
21441
21732
|
if (!result.ok) {
|
|
21442
|
-
throw new Error(
|
|
21733
|
+
throw new Error(`readFile failed: ${extractFetcherError(result.error)}`);
|
|
21443
21734
|
}
|
|
21444
21735
|
return { content: result.body.data?.content ?? "" };
|
|
21445
21736
|
},
|
|
21446
21737
|
writeFile: async (file, content) => {
|
|
21447
|
-
const
|
|
21738
|
+
const resolved = this.resolvePath(file);
|
|
21739
|
+
const result = await this.client.file.writeFile({ file: resolved, content });
|
|
21448
21740
|
if (!result.ok) {
|
|
21449
|
-
throw new Error(
|
|
21741
|
+
throw new Error(`writeFile failed: ${extractFetcherError(result.error)}`);
|
|
21450
21742
|
}
|
|
21451
21743
|
},
|
|
21452
21744
|
listPath: async (path3, options) => {
|
|
21745
|
+
const resolved = this.resolvePath(path3);
|
|
21453
21746
|
const result = await this.client.file.listPath({
|
|
21454
|
-
path:
|
|
21747
|
+
path: resolved,
|
|
21455
21748
|
recursive: options?.recursive ?? false
|
|
21456
21749
|
});
|
|
21457
21750
|
if (!result.ok) {
|
|
21458
|
-
throw new Error(
|
|
21751
|
+
throw new Error(`listPath failed: ${extractFetcherError(result.error)}`);
|
|
21459
21752
|
}
|
|
21460
21753
|
const files = (result.body.data?.files || []).map((f) => ({
|
|
21461
21754
|
path: f.path,
|
|
21462
|
-
is_dir: f.is_dir
|
|
21463
|
-
size: f.size,
|
|
21755
|
+
is_dir: f.is_dir === true || f.size === null,
|
|
21756
|
+
size: f.size ?? void 0,
|
|
21464
21757
|
modified_at: f.modified_at
|
|
21465
21758
|
}));
|
|
21466
21759
|
return { files };
|
|
21467
21760
|
},
|
|
21468
21761
|
findFiles: async (path3, glob) => {
|
|
21469
|
-
const
|
|
21762
|
+
const resolved = this.resolvePath(path3);
|
|
21763
|
+
const result = await this.client.file.findFiles({ path: resolved, glob });
|
|
21470
21764
|
if (!result.ok) {
|
|
21471
|
-
throw new Error(
|
|
21765
|
+
throw new Error(`findFiles failed: ${extractFetcherError(result.error)}`);
|
|
21472
21766
|
}
|
|
21473
21767
|
return { files: result.body.data?.files || [] };
|
|
21474
21768
|
},
|
|
21475
21769
|
searchInFile: async (file, regex) => {
|
|
21476
|
-
const
|
|
21770
|
+
const resolved = this.resolvePath(file);
|
|
21771
|
+
const result = await this.client.file.searchInFile({ file: resolved, regex });
|
|
21477
21772
|
if (!result.ok) {
|
|
21478
|
-
throw new Error(
|
|
21773
|
+
throw new Error(`searchInFile failed: ${extractFetcherError(result.error)}`);
|
|
21479
21774
|
}
|
|
21480
21775
|
return {
|
|
21481
21776
|
matches: result.body.data?.matches || [],
|
|
@@ -21483,30 +21778,33 @@ var RemoteSandboxInstance = class {
|
|
|
21483
21778
|
};
|
|
21484
21779
|
},
|
|
21485
21780
|
strReplaceEditor: async (params) => {
|
|
21781
|
+
const resolved = this.resolvePath(params.path);
|
|
21486
21782
|
const result = await this.client.file.strReplaceEditor({
|
|
21487
21783
|
command: params.command,
|
|
21488
|
-
path:
|
|
21784
|
+
path: resolved,
|
|
21489
21785
|
old_str: params.old_str,
|
|
21490
21786
|
new_str: params.new_str,
|
|
21491
21787
|
replace_mode: params.replace_mode
|
|
21492
21788
|
});
|
|
21493
21789
|
if (!result.ok) {
|
|
21494
|
-
throw new Error(
|
|
21790
|
+
throw new Error(`strReplaceEditor failed: ${extractFetcherError(result.error)}`);
|
|
21495
21791
|
}
|
|
21496
21792
|
},
|
|
21497
21793
|
uploadFile: async (params) => {
|
|
21794
|
+
const resolved = this.resolvePath(params.file);
|
|
21498
21795
|
const result = await this.client.file.uploadFile({
|
|
21499
21796
|
file: params.data,
|
|
21500
|
-
path:
|
|
21797
|
+
path: resolved
|
|
21501
21798
|
});
|
|
21502
21799
|
if (!result.ok) {
|
|
21503
|
-
throw new Error(
|
|
21800
|
+
throw new Error(`uploadFile failed: ${extractFetcherError(result.error)}`);
|
|
21504
21801
|
}
|
|
21505
21802
|
},
|
|
21506
21803
|
downloadFile: async (params) => {
|
|
21507
|
-
const
|
|
21804
|
+
const resolved = this.resolvePath(params.file);
|
|
21805
|
+
const result = await this.client.file.downloadFile({ path: resolved });
|
|
21508
21806
|
if (!result.ok) {
|
|
21509
|
-
throw new Error(
|
|
21807
|
+
throw new Error(`downloadFile failed: ${extractFetcherError(result.error)}`);
|
|
21510
21808
|
}
|
|
21511
21809
|
const buffer2 = await result.body.arrayBuffer();
|
|
21512
21810
|
return Buffer.from(buffer2);
|
|
@@ -21516,11 +21814,11 @@ var RemoteSandboxInstance = class {
|
|
|
21516
21814
|
execCommand: async (params) => {
|
|
21517
21815
|
const result = await this.client.shell.execCommand({
|
|
21518
21816
|
command: params.command,
|
|
21519
|
-
exec_dir: params.exec_dir,
|
|
21817
|
+
exec_dir: params.exec_dir ? this.resolvePath(params.exec_dir) : void 0,
|
|
21520
21818
|
timeout: params.timeout
|
|
21521
21819
|
});
|
|
21522
21820
|
if (!result.ok) {
|
|
21523
|
-
throw new Error(
|
|
21821
|
+
throw new Error(`execCommand failed: ${extractFetcherError(result.error)}`);
|
|
21524
21822
|
}
|
|
21525
21823
|
return {
|
|
21526
21824
|
output: result.body.data?.output ?? "",
|
|
@@ -21530,6 +21828,15 @@ var RemoteSandboxInstance = class {
|
|
|
21530
21828
|
};
|
|
21531
21829
|
this.name = name;
|
|
21532
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
|
+
}
|
|
21533
21840
|
async start() {
|
|
21534
21841
|
}
|
|
21535
21842
|
async stop() {
|
|
@@ -21550,23 +21857,58 @@ var RemoteSandboxInstance = class {
|
|
|
21550
21857
|
};
|
|
21551
21858
|
|
|
21552
21859
|
// src/sandbox_lattice/providers/RemoteSandboxProvider.ts
|
|
21860
|
+
var DEFAULT_WORKSPACE = "/home/gem";
|
|
21553
21861
|
var RemoteSandboxProvider = class {
|
|
21554
21862
|
constructor(config) {
|
|
21555
21863
|
this.config = config;
|
|
21556
21864
|
this.instances = /* @__PURE__ */ new Map();
|
|
21865
|
+
this.creating = /* @__PURE__ */ new Map();
|
|
21866
|
+
this.workspace = DEFAULT_WORKSPACE;
|
|
21867
|
+
this.workspaceResolved = false;
|
|
21557
21868
|
this.client = new import_sandbox23.SandboxClient({
|
|
21558
21869
|
baseUrl: config.baseURL,
|
|
21559
21870
|
environment: ""
|
|
21560
21871
|
});
|
|
21561
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
|
+
}
|
|
21562
21887
|
async createSandbox(name, _config) {
|
|
21563
21888
|
const existing = this.instances.get(name);
|
|
21564
21889
|
if (existing) {
|
|
21565
21890
|
return existing;
|
|
21566
21891
|
}
|
|
21567
|
-
const
|
|
21568
|
-
|
|
21569
|
-
|
|
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;
|
|
21570
21912
|
}
|
|
21571
21913
|
async getSandbox(name) {
|
|
21572
21914
|
const instance = this.instances.get(name);
|
|
@@ -21576,9 +21918,7 @@ var RemoteSandboxProvider = class {
|
|
|
21576
21918
|
return instance;
|
|
21577
21919
|
}
|
|
21578
21920
|
async stopSandbox(name) {
|
|
21579
|
-
|
|
21580
|
-
if (instance) {
|
|
21581
|
-
}
|
|
21921
|
+
this.instances.delete(name);
|
|
21582
21922
|
}
|
|
21583
21923
|
async deleteSandbox(name) {
|
|
21584
21924
|
this.instances.delete(name);
|
|
@@ -21586,6 +21926,82 @@ var RemoteSandboxProvider = class {
|
|
|
21586
21926
|
async listSandboxes() {
|
|
21587
21927
|
return Array.from(this.instances.values());
|
|
21588
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
|
+
}
|
|
21589
22005
|
};
|
|
21590
22006
|
|
|
21591
22007
|
// src/sandbox_lattice/providers/E2BProvider.ts
|
|
@@ -22227,6 +22643,7 @@ function clearEncryptionKeyCache() {
|
|
|
22227
22643
|
MicrosandboxRemoteProvider,
|
|
22228
22644
|
MicrosandboxServiceClient,
|
|
22229
22645
|
ModelLatticeManager,
|
|
22646
|
+
MysqlDatabase,
|
|
22230
22647
|
PinoLoggerClient,
|
|
22231
22648
|
PostgresDatabase,
|
|
22232
22649
|
PrometheusClient,
|
|
@@ -22291,6 +22708,7 @@ function clearEncryptionKeyCache() {
|
|
|
22291
22708
|
ensureBuiltinAgentsForTenant,
|
|
22292
22709
|
eventBus,
|
|
22293
22710
|
eventBusDefault,
|
|
22711
|
+
extractFetcherError,
|
|
22294
22712
|
fileDataToString,
|
|
22295
22713
|
formatContentWithLineNumbers,
|
|
22296
22714
|
formatGrepMatches,
|