ConusAI vendor v0.1.0-beta.114
ci / gate (push) Waiting to run

This commit is contained in:
ConusAI vendor v0.1.0-beta.114
2026-11-14 09:56:45 +00:00
commit 1ce8d23c35
867 changed files with 122104 additions and 0 deletions
+39
View File
@@ -0,0 +1,39 @@
// The ports the agent module's use cases are written against, and the tokens the composition
// roots bind. The runtime itself (durable run record, step log, engine) is @conusai-kit/agent;
// this module is its template integration: procedures, job and pages.
import { type TenantScope, token } from "@conusai-kit/core"
import type { DataSource } from "@conusai-kit/data"
export type AgentScope = TenantScope & { workspaceId: string; projectId: string }
export interface AgentDeps {
readonly data: DataSource
}
/**
* The project a run's job executes in, with a system actor. The worker binds it per job from the
* enqueueing scope (the same arrangement as `DOCUMENTS_SCOPE`, decision AT-F6): a payload never
* names a tenant.
*/
export const AGENT_SCOPE = token<TenantScope>("agent.scope")
/** The scope the tools adapter needs to review persisted proposals in the console. */
export interface AgentActionScope {
readonly orgSlug: string
readonly workspaceSlug: string
readonly projectSlug: string
}
/** Resolves the slug scope the registry's tool-actions API is addressed by, from ids. */
export async function actionScopeOf(
data: import("@conusai-kit/data").DataSource,
scope: AgentScope,
): Promise<AgentActionScope> {
const { organizations, workspaces, projects } = await import("@conusai-kit/tenancy")
const org = await data.global(organizations).get(scope.orgId)
const workspace = await data.forScope(scope).of(workspaces).get(scope.workspaceId)
const project = await data.forScope(scope).of(projects).get(scope.projectId)
if (!org || !workspace || !project) throw new Error("the run's organization, workspace or project is gone")
return { orgSlug: org.slug, workspaceSlug: workspace.slug, projectSlug: project.slug }
}
+301
View File
@@ -0,0 +1,301 @@
// The agent module's use cases: start a run, read one, list them, cancel one, and the approval
// queue. Every write is the run row and the outbox event in one transaction; the worker's
// subscriber enqueues the run job, and the engine (@conusai-kit/agent) does the durable execution.
import {
AGENT_ENTITIES,
type AgentRunRecord,
type AgentStepRecord,
admitPlan,
agentRuns,
answerOf,
clampBudget,
dataAgentPersistence,
dataRunStore,
isTerminalRunStatus,
} from "@conusai-kit/agent"
import { resumeAfter } from "@conusai-kit/agent/agui"
import { notFound, validationFailed } from "@conusai-kit/core"
import { type ApprovalView, RUN_JOB, type RunView, runResumeRequested } from "../contract/index.js"
import type { AgentDeps, AgentScope } from "./ports.js"
const DEFAULT_BUDGET = { maxCostMicrocents: 100_000_000, maxSteps: 10, maxDurationSeconds: 600 }
const PAGE = 50
export const runViewOf = async (deps: AgentDeps, scope: AgentScope, run: { id: string }): Promise<RunView> => {
const store = dataRunStore(deps.data, scope)
const record = await store.get(run.id)
if (!record) throw notFound("no such run")
const steps = await store.listSteps(run.id)
const stepViews = record.plan.map((planned) => {
const logged = steps.find((candidate) => candidate.key === planned.key)
return {
key: planned.key,
label: planned.label,
tool: planned.tool,
args: planned.args,
needsApproval: planned.needsApproval === true,
status: logged?.status ?? ("pending" as const),
attempts: logged?.attempts ?? 0,
error: logged?.error ?? null,
}
})
const answer = await answerOf(dataAgentPersistence(deps.data, scope), record)
return {
runId: record.id,
goal: record.goal,
status: record.status,
failureCode: record.failureCode,
failureDetail: record.failureDetail,
plan: stepViews,
usageCostMicrocents: record.usageCostMicrocents,
usageSteps: record.usageSteps,
percent: record.plan.length === 0 ? 0 : Math.min(record.usageSteps, record.plan.length) / record.plan.length,
cancelRequested: record.cancelRequestedAt !== null,
answer,
answerProvenance: answer === null ? null : record.answerProvenance,
actorId: record.actorId,
createdAt: record.createdAt,
startedAt: record.startedAt,
finishedAt: record.finishedAt,
}
}
/**
* Starts a run: the plan is admitted against the hard ceilings before anything is written, the run
* row and the resume event land in one transaction, and the subscriber's enqueue (singleton on
* the run id) is what actually starts the work. Idempotency is the caller's idempotency key at
* the transport; a repeated start with the same key answers the first run.
*/
export async function startRun(
deps: AgentDeps,
scope: AgentScope,
input: {
goal: string
plan: {
key: string
label: string
tool: string
args: Record<string, unknown>
needsApproval?: boolean | undefined
}[]
budget?: {
maxCostMicrocents?: number | undefined
maxSteps?: number | undefined
maxDurationSeconds?: number | undefined
}
},
): Promise<RunView> {
const budget = clampBudget({
maxCostMicrocents: input.budget?.maxCostMicrocents ?? DEFAULT_BUDGET.maxCostMicrocents,
maxSteps: input.budget?.maxSteps ?? DEFAULT_BUDGET.maxSteps,
maxDurationSeconds: input.budget?.maxDurationSeconds ?? DEFAULT_BUDGET.maxDurationSeconds,
})
// The plan is data here; the engine's steps come from these rows in the worker.
admitPlan(
input.plan.map((planned) => ({
key: planned.key,
label: planned.label,
invoke: () => Promise.resolve({ ok: true as const }),
})),
budget,
)
const run = await deps.data.unitOfWork.run(scope, async (tx) => {
const row = await tx.of(agentRuns).insert({
goal: input.goal,
plan: input.plan.map((planned) => ({
key: planned.key,
label: planned.label,
tool: planned.tool,
args: planned.args,
...(planned.needsApproval === true ? { needsApproval: true } : {}),
})),
status: "queued",
failureCode: null,
failureDetail: null,
actorId: scope.actor.userId,
budgetCostMicrocents: budget.maxCostMicrocents,
budgetSteps: budget.maxSteps,
budgetSeconds: budget.maxDurationSeconds,
usageCostMicrocents: 0,
usageSteps: 0,
cancelRequestedAt: null,
startedAt: null,
finishedAt: null,
})
await tx.publish(runResumeRequested, {
orgId: scope.orgId,
workspaceId: scope.workspaceId,
projectId: scope.projectId,
runId: row.id,
})
return row
})
return runViewOf(deps, scope, run)
}
/**
* Opens a run's event stream: the run must be one this scope can read (another organization's or
* project's run is not found, exactly as `agent.run.status` answers), and the resume point must
* belong to it. Answers the offset to replay after and a reader of the durable record. The reader
* reads the run row before its step log: both only move forward, so a step log newer than its run
* row projects a prefix of the next projection, never a terminal event ahead of its steps.
*/
export async function openRunEvents(
deps: AgentDeps,
scope: AgentScope,
input: { runId: string; after?: string | undefined },
): Promise<{
after: number
load: () => Promise<{ run: AgentRunRecord; steps: readonly AgentStepRecord[]; answer: string | null } | null>
}> {
const store = dataRunStore(deps.data, scope)
const persistence = dataAgentPersistence(deps.data, scope)
if (!(await store.get(input.runId))) throw notFound("no such run")
let after: number
try {
after = resumeAfter(input.runId, input.after)
} catch {
throw validationFailed([{ path: "after", message: "the offset does not belong to this run" }], "invalid offset")
}
return {
after,
load: async () => {
const run = await store.get(input.runId)
return run ? { run, steps: await store.listSteps(input.runId), answer: await answerOf(persistence, run) } : null
},
}
}
export async function getRun(deps: AgentDeps, scope: AgentScope, runId: string): Promise<RunView> {
return runViewOf(deps, scope, { id: runId })
}
export async function listRuns(
deps: AgentDeps,
scope: AgentScope,
input: { cursor?: string | undefined; limit?: number | undefined },
): Promise<{ runs: RunView[]; cursor?: string; hasMore: boolean }> {
const store = dataRunStore(deps.data, scope, { pageSize: PAGE })
const page = await store.list({
...(input.cursor === undefined ? {} : { cursor: input.cursor }),
...(input.limit === undefined ? {} : { limit: input.limit }),
})
return {
runs: await Promise.all(page.runs.map((run) => runViewOf(deps, scope, run))),
...("cursor" in page ? { cursor: page.cursor } : {}),
hasMore: page.hasMore,
}
}
/** The most ids one batch-get reads (contract C-05). */
export const MAX_BATCH = 100
/**
* The live collection's read-back: the runs with these ids, as the list shows them. A run this caller
* cannot see is not in the answer: the repository's tenant wall leaves it out.
*/
export async function getManyRuns(deps: AgentDeps, scope: AgentScope, runIds: readonly string[]): Promise<RunView[]> {
const page = await deps.data
.forScope(scope)
.of(agentRuns)
.list({ where: [{ field: "id", op: "in", values: [...new Set(runIds)] }], limit: MAX_BATCH })
return Promise.all(page.items.map((run) => runViewOf(deps, scope, run)))
}
/** Cancels a run: the persisted request is honored between steps and inside the in-flight call. */
export async function cancelRun(
deps: AgentDeps,
scope: AgentScope,
runId: string,
): Promise<{ runId: string; cancelled: boolean }> {
const store = dataRunStore(deps.data, scope)
const record = await store.get(runId)
if (!record) throw notFound("no such run")
if (record.cancelRequestedAt !== null) return { runId, cancelled: true }
await store.requestCancel(runId, new Date().toISOString())
// A parked run only notices the request when it is resumed; enqueue the resume so the cancel
// lands even while the run waits in awaiting_approval.
await deps.data.unitOfWork.run(scope, async (tx) => {
await tx.publish(runResumeRequested, {
orgId: scope.orgId,
workspaceId: scope.workspaceId,
projectId: scope.projectId,
runId,
})
})
return { runId, cancelled: true }
}
/**
* The approval queue: every step that parked an approval, with the EXACT stored proposed
* arguments. Nothing here is a model's narration; the arguments are what the tool was called
* with, copied before they were proposed.
*/
export async function listApprovals(deps: AgentDeps, scope: AgentScope): Promise<{ approvals: ApprovalView[] }> {
const approvals: ApprovalView[] = []
let cursor: string | undefined
for (;;) {
const page = await deps.data
.forScope(scope)
.of(agentRuns)
.list({
order: [{ field: "createdAt", direction: "desc" }],
limit: PAGE,
...(cursor === undefined ? {} : { cursor }),
})
for (const run of page.items) {
if (isTerminalRunStatus(run.status)) continue
const steps = await dataRunStore(deps.data, scope).listSteps(run.id)
for (const step of steps) {
// Only what still waits for a person: a decided approval or a step that moved on is history.
if (step.approval === null || step.approval.decision !== null || step.status !== "pending") continue
approvals.push({
runId: run.id,
stepKey: step.key,
goal: run.goal,
tool: step.approval.tool,
arguments: step.approval.arguments,
reviewUrl: step.approval.reviewUrl,
createdAt: run.createdAt,
})
}
}
if (!page.hasMore) break
cursor = page.cursor
}
return { approvals }
}
/**
* Records a person's decision on the step and resumes the run. An approved `needsApproval` step
* resumes its TanStack AI interrupt and runs once; an approved platform proposal re-enters the
* parked step, whose tools adapter re-calls with the step's idempotency key so the platform executes
* the approved, persisted proposal exactly once. Rejection cancels the run: nothing is executed. A
* step with nothing parked, or one already decided, is refused.
*/
export async function reviewApproval(
deps: AgentDeps,
scope: AgentScope,
input: { runId: string; stepKey: string; decision: "approve" | "reject" },
): Promise<{ runId: string; status: RunView["status"] }> {
const store = dataRunStore(deps.data, scope)
const record = await store.get(input.runId)
if (!record) throw notFound("no such run")
await store.decideApproval(input.runId, input.stepKey, input.decision === "approve" ? "approved" : "rejected")
if (input.decision === "reject") {
await store.requestCancel(input.runId, new Date().toISOString())
}
await deps.data.unitOfWork.run(scope, async (tx) => {
await tx.publish(runResumeRequested, {
orgId: scope.orgId,
workspaceId: scope.workspaceId,
projectId: scope.projectId,
runId: input.runId,
})
})
return { runId: input.runId, status: (await store.get(input.runId))?.status ?? record.status }
}
export { AGENT_ENTITIES, RUN_JOB }