@hilbras/omninode 2.0.0-alpha.4 → 2.0.0-alpha.5
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/README.md +10 -3
- package/dist/cli/index.js +142 -14
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +58 -4
- package/dist/index.js +112 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -443,18 +443,37 @@ interface PipelineDefinition {
|
|
|
443
443
|
* authoritative detail always lives in `stepRuns`/`taskRuns`.
|
|
444
444
|
*/
|
|
445
445
|
type PipelineRunStatus = "pending" | "running" | "completed" | "failed" | "partial" | "cancelled";
|
|
446
|
+
/**
|
|
447
|
+
* One step execution inside a run (§9.1 — Step Run is NOT the Step).
|
|
448
|
+
*/
|
|
446
449
|
interface PipelineStepRun {
|
|
447
450
|
stepId: string;
|
|
448
451
|
status: TaskStatus;
|
|
449
452
|
/** Tasks created for this step (research fans out to several). */
|
|
450
453
|
taskIds?: string[];
|
|
454
|
+
/** Execution ids of the tasks this step created, for correlation (§6.5). */
|
|
455
|
+
executionIds?: string[];
|
|
456
|
+
/** Which attempt of this step produced this record (1 = first try). */
|
|
457
|
+
attempt?: number;
|
|
451
458
|
/** Set on plan steps that produced a stored plan (§18). */
|
|
452
459
|
planId?: string;
|
|
453
460
|
error?: string;
|
|
454
461
|
}
|
|
462
|
+
/** One execution attempt of a run (§9.1 — Attempt is not the Run). */
|
|
463
|
+
interface PipelineRunAttempt {
|
|
464
|
+
attempt: number;
|
|
465
|
+
startedAt: string;
|
|
466
|
+
finishedAt?: string;
|
|
467
|
+
status: PipelineRunStatus;
|
|
468
|
+
}
|
|
455
469
|
interface PipelineRun {
|
|
456
470
|
id: string;
|
|
457
471
|
pipelineId: string;
|
|
472
|
+
/** Execution attempt counter: retries of the same run increment it. */
|
|
473
|
+
attempt: number;
|
|
474
|
+
/** Set when cancellation was requested; the run stops at the next check point. */
|
|
475
|
+
cancellationRequested?: boolean;
|
|
476
|
+
cancellationRequestedAt?: string;
|
|
458
477
|
/** The objective this run is executing (persisted for retries). */
|
|
459
478
|
objective?: string;
|
|
460
479
|
status: PipelineRunStatus;
|
|
@@ -469,6 +488,28 @@ interface PipelineRun {
|
|
|
469
488
|
planId?: string;
|
|
470
489
|
/** Outcome summary of the final executed step (§28 — Result). */
|
|
471
490
|
resultSummary?: string;
|
|
491
|
+
/** Per-attempt history (§9.1). */
|
|
492
|
+
attempts?: PipelineRunAttempt[];
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Executor contract (roadmap §9.1 / §9.2): a Pipeline definition, a Run of
|
|
496
|
+
* it, Steps, Step Runs and Attempts are distinct concepts; this interface is
|
|
497
|
+
* what orchestration code depends on.
|
|
498
|
+
*/
|
|
499
|
+
interface IPipelineExecutor {
|
|
500
|
+
validate(definition: PipelineDefinition): void;
|
|
501
|
+
run(definition: PipelineDefinition, options?: PipelineRunOptions): Promise<PipelineRun>;
|
|
502
|
+
cancel(runId: string): Promise<void>;
|
|
503
|
+
get(runId: string): Promise<PipelineRun | undefined>;
|
|
504
|
+
listRuns(filter?: {
|
|
505
|
+
pipelineId?: string;
|
|
506
|
+
}): Promise<PipelineRun[]>;
|
|
507
|
+
}
|
|
508
|
+
interface PipelineRunOptions {
|
|
509
|
+
objective?: string;
|
|
510
|
+
onStep?: (stepRun: PipelineStepRun) => void;
|
|
511
|
+
/** Total run attempts (1 = no automatic rerun of the whole run). */
|
|
512
|
+
maxAttempts?: number;
|
|
472
513
|
}
|
|
473
514
|
|
|
474
515
|
/** Plan types: the final implementation plan produced by the planner layer (§18). */
|
|
@@ -2458,11 +2499,19 @@ interface RunPipelineOptions {
|
|
|
2458
2499
|
objective?: string;
|
|
2459
2500
|
onStep?: (stepRun: PipelineStepRun) => void;
|
|
2460
2501
|
}
|
|
2461
|
-
declare class PipelineEngine {
|
|
2502
|
+
declare class PipelineEngine implements IPipelineExecutor {
|
|
2462
2503
|
private readonly options;
|
|
2463
2504
|
private readonly log;
|
|
2505
|
+
/** Runs executing in THIS process — cancellation can terminate them directly. */
|
|
2506
|
+
private readonly activeRuns;
|
|
2464
2507
|
constructor(options: PipelineEngineOptions);
|
|
2465
2508
|
get store(): PipelineRunStore;
|
|
2509
|
+
/**
|
|
2510
|
+
* Saves the run while preserving fields that may be set by another process
|
|
2511
|
+
* (e.g. a cancellation request) — an in-memory snapshot must never clobber
|
|
2512
|
+
* externally requested cancellation (§9.2).
|
|
2513
|
+
*/
|
|
2514
|
+
private persist;
|
|
2466
2515
|
/** Structural + semantic validation (§27 Phase 5 — pipeline parser). */
|
|
2467
2516
|
validate(def: PipelineDefinition): void;
|
|
2468
2517
|
private assertAcyclic;
|
|
@@ -2471,13 +2520,18 @@ declare class PipelineEngine {
|
|
|
2471
2520
|
* dependencies, which enable parallel branches.
|
|
2472
2521
|
*/
|
|
2473
2522
|
private effectiveDependencies;
|
|
2474
|
-
run(def: PipelineDefinition, options?:
|
|
2523
|
+
run(def: PipelineDefinition, options?: PipelineRunOptions): Promise<PipelineRun>;
|
|
2524
|
+
/** First-class cancellation (§9.2): requests cancellation and terminates
|
|
2525
|
+
* tasks that are running in this process immediately. */
|
|
2526
|
+
cancel(runId: string): Promise<void>;
|
|
2475
2527
|
get(runId: string): Promise<PipelineRun | undefined>;
|
|
2476
2528
|
listRuns(filter?: {
|
|
2477
2529
|
pipelineId?: string;
|
|
2478
2530
|
}): Promise<PipelineRun[]>;
|
|
2479
2531
|
private shouldRun;
|
|
2480
2532
|
private executeStep;
|
|
2533
|
+
/** Registers tasks created for a step as live, so cancellation can terminate them (§9.2). */
|
|
2534
|
+
private trackLiveTasks;
|
|
2481
2535
|
private executeStepOnce;
|
|
2482
2536
|
/** Research fan-out: one task per agent, in parallel (§15). */
|
|
2483
2537
|
private runFanOut;
|
|
@@ -2509,6 +2563,6 @@ declare class ProjectStores {
|
|
|
2509
2563
|
constructor(directory?: string);
|
|
2510
2564
|
}
|
|
2511
2565
|
|
|
2512
|
-
declare const OMNINODE_VERSION = "2.0.0-alpha.
|
|
2566
|
+
declare const OMNINODE_VERSION = "2.0.0-alpha.5";
|
|
2513
2567
|
|
|
2514
|
-
export { AgentAdapterRegistry, type AgentConfig, type AgentConfigYaml, type AgentDescriptor, AgentError, type AgentInfo, type AgentInputMode, type AgentIntegrationType, AgentRegistry, type AgentStatus, type AgentTaskInput, type AgentTaskOutput, type AgentToNodeMessage, type AggregateOptions, type AggregatedFinding, type AggregatedRecommendation, type AppConfig, type AppConfigYaml, type ArtifactKind, type ArtifactPayload, type AskedQuestion, type AuditAction, type AuditEvent, type AuditSink, type ChatFn, type ChatMessage, type ChatRequest, type ChatResponse, type ChatRole, type ChatUsage, type CombinedMeta, type CombinedReport, type CombinedReportFilter, type Confidence, ConfigError, ConsoleLogSink, type CreateTaskInput, type CwdValidation, DEFAULT_MAX_OUTPUT_BYTES, type DecodeResult, type DiscoveryResult, type EnvPolicy, type EnvelopeMeta, type ExecutionRecord, type ExtractionMeta, FileAuditLog, FilePipelineRunStore, FilePlanStore, FileReportStore, FileTaskStore, type Finding, type FindingSeverity, type FindingSource, type HelloResult, HeuristicPlanner, type HttpRequestOptions, type HttpResponse, type IAgent, type IAgentAdapter, type IChatProvider, type IMemoryProvider, type IPlanner, type IProvider, type JsonDocument, JsonFileStore, type JsonFileStoreOptions, type LoadConfigOptions, LocalMemoryProvider, type LogLevel, type LogSink, Logger, type LoggerOptions, MAX_MESSAGE_BYTES, type MemoryContextQuery, type MemoryEntry, MemoryError, type MemoryProviderConfig, type MemoryQuery, type MemoryScope, MemoryService, type MessageEnvelope, type ModelCapabilities, type ModelFilter, type ModelInfo, ModelPlanner, ModelRegistry, type ModelStatus, type NodeToAgentMessage, OMNINODE_VERSION, OPENAI_COMPATIBLE_TYPES, type OmniHilbrasConnectionResult, OmniHilbrasProvider, OmniNodeError, type OmniNodeErrorCode, type OmniNodeErrorOptions, OpenAICompatibleProvider, PROTOCOL_V2, type PipelineConfigYaml, type PipelineDefinition, PipelineEngine, type PipelineEngineOptions, PipelineError, type PipelineRun, type PipelineRunFilter, type PipelineRunStatus, type PipelineRunStore, type PipelineStep, type PipelineStepCondition, type PipelineStepConfigYaml, type PipelineStepKind, type PipelineStepRun, type Plan, type PlanFilter, type PlanRequest, type PlanStep, type PlanStore, type PlannerConfigYaml, PlannerError, ProcessAgent, ProcessAgentAdapter, type Project, type ProjectConfigYaml, ProjectStores, type ProtocolAgentToNodeType, ProtocolDecoder, type ProtocolEnvelope, ProtocolError, type ProtocolMessageType, type ProtocolNodeToAgentType, ProtocolSession, type ProtocolViolation, type ProtocolViolationCode, type ProviderConfig, type ProviderConfigYaml, ProviderError, type ProviderHealth, type ProviderStatus, type ProviderType, type QuestionPayload, type QuestionResponder, type RememberaConfig, RememberaMemoryProvider, type Report, type ReportFilter, type ReportPayload, ReportService, type ReportStore, type RoleConfigYaml, type RoleDefinition, RoleRegistry, type RunPipelineOptions, SUPPORTED_PROTOCOL_VERSIONS, type SessionIds, TERMINAL_TASK_STATUSES, type Task, type TaskContext, TaskEngine, type TaskEngineOptions, TaskError, type TaskPayload, type TaskResult, type TaskStatus, type TaskStore, type TaskStoreFilter, type WritableLike, agentConfigSchema, aggregateReports, appConfigSchema, authHeaders, buildAgentRegistry, buildChildEnv, buildHello, buildHelloAck, buildPipelineEngine, buildPlanner, buildPlannerContext, buildRoleRegistry, composeTaskText, createAgent, createDefaultChatFn, createMemoryProvider, createProvider, createTaskEngine, decodeMessage, decodeStream, defaultProjectConfigYaml, describeExit, encodeMessage, envelope, expandEnvRefs, extractReportFromText, findConfigFile, isOmniNodeError, isSupportedProtocol, keywords, killTree, loadConfig, logger, newMessageId, parseHello, parsePlanJson, pipelineConfigSchema, pipelineStepConfigSchema, plannerConfigSchema, projectConfigSchema, providerConfigSchema, registryKey, requestJson, requireCompletion, resolveApiKey, resolveEnvPolicy, roleConfigSchema, sanitizeChunk, similar, validateEnvelope, validateWorkingDirectory };
|
|
2568
|
+
export { AgentAdapterRegistry, type AgentConfig, type AgentConfigYaml, type AgentDescriptor, AgentError, type AgentInfo, type AgentInputMode, type AgentIntegrationType, AgentRegistry, type AgentStatus, type AgentTaskInput, type AgentTaskOutput, type AgentToNodeMessage, type AggregateOptions, type AggregatedFinding, type AggregatedRecommendation, type AppConfig, type AppConfigYaml, type ArtifactKind, type ArtifactPayload, type AskedQuestion, type AuditAction, type AuditEvent, type AuditSink, type ChatFn, type ChatMessage, type ChatRequest, type ChatResponse, type ChatRole, type ChatUsage, type CombinedMeta, type CombinedReport, type CombinedReportFilter, type Confidence, ConfigError, ConsoleLogSink, type CreateTaskInput, type CwdValidation, DEFAULT_MAX_OUTPUT_BYTES, type DecodeResult, type DiscoveryResult, type EnvPolicy, type EnvelopeMeta, type ExecutionRecord, type ExtractionMeta, FileAuditLog, FilePipelineRunStore, FilePlanStore, FileReportStore, FileTaskStore, type Finding, type FindingSeverity, type FindingSource, type HelloResult, HeuristicPlanner, type HttpRequestOptions, type HttpResponse, type IAgent, type IAgentAdapter, type IChatProvider, type IMemoryProvider, type IPipelineExecutor, type IPlanner, type IProvider, type JsonDocument, JsonFileStore, type JsonFileStoreOptions, type LoadConfigOptions, LocalMemoryProvider, type LogLevel, type LogSink, Logger, type LoggerOptions, MAX_MESSAGE_BYTES, type MemoryContextQuery, type MemoryEntry, MemoryError, type MemoryProviderConfig, type MemoryQuery, type MemoryScope, MemoryService, type MessageEnvelope, type ModelCapabilities, type ModelFilter, type ModelInfo, ModelPlanner, ModelRegistry, type ModelStatus, type NodeToAgentMessage, OMNINODE_VERSION, OPENAI_COMPATIBLE_TYPES, type OmniHilbrasConnectionResult, OmniHilbrasProvider, OmniNodeError, type OmniNodeErrorCode, type OmniNodeErrorOptions, OpenAICompatibleProvider, PROTOCOL_V2, type PipelineConfigYaml, type PipelineDefinition, PipelineEngine, type PipelineEngineOptions, PipelineError, type PipelineRun, type PipelineRunAttempt, type PipelineRunFilter, type PipelineRunOptions, type PipelineRunStatus, type PipelineRunStore, type PipelineStep, type PipelineStepCondition, type PipelineStepConfigYaml, type PipelineStepKind, type PipelineStepRun, type Plan, type PlanFilter, type PlanRequest, type PlanStep, type PlanStore, type PlannerConfigYaml, PlannerError, ProcessAgent, ProcessAgentAdapter, type Project, type ProjectConfigYaml, ProjectStores, type ProtocolAgentToNodeType, ProtocolDecoder, type ProtocolEnvelope, ProtocolError, type ProtocolMessageType, type ProtocolNodeToAgentType, ProtocolSession, type ProtocolViolation, type ProtocolViolationCode, type ProviderConfig, type ProviderConfigYaml, ProviderError, type ProviderHealth, type ProviderStatus, type ProviderType, type QuestionPayload, type QuestionResponder, type RememberaConfig, RememberaMemoryProvider, type Report, type ReportFilter, type ReportPayload, ReportService, type ReportStore, type RoleConfigYaml, type RoleDefinition, RoleRegistry, type RunPipelineOptions, SUPPORTED_PROTOCOL_VERSIONS, type SessionIds, TERMINAL_TASK_STATUSES, type Task, type TaskContext, TaskEngine, type TaskEngineOptions, TaskError, type TaskPayload, type TaskResult, type TaskStatus, type TaskStore, type TaskStoreFilter, type WritableLike, agentConfigSchema, aggregateReports, appConfigSchema, authHeaders, buildAgentRegistry, buildChildEnv, buildHello, buildHelloAck, buildPipelineEngine, buildPlanner, buildPlannerContext, buildRoleRegistry, composeTaskText, createAgent, createDefaultChatFn, createMemoryProvider, createProvider, createTaskEngine, decodeMessage, decodeStream, defaultProjectConfigYaml, describeExit, encodeMessage, envelope, expandEnvRefs, extractReportFromText, findConfigFile, isOmniNodeError, isSupportedProtocol, keywords, killTree, loadConfig, logger, newMessageId, parseHello, parsePlanJson, pipelineConfigSchema, pipelineStepConfigSchema, plannerConfigSchema, projectConfigSchema, providerConfigSchema, registryKey, requestJson, requireCompletion, resolveApiKey, resolveEnvPolicy, roleConfigSchema, sanitizeChunk, similar, validateEnvelope, validateWorkingDirectory };
|
package/dist/index.js
CHANGED
|
@@ -1430,7 +1430,7 @@ function describeExit(code, signal) {
|
|
|
1430
1430
|
return `Process exited with code ${code}.`;
|
|
1431
1431
|
}
|
|
1432
1432
|
function sanitizeChunk(chunk) {
|
|
1433
|
-
return chunk.toString("utf8").
|
|
1433
|
+
return [...chunk.toString("utf8")].filter((char) => char.charCodeAt(0) !== 0).join("");
|
|
1434
1434
|
}
|
|
1435
1435
|
function normalizeReport(payload, taskId, agentName, index) {
|
|
1436
1436
|
if (payload === null || typeof payload !== "object") return void 0;
|
|
@@ -1777,6 +1777,11 @@ var TaskEngine = class {
|
|
|
1777
1777
|
if (this.options.memory) await this.options.memory.recordTaskOutcome(current);
|
|
1778
1778
|
return current;
|
|
1779
1779
|
}
|
|
1780
|
+
const currentState = await this.options.store.get(current.id);
|
|
1781
|
+
if (currentState?.status === "cancelled") {
|
|
1782
|
+
current = currentState;
|
|
1783
|
+
break;
|
|
1784
|
+
}
|
|
1780
1785
|
const result = {
|
|
1781
1786
|
...output.summary !== void 0 ? { summary: output.summary } : {},
|
|
1782
1787
|
...output.reports !== void 0 && output.reports.length > 0 ? { reports: output.reports } : {},
|
|
@@ -2439,9 +2444,23 @@ var PipelineEngine = class {
|
|
|
2439
2444
|
}
|
|
2440
2445
|
options;
|
|
2441
2446
|
log;
|
|
2447
|
+
/** Runs executing in THIS process — cancellation can terminate them directly. */
|
|
2448
|
+
activeRuns = /* @__PURE__ */ new Map();
|
|
2442
2449
|
get store() {
|
|
2443
2450
|
return this.options.store;
|
|
2444
2451
|
}
|
|
2452
|
+
/**
|
|
2453
|
+
* Saves the run while preserving fields that may be set by another process
|
|
2454
|
+
* (e.g. a cancellation request) — an in-memory snapshot must never clobber
|
|
2455
|
+
* externally requested cancellation (§9.2).
|
|
2456
|
+
*/
|
|
2457
|
+
async persist(run) {
|
|
2458
|
+
const current = await this.options.store.get(run.id);
|
|
2459
|
+
await this.options.store.save({
|
|
2460
|
+
...run,
|
|
2461
|
+
...current?.cancellationRequested === true ? { cancellationRequested: true, cancellationRequestedAt: current.cancellationRequestedAt } : {}
|
|
2462
|
+
});
|
|
2463
|
+
}
|
|
2445
2464
|
/** Structural + semantic validation (§27 Phase 5 — pipeline parser). */
|
|
2446
2465
|
validate(def) {
|
|
2447
2466
|
const ids = /* @__PURE__ */ new Set();
|
|
@@ -2541,18 +2560,44 @@ var PipelineEngine = class {
|
|
|
2541
2560
|
);
|
|
2542
2561
|
}
|
|
2543
2562
|
}
|
|
2563
|
+
if (step.model) {
|
|
2564
|
+
const separator = step.model.indexOf(":");
|
|
2565
|
+
if (separator <= 0 || separator === step.model.length - 1) {
|
|
2566
|
+
throw new PipelineError(
|
|
2567
|
+
"PIPELINE_INVALID",
|
|
2568
|
+
`Step "${step.id}" has an invalid model reference "${step.model}" \u2014 use "provider:model-id".`
|
|
2569
|
+
);
|
|
2570
|
+
}
|
|
2571
|
+
const providerName = step.model.slice(0, separator);
|
|
2572
|
+
if (!this.options.providers.some((p) => p.name === providerName)) {
|
|
2573
|
+
throw new PipelineError(
|
|
2574
|
+
"PIPELINE_INVALID",
|
|
2575
|
+
`Step "${step.id}" uses model "${step.model}" but provider "${providerName}" is not configured.`
|
|
2576
|
+
);
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2544
2579
|
}
|
|
2545
2580
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2546
2581
|
const run = {
|
|
2547
2582
|
id: `run-${Date.now().toString(36)}-${randomBytes4(3).toString("hex")}`,
|
|
2548
2583
|
pipelineId: def.id,
|
|
2584
|
+
attempt: 1,
|
|
2549
2585
|
objective,
|
|
2550
2586
|
status: "running",
|
|
2551
2587
|
startedAt: now,
|
|
2552
2588
|
stepRuns: []
|
|
2553
2589
|
};
|
|
2554
2590
|
await this.options.store.save(run);
|
|
2555
|
-
|
|
2591
|
+
const liveTaskIds = /* @__PURE__ */ new Set();
|
|
2592
|
+
this.activeRuns.set(run.id, {
|
|
2593
|
+
taskIds: liveTaskIds,
|
|
2594
|
+
cancelTasks: async () => {
|
|
2595
|
+
for (const taskId of liveTaskIds) {
|
|
2596
|
+
await this.options.tasks.cancel(taskId).catch(() => void 0);
|
|
2597
|
+
}
|
|
2598
|
+
}
|
|
2599
|
+
});
|
|
2600
|
+
this.log.info(`Running pipeline ${def.id} as ${run.id} (attempt ${run.attempt}).`);
|
|
2556
2601
|
await this.options.audit?.record({
|
|
2557
2602
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2558
2603
|
action: "pipeline.run.started",
|
|
@@ -2564,7 +2609,22 @@ var PipelineEngine = class {
|
|
|
2564
2609
|
const pending = new Set(def.steps.map((s) => s.id));
|
|
2565
2610
|
const contextParts = [];
|
|
2566
2611
|
const allReports = [];
|
|
2612
|
+
let cancelled = false;
|
|
2567
2613
|
while (pending.size > 0) {
|
|
2614
|
+
const persisted = await this.options.store.get(run.id);
|
|
2615
|
+
if (persisted?.cancellationRequested === true) {
|
|
2616
|
+
cancelled = true;
|
|
2617
|
+
run.cancellationRequested = true;
|
|
2618
|
+
run.cancellationRequestedAt = persisted.cancellationRequestedAt;
|
|
2619
|
+
await this.activeRuns.get(run.id)?.cancelTasks();
|
|
2620
|
+
for (const step of def.steps.filter((s) => pending.has(s.id))) {
|
|
2621
|
+
const stepRun = { stepId: step.id, status: "cancelled" };
|
|
2622
|
+
run.stepRuns.push(stepRun);
|
|
2623
|
+
options.onStep?.(stepRun);
|
|
2624
|
+
}
|
|
2625
|
+
pending.clear();
|
|
2626
|
+
break;
|
|
2627
|
+
}
|
|
2568
2628
|
const ready = def.steps.filter(
|
|
2569
2629
|
(step) => pending.has(step.id) && (deps.get(step.id) ?? []).every((d) => outcomes.has(d))
|
|
2570
2630
|
);
|
|
@@ -2581,7 +2641,8 @@ var PipelineEngine = class {
|
|
|
2581
2641
|
...role ? { role } : {},
|
|
2582
2642
|
combinedContext: contextParts.join("\n\n"),
|
|
2583
2643
|
reports: [...allReports],
|
|
2584
|
-
pipelineRunId: run.id
|
|
2644
|
+
pipelineRunId: run.id,
|
|
2645
|
+
runId: run.id
|
|
2585
2646
|
};
|
|
2586
2647
|
return this.executeStep(step, ctx);
|
|
2587
2648
|
})
|
|
@@ -2598,6 +2659,8 @@ ${contribution}`);
|
|
|
2598
2659
|
}
|
|
2599
2660
|
const stepRun = {
|
|
2600
2661
|
stepId: step.id,
|
|
2662
|
+
attempt: outcome.attempt ?? 1,
|
|
2663
|
+
...outcome.executionIds && outcome.executionIds.length > 0 ? { executionIds: outcome.executionIds } : {},
|
|
2601
2664
|
status: outcome.status === "skipped" ? "cancelled" : outcome.status === "failed" ? "failed" : outcome.status === "partial" ? "partially_completed" : "completed",
|
|
2602
2665
|
...outcome.taskIds.length > 0 ? { taskIds: outcome.taskIds } : {},
|
|
2603
2666
|
...outcome.planId !== void 0 ? { planId: outcome.planId } : {},
|
|
@@ -2607,12 +2670,12 @@ ${contribution}`);
|
|
|
2607
2670
|
options.onStep?.(stepRun);
|
|
2608
2671
|
});
|
|
2609
2672
|
run.reports = [...allReports];
|
|
2610
|
-
await this.
|
|
2673
|
+
await this.persist(run);
|
|
2611
2674
|
}
|
|
2612
2675
|
const allOutcomes = [...outcomes.values()];
|
|
2613
|
-
const failed = allOutcomes.some((o) => o.status === "failed");
|
|
2614
|
-
const partial = !failed && allOutcomes.some((o) => o.status === "partial");
|
|
2615
|
-
const finalStatus = failed ? "failed" : partial ? "partial" : "completed";
|
|
2676
|
+
const failed = !cancelled && allOutcomes.some((o) => o.status === "failed");
|
|
2677
|
+
const partial = !cancelled && !failed && allOutcomes.some((o) => o.status === "partial");
|
|
2678
|
+
const finalStatus = cancelled ? "cancelled" : failed ? "failed" : partial ? "partial" : "completed";
|
|
2616
2679
|
const planId = [...outcomes.values()].find((o) => o.planId !== void 0)?.planId;
|
|
2617
2680
|
let resultSummary;
|
|
2618
2681
|
for (let i = def.steps.length - 1; i >= 0; i -= 1) {
|
|
@@ -2640,16 +2703,19 @@ ${contribution}`);
|
|
|
2640
2703
|
run.reports = collected;
|
|
2641
2704
|
}
|
|
2642
2705
|
}
|
|
2706
|
+
const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2707
|
+
this.activeRuns.delete(run.id);
|
|
2643
2708
|
const finished = {
|
|
2644
2709
|
...run,
|
|
2645
2710
|
status: finalStatus,
|
|
2646
|
-
finishedAt
|
|
2711
|
+
finishedAt,
|
|
2712
|
+
attempts: [...run.attempts ?? [], { attempt: run.attempt, startedAt: run.startedAt ?? finishedAt, finishedAt, status: finalStatus }],
|
|
2647
2713
|
...run.reports !== void 0 && run.reports.length > 0 ? { reports: run.reports } : {},
|
|
2648
2714
|
...combinedReportId !== void 0 ? { combinedReportId } : {},
|
|
2649
2715
|
...planId !== void 0 ? { planId } : {},
|
|
2650
2716
|
...resultSummary !== void 0 ? { resultSummary } : {}
|
|
2651
2717
|
};
|
|
2652
|
-
await this.
|
|
2718
|
+
await this.persist(finished);
|
|
2653
2719
|
this.log.info(`Pipeline ${def.id} finished: ${finalStatus}.`);
|
|
2654
2720
|
await this.options.audit?.record({
|
|
2655
2721
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -2659,6 +2725,23 @@ ${contribution}`);
|
|
|
2659
2725
|
});
|
|
2660
2726
|
return finished;
|
|
2661
2727
|
}
|
|
2728
|
+
/** First-class cancellation (§9.2): requests cancellation and terminates
|
|
2729
|
+
* tasks that are running in this process immediately. */
|
|
2730
|
+
async cancel(runId) {
|
|
2731
|
+
const run = await this.options.store.get(runId);
|
|
2732
|
+
if (!run) {
|
|
2733
|
+
throw new PipelineError("PIPELINE_NOT_FOUND", `Pipeline run "${runId}" does not exist.`);
|
|
2734
|
+
}
|
|
2735
|
+
await this.options.store.save({
|
|
2736
|
+
...run,
|
|
2737
|
+
cancellationRequested: true,
|
|
2738
|
+
cancellationRequestedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2739
|
+
});
|
|
2740
|
+
const active = this.activeRuns.get(runId);
|
|
2741
|
+
if (active) {
|
|
2742
|
+
await active.cancelTasks();
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2662
2745
|
async get(runId) {
|
|
2663
2746
|
return this.options.store.get(runId);
|
|
2664
2747
|
}
|
|
@@ -2682,9 +2765,16 @@ ${contribution}`);
|
|
|
2682
2765
|
this.log.warn(`Step "${step.id}" failed \u2014 retry ${attempt}/${retries}.`);
|
|
2683
2766
|
}
|
|
2684
2767
|
last = await this.executeStepOnce(step, ctx);
|
|
2685
|
-
if (last.status !== "failed") return last;
|
|
2768
|
+
if (last.status !== "failed") return { ...last, attempt: attempt + 1 };
|
|
2686
2769
|
}
|
|
2687
|
-
return last;
|
|
2770
|
+
return { ...last, attempt: retries + 1 };
|
|
2771
|
+
}
|
|
2772
|
+
/** Registers tasks created for a step as live, so cancellation can terminate them (§9.2). */
|
|
2773
|
+
trackLiveTasks(runId, taskIds) {
|
|
2774
|
+
if (!runId) return;
|
|
2775
|
+
const active = this.activeRuns.get(runId);
|
|
2776
|
+
if (!active) return;
|
|
2777
|
+
for (const id of taskIds) active.taskIds.add(id);
|
|
2688
2778
|
}
|
|
2689
2779
|
async executeStepOnce(step, ctx) {
|
|
2690
2780
|
switch (step.kind) {
|
|
@@ -2717,7 +2807,9 @@ ${contribution}`);
|
|
|
2717
2807
|
})
|
|
2718
2808
|
)
|
|
2719
2809
|
);
|
|
2810
|
+
this.trackLiveTasks(ctx.runId, created.map((t) => t.id));
|
|
2720
2811
|
const results = await Promise.all(created.map((task) => this.options.tasks.run(task.id)));
|
|
2812
|
+
const executionIds = results.map((r) => r.executions?.at(-1)?.executionId).filter((id) => id !== void 0);
|
|
2721
2813
|
const completedTasks = results.filter((r) => r.status === "completed");
|
|
2722
2814
|
const failedTasks = results.filter((r) => r.status !== "completed");
|
|
2723
2815
|
const lines = results.map((result, index) => {
|
|
@@ -2740,7 +2832,13 @@ ${contribution}`);
|
|
|
2740
2832
|
reports
|
|
2741
2833
|
};
|
|
2742
2834
|
}
|
|
2743
|
-
return {
|
|
2835
|
+
return {
|
|
2836
|
+
status: "completed",
|
|
2837
|
+
summary,
|
|
2838
|
+
taskIds: created.map((t) => t.id),
|
|
2839
|
+
...executionIds.length > 0 ? { executionIds } : {},
|
|
2840
|
+
reports
|
|
2841
|
+
};
|
|
2744
2842
|
}
|
|
2745
2843
|
async runSingle(step, ctx, agentName) {
|
|
2746
2844
|
const task = await this.options.tasks.create({
|
|
@@ -2749,6 +2847,7 @@ ${contribution}`);
|
|
|
2749
2847
|
...ctx.role ? { role: ctx.role.id } : {},
|
|
2750
2848
|
...ctx.combinedContext.length > 0 ? { context: { background: ctx.combinedContext } } : {}
|
|
2751
2849
|
});
|
|
2850
|
+
this.trackLiveTasks(ctx.runId, [task.id]);
|
|
2752
2851
|
const result = await this.options.tasks.run(task.id);
|
|
2753
2852
|
if (result.status !== "completed") {
|
|
2754
2853
|
return {
|
|
@@ -3226,7 +3325,7 @@ var ProjectStores = class {
|
|
|
3226
3325
|
};
|
|
3227
3326
|
|
|
3228
3327
|
// src/version.ts
|
|
3229
|
-
var OMNINODE_VERSION = "2.0.0-alpha.
|
|
3328
|
+
var OMNINODE_VERSION = "2.0.0-alpha.5";
|
|
3230
3329
|
export {
|
|
3231
3330
|
AgentAdapterRegistry,
|
|
3232
3331
|
AgentError,
|