@hilbras/omninode 2.0.0-alpha.5 → 2.0.0-alpha.6
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 +11 -3
- package/dist/cli/index.js +218 -69
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +87 -5
- package/dist/index.js +228 -68
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -334,14 +334,25 @@ interface ModelCapabilities {
|
|
|
334
334
|
embeddings?: boolean;
|
|
335
335
|
}
|
|
336
336
|
type ModelStatus = "available" | "unavailable" | "deprecated";
|
|
337
|
+
type Modality = "text" | "image" | "audio" | "video" | "embedding";
|
|
338
|
+
/** Model metadata (roadmap §10, Model Metadata). */
|
|
337
339
|
interface ModelInfo {
|
|
338
340
|
/** Name of the provider this model belongs to. */
|
|
339
341
|
provider: string;
|
|
340
342
|
/** Provider-specific model identifier, e.g. "qwen3-coder". */
|
|
341
343
|
id: string;
|
|
342
344
|
displayName?: string;
|
|
345
|
+
/** Human-readable model name reported by the provider, when available. */
|
|
346
|
+
name?: string;
|
|
343
347
|
capabilities?: ModelCapabilities;
|
|
344
348
|
contextWindow?: number;
|
|
349
|
+
inputTypes?: Modality[];
|
|
350
|
+
outputTypes?: Modality[];
|
|
351
|
+
supportsTools?: boolean;
|
|
352
|
+
supportsVision?: boolean;
|
|
353
|
+
supportsReasoning?: boolean;
|
|
354
|
+
supportsStructuredOutput?: boolean;
|
|
355
|
+
supportsStreaming?: boolean;
|
|
345
356
|
status?: ModelStatus;
|
|
346
357
|
metadata?: Record<string, unknown>;
|
|
347
358
|
}
|
|
@@ -650,7 +661,20 @@ interface Project {
|
|
|
650
661
|
|
|
651
662
|
type ProviderType = "openai-compatible" | "omnihilbras" | "openrouter" | "local" | "custom";
|
|
652
663
|
type ProviderHealth = "unknown" | "healthy" | "degraded" | "unreachable";
|
|
664
|
+
/** Declared provider capabilities (roadmap §10, Provider Interface). */
|
|
665
|
+
type ProviderCapability = "chat" | "models" | "streaming" | "tools" | "embeddings" | "vision";
|
|
666
|
+
/** Normalized authentication description — never contains a secret value. */
|
|
667
|
+
interface ProviderAuthentication {
|
|
668
|
+
/** How the provider authenticates. */
|
|
669
|
+
method: "bearer" | "none" | "custom";
|
|
670
|
+
/** Environment variable that holds the credential, if any. */
|
|
671
|
+
envVar?: string;
|
|
672
|
+
/** True when the referenced variable is currently set. */
|
|
673
|
+
configured: boolean;
|
|
674
|
+
}
|
|
653
675
|
interface ProviderConfig {
|
|
676
|
+
/** Stable identifier used in records and references (defaults to `name`). */
|
|
677
|
+
providerId?: string;
|
|
654
678
|
/** Unique name used in project configuration and the model registry. */
|
|
655
679
|
name: string;
|
|
656
680
|
type: ProviderType;
|
|
@@ -661,6 +685,8 @@ interface ProviderConfig {
|
|
|
661
685
|
*/
|
|
662
686
|
apiKeyEnvVar?: string;
|
|
663
687
|
headers?: Record<string, string>;
|
|
688
|
+
/** Capabilities declared for this provider (discovered ones are merged in). */
|
|
689
|
+
capabilities?: ProviderCapability[];
|
|
664
690
|
enabled?: boolean;
|
|
665
691
|
metadata?: Record<string, unknown>;
|
|
666
692
|
}
|
|
@@ -674,11 +700,22 @@ interface ProviderStatus {
|
|
|
674
700
|
lastCheckedAt?: string;
|
|
675
701
|
message?: string;
|
|
676
702
|
}
|
|
677
|
-
/** Contract every provider adapter implements (
|
|
703
|
+
/** Contract every provider adapter implements (roadmap §10). */
|
|
678
704
|
interface IProvider {
|
|
679
705
|
readonly config: ProviderConfig;
|
|
706
|
+
/** Stable identifier of this provider. */
|
|
707
|
+
readonly providerId: string;
|
|
708
|
+
/** Normalized authentication description (no secret values). */
|
|
709
|
+
readonly authentication: ProviderAuthentication;
|
|
710
|
+
/**
|
|
711
|
+
* Connect: authenticate and discover models (roadmap §10, Model Discovery).
|
|
712
|
+
* Returns the discovered models.
|
|
713
|
+
*/
|
|
714
|
+
connect(): Promise<ModelInfo[]>;
|
|
680
715
|
/** Discover models exposed by this provider. */
|
|
681
716
|
listModels(): Promise<ModelInfo[]>;
|
|
717
|
+
/** Fetch a single model's metadata (from discovery; re-discovers if unknown). */
|
|
718
|
+
getModel(modelId: string): Promise<ModelInfo | undefined>;
|
|
682
719
|
/** Check connectivity and authentication. */
|
|
683
720
|
healthCheck(): Promise<ProviderStatus>;
|
|
684
721
|
}
|
|
@@ -1842,11 +1879,56 @@ declare function requestJson(url: string, options?: HttpRequestOptions): Promise
|
|
|
1842
1879
|
declare const OPENAI_COMPATIBLE_TYPES: readonly ProviderType[];
|
|
1843
1880
|
declare function createProvider(config: ProviderConfig): IChatProvider;
|
|
1844
1881
|
|
|
1882
|
+
/**
|
|
1883
|
+
* Provider error normalization (roadmap §10).
|
|
1884
|
+
*
|
|
1885
|
+
* Every provider failure is mapped to one stable kind, so callers can react
|
|
1886
|
+
* (retry a rate limit, surface an auth problem, treat a missing model
|
|
1887
|
+
* differently) without string-matching provider-specific payloads.
|
|
1888
|
+
*/
|
|
1889
|
+
|
|
1890
|
+
type ProviderErrorKind = "AUTHENTICATION_ERROR" | "RATE_LIMIT_ERROR" | "INVALID_REQUEST" | "MODEL_NOT_FOUND" | "TIMEOUT" | "NETWORK_ERROR" | "SERVER_ERROR" | "UNKNOWN_ERROR";
|
|
1891
|
+
interface ProviderErrorContext {
|
|
1892
|
+
provider: string;
|
|
1893
|
+
operation: string;
|
|
1894
|
+
status?: number;
|
|
1895
|
+
body?: unknown;
|
|
1896
|
+
retryAfterMs?: number;
|
|
1897
|
+
cause?: unknown;
|
|
1898
|
+
/** Maps the normalized kind onto the legacy stable error code. */
|
|
1899
|
+
code?: "PROVIDER_UNAVAILABLE" | "PROVIDER_AUTH_FAILED" | "MODEL_NOT_FOUND";
|
|
1900
|
+
}
|
|
1901
|
+
/** Kinds worth retrying automatically (rate limits and transient server errors). */
|
|
1902
|
+
declare function isRetryable(kind: ProviderErrorKind): boolean;
|
|
1903
|
+
/** Maps an HTTP status (and optional body) to a normalized kind. */
|
|
1904
|
+
declare function kindFromStatus(status: number): ProviderErrorKind;
|
|
1905
|
+
/** Extracts a human message from common provider error body shapes. */
|
|
1906
|
+
declare function extractMessage(body: unknown): string | undefined;
|
|
1907
|
+
/** Parses `Retry-After` (seconds or HTTP-date) into milliseconds. */
|
|
1908
|
+
declare function parseRetryAfter(value: string | null | undefined, now?: number): number | undefined;
|
|
1909
|
+
/** True for the abort/timeout errors raised by fetch's AbortSignal.timeout. */
|
|
1910
|
+
declare function isTimeoutError(error: unknown): boolean;
|
|
1911
|
+
/** True for transport failures (DNS, refused, TLS, offline). */
|
|
1912
|
+
declare function isNetworkError(error: unknown): boolean;
|
|
1913
|
+
declare function providerHttpError(context: ProviderErrorContext): ProviderError;
|
|
1914
|
+
/** Wraps a thrown transport/abort error into a normalized ProviderError. */
|
|
1915
|
+
declare function providerTransportError(context: Omit<ProviderErrorContext, "status" | "body">): ProviderError;
|
|
1916
|
+
|
|
1845
1917
|
declare class OpenAICompatibleProvider implements IChatProvider {
|
|
1846
1918
|
readonly config: ProviderConfig;
|
|
1919
|
+
readonly providerId: string;
|
|
1920
|
+
readonly authentication: ProviderAuthentication;
|
|
1847
1921
|
private readonly log;
|
|
1848
|
-
|
|
1922
|
+
/** Discovered models, so getModel() answers without another round-trip. */
|
|
1923
|
+
private discovered?;
|
|
1924
|
+
private readonly env;
|
|
1925
|
+
constructor(config: ProviderConfig, log?: Logger, env?: Record<string, string | undefined>);
|
|
1926
|
+
/** Authenticate + discover (roadmap §10, Model Discovery). */
|
|
1927
|
+
connect(): Promise<ModelInfo[]>;
|
|
1928
|
+
getModel(modelId: string): Promise<ModelInfo | undefined>;
|
|
1849
1929
|
listModels(): Promise<ModelInfo[]>;
|
|
1930
|
+
/** Maps a raw model entry onto the normalized metadata shape (§10). */
|
|
1931
|
+
private toModelInfo;
|
|
1850
1932
|
healthCheck(): Promise<ProviderStatus>;
|
|
1851
1933
|
chat(request: ChatRequest): Promise<ChatResponse>;
|
|
1852
1934
|
}
|
|
@@ -1893,7 +1975,7 @@ declare class OmniHilbrasProvider extends OpenAICompatibleProvider {
|
|
|
1893
1975
|
* Run the full connect flow. Throws on authentication or transport failure
|
|
1894
1976
|
* (use healthCheck() for a non-throwing probe).
|
|
1895
1977
|
*/
|
|
1896
|
-
|
|
1978
|
+
connectAndRegister(registry?: ModelRegistry): Promise<OmniHilbrasConnectionResult>;
|
|
1897
1979
|
}
|
|
1898
1980
|
|
|
1899
1981
|
/**
|
|
@@ -2563,6 +2645,6 @@ declare class ProjectStores {
|
|
|
2563
2645
|
constructor(directory?: string);
|
|
2564
2646
|
}
|
|
2565
2647
|
|
|
2566
|
-
declare const OMNINODE_VERSION = "2.0.0-alpha.
|
|
2648
|
+
declare const OMNINODE_VERSION = "2.0.0-alpha.6";
|
|
2567
2649
|
|
|
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 };
|
|
2650
|
+
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 Modality, 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 ProviderAuthentication, type ProviderCapability, type ProviderConfig, type ProviderConfigYaml, ProviderError, type ProviderErrorKind, 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, extractMessage, extractReportFromText, findConfigFile, isNetworkError, isOmniNodeError, isRetryable, isSupportedProtocol, isTimeoutError, keywords, killTree, kindFromStatus, loadConfig, logger, newMessageId, parseHello, parsePlanJson, parseRetryAfter, pipelineConfigSchema, pipelineStepConfigSchema, plannerConfigSchema, projectConfigSchema, providerConfigSchema, providerHttpError, providerTransportError, registryKey, requestJson, requireCompletion, resolveApiKey, resolveEnvPolicy, roleConfigSchema, sanitizeChunk, similar, validateEnvelope, validateWorkingDirectory };
|
package/dist/index.js
CHANGED
|
@@ -394,56 +394,184 @@ function authHeaders(config, env = process.env) {
|
|
|
394
394
|
}
|
|
395
395
|
|
|
396
396
|
// src/providers/http.ts
|
|
397
|
+
var HttpResponseError = class extends Error {
|
|
398
|
+
constructor(message, status, cause) {
|
|
399
|
+
super(message, { cause });
|
|
400
|
+
this.status = status;
|
|
401
|
+
this.name = "HttpResponseError";
|
|
402
|
+
}
|
|
403
|
+
status;
|
|
404
|
+
};
|
|
397
405
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
398
406
|
async function requestJson(url, options = {}) {
|
|
399
407
|
const { method = "GET", headers = {}, body, timeoutMs = DEFAULT_TIMEOUT_MS } = options;
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
411
|
-
});
|
|
412
|
-
} catch (error) {
|
|
413
|
-
const reason = error instanceof Error && error.name === "TimeoutError" ? `timed out after ${timeoutMs}ms` : error instanceof Error ? error.message : String(error);
|
|
414
|
-
throw new ProviderError("PROVIDER_UNAVAILABLE", `Request to ${url} failed: ${reason}.`, {
|
|
415
|
-
cause: error
|
|
416
|
-
});
|
|
417
|
-
}
|
|
408
|
+
const response = await fetch(url, {
|
|
409
|
+
method,
|
|
410
|
+
headers: {
|
|
411
|
+
accept: "application/json",
|
|
412
|
+
...body !== void 0 ? { "content-type": "application/json" } : {},
|
|
413
|
+
...headers
|
|
414
|
+
},
|
|
415
|
+
...body !== void 0 ? { body: JSON.stringify(body) } : {},
|
|
416
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
417
|
+
});
|
|
418
418
|
let parsed;
|
|
419
419
|
try {
|
|
420
420
|
parsed = await response.json();
|
|
421
421
|
} catch (error) {
|
|
422
|
-
throw new
|
|
423
|
-
cause: error,
|
|
424
|
-
details: { status: response.status }
|
|
425
|
-
});
|
|
422
|
+
throw new HttpResponseError(`Response from ${url} was not valid JSON.`, response.status, error);
|
|
426
423
|
}
|
|
427
424
|
return { status: response.status, body: parsed };
|
|
428
425
|
}
|
|
429
426
|
|
|
427
|
+
// src/providers/errors.ts
|
|
428
|
+
function kindToCode(kind) {
|
|
429
|
+
switch (kind) {
|
|
430
|
+
case "AUTHENTICATION_ERROR":
|
|
431
|
+
return "PROVIDER_AUTH_FAILED";
|
|
432
|
+
case "MODEL_NOT_FOUND":
|
|
433
|
+
return "MODEL_NOT_FOUND";
|
|
434
|
+
default:
|
|
435
|
+
return "PROVIDER_UNAVAILABLE";
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
function isRetryable(kind) {
|
|
439
|
+
return kind === "RATE_LIMIT_ERROR" || kind === "SERVER_ERROR" || kind === "NETWORK_ERROR";
|
|
440
|
+
}
|
|
441
|
+
function kindFromStatus(status) {
|
|
442
|
+
if (status === 401 || status === 403) return "AUTHENTICATION_ERROR";
|
|
443
|
+
if (status === 429) return "RATE_LIMIT_ERROR";
|
|
444
|
+
if (status === 404) return "MODEL_NOT_FOUND";
|
|
445
|
+
if (status === 408 || status === 504) return "TIMEOUT";
|
|
446
|
+
if (status >= 500) return "SERVER_ERROR";
|
|
447
|
+
if (status >= 400) return "INVALID_REQUEST";
|
|
448
|
+
return "UNKNOWN_ERROR";
|
|
449
|
+
}
|
|
450
|
+
function extractMessage(body) {
|
|
451
|
+
if (body === null || typeof body !== "object") return void 0;
|
|
452
|
+
const root = body;
|
|
453
|
+
const error = root.error ?? root;
|
|
454
|
+
const message = error.message ?? error.detail ?? root.message;
|
|
455
|
+
return typeof message === "string" ? message : void 0;
|
|
456
|
+
}
|
|
457
|
+
function parseRetryAfter(value, now = Date.now()) {
|
|
458
|
+
if (!value) return void 0;
|
|
459
|
+
const seconds = Number(value);
|
|
460
|
+
if (Number.isFinite(seconds)) return Math.max(0, seconds * 1e3);
|
|
461
|
+
const date = Date.parse(value);
|
|
462
|
+
return Number.isNaN(date) ? void 0 : Math.max(0, date - now);
|
|
463
|
+
}
|
|
464
|
+
function isTimeoutError(error) {
|
|
465
|
+
return error instanceof Error && (error.name === "TimeoutError" || error.name === "AbortError") || typeof error?.code === "string" && error.code === "ABORT_ERR";
|
|
466
|
+
}
|
|
467
|
+
function isNetworkError(error) {
|
|
468
|
+
return error instanceof TypeError || typeof error?.cause === "object" && error instanceof Error && !error.code;
|
|
469
|
+
}
|
|
470
|
+
function fallbackMessage(kind, context, status) {
|
|
471
|
+
const { provider, operation } = context;
|
|
472
|
+
switch (kind) {
|
|
473
|
+
case "AUTHENTICATION_ERROR":
|
|
474
|
+
return `Authentication with provider "${provider}" failed (HTTP ${status}). Check that the referenced API key is set and valid.`;
|
|
475
|
+
case "RATE_LIMIT_ERROR":
|
|
476
|
+
return `Provider "${provider}" rate-limited ${operation} (HTTP ${status}). Retry later.`;
|
|
477
|
+
case "MODEL_NOT_FOUND":
|
|
478
|
+
return `Provider "${provider}" does not expose the requested model (HTTP ${status}).`;
|
|
479
|
+
case "TIMEOUT":
|
|
480
|
+
return `Provider "${provider}" timed out during ${operation} (HTTP ${status}).`;
|
|
481
|
+
case "SERVER_ERROR":
|
|
482
|
+
return `Provider "${provider}" returned a server error during ${operation} (HTTP ${status}).`;
|
|
483
|
+
case "INVALID_REQUEST":
|
|
484
|
+
return `Provider "${provider}" rejected ${operation} as invalid (HTTP ${status}).`;
|
|
485
|
+
default:
|
|
486
|
+
return `Provider "${provider}" failed during ${operation} (HTTP ${status}).`;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
function providerHttpError(context) {
|
|
490
|
+
const status = context.status ?? 0;
|
|
491
|
+
const kind = kindFromStatus(status);
|
|
492
|
+
const detail = extractMessage(context.body);
|
|
493
|
+
const retryAfterMs = context.retryAfterMs ?? parseRetryAfter(void 0);
|
|
494
|
+
return new ProviderError(
|
|
495
|
+
context.code ?? kindToCode(kind),
|
|
496
|
+
detail ?? fallbackMessage(kind, context, status),
|
|
497
|
+
{
|
|
498
|
+
cause: context.cause,
|
|
499
|
+
details: {
|
|
500
|
+
kind,
|
|
501
|
+
provider: context.provider,
|
|
502
|
+
operation: context.operation,
|
|
503
|
+
status,
|
|
504
|
+
retryable: isRetryable(kind),
|
|
505
|
+
...retryAfterMs !== void 0 ? { retryAfterMs } : {},
|
|
506
|
+
...detail ? { providerMessage: detail } : {}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
function providerTransportError(context) {
|
|
512
|
+
const cause = context.cause;
|
|
513
|
+
const kind = isTimeoutError(cause) ? "TIMEOUT" : cause instanceof SyntaxError || cause?.name === "HttpResponseError" ? "UNKNOWN_ERROR" : "NETWORK_ERROR";
|
|
514
|
+
const message = context.cause instanceof Error ? context.cause.message : String(context.cause);
|
|
515
|
+
return new ProviderError("PROVIDER_UNAVAILABLE", `Provider request failed: ${message}`, {
|
|
516
|
+
cause: context.cause,
|
|
517
|
+
details: {
|
|
518
|
+
kind,
|
|
519
|
+
provider: context.provider,
|
|
520
|
+
operation: context.operation,
|
|
521
|
+
retryable: isRetryable(kind)
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
|
|
430
526
|
// src/providers/openai-compatible/index.ts
|
|
431
527
|
var OpenAICompatibleProvider = class {
|
|
432
528
|
config;
|
|
529
|
+
providerId;
|
|
530
|
+
authentication;
|
|
433
531
|
log;
|
|
434
|
-
|
|
532
|
+
/** Discovered models, so getModel() answers without another round-trip. */
|
|
533
|
+
discovered;
|
|
534
|
+
env;
|
|
535
|
+
constructor(config, log = logger, env = process.env) {
|
|
435
536
|
this.config = { ...config, baseUrl: normalizeBaseUrl(config.baseUrl) };
|
|
537
|
+
this.env = env;
|
|
538
|
+
this.providerId = config.providerId ?? config.name;
|
|
539
|
+
this.authentication = {
|
|
540
|
+
method: config.apiKeyEnvVar ? "bearer" : "none",
|
|
541
|
+
...config.apiKeyEnvVar ? { envVar: config.apiKeyEnvVar } : {},
|
|
542
|
+
configured: config.apiKeyEnvVar ? Boolean(env[config.apiKeyEnvVar]) : true
|
|
543
|
+
};
|
|
436
544
|
this.log = log.child({ provider: config.name });
|
|
437
545
|
}
|
|
546
|
+
/** Authenticate + discover (roadmap §10, Model Discovery). */
|
|
547
|
+
async connect() {
|
|
548
|
+
authHeaders(this.config, this.env);
|
|
549
|
+
const models = await this.listModels();
|
|
550
|
+
this.discovered = models;
|
|
551
|
+
return models;
|
|
552
|
+
}
|
|
553
|
+
async getModel(modelId) {
|
|
554
|
+
const models = this.discovered ?? await this.connect();
|
|
555
|
+
return models.find((m) => m.id === modelId);
|
|
556
|
+
}
|
|
438
557
|
async listModels() {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
558
|
+
let response;
|
|
559
|
+
try {
|
|
560
|
+
response = await requestJson(`${this.config.baseUrl}/models`, {
|
|
561
|
+
headers: authHeaders(this.config, this.env)
|
|
562
|
+
});
|
|
563
|
+
} catch (error) {
|
|
564
|
+
if (error instanceof ProviderError) throw error;
|
|
565
|
+
throw providerTransportError({ provider: this.config.name, operation: "listModels", cause: error });
|
|
444
566
|
}
|
|
567
|
+
const { status, body } = response;
|
|
445
568
|
if (status !== 200) {
|
|
446
|
-
throw
|
|
569
|
+
throw providerHttpError({
|
|
570
|
+
provider: this.config.name,
|
|
571
|
+
operation: "listModels",
|
|
572
|
+
status,
|
|
573
|
+
body
|
|
574
|
+
});
|
|
447
575
|
}
|
|
448
576
|
const entries = extractModelEntries(body, this.config);
|
|
449
577
|
const models = [];
|
|
@@ -453,22 +581,40 @@ var OpenAICompatibleProvider = class {
|
|
|
453
581
|
skipped += 1;
|
|
454
582
|
continue;
|
|
455
583
|
}
|
|
456
|
-
models.push(
|
|
457
|
-
provider: this.config.name,
|
|
458
|
-
id: entry.id,
|
|
459
|
-
displayName: entry.id,
|
|
460
|
-
status: "available",
|
|
461
|
-
metadata: {
|
|
462
|
-
...typeof entry.owned_by === "string" ? { ownedBy: entry.owned_by } : {},
|
|
463
|
-
...typeof entry.created === "number" ? { createdAt: entry.created } : {}
|
|
464
|
-
}
|
|
465
|
-
});
|
|
584
|
+
models.push(this.toModelInfo(entry));
|
|
466
585
|
}
|
|
467
586
|
if (skipped > 0) {
|
|
468
587
|
this.log.warn(`Skipped ${skipped} model entr(y/ies) without a valid id.`);
|
|
469
588
|
}
|
|
470
589
|
return models;
|
|
471
590
|
}
|
|
591
|
+
/** Maps a raw model entry onto the normalized metadata shape (§10). */
|
|
592
|
+
toModelInfo(entry) {
|
|
593
|
+
const parameters = Array.isArray(entry.supported_parameters) ? entry.supported_parameters.filter((p) => typeof p === "string") : void 0;
|
|
594
|
+
const contextWindow = typeof entry.context_length === "number" ? entry.context_length : typeof entry.context_window === "number" ? entry.context_window : void 0;
|
|
595
|
+
const inputTypes = normalizeModalities(entry.input_modalities);
|
|
596
|
+
const outputTypes = normalizeModalities(entry.output_modalities);
|
|
597
|
+
return {
|
|
598
|
+
provider: this.config.name,
|
|
599
|
+
id: entry.id,
|
|
600
|
+
displayName: entry.id,
|
|
601
|
+
...typeof entry.name === "string" ? { name: entry.name } : {},
|
|
602
|
+
status: "available",
|
|
603
|
+
...contextWindow !== void 0 ? { contextWindow } : {},
|
|
604
|
+
...inputTypes !== void 0 ? { inputTypes } : {},
|
|
605
|
+
...outputTypes !== void 0 ? { outputTypes } : {},
|
|
606
|
+
...parameters !== void 0 ? {
|
|
607
|
+
supportsTools: parameters.includes("tools") || parameters.includes("tool_choice"),
|
|
608
|
+
supportsStructuredOutput: parameters.includes("response_format"),
|
|
609
|
+
supportsStreaming: parameters.includes("stream")
|
|
610
|
+
} : {},
|
|
611
|
+
metadata: {
|
|
612
|
+
...typeof entry.owned_by === "string" ? { ownedBy: entry.owned_by } : {},
|
|
613
|
+
...typeof entry.created === "number" ? { createdAt: entry.created } : {},
|
|
614
|
+
...parameters !== void 0 ? { supportedParameters: parameters } : {}
|
|
615
|
+
}
|
|
616
|
+
};
|
|
617
|
+
}
|
|
472
618
|
async healthCheck() {
|
|
473
619
|
const lastCheckedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
474
620
|
try {
|
|
@@ -498,27 +644,34 @@ var OpenAICompatibleProvider = class {
|
|
|
498
644
|
}
|
|
499
645
|
}
|
|
500
646
|
async chat(request) {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
{ details: { status } }
|
|
518
|
-
);
|
|
647
|
+
let response;
|
|
648
|
+
try {
|
|
649
|
+
response = await requestJson(`${this.config.baseUrl}/chat/completions`, {
|
|
650
|
+
method: "POST",
|
|
651
|
+
headers: authHeaders(this.config, this.env),
|
|
652
|
+
body: {
|
|
653
|
+
model: request.model,
|
|
654
|
+
messages: request.messages,
|
|
655
|
+
...request.temperature !== void 0 ? { temperature: request.temperature } : {},
|
|
656
|
+
...request.maxTokens !== void 0 ? { max_tokens: request.maxTokens } : {},
|
|
657
|
+
...request.stop !== void 0 ? { stop: request.stop } : {}
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
} catch (error) {
|
|
661
|
+
if (error instanceof ProviderError) throw error;
|
|
662
|
+
throw providerTransportError({ provider: this.config.name, operation: "chat", cause: error });
|
|
519
663
|
}
|
|
664
|
+
const { status, body } = response;
|
|
520
665
|
if (status !== 200) {
|
|
521
|
-
throw
|
|
666
|
+
throw providerHttpError({
|
|
667
|
+
provider: this.config.name,
|
|
668
|
+
operation: "chat",
|
|
669
|
+
status,
|
|
670
|
+
body,
|
|
671
|
+
...status === 404 ? {
|
|
672
|
+
code: "MODEL_NOT_FOUND"
|
|
673
|
+
} : {}
|
|
674
|
+
});
|
|
522
675
|
}
|
|
523
676
|
const payload = body;
|
|
524
677
|
const choices = Array.isArray(payload.choices) ? payload.choices : [];
|
|
@@ -540,6 +693,13 @@ var OpenAICompatibleProvider = class {
|
|
|
540
693
|
};
|
|
541
694
|
}
|
|
542
695
|
};
|
|
696
|
+
function normalizeModalities(value) {
|
|
697
|
+
const list = Array.isArray(value) ? value : typeof value === "string" ? [value] : void 0;
|
|
698
|
+
if (!list) return void 0;
|
|
699
|
+
const allowed = /* @__PURE__ */ new Set(["text", "image", "audio", "video", "embedding"]);
|
|
700
|
+
const modalities = list.filter((m) => typeof m === "string" && allowed.has(m));
|
|
701
|
+
return modalities.length > 0 ? modalities : void 0;
|
|
702
|
+
}
|
|
543
703
|
function normalizeBaseUrl(baseUrl) {
|
|
544
704
|
return baseUrl.replace(/\/+$/, "");
|
|
545
705
|
}
|
|
@@ -554,14 +714,6 @@ function extractModelEntries(body, config) {
|
|
|
554
714
|
{ details: { endpoint: "models" } }
|
|
555
715
|
);
|
|
556
716
|
}
|
|
557
|
-
function authFailed(config, status) {
|
|
558
|
-
const envHint = config.apiKeyEnvVar ? ` Check that $${config.apiKeyEnvVar} is set and valid.` : " The provider requires authentication; configure api_key_env_var for it.";
|
|
559
|
-
return new ProviderError(
|
|
560
|
-
"PROVIDER_AUTH_FAILED",
|
|
561
|
-
`Authentication with provider "${config.name}" failed (HTTP ${status}).${envHint}`,
|
|
562
|
-
{ details: { status } }
|
|
563
|
-
);
|
|
564
|
-
}
|
|
565
717
|
function unavailable(config, message, status) {
|
|
566
718
|
return new ProviderError("PROVIDER_UNAVAILABLE", `Provider "${config.name}": ${message}`, {
|
|
567
719
|
details: { status }
|
|
@@ -578,7 +730,7 @@ var OmniHilbrasProvider = class extends OpenAICompatibleProvider {
|
|
|
578
730
|
* Run the full connect flow. Throws on authentication or transport failure
|
|
579
731
|
* (use healthCheck() for a non-throwing probe).
|
|
580
732
|
*/
|
|
581
|
-
async
|
|
733
|
+
async connectAndRegister(registry) {
|
|
582
734
|
const apiKey = resolveApiKey(this.config);
|
|
583
735
|
const discovered = await this.listModels();
|
|
584
736
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -3325,7 +3477,7 @@ var ProjectStores = class {
|
|
|
3325
3477
|
};
|
|
3326
3478
|
|
|
3327
3479
|
// src/version.ts
|
|
3328
|
-
var OMNINODE_VERSION = "2.0.0-alpha.
|
|
3480
|
+
var OMNINODE_VERSION = "2.0.0-alpha.6";
|
|
3329
3481
|
export {
|
|
3330
3482
|
AgentAdapterRegistry,
|
|
3331
3483
|
AgentError,
|
|
@@ -3395,22 +3547,30 @@ export {
|
|
|
3395
3547
|
encodeMessage,
|
|
3396
3548
|
envelope,
|
|
3397
3549
|
expandEnvRefs,
|
|
3550
|
+
extractMessage,
|
|
3398
3551
|
extractReportFromText,
|
|
3399
3552
|
findConfigFile,
|
|
3553
|
+
isNetworkError,
|
|
3400
3554
|
isOmniNodeError,
|
|
3555
|
+
isRetryable,
|
|
3401
3556
|
isSupportedProtocol,
|
|
3557
|
+
isTimeoutError,
|
|
3402
3558
|
keywords,
|
|
3403
3559
|
killTree,
|
|
3560
|
+
kindFromStatus,
|
|
3404
3561
|
loadConfig,
|
|
3405
3562
|
logger,
|
|
3406
3563
|
newMessageId,
|
|
3407
3564
|
parseHello,
|
|
3408
3565
|
parsePlanJson,
|
|
3566
|
+
parseRetryAfter,
|
|
3409
3567
|
pipelineConfigSchema,
|
|
3410
3568
|
pipelineStepConfigSchema,
|
|
3411
3569
|
plannerConfigSchema,
|
|
3412
3570
|
projectConfigSchema,
|
|
3413
3571
|
providerConfigSchema,
|
|
3572
|
+
providerHttpError,
|
|
3573
|
+
providerTransportError,
|
|
3414
3574
|
registryKey,
|
|
3415
3575
|
requestJson,
|
|
3416
3576
|
requireCompletion,
|