mirror of
https://github.com/callstack/agent-device.git
synced 2026-09-14 20:06:34 +08:00
801734d433
* feat(ai-sdk): add agent-device/ai-sdk tool set and document the MCP zero-code path
Adds `createAgentDeviceTools()` under a new `agent-device/ai-sdk` subpath,
built from the same command registry the MCP server uses so both stay in
lockstep without a hand-maintained tool list. Introduces a `frameworkTier`
descriptor facet ('core' | 'extended') so the factory can default to a
curated perceive/act loop instead of handing a model dozens of tools.
`ai` is wired as an optional peer dependency, imported lazily inside the
factory rather than at module scope, so importing the subpath itself never
requires `ai` to be installed - only calling it does. The package's own
publishing gate (scripts/lib/shipped-imports.ts) is extended to recognize
peerDependencies as a valid resolution source, since this is the first
optional peer this package has shipped.
Also restructures the AI SDK doc around three tiers (zero-code via
@ai-sdk/mcp, the new typed tool set, hand-written tools) and fixes a stale
`needsApproval` reference in favor of the current `toolApproval` API.
* fix(layering): classify src/ai-sdk as a rank-4 zone
The layering guard requires every src/<folder>/ to be explicitly ranked or
unranked; the new src/ai-sdk/ subpath (added in the prior commit) was left
unclassified, failing CI's Layering Guard job. It sits at the same tier as
client/compat/daemon-server/metro/remote/sdk - a public integration surface
consuming mcp (3) and core (2), imported by nothing else in the tree.
* fix(ci): cover, exempt, and pack the new ai-sdk subpath
Fixes the remaining CI failures on the ai-sdk subpath commit:
- Coverage: src/ai-sdk/index.ts had no dedicated unit test (only manual/
integration verification), so changed-line coverage sat at 6.9% against
the 70% gate. Adds src/ai-sdk/__tests__/index.test.ts (core vs 'all' tool
filtering, session/platform pinning and schema hiding, error
normalization, toolApproval passthrough) with createCommandToolExecutor
and createAgentDeviceClient mocked the same way command-tools.test.ts
does, plus a dedicated missing-peer-dependency.test.ts that mocks `ai`
itself to throw, isolated to its own file so it doesn't affect the other
tests' use of the real, installed `ai` package. Changed-line coverage is
now 29/29 (100%).
- Fallow Code Quality: src/ai-sdk/index.ts and examples/sdk/ai-sdk-tools.ts
are entry points with no in-repo importer (reached only via package.json
exports / run directly), and the new subpath's exports are unused
internally by design - both need the same treatment src/sdk/*.ts and its
examples already have in .fallowrc.json.
- Integration Tests: test/integration/installed-package-metro.test.ts and
src/__tests__/package-exports.test.ts each hand-list every published
subpath and smoke-check it from a real packed install; added ./ai-sdk to
both so the new subpath is actually exercised, not just silently passing.
* fix(ai-sdk): hide MCP transport/config fields from the model too
createAgentDeviceTools() only removed session and mcpOutputFormat from tool
schemas. stateDir was still model-visible and reached the shared executor
as client configuration, letting a tool call redirect into a different
daemon state directory - defeating the "one pinned session" guarantee the
factory exists to provide. includeCost and responseLevel are MCP
tool-config knobs in the same category, irrelevant to this adapter.
Widens the hidden-field set to session/stateDir/mcpOutputFormat/
includeCost/responseLevel, and now strips them from the runtime input
inside execute() too (not just the schema), so the guarantee holds even if
a caller bypasses schema validation. The schema-properties filter and the
input filter now share one omitHidden() helper instead of two near-
duplicate implementations.
Addresses the P1 review comment on #1804.
53 lines
1.7 KiB
TypeScript
53 lines
1.7 KiB
TypeScript
/**
|
|
* AI SDK tool set: build a typed tool set from the command registry with
|
|
* `createAgentDeviceTools()`, drive it through a `ToolLoopAgent`, then close
|
|
* the session — no hand-written tool definitions.
|
|
*
|
|
* Demonstrates: `createAgentDeviceTools` from the `agent-device/ai-sdk`
|
|
* subpath.
|
|
*
|
|
* Prerequisites: an `agent-device` daemon target (a booted iOS simulator),
|
|
* `ai` installed, and `AI_MODEL` set to a model available through your
|
|
* configured AI SDK provider. This file typechecks without any of those;
|
|
* running it for real also requires `pnpm build` first, so the package
|
|
* resolves at runtime.
|
|
*
|
|
* Run: node --experimental-strip-types examples/sdk/ai-sdk-tools.ts
|
|
*/
|
|
import { ToolLoopAgent } from 'ai';
|
|
import { createAgentDeviceTools } from 'agent-device/ai-sdk';
|
|
|
|
async function main(): Promise<void> {
|
|
const { tools, client, toolApproval } = await createAgentDeviceTools({
|
|
session: 'sdk-example-ai-sdk',
|
|
platform: 'ios',
|
|
// Closing the session is the one destructive action in this example's
|
|
// default tool set, so require a human decision before the model can call it.
|
|
approval: { close: 'user-approval' },
|
|
});
|
|
|
|
const agent = new ToolLoopAgent({
|
|
model: process.env.AI_MODEL!,
|
|
instructions: [
|
|
'Inspect the current UI before acting.',
|
|
'Verify the requested outcome with another snapshot before reporting success.',
|
|
].join('\n'),
|
|
tools,
|
|
toolApproval,
|
|
});
|
|
|
|
try {
|
|
await client.apps.open({ app: 'com.apple.Preferences', platform: 'ios' });
|
|
|
|
const result = await agent.generate({
|
|
prompt: 'Open Notifications settings and report whether notifications are enabled.',
|
|
});
|
|
|
|
console.log(result.text);
|
|
} finally {
|
|
await client.sessions.close();
|
|
}
|
|
}
|
|
|
|
await main();
|