@agimon-ai/po-config
Typed configuration loading, validation, and host services for composing Po sessions.
Package details
Install @agimon-ai/po-config from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@agimon-ai/po-config- Package
@agimon-ai/po-config- Version
0.0.0-alpha.107- Published
- Nov 4, 2026
- Downloads
- 31.9K/mo · 14K/wk
- Author
- agiflow-ai
- License
- BUSL-1.1
- Types
- package
- Size
- 1.9 MB
- Dependencies
- 5 dependencies · 1 peer
Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@agimon-ai/po-config
Typed runtime configuration and immutable session context for Po.
This package is fixed core in the Po distribution. It loads config.yaml, validates supported
runtime settings, publishes the po/config Cordis service, and maintains selection state shared
by the major-mode, domain, and profile transition flows.
Alpha: configuration contracts may change between releases.
Requirements
- Node.js 24 or newer
- Pi 1.0.0 as a peer dependency
Install
npm install @agimon-ai/po-config
Do not add this package to a Po layer. The distribution activates it before selectable packages so the rest of the parent session can consume one resolved configuration snapshot.
Runtime configuration
Po reads ~/.po/config.yaml first and <repoRoot>/.po/config.yaml second. Merge policy
is field-specific because some settings are personal and others are repository policy:
| Setting | Effective source policy |
|---|---|
projectTrust |
Repository value, defaulting to ask |
| Workspace declarations | Repository .po/workspaces.yaml, or legacy repository config.yaml fallback |
editor |
Personal config only |
modes.planning |
Personal and repository fields merge, with repository values winning |
voice |
Personal and repository fields merge, with repository values winning |
voice.autoCapture |
Personal config only |
selection |
Per-axis merge, with repository values winning |
Supported runtime root keys include modes, projectTrust, editor, voice, and selection.
The deprecated workspaces key remains readable for compatibility. Unknown keys and invalid values fail during loading.
projectTrust: ask
modes:
planning:
main:
model: openai/gpt-5.4
thinking: high
plansDirectory: .po/plans
voice:
engine: auto
language: en
selection:
majorMode: copilot
domains: [default]
profile: reviewer
Workspace declarations
Declare selectable workspaces in <repoRoot>/.po/workspaces.yaml:
workspaces:
- name: Agiflow
path: .
alias: af
instructions: Work on the Agiflow product.
metadata:
'@agimon-ai/po-agiflow': { projectId: 'your-project-id' }
- name: Unsendbox
path: .
alias: ub
metadata: {}
Names are trimmed, case-insensitively unique within the file, and use the admission naming rules
(letters, numbers, spaces, dots, dashes or underscores, starting with a letter or number, at most
80 characters, no ..). Aliases are optional non-empty strings, unique within the file.
path defaults to . and resolves from the repository root. This version supports only paths
canonically equal to that root, including equivalent symlinks; product-folder and cross-repository
paths are rejected rather than silently normalized. Distinct declarations create distinct workspace
ids sharing that root. Instructions are copied on first creation, not overwritten on re-admission.
metadata is a free-form JSON object. Plugin namespacing is a convention, not a schema restriction.
Each plugin validates its own values and decides whether they are defaults or enforced scope.
Keep credentials in the existing vault or credential services, not metadata.
The new file is repository-only and authoritative, including workspaces: []. Invalid or blank
new files report an error, never silently fall back. Only when it is absent does Po read the old
repository config.yaml list of { name, instructions? } and emit a deprecation notice. Personal
declarations are ignored. Po never rewrites either file automatically.
Hosts call readWorkspaceDeclarations({ fs, repositoryRoot, context }) from the root or /config
export. It returns { declarations, source, notices }. Plugins use the host-provided
po/workspace-registry service instead of rereading YAML.
The selection mapping names defaults. Definitions for those axes live in modes.yaml,
domains.yaml, and profiles.yaml and are documented by their owning package Help skills.
See the shipped configuration contract for the complete runtime schema and additional configuration details.
Typed session context
The native session server root provides
PO_CONFIG_SERVICE. Consumers must access it under an owning service injection:
import { PO_CONFIG_SERVICE, type PoConfigContext, requirePoConfigContext } from '@agimon-ai/po-config';
import type { Context } from '@deepseek-ai/cordis';
export function consumePoConfig(context: Context, consume: (snapshot: PoConfigContext) => void): void {
context.inject([PO_CONFIG_SERVICE], (configContext) => {
consume(requirePoConfigContext(configContext));
});
}
The snapshot is deeply frozen. It contains validated settings, active harness state, an optional
pendingSelection, and requiresRelaunch. Do not mutate it or retain it across provider or session
replacement. The next session publishes a new snapshot.
Plugin structure and lifecycle
Native server declarations live in src/extensions. HTTP request handling lives in routed api/ files, package behavior in src/services/{serviceName}, and cached harness state in src/models. Public consumption modules remain flat under src/exports.
The native session server root installs the Config runtime as a Cordis service and awaits its readiness in onStart. It uses Promise.allSettled to preserve degraded initialization reporting rather than throwing the readiness rejection from startup. The runtime receives the scope signal. Config and MCP projection logic stays in services, while public src/exports modules only forward symbols from their owners.
The root publishes its service before onStart awaits readiness, so startup consumers can observe the coordinator.
Selection transitions
Major-mode, domain, and profile packages resolve their own requested changes, then use the shared transition coordinator. Config owns the persisted selection and transition journal records used to distinguish active state from pending intent.
Native session selection is serialized by the kernel and applied to retained server package candidates. Config owns persisted selection and pending transition records; Po factory reload and terminal relaunch are not native authoring mechanisms.
Consumers must not edit snapshot.harness, bypass the coordinator, or cache launcher environment
state at module scope.
Public API
The root and focused /config and /piContext exports provide runtime parsing, merge policy, and
session integration:
import { loadPoConfig } from '@agimon-ai/po-config';
const settings = loadPoConfig(process.cwd());
Pi-specific JSON settings are exposed through /pi-config; their types are exposed through /config-schema. The removed /config/piConfig and /config/schema paths have no aliases.
The package also exposes lower-level loaders used by the fixed axis packages. User-facing guidance for defining modes, domains, and profiles is intentionally owned by those packages instead of this runtime Config authoring skill.
Help
The package publishes src/prompts/help-how-to-config, links it from llms.txt, and registers
help-how-to-config with the po/help Cordis service. The guidance is visible to the AI only
while the parent Help minor mode is active.
Remote session app
The remote-only show_session tool returns a read-only summary and links it to an MCP App.
Compatible hosts render the repository name, session identity, revision, profile, domains, layers,
and modes. Text-only clients receive the same information as readable text. load_context remains
separate and does not open a widget.
The component refreshes through the host's tools/call bridge. It receives no access token, does
not contact localhost or an external asset server, and does not include instructions, persona text,
or absolute repository paths. Conversation-routed connections still require host-supplied
conversation metadata on every tool call, including refresh. A host that cannot preserve that
metadata must use a dedicated-session connection; there is no fallback to a shared session.
build:mcp first runs build:app. The browser SDK and HTML are bundled into
generated/mcp-apps/session.ts, then embedded in the published MCP facet. The ui:// resource URI
contains a hash of the complete HTML. Do not edit generated assets or reuse an old URI for changed
content. Resource reads are authorized static prefetches and never create a child session.
Connect an MCP Apps host to the existing session MCP URL. After rebuilding and restarting the
server, refresh the host's tool catalog and invoke show_session. ChatGPT developer-mode
connections use the same endpoint. Public app submission, a stable production widget origin, and
upstream third-party widget forwarding are separate deployment work.
Development
pnpm build
pnpm typecheck
pnpm test
pnpm lint
pnpm test:app
The browser tests require Playwright Chromium (pnpm exec playwright install chromium). They
exercise the packaged HTML in a sandboxed iframe using the standard SDK's AppBridge, including
refresh, theme changes, errors, text safety, and teardown. They do not substitute for testing the
connection inside ChatGPT itself.
Maintained by Agimon.
License
Business Source License 1.1: free for personal use, organisations under USD 1M revenue, non-profits and education. See LICENSE and https://agimon.ai/licensing.