Commit Graph

302 Commits

Author SHA1 Message Date
can1357 771f93244f Merge PR #2907: fix(coding-agent): support getModel/getModels aliases in legacy extensions (@pidevxplay) 2026-06-20 22:12:49 +02:00
roboomp a63da8a3a3 fix(coding-agent): made plugin install transaction atomic on validation failure
The #3063 fix introduced a second mutating step — `bun update <name>` —
that rewrites bun.lock before extension validation runs. Three failure
paths could still leave the rejected commit pinned in the lockfile or
active tree:

- Extension validation throwing after `bun update` had refreshed
  bun.lock — rollback restored package.json and node_modules/<name>
  but never touched bun.lock.
- Feature validation (`omp plugin install pkg[ghost]`) throwing
  outside the rollback block entirely.
- Runtime-config save failing after a successful install with no
  rollback path.

Snapshot bun.lock alongside package.json before `bun install` runs and
route every post-install step (resolution, update, package.json read,
feature validation, extension validation, runtime-config save) through
one outer catch that restores all three (package.json + bun.lock +
node_modules/<name> from snapshot). `#rollbackFailedInstall` now
tolerates an unresolved `actualName` for failures that throw before
the dep key is known.

Three regression tests in plugin-install-validation.test.ts pin the
new contract: bun.lock restoration after a git reinstall fails
validation, bun.lock removal when it didn't exist pre-install, and
rollback on an unknown feature request.

Addresses review feedback on #3069.
2026-06-19 18:33:33 +00:00
roboomp 0ada5fe168 fix(coding-agent): refreshed github plugin lockfile pin on re-install
bun install <spec> respects the existing bun.lock pin when the spec is
unchanged and never re-resolves the remote ref, so re-running
`omp plugin install github:owner/repo` on an already-installed plugin
reported success while silently keeping the user on the original
resolved commit (1ms no-op, no network).

PluginManager.install now follows a git re-install with
`bun update <name>` to force re-resolution of the ref against the
upstream. First-time installs (no prior dep entry) skip the update —
the initial bun install already fetches HEAD. bun update failures
trigger the same rollback path as validation failures.

Fixes #3063
2026-06-19 18:22:57 +00:00
can1357 e1cd7a6692 perf(coding-agent/extensibility): deferred context allocation in extension runner
- Delay the creation of the extension context until a relevant handler is identified.
- Avoid unnecessary performance overhead for events that have no registered handlers, such as frequent streaming updates.
2026-06-19 16:06:17 +02:00
can1357 71144825ec feat(coding-agent): extended compact command with submode support
- Added a `mode` property to `CompactOptions` to allow fine-grained control over compaction strategies.
- Implemented `soft`, `remote`, and `snapcompact` submode overrides for the `/compact` command.
- Integrated `parseCompactArgs` to enable robust subcommand routing and validation, including focus instruction rejection for specific modes.
- Established a `CompactMode` registry to manage compaction strategies and verify remote availability.
2026-06-19 02:55:21 +02:00
devxpi d9184f10c0 fix(extensibility): forward optional metadata options to StringEnum in legacy-pi-ai-shim 2026-06-18 13:14:20 +08:00
devxpi a058ff3763 fix(coding-agent): support bare typebox and getModel/StringEnum in legacy extensions
- Support bare 'typebox' package specifier in on-resolve hooks and source remapping, mirroring '@sinclair/typebox' remapping onto the in-repo Zod-backed shim.
- Support 'getModel', 'getModels', and 'StringEnum' imports from the '@oh-my-pi/pi-ai' package root in the legacy pi-ai compatibility shim.
2026-06-18 13:12:38 +08:00
can1357 1dfac0322c fix: align typebox shim 2026-06-18 04:58:00 +02:00
can1357 2e658e28ce Merge remote-tracking branch 'origin/farm/39009a49/fix-extension-validation-shims' 2026-06-18 04:52:33 +02:00
roboomp 71481ab47e fix(cli): returned usable legacy coding tools
Changed createCodingTools compatibility exports to instantiate cwd-bound built-in read/bash/edit/write tool definitions instead of throwing placeholders.

