@sema-agent/core
Version:
Stateless, task-oriented AI agent core
115 lines (114 loc) • 8.48 kB
TypeScript
import type { ResolvedSkillListingBudget } from "../skill-listing-budget.js";
import { type StoredSession } from "../session.js";
import type { RunnerDeps, TaskSpec, ToolSpec } from "../types.js";
import { type SkillGrantTable, type SkillSeatReader } from "../skill-grant.js";
import { type AllowEntryTable } from "../allow-entry.js";
import type { AnnounceOnceSink, Prepared, PrepareResume, RunInternals, ToolFaceSnapshot } from "./contracts.js";
import { normalizeSkills } from "./synthetic-tools.js";
import { RosterBuilder } from "../tool-roster.js";
export interface PrepareProjectContextInput {
/** borrowed-readonly — the deployment seams this phase reads: `loadProjectMemory` (the snapshot),
* `onError` (the operator lane for a throwing seam / seeding / oversize skill), `sharedMemoryStores`
* (the shared-memory pair's switch: wired ⇒ mount). Receiver preserved (`deps.onError?.(…)`). */
deps: Pick<RunnerDeps, "loadProjectMemory" | "onError" | "sharedMemoryStores" | "onNotice" | "allowedTools">;
/** borrowed-readonly — the REBOUND spec (`spec′`). Read: `sessionId` (phase derivation + the
* continuation projections), `skills` (the roster), `userInvokedSkills` (the person's invoked skills — their
* rows are written here), `principal` (the shared-memory tools' trusted identity). Never mutated. */
spec: Pick<TaskSpec, "sessionId" | "skills" | "userInvokedSkills" | "principal">;
/** borrowed-readonly — trusted internals: `agentName` (seam ctx), `inheritedSkillGrants` (the parent's captured
* skill grant rows, seeded as `inherited`), `inheritedAllowedTools` (the parent's request entries, seeded as this leg's
* own). `undefined` on a standalone prepare. */
internals: Pick<RunInternals, "agentName" | "inheritedSkillGrants" | "inheritedAllowedTools"> | undefined;
/** borrowed-readonly — the request's `allowedTools`, screened and snapshotted at the config door (before the first await). */
allowedTools: readonly string[] | undefined;
/** borrowed-mutable — the request's and the deployment's allow-entry tables (identity is the contract: the gate's lanes and
* the delegation capture alias these objects). Seeded here, once; nothing writes them after this phase. */
allowedToolTables: {
readonly request: AllowEntryTable;
readonly deployment: AllowEntryTable;
};
/** borrowed-readonly — the acquired session; only `getBranch()` is read (phase derivation walk).
* The read is best-effort: a throw keeps the provisional phase. */
session: Pick<StoredSession, "getBranch">;
/** borrowed-readonly — the acquired session's id (seam ctx cache key; operator-line context). */
sessionId: string;
/** borrowed-readonly — `spec.taskId ?? sessionId`: the shared-memory tools' trusted task identity. */
hostTaskId: string;
/** borrowed-readonly — the FINAL task root (post-restore): the seam's `cwd`. */
taskRootFinal: string;
/** borrowed-readonly — whether a real execution env is mounted (seam ctx flag). */
handsEnabled: boolean;
/** borrowed-readonly — the leg's effective-delegation facts; only `isNonForkChild` is read (the
* seam's `isSubagent` — one derivation shared with the prompt fact, never re-derived here). */
delegation: {
readonly isNonForkChild: boolean;
};
/** borrowed-readonly — the hands phase's read-state seeding closure (CREATED there, CALLED here for
* the snapshot's declared `seededFiles`); `undefined` on a hands-less task = nothing to seed. */
seedContextFiles: ((files: ReadonlyArray<{
path: string;
content: string;
}>) => Promise<void>) | undefined;
/** borrowed-readonly — the memory phase's composed block, as returned (recall discipline + engine
* files). This phase APPENDS the project layer and hands the result back as
* {@link PrepareProjectContextResult.memoryBlock}; the input value itself is never mutated. */
memoryBlockFromEngine: string | undefined;
/** borrowed-mutable — the run's skill grant table (identity is the contract: the `skill` tool, the gate's lane and the
* ctx capture alias this exact object). Mutated here: the parent's captured rows (`inherited`) and the person's invoked
* skills (`user`); after this phase only the `skill` tool writes (on activation). */
skillGrants: SkillGrantTable;
/** borrowed-mutable — the run's roster builder (later refs alias its read face; in-place contract). Mutated
* here: `mount` of the `skill` tool, the shared-memory pair and the engine-memory pair. Occupancy
* is judged on the ALREADY-MOUNTED read face (names + aliases). */
roster: RosterBuilder;
/** borrowed-readonly — the frozen task-start tool face; only `exclude` is read (pair yield ①). */
toolFaceSnapshot: Pick<ToolFaceSnapshot, "exclude">;
/** borrowed-readonly — the once-per-session announcement ledger; only its deduplicated `onError`
* sink is invoked (a pair's mount shape is a session-level fact, announced once). */
onceLedger: AnnounceOnceSink;
/** borrowed-readonly — the memory phase's engine-pair ToolSpecs (present iff the pair may mount). */
memoryTools: ToolSpec[] | undefined;
/** borrowed-readonly — the memory phase's session seat; only `!== undefined` is read (the
* blocked-mount disclosure fires only when a session mounted). */
memoryEngineSession: Prepared["memoryEngineSession"];
/** borrowed-readonly — the engine pair's early conjuncts (computed before the memory phase). */
memorySearchToolsPlanned: boolean;
/** borrowed-readonly — the engine-pair name the exclusion valve removed, if any (disclosure text). */
memoryPairExcludedName: string | undefined;
/** borrowed-readonly — the engine-pair name a declared tool already occupies, if any (disclosure text). */
memoryPairOccupiedName: string | undefined;
/** borrowed-readonly — the durable-resume carrier; read for `!== undefined` (seedAnnounced),
* `seed.announcedListings.skills` (the removal-to-zero projection's gate) and `seed.skillGrants` (the frozen grant rows). */
resume: Pick<PrepareResume, "seed"> | undefined;
/** borrowed-readonly — the lowered listing-budget seats from the config door. The listing projection
* carries it to the boundary renderer, and the over-budget disclosure below is priced against it. */
skillListingBudget: ResolvedSkillListingBudget;
}
export interface PrepareProjectContextResult {
/** owned — the memory block with the project layer appended at the tail (unchanged when the seam is
* unwired or returns null/blank). The driver binds it under a NEW name; the defer-classification
* stretch may still strip the recall-discipline segment from it. */
memoryBlock: string | undefined;
/** owned — the snapshot's declared instruction sources (non-empty only), for the run loop's
* instructions_change lane (`Prepared.instructionSources`). */
instructionSources: ReadonlyArray<{
path: string;
contentHash: string | null;
}> | undefined;
/** owned — the RAW snapshot text (pre-compose) for the compaction lanes' instruction-file seat
* (`Prepared.projectInstructionContent`). */
projectInstructionContent: string | undefined;
/** owned — the normalized, load-gated skills (first-wins dedupe, name-sorted). Consumed inside this
* phase (tool + listing); exposed as the phase's own product. */
skillSpecs: ReturnType<typeof normalizeSkills>;
/** owned — the `Skill` tool's per-call seat over the loaded skills (`Execute skill: <name>`); `undefined` with no skill. */
skillSeatOf: SkillSeatReader | undefined;
/** owned — the skills-listing projection the run loop's announce lane consumes (`Prepared.skillsListing`). */
skillsListing: Prepared["skillsListing"];
/** owned — whether the shared-memory pair mounted here (the support-name pre-check reads it). */
sharedMemoryPairMounted: boolean;
/** owned — whether the engine-memory pair mounted here (the support-name pre-check reads it). */
memoryEnginePairMounted: boolean;
}
/** The M9 phase body — prepareTask's project-context stretch, verbatim (see the module header). */
export declare function prepareProjectContext(input: PrepareProjectContextInput): Promise<PrepareProjectContextResult>;