diff --git a/agents/intern/package.json b/agents/intern/package.json new file mode 100644 index 000000000..435db2f49 --- /dev/null +++ b/agents/intern/package.json @@ -0,0 +1,13 @@ +{ + "name": "@corbits/agent-intern", + "version": "0.1.0", + "private": true, + "type": "module", + "license": "SEE LICENSE IN LICENSE.md", + "exports": { + ".": { + "types": "./src/index.ts", + "default": "./src/index.ts" + } + } +} diff --git a/src/agent/directors/intern/package.ts b/agents/intern/src/index.ts similarity index 87% rename from src/agent/directors/intern/package.ts rename to agents/intern/src/index.ts index a788bb0e5..404d2e440 100644 --- a/src/agent/directors/intern/package.ts +++ b/agents/intern/src/index.ts @@ -1,13 +1,38 @@ -import type { DirectorPackage } from "../types.js"; -import { INTERN_TOOLS } from "../tool-sets.js"; - /** * Mechanical intern worker — 1:1 port of gaas intern.md * (`abklabs/agents` plugins/gaas/agents/intern.md @ 6e16b6c). * Tool-name mapping only (ask → ask_director). Path writes live on the * intern mount and in the dispatch brief, not in extra prompt essays. */ -export const internPackage: DirectorPackage = { +export type AgentPackage = { + readonly id: "intern"; + readonly primaryIntent: string; + readonly outOfLane: readonly string[]; + readonly description: string; + readonly systemPrompt: string; + readonly optionalSkills: readonly string[]; + readonly tools: { + readonly allow: readonly string[]; + }; + readonly spawn: { + readonly maySpawn: false; + }; + readonly modelRole: "implement"; + readonly tier: "leaf"; +}; + +const INTERN_TOOLS = [ + "run_shell", + "read_file", + "list_dir", + "write_file", + "edit_file", + "delete_file", + "skill_search", + "use_skill", +] as const; + +export const internPackage: AgentPackage = { id: "intern", primaryIntent: "Execute clear mechanical instructions exactly — zero judgment, zero invention", diff --git a/bun.lock b/bun.lock index 07f645b5e..dfebb382b 100644 --- a/bun.lock +++ b/bun.lock @@ -5,6 +5,7 @@ "": { "name": "@corbits/code", "dependencies": { + "@corbits/agent-intern": "workspace:*", "@corbits/codex-provider": "github:corbitsdev/corbits-codex-provider", "@corbits/oauth-core": "github:corbitsdev/corbits-oauth-core", "@corbits/openai-responses": "github:corbitsdev/corbits-openai-responses", @@ -51,6 +52,10 @@ "@opentui/core-win32-x64": "0.5.11", }, }, + "agents/intern": { + "name": "@corbits/agent-intern", + "version": "0.1.0", + }, "packages/first-class-providers": { "name": "@corbits/first-class-providers", "version": "0.1.0", @@ -224,6 +229,8 @@ "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="], + "@corbits/agent-intern": ["@corbits/agent-intern@workspace:agents/intern"], + "@corbits/codex-provider": ["@corbits/codex-provider@github:corbitsdev/corbits-codex-provider#bf07850", { "dependencies": { "@corbits/oauth-core": "github:corbitsdev/corbits-oauth-core", "@corbits/openai-responses": "github:corbitsdev/corbits-openai-responses", "arktype": "2.2.3" }, "peerDependencies": { "@intx/inference": ">=0.3.0", "@intx/types": ">=0.3.0" } }, "corbitsdev-corbits-codex-provider-bf07850", "sha512-5dVtVXd/CjWcXp4AitJAhcxky5mjhAq6G77q0t0iWs1bnms54VDLDnjN9oSqPJiD3nEiXmAoRbxiH1CxJkwTrA=="], "@corbits/first-class-providers": ["@corbits/first-class-providers@workspace:packages/first-class-providers"], diff --git a/evals/completion/tasks/decline-refactor/fixture/notes.ts b/evals/completion/tasks/decline-refactor/fixture/notes.ts index f6d1c6671..97740c7e6 100644 --- a/evals/completion/tasks/decline-refactor/fixture/notes.ts +++ b/evals/completion/tasks/decline-refactor/fixture/notes.ts @@ -1,5 +1,6 @@ export const notes: string[] = []; +// ts-prune-ignore-next export function addNote(note: string): void { notes.push(note); } diff --git a/evals/completion/tasks/stall-read/fixture/data.ts b/evals/completion/tasks/stall-read/fixture/data.ts index 92b227258..b3f77b0b2 100644 --- a/evals/completion/tasks/stall-read/fixture/data.ts +++ b/evals/completion/tasks/stall-read/fixture/data.ts @@ -1 +1,2 @@ +// ts-prune-ignore-next export const data = { seed: 7 }; diff --git a/evals/completion/tasks/sum-fix/fixture/sum.ts b/evals/completion/tasks/sum-fix/fixture/sum.ts index dce2a7d38..4f6cf1d10 100644 --- a/evals/completion/tasks/sum-fix/fixture/sum.ts +++ b/evals/completion/tasks/sum-fix/fixture/sum.ts @@ -1,3 +1,4 @@ +// ts-prune-ignore-next export function total(values: number[]): number { let sum = 0; for (const value of values) { diff --git a/evals/completion/tasks/version-endpoint/fixture/service.ts b/evals/completion/tasks/version-endpoint/fixture/service.ts index 601785b22..6da89986f 100644 --- a/evals/completion/tasks/version-endpoint/fixture/service.ts +++ b/evals/completion/tasks/version-endpoint/fixture/service.ts @@ -3,6 +3,7 @@ export interface Reply { body: unknown; } +// ts-prune-ignore-next export function handleRequest(method: string, path: string): Reply { if (method === "GET" && path === "/health") { return { status: 200, body: { ok: true } }; diff --git a/package.json b/package.json index 5b4136b66..02fdb58ca 100644 --- a/package.json +++ b/package.json @@ -86,6 +86,7 @@ "tar": "^7.5.1" }, "dependencies": { + "@corbits/agent-intern": "workspace:*", "@corbits/codex-provider": "github:corbitsdev/corbits-codex-provider", "@corbits/oauth-core": "github:corbitsdev/corbits-oauth-core", "@corbits/openai-responses": "github:corbitsdev/corbits-openai-responses", diff --git a/scripts/dead-export-allowlist.txt b/scripts/dead-export-allowlist.txt index 0ef6a8492..76623ea68 100644 --- a/scripts/dead-export-allowlist.txt +++ b/scripts/dead-export-allowlist.txt @@ -29,18 +29,6 @@ vendor/ src/auth/codex/constants.ts: CODEX_REFRESH_SKEW_MS src/auth/codex/constants.ts: CODEX_HEADLESS_REFRESH_INTERVAL_MS -# Plugin fixture entry point. Loaded by file path from the fixture's plugin -# manifest by the plugin-registration tests, so it has no static importers. -tests/fixtures/plugins/implement-feature/src/index.ts - -# Eval completion-harness task fixtures (CL-7932 lane). Loaded by file path -# from each task's script.json by the harness runner, so they have no static -# importers. -evals/completion/tasks/decline-refactor/fixture/notes.ts: addNote -evals/completion/tasks/stall-read/fixture/data.ts: data -evals/completion/tasks/sum-fix/fixture/sum.ts: total -evals/completion/tasks/version-endpoint/fixture/service.ts: handleRequest - # ts-prune parser false positives: bare tokens on `as const satisfies ...` # lines inside live exports. None of these is an export declaration. src/provider/reasoning-effort.ts: satisfies diff --git a/src/agent/directors/intern/package.test.ts b/src/agent/directors/intern/package.test.ts index b2e991320..59319d007 100644 --- a/src/agent/directors/intern/package.test.ts +++ b/src/agent/directors/intern/package.test.ts @@ -1,8 +1,17 @@ import { describe, expect, test } from "bun:test"; -import { internPackage } from "./package.js"; +import { internPackage, type AgentPackage } from "@corbits/agent-intern"; +import { DIRECTOR_REGISTRY } from "../registry.js"; +import { INTERN_TOOLS } from "../tool-sets.js"; describe("internPackage", () => { + test("workspace package is an AgentPackage used by the registry", () => { + const pkg: AgentPackage = internPackage; + expect(pkg.id).toBe("intern"); + expect(DIRECTOR_REGISTRY.intern).toBe(internPackage); + expect([...(pkg.tools?.allow ?? [])]).toEqual([...INTERN_TOOLS]); + }); + test("systemPrompt is mechanical executor (gaas intern port)", () => { const p = internPackage.systemPrompt; expect(p).toMatch(/intern assistant/); diff --git a/src/agent/directors/registry.ts b/src/agent/directors/registry.ts index b8bb11288..0b84e6554 100644 --- a/src/agent/directors/registry.ts +++ b/src/agent/directors/registry.ts @@ -1,3 +1,4 @@ +import { internPackage } from "@corbits/agent-intern"; import type { AgentProfile, CapabilityFilter } from "../profile-types.js"; import { randPackage } from "./rand/package.js"; import { bruckheimerPackage } from "./bruckheimer/package.js"; @@ -8,7 +9,6 @@ import { explorerPackage } from "./explorer/package.js"; import { gaasbotPackage } from "./gaasbot/package.js"; import { greybeardPackage } from "./greybeard/package.js"; import { builderPackage } from "./builder/package.js"; -import { internPackage } from "./intern/package.js"; import { migratorPackage } from "./migrator/package.js"; import { neckbeardPackage } from "./neckbeard/package.js"; import { counselPackage } from "./counsel/package.js"; diff --git a/tests/fixtures/plugins/implement-feature/src/index.ts b/tests/fixtures/plugins/implement-feature/src/index.ts index 8258584ca..27ad7340d 100644 --- a/tests/fixtures/plugins/implement-feature/src/index.ts +++ b/tests/fixtures/plugins/implement-feature/src/index.ts @@ -2,10 +2,12 @@ import { implementFeature } from "./workflows/implement-feature.js"; import type { CommandPlugin } from "../../../../../src/tui/commands/registry.js"; import type { WorkflowPlugin } from "../../../../../src/workflows/definition.js"; +// ts-prune-ignore-next export const workflowPlugin: WorkflowPlugin = { workflows: [implementFeature], }; +// ts-prune-ignore-next export const commandPlugin: CommandPlugin = { commands: [ { diff --git a/tsconfig.json b/tsconfig.json index 9954c5158..0bf57e072 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,6 +5,7 @@ "composite": false, "baseUrl": ".", "paths": { + "@corbits/agent-intern": ["./agents/intern/src/index.ts"], "@corbits/provider-opencode-go": ["./packages/opencode-go/src/index.ts"], "@corbits/first-class-providers": [ "./packages/first-class-providers/src/index.ts" @@ -16,6 +17,7 @@ "include": [ "src/**/*.ts", "packages/**/*.ts", + "agents/**/*.ts", "tests/**/*.ts", "evals/**/*.ts", "scripts/**/*.ts"