capacitor-mobile-claw 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -45,11 +45,25 @@ export interface FileWriteMessage {
45
45
  path: string;
46
46
  content: string;
47
47
  }
48
+ export interface SkillToolDef {
49
+ name: string;
50
+ description: string;
51
+ input_schema: Record<string, unknown>;
52
+ /** When true, the worker emits a bridge message with the tool input instead of returning a result */
53
+ bridgeEvent?: string;
54
+ }
48
55
  export interface SkillStartMessage {
49
56
  type: 'skill.start';
50
57
  skill: string;
51
58
  agentId?: string;
52
59
  locale?: string;
60
+ /** Injected skill config — if provided, overrides worker defaults */
61
+ config?: {
62
+ systemPrompt: string;
63
+ milestones: string[];
64
+ tools: SkillToolDef[];
65
+ kickoff: string;
66
+ };
53
67
  }
54
68
  export type UIToNodeMessage = AgentStartMessage | AgentStopMessage | ToolApproveMessage | AgentSteerMessage | ConfigUpdateMessage | ConfigStatusMessage | SessionListMessage | SessionClearMessage | FileReadMessage | FileWriteMessage | SkillStartMessage;
55
69
  export interface AgentEventMessage {
@@ -1 +1 @@
1
- {"version":3,"file":"bridge-protocol.d.ts","sourceRoot":"","sources":["../../../src/services/bridge-protocol.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bridge-protocol.d.ts","sourceRoot":"","sources":["../../../src/services/bridge-protocol.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,aAAa,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,YAAY,CAAA;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,cAAc,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,aAAa,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,eAAe,CAAA;IACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,cAAc,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,eAAe,CAAA;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,eAAe,CAAA;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,WAAW,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,YAAY,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACrC,qGAAqG;IACrG,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,aAAa,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,qEAAqE;IACrE,MAAM,CAAC,EAAE;QACP,YAAY,EAAE,MAAM,CAAA;QACpB,UAAU,EAAE,MAAM,EAAE,CAAA;QACpB,KAAK,EAAE,YAAY,EAAE,CAAA;QACrB,OAAO,EAAE,MAAM,CAAA;KAChB,CAAA;CACF;AAED,MAAM,MAAM,eAAe,GACvB,iBAAiB,GACjB,gBAAgB,GAChB,kBAAkB,GAClB,iBAAiB,GACjB,mBAAmB,GACnB,mBAAmB,GACnB,kBAAkB,GAClB,mBAAmB,GACnB,eAAe,GACf,gBAAgB,GAChB,iBAAiB,CAAA;AAIrB,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,aAAa,CAAA;IACnB,SAAS,EAAE,YAAY,GAAG,UAAU,GAAG,aAAa,GAAG,UAAU,GAAG,OAAO,CAAA;IAC3E,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC9B;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,iBAAiB,CAAA;IACvB,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE;QACN,WAAW,EAAE,MAAM,CAAA;QACnB,YAAY,EAAE,MAAM,CAAA;QACpB,WAAW,EAAE,MAAM,CAAA;KACpB,CAAA;IACD,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,aAAa,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,uBAAuB,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,cAAc,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,qBAAqB,CAAA;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,KAAK,CAAC;QACd,UAAU,EAAE,MAAM,CAAA;QAClB,SAAS,EAAE,MAAM,CAAA;QACjB,SAAS,EAAE,MAAM,CAAA;QACjB,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,WAAW,CAAC,EAAE,MAAM,CAAA;KACrB,CAAC,CAAA;CACH;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,kBAAkB,CAAA;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,sBAAsB,CAAA;IAC5B,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,sBAAsB,CAAA;IAC5B,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,MAAM,eAAe,GACvB,iBAAiB,GACjB,qBAAqB,GACrB,iBAAiB,GACjB,0BAA0B,GAC1B,YAAY,GACZ,wBAAwB,GACxB,qBAAqB,GACrB,yBAAyB,GACzB,yBAAyB,CAAA"}
@@ -1349,34 +1349,35 @@ function buildSetupSystemPrompt(locale) {
1349
1349
 
1350
1350
  const setupMilestonesReached = new Set();
1351
1351
 
1352
- async function runSetupSkill(agentId, locale = 'en') {
1353
- await refreshOAuthTokenIfNeeded(agentId);
1354
- const authProfiles = loadAuthProfiles(agentId);
1355
- const apiKey = resolveApiKey(authProfiles);
1356
-
1357
- if (!apiKey) {
1358
- channel.send('message', {
1359
- type: 'agent.error',
1360
- error: 'No AI provider configured. Connect a provider first.',
1361
- });
1362
- return;
1363
- }
1352
+ /**
1353
+ * Convert injected skill tool definitions (from client setup-skill.js) into
1354
+ * the Agent tool format with execute handlers.
1355
+ *
1356
+ * Tools with a `bridgeEvent` string emit the tool input as a bridge message.
1357
+ * Special tools (setup_milestone, setup_complete) get dedicated handlers.
1358
+ */
1359
+ function buildSkillTools(injectedTools, milestones) {
1360
+ return injectedTools.map((toolDef) => {
1361
+ const props = toolDef.input_schema?.properties || {};
1362
+ const required = toolDef.input_schema?.required || [];
1363
+ const typeProps = {};
1364
+ for (const [key, val] of Object.entries(props)) {
1365
+ const desc = val.description || key;
1366
+ const typeVal = Type.String({ description: desc });
1367
+ typeProps[key] = required.includes(key) ? typeVal : Type.Optional(typeVal);
1368
+ }
1364
1369
 
1365
- const modelId = 'claude-sonnet-4-5';
1366
- const model = getModel('anthropic', modelId);
1370
+ const base = {
1371
+ name: toolDef.name,
1372
+ label: toolDef.name.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase()),
1373
+ description: toolDef.description || '',
1374
+ parameters: Type.Object(typeProps),
1375
+ };
1367
1376
 
1368
- // Setup-specific tools: milestone + complete
1369
- const setupTools = [
1370
- {
1371
- name: 'setup_milestone',
1372
- label: 'Setup Milestone',
1373
- description: 'Report that a setup milestone has been reached during the onboarding interview.',
1374
- parameters: Type.Object({
1375
- milestone: Type.String({ description: 'The milestone name' }),
1376
- }),
1377
- execute: async (_id, params) => {
1377
+ if (toolDef.name === 'setup_milestone') {
1378
+ base.execute = async (_id, params) => {
1378
1379
  const m = params.milestone;
1379
- if (SETUP_MILESTONES.includes(m)) {
1380
+ if (milestones.includes(m)) {
1380
1381
  setupMilestonesReached.add(m);
1381
1382
  channel.send('message', {
1382
1383
  type: 'setup.milestone',
@@ -1385,53 +1386,77 @@ async function runSetupSkill(agentId, locale = 'en') {
1385
1386
  });
1386
1387
  }
1387
1388
  return toToolResult({ success: true, milestone: m, completedCount: setupMilestonesReached.size });
1388
- },
1389
- },
1390
- {
1391
- name: 'setup_complete',
1392
- label: 'Setup Complete',
1393
- description: 'Complete the setup process. Call this ONLY after all milestones are reached and the user has confirmed the summary.',
1394
- parameters: Type.Object({
1395
- shellName: Type.String({ description: 'The chosen name for the Shell' }),
1396
- identity: Type.String({ description: 'Full IDENTITY.md content' }),
1397
- memory: Type.String({ description: 'Full MEMORY.md content' }),
1398
- soul: Type.String({ description: 'Full SOUL.md content' }),
1399
- }),
1400
- execute: async (_id, params) => {
1401
- // Write configuration files to workspace
1389
+ };
1390
+ return base;
1391
+ }
1392
+
1393
+ if (toolDef.name === 'setup_complete') {
1394
+ base.execute = async (_id, params) => {
1402
1395
  const workspaceDir = join(OPENCLAW_ROOT, 'workspace');
1403
1396
  mkdirSync(workspaceDir, { recursive: true });
1404
-
1405
- atomicWrite(join(workspaceDir, 'IDENTITY.md'), params.identity);
1406
- atomicWrite(join(workspaceDir, 'MEMORY.md'), params.memory);
1407
- atomicWrite(join(workspaceDir, 'SOUL.md'), params.soul);
1408
-
1409
- // Emit completion to UI
1397
+ if (params.identity) atomicWrite(join(workspaceDir, 'IDENTITY.md'), params.identity);
1398
+ if (params.memory) atomicWrite(join(workspaceDir, 'MEMORY.md'), params.memory);
1399
+ if (params.soul) atomicWrite(join(workspaceDir, 'SOUL.md'), params.soul);
1410
1400
  channel.send('message', {
1411
1401
  type: 'setup.complete',
1412
1402
  shellName: params.shellName,
1413
- files: {
1414
- 'IDENTITY.md': params.identity,
1415
- 'MEMORY.md': params.memory,
1416
- 'SOUL.md': params.soul,
1417
- },
1403
+ files: { 'IDENTITY.md': params.identity, 'MEMORY.md': params.memory, 'SOUL.md': params.soul },
1418
1404
  });
1419
-
1420
1405
  return toToolResult({ success: true, shellName: params.shellName });
1421
- },
1422
- },
1423
- ];
1406
+ };
1407
+ return base;
1408
+ }
1409
+
1410
+ // bridgeEvent tools — emit tool input as a bridge message to the UI
1411
+ if (toolDef.bridgeEvent) {
1412
+ const eventType = toolDef.bridgeEvent;
1413
+ base.execute = async (_id, params) => {
1414
+ channel.send('message', { type: eventType, ...params });
1415
+ return toToolResult({ success: true, applied: true });
1416
+ };
1417
+ return base;
1418
+ }
1419
+
1420
+ // Generic fallback
1421
+ base.execute = async (_id, params) => toToolResult(params);
1422
+ return base;
1423
+ });
1424
+ }
1425
+
1426
+ async function runSetupSkill(agentId, locale = 'en', injectedConfig = null) {
1427
+ await refreshOAuthTokenIfNeeded(agentId);
1428
+ const authProfiles = loadAuthProfiles(agentId);
1429
+ const apiKey = resolveApiKey(authProfiles);
1430
+
1431
+ if (!apiKey) {
1432
+ channel.send('message', {
1433
+ type: 'agent.error',
1434
+ error: 'No AI provider configured. Connect a provider first.',
1435
+ });
1436
+ return;
1437
+ }
1438
+
1439
+ const modelId = 'claude-sonnet-4-5';
1440
+ const model = getModel('anthropic', modelId);
1441
+
1442
+ // Use injected config from client if available, fall back to hardcoded defaults
1443
+ const milestones = injectedConfig?.milestones || SETUP_MILESTONES;
1444
+ const systemPrompt = injectedConfig?.systemPrompt || buildSetupSystemPrompt(locale);
1445
+ const kickoff = injectedConfig?.kickoff || (SETUP_KICKOFF_PROMPTS[locale] || SETUP_KICKOFF_PROMPTS.en);
1446
+
1447
+ const setupTools = injectedConfig?.tools
1448
+ ? buildSkillTools(injectedConfig.tools, milestones)
1449
+ : _legacySetupTools();
1424
1450
 
1425
1451
  // Merge setup tools with base file tools + MCP tools
1426
1452
  const baseTools = buildAgentTools();
1427
1453
  const mcpTools = await discoverMcpTools();
1428
1454
  const tools = [...setupTools, ...baseTools, ...mcpTools];
1429
1455
 
1430
- // Create a fresh agent with setup system prompt
1431
1456
  const sessionKey = `setup/${Date.now()}`;
1432
1457
  const agent = new Agent({
1433
1458
  initialState: {
1434
- systemPrompt: buildSetupSystemPrompt(locale),
1459
+ systemPrompt,
1435
1460
  model,
1436
1461
  tools,
1437
1462
  thinkingLevel: 'off',
@@ -1446,7 +1471,6 @@ async function runSetupSkill(agentId, locale = 'en') {
1446
1471
  persistedMessageCount = 0;
1447
1472
  setupMilestonesReached.clear();
1448
1473
 
1449
- // Subscribe to events
1450
1474
  agent.subscribe((event) => {
1451
1475
  bridgeEvent(event);
1452
1476
  if (event.type === 'tool_execution_end' && sessionKey) {
@@ -1454,10 +1478,9 @@ async function runSetupSkill(agentId, locale = 'en') {
1454
1478
  }
1455
1479
  });
1456
1480
 
1457
- // Kick off the setup conversation — agent speaks first
1458
1481
  const startTime = Date.now();
1459
1482
  try {
1460
- await agent.prompt(SETUP_KICKOFF_PROMPTS[locale] || SETUP_KICKOFF_PROMPTS.en);
1483
+ await agent.prompt(kickoff);
1461
1484
  await agent.waitForIdle();
1462
1485
 
1463
1486
  saveSession(agent, agentId, sessionKey, startTime);
@@ -1480,6 +1503,49 @@ async function runSetupSkill(agentId, locale = 'en') {
1480
1503
  }
1481
1504
  }
1482
1505
 
1506
+ /** Legacy hardcoded setup tools (fallback when client doesn't inject config) */
1507
+ function _legacySetupTools() {
1508
+ return [
1509
+ {
1510
+ name: 'setup_milestone',
1511
+ label: 'Setup Milestone',
1512
+ description: 'Report that a setup milestone has been reached.',
1513
+ parameters: Type.Object({ milestone: Type.String({ description: 'The milestone name' }) }),
1514
+ execute: async (_id, params) => {
1515
+ const m = params.milestone;
1516
+ if (SETUP_MILESTONES.includes(m)) {
1517
+ setupMilestonesReached.add(m);
1518
+ channel.send('message', { type: 'setup.milestone', milestone: m, completedCount: setupMilestonesReached.size });
1519
+ }
1520
+ return toToolResult({ success: true, milestone: m, completedCount: setupMilestonesReached.size });
1521
+ },
1522
+ },
1523
+ {
1524
+ name: 'setup_complete',
1525
+ label: 'Setup Complete',
1526
+ description: 'Complete the setup process.',
1527
+ parameters: Type.Object({
1528
+ shellName: Type.String({ description: 'The chosen name for the Shell' }),
1529
+ identity: Type.String({ description: 'Full IDENTITY.md content' }),
1530
+ memory: Type.String({ description: 'Full MEMORY.md content' }),
1531
+ soul: Type.String({ description: 'Full SOUL.md content' }),
1532
+ }),
1533
+ execute: async (_id, params) => {
1534
+ const workspaceDir = join(OPENCLAW_ROOT, 'workspace');
1535
+ mkdirSync(workspaceDir, { recursive: true });
1536
+ atomicWrite(join(workspaceDir, 'IDENTITY.md'), params.identity);
1537
+ atomicWrite(join(workspaceDir, 'MEMORY.md'), params.memory);
1538
+ atomicWrite(join(workspaceDir, 'SOUL.md'), params.soul);
1539
+ channel.send('message', {
1540
+ type: 'setup.complete', shellName: params.shellName,
1541
+ files: { 'IDENTITY.md': params.identity, 'MEMORY.md': params.memory, 'SOUL.md': params.soul },
1542
+ });
1543
+ return toToolResult({ success: true, shellName: params.shellName });
1544
+ },
1545
+ },
1546
+ ];
1547
+ }
1548
+
1483
1549
  // ── Main agent run function ──────────────────────────────────────────────
1484
1550
 
1485
1551
  async function runAgentLoop(agentId, sessionKey, prompt, requestedModel) {
@@ -1726,7 +1792,7 @@ channel.addListener('message', async (event) => {
1726
1792
  if (msg.skill === 'setup') {
1727
1793
  const agentId = msg.agentId || 'main';
1728
1794
  const locale = msg.locale || 'en';
1729
- await runSetupSkill(agentId, locale);
1795
+ await runSetupSkill(agentId, locale, msg.config || null);
1730
1796
  } else {
1731
1797
  channel.send('message', {
1732
1798
  type: 'agent.error',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capacitor-mobile-claw",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "On-device AI agent engine for Capacitor apps — embedded Node.js worker with LLM, file tools, code execution, git, and extensible MCP server",
5
5
  "main": "dist/esm/index.js",
6
6
  "types": "dist/esm/index.d.ts",