@kernel.chat/agent-os
Advanced tools
| /** | ||
| * Outcomes — rubric-graded self-evaluation with auto-iteration. | ||
| * | ||
| * Adopted from Claude Managed Agents' `define_outcome` pattern. A | ||
| * separate evaluator (running in its own context, typically with a | ||
| * different model or at least a different prompt) judges the agent's | ||
| * work product against per-criterion rubric. If unsatisfied, the | ||
| * agent revises; the loop runs until satisfied or max_iterations. | ||
| * | ||
| * agent-os generalizes CMA's pattern in three ways: | ||
| * - the evaluator is pluggable (LLM-based, rules-based, hybrid) | ||
| * - the rubric supports weighted criteria | ||
| * - each iteration's evaluation is content-addressable so the loop | ||
| * is replayable in an audit-grade environment | ||
| */ | ||
| export interface RubricCriterion { | ||
| /** Stable identifier — used in audit logs. */ | ||
| readonly name: string; | ||
| /** Plain-language description the evaluator scores against. */ | ||
| readonly description: string; | ||
| /** Optional weight. Defaults to 1.0. */ | ||
| readonly weight?: number; | ||
| } | ||
| export interface Rubric { | ||
| readonly criteria: ReadonlyArray<RubricCriterion>; | ||
| /** Weighted-average score threshold for `satisfied` verdict (0.0–1.0). | ||
| * Defaults to 0.85. */ | ||
| readonly satisfied_at?: number; | ||
| } | ||
| export interface CriterionScore { | ||
| readonly name: string; | ||
| /** 0.0–1.0. Higher is better. */ | ||
| readonly score: number; | ||
| /** Plain-language feedback explaining the score; used by the agent | ||
| * to revise on the next iteration. */ | ||
| readonly feedback: string; | ||
| } | ||
| export interface RubricEvaluation { | ||
| readonly per_criterion: ReadonlyArray<CriterionScore>; | ||
| /** Weighted average across criteria. */ | ||
| readonly overall_score: number; | ||
| readonly verdict: 'satisfied' | 'needs_revision' | 'failed'; | ||
| /** Optional structured feedback the agent should consume on the next | ||
| * iteration. The evaluator may synthesize this from per-criterion | ||
| * feedback. */ | ||
| readonly revision_guidance?: string; | ||
| } | ||
| export interface RubricEvaluator { | ||
| evaluate(work_product: string, rubric: Rubric, iteration: number): Promise<RubricEvaluation>; | ||
| } | ||
| export type OutcomeResultCode = 'satisfied' | 'needs_revision' | 'max_iterations_reached' | 'failed' | 'interrupted'; | ||
| export interface OutcomeIteration<T> { | ||
| readonly iteration: number; | ||
| readonly work: T; | ||
| readonly work_serialized: string; | ||
| readonly evaluation: RubricEvaluation; | ||
| readonly at: string; | ||
| } | ||
| export interface OutcomeResult<T> { | ||
| readonly code: OutcomeResultCode; | ||
| readonly iterations_used: number; | ||
| readonly final_work: T | null; | ||
| readonly final_evaluation: RubricEvaluation | null; | ||
| readonly history: ReadonlyArray<OutcomeIteration<T>>; | ||
| } | ||
| export interface WithOutcomeOptions<T> { | ||
| readonly max_iterations: number; | ||
| /** Serialize the agent's work product to a string the evaluator can | ||
| * judge. Defaults to JSON.stringify. */ | ||
| readonly serialize?: (work: T) => string; | ||
| /** Abort signal — interrupting mid-iteration returns the | ||
| * `interrupted` result code with the history so far. */ | ||
| readonly signal?: AbortSignal; | ||
| } | ||
| /** | ||
| * Run an attempt → evaluate → revise loop against a rubric. | ||
| * | ||
| * `attempt(feedback)` is called once per iteration. On the first call, | ||
| * `feedback` is `null`; on subsequent calls it's the evaluator's | ||
| * revision_guidance (or a synthesized summary of per-criterion feedback | ||
| * if no guidance was provided). | ||
| * | ||
| * The loop terminates on: | ||
| * - `satisfied` verdict from the evaluator | ||
| * - `failed` verdict from the evaluator (non-recoverable) | ||
| * - max_iterations reached | ||
| * - signal.aborted (interrupted) | ||
| * - attempt() or evaluate() throwing — caught and reported as `failed` | ||
| */ | ||
| export declare function withOutcome<T>(rubric: Rubric, attempt: (feedback: string | null, iteration: number) => Promise<T>, evaluator: RubricEvaluator, options: WithOutcomeOptions<T>): Promise<OutcomeResult<T>>; | ||
| /** Helper: weighted-average score. Useful for evaluator implementations. */ | ||
| export declare function weightedAverage(scores: ReadonlyArray<CriterionScore>, rubric: Rubric): number; | ||
| /** Helper: classify a score into a verdict against the rubric's threshold. */ | ||
| export declare function classify(score: number, rubric: Rubric): 'satisfied' | 'needs_revision'; | ||
| /** A trivial evaluator useful for tests — accepts the work product as | ||
| * satisfying if it matches a predicate. Production code uses an LLM | ||
| * evaluator running in a separate context. */ | ||
| export declare function predicateEvaluator(predicate: (work: string) => boolean, rubric: Rubric, feedback_when_failing: string): RubricEvaluator; | ||
| //# sourceMappingURL=outcomes.d.ts.map |
| {"version":3,"file":"outcomes.d.ts","sourceRoot":"","sources":["../src/outcomes.ts"],"names":[],"mappings":"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"} |
+150
| /** | ||
| * Run an attempt → evaluate → revise loop against a rubric. | ||
| * | ||
| * `attempt(feedback)` is called once per iteration. On the first call, | ||
| * `feedback` is `null`; on subsequent calls it's the evaluator's | ||
| * revision_guidance (or a synthesized summary of per-criterion feedback | ||
| * if no guidance was provided). | ||
| * | ||
| * The loop terminates on: | ||
| * - `satisfied` verdict from the evaluator | ||
| * - `failed` verdict from the evaluator (non-recoverable) | ||
| * - max_iterations reached | ||
| * - signal.aborted (interrupted) | ||
| * - attempt() or evaluate() throwing — caught and reported as `failed` | ||
| */ | ||
| export async function withOutcome(rubric, attempt, evaluator, options) { | ||
| const serialize = options.serialize ?? ((t) => JSON.stringify(t)); | ||
| const max = Math.max(1, Math.floor(options.max_iterations)); | ||
| const history = []; | ||
| let feedback = null; | ||
| let lastWork = null; | ||
| let lastEval = null; | ||
| for (let i = 1; i <= max; i++) { | ||
| if (options.signal?.aborted) { | ||
| return { | ||
| code: 'interrupted', | ||
| iterations_used: i - 1, | ||
| final_work: lastWork, | ||
| final_evaluation: lastEval, | ||
| history, | ||
| }; | ||
| } | ||
| let work; | ||
| try { | ||
| work = await attempt(feedback, i); | ||
| } | ||
| catch (e) { | ||
| return { | ||
| code: 'failed', | ||
| iterations_used: i - 1, | ||
| final_work: lastWork, | ||
| final_evaluation: lastEval, | ||
| history, | ||
| }; | ||
| } | ||
| const serialized = serialize(work); | ||
| let evaluation; | ||
| try { | ||
| evaluation = await evaluator.evaluate(serialized, rubric, i); | ||
| } | ||
| catch (e) { | ||
| return { | ||
| code: 'failed', | ||
| iterations_used: i, | ||
| final_work: work, | ||
| final_evaluation: lastEval, | ||
| history, | ||
| }; | ||
| } | ||
| const iter = { | ||
| iteration: i, | ||
| work, | ||
| work_serialized: serialized, | ||
| evaluation, | ||
| at: new Date().toISOString(), | ||
| }; | ||
| history.push(iter); | ||
| lastWork = work; | ||
| lastEval = evaluation; | ||
| if (evaluation.verdict === 'satisfied') { | ||
| return { | ||
| code: 'satisfied', | ||
| iterations_used: i, | ||
| final_work: work, | ||
| final_evaluation: evaluation, | ||
| history, | ||
| }; | ||
| } | ||
| if (evaluation.verdict === 'failed') { | ||
| return { | ||
| code: 'failed', | ||
| iterations_used: i, | ||
| final_work: work, | ||
| final_evaluation: evaluation, | ||
| history, | ||
| }; | ||
| } | ||
| feedback = | ||
| evaluation.revision_guidance ?? synthesizeFeedback(evaluation.per_criterion); | ||
| } | ||
| return { | ||
| code: 'max_iterations_reached', | ||
| iterations_used: max, | ||
| final_work: lastWork, | ||
| final_evaluation: lastEval, | ||
| history, | ||
| }; | ||
| } | ||
| /** Default feedback synthesizer — joins per-criterion feedback into a | ||
| * single message the agent can act on. */ | ||
| function synthesizeFeedback(scores) { | ||
| const weakest = [...scores].sort((a, b) => a.score - b.score).slice(0, 3); | ||
| if (weakest.length === 0) | ||
| return ''; | ||
| return weakest | ||
| .map((s) => `[${s.name} score=${s.score.toFixed(2)}] ${s.feedback}`) | ||
| .join('\n'); | ||
| } | ||
| /** Helper: weighted-average score. Useful for evaluator implementations. */ | ||
| export function weightedAverage(scores, rubric) { | ||
| if (scores.length === 0) | ||
| return 0; | ||
| const lookup = new Map(rubric.criteria.map((c) => [c.name, c.weight ?? 1.0])); | ||
| let weighted_sum = 0; | ||
| let total_weight = 0; | ||
| for (const s of scores) { | ||
| const w = lookup.get(s.name) ?? 1.0; | ||
| weighted_sum += s.score * w; | ||
| total_weight += w; | ||
| } | ||
| return total_weight > 0 ? weighted_sum / total_weight : 0; | ||
| } | ||
| /** Helper: classify a score into a verdict against the rubric's threshold. */ | ||
| export function classify(score, rubric) { | ||
| const threshold = rubric.satisfied_at ?? 0.85; | ||
| return score >= threshold ? 'satisfied' : 'needs_revision'; | ||
| } | ||
| /** A trivial evaluator useful for tests — accepts the work product as | ||
| * satisfying if it matches a predicate. Production code uses an LLM | ||
| * evaluator running in a separate context. */ | ||
| export function predicateEvaluator(predicate, rubric, feedback_when_failing) { | ||
| return { | ||
| async evaluate(work) { | ||
| const passing = predicate(work); | ||
| const per_criterion = rubric.criteria.map((c) => ({ | ||
| name: c.name, | ||
| score: passing ? 1.0 : 0.0, | ||
| feedback: passing ? 'meets criterion' : feedback_when_failing, | ||
| })); | ||
| const overall_score = weightedAverage(per_criterion, rubric); | ||
| return { | ||
| per_criterion, | ||
| overall_score, | ||
| verdict: passing ? 'satisfied' : 'needs_revision', | ||
| revision_guidance: passing ? undefined : feedback_when_failing, | ||
| }; | ||
| }, | ||
| }; | ||
| } | ||
| //# sourceMappingURL=outcomes.js.map |
| {"version":3,"file":"outcomes.js","sourceRoot":"","sources":["../src/outcomes.ts"],"names":[],"mappings":"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"} |
+113
| import type { ACap, ACapSubject, OSResult } from './types.js'; | ||
| /** | ||
| * Vault — server-side credential injection outside the agent sandbox. | ||
| * | ||
| * The pattern adopted from Claude Managed Agents' vault design: credentials | ||
| * never enter the agent's context. The agent references a credential by | ||
| * name; the OS resolves and injects it at the chexec boundary; the secret | ||
| * material is added to the outbound tool request server-side. A | ||
| * prompt-injection attack that compromises the agent's reasoning cannot | ||
| * read secrets that never crossed into its context. | ||
| * | ||
| * agent-os generalizes CMA's pattern in two ways: | ||
| * - bindings are to any ACapSubject, not just MCP server URLs | ||
| * - the resolver is pluggable so secrets can live in any backing store | ||
| * (file, env, AWS Secrets Manager, Vault, 1Password, on-device keychain) | ||
| * | ||
| * v0.1 ships with an in-memory resolver. Production deployments register | ||
| * a custom resolver via `Vault.withResolver()`. | ||
| */ | ||
| /** A reference name an agent uses to ask for a credential without seeing | ||
| * its value. e.g. "factset_api", "sec_edgar_user_agent". */ | ||
| export type CredentialRef = string & { | ||
| readonly __cred_ref: unique symbol; | ||
| }; | ||
| /** The actual secret material — must never leave the Vault unrewritten. */ | ||
| export type CredentialValue = string & { | ||
| readonly __cred_value: unique symbol; | ||
| }; | ||
| export interface VaultEntry { | ||
| readonly ref: CredentialRef; | ||
| /** Which capability subject is allowed to invoke this credential. | ||
| * The chexec layer cross-checks the caller's acap against this binding. */ | ||
| readonly bound_to: ACapSubject; | ||
| /** How the secret material is injected into the tool's outbound request. | ||
| * Currently three shapes; extensible. */ | ||
| readonly injection: InjectionShape; | ||
| /** Optional metadata for audit log entries. Never includes the secret. */ | ||
| readonly description?: string; | ||
| } | ||
| export type InjectionShape = { | ||
| readonly kind: 'header'; | ||
| readonly name: string; | ||
| readonly prefix?: string; | ||
| } | { | ||
| readonly kind: 'query_param'; | ||
| readonly name: string; | ||
| } | { | ||
| readonly kind: 'bearer_token'; | ||
| }; | ||
| /** A credential resolver fetches the actual secret value at injection | ||
| * time. The Vault holds references to resolvers, not secrets themselves — | ||
| * so memory snapshots and core dumps don't leak credentials. */ | ||
| export type CredentialResolver = (ref: CredentialRef) => Promise<CredentialValue | null>; | ||
| /** Materialized injection — what the chexec layer should add to the | ||
| * outbound tool request. The secret is in `header_value` / `param_value`; | ||
| * the agent never sees this struct. */ | ||
| export type Injection = { | ||
| readonly kind: 'header'; | ||
| readonly name: string; | ||
| readonly header_value: string; | ||
| } | { | ||
| readonly kind: 'query_param'; | ||
| readonly name: string; | ||
| readonly param_value: string; | ||
| } | { | ||
| readonly kind: 'bearer_token'; | ||
| readonly header_value: string; | ||
| }; | ||
| /** Audit-loggable record of an injection. Crucially: does NOT include | ||
| * the secret value. Records the ref name + binding + outcome. */ | ||
| export interface InjectionLog { | ||
| readonly cred_ref: CredentialRef; | ||
| readonly caller_acap: string; | ||
| readonly bound_subject: ACapSubject; | ||
| readonly injection_kind: InjectionShape['kind']; | ||
| readonly outcome: 'injected' | 'denied' | 'missing'; | ||
| readonly at: string; | ||
| } | ||
| export declare class Vault { | ||
| private readonly entries; | ||
| private resolver; | ||
| private readonly logs; | ||
| constructor(resolver?: CredentialResolver); | ||
| /** Register a credential reference. Only metadata; the secret value | ||
| * stays with the resolver. */ | ||
| register(entry: VaultEntry): OSResult<true>; | ||
| /** Replace the resolver (for plugging in AWS Secrets Manager / Vault / | ||
| * 1Password etc. without changing the agent contract). */ | ||
| withResolver(resolver: CredentialResolver): void; | ||
| /** | ||
| * Inject a credential into a tool call. Returns the materialized | ||
| * injection or an error. Validates: | ||
| * 1. The credential exists in the vault. | ||
| * 2. The caller's acap binds to a subject that matches the | ||
| * vault entry's `bound_to`. | ||
| * 3. The resolver returns a value. | ||
| * | ||
| * Logs the outcome regardless of success. | ||
| */ | ||
| inject(ref: CredentialRef, caller_acap: ACap): Promise<OSResult<Injection>>; | ||
| /** Read-only snapshot of recent injection log entries. Audit substrate | ||
| * consumes this; the agent does not. */ | ||
| recentLogs(limit?: number): ReadonlyArray<InjectionLog>; | ||
| /** Number of registered entries. */ | ||
| size(): number; | ||
| /** Archive a credential reference. The entry is removed; resolvers | ||
| * may continue to hold the underlying secret independently. */ | ||
| archive(ref: CredentialRef): OSResult<true>; | ||
| private log; | ||
| } | ||
| /** Helper for tests: build an in-memory resolver pre-populated with a map. */ | ||
| export declare function inMemoryResolver(entries: Record<string, string>): CredentialResolver; | ||
| //# sourceMappingURL=vault.d.ts.map |
| {"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"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"} |
+132
| import { err, ok } from './types.js'; | ||
| export class Vault { | ||
| entries = new Map(); | ||
| resolver; | ||
| logs = []; | ||
| constructor(resolver) { | ||
| this.resolver = resolver ?? makeInMemoryResolver(); | ||
| } | ||
| /** Register a credential reference. Only metadata; the secret value | ||
| * stays with the resolver. */ | ||
| register(entry) { | ||
| if (this.entries.has(entry.ref)) { | ||
| return err('capability_denied', `vault entry ${entry.ref} already exists`); | ||
| } | ||
| this.entries.set(entry.ref, entry); | ||
| return ok(true); | ||
| } | ||
| /** Replace the resolver (for plugging in AWS Secrets Manager / Vault / | ||
| * 1Password etc. without changing the agent contract). */ | ||
| withResolver(resolver) { | ||
| this.resolver = resolver; | ||
| } | ||
| /** | ||
| * Inject a credential into a tool call. Returns the materialized | ||
| * injection or an error. Validates: | ||
| * 1. The credential exists in the vault. | ||
| * 2. The caller's acap binds to a subject that matches the | ||
| * vault entry's `bound_to`. | ||
| * 3. The resolver returns a value. | ||
| * | ||
| * Logs the outcome regardless of success. | ||
| */ | ||
| async inject(ref, caller_acap) { | ||
| const entry = this.entries.get(ref); | ||
| if (!entry) { | ||
| this.log(ref, caller_acap, undefined, 'missing'); | ||
| return err('namespace_violation', `vault has no entry for ${ref}`); | ||
| } | ||
| if (!subjectsMatch(caller_acap.subject, entry.bound_to)) { | ||
| this.log(ref, caller_acap, entry.bound_to, 'denied'); | ||
| return err('capability_denied', `acap subject does not match vault entry binding`, { | ||
| cred_ref: ref, | ||
| acap_subject: caller_acap.subject, | ||
| bound_to: entry.bound_to, | ||
| }); | ||
| } | ||
| const value = await this.resolver(ref); | ||
| if (value === null) { | ||
| this.log(ref, caller_acap, entry.bound_to, 'missing'); | ||
| return err('namespace_violation', `resolver returned null for ${ref}`); | ||
| } | ||
| this.log(ref, caller_acap, entry.bound_to, 'injected'); | ||
| return ok(materialize(entry.injection, value)); | ||
| } | ||
| /** Read-only snapshot of recent injection log entries. Audit substrate | ||
| * consumes this; the agent does not. */ | ||
| recentLogs(limit = 100) { | ||
| return this.logs.slice(-limit); | ||
| } | ||
| /** Number of registered entries. */ | ||
| size() { | ||
| return this.entries.size; | ||
| } | ||
| /** Archive a credential reference. The entry is removed; resolvers | ||
| * may continue to hold the underlying secret independently. */ | ||
| archive(ref) { | ||
| if (!this.entries.has(ref)) { | ||
| return err('namespace_violation', `vault has no entry for ${ref}`); | ||
| } | ||
| this.entries.delete(ref); | ||
| return ok(true); | ||
| } | ||
| log(cred_ref, caller, bound_subject, outcome) { | ||
| this.logs.push({ | ||
| cred_ref, | ||
| caller_acap: caller.id, | ||
| bound_subject: bound_subject ?? caller.subject, | ||
| injection_kind: 'header', | ||
| outcome, | ||
| at: new Date().toISOString(), | ||
| }); | ||
| } | ||
| } | ||
| function materialize(shape, value) { | ||
| switch (shape.kind) { | ||
| case 'header': | ||
| return { | ||
| kind: 'header', | ||
| name: shape.name, | ||
| header_value: shape.prefix !== undefined ? `${shape.prefix}${value}` : value, | ||
| }; | ||
| case 'query_param': | ||
| return { kind: 'query_param', name: shape.name, param_value: value }; | ||
| case 'bearer_token': | ||
| return { kind: 'bearer_token', header_value: `Bearer ${value}` }; | ||
| } | ||
| } | ||
| function subjectsMatch(a, b) { | ||
| if (a.kind !== b.kind) | ||
| return false; | ||
| switch (a.kind) { | ||
| case 'tool': | ||
| return a.name === b.name; | ||
| case 'mcp_server': | ||
| return a.server === b.server; | ||
| case 'resource': | ||
| return a.uri === b.uri; | ||
| case 'memory_block': | ||
| return a.block_id === b.block_id; | ||
| case 'audit_log': | ||
| return a.namespace === b.namespace; | ||
| case 'agent_handoff': | ||
| return a.target_pattern === b.target_pattern; | ||
| } | ||
| } | ||
| /** Default resolver — in-memory map for tests and local dev. Production | ||
| * deployments register a real resolver via `vault.withResolver()`. */ | ||
| function makeInMemoryResolver() { | ||
| const store = new Map(); | ||
| const fn = async (ref) => store.get(ref) ?? null; | ||
| fn.set = (ref, value) => store.set(ref, value); | ||
| return fn; | ||
| } | ||
| /** Helper for tests: build an in-memory resolver pre-populated with a map. */ | ||
| export function inMemoryResolver(entries) { | ||
| const store = new Map(Object.entries(entries)); | ||
| return async (ref) => { | ||
| const v = store.get(ref); | ||
| return v !== undefined ? v : null; | ||
| }; | ||
| } | ||
| //# sourceMappingURL=vault.js.map |
| {"version":3,"file":"vault.js","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"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"} |
+12
-9
@@ -5,20 +5,21 @@ /** | ||
| * Permissions, namespaces, resource quotas, content-addressed audit, | ||
| * and downscoped handoff. The OS-level substrate that runs above | ||
| * downscoped handoff, server-side credential injection, and rubric- | ||
| * graded self-evaluation. The OS-level substrate that runs above | ||
| * Modal-class sandboxes (Modal, Daytona, RunPod, E2B, local Docker) | ||
| * and below MCP/A2A as the wire formats agents speak. | ||
| * | ||
| * Eight primitives (v0.1 ships the first 5): | ||
| * Ten primitives (v0.2 ships 7 of 10): | ||
| * | ||
| * 1. spawn(manifest) ✓ src/spawn.ts | ||
| * 2. acap ✓ src/acap.ts | ||
| * 3. ns — namespaces are typed in src/types.ts; | ||
| * enforcement lands in v0.2 | ||
| * 3. ns — namespaces typed; enforcement v0.3 | ||
| * 4. ulimit-tok ✓ src/budget.ts | ||
| * 5. chexec ✓ src/taint.ts | ||
| * 6. audit — uses @kernel.chat/kbot-finance's hash-chained | ||
| * log directly; namespace isolation lands in v0.2 | ||
| * 7. handoff ✓ src/acap.ts (downscope() primitive) | ||
| * 8. snapshot — content-addressed agent state; v0.2 | ||
| * 6. audit — uses @kernel.chat/kbot-finance log; ns isolation v0.3 | ||
| * 7. handoff ✓ src/acap.ts (downscope()) | ||
| * 8. snapshot — content-addressed agent state; v0.3 | ||
| * 9. vault ✓ src/vault.ts (NEW v0.2 — from CMA) | ||
| * 10. outcomes ✓ src/outcomes.ts (NEW v0.2 — from CMA) | ||
| * | ||
| * Apache 2.0. Status: v0.1.0-alpha.0. Reference implementation; not | ||
| * Apache 2.0. Status: v0.2.0-alpha.0. Reference implementation; not | ||
| * yet certified for multi-tenant production. | ||
@@ -31,2 +32,4 @@ */ | ||
| export * from './taint.js'; | ||
| export * from './vault.js'; | ||
| export * from './outcomes.js'; | ||
| //# sourceMappingURL=index.d.ts.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA"} | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,eAAe,CAAA"} |
+12
-9
@@ -5,20 +5,21 @@ /** | ||
| * Permissions, namespaces, resource quotas, content-addressed audit, | ||
| * and downscoped handoff. The OS-level substrate that runs above | ||
| * downscoped handoff, server-side credential injection, and rubric- | ||
| * graded self-evaluation. The OS-level substrate that runs above | ||
| * Modal-class sandboxes (Modal, Daytona, RunPod, E2B, local Docker) | ||
| * and below MCP/A2A as the wire formats agents speak. | ||
| * | ||
| * Eight primitives (v0.1 ships the first 5): | ||
| * Ten primitives (v0.2 ships 7 of 10): | ||
| * | ||
| * 1. spawn(manifest) ✓ src/spawn.ts | ||
| * 2. acap ✓ src/acap.ts | ||
| * 3. ns — namespaces are typed in src/types.ts; | ||
| * enforcement lands in v0.2 | ||
| * 3. ns — namespaces typed; enforcement v0.3 | ||
| * 4. ulimit-tok ✓ src/budget.ts | ||
| * 5. chexec ✓ src/taint.ts | ||
| * 6. audit — uses @kernel.chat/kbot-finance's hash-chained | ||
| * log directly; namespace isolation lands in v0.2 | ||
| * 7. handoff ✓ src/acap.ts (downscope() primitive) | ||
| * 8. snapshot — content-addressed agent state; v0.2 | ||
| * 6. audit — uses @kernel.chat/kbot-finance log; ns isolation v0.3 | ||
| * 7. handoff ✓ src/acap.ts (downscope()) | ||
| * 8. snapshot — content-addressed agent state; v0.3 | ||
| * 9. vault ✓ src/vault.ts (NEW v0.2 — from CMA) | ||
| * 10. outcomes ✓ src/outcomes.ts (NEW v0.2 — from CMA) | ||
| * | ||
| * Apache 2.0. Status: v0.1.0-alpha.0. Reference implementation; not | ||
| * Apache 2.0. Status: v0.2.0-alpha.0. Reference implementation; not | ||
| * yet certified for multi-tenant production. | ||
@@ -31,2 +32,4 @@ */ | ||
| export * from './taint.js'; | ||
| export * from './vault.js'; | ||
| export * from './outcomes.js'; | ||
| //# sourceMappingURL=index.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA"} | ||
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,eAAe,CAAA"} |
+10
-2
| { | ||
| "name": "@kernel.chat/agent-os", | ||
| "version": "0.1.0-alpha.0", | ||
| "description": "POSIX for AI agents — permissions, namespaces, resource quotas, content-addressed audit, and downscoped handoff. The OS-level substrate that runs above Modal-class sandboxes and below MCP/A2A.", | ||
| "version": "0.2.0-alpha.0", | ||
| "description": "POSIX for AI agents — permissions, namespaces, resource quotas, content-addressed audit, downscoped handoff, server-side credential vaults, and rubric-graded outcomes. The OS-level substrate that runs above Modal-class sandboxes and below MCP/A2A.", | ||
| "type": "module", | ||
@@ -25,2 +25,10 @@ "license": "Apache-2.0", | ||
| "types": "./dist/audit.d.ts" | ||
| }, | ||
| "./vault": { | ||
| "import": "./dist/vault.js", | ||
| "types": "./dist/vault.d.ts" | ||
| }, | ||
| "./outcomes": { | ||
| "import": "./dist/outcomes.js", | ||
| "types": "./dist/outcomes.d.ts" | ||
| } | ||
@@ -27,0 +35,0 @@ }, |
107349
44.68%34
30.77%1409
54.33%