Live code reference
This page is generated from the package runtime TypeScript during the site build. Signatures are source text, not a hand-maintained API copy.
Key components
- dispatch_worker — The supervisor submits a bounded request and receives one validated terminal worker result. The request selects the worker mode, context packet, optional skills, model role, and timeout.
- launchPiWorker — The launcher starts a clean Pi process, limits its visible tools, and turns cancellation or timeout into a controlled process stop before dispatch accepts a result.
- project_status — This registered tool reports hash and dependency observations or atomically records acknowledgement. It reports mechanical state only; it does not judge semantic drift.
- compact — Custom compaction creates bounded project snapshots, asks the configured model for validated working memory, and writes at most five unreviewed proposals to the inbox.
- literature_search — The read-only literature tool is available to the supervisor and selected research workers; it queries the configured local SQLite FTS database and returns matching metadata, snippets, scores, and resolved source paths.
Important TypeBox schemas
statusSchema—extensions/workbench/index.tsdispatchSchema—extensions/workbench/src/worker-engine.tsworkerResultSchema—extensions/workbench/src/worker-engine.ts
Runtime exports
extensions/plannotator/index.ts
function: piSychPlannotator
export default async function piSychPlannotator(pi: ExtensionAPI): Promise<void>;extensions/plannotator/runtime.ts
interface: PlannotatorRuntime
export interface PlannotatorRuntime {
preload(): Promise<unknown>;
last(ctx: ExtensionCommandContext): ReturnType<typeof startLastMessageAnnotation>;
file(
ctx: ExtensionCommandContext,
path: string,
content: string,
): ReturnType<typeof startFileAnnotation>;
review(
ctx: ExtensionCommandContext,
args: ReturnType<typeof parseCodeReviewArgs>,
): ReturnType<typeof startCodeReview>;
}function: registerPlannotator
export async function registerPlannotator(
pi: ExtensionAPI,
runtime: PlannotatorRuntime = defaultRuntime,
): Promise<void>;extensions/workbench/index.ts
constant: PACKAGE_ROOT
export const PACKAGE_ROOT = resolve(
process.env.PI_PACKAGE_DIR ?? resolve(import.meta.dirname, "../.."),
);constant: SUPERVISOR_GUIDANCE
export const SUPERVISOR_GUIDANCE = [
"Pi Sych is a small mechanical substrate; skills and humans own semantic judgment.",
"Keep replies concise. Use direct work and read-only retrieval (literature_search; web when active) for small or tightly connected exploration; dispatch for independent context, breadth, specialization, or substantial execution.",
"Use project_status for mechanical state; changed content is not conceptual drift.",
`For Pi Sych questions, read ${PACKAGE_ROOT}/README.md and its linked documentation.`,
"Before dispatch, inspect the available skill catalogue and select only skills valuable for the assignment. dispatch_worker defaults to clean context and 90 seconds. Use trajectory context only when prior conversation materially helps; choose context, model role, and timeout deliberately. Worker modes are not sandboxes.",
"Treat the configured proposal inbox as human-review proposal state: report its pending count through project_status and read it only when the user requests inbox review.",
].join("\n");function: formatDispatchWorkerCallSummary
export function formatDispatchWorkerCallSummary(
args: Pick<
DispatchRequest,
| "task"
| "contextMode"
| "modelRole"
| "thinkingLevel"
| "mode"
| "skills"
| "remoteResearch"
| "timeoutMs"
>,
);function: formatDispatchWorkerOutcome
export function formatDispatchWorkerOutcome(outcome: DispatchOutcome);constant: shouldCompactAt100k
export const shouldCompactAt100k = (enabled: boolean, tokens?: number | null) =>
enabled && (tokens ?? 0) >= 100_000;function: configuredSupervisorInstructions
export async function configuredSupervisorInstructions(cwd: string, existing = "");function: piSychWorkbench
export default async function piSychWorkbench(pi: ExtensionAPI): Promise<void>;export: re-export
export { MAX_TIMEOUT_MS };extensions/workbench/src/compaction.ts
interface: Memory
export interface Memory {
task: string;
constraints: string[];
active: string[];
blockers: string[];
next: string;
files: string[];
}typealias: PromotionTarget
export type PromotionTarget =
| "project"
| "agents"
| "personal-agents"
| "style"
| "evidence"
| "decisions"
| "todo";interface: Promotion
export interface Promotion {
target: PromotionTarget;
proposal: string;
}function: validateWorkingMemory
export function validateWorkingMemory(value: unknown): Memory;function: parseCompactionModelOutput
export function parseCompactionModelOutput(raw: string): {
workingMemory: Memory;
promotions: Promotion[];
};function: renderWorkingMemory
export function renderWorkingMemory(memory: Memory): string;constant: COMPACTION_FILE_BYTE_LIMIT
export const COMPACTION_FILE_BYTE_LIMIT = 16 * 1024;constant: COMPACTION_TOTAL_BYTE_LIMIT
export const COMPACTION_TOTAL_BYTE_LIMIT = 48 * 1024;function: pendingPromotions
export async function pendingPromotions(
project: Pick<ResolvedProject, "canonical">,
): Promise<number>;function: filterWorkingMemoryFiles
export async function filterWorkingMemoryFiles(
project: ResolvedProject,
snapshotPaths: Set<string>,
files: string[],
): Promise<string[]>;function: compactionSnapshot
export async function compactionSnapshot(
project: ResolvedProject,
state: Awaited<ReturnType<typeof checkProjectStatus>>,
);function: buildCompactionPrompt
export function buildCompactionPrompt(
event: SessionBeforeCompactEvent,
snapshot: Awaited<ReturnType<typeof compactionSnapshot>>,
status: Awaited<ReturnType<typeof checkProjectStatus>>,
inboxPath: string,
);function: compact
export async function compact(
event: SessionBeforeCompactEvent,
ctx: ExtensionContext,
completeModel = complete,
);extensions/workbench/src/config-directory.ts
interface: PiSychConfig
export interface PiSychConfig {
version: 1;
workerAgentDir: string;
modelCatalog: string;
mcporterConfig: string;
literatureDatabase?: string;
compaction: { custom: boolean; compactAt100k: boolean };
review: { mode: "plannotator" | "manual" };
}constant: DEFAULT_CONFIG
export const DEFAULT_CONFIG = {
version: 1,
workerAgentDir: "worker-agent",
modelCatalog: "models.json",
mcporterConfig: "mcp/mcporter.json",
compaction: { custom: true, compactAt100k: false },
review: { mode: "plannotator" },
} satisfies PiSychConfig;interface: ConfigDirectoryOptions
export interface ConfigDirectoryOptions {
projectRoot?: string;
env?: NodeJS.ProcessEnv;
home?: string;
exists?: (path: string) => boolean;
configDirectory?: string;
}function: piConfigRoot
export function piConfigRoot({
projectRoot,
env = process.env,
home = homedir(),
exists = existsSync,
}: ConfigDirectoryOptions = {}): string;constant: piSychConfigDirectory
export const piSychConfigDirectory = (options: ConfigDirectoryOptions = {}) =>
options.configDirectory ?? resolve(piConfigRoot(options), "pi-sych");constant: piSkillDirectory
export const piSkillDirectory = (options: ConfigDirectoryOptions = {}) =>
resolve(piConfigRoot(options), "skills");function: loadPiSychConfig
export function loadPiSychConfig(options: ConfigDirectoryOptions = {}): PiSychConfig;function: piSychConfigPath
export function piSychConfigPath(
key: "workerAgentDir" | "modelCatalog" | "mcporterConfig",
options: ConfigDirectoryOptions = {},
): string;function: ensurePiSychConfig
export async function ensurePiSychConfig(options: ConfigDirectoryOptions = {}): Promise<string>;extensions/workbench/src/literature-search.ts
interface: LiteratureResult
export interface LiteratureResult {
metadata: {
title: unknown;
itemType: string | null;
creators: unknown;
year: unknown;
doi: unknown;
};
snippet: unknown;
score: unknown;
sourcePath: string;
}function: literatureDatabasePath
export function literatureDatabasePath(projectRoot: string, configDirectory?: string): string;function: searchLiterature
export function searchLiterature(
projectRoot: string,
queryText: string,
limit = 10,
configDirectory?: string,
): LiteratureResult[];function: registerLiteratureSearch
export function registerLiteratureSearch(
pi: ExtensionAPI,
configDirectory?: string,
resolveProjectRoot: (cwd: string) => string | Promise<string> = (cwd) => cwd,
): void;extensions/workbench/src/mcporter.ts
constant: remoteResearchExtensionPaths
export const remoteResearchExtensionPaths = (
enabled: boolean,
resolveExtension = () => require.resolve("pi-mcporter/dist/index.js"),
) => {
if (!enabled) return [];
try {
return [resolveExtension()];
} catch {
throw new Error("pi-mcporter is not installed; run npm install pi-mcporter@latest");
}
};interface: McporterDiagnostic
export interface McporterDiagnostic {
available: boolean;
configPath: string;
configExists: boolean;
servers: string[];
configError?: string;
}constant: mcporterConfigPath
export const mcporterConfigPath = (projectRoot?: string) =>
piSychConfigPath("mcporterConfig", projectRoot ? { projectRoot } : {});function: inspectMcporter
export function inspectMcporter(configPath = mcporterConfigPath()): McporterDiagnostic;constant: formatMcporterDiagnostic
export const formatMcporterDiagnostic = (value: McporterDiagnostic) =>
[
"Pi Sych MCPorter diagnostics",
`extension: ${value.available ? "available" : "unavailable"}`,
`config: ${value.configPath} (${value.configExists ? "present" : "missing"})`,
`servers: ${value.servers.join(", ") || "none"}`,
...(value.configError ? [`config error: ${value.configError}`] : []),
].join("\n");extensions/workbench/src/model-catalog.ts
interface: ModelEntry
export interface ModelEntry {
model: string;
cost?: string;
notes?: string;
}interface: ModelCatalog
export interface ModelCatalog {
default: string;
models: Record<string, ModelEntry>;
}function: parseModelCatalog
export function parseModelCatalog(value: unknown): ModelCatalog;function: modelCatalogPath
export function modelCatalogPath(
projectRoot?: string,
env: NodeJS.ProcessEnv = process.env,
): string;function: loadModelCatalog
export function loadModelCatalog(
projectRoot?: string,
env: NodeJS.ProcessEnv = process.env,
): ModelCatalog;function: loadOptionalModelCatalog
export function loadOptionalModelCatalog(
projectRoot?: string,
env: NodeJS.ProcessEnv = process.env,
): ModelCatalog | undefined;extensions/workbench/src/pew-pew.ts
function: enabledPewPewExtension
export async function enabledPewPewExtension(
tools: readonly ToolInfo[],
activeTools: readonly string[],
): Promise<string | undefined>;extensions/workbench/src/plannotator.ts
interface: AnnotationDecision
export interface AnnotationDecision {
feedback?: string;
exit?: boolean;
}interface: CodeReviewDecision
export interface CodeReviewDecision extends AnnotationDecision {
approved?: boolean;
}interface: AnnotationSession
export interface AnnotationSession {
url: string;
waitForDecision(): Promise<AnnotationDecision>;
}interface: CodeReviewSession
export interface CodeReviewSession {
url: string;
waitForDecision(): Promise<CodeReviewDecision>;
}interface: CodeReviewRequest
export interface CodeReviewRequest {
prUrl?: string;
vcsType?: "git" | "gitbutler";
useLocal?: boolean;
}constant: plannotatorUnavailable
export const plannotatorUnavailable = (reason?: string) =>
new Error(
`Plannotator unavailable; ensure its integration is installed${reason ? ` and compatible: ${reason}` : ""}`,
);function: loadPlannotator
export async function loadPlannotator(): Promise<Plannotator>;constant: startFileAnnotation
export const startFileAnnotation = async (ctx: ExtensionContext, path: string, content: string) =>
(await loadPlannotator()).startMarkdownAnnotationSession(ctx, path, content, "annotate");constant: startLastMessageAnnotation
export const startLastMessageAnnotation = async (ctx: ExtensionContext) => {
const api = await loadPlannotator(),
text = api.getLastAssistantMessageText(ctx);
return text ? api.startLastMessageAnnotationSession(ctx, text) : undefined;
};function: parseCodeReviewArgs
export function parseCodeReviewArgs(input = ""): CodeReviewRequest;constant: startCodeReview
export const startCodeReview = async (ctx: ExtensionContext, options: CodeReviewRequest = {}) =>
(await loadPlannotator()).startCodeReviewBrowserSession(ctx, options);extensions/workbench/src/project-files.ts
constant: CANONICAL_FILES
export const CANONICAL_FILES = [
"project",
"agents",
"style",
"evidence",
"decisions",
"todo",
"inbox",
] as const;typealias: CanonicalFile
export type CanonicalFile = (typeof CANONICAL_FILES)[number];constant: DEFAULT_CANONICAL_PATHS
export const DEFAULT_CANONICAL_PATHS = {
project: "PROJECT.md",
agents: "AGENTS.md",
style: "STYLE.md",
evidence: "EVIDENCE.md",
decisions: "DECISIONS.md",
todo: "TODO.md",
inbox: "INBOX.md",
} satisfies Record<CanonicalFile, string>;interface: SyncManifest
export interface SyncManifest {
version: 2;
projectRoot?: string;
canonical?: Partial<Record<CanonicalFile, string>>;
confirmedAt: string;
artifacts: unknown[];
[key: string]: unknown;
}interface: ResolvedProject
export interface ResolvedProject {
cwd: string;
workspaceRoot: string;
projectRoot: string;
syncPath: string;
manifest?: SyncManifest;
syncError?: string;
canonical: Record<CanonicalFile, string>;
}interface: ProjectValidation
export interface ProjectValidation {
valid: boolean;
errors: string[];
headings: string[];
}constant: showPath
export const showPath = (root: string, path: string) => {
const display = relative(root, path);
return display && display !== ".." && !display.startsWith(`..${sep}`) && !isAbsolute(display)
? display
: path;
};function: parseSyncManifest
export function parseSyncManifest(value: string): SyncManifest;constant: formatSyncManifest
export const formatSyncManifest = (manifest: SyncManifest) =>
`${JSON.stringify(manifest, null, 2)}\n`;function: resolveProject
export async function resolveProject(startPath: string): Promise<ResolvedProject>;function: validateProjectMarkdown
export function validateProjectMarkdown(markdown: string): ProjectValidation;constant: readAndValidateProject
export const readAndValidateProject = async (path: string) =>
validateProjectMarkdown(await readFile(path, "utf8"));function: resolveProjectPath
export function resolveProjectPath(root: string, path: string);function: resolveConfiguredPath
export async function resolveConfiguredPath(path: string);function: resolveExistingProjectPath
export async function resolveExistingProjectPath(root: string, path: string);function: resolveExistingProjectContextPath
export async function resolveExistingProjectContextPath(root: string, path: string);function: writeAtomicFile
export async function writeAtomicFile(path: string, content: string);extensions/workbench/src/project-status.ts
constant: PROJECT_STATUSES
export const PROJECT_STATUSES = [
"current",
"stale",
"needs-review",
"conflicted",
"missing",
] as const;typealias: ProjectStatus
export type ProjectStatus = (typeof PROJECT_STATUSES)[number];typealias: Dependency
export type Dependency = string | { path: string; reason: string };interface: ProjectArtifact
export interface ProjectArtifact {
path: string;
fingerprint: string;
status: ProjectStatus;
role?: string;
authoritativeFor?: string[];
updateFrom?: Dependency[];
dependsOn?: Dependency[];
acknowledgement?: { at: string; reason: string };
[key: string]: unknown;
}interface: ProjectStatusManifest
export interface ProjectStatusManifest extends Omit<SyncManifest, "artifacts"> {
artifacts: ProjectArtifact[];
}typealias: Observation
export type Observation =
| { state: "current" | "changed"; fingerprint: string }
| { state: "missing" }
| { state: "error"; message: string };interface: CheckedArtifact
export interface CheckedArtifact extends ProjectArtifact {
observation: Observation;
}interface: ProjectStatusCheck
export interface ProjectStatusCheck {
projectRoot: string;
syncPath: string;
manifest?: ProjectStatusManifest;
syncError?: string;
artifacts: CheckedArtifact[];
changed: string[];
missing: string[];
errors: Array<{ path: string; message: string }>;
impacted: Array<{ path: string; from: string[]; direct: boolean }>;
cycles: string[][];
missingCore: string[];
projectErrors: string[];
}function: parseProjectStatusManifest
export function parseProjectStatusManifest(value: string | SyncManifest): ProjectStatusManifest;function: fingerprintFile
export async function fingerprintFile(path: string);function: checkProjectStatus
export async function checkProjectStatus(
startPath: string,
project?: ResolvedProject,
): Promise<ProjectStatusCheck>;function: formatProjectStatusCheck
export function formatProjectStatusCheck(
state: ProjectStatusCheck,
pending = 0,
inboxPath = "INBOX.md",
): string;function: verifyAcknowledgementObservation
export async function verifyAcknowledgementObservation(
state: ProjectStatusCheck,
selected: Set<string>,
);function: acknowledgeProjectStatus
export async function acknowledgeProjectStatus(
startPath: string,
files: string[],
reason: string,
now = new Date(),
);extensions/workbench/src/validation.ts
constant: nonEmptyString
export const nonEmptyString = (value: unknown, label: string) => {
if (typeof value !== "string" || !value.trim())
throw new Error(`${label} must be a non-empty string`);
return value.trim();
};constant: stringArray
export const stringArray = (value: unknown, label: string) => {
if (!Array.isArray(value) || value.some((item) => typeof item !== "string"))
throw new Error(`${label} must be an array of strings`);
return value.map((item) => item.trim()).filter(Boolean);
};extensions/workbench/src/worker-engine.ts
constant: WORKER_MODES
export const WORKER_MODES = ["read-only", "edit", "full-host"] as const;typealias: WorkerMode
export type WorkerMode = (typeof WORKER_MODES)[number];constant: CONTEXT_MODES
export const CONTEXT_MODES = ["clean", "trajectory"] as const;typealias: ContextMode
export type ContextMode = (typeof CONTEXT_MODES)[number];constant: THINKING_LEVELS
export const THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"] as const;constant: DEFAULT_TIMEOUT_MS
export const DEFAULT_TIMEOUT_MS = 90_000;constant: MAX_TIMEOUT_MS
export const MAX_TIMEOUT_MS = 30 * 60_000;constant: PI_SYCH_PACKAGE_ROOT
export const PI_SYCH_PACKAGE_ROOT = resolve(
process.env.PI_PACKAGE_DIR ?? resolve(import.meta.dirname, "../../.."),
);interface: ContextFile
export interface ContextFile {
path: string;
purpose: string;
}typealias: DispatchRequest
export type DispatchRequest = Static<typeof dispatchSchema>;typealias: WorkerResult
export type WorkerResult = Static<typeof workerResultSchema>;interface: WorkerLaunchSpec
export interface WorkerLaunchSpec {
id: string;
request: DispatchRequest;
workerAgentDir: string;
piSychConfigDirectory?: string;
resultPath: string;
projectRoot: string;
model: string;
prompt: string;
packageRoot: string;
extraExtensionPaths: string[];
webExtensionPath?: string;
sessionPath?: string;
onActivity?: (activity: readonly string[]) => void;
signal?: AbortSignal;
}interface: WorkerLaunchOutcome
export interface WorkerLaunchOutcome {
exitCode: number | null;
stderr: string;
classification?: "cancelled" | "timeout" | "spawn-failure";
terminationSignal?: NodeJS.Signals | null;
}interface: DispatchOutcome
export interface DispatchOutcome {
id: string;
model: string;
timeoutMs: number;
launch: WorkerLaunchOutcome;
result?: WorkerResult;
error?: string;
}typealias: WorkerLauncher
export type WorkerLauncher = (spec: WorkerLaunchSpec) => Promise<WorkerLaunchOutcome>;constant: dispatchSchema
export const dispatchSchema = Type.Object({
task: Type.String({ description: "One explicit bounded assignment for the worker" }),
mode: StringEnum(WORKER_MODES, { description: "Visible worker tool capability" }),
expectedOutput: Type.String({ description: "Required terminal result or file deliverable" }),
contextMode: Type.Optional(
StringEnum(CONTEXT_MODES, {
description: "Conversation context: clean by default, or persisted pre-dispatch trajectory",
}),
),
contextFiles: Type.Array(
Type.Object({
path: Type.String({ description: "Existing context file; relative paths are project-local" }),
purpose: Type.String({ description: "Why the worker needs this file" }),
}),
{ description: "Smallest complete explicit file packet" },
),
skills: Type.Optional(
Type.Array(Type.String(), {
description: "Exact selectors chosen after inspecting the available skill catalogue",
}),
),
modelRole: Type.Optional(Type.String({ description: "Exact configured worker model role" })),
thinkingLevel: Type.Optional(
StringEnum(THINKING_LEVELS, {
description: "Pi thinking level; omission leaves the selected model's default intact",
}),
),
remoteResearch: Type.Optional(
Type.Boolean({ description: "Expose configured remote-research integrations for this task" }),
),
timeoutMs: Type.Optional(
Type.Integer({
minimum: 1,
maximum: MAX_TIMEOUT_MS,
description: "Bounded runtime in milliseconds; defaults to 90000",
}),
),
});constant: toolsForRequest
export const toolsForRequest = (
request: Pick<DispatchRequest, "mode" | "remoteResearch" | "skills">,
webEnabled = false,
) => [
...MODE_TOOLS[request.mode],
...(request.skills?.includes("research") ? ["literature_search"] : []),
...(request.remoteResearch ? ["mcporter"] : []),
...(request.remoteResearch && webEnabled ? ["web"] : []),
];function: skillPaths
export function skillPaths(
selectors: string[] = [],
projectRoot: string,
packageRoot: string,
userRoot?: string,
): string[];constant: modelFor
export const modelFor = (catalog: ModelCatalog, role?: string) => {
const key = role ?? catalog.default,
model = catalog.models[key]?.model;
if (!model) throw new Error(`Unknown worker model: ${key}`);
return model;
};function: taskPrompt
export function taskPrompt(spec: WorkerLaunchSpec, files: ContextFile[]);function: prepareTrajectorySession
export async function prepareTrajectorySession(options: {
manager: SupervisorSession;
toolCallId: string;
runtimePath: string;
}): Promise<string>;function: writeImmutableResult
export async function writeImmutableResult(path: string, result: WorkerResult);constant: workerResultSchema
export const workerResultSchema = Type.Object({
status: StringEnum(["complete", "partial", "failed"] as const),
summary: Type.String(),
files: Type.Array(Type.String()),
limitations: Type.Array(Type.String()),
});function: validateWorkerResult
export function validateWorkerResult(value: unknown): WorkerResult;function: launchPiWorker
export async function launchPiWorker(
spec: WorkerLaunchSpec,
spawnWorker = spawn,
): Promise<WorkerLaunchOutcome>;function: dispatchWorker
export async function dispatchWorker(options: {
project: ResolvedProject;
workerAgentDir: string;
piSychConfigDirectory?: string;
request: DispatchRequest;
catalog: ModelCatalog;
packageRoot?: string;
extraExtensionPaths?: string[];
webExtensionPath?: string;
trajectory?: { manager: SupervisorSession; toolCallId: string };
launcher?: WorkerLauncher;
onActivity?: (activity: readonly string[]) => void;
signal?: AbortSignal;
}): Promise<DispatchOutcome>;extensions/worker/index.ts
function: piSychWorker
export default function piSychWorker(pi: ExtensionAPI): void;