@aglit-ai/sdk

中文文档
0.1.17208发布于 2026/11/03Aglit AI Commercial LicenseTypeScriptCommonJS近 30 天下载 3671

Aglit AI SDK helpers + OpenAPI-driven client generation entrypoints

原始使用文档
文档目录14 节
  1. Encrypted private website content
  2. Private-site app and desktop streams
  3. Install
  4. Quick Start (TypeScript)
  5. Quick Start (JavaScript)
  6. IPC Tool Execution
  7. Examples
  8. Terminal Commands
  9. Browser Automation
  10. Create Chat Sessions
  11. Run the Bundled Examples
  12. OpenAPI Specs
  13. Native control migration
  14. Build and deployment

@aglit-ai/sdk

MIT-licensed SDK for building against the Aglit AI desktop API and tool runtime.

  • Requires the Aglit AI desktop app/API running locally
  • Type-safe fetch wrapper for the desktop API
  • JSON-RPC tool executor with a required x_aglit_ai_tool_reason
  • OpenAPI specs for Desktop + Tool Builder + Provider SPI APIs

You must have the Aglit AI desktop app/API running locally (localhost). Set SERVER_PORT/PORT/AGLIT_DESKTOP_BASE_URL as needed.

Encrypted private website content

The trusted /_sites/bootstrap shell can render a normal device-local website without exposing its HTML, scripts, assets or HTTP API bodies to the gateway:

import { createAuthenticatedSiteRuntimeFetch, mountEncryptedSite } from '@aglit-ai/sdk/browser';

const response = await fetch('/_sites/context', { credentials: 'same-origin', cache: 'no-store' });
if (!response.ok) throw new Error('Sign in to this site’s team');
const context = await response.json();
const runtimeFetch = await createAuthenticatedSiteRuntimeFetch({
  deviceId: context.site.deviceId,
  authenticatedEmail: context.user.email,
});
const surface = await mountEncryptedSite(document.querySelector('#site')!, {
  siteName: context.site.name,
  deviceId: context.site.deviceId,
  agentId: context.site.agentId,
  initialPath: new URLSearchParams(location.hash.slice(1)).get('path') ?? '/',
  runtimeFetch,
});
// On teardown: await surface.destroy();

Serve the SDK's standalone site-worker.js as the trusted, authenticated /_sites/worker.js, with Service-Worker-Allowed: / and a JavaScript content type. Serve the bundled shell code at /_sites/bootstrap.js. The shell, worker, context and existing /remote-access/api/... endpoints remain protected by their canonical server authentication and route allowlists. All other site content is requested only through the generated proxyPrivateSiteRequest operation inside the existing signed and encrypted runtime channel. A bare site cookie never replaces that channel.