Fixes #2858
2026-06-18 02:37:53 +00:00
roboomp d2d876b129 fix(cli): preserved legacy shim behavior
Restored StringEnum's plain string enum wire schema and returned legacy coding tool placeholders that let createAgentSession keep the real built-in tools active.

Fixes #2858
2026-06-18 02:10:39 +00:00
roboomp 906143e9fd fix(cli): restored legacy extension shim exports
Added compatibility exports for legacy plugin validation, including defineTool, StringEnum, TypeBox bare imports, frontmatter helpers, SettingsManager, and createCodingTools.

Updated SDK settingsManager alias handling and regression coverage for the affected shim surfaces.

Fixes #2858
2026-06-18 01:29:32 +00:00
can1357 7bec9af48f refactor(coding-agent): integrated zod validation and upgraded typebox shim
- Imported and injected `zod/v4` under `zod` in runtime environments for custom commands, custom tools, extensions, and hooks.
- Added corresponding Type definitions to `CustomCommandAPI`, `CustomToolAPI`, `ExtensionAPI`, and `HookAPI` interfaces.
- Re-exported Zod and its alias from the main package entry point to expand the public API surface.
- Refactored the internal Typebox validation shim to support parsing via standard `.safeParse()` and `.toJSON()` methods.
- Advanced Typebox shim utility capabilities with support for dual-key record validation and enhanced schema structure handling.
2026-06-18 01:57:23 +02:00
can1357 e92db73ec6 feat(coding-agent/tools): added explicit ArkType schema descriptions to agent tools
- Added explicit ArkType schema descriptions across all coding agent tool definitions.
- Updated schema definitions in autoresearch and commit tools with descriptive wrappers.
- Documented tool schema enhancements in the packages/coding-agent CHANGELOG.
2026-06-18 00:59:55 +02:00
can1357 a050474af7 feat: migrated validation schemas and tool definitions from Zod to ArkType
- Migrated all wire protocol, schema definitions, and tools validation from Zod to ArkType across multiple packages.
- Updated extension runtimes, custom tools loader, and TypeBox compatibility shim to expose and use ArkType instances.
- Added a comprehensive ArkType migration guide, validation parity tests, and helper utilities.
- Removed redundant PDF asset routing and parsing implementations from the read tool.
2026-06-18 00:59:53 +02:00
ben bd14fed678 fix(coding-agent): finalize session stop lifecycle 2026-06-17 12:26:52 +02:00
ben c93774f892 fix(coding-agent): implement session stop hook semantics 2026-06-17 12:26:52 +02:00
ben b7ac4b4c43 fix(coding-agent): use session stop extension event 2026-06-17 12:26:01 +02:00
ben 8e45ed9016 fix(coding-agent): add subagent stop extension event 2026-06-17 12:26:00 +02:00
can1357 48decd15d7 fix(coding-agent): fixed context usage tracking to keep status and selector totals in sync
- Added context snapshot metadata to AssistantMessage for prompt and non-message token history.
- Anchored context usage calculations on assistant snapshots and computed percent numerically.
- Updated status-line, /context, selector, and interactive mode flows to share session usage totals.
- Extended status-line cache fingerprinting and invalidation for assistant usage and prompt/tool/skill changes.
2026-06-17 12:24:20 +02:00
roboomp 205413860b fix(coding-agent): preserved hook disabled filters
Preserved Settings.disabledExtensions fallback when extension discovery is called without an explicit disabled list and kept hookCapability paths out of extension-module basename filtering.

Fixes #2796
2026-06-16 20:11:09 +00:00
roboomp 20f78c4693 fix(coding-agent): loaded discovered hook factories
Included JS and TS hookCapability results in extension path discovery so hooks under hooks/pre and hooks/post bind to the extension runner without explicit settings entries.

