managarten/packages/shared-ai/src/index.ts
Till JS bc77b36234 feat(agents): Agent CRUD + default bootstrap + Mission.agentId (Phase 2)
Second phase of the Multi-Agent Workbench rollout (docs/plans/
multi-agent-workbench.md). Builds on Phase 1's identity-aware Actor.

Adds the Agent primitive — a named AI persona that owns Missions,
carries its own policy + memory, and (from Phase 3 on) drives the
Workbench lens. Everything is wired; a single user currently has one
"Mana" default agent until the UI (Phase 5) lets them create more.

Shared types (@mana/shared-ai):
- agents/types.ts: Agent, AgentState, DEFAULT_AGENT_ID/NAME constants
- policy/types.ts: AiPolicy + PolicyDecision (moved from webapp so
  Agent.policy can reference it without a runtime dep on the web app)
- missions/types.ts: new optional Mission.agentId field

Webapp data layer:
- data/ai/agents/{types,store,queries,bootstrap}.ts
- Dexie schema v19 adds `agents` table (indexes on state, name,
  [state+name]); sync registered under the existing ai app-id
- Encryption registry: agents.systemPrompt + agents.memory encrypted;
  name/role/avatar/policy stay plaintext for search + UI rendering
- DuplicateAgentNameError thrown at write time (not a Dexie unique
  index — bootstrap races between tabs would otherwise hit
  ConstraintError; store now resolves via getOrCreateAgent)
- bootstrap.ts: ensureDefaultAgent + backfillMissionsAgentId. The
  backfill runs once per device (localStorage sentinel) so missions
  that pre-date the rollout get stamped with the default agent's id.
  Called fire-and-forget from startMissionTick() during layout init.

Runner threading (already merged into d5c351d63 via Till's debug-log
commit that picked up my uncommitted edits):
- runner.ts + server-iteration-staging.ts now resolve mission.agentId
  to the real Agent and build makeAgentActor with agent.name as
  displayName. Missing-agent fallback keeps using LEGACY_AI_PRINCIPAL
  so historical writes still attribute cleanly.

Tests: shared-ai 26/26, mana-ai 35/35, svelte-check 0 errors.
Agent store vitest suite is present but blocked by a pre-existing
\$lib alias resolution issue in the webapp vitest config that
predates this phase (proposals/store.test.ts is broken the same way
on HEAD). Will address separately.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 20:35:49 +02:00

79 lines
1.5 KiB
TypeScript

/**
* @mana/shared-ai
*
* AI Workbench code that both the webapp (SvelteKit/Vite) and the
* server-side mana-ai service (Bun) import. Keep this package free of
* runtime imports from storage layers (Dexie, Postgres) — the types +
* pure functions here must work in both environments.
*/
export type {
Actor,
ActorKind,
BaseActor,
UserActor,
AiActor,
SystemActor,
SystemSource,
} from './actor';
export {
SYSTEM_PROJECTION,
SYSTEM_RULE,
SYSTEM_MIGRATION,
SYSTEM_STREAM,
SYSTEM_MISSION_RUNNER,
LEGACY_USER_PRINCIPAL,
LEGACY_AI_PRINCIPAL,
LEGACY_SYSTEM_PRINCIPAL,
LEGACY_DISPLAY_NAME,
USER_ACTOR,
makeUserActor,
makeAgentActor,
makeSystemActor,
normalizeActor,
isUserActor,
isAiActor,
isSystemActor,
isFromMissionRunner,
} from './actor';
export type {
IterationPhase,
Mission,
MissionCadence,
MissionInputRef,
MissionIteration,
MissionState,
PlanStep,
GrantDerivation,
GrantDerivationVersion,
MissionGrant,
} from './missions';
export {
GRANT_DERIVATION_VERSION,
canonicalInfoString,
deriveMissionDataKey,
deriveMissionDataKeyRaw,
} from './missions';
export type {
AiPlanInput,
AiPlanOutput,
AvailableTool,
ParseResult,
PlannedStep,
PlannerMessages,
ResolvedInput,
} from './planner';
export { buildPlannerPrompt, parsePlannerResponse } from './planner';
export {
AI_PROPOSABLE_TOOL_NAMES,
AI_PROPOSABLE_TOOL_SET,
type AiProposableToolName,
type AiPolicy,
type PolicyDecision,
} from './policy';
export type { Agent, AgentState } from './agents';
export { DEFAULT_AGENT_ID, DEFAULT_AGENT_NAME } from './agents';