[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
152
infrastructure/ai/harness/builtinSkillRunner.ts
Normal file
152
infrastructure/ai/harness/builtinSkillRunner.ts
Normal file
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* Runner for built-in diagnostic skills.
|
||||
*
|
||||
* Fetches the skill by id, filters its steps for the target session's shell
|
||||
* family, executes each step sequentially via the bridge, and assembles a
|
||||
* single structured report with labels, stdout/stderr, and exit codes.
|
||||
*/
|
||||
|
||||
import { getBuiltinSkill, filterStepsForShell, type SkillStep } from './builtinSkills';
|
||||
import type { ToolDeps, ToolExecResult } from '../shared/toolExecutors';
|
||||
|
||||
interface RunOptions {
|
||||
chatSessionId?: string;
|
||||
}
|
||||
|
||||
interface StepResult {
|
||||
label: string;
|
||||
command: string;
|
||||
stdout: string;
|
||||
stderr: string;
|
||||
exitCode: number | null;
|
||||
durationMs: number;
|
||||
ok: boolean;
|
||||
}
|
||||
|
||||
export interface SkillRunReport {
|
||||
skill: string;
|
||||
sessionId: string;
|
||||
shellType?: string;
|
||||
os?: string;
|
||||
hostname?: string;
|
||||
startedAt: string;
|
||||
completedAt: string;
|
||||
durationMs: number;
|
||||
steps: StepResult[];
|
||||
}
|
||||
|
||||
export async function executeSkillRun(
|
||||
deps: ToolDeps,
|
||||
args: Record<string, unknown>,
|
||||
options: RunOptions = {},
|
||||
): Promise<ToolExecResult<SkillRunReport>> {
|
||||
const { bridge, context, permissionMode } = deps;
|
||||
const resolveContext = () => (typeof context === 'function' ? context() : context);
|
||||
const ctx = resolveContext();
|
||||
|
||||
const sessionId = typeof args.sessionId === 'string' ? args.sessionId.trim() : '';
|
||||
const skillName = typeof args.skillName === 'string' ? args.skillName.trim() : '';
|
||||
|
||||
if (!sessionId) {
|
||||
return { ok: false, error: 'Missing sessionId.' };
|
||||
}
|
||||
if (!skillName) {
|
||||
return { ok: false, error: 'Missing skillName.' };
|
||||
}
|
||||
|
||||
if (permissionMode === 'observer') {
|
||||
return { ok: false, error: 'Observer mode: skill execution is disabled. Switch to Confirm or Auto mode.' };
|
||||
}
|
||||
|
||||
// Validate session is in scope
|
||||
const session = ctx.sessions.find(s => s.sessionId === sessionId);
|
||||
if (!session) {
|
||||
return { ok: false, error: `Session "${sessionId}" is not in the current AI scope.` };
|
||||
}
|
||||
|
||||
// Resolve skill
|
||||
const skill = getBuiltinSkill(skillName);
|
||||
if (!skill) {
|
||||
const available = Object.keys((await import('./builtinSkills')).BUILTIN_SKILLS).join(', ');
|
||||
return { ok: false, error: `Unknown skill "${skillName}". Available: ${available}` };
|
||||
}
|
||||
|
||||
// Filter steps for this shell family
|
||||
const steps = filterStepsForShell(skill, session.shellType);
|
||||
if (steps.length === 0) {
|
||||
return {
|
||||
ok: false,
|
||||
error: `Skill "${skill.id}" has no steps for shell family "${session.shellType ?? 'unknown'}".`,
|
||||
};
|
||||
}
|
||||
|
||||
// Run each step sequentially, capture everything
|
||||
const startedAt = new Date();
|
||||
const stepResults: StepResult[] = [];
|
||||
|
||||
for (const step of steps) {
|
||||
const stepResult = await runStep(bridge, sessionId, step, options.chatSessionId);
|
||||
stepResults.push(stepResult);
|
||||
}
|
||||
|
||||
const completedAt = new Date();
|
||||
const report: SkillRunReport = {
|
||||
skill: skill.id,
|
||||
sessionId,
|
||||
shellType: session.shellType,
|
||||
os: session.os,
|
||||
hostname: session.hostname,
|
||||
startedAt: startedAt.toISOString(),
|
||||
completedAt: completedAt.toISOString(),
|
||||
durationMs: completedAt.getTime() - startedAt.getTime(),
|
||||
steps: stepResults,
|
||||
};
|
||||
|
||||
return { ok: true, data: report };
|
||||
}
|
||||
|
||||
async function runStep(
|
||||
bridge: NonNullable<ToolDeps['bridge']>,
|
||||
sessionId: string,
|
||||
step: SkillStep,
|
||||
chatSessionId?: string,
|
||||
): Promise<StepResult> {
|
||||
const t0 = Date.now();
|
||||
try {
|
||||
const result = await bridge.aiExec(sessionId, step.command, chatSessionId);
|
||||
const durationMs = Date.now() - t0;
|
||||
|
||||
if (!result.ok && result.error) {
|
||||
return {
|
||||
label: step.label,
|
||||
command: step.command,
|
||||
stdout: result.stdout || '',
|
||||
stderr: `[exec error] ${result.error}`,
|
||||
exitCode: null,
|
||||
durationMs,
|
||||
ok: false,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
label: step.label,
|
||||
command: step.command,
|
||||
stdout: result.stdout || '',
|
||||
stderr: result.stderr || '',
|
||||
exitCode: result.exitCode ?? -1,
|
||||
durationMs,
|
||||
ok: (result.exitCode ?? 0) === 0,
|
||||
};
|
||||
} catch (err) {
|
||||
const durationMs = Date.now() - t0;
|
||||
return {
|
||||
label: step.label,
|
||||
command: step.command,
|
||||
stdout: '',
|
||||
stderr: `[exception] ${err instanceof Error ? err.message : String(err)}`,
|
||||
exitCode: null,
|
||||
durationMs,
|
||||
ok: false,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user