Fixes #2796
2026-06-16 19:44:28 +00:00
can1357 3aea0bfb38 Merge PR #2714: fix(plugins): resolve directory extension manifest entries one level deep
Resolve directory extension manifest entries one level deep with manifest-first precedence (issue #2713). Supersedes #2723.
2026-06-16 14:53:39 +02:00
can1357 9e6f6b2862 Merge PR #2745: fix(cli): speed up exit shutdown handlers
Run session_shutdown extension handlers concurrently under one shared cap instead of serially; each handler keeps its full per-handler timeout budget.
2026-06-16 14:52:40 +02:00
roboomp 4c336543d5 fix(cli): preserved linked plugin doctor state
Taught plugin doctor to treat lockfile-only plugins with node_modules entries as installed instead of orphaned.

Added coverage for plugin doctor --fix after linking a local plugin without package dependencies.

Fixes #2742
2026-06-16 05:17:24 +00:00
roboomp 7244e21b73 fix(cli): listed linked local plugins
Included lockfile-only linked plugins when building plugin list output so local symlink installs are visible after successful link operations.

Added regression coverage for plugin link followed by plugin list --json.

Fixes #2742
2026-06-16 05:02:20 +00:00
roboomp df510d3b1d fix(cli): sped up exit shutdown handlers
Run session_shutdown extension handlers concurrently under the existing shutdown cap so /exit and /quit do not wait one full timeout per hanging extension.

Fixes #2736
2026-06-16 04:49:58 +00:00
Asaf Mahlev b740faf6ce fix(plugins): resolve directory extension manifest entries one level deep
Installed pi packages declare their entry as `pi.extensions: ["./extensions"]` with the real module at `extensions/<name>/index.ts`, but the plugin manifest resolver only matched a file or a directory containing a direct index.{ts,js,mjs,cjs}. A directory whose entry sits one level below resolved to null, so `omp plugin install` rejected it ("declared extension entry not found on disk") and runtime load silently skipped it.

For the extensions key, resolveManifestEntryFiles now resolves a directory like OMP's configured-directory (-e) scanner: the directory's own package.json omp/pi extensions (authoritative -- a declared-but-missing entry is reported, not replaced by a decoy index), then a direct index.{ts,js,mjs,cjs}, then a one-level scan where each child directory is itself resolved manifest-first plus direct *.{ts,js,mjs,cjs} files. The directory expansion is gated to the extensions key; tools/hooks/commands keep direct-index resolution so a directory entry like `tools: "."` is unaffected.

Adds CHANGELOG Unreleased entry and regression tests for subdir-index, nested-manifest-over-index, missing-declared-entry, and key-aware (tools vs extensions) resolution. Verified: omp plugin install @zosmaai/pi-llm-wiki registers all 14 wiki_* tools; pi-mcp-adapter loads.
2026-06-16 03:01:07 +03:00
can1357 39d819e8b9 Merge PR #2237: fix(coding-agent): handle legacy plugin config settings 2026-06-15 19:46:15 +02:00
can1357 15184332b8 Merge PR #1173: feat(marketplace): prefer .omp-plugin/marketplace.json catalog path 2026-06-15 19:46:14 +02:00
can1357 dcdfb581cb Merge PR #1942: Add /review PR URL support 2026-06-15 19:46:14 +02:00
roboomp b0d0bd5bcb fix(coding-agent): cap session_shutdown extension handler at 2s
ExtensionRunner.emit shared the generic 30s EXTENSION_HANDLER_TIMEOUT_MS budget with every event, including the fire-and-forget session_shutdown teardown event extensions cannot observe. A hung third-party handler — observed on Windows with omp-discord-presence 0.1.2 waiting on a stuck Discord IPC pipe — held AgentSession.dispose() for the full window, making Ctrl+C look ignored for 30s.

session_shutdown now uses a dedicated 2s SESSION_SHUTDOWN_HANDLER_TIMEOUT_MS cap routed through a per-event handlerTimeoutForEvent() lookup so generic and shutdown budgets are independently configurable. The interactive-mode Ctrl+C path adds a defence-in-depth hard-exit: when isShuttingDown is true a fresh Ctrl+C exits with code 130 (the session JSONL has already been sync-flushed by the first press) instead of stacking another no-op shutdown() call.

Fixes #2600
2026-06-15 01:08:26 +00:00
can1357 77ea88e436 fix(coding-agent): fixed crashes when system prompts were provided as strings
- Normalized agent `setSystemPrompt` to wrap string inputs into one-item arrays.
- Updated session creation to accept string `systemPrompt` values and normalize callback or direct results to string arrays.
- Adjusted extension result handling and test fixtures to accept string `systemPrompt` and missing `assistant_message` fields without crashing.
2026-06-14 21:53:24 +02:00
Can Bölük 6eb57448c5 Merge pull request #2444 from 381181295/extension-approval-lifecycle
feat(coding-agent): emit tool approval lifecycle events
2026-06-14 18:16:36 +02:00
can1357 9e18d3fbb0 Merge branch 'main' into farm/a4aed75b/npm-plugin-load-deps 2026-06-14 18:13:29 +02:00
can1357 091c452dd1 Merge PR #2377: fix(coding-agent): derive bundled self root from dist path 2026-06-14 17:44:28 +02:00
Asaf Mahlev 57ea171859 address #2406 review: full-priority role resolve, family JSDoc, catalog changelog, role + canonical tests 2026-06-14 17:24:48 +02:00
Asaf Mahlev 3c53218e19 feat(extensions): add read-only ctx.models query facade
Expose `ctx.models` to extensions: list() / current() / resolve(spec) /
family(model). Lets extension tools select models the same way core does
(settings-backed aliases, match preferences, canonical-identity family
classification) without reaching into the mutable registry.

- types.ts: ExtensionModelQuery interface + `models` on ExtensionContext
- model-api.ts: createExtensionModelQuery facade
- runner.ts: thread optional Settings; build `models` in createContext()
- sdk.ts + agent-session.ts + extension-ui-controller.ts: pass settings / build models on the direct context literals
- catalog identity: modelFamilyToken() — coarse canonical-backed lineage token
- docs + changelog + tests

Implements #2406.
2026-06-14 17:24:48 +02:00
jiwangyihao c47718a6b5 fix(coding-agent): derive bundled self root from dist path 2026-06-14 17:24:07 +02:00
can1357 f22a7e22ce Merge remote-tracking branch 'origin/farm/0c857c58/load-agents-user-skills-into-slash' 2026-06-14 17:10:19 +02:00
can1357 3efebf8805 fix: harden merged provider, agent-loop, eager, and autolearn paths
- agent-loop: raise repetition-detection floor to 180 chars and clear thinking
  replay anchors when collapsing a detected loop.
- providers/google: ignore empty text parts, retain terminal thoughtSignatures,
  and stop function-call signatures clobbering the prior block.
- autolearn: capture goal-mode at the turn boundary; harden managed-skill writes
  against hard-links/symlinks (O_NOFOLLOW + nlink); refuse minting managed skills
  whose name an authored skill already claims.
- eager tasks: thread agentKind through the session so a custom top-level agentId
  still gets always-mode delegation; split Eager Tasks prompt into hard vs soft.
- title-generator: race the online title model against a local tiny-model fallback.
- eager-todo: keep the soft reminder aligned with the todo init schema.
- mcp/stdio: keep close() detaching the read loop instead of awaiting it.
- stream loop: fix collapsing and tool-call thought-signature handling.
2026-06-14 17:09:59 +02:00
can1357 42bd488859 Merge PR #2542: feat(coding-agent): opt-in experimental auto-learn (memory + isolated managed skills) 2026-06-14 17:09:41 +02:00
roboomp fed5e43f45 fix(coding-agent): remapped legacy oauth imports
Redirected legacy pi-ai utils/oauth subpaths through the compatibility loader so background workers load the relocated OAuth registry modules.\n\nFixes #2566
2026-06-14 12:56:05 +00:00
roboomp 294a61d94d fix(skills): exclude agents toggles from third-party fall-through gate
The previous `anyBuiltInSkillSourceEnabled` mixed the new
`enableAgentsUser`/`enableAgentsProject` defaults with the named
third-party toggles, so a user who disabled Codex/Claude/Pi to silence
third-party CLI skill sources but kept the default `.agent[s]/skills`
toggles on still saw unknown providers (`opencode`, `github`,
`claude-plugins`, `gemini`) load via the fallback branch. The
`agents` provider already has its own explicit branch in
`isSourceEnabled`, so the fall-through gate now only inspects the named
third-party toggles. Adds a regression test that creates a fake
`~/.config/opencode/skills/leaked-opencode` and verifies it stays
filtered out when the third-party toggles are off and agents toggles
default to on.

Addresses PR #2405 review.
2026-06-14 07:13:09 +00:00
metaphorics f83084c92c docs(coding-agent): pin load-bearing custom-dir vs managed skill ordering
The managed-skill discovery block vetoes a name already in `skillMap` to let a
custom-directory authored skill win. Custom dirs never enter `result.all`, so
they are absent from `enabledAuthoredNames` — the map check is the only veto, and
it only works because the custom-dir loop runs first. Add a comment so a future
refactor doesn't invert the order.

Addresses review thread on PR #2542 (thread 7).
2026-06-14 12:51:58 +09:00
metaphorics 18ee97751a feat(coding-agent): opt-in experimental auto-learn (memory + isolated managed skills)
Add a default-off "auto-learn" loop. When `autolearn.enabled` is set, after the
agent stops a session controller nudges it to capture reusable lessons: durable
facts go to long-term memory and repeatable procedures become "managed skills" —
SKILL.md files written to an isolated ~/.omp/agent/managed-skills directory that is
discovered and surfaced like authored skills but never overwrites them.

Two tools back this:
- `manage_skill` — create/update/delete managed skills.
- `learn` — record a lesson, optionally minting/enhancing a managed skill in the
  same call (requires a hindsight/mnemopi memory backend).

The nudge is passive by default (a hidden reminder rides the next turn);
`autolearn.autoContinue` instead auto-runs one capture turn at stop, and
`autolearn.minToolCalls` (default 5) gates trivial turns. Plan/goal-mode turns and
subagents are never nudged, and the controller re-checks the live setting at fire
time so a mid-session opt-out takes effect.

Isolation & precedence: managed skills are a separate lowest-priority discovery
provider, so an authored skill of the same name wins across every provider and
custom directory regardless of third-party toggles; a disabled higher-priority
authored skill can never hide a managed one, and managed never masks an enabled
authored skill. Managed names and descriptions are sanitized on both write and
read (control/format chars, angle brackets, and Markdown fences) before they render
into the system prompt, and the SKILL.md byte cap is enforced on the final
serialized file.

Default off → zero footprint when disabled.
2026-06-14 10:45:23 +09:00
can1357 24c8bb24c6 feat(session): added modular session APIs and rebuilt listing/persistence behavior
- Added session-domain modules and exports for session-entries, context, listing, loader, and migrations.
- Changed persistence to async append writes plus writeTextAtomic, removing sync line APIs.
- Added compaction-aware session context rebuild with dangling tool-call cleanup.
- Added resumable session resolution with status inference, id/stem/suffix matching, and backup recovery.
2026-06-14 02:02:53 +02:00
charlie 4fac874ebf feat(coding-agent): emit tool approval lifecycle events 2026-06-13 16:04:29 -06:00
can1357 95ec4f8bcb refactor(packages/coding-agent): migrated named zod imports and types
- Switched extensibility loader imports from namespace-style `zod` imports to named `z` imports in `zod/v4`.
- Updated extensibility type interfaces to use `typeof z` for injected `zod` modules in hook, extension, tool, and command APIs.
2026-06-13 00:24:45 +02:00
can1357 64aa558e62 chore: consistency 2026-06-13 00:03:27 +02:00