Commit Graph

4521 Commits

  • feat(ai): ImagesModels collections mirroring the chat-side design
    createImagesModels()/ImagesProvider/createImagesProvider() give image
    generation the same shape as chat: sync model reads, explicit async
    refresh(provider?) with in-flight dedupe, provider-resolved auth, and
    never-rejecting generateImages() (failures return AssistantImages with
    stopReason error). Auth resolution is shared with the chat side via the
    free-standing resolveProviderAuth() in auth/resolve.ts, which also owns
    ModelsError; both collections pass their store/context as arguments.
    
    The OpenRouter implementation moves to api/openrouter-images.ts with a
    lazy wrapper; openrouterImagesProvider() factory plus
    builtinImagesProviders()/builtinImagesModels() land in providers/all.
    The ImagesProvider id type alias is renamed to ImagesProviderId
    (mirror of Provider -> ProviderId). The old global image API
    (getImageModel*, generateImages, registerImagesApiProvider) stays on
    /compat, its registration shim repointed at the moved implementation.
    
    README: Quick Start uses builtinModels(), the full streaming event
    switch, image generation and the development checklist are restored in
    full, image generation documents the new collections with compat noted
    for the old API, plus the review fixes (builtinModels options,
    credential-store mention for browsers, ImagesModels notes).
  • docs(ai): rewrite README around the Models API
    Quick Start, querying, auth, OAuth, custom providers, faux, handoffs,
    browser usage, and the dev checklist now demonstrate createModels() +
    provider factories: sync model reads with explicit refresh, provider-
    owned auth resolution (getAuth, credential store, env tables),
    OAuthAuth login/refresh with prompt()/notify() callbacks, and
    createProvider() for custom/dynamic providers (replacing bare Model +
    global stream). Direct API implementation calls documented under the
    canonical ./api/<id> subpaths with the legacy aliases noted.
    
    The old global API is documented once, in a migration section pointing
    at /compat with an old-to-new mapping table. Image generation is
    documented as living on compat for now. All import/code claims
    verified with a compile-and-run smoke script.
  • feat(ai): sync model reads, explicit async refresh
    Provider.getModels() is sync-only (last-known list; must not throw) with
    an optional refreshModels() where dynamic providers fetch. The
    sync-or-async union invited latent sync assumptions that would detonate
    on the first dynamic provider; async-only reads would force sync
    consumer surfaces (extension find/getAll) through Promises. Sync reads
    plus an explicit refresh verb keeps the contract single and the
    staleness visible.
    
    Models.getModels()/getModel() are sync best-effort reads;
    Models.refresh(provider?) rejects with ModelsError(model_source) for a
    single provider and is concurrent best-effort across all providers.
    createProvider() takes a models array plus an optional refreshModels
    fetcher (stored on success, in-flight calls deduped, list unchanged on
    rejection). forceRefresh options are gone.
    
    Also finishes the in-progress AuthStorage fallbackResolver removal
    (drops the now-unused includeFallback option from getApiKey).
  • feat(agent): Models is the harness's only auth path
    Remove AgentHarnessOptions.getApiKeyAndHeaders: turn streaming,
    compaction, and branch summarization resolve auth exclusively through
    the injected Models instance. compact()/generateSummary()/
    generateBranchSummary() lose their explicit apiKey/headers parameters.
  • docs: changelogs and phase restructure for the models refactor (phase 8)
    Breaking-change entries with migration guides: pi-ai (compat
    entrypoint, Provider -> ProviderId, api module moves, new Models/
    provider/auth API), agent (required AgentHarnessOptions.models,
    compaction signatures, structural StreamFn), coding-agent (extension
    author note: runtime unaffected via loader compat alias).
    
    models.md: Phase 7 closed out (import switch landed with phase 5; the
    gated bullets move to a new Phase 9 ModelManager-migration outline:
    per-session Models, AgentSession streaming, AuthStorage replacement,
    login UI on OAuthAuth, cloudflare cleanup, internal compat removal,
    compat deletion).
  • feat(agent): AgentHarness streams through a required Models instance (phase 6)
    AgentHarnessOptions.models is required; the harness stream path,
    compaction, and branch summarization go through models.streamSimple()/
    completeSimple() instead of the compat globals. getApiKeyAndHeaders
    stays and wins per-field over provider-resolved auth, but is no longer
    required: without it, requests resolve through provider auth.
    
    compact()/generateSummary()/generateBranchSummary() take a Models
    parameter; explicit apiKey becomes optional. StreamFn is redefined
    structurally (Models.streamSimple satisfies it), dropping the compat
    type dependency from agent types.
    
    Harness tests build per-file Models collections with fauxProvider()
    and unique provider ids instead of mutating the global api-registry.
  • feat(ai): compat entrypoint, core-only root barrel (phase 5)
    The root barrel is now core-only and side-effect free: types,
    createModels/createProvider, auth substrate, lazyStream/lazyApi, faux,
    utils. Generated catalogs, api-registry, env-api-keys, images, global
    stream functions, and per-API lazy wrappers leave the root.
    
    New @earendil-works/pi-ai/compat preserves the old surface verbatim as
    a strict superset of the root: api-dispatch stream/complete with env
    key injection, the builtin registration side effect (skip-if-present so
    it cannot clobber earlier overrides), deprecated getModel/getModels/
    getProviders aliases of the new getBuiltin* reads in providers/all,
    lazy api wrappers + setBedrockProviderModule, and image generation.
    Compat dies with the coding-agent ModelManager migration.
    
    Packaging: exports map gains ./compat, ./providers/*, ./api/*;
    sideEffects array lists only the effectful modules.
    
    Old-global imports across agent/coding-agent/examples and pi-ai tests
    switch to /compat (path-only; compat is a superset). The coding-agent
    extension loader resolves the pi-ai ROOT specifier to compat, so
    existing user extensions using the old global API keep working at
    runtime until compat is removed. vitest configs alias /compat to src;
    browser smoke imports old globals from /compat.
  • feat(ai): adapt OAuth flows to OAuthAuth (phase 4)
    anthropic, openai-codex, and github-copilot flow modules gain OAuthAuth
    exports (login/refresh/toAuth) wired to the prompt()/notify() login
    callbacks, making the lazyOAuth attachments on the provider factories
    functional. Copilot's modifyModels baseUrl rewriting becomes toAuth()
    returning ModelAuth.baseUrl derived from the token proxy endpoint.
    
    Callback-server flows race a manual_code prompt and abort it through
    AuthPrompt.signal once the flow settles; OAuthAuth has no
    usesCallbackServer flag. The old OAuthProviderInterface exports stay
    unchanged until the coding-agent migration.
  • feat(ai): provider factories, per-provider catalogs, createProvider (phase 3)
    Auth helpers in src/auth/helpers.ts: envApiKeyAuth() (stored key wins,
    then env vars in order, with secret-prompt login) and lazyOAuth()
    (flow loads on first use through bundler-opaque dynamic imports in
    utils/oauth/load.ts; the OAuthAuth flow exports land in phase 4).
    There is no OAuth factory toggle: providers that support OAuth always
    attach it, advertising costs nothing until login/refresh runs.
    
    createProvider() in models.ts builds providers from parts: single API
    implementation or a map dispatched on model.api (mixed-API providers
    like opencode and github-copilot); unknown api yields a stream error.
    
    generate-models.ts now emits one providers/<id>.models.ts catalog per
    provider (35 files, biome-excluded like models.generated.ts) and
    models.generated.ts becomes a generated aggregator, so importing one
    provider factory pulls one catalog. Typed getModel globals unchanged.
    
    One factory per built-in provider under src/providers/: envApiKeyAuth
    for standard providers, OAuth for anthropic/openai-codex/github-copilot,
    ambient ApiKeyAuth for amazon-bedrock (AWS env/profile/IAM) and
    google-vertex (explicit key or ADC+project+location).
    
    providers/all.ts: builtinProviders(), builtinModels(), getBuiltin*
    re-exports. fauxProvider() factory returns a real Provider for tests;
    legacy registerFauxProvider() unchanged.
  • fix(coding-agent): use physical temp paths in session-id-readonly test
    On macOS tmpdir() is a symlink (/var -> /private/var) while the spawned
    CLI's process.cwd() is physical, so session cwd filtering never matched
    the fixtures and the fork-target rejection test failed locally.
  • fix: unset NVIDIA_API_KEY and ANT_LING_API_KEY in test.sh
    stream.test.ts gates e2e suites on these env vars; test.sh missed them,
    so local runs with the keys present executed live NVIDIA NIM e2e
    tests.
  • fix(ai): regenerate model catalog
    Picks up the Claude Fable 5 thinking-off metadata (off: null in
    thinkingLevelMap) that 9ccfcd7c added to the generator without
    regenerating, fixing anthropic-thinking-disable and supports-xhigh
    tests. Includes upstream catalog drift; OpenRouter delisted
    moonshotai/kimi-k2.6:free, so the kimi compat test now pins only the
    listed variant.
  • feat(ai): move API implementations to src/api with lazy wrappers (phase 2)
    Stream implementations move from src/providers/ to src/api/, renamed by
    API id (anthropic.ts -> anthropic-messages.ts, google.ts ->
    google-generative-ai.ts, mistral.ts -> mistral-conversations.ts,
    amazon-bedrock.ts -> bedrock-converse-stream.ts). Every module now
    exports exactly stream/streamSimple; shared helpers move alongside.
    
    New ProviderStreams dispatch contract in types.ts, lazyApi() wrapper in
    api/lazy.ts, and one .lazy.ts wrapper per API. Bedrock's wrapper keeps
    the node-only variable-specifier import and setBedrockProviderModule()
    (now taking ProviderStreams).
    
    providers/register-builtins.ts deleted; interim until the compat
    entrypoint lands, builtin api-registry registration lives in stream.ts
    and lazy wrappers are exported from the root barrel. Old per-API lazy
    exports (streamAnthropic, ...) are gone; package.json subpaths retarget
    to dist/api/.
  • feat(ai): add Models runtime with provider-owned auth (phase 1)
    New Models/MutableModels/createModels collection: provider map, async
    model listing (best-effort aggregation), getAuth decision tree with
    double-checked locked OAuth refresh, stream/complete with per-field
    auth merge over lazyStream.
    
    Auth substrate: ProviderAuth { apiKey?, oauth? }, one type-tagged
    credential per provider, CredentialStore (read/modify/delete; modify
    is the only write path, serialized RMW), OAuthAuth login/refresh/toAuth
    split, prompt()/notify() login callbacks, browser-safe default
    AuthContext.
    
    types.ts: Provider alias renamed to ProviderId; ApiOptionsMap and
    ApiStreamOptions<TApi> for typed per-API stream options; hasApi()
    runtime narrowing guard.
  • feat(coding-agent): add experimental first-time setup flow (#5587)
    Behind PI_EXPERIMENTAL=1, show a first-time setup dialog on interactive startup when the default agent directory is used and settings.json does not exist. The dialog preselects the detected terminal appearance with an explicit dark/light choice (live preview) and asks for opt-in analytics data sharing. Submitting writes settings.json, which serves as the completion marker; opting in stores a generated trackingId. Escape at any point skips out of setup.
  • Merge pull request #5585 from haoqixu/fix-editor-cjk-wrap
    fix(tui): wrap CJK text at character boundaries in editor
  • Merge pull request #5562 from Perlence/fix-tui-render-loose-lists
    fix(tui): separate list items with blank lines in loose lists
  • Merge pull request #5561 from unexge/push-lpxyxwstnswr
    feat(ai): link AWS data retention docs in Bedrock validation errors
  • Merge pull request #5560 from haoqixu/fix-5552
    fix(coding-agent): parse :thinking suffix from custom model IDs in fallback path
  • feat(ai): link AWS data retention docs in Bedrock validation errors
    When Bedrock rejects a request with "data retention mode '<mode>' is not
    available for this model", append a pointer to the AWS data retention
    documentation so users can configure a supported mode.
  • docs(agent): consolidate models architecture design
    Unified auth methods (api-key/oauth discriminated union), single
    createProvider() helper, src/api layout, compat entrypoint design,
    fixed auth resolution policy, prompt/notify login callbacks, and
    checkbox implementation TODOs.
  • fix(ai): regenerate models for Claude Fable 5 and Azure metadata overrides
    Also add inherited coding-agent changelog entries for Fable 5 and the
    Azure gpt-5.4/5.5 context window and gpt-5-pro maxTokens fixes.
  • fix(ai): correct Azure gpt-5.4/5.5 context window and gpt-5-pro maxTokens
    Azure Foundry deploys gpt-5.4 and gpt-5.5 with a 1,050,000 context
    window, but the Azure provider cloned OpenAI-direct's 272k API limit.
    Override the context window in the Azure derivation.
    
    Also fix gpt-5-pro maxTokens, which upstream metadata set to 272000 (a
    duplicate of the input sub-limit) instead of the actual 128000 max
    output; corrected at the source so OpenAI-direct and Azure both match.
    
    closes #5559
  • Merge pull request #5549 from earendil-works/approval-settings
    feat(ui): Improved project approval settings