@hilbras/omninode 0.4.0 → 0.5.1
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 +21 -3
- package/dist/cli/index.js +325 -7
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +79 -5
- package/dist/index.js +241 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -184,6 +184,7 @@ interface ModelInfo {
|
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
/** Task system: every operation becomes a Task (§13). */
|
|
187
|
+
|
|
187
188
|
type TaskStatus = "created" | "queued" | "running" | "waiting" | "completed" | "failed" | "cancelled";
|
|
188
189
|
interface TaskContext {
|
|
189
190
|
project?: string;
|
|
@@ -198,6 +199,8 @@ interface TaskResult {
|
|
|
198
199
|
summary?: string;
|
|
199
200
|
artifacts?: string[];
|
|
200
201
|
reportId?: string;
|
|
202
|
+
/** Structured reports produced by protocol-mode agents (Phase 6 builds on this). */
|
|
203
|
+
reports?: Report[];
|
|
201
204
|
error?: string;
|
|
202
205
|
finishedAt?: string;
|
|
203
206
|
}
|
|
@@ -397,7 +400,7 @@ interface IChatProvider extends IProvider {
|
|
|
397
400
|
}
|
|
398
401
|
|
|
399
402
|
/** Typed error hierarchy shared across the whole codebase (§4.1 — error model). */
|
|
400
|
-
type OmniNodeErrorCode = "CONFIG_NOT_FOUND" | "CONFIG_INVALID" | "PROVIDER_NOT_FOUND" | "PROVIDER_UNAVAILABLE" | "PROVIDER_AUTH_FAILED" | "MODEL_NOT_FOUND" | "AGENT_NOT_FOUND" | "AGENT_FAILED" | "AGENT_TIMEOUT" | "TASK_INVALID" | "TASK_FAILED" | "PIPELINE_INVALID" | "PIPELINE_FAILED" | "PROTOCOL_VIOLATION" | "MEMORY_UNAVAILABLE" | "NOT_IMPLEMENTED" | "CLI_USAGE" | "INTERNAL";
|
|
403
|
+
type OmniNodeErrorCode = "CONFIG_NOT_FOUND" | "CONFIG_INVALID" | "PROVIDER_NOT_FOUND" | "PROVIDER_UNAVAILABLE" | "PROVIDER_AUTH_FAILED" | "MODEL_NOT_FOUND" | "AGENT_NOT_FOUND" | "AGENT_FAILED" | "AGENT_TIMEOUT" | "TASK_INVALID" | "TASK_NOT_FOUND" | "TASK_FAILED" | "PIPELINE_INVALID" | "PIPELINE_FAILED" | "PROTOCOL_VIOLATION" | "MEMORY_UNAVAILABLE" | "NOT_IMPLEMENTED" | "CLI_USAGE" | "INTERNAL";
|
|
401
404
|
interface OmniNodeErrorOptions {
|
|
402
405
|
cause?: unknown;
|
|
403
406
|
details?: Record<string, unknown>;
|
|
@@ -417,7 +420,7 @@ declare class AgentError extends OmniNodeError {
|
|
|
417
420
|
constructor(code: "AGENT_NOT_FOUND" | "AGENT_FAILED" | "AGENT_TIMEOUT", message: string, options?: OmniNodeErrorOptions);
|
|
418
421
|
}
|
|
419
422
|
declare class TaskError extends OmniNodeError {
|
|
420
|
-
constructor(code: "TASK_INVALID" | "TASK_FAILED", message: string, options?: OmniNodeErrorOptions);
|
|
423
|
+
constructor(code: "TASK_INVALID" | "TASK_NOT_FOUND" | "TASK_FAILED", message: string, options?: OmniNodeErrorOptions);
|
|
421
424
|
}
|
|
422
425
|
declare class PipelineError extends OmniNodeError {
|
|
423
426
|
constructor(code: "PIPELINE_INVALID" | "PIPELINE_FAILED", message: string, options?: OmniNodeErrorOptions);
|
|
@@ -1099,8 +1102,6 @@ declare class ProcessAgent implements IAgent {
|
|
|
1099
1102
|
runningTaskIds(): string[];
|
|
1100
1103
|
}
|
|
1101
1104
|
|
|
1102
|
-
declare function createAgent(config: AgentConfig): IAgent;
|
|
1103
|
-
|
|
1104
1105
|
/** Agent registry (§10): the set of agents connected to OmniNode. */
|
|
1105
1106
|
|
|
1106
1107
|
declare class AgentRegistry {
|
|
@@ -1110,6 +1111,79 @@ declare class AgentRegistry {
|
|
|
1110
1111
|
list(): IAgent[];
|
|
1111
1112
|
}
|
|
1112
1113
|
|
|
1114
|
+
/**
|
|
1115
|
+
* Agent factory (§9–§10): builds adapter instances from configuration.
|
|
1116
|
+
* "cli" agent configs are mapped to the process integration by the loader.
|
|
1117
|
+
*/
|
|
1118
|
+
|
|
1119
|
+
declare function createAgent(config: AgentConfig): IAgent;
|
|
1120
|
+
/** Builds an agent registry from the project configuration, skipping agents that fail to construct. */
|
|
1121
|
+
declare function buildAgentRegistry(config: AppConfig, log?: Logger): AgentRegistry;
|
|
1122
|
+
|
|
1123
|
+
/** Role registry (§11): the set of roles available for task assignment. */
|
|
1124
|
+
|
|
1125
|
+
declare class RoleRegistry {
|
|
1126
|
+
private readonly roles;
|
|
1127
|
+
register(role: RoleDefinition): void;
|
|
1128
|
+
registerAll(roles: RoleDefinition[]): void;
|
|
1129
|
+
get(id: string): RoleDefinition | undefined;
|
|
1130
|
+
list(): RoleDefinition[];
|
|
1131
|
+
}
|
|
1132
|
+
/** Builds a role registry from the project configuration. */
|
|
1133
|
+
declare function buildRoleRegistry(config: AppConfig): RoleRegistry;
|
|
1134
|
+
|
|
1135
|
+
interface TaskStoreFilter {
|
|
1136
|
+
status?: TaskStatus;
|
|
1137
|
+
project?: string;
|
|
1138
|
+
}
|
|
1139
|
+
interface TaskStore {
|
|
1140
|
+
save(task: Task): Promise<void>;
|
|
1141
|
+
get(id: string): Promise<Task | undefined>;
|
|
1142
|
+
list(filter?: TaskStoreFilter): Promise<Task[]>;
|
|
1143
|
+
}
|
|
1144
|
+
declare class FileTaskStore implements TaskStore {
|
|
1145
|
+
private readonly filePath;
|
|
1146
|
+
constructor(directory?: string);
|
|
1147
|
+
save(task: Task): Promise<void>;
|
|
1148
|
+
get(id: string): Promise<Task | undefined>;
|
|
1149
|
+
list(filter?: TaskStoreFilter): Promise<Task[]>;
|
|
1150
|
+
private load;
|
|
1151
|
+
private write;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
interface CreateTaskInput {
|
|
1155
|
+
objective: string;
|
|
1156
|
+
project?: string;
|
|
1157
|
+
role?: string;
|
|
1158
|
+
agent?: string;
|
|
1159
|
+
context?: TaskContext;
|
|
1160
|
+
}
|
|
1161
|
+
interface TaskEngineOptions {
|
|
1162
|
+
agents: AgentRegistry;
|
|
1163
|
+
roles: RoleRegistry;
|
|
1164
|
+
store: TaskStore;
|
|
1165
|
+
log?: Logger;
|
|
1166
|
+
}
|
|
1167
|
+
declare class TaskEngine {
|
|
1168
|
+
private readonly options;
|
|
1169
|
+
private readonly log;
|
|
1170
|
+
constructor(options: TaskEngineOptions);
|
|
1171
|
+
get store(): TaskStore;
|
|
1172
|
+
create(input: CreateTaskInput): Promise<Task>;
|
|
1173
|
+
queue(id: string): Promise<Task>;
|
|
1174
|
+
/** Runs the task through its assigned agent and records the result. */
|
|
1175
|
+
run(id: string): Promise<Task>;
|
|
1176
|
+
cancel(id: string): Promise<Task>;
|
|
1177
|
+
get(id: string): Promise<Task | undefined>;
|
|
1178
|
+
list(filter?: TaskStoreFilter): Promise<Task[]>;
|
|
1179
|
+
private mustGet;
|
|
1180
|
+
private transition;
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
/** Assembles a TaskEngine from the project configuration (local-first defaults). */
|
|
1184
|
+
|
|
1185
|
+
declare function createTaskEngine(config: AppConfig, log?: Logger, directory?: string): TaskEngine;
|
|
1186
|
+
|
|
1113
1187
|
declare const OMNINODE_VERSION = "0.4.0";
|
|
1114
1188
|
|
|
1115
|
-
export { type AgentConfig, type AgentConfigYaml, AgentError, type AgentInfo, type AgentInputMode, type AgentIntegrationType, AgentRegistry, type AgentStatus, type AgentTaskInput, type AgentTaskOutput, type AgentToNodeMessage, type AppConfig, type AppConfigYaml, type ChatMessage, type ChatRequest, type ChatResponse, type ChatRole, type ChatUsage, type Confidence, ConfigError, ConsoleLogSink, type DiscoveryResult, type EnvelopeMeta, type Finding, type FindingSeverity, type HttpRequestOptions, type HttpResponse, type IAgent, type IChatProvider, type IMemoryProvider, type IProvider, type LoadConfigOptions, type LogLevel, type LogSink, Logger, type LoggerOptions, type MemoryEntry, MemoryError, type MemoryQuery, type MemoryScope, type MessageEnvelope, type ModelCapabilities, type ModelFilter, type ModelInfo, ModelRegistry, type ModelStatus, type NodeToAgentMessage, OMNINODE_VERSION, OPENAI_COMPATIBLE_TYPES, type OmniHilbrasConnectionResult, OmniHilbrasProvider, OmniNodeError, type OmniNodeErrorCode, type OmniNodeErrorOptions, OpenAICompatibleProvider, type PipelineDefinition, PipelineError, type PipelineRun, type PipelineRunStatus, type PipelineStep, type PipelineStepCondition, type PipelineStepKind, type PipelineStepRun, ProcessAgent, type Project, type ProjectConfigYaml, ProtocolError, type ProviderConfig, type ProviderConfigYaml, ProviderError, type ProviderHealth, type ProviderStatus, type ProviderType, type Report, type RoleConfigYaml, type RoleDefinition, type Task, type TaskContext, TaskError, type TaskResult, type TaskStatus, type WritableLike, agentConfigSchema, appConfigSchema, authHeaders, composeTaskText, createAgent, createProvider, defaultProjectConfigYaml, expandEnvRefs, findConfigFile, isOmniNodeError, loadConfig, logger, projectConfigSchema, providerConfigSchema, registryKey, requestJson, resolveApiKey, roleConfigSchema };
|
|
1189
|
+
export { type AgentConfig, type AgentConfigYaml, AgentError, type AgentInfo, type AgentInputMode, type AgentIntegrationType, AgentRegistry, type AgentStatus, type AgentTaskInput, type AgentTaskOutput, type AgentToNodeMessage, type AppConfig, type AppConfigYaml, type ChatMessage, type ChatRequest, type ChatResponse, type ChatRole, type ChatUsage, type Confidence, ConfigError, ConsoleLogSink, type CreateTaskInput, type DiscoveryResult, type EnvelopeMeta, FileTaskStore, type Finding, type FindingSeverity, type HttpRequestOptions, type HttpResponse, type IAgent, type IChatProvider, type IMemoryProvider, type IProvider, type LoadConfigOptions, type LogLevel, type LogSink, Logger, type LoggerOptions, type MemoryEntry, MemoryError, type MemoryQuery, type MemoryScope, type MessageEnvelope, type ModelCapabilities, type ModelFilter, type ModelInfo, ModelRegistry, type ModelStatus, type NodeToAgentMessage, OMNINODE_VERSION, OPENAI_COMPATIBLE_TYPES, type OmniHilbrasConnectionResult, OmniHilbrasProvider, OmniNodeError, type OmniNodeErrorCode, type OmniNodeErrorOptions, OpenAICompatibleProvider, type PipelineDefinition, PipelineError, type PipelineRun, type PipelineRunStatus, type PipelineStep, type PipelineStepCondition, type PipelineStepKind, type PipelineStepRun, ProcessAgent, type Project, type ProjectConfigYaml, ProtocolError, type ProviderConfig, type ProviderConfigYaml, ProviderError, type ProviderHealth, type ProviderStatus, type ProviderType, type Report, type RoleConfigYaml, type RoleDefinition, RoleRegistry, type Task, type TaskContext, TaskEngine, type TaskEngineOptions, TaskError, type TaskResult, type TaskStatus, type TaskStore, type TaskStoreFilter, type WritableLike, agentConfigSchema, appConfigSchema, authHeaders, buildAgentRegistry, buildRoleRegistry, composeTaskText, createAgent, createProvider, createTaskEngine, defaultProjectConfigYaml, expandEnvRefs, findConfigFile, isOmniNodeError, loadConfig, logger, projectConfigSchema, providerConfigSchema, registryKey, requestJson, resolveApiKey, roleConfigSchema };
|
package/dist/index.js
CHANGED
|
@@ -846,6 +846,20 @@ function firstLine(text, maxLength = 200) {
|
|
|
846
846
|
return line.length > maxLength ? `${line.slice(0, maxLength)}\u2026` : line;
|
|
847
847
|
}
|
|
848
848
|
|
|
849
|
+
// src/agents/registry.ts
|
|
850
|
+
var AgentRegistry = class {
|
|
851
|
+
agents = /* @__PURE__ */ new Map();
|
|
852
|
+
register(agent) {
|
|
853
|
+
this.agents.set(agent.info.name, agent);
|
|
854
|
+
}
|
|
855
|
+
get(name) {
|
|
856
|
+
return this.agents.get(name);
|
|
857
|
+
}
|
|
858
|
+
list() {
|
|
859
|
+
return [...this.agents.values()].sort((a, b) => a.info.name.localeCompare(b.info.name));
|
|
860
|
+
}
|
|
861
|
+
};
|
|
862
|
+
|
|
849
863
|
// src/agents/factory.ts
|
|
850
864
|
function createAgent(config) {
|
|
851
865
|
if (config.integration === "process") {
|
|
@@ -859,20 +873,233 @@ function createAgent(config) {
|
|
|
859
873
|
}
|
|
860
874
|
throw new OmniNodeError("NOT_IMPLEMENTED", `Agent integration "${config.integration}" has no adapter yet.`);
|
|
861
875
|
}
|
|
876
|
+
function buildAgentRegistry(config, log = logger) {
|
|
877
|
+
const registry = new AgentRegistry();
|
|
878
|
+
for (const agentConfig of config.project.agents) {
|
|
879
|
+
try {
|
|
880
|
+
registry.register(createAgent(agentConfig));
|
|
881
|
+
} catch (error) {
|
|
882
|
+
log.warn(
|
|
883
|
+
`Skipping agent "${agentConfig.name}": ${error instanceof Error ? error.message : String(error)}`
|
|
884
|
+
);
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
return registry;
|
|
888
|
+
}
|
|
862
889
|
|
|
863
|
-
// src/
|
|
864
|
-
var
|
|
865
|
-
|
|
866
|
-
register(
|
|
867
|
-
this.
|
|
890
|
+
// src/roles/index.ts
|
|
891
|
+
var RoleRegistry = class {
|
|
892
|
+
roles = /* @__PURE__ */ new Map();
|
|
893
|
+
register(role) {
|
|
894
|
+
this.roles.set(role.id, role);
|
|
868
895
|
}
|
|
869
|
-
|
|
870
|
-
|
|
896
|
+
registerAll(roles) {
|
|
897
|
+
for (const role of roles) this.register(role);
|
|
898
|
+
}
|
|
899
|
+
get(id) {
|
|
900
|
+
return this.roles.get(id);
|
|
871
901
|
}
|
|
872
902
|
list() {
|
|
873
|
-
return [...this.
|
|
903
|
+
return [...this.roles.values()].sort((a, b) => a.id.localeCompare(b.id));
|
|
904
|
+
}
|
|
905
|
+
};
|
|
906
|
+
function buildRoleRegistry(config) {
|
|
907
|
+
const registry = new RoleRegistry();
|
|
908
|
+
registry.registerAll(config.project.roles);
|
|
909
|
+
return registry;
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
// src/tasks/store.ts
|
|
913
|
+
import { mkdir, readFile, rename, writeFile } from "fs/promises";
|
|
914
|
+
import { dirname } from "path";
|
|
915
|
+
var FileTaskStore = class {
|
|
916
|
+
filePath;
|
|
917
|
+
constructor(directory = `${process.cwd()}/.omninode`) {
|
|
918
|
+
this.filePath = `${directory}/tasks.json`;
|
|
919
|
+
}
|
|
920
|
+
async save(task) {
|
|
921
|
+
const tasks = await this.load();
|
|
922
|
+
const index = tasks.findIndex((t) => t.id === task.id);
|
|
923
|
+
if (index >= 0) tasks[index] = task;
|
|
924
|
+
else tasks.push(task);
|
|
925
|
+
await this.write(tasks);
|
|
926
|
+
}
|
|
927
|
+
async get(id) {
|
|
928
|
+
const tasks = await this.load();
|
|
929
|
+
return tasks.find((t) => t.id === id);
|
|
930
|
+
}
|
|
931
|
+
async list(filter = {}) {
|
|
932
|
+
const tasks = await this.load();
|
|
933
|
+
return tasks.filter((task) => filter.status ? task.status === filter.status : true).filter((task) => filter.project ? task.project === filter.project : true).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
934
|
+
}
|
|
935
|
+
async load() {
|
|
936
|
+
try {
|
|
937
|
+
const raw = await readFile(this.filePath, "utf8");
|
|
938
|
+
const parsed = JSON.parse(raw);
|
|
939
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
940
|
+
} catch {
|
|
941
|
+
return [];
|
|
942
|
+
}
|
|
874
943
|
}
|
|
944
|
+
async write(tasks) {
|
|
945
|
+
const tmp = `${this.filePath}.tmp`;
|
|
946
|
+
await mkdir(dirname(this.filePath), { recursive: true });
|
|
947
|
+
await writeFile(tmp, `${JSON.stringify(tasks, null, 2)}
|
|
948
|
+
`, "utf8");
|
|
949
|
+
await rename(tmp, this.filePath);
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
|
|
953
|
+
// src/tasks/engine.ts
|
|
954
|
+
import { randomBytes } from "crypto";
|
|
955
|
+
var ALLOWED_TRANSITIONS = {
|
|
956
|
+
created: ["queued", "running", "cancelled"],
|
|
957
|
+
queued: ["running", "cancelled"],
|
|
958
|
+
running: ["completed", "failed", "cancelled"],
|
|
959
|
+
waiting: ["running", "cancelled"],
|
|
960
|
+
completed: [],
|
|
961
|
+
failed: [],
|
|
962
|
+
cancelled: []
|
|
875
963
|
};
|
|
964
|
+
var TaskEngine = class {
|
|
965
|
+
constructor(options) {
|
|
966
|
+
this.options = options;
|
|
967
|
+
this.log = (options.log ?? logger).child({ component: "tasks" });
|
|
968
|
+
}
|
|
969
|
+
options;
|
|
970
|
+
log;
|
|
971
|
+
get store() {
|
|
972
|
+
return this.options.store;
|
|
973
|
+
}
|
|
974
|
+
async create(input) {
|
|
975
|
+
if (!input.objective || input.objective.trim().length === 0) {
|
|
976
|
+
throw new TaskError("TASK_INVALID", "Task objective must not be empty.");
|
|
977
|
+
}
|
|
978
|
+
if (input.role && !this.options.roles.get(input.role)) {
|
|
979
|
+
throw new TaskError(
|
|
980
|
+
"TASK_INVALID",
|
|
981
|
+
`Role "${input.role}" is not defined. Add it under project.roles in omninode.yaml.`
|
|
982
|
+
);
|
|
983
|
+
}
|
|
984
|
+
if (input.agent && !this.options.agents.get(input.agent)) {
|
|
985
|
+
throw new TaskError(
|
|
986
|
+
"TASK_INVALID",
|
|
987
|
+
`Agent "${input.agent}" is not registered. Add it with \`omninode agent add\`.`
|
|
988
|
+
);
|
|
989
|
+
}
|
|
990
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
991
|
+
const task = {
|
|
992
|
+
id: generateTaskId(),
|
|
993
|
+
objective: input.objective.trim(),
|
|
994
|
+
status: "created",
|
|
995
|
+
createdAt: now,
|
|
996
|
+
updatedAt: now,
|
|
997
|
+
...input.project !== void 0 ? { project: input.project } : {},
|
|
998
|
+
...input.role !== void 0 ? { role: input.role } : {},
|
|
999
|
+
...input.agent !== void 0 ? { agent: input.agent } : {},
|
|
1000
|
+
...input.context !== void 0 ? { context: input.context } : {}
|
|
1001
|
+
};
|
|
1002
|
+
await this.options.store.save(task);
|
|
1003
|
+
this.log.info(`Created task ${task.id}.`);
|
|
1004
|
+
return task;
|
|
1005
|
+
}
|
|
1006
|
+
async queue(id) {
|
|
1007
|
+
const task = await this.mustGet(id);
|
|
1008
|
+
return this.transition(task, "queued");
|
|
1009
|
+
}
|
|
1010
|
+
/** Runs the task through its assigned agent and records the result. */
|
|
1011
|
+
async run(id) {
|
|
1012
|
+
const task = await this.mustGet(id);
|
|
1013
|
+
if (task.status !== "created" && task.status !== "queued") {
|
|
1014
|
+
throw new TaskError("TASK_INVALID", `Task ${id} is "${task.status}" and cannot be run.`);
|
|
1015
|
+
}
|
|
1016
|
+
if (!task.agent) {
|
|
1017
|
+
throw new TaskError("TASK_INVALID", `Task ${id} has no agent assigned. Re-create it with --agent.`);
|
|
1018
|
+
}
|
|
1019
|
+
const agent = this.options.agents.get(task.agent);
|
|
1020
|
+
if (!agent) {
|
|
1021
|
+
throw new TaskError("TASK_INVALID", `Agent "${task.agent}" is not registered anymore.`);
|
|
1022
|
+
}
|
|
1023
|
+
const role = task.role ? this.options.roles.get(task.role) : void 0;
|
|
1024
|
+
const running = await this.transition(task, "running");
|
|
1025
|
+
this.log.info(`Running task ${task.id} on agent "${task.agent}".`);
|
|
1026
|
+
let output;
|
|
1027
|
+
try {
|
|
1028
|
+
output = await agent.run({
|
|
1029
|
+
taskId: running.id,
|
|
1030
|
+
objective: running.objective,
|
|
1031
|
+
...role ? { role } : {},
|
|
1032
|
+
...running.context?.background ? { context: running.context.background } : {}
|
|
1033
|
+
});
|
|
1034
|
+
} catch (error) {
|
|
1035
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1036
|
+
this.log.error(`Task ${task.id} failed: ${message}`);
|
|
1037
|
+
return this.transition(running, "failed", {
|
|
1038
|
+
result: { error: message, finishedAt: (/* @__PURE__ */ new Date()).toISOString() }
|
|
1039
|
+
});
|
|
1040
|
+
}
|
|
1041
|
+
const result = {
|
|
1042
|
+
...output.summary !== void 0 ? { summary: output.summary } : {},
|
|
1043
|
+
...output.reports !== void 0 && output.reports.length > 0 ? { reports: output.reports } : {},
|
|
1044
|
+
...output.error !== void 0 ? { error: output.error } : {},
|
|
1045
|
+
finishedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1046
|
+
};
|
|
1047
|
+
const finalStatus = output.status === "completed" ? "completed" : "failed";
|
|
1048
|
+
this.log.info(`Task ${task.id} finished: ${finalStatus}.`);
|
|
1049
|
+
return this.transition(running, finalStatus, { result });
|
|
1050
|
+
}
|
|
1051
|
+
async cancel(id) {
|
|
1052
|
+
const task = await this.mustGet(id);
|
|
1053
|
+
if (!ALLOWED_TRANSITIONS[task.status].includes("cancelled")) {
|
|
1054
|
+
throw new TaskError("TASK_INVALID", `Task ${id} is "${task.status}" and cannot be cancelled.`);
|
|
1055
|
+
}
|
|
1056
|
+
if (task.agent) {
|
|
1057
|
+
const agent = this.options.agents.get(task.agent);
|
|
1058
|
+
await agent?.cancel?.(task.id);
|
|
1059
|
+
}
|
|
1060
|
+
return this.transition(task, "cancelled");
|
|
1061
|
+
}
|
|
1062
|
+
async get(id) {
|
|
1063
|
+
return this.options.store.get(id);
|
|
1064
|
+
}
|
|
1065
|
+
async list(filter) {
|
|
1066
|
+
return this.options.store.list(filter);
|
|
1067
|
+
}
|
|
1068
|
+
async mustGet(id) {
|
|
1069
|
+
const task = await this.options.store.get(id);
|
|
1070
|
+
if (!task) {
|
|
1071
|
+
throw new TaskError("TASK_NOT_FOUND", `Task "${id}" does not exist in this project's task store.`);
|
|
1072
|
+
}
|
|
1073
|
+
return task;
|
|
1074
|
+
}
|
|
1075
|
+
async transition(task, to, extra = {}) {
|
|
1076
|
+
const allowed = ALLOWED_TRANSITIONS[task.status] ?? [];
|
|
1077
|
+
if (!allowed.includes(to)) {
|
|
1078
|
+
throw new TaskError("TASK_INVALID", `Task ${task.id} cannot move from "${task.status}" to "${to}".`);
|
|
1079
|
+
}
|
|
1080
|
+
const updated = {
|
|
1081
|
+
...task,
|
|
1082
|
+
status: to,
|
|
1083
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1084
|
+
...extra.result !== void 0 ? { result: { ...task.result, ...extra.result } } : {}
|
|
1085
|
+
};
|
|
1086
|
+
await this.options.store.save(updated);
|
|
1087
|
+
return updated;
|
|
1088
|
+
}
|
|
1089
|
+
};
|
|
1090
|
+
function generateTaskId() {
|
|
1091
|
+
return `task-${Date.now().toString(36)}-${randomBytes(3).toString("hex")}`;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
// src/tasks/engine-factory.ts
|
|
1095
|
+
function createTaskEngine(config, log = logger, directory) {
|
|
1096
|
+
return new TaskEngine({
|
|
1097
|
+
agents: buildAgentRegistry(config, log),
|
|
1098
|
+
roles: buildRoleRegistry(config),
|
|
1099
|
+
store: new FileTaskStore(directory),
|
|
1100
|
+
log
|
|
1101
|
+
});
|
|
1102
|
+
}
|
|
876
1103
|
|
|
877
1104
|
// src/version.ts
|
|
878
1105
|
var OMNINODE_VERSION = "0.4.0";
|
|
@@ -881,6 +1108,7 @@ export {
|
|
|
881
1108
|
AgentRegistry,
|
|
882
1109
|
ConfigError,
|
|
883
1110
|
ConsoleLogSink,
|
|
1111
|
+
FileTaskStore,
|
|
884
1112
|
Logger,
|
|
885
1113
|
MemoryError,
|
|
886
1114
|
ModelRegistry,
|
|
@@ -893,13 +1121,18 @@ export {
|
|
|
893
1121
|
ProcessAgent,
|
|
894
1122
|
ProtocolError,
|
|
895
1123
|
ProviderError,
|
|
1124
|
+
RoleRegistry,
|
|
1125
|
+
TaskEngine,
|
|
896
1126
|
TaskError,
|
|
897
1127
|
agentConfigSchema,
|
|
898
1128
|
appConfigSchema,
|
|
899
1129
|
authHeaders,
|
|
1130
|
+
buildAgentRegistry,
|
|
1131
|
+
buildRoleRegistry,
|
|
900
1132
|
composeTaskText,
|
|
901
1133
|
createAgent,
|
|
902
1134
|
createProvider,
|
|
1135
|
+
createTaskEngine,
|
|
903
1136
|
defaultProjectConfigYaml,
|
|
904
1137
|
expandEnvRefs,
|
|
905
1138
|
findConfigFile,
|