The page holds the canonical endpoint crypto; the worker receives no keys. An in-memory MessageChannel binds the exact top-level shell, one-use initial iframe navigation, and browser-owned child client IDs. It returns decrypted responses locally to the iframe. It never fetches site content directly or stores content or keys in CacheStorage, IndexedDB, or a service-worker cache. Responses use no-store and a same-origin CSP; external content requests fail closed. The worker leaves only gateway-reserved /_sites/* and /remote-access/api/* requests to their existing authenticated handlers.

The persistent shell must stay alive. A closed shell, rejected membership, missing endpoint verification, or unavailable crypto returns an error rather than plaintext fallback. A worker restart loses client custody, so the shell reconnects and reloads a newly owned iframe. Site documents share their site's origin and code trust; the iframe is a rendering surface, not an isolation boundary between the site's own scripts and its Aglit SDK capabilities.

Shell links use /_sites/bootstrap#path=<encoded-local-path> so application paths and queries stay browser-local during worker navigation. Keep secrets out of ordinary URLs entered before the worker controls the page, as those initial network URLs are necessarily routing metadata.

The first version supports bounded HTTP request bodies up to 1 MiB and individual responses up to 8 MiB. Open-ended media ranges are bounded to 1 MiB segments. Site cookies, worker registrations, external resources, WebSockets and unbounded HTTP streams are not forwarded by the content bridge. Use the direct WebRTC primitive below for live app/desktop video and input.

Private-site app and desktop streams

Browser applications can import @aglit-ai/sdk/browser without loading local credential-file or IPC helpers. The default SDK entrypoint remains for local desktop/server integration.

createDirectRemoteStreamTransport(binding, { baseUrl, runtimeFetch }) connects to the existing authenticated direct WebRTC runtime. mountAppStream, mountDesktopStream, and mountRemoteStream provide framework-neutral video, connection status, and optional pointer/keyboard controls. They use the existing OpenAPI-generated signaling routes and direct ICE/TURN media, with the same aglit-input-reliable and aglit-input-volatile input channels as Aglit.

import { createAuthenticatedSiteRuntimeFetch, createDirectRemoteStreamTransport, mountAppStream } from '@aglit-ai/sdk/browser';

// binding comes from your authorized backend's exact persisted game chat/window:
// binding: { agentId, deviceId, sessionId, streamId,
//   target: { streamType: 'app', appId, windowId } }
const response = await fetch('/_sites/context', { credentials: 'same-origin', cache: 'no-store' });
if (!response.ok) throw new Error('Sign in to this site’s team');
const context = await response.json();
if (context.site.deviceId !== binding.deviceId) throw new Error('Game device changed');
const encryptedRuntimeFetch = await createAuthenticatedSiteRuntimeFetch({
  deviceId: context.site.deviceId,
  authenticatedEmail: context.user.email,
  runtimeSessionId: binding.sessionId,
});
const surface = mountAppStream(document.querySelector('#game')!, {
  title: "slurp's up!",
  interactive: true,
  transport: createDirectRemoteStreamTransport(binding, {
    baseUrl: window.location.origin,
    runtimeFetch: encryptedRuntimeFetch,
    captureSpeakerAudio: true,
  }),
});
await surface.connect();
// During component/page cleanup:
await surface.destroy();

For a desktop, use mountDesktopStream with target: { streamType: 'desktop', displayId } and omit interactive. Desktop streams are view-only in this version: interactive desktop mounting is rejected, and the direct transport rejects desktop control/input. Display video pixels can differ from logical native coordinates on Retina or scaled captures; desktop control requires the canonical verified logical display-bounds mapping. Supply a real persisted chat session, the original registered device, and an exact enumerated app window or display authorized by the backend. IDs select a target; they never grant access. The primitive does not launch apps or create account, team, or device grants.

createAuthenticatedSiteRuntimeFetch enrolls this browser through the existing runtime auth/key flow. Obtain its account and device from authenticated /_sites/context, never a URL claim. It reuses canonical nonextractable browser keys, device identity verification and existing managed pins or fingerprint confirmation UI. A configured computer verification code is requested through a real code dialog; denied access and API-key requirements remain failures. The separate site cookie stays HttpOnly. No cookie or device key is copied into application JavaScript. The optional runtimeSessionId is an existing task/chat used to select the serving runtime generation; the auth flow allocates its own separate crypto session.

The resulting authenticated, encrypted runtime fetch receives the unchanged generated /remote-access/api/... URLs on the site origin. The site gateway preserves their exact paths and queries, including URL-bound encryption proofs; it never rewrites them behind another API prefix. Passing ordinary fetch with a site cookie does not establish that runtime session. No broad local SDK token, browser cookie export, or provider-terminated media fallback is introduced.

The adapter signs exact encrypted bytes and URLs with the canonical v2 proof, then accepts only authenticated nonce-bound successful responses. It has one account/device scope per page; reload after account, device or credential changes.

App input is off by default. With interactive: true, the user explicitly selects Take control after the authorized direct input channel opens. Pointer input is mapped to the contained video rather than its letterbox. The default mode sends the canonical complete keyEvent: press gestures, including browser keyboard repeats, and complete clicks or left-button drags on pointer release. Interrupted pointer gestures are cancelled locally. It never leaves a native key or button waiting for a later release from a vanished viewer.

For games that need continuous movement, explicitly set keyboardMode: 'hold'. Connection then requires the actual packaged native helper's advertised app held-key capability. It sends existing down/up events with one keyHoldId per physical hold; keyHoldRenew: true renewals preserve that identity and never repeat key-down callbacks. Simultaneous keys remain down together. Renewal runs every 250 ms only while the video has focus, the page is visible, and this surface has control. Blur, hidden pages, key-up and teardown stop renewal before sending releases. Queued down/renew packets expire before native admission; a renewal cannot create a hold. Native down/renew also requires the captured window to remain the foreground app's exact focused window, without focusing or changing that window.

The native helper holds one exclusive app-keyboard owner per process, bound to its process birth and admitted exact window. App input and global keyboard events from another viewer cannot release or interrupt those keys. Existing authorized desktop pointer control may change focus; that stops app key renewal. A missing renewal expires its two-second native lease, checked every 100 ms; helper EOF/orderly shutdown also releases them. Cleanup uses the captured process identity and never focuses or resolves a replacement app. Expired/released hold IDs cannot be renewed into a new hold. Older runtimes reject held mode; they continue to support viewing and complete presses. Native activation and real game acceptance still require the new signed helper. An abrupt helper crash, SIGKILL or a suspended native process cannot run cleanup; the expiry guarantee requires the native helper to remain scheduled and healthy. Live button-held dragging and standalone modifier holds remain unsupported. Audio starts muted to respect browser playback requirements; a site can expose its own sound control using surface.video.muted. All viewers currently share the same running app and player state. Native held mode admits one input owner while keys are held; the Take control button itself grants no additional authority.

Call surface.destroy() on unmount to abort signaling, cancel pending input, and delete only this exact viewer session. An auth/signaling failure closes the peer; create a new surface after restoring the authorized runtime session. Offer creation and local SDP readiness are bounded separately inside the full 60-second startup deadline, matching the web viewer's browser compatibility path.

See examples/site-game.ts for the minimal game wrapper.

Install

pnpm add @aglit-ai/sdk
# or: npm install @aglit-ai/sdk

Quick Start (TypeScript)

import { createDesktopClient, executeTool } from '@aglit-ai/sdk';

const SERVER_PORT = process.env.SERVER_PORT ?? '49117';
const baseUrl = `http://127.0.0.1:${SERVER_PORT}`;
const agentId = 'root-agent';

const desktop = createDesktopClient({ baseUrl });

// Call REST endpoints (typed from OpenAPI)
const tasks = await desktop.GET('/tasks');
console.log(tasks.data?.tasks?.length);

// Execute tools via IPC (requires x_aglit_ai_tool_reason)
const response = await executeTool({
  agentId,
  request: {
    jsonrpc: '2.0',
    id: 'sdk-run-terminal',
    params: {
      name: 'p1_terminal',
      arguments: {
        action: 'open',
        x_aglit_ai_tool_reason: 'SDK example: open terminal via IPC',
      },
    },
    context: {
      sessionId: `sdk-terminal-${Date.now()}`,
      agentId,
    },
  },
});
console.log('tool response', response.data?.result);

Quick Start (JavaScript)

const { executeTool } = require('@aglit-ai/sdk');

(async () => {
  const response = await executeTool({
    agentId: 'root-agent',
    request: {
      jsonrpc: '2.0',
      id: 'sdk-ipc-example',
      params: {
        name: 'p1_todo',
        arguments: {
          action: 'list',
          x_aglit_ai_tool_reason: 'SDK IPC example: list todos',
        },
      },
      context: {
        agentId: 'root-agent',
        sessionId: 'sdk-ipc-session',
      },
    },
  });
  console.log(JSON.stringify(response, null, 2));
})();

IPC Tool Execution

Local tool execution runs over the IPC broker so there is no unauthenticated HTTP surface on loopback. If you store the IPC configuration somewhere custom, set AGLIT_SDK_IPC_CONFIG_PATH accordingly (default: <user-data>/ipc/sdk-ipc.json, where <user-data> is ~/Library/Application Support/Aglit AI/ on macOS).

On macOS, the SDK routes requests through a signed helper into an XPC broker. The broker only accepts requests from trusted apps and will prompt in the desktop app if a new app requests access. The socket endpoint is never written to disk. For local development, set AGLIT_SDK_XPC_ONLY=0 to keep the legacy socket config.

Always include x_aglit_ai_tool_reason and pass structured arguments rather than raw shell strings. The IPC broker also enforces the same tool policies you see in the UI, including approval flows and logging. Scripts started from an Aglit chat terminal inherit AGLIT_AGENT_ID, AGLIT_SESSION_ID, and AGLIT_SDK_MODULE_PATH. Load the bundled SDK with require(process.env.AGLIT_SDK_MODULE_PATH) to avoid an older workspace copy. executeTool uses the inherited session ID automatically; an explicit request _meta.sessionId takes precedence.

Examples

The SDK ships ready-to-run examples for common automation surfaces. Always include x_aglit_ai_tool_reason to explain why the tool is being called.

Terminal Commands

await executeTool({
  agentId: 'root-agent',
  request: {
    jsonrpc: '2.0',
    id: 'open-terminal',
    params: {
      name: 'p1_terminal',
      arguments: {
        action: 'open',
        x_aglit_ai_tool_reason: 'SDK example: open terminal',
      },
    },
    context: { sessionId: 'sdk-shell', agentId: 'root-agent' },
  },
});

await executeTool({
  agentId: 'root-agent',
  request: {
    jsonrpc: '2.0',
    id: 'type-ls',
    params: {
      name: 'p1_terminal',
      arguments: {
        action: 'type',
        windowId: '<window-id-from-open>',
        text: 'ls -la /tmp',
        submit_command: true,
        x_aglit_ai_tool_reason: 'SDK example: list temp files',
      },
    },
    context: { sessionId: 'sdk-shell', agentId: 'root-agent' },
  },
});

Browser Automation

Use the SDK compatibility adapter for structured browser actions. The adapter executes only p1_codex_browser registry calls, preserves chat authorization and approvals, and returns the exact native tab ID. Page evaluation is read-only; use native click/fill actions to change a page.

import { executeNativeControl, unwrapNativeControlResult } from '@aglit-ai/sdk';

const call = (args: Record<string, unknown>, reason: string) => executeNativeControl({
  toolName: 'p1_codex_browser', agentId: 'root-agent', sessionId: 'sdk-browser', args, reason,
});
const nav = unwrapNativeControlResult(await call(
  { action: 'navigate', url: 'https://example.com' }, 'Open example.com'
));
if (!nav?.tabId) throw new Error('Native browser returned no exact tab ID');
await call({ action: 'execute_javascript', tabId: nav.tabId, code: 'document.title' },
  'Read the page title');

Create Chat Sessions

import { createDesktopClient } from '@aglit-ai/sdk';

const desktop = createDesktopClient({ baseUrl });

const chat = await desktop.POST('/chats', {
  body: {
    agentId: 'root-agent',
    initialText: 'Say hello from the SDK',
  },
});
console.log('chat id', chat.data?.chat?.id);

Run the Bundled Examples

Make sure the desktop app/API is running locally, then:

pnpm --filter @aglit-ai/sdk run build        # if you haven't built yet
pnpm --filter @aglit-ai/sdk run test:examples

Configure via environment:

  • AGLIT_DESKTOP_BASE_URL (overrides host/port)
  • SERVER_PORT or PORT (default 49117 prod; 49217 for local dev)
  • AGLIT_AGENT_ID (default root-agent)

OpenAPI Specs

The SDK resolves the current OpenAPI source files from @aglit-ai/types:

  • Desktop API: @aglit-ai/types/schema/api.openapi.yaml
  • Tool Builder API: @aglit-ai/types/schema/tools-api.openapi.yaml
  • Provider SPI API: @aglit-ai/types/schema/provider-spi.openapi.yaml

Native control migration

executeNativeControl({toolName, args, reason, agentId, sessionId}) adapts structured custom-tool browser/app actions to p1_codex_browser and p1_codex_computer. Existing native execute/capture/stream/focus calls pass through. The retired IDs remain rejected.

import { executeNativeControl } from '@aglit-ai/sdk';
const result = await executeNativeControl({
  toolName: 'p1_codex_browser',
  args: {action: 'navigate', url: 'https://example.com'},
  reason: 'Open the requested example page',
  agentId, sessionId,
});

The adapter keeps exact native targets, preserves typing/submit flags, returns original proof and familiar result fields, and never replays an uncertain mutation. Page evaluation is read-only. Authored DOM input plans use aglitNativeClick(element) and aglitNativeFill(element, text) during inspection; the adapter performs those actions through native input APIs afterward. No page mutation, CDP or terminal fallback is used. Custom runtimes package this same SDK adapter locally, so they need no new SDK dependency.

Native control still requires the agent's existing unrestricted profiles and explicit access. Upload/file permissions remain separate native grants. Downloads return a saved path directly; old download progress stream IDs are unsupported. App window requests are verified against the private capture receipt before input; ambiguous/mismatched targets fail. Encoded recording and some legacy desktop-only APIs have no native equivalent.

Build and deployment

Run pnpm run build before pnpm run deploy. Deploy requires the compiled entrypoints and bundled OpenAPI schemas, then publishes the already built SDK using the version committed in package.json and existing registry credentials. Deploy does not rebuild, bump versions or launch an interactive registry login.

版本与发布记录

@aglit-ai/sdk 共发布 23 个版本,首次发布于 2026/02/01;过去 12 个月发布了 23 个版本。

版本发布日期距今
0.1.17208latest2026/11/035 天前
0.1.172042026/11/035 天前
0.1.171872026/11/025 天前
0.1.171852026/11/025 天前
0.1.171832026/11/025 天前
0.1.171702026/11/025 天前

关于 @aglit-ai/sdk 的常见问题

@aglit-ai/sdk 是什么?

Aglit AI SDK helpers + OpenAPI-driven client generation entrypoints

如何安装 @aglit-ai/sdk?

在项目目录运行 npm install @aglit-ai/sdk,或使用 pnpm add / yarn add / bun add。

@aglit-ai/sdk 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@aglit-ai/sdk 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@aglit-ai/sdk 可以商用吗?

@aglit-ai/sdk 使用 Aglit AI Commercial License 许可。声明的许可为 Aglit AI Commercial License,请阅读许可原文确认使用条件。以上为概括,不构成法律意见,请以许可原文为准。

@aglit-ai/sdk 的下载量有多少?

根据 npm 官方下载统计,@aglit-ai/sdk 在 2026/10/05 – 2026/11/03 这 30 天内被下载 3,671 次,日均约 122 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@aglit-ai/sdk 还在维护吗?

最新版本 0.1.17208 发布于 2026/11/03(5 天前);至今共发布 23 个版本,其中过去 12 个月发布了 23 个;首次发布于 2026/02/01。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。