plugin-agent-orchestrator 1.0.21 → 1.0.23
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/client-v2.d.ts +2 -0
- package/client-v2.js +1 -0
- package/dist/client/index.js +1 -1
- package/dist/client-v2/214.723affb37c13bf7a.js +10 -0
- package/dist/client-v2/264.0533912e6c5ea2d7.js +10 -0
- package/dist/client-v2/41.1805b2edfaa4afe2.js +10 -0
- package/dist/client-v2/418.5ae055abf141820e.js +10 -0
- package/dist/client-v2/619.d99d3c9e61c99064.js +10 -0
- package/dist/client-v2/70.a15d7fcec7c41768.js +10 -0
- package/dist/client-v2/892.72db4161511c8a16.js +10 -0
- package/dist/client-v2/926.87f660b670d85bcc.js +10 -0
- package/dist/client-v2/index.js +10 -0
- package/dist/externalVersion.js +7 -6
- package/dist/locale/en-US.json +7 -0
- package/dist/locale/vi-VN.json +7 -0
- package/dist/locale/zh-CN.json +27 -0
- package/dist/server/migrations/20260615000000-normalize-ai-employee-tool-bindings.js +63 -0
- package/dist/server/plugin.js +41 -1
- package/dist/server/services/AgentHarness.js +52 -27
- package/dist/server/services/AgentLoopController.js +8 -2
- package/dist/server/services/AgentLoopService.js +1 -1
- package/dist/server/services/AgentRegistryService.js +53 -42
- package/dist/server/services/CircuitBreaker.js +7 -2
- package/dist/server/services/CodeValidator.js +48 -14
- package/dist/server/services/SandboxRunner.js +18 -14
- package/dist/server/skill-hub/plugin.js +44 -17
- package/dist/server/tools/delegate-task.js +7 -2
- package/dist/server/tools/skill-execute.js +33 -2
- package/dist/server/utils/ai-manager.js +51 -0
- package/dist/server/utils/ctx-utils.js +11 -0
- package/dist/server/utils/skill-settings.js +122 -0
- package/package.json +49 -45
- package/src/client/AIEmployeesContext.tsx +51 -14
- package/src/client/AgentRunsTab.tsx +767 -764
- package/src/client/HarnessProfilesTab.tsx +254 -247
- package/src/client/RulesTab.tsx +780 -716
- package/src/client/TracingTab.tsx +1 -0
- package/src/client/plugin.tsx +34 -27
- package/src/client/skill-hub/components/GitSkillImport.tsx +10 -3
- package/src/client/skill-hub/components/SkillMetrics.tsx +157 -124
- package/src/client/skill-hub/index.tsx +58 -51
- package/src/client/skill-hub/tools/InteractionSchemasProvider.tsx +132 -99
- package/src/client/skill-hub/tools/registerSkillLoopCards.ts +71 -58
- package/src/client/tools/registerOrchestratorCards.ts +17 -7
- package/src/client-v2/components/AIEmployeeSelect.tsx +47 -0
- package/src/client-v2/components/AIEmployeesContext.tsx +110 -0
- package/src/client-v2/components/AgentRunsTab.tsx +767 -0
- package/src/client-v2/components/HarnessProfilesTab.tsx +254 -0
- package/src/client-v2/components/RulesTab.tsx +782 -0
- package/src/client-v2/components/TracingTab.tsx +432 -0
- package/src/client-v2/hooks/useApiRequest.ts +114 -0
- package/src/client-v2/pages/AgentRunsPage.tsx +13 -0
- package/src/client-v2/pages/ExecutionHistoryPage.tsx +10 -0
- package/src/client-v2/pages/HarnessProfilesPage.tsx +10 -0
- package/src/client-v2/pages/LoopSettingsPage.tsx +10 -0
- package/src/client-v2/pages/RulesPage.tsx +13 -0
- package/src/client-v2/pages/SkillDefinitionsPage.tsx +10 -0
- package/src/client-v2/pages/SkillMetricsPage.tsx +10 -0
- package/src/client-v2/pages/TracingPage.tsx +13 -0
- package/src/client-v2/plugin.tsx +70 -0
- package/src/client-v2/skill-hub/components/ExecutionHistory.tsx +196 -0
- package/src/client-v2/skill-hub/components/FileLinkList.tsx +37 -0
- package/src/client-v2/skill-hub/components/GitSkillImport.tsx +539 -0
- package/src/client-v2/skill-hub/components/LoopSettings.tsx +331 -0
- package/src/client-v2/skill-hub/components/SkillEditor.tsx +453 -0
- package/src/client-v2/skill-hub/components/SkillManager.tsx +174 -0
- package/src/client-v2/skill-hub/components/SkillMetrics.tsx +157 -0
- package/src/client-v2/skill-hub/components/SkillTestPanel.tsx +135 -0
- package/src/client-v2/skill-hub/locale.ts +13 -0
- package/src/client-v2/skill-hub/tools/loopTemplates.ts +52 -0
- package/src/client-v2/skill-hub/utils/jsonFields.ts +41 -0
- package/src/client-v2/utils/jsonFields.ts +41 -0
- package/src/locale/en-US.json +7 -0
- package/src/locale/vi-VN.json +7 -0
- package/src/locale/zh-CN.json +27 -0
- package/src/server/__tests__/agent-registry-service.test.ts +147 -0
- package/src/server/__tests__/code-validator.test.ts +63 -0
- package/src/server/__tests__/skill-execute.test.ts +33 -0
- package/src/server/__tests__/skill-settings.test.ts +63 -0
- package/src/server/migrations/20260615000000-normalize-ai-employee-tool-bindings.ts +39 -0
- package/src/server/plugin.ts +68 -12
- package/src/server/services/AgentHarness.ts +49 -22
- package/src/server/services/AgentLoopController.ts +17 -6
- package/src/server/services/AgentLoopService.ts +1 -1
- package/src/server/services/AgentPlannerService.ts +10 -0
- package/src/server/services/AgentRegistryService.ts +89 -47
- package/src/server/services/CircuitBreaker.ts +10 -0
- package/src/server/services/CodeValidator.ts +237 -159
- package/src/server/services/SandboxRunner.ts +203 -189
- package/src/server/skill-hub/plugin.ts +933 -898
- package/src/server/tools/delegate-task.ts +12 -9
- package/src/server/tools/skill-execute.ts +194 -160
- package/src/server/utils/ai-manager.ts +24 -0
- package/src/server/utils/ctx-utils.ts +14 -0
- package/src/server/utils/skill-settings.ts +116 -0
- package/dist/client/AIEmployeeSelect.d.ts +0 -11
- package/dist/client/AIEmployeesContext.d.ts +0 -30
- package/dist/client/AgentRunsTab.d.ts +0 -2
- package/dist/client/HarnessProfilesTab.d.ts +0 -2
- package/dist/client/OrchestratorSettings.d.ts +0 -3
- package/dist/client/RulesTab.d.ts +0 -2
- package/dist/client/TracingTab.d.ts +0 -2
- package/dist/client/hooks/useRunEventStream.d.ts +0 -22
- package/dist/client/index.d.ts +0 -2
- package/dist/client/plugin.d.ts +0 -6
- package/dist/client/skill-hub/components/ExecutionHistory.d.ts +0 -2
- package/dist/client/skill-hub/components/ExecutionProgress.d.ts +0 -20
- package/dist/client/skill-hub/components/GitSkillImport.d.ts +0 -7
- package/dist/client/skill-hub/components/LoopSettings.d.ts +0 -2
- package/dist/client/skill-hub/components/SkillEditor.d.ts +0 -7
- package/dist/client/skill-hub/components/SkillManager.d.ts +0 -2
- package/dist/client/skill-hub/components/SkillMetrics.d.ts +0 -2
- package/dist/client/skill-hub/components/SkillTestPanel.d.ts +0 -7
- package/dist/client/skill-hub/index.d.ts +0 -11
- package/dist/client/skill-hub/locale.d.ts +0 -3
- package/dist/client/skill-hub/tools/InteractionSchemasProvider.d.ts +0 -6
- package/dist/client/skill-hub/tools/SkillHubCard.d.ts +0 -3
- package/dist/client/skill-hub/tools/loopTemplates.d.ts +0 -22
- package/dist/client/skill-hub/tools/registerSkillLoopCards.d.ts +0 -1
- package/dist/client/skill-hub/utils/jsonFields.d.ts +0 -3
- package/dist/client/tools/PlanApprovalCard.d.ts +0 -3
- package/dist/client/tools/registerOrchestratorCards.d.ts +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/server/collections/agent-execution-spans.d.ts +0 -9
- package/dist/server/collections/agent-harness-profiles.d.ts +0 -2
- package/dist/server/collections/agent-loop-events.d.ts +0 -2
- package/dist/server/collections/agent-loop-runs.d.ts +0 -2
- package/dist/server/collections/agent-loop-steps.d.ts +0 -2
- package/dist/server/collections/orchestrator-config.d.ts +0 -2
- package/dist/server/collections/orchestrator-logs.d.ts +0 -8
- package/dist/server/collections/skill-definitions.d.ts +0 -3
- package/dist/server/collections/skill-executions.d.ts +0 -3
- package/dist/server/collections/skill-loop-configs.d.ts +0 -3
- package/dist/server/collections/skill-worker-configs.d.ts +0 -3
- package/dist/server/migrations/20260423000000-add-progress-fields.d.ts +0 -4
- package/dist/server/migrations/20260425000000-add-interaction-schema.d.ts +0 -4
- package/dist/server/migrations/20260427000000-add-tracing-detail-fields.d.ts +0 -7
- package/dist/server/migrations/20260427000000-change-packages-to-text.d.ts +0 -4
- package/dist/server/migrations/20260427000001-change-other-json-to-text.d.ts +0 -4
- package/dist/server/migrations/20260429000000-add-llm-fields.d.ts +0 -7
- package/dist/server/migrations/20260429000000-fix-inputargs-json-to-text.d.ts +0 -16
- package/dist/server/migrations/20260503000000-add-orchestrator-trace-fields.d.ts +0 -7
- package/dist/server/migrations/20260524000000-add-agent-loop-fields-to-skill-executions.d.ts +0 -7
- package/dist/server/migrations/20260524001000-add-plan-approval-and-harness-profiles.d.ts +0 -12
- package/dist/server/migrations/20260601000000-add-token-fields.d.ts +0 -7
- package/dist/server/plugin.d.ts +0 -16
- package/dist/server/resources/agent-loop.d.ts +0 -3
- package/dist/server/resources/tracing.d.ts +0 -7
- package/dist/server/services/AgentHarness.d.ts +0 -44
- package/dist/server/services/AgentLoopController.d.ts +0 -218
- package/dist/server/services/AgentLoopRepository.d.ts +0 -20
- package/dist/server/services/AgentLoopService.d.ts +0 -159
- package/dist/server/services/AgentPlanValidator.d.ts +0 -4
- package/dist/server/services/AgentPlannerService.d.ts +0 -8
- package/dist/server/services/AgentRegistryService.d.ts +0 -21
- package/dist/server/services/CircuitBreaker.d.ts +0 -40
- package/dist/server/services/CodeValidator.d.ts +0 -32
- package/dist/server/services/ContextAggregator.d.ts +0 -45
- package/dist/server/services/ExecutionSpanService.d.ts +0 -46
- package/dist/server/services/FileManager.d.ts +0 -28
- package/dist/server/services/RunEventBus.d.ts +0 -9
- package/dist/server/services/SandboxRunner.d.ts +0 -41
- package/dist/server/services/SkillManager.d.ts +0 -6
- package/dist/server/services/SkillRepositoryService.d.ts +0 -22
- package/dist/server/services/TokenTracker.d.ts +0 -62
- package/dist/server/services/WorkerEnvManager.d.ts +0 -26
- package/dist/server/skill-hub/actions/git-import.d.ts +0 -21
- package/dist/server/skill-hub/mcp/McpController.d.ts +0 -15
- package/dist/server/skill-hub/plugin.d.ts +0 -61
- package/dist/server/skill-hub/tasks/SkillExecutionTask.d.ts +0 -16
- package/dist/server/skill-hub/utils/json-fields.d.ts +0 -7
- package/dist/server/tools/agent-loop.d.ts +0 -235
- package/dist/server/tools/delegate-task.d.ts +0 -19
- package/dist/server/tools/external-rag-search.d.ts +0 -42
- package/dist/server/tools/orchestrator-plan.d.ts +0 -205
- package/dist/server/tools/skill-execute.d.ts +0 -36
- package/dist/server/types.d.ts +0 -47
- package/dist/server/utils/ctx-utils.d.ts +0 -30
- package/dist/server/utils/logging.d.ts +0 -6
- /package/{dist/server/index.d.ts → src/client-v2/index.tsx} +0 -0
|
@@ -1,205 +1,219 @@
|
|
|
1
|
-
import { exec, ChildProcess, ExecException } from 'child_process';
|
|
2
|
-
import { writeFileSync } from 'fs';
|
|
3
|
-
import { resolve } from 'path';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
import { exec, ChildProcess, ExecException } from 'child_process';
|
|
2
|
+
import { writeFileSync } from 'fs';
|
|
3
|
+
import { resolve, delimiter } from 'path';
|
|
4
|
+
import { tmpdir } from 'os';
|
|
5
|
+
import { FileManager, OutputFileInfo } from './FileManager';
|
|
6
|
+
import { CodeValidator } from './CodeValidator';
|
|
7
|
+
|
|
8
|
+
const IS_WINDOWS = process.platform === 'win32';
|
|
9
|
+
|
|
10
|
+
/** Resolve the python executable name per platform (python3 on *nix, python on Windows). */
|
|
11
|
+
function pythonBinary() {
|
|
12
|
+
return process.env.SKILL_HUB_PYTHON_BIN || (IS_WINDOWS ? 'python' : 'python3');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ExecuteOptions {
|
|
16
|
+
language: 'node' | 'python';
|
|
17
|
+
code: string;
|
|
18
|
+
execId: string;
|
|
19
|
+
timeoutSeconds?: number;
|
|
20
|
+
maxOutputSizeMb?: number;
|
|
21
|
+
onProgress?: (progress: ProgressUpdate) => void;
|
|
22
|
+
/** AbortSignal — when aborted, the child process is killed */
|
|
23
|
+
signal?: { addEventListener(event: string, listener: () => void): void };
|
|
16
24
|
/** Package whitelist for import validation (from skillWorkerConfigs) */
|
|
17
25
|
packageWhitelist?: string[];
|
|
18
26
|
/** Optional installed/copied skill package root exposed to the runtime as SKILL_DIR. */
|
|
19
27
|
skillDir?: string;
|
|
20
28
|
}
|
|
21
|
-
|
|
22
|
-
export interface ProgressUpdate {
|
|
23
|
-
percent: number;
|
|
24
|
-
log: string;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface ExecutionResult {
|
|
28
|
-
success: boolean;
|
|
29
|
-
stdout: string;
|
|
30
|
-
stderr: string;
|
|
31
|
-
files: OutputFileInfo[];
|
|
32
|
-
durationMs: number;
|
|
33
|
-
/** true if execution was canceled by user */
|
|
34
|
-
canceled?: boolean;
|
|
35
|
-
/** true if execution timed out */
|
|
36
|
-
timedOut?: boolean;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export class SandboxRunner {
|
|
40
|
-
private validator = new CodeValidator();
|
|
41
|
-
|
|
42
|
-
private sandboxWorkspace: string;
|
|
43
|
-
|
|
44
|
-
constructor(
|
|
45
|
-
private fileManager: FileManager,
|
|
46
|
-
private logger: any,
|
|
47
|
-
private storagePath: string,
|
|
48
|
-
) {
|
|
49
|
-
this.sandboxWorkspace = resolve(storagePath, 'sandbox-workspace');
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async execute(options: ExecuteOptions): Promise<ExecutionResult> {
|
|
53
|
-
const {
|
|
54
|
-
language,
|
|
55
|
-
code,
|
|
56
|
-
execId,
|
|
57
|
-
timeoutSeconds = 60,
|
|
58
|
-
maxOutputSizeMb = 50,
|
|
59
|
-
onProgress,
|
|
29
|
+
|
|
30
|
+
export interface ProgressUpdate {
|
|
31
|
+
percent: number;
|
|
32
|
+
log: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface ExecutionResult {
|
|
36
|
+
success: boolean;
|
|
37
|
+
stdout: string;
|
|
38
|
+
stderr: string;
|
|
39
|
+
files: OutputFileInfo[];
|
|
40
|
+
durationMs: number;
|
|
41
|
+
/** true if execution was canceled by user */
|
|
42
|
+
canceled?: boolean;
|
|
43
|
+
/** true if execution timed out */
|
|
44
|
+
timedOut?: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export class SandboxRunner {
|
|
48
|
+
private validator = new CodeValidator();
|
|
49
|
+
|
|
50
|
+
private sandboxWorkspace: string;
|
|
51
|
+
|
|
52
|
+
constructor(
|
|
53
|
+
private fileManager: FileManager,
|
|
54
|
+
private logger: any,
|
|
55
|
+
private storagePath: string,
|
|
56
|
+
) {
|
|
57
|
+
this.sandboxWorkspace = resolve(storagePath, 'sandbox-workspace');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async execute(options: ExecuteOptions): Promise<ExecutionResult> {
|
|
61
|
+
const {
|
|
62
|
+
language,
|
|
63
|
+
code,
|
|
64
|
+
execId,
|
|
65
|
+
timeoutSeconds = 60,
|
|
66
|
+
maxOutputSizeMb = 50,
|
|
67
|
+
onProgress,
|
|
60
68
|
signal,
|
|
61
69
|
packageWhitelist,
|
|
62
70
|
skillDir,
|
|
63
71
|
} = options;
|
|
64
|
-
|
|
65
|
-
// 1. Validate code against forbidden patterns
|
|
66
|
-
this.validator.validate(code, language);
|
|
67
|
-
|
|
68
|
-
// 1b. Validate imports against
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
// 2. Prepare workspace
|
|
74
|
-
const workDir = this.fileManager.createExecDir(execId);
|
|
75
|
-
const outputDir = this.fileManager.getOutputDir(execId);
|
|
76
|
-
|
|
77
|
-
const filename = language === 'node' ? 'script.js' : 'script.py';
|
|
78
|
-
const scriptPath = resolve(workDir, filename);
|
|
79
|
-
writeFileSync(scriptPath, code, 'utf-8');
|
|
80
|
-
|
|
81
|
-
onProgress?.({ percent: 20, log: 'Code validated, executing...' });
|
|
82
|
-
|
|
83
|
-
// 3.
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
//
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
72
|
+
|
|
73
|
+
// 1. Validate code against forbidden patterns
|
|
74
|
+
this.validator.validate(code, language);
|
|
75
|
+
|
|
76
|
+
// 1b. Validate imports against the allowlist (builtins + whitelist).
|
|
77
|
+
// Always runs: an empty whitelist restricts code to built-in modules only,
|
|
78
|
+
// which blocks stdlib-based network exfiltration (urllib/socket/etc.).
|
|
79
|
+
this.validator.validateImports(code, language, packageWhitelist || []);
|
|
80
|
+
|
|
81
|
+
// 2. Prepare workspace
|
|
82
|
+
const workDir = this.fileManager.createExecDir(execId);
|
|
83
|
+
const outputDir = this.fileManager.getOutputDir(execId);
|
|
84
|
+
|
|
85
|
+
const filename = language === 'node' ? 'script.js' : 'script.py';
|
|
86
|
+
const scriptPath = resolve(workDir, filename);
|
|
87
|
+
writeFileSync(scriptPath, code, 'utf-8');
|
|
88
|
+
|
|
89
|
+
onProgress?.({ percent: 20, log: 'Code validated, executing...' });
|
|
90
|
+
|
|
91
|
+
// 3. Resolve Node Modules Path using the local sandbox workspace
|
|
92
|
+
const nodePath = resolve(this.sandboxWorkspace, 'node_modules');
|
|
93
|
+
const finalNodePath = process.env.NODE_PATH ? `${nodePath}${delimiter}${process.env.NODE_PATH}` : nodePath;
|
|
94
|
+
|
|
95
|
+
// 4. Build command.
|
|
96
|
+
// Memory cap (MB): node gets --max-old-space-size; on Linux/macOS the whole
|
|
97
|
+
// process tree is additionally bounded with `ulimit -v` so a python skill
|
|
98
|
+
// cannot exhaust host memory. Windows has no ulimit equivalent, so the cap
|
|
99
|
+
// there is best-effort (node heap only) — production runs on Linux.
|
|
100
|
+
const memLimitMb = Math.max(64, Number(process.env.SKILL_HUB_MEM_LIMIT_MB || 512));
|
|
101
|
+
const baseCmd =
|
|
102
|
+
language === 'node'
|
|
103
|
+
? `node --max-old-space-size=${memLimitMb} "${scriptPath}"`
|
|
104
|
+
: `${pythonBinary()} "${scriptPath}"`;
|
|
105
|
+
const cmd = !IS_WINDOWS && memLimitMb > 0 ? `ulimit -v ${memLimitMb * 1024} 2>/dev/null; exec ${baseCmd}` : baseCmd;
|
|
106
|
+
|
|
107
|
+
// 5. Execute via child_process with sanitized env
|
|
108
|
+
const startTime = Date.now();
|
|
109
|
+
let childProc: ChildProcess | null = null;
|
|
110
|
+
let wasCanceled = false;
|
|
111
|
+
|
|
112
|
+
const processResult = await new Promise<{
|
|
113
|
+
exitCode: number;
|
|
114
|
+
stdout: string;
|
|
115
|
+
stderr: string;
|
|
116
|
+
}>((_resolve) => {
|
|
117
|
+
childProc = exec(
|
|
118
|
+
cmd,
|
|
119
|
+
{
|
|
120
|
+
timeout: timeoutSeconds * 1000,
|
|
121
|
+
maxBuffer: 10 * 1024 * 1024, // 10MB stdout/stderr buffer
|
|
122
|
+
cwd: workDir,
|
|
123
|
+
env: {
|
|
124
|
+
// Sanitized environment — only expose what's necessary
|
|
125
|
+
PATH: process.env.PATH,
|
|
126
|
+
HOME: tmpdir(),
|
|
127
|
+
TMPDIR: tmpdir(),
|
|
128
|
+
OUTPUT_DIR: outputDir,
|
|
129
|
+
LANG: 'en_US.UTF-8',
|
|
130
|
+
// Node.js
|
|
131
|
+
NODE_PATH: finalNodePath,
|
|
120
132
|
// Python — include bundled packages (svg_to_pptx etc.)
|
|
121
133
|
PYTHONPATH: [
|
|
122
|
-
skillDir ?
|
|
123
|
-
|
|
134
|
+
skillDir ? resolve(skillDir, 'scripts') : '',
|
|
135
|
+
resolve(this.sandboxWorkspace, 'python_packages'),
|
|
124
136
|
process.env.PYTHONPATH || '',
|
|
125
|
-
]
|
|
137
|
+
]
|
|
138
|
+
.filter(Boolean)
|
|
139
|
+
.join(delimiter),
|
|
126
140
|
PYTHONIOENCODING: 'utf-8',
|
|
127
141
|
SKILL_DIR: skillDir || '',
|
|
128
142
|
// DO NOT pass: DB credentials, API keys, APP_KEY, etc.
|
|
129
143
|
},
|
|
130
|
-
},
|
|
131
|
-
(error: ExecException | null, stdout: string, stderr: string) => {
|
|
132
|
-
let exitCode = 0;
|
|
133
|
-
if (error) {
|
|
134
|
-
if (error.killed) {
|
|
135
|
-
exitCode = -1; // Killed by timeout or abort
|
|
136
|
-
} else {
|
|
137
|
-
exitCode = error.code || 1;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
exitCode,
|
|
143
|
-
stdout: (stdout || '').slice(0, 5000),
|
|
144
|
-
stderr: (stderr || '').slice(0, 2000),
|
|
145
|
-
});
|
|
146
|
-
},
|
|
147
|
-
);
|
|
148
|
-
|
|
149
|
-
// 5. Wire abort signal → kill child process
|
|
150
|
-
if (signal) {
|
|
151
|
-
signal.addEventListener('abort', () => {
|
|
152
|
-
wasCanceled = true;
|
|
153
|
-
if (childProc && !childProc.killed) {
|
|
154
|
-
this.logger.info(`[skill-hub] Killing child process for exec ${execId} (user abort)`);
|
|
155
|
-
childProc.kill('SIGTERM');
|
|
156
|
-
// Force kill after 3 seconds if SIGTERM didn't work
|
|
157
|
-
setTimeout(() => {
|
|
158
|
-
if (childProc && !childProc.killed) {
|
|
159
|
-
childProc.kill('SIGKILL');
|
|
160
|
-
}
|
|
161
|
-
}, 3000);
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
const durationMs = Date.now() - startTime;
|
|
168
|
-
|
|
169
|
-
onProgress?.({ percent: 80, log: wasCanceled ? 'Canceled' : 'Execution completed, collecting files...' });
|
|
170
|
-
|
|
171
|
-
// 6. Collect output files
|
|
172
|
-
const files = this.fileManager.listOutputFiles(execId);
|
|
173
|
-
|
|
174
|
-
// 7. Check output size limit
|
|
175
|
-
const totalSizeBytes = this.fileManager.getTotalOutputSize(execId);
|
|
176
|
-
const maxBytes = maxOutputSizeMb * 1024 * 1024;
|
|
177
|
-
if (totalSizeBytes > maxBytes) {
|
|
178
|
-
this.logger.warn(
|
|
179
|
-
`[skill-hub] Execution ${execId}: output size ${totalSizeBytes} bytes exceeds limit ${maxBytes}`,
|
|
180
|
-
);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
onProgress?.({ percent: 100, log: 'Done' });
|
|
184
|
-
|
|
185
|
-
// Detect timeout
|
|
186
|
-
const timedOut = !wasCanceled && processResult.exitCode === -1;
|
|
187
|
-
if (timedOut) {
|
|
188
|
-
processResult.stderr = `Execution timed out after ${timeoutSeconds}s\n${processResult.stderr}`;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (wasCanceled) {
|
|
192
|
-
processResult.stderr = `Execution canceled by user\n${processResult.stderr}`;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
return {
|
|
196
|
-
success: !wasCanceled && !timedOut && processResult.exitCode === 0,
|
|
197
|
-
stdout: processResult.stdout,
|
|
198
|
-
stderr: processResult.stderr,
|
|
199
|
-
files,
|
|
200
|
-
durationMs,
|
|
201
|
-
canceled: wasCanceled,
|
|
202
|
-
timedOut,
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
}
|
|
144
|
+
},
|
|
145
|
+
(error: ExecException | null, stdout: string, stderr: string) => {
|
|
146
|
+
let exitCode = 0;
|
|
147
|
+
if (error) {
|
|
148
|
+
if (error.killed) {
|
|
149
|
+
exitCode = -1; // Killed by timeout or abort
|
|
150
|
+
} else {
|
|
151
|
+
exitCode = error.code || 1;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
_resolve({
|
|
156
|
+
exitCode,
|
|
157
|
+
stdout: (stdout || '').slice(0, 5000),
|
|
158
|
+
stderr: (stderr || '').slice(0, 2000),
|
|
159
|
+
});
|
|
160
|
+
},
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
// 5. Wire abort signal → kill child process
|
|
164
|
+
if (signal) {
|
|
165
|
+
signal.addEventListener('abort', () => {
|
|
166
|
+
wasCanceled = true;
|
|
167
|
+
if (childProc && !childProc.killed) {
|
|
168
|
+
this.logger.info(`[skill-hub] Killing child process for exec ${execId} (user abort)`);
|
|
169
|
+
childProc.kill('SIGTERM');
|
|
170
|
+
// Force kill after 3 seconds if SIGTERM didn't work
|
|
171
|
+
setTimeout(() => {
|
|
172
|
+
if (childProc && !childProc.killed) {
|
|
173
|
+
childProc.kill('SIGKILL');
|
|
174
|
+
}
|
|
175
|
+
}, 3000);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
const durationMs = Date.now() - startTime;
|
|
182
|
+
|
|
183
|
+
onProgress?.({ percent: 80, log: wasCanceled ? 'Canceled' : 'Execution completed, collecting files...' });
|
|
184
|
+
|
|
185
|
+
// 6. Collect output files
|
|
186
|
+
const files = this.fileManager.listOutputFiles(execId);
|
|
187
|
+
|
|
188
|
+
// 7. Check output size limit
|
|
189
|
+
const totalSizeBytes = this.fileManager.getTotalOutputSize(execId);
|
|
190
|
+
const maxBytes = maxOutputSizeMb * 1024 * 1024;
|
|
191
|
+
if (totalSizeBytes > maxBytes) {
|
|
192
|
+
this.logger.warn(
|
|
193
|
+
`[skill-hub] Execution ${execId}: output size ${totalSizeBytes} bytes exceeds limit ${maxBytes}`,
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
onProgress?.({ percent: 100, log: 'Done' });
|
|
198
|
+
|
|
199
|
+
// Detect timeout
|
|
200
|
+
const timedOut = !wasCanceled && processResult.exitCode === -1;
|
|
201
|
+
if (timedOut) {
|
|
202
|
+
processResult.stderr = `Execution timed out after ${timeoutSeconds}s\n${processResult.stderr}`;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (wasCanceled) {
|
|
206
|
+
processResult.stderr = `Execution canceled by user\n${processResult.stderr}`;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
success: !wasCanceled && !timedOut && processResult.exitCode === 0,
|
|
211
|
+
stdout: processResult.stdout,
|
|
212
|
+
stderr: processResult.stderr,
|
|
213
|
+
files,
|
|
214
|
+
durationMs,
|
|
215
|
+
canceled: wasCanceled,
|
|
216
|
+
timedOut,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
}
|