{"_id":"@aimount/browser","name":"@aimount/browser","dist-tags":{"alpha":"0.1.0-alpha.0","latest":"0.1.0-alpha.0"},"versions":{"0.1.0-alpha.0":{"name":"@aimount/browser","private":false,"version":"0.1.0-alpha.0","type":"module","description":"Browser snapshot and scroll tools for embedded aimount integrations","publishConfig":{"access":"public"},"main":"./dist/index.cjs.js","module":"./dist/index.es.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.cjs.js","default":"./dist/index.es.js"},"./package.json":"./package.json"},"scripts":{"build":"tsc -p tsconfig.json --noEmit && vite build","test":"bun test src","e2e":"bunx playwright test --config playwright.config.ts"},"dependencies":{"zod":"^4.3.6"},"devDependencies":{"@playwright/test":"^1.56.1","@tsconfig/strictest":"^2.0.8","@types/bun":"^1.3.9","@types/jsdom":"^28.0.0","jsdom":"^28.1.0","typescript":"^5.9.3","vite":"^7.3.1","vite-plugin-dts":"^4.5.4"},"_id":"@aimount/browser@0.1.0-alpha.0","_nodeVersion":"25.9.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-gWBm0PPUpcE7aZZfPIjG+YSSawIlz0bcc0l04Zxr8CHdTwOtckWXf8WfL8h1mFkvie91oP+nGdVDUYd9Df4+lw==","shasum":"0d9bc58f5303a772312f43b51a614a64f273123e","tarball":"https://registry.npmjs.org/@aimount/browser/-/browser-0.1.0-alpha.0.tgz","fileCount":2,"unpackedSize":9045,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD15veOLONSY2179yj4MmL5M/0myklC13ltxFKEEg4xswIhAKU0R20i8pk/jjih1KFIfagWLq50F6v5lWIpi9FYRL+5"}]},"_npmUser":{"name":"akhmanov","email":"bulat.akhmanov@gmail.com"},"directories":{},"maintainers":[{"name":"akhmanov","email":"bulat.akhmanov@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/browser_0.1.0-alpha.0_1777209913798_0.9604462015251041"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-26T13:25:13.726Z","0.1.0-alpha.0":"2026-04-26T13:25:13.930Z","modified":"2026-04-26T13:25:14.123Z"},"maintainers":[{"name":"akhmanov","email":"bulat.akhmanov@gmail.com"}],"description":"Browser snapshot and scroll tools for embedded aimount integrations","readme":"# @aimount/browser\n\nShared browser observation tools for embedded aimount integrations.\n\nThis README freezes the important stage-1 architecture decisions that led to the first package cut, so later work does not need to reconstruct them from chat history.\n\n## Why this package exists\n\n`aimount` is an embedded assistant platform. Host apps already register project-specific browser tools next to domain tools, as seen in `senler`. The reusable value here is not a second browser-side agent loop. The reusable value is a shared browser engine plus standard tools that fit the existing aimount tool/runtime model.\n\n`_ref/page-agent/` is a donor, not a template. The part worth borrowing is the browser controller / snapshot extraction idea. The full page-agent loop, extension transport, and action lifecycle are intentionally not copied into aimount.\n\n## v1 public scope\n\nThe first public cut is intentionally small.\n\n- Export `createBrowserEngine(...)`.\n- Export `createPageSnapshotTool(engine)`.\n- Export `createPageScrollTool(engine)`.\n- Do not ship `navigate` or `reload` in v1.\n\nThe validated reason for cutting `navigate` and `reload` is complexity versus shared value. They drag in page transition recovery, durable restart handling, and future runtime-session semantics across tabs. Those concerns remain important, but they do not belong in the first public package cut.\n\n## Public wiring\n\nThe host owns engine creation. Tools are explicit and separate.\n\n```ts\nimport {\n  createBrowserEngine,\n  createPageScrollTool,\n  createPageSnapshotTool,\n} from '@aimount/browser';\n\nconst browserEngine = createBrowserEngine({\n  layers: {\n    content: { selectors: ['#content'] },\n    assistant: { selectors: ['#assistant'] },\n  },\n  defaultLayers: ['content'],\n});\n\nexport const page_snapshot = createPageSnapshotTool(browserEngine);\nexport const page_scroll = createPageScrollTool(browserEngine);\n```\n\nImportant: aimount tool ids come from export keys, not from an internal `name` field. If the host wants the tool ids to be `page_snapshot` and `page_scroll`, the host should export them under exactly those keys.\n\n## Shared engine contract\n\n`createBrowserEngine(...)` exists because reads and actions must share one browser observer/controller state.\n\n- The engine is shared.\n- The host creates it once.\n- Each tool creator receives the same engine instance.\n- There is no hidden singleton.\n- `AssistantWIProvider` does not own browser engine lifecycle in v1.\n\nThis is the aimount analogue of borrowing the `PageController` boundary from `page-agent` without importing the rest of the agent runtime.\n\n## `page_snapshot` contract\n\nPublic API:\n\n```ts\npage_snapshot({ layers?: string[] })\n```\n\nLocked decisions:\n\n- View is viewport-only, not full-document.\n- Result shape is `text + meta`.\n- `layers` are named layer ids, not raw selectors.\n- Layer selector mapping is configured in the engine.\n- If `layers` are omitted, the engine uses configured default layers.\n- Unknown layer ids fail explicitly.\n- Visibility boundaries are integrator-provided. The package does not try to autodetect the assistant container or any other hidden zones.\n\nSnapshot content rules:\n\n- Result shape stays `text + meta`, but `text` is now a structural browser-state snapshot.\n- The top-level text format is `Page state:` plus `Visible structure:`.\n- Keep visible interactive nodes even when they do not have a reliable name.\n- Include nearby readable context, not only control names.\n- Add coarse 3x3 zones: `top-left`, `top-center`, `top-right`, `middle-left`, `center`, `middle-right`, `bottom-left`, `bottom-center`, `bottom-right`.\n- Do not emit semantic `overlays`; container-level text blobs were removed because they created noisy evidence for exact UI claims.\n- Include `snapshotId` and freshness metadata so later action flows do not have to invent identity after the fact.\n\nItem-level evidence rules:\n\n- Every `meta.items[]` entry includes `name`, `nameSource`, and `nameStatus`.\n- `nameSource` is one of `text | aria-label | title | placeholder | value | unknown`.\n- `nameStatus` is one of `strong | weak | unknown`.\n- Unknown or weakly named controls remain visible in the snapshot instead of being dropped.\n\nObservation honesty rules:\n\n- `meta.observation.totalInteractive` counts all visible distinct actionable nodes.\n- `meta.observation.weakInteractive` counts items whose best name comes from a weak source.\n- `meta.observation.unknownInteractive` counts visible interactives with no reliable name.\n- `meta.observation.exactUiClaims` communicates whether the snapshot is safe for exact button/icon/label claims:\n  - `safe` when visible interactives are structurally preserved and meaningfully named,\n  - `partial` when rough guidance is okay but exact UI claims should be limited to strong items,\n  - `unsafe` when the page is too semantically weak for exact UI claims.\n\nSafety rules:\n\n- Minimal built-in redaction is required.\n- Password values and obvious secret/token-like values should not leak into snapshot text.\n\n## `page_scroll` v1 contract\n\nPublic API:\n\n```ts\npage_scroll({ direction, screens? })\n```\n\nLocked v1 decisions:\n\n- Scope is page-only vertical scroll.\n- Container scroll is out of v1.\n- Unit name is `screens`, both externally and internally.\n- Fractional values are allowed.\n- Default amount is `0.75` screens.\n- Scrolling should be smooth/animated.\n- Result shape is nested: action metadata plus `snapshot`.\n- Returned snapshot always uses engine default layers.\n- Action tools do not accept custom `layers` in v1.\n\nReadiness rules:\n\n- `assistant-wi` intentionally differs from `page-agent` here.\n- `page-agent` mostly does short waits and expects the model to call a later observe step.\n- In this package, the action tool itself waits heuristically, then returns the post-action snapshot publicly.\n- Readiness is heuristic + timeout.\n- Heuristics are action-specific, not one universal settle rule.\n- Budgets are per-action.\n- On timeout the tool returns best-effort state with an incompleteness flag rather than blocking forever.\n\n## Deferred and intentionally out of v1\n\nThese topics were discussed and are intentionally not in the first package cut:\n\n### `navigate` and `reload`\n\nThey were explored in detail, including a recovery design based on:\n\n- package-owned automatic recovery,\n- `localStorage`,\n- per-tab ownership,\n- `toolCallId`,\n- TTL expiry,\n- fail-closed cleanup.\n\nThat design context is still useful, but it is deferred rather than shipped in v1.\n\n### New-tab navigation\n\nNew-tab behavior is not the same thing as current-tab navigation. It likely needs explicit runtime session semantics such as fork/clone/handoff instead of silently reusing the same session.\n\nThis concern is tracked in the tasks backlog:\n\n- `tasks/projects/browser-std-tools/tasks/model-new-tab-session-fork`\n\n### Future `page_action`\n\nThe package name is `browser`, not `page-snapshot`, because the boundary should survive growth into future browser actions. Those actions are deliberately deferred until the shared snapshot model is stable.\n\n## Validation strategy\n\nPlaywright is mandatory for acceptance because the real browser is the source of truth for viewport, geometry, scroll, and overlay behavior.\n\nThe validation stack is:\n\n- fast unit tests for layer resolution, redaction, structural item preservation, honesty metadata, and nested action results;\n- Playwright acceptance tests for real browser behavior, including icon-only visible controls.\n\n## Donor notes from `page-agent`\n\nUseful donor ideas:\n\n- browser-state extraction around a shared controller,\n- indexed interactive elements,\n- local readable context around actions,\n- visible-page guidance rather than raw DOM dumping,\n- preserving actionable structure even when semantics are weak.\n\nThings intentionally not copied:\n\n- a second browser-side planner/agent loop,\n- extension-centric transport,\n- a separate public `wait` tool mental model,\n- weakly controlled execute-JS style behavior.\n","readmeFilename":"README.md","_rev":"1-01cd00e91558546d1e85b7add2991cf8"}