mirror of
https://github.com/KeygraphHQ/shannon.git
synced 2026-09-16 15:05:40 +02:00
Add the ten-stage Agentic SAST pipeline, confined repository tools, model runtime, prompt templates, and SARIF export. Make retries, repair sessions, reduced coverage, usage accounting, and model-output drift durable across Temporal replay and resume. Keep retry diagnostics in their actionable closed vocabulary. Package the Mantis-derived license material with the prompts that require it.
55 lines
2.2 KiB
TypeScript
55 lines
2.2 KiB
TypeScript
// Copyright (C) 2026 Keygraph, Inc.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License version 3
|
|
// as published by the Free Software Foundation.
|
|
|
|
import { classifyProviderFailure } from '../services/error-handling.js';
|
|
import type { ProviderFailure } from '../types/errors.js';
|
|
import { type ModelSelection, resolveModelSelection } from './models.js';
|
|
|
|
/** Intended cost/capability role for a model call. All roles use the run's one selected model. */
|
|
export type ModelRole = 'small' | 'medium' | 'large';
|
|
|
|
/** Credential-preserving model selection and provider-failure classification boundary. */
|
|
export interface ModelHost {
|
|
resolve(role: ModelRole): Promise<ModelSelection>;
|
|
classify(error: unknown, contextWindow?: number): ProviderFailure;
|
|
}
|
|
|
|
export type ModelSelectionResolver = () => Promise<ModelSelection>;
|
|
|
|
class ShannonModelHost implements ModelHost {
|
|
private selection: Promise<ModelSelection> | undefined;
|
|
|
|
constructor(private readonly resolver: ModelSelectionResolver) {}
|
|
|
|
// Cache only a selection that resolves. The catch clears the slot on rejection so a later
|
|
// attempt (a retried activity) can resolve again instead of replaying the first failure forever.
|
|
// The identity guard leaves a newer in-flight selection in place if one already replaced this one.
|
|
resolve(_role: ModelRole): Promise<ModelSelection> {
|
|
if (this.selection) return this.selection;
|
|
|
|
const selection = Promise.resolve()
|
|
.then(() => this.resolver())
|
|
.catch((error: unknown) => {
|
|
if (this.selection === selection) this.selection = undefined;
|
|
throw error;
|
|
});
|
|
this.selection = selection;
|
|
return this.selection;
|
|
}
|
|
|
|
classify(error: unknown, contextWindow?: number): ProviderFailure {
|
|
return classifyProviderFailure(error, contextWindow);
|
|
}
|
|
}
|
|
|
|
/** Create an isolated host, primarily for callers with an explicit lifecycle or focused verification. */
|
|
export function createModelHost(resolver: ModelSelectionResolver = resolveModelSelection): ModelHost {
|
|
return new ShannonModelHost(resolver);
|
|
}
|
|
|
|
/** Process-local model host shared by production model callers. */
|
|
export const modelHost: ModelHost = createModelHost();
|