@apitap/core 1.0.22 → 1.2.0

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.
@@ -0,0 +1,288 @@
1
+ #!/usr/bin/env node
2
+ // ApiTap Native Messaging Host
3
+ // Receives skill files from the Chrome extension and saves to ~/.apitap/skills/
4
+ import { promises as fs } from 'node:fs';
5
+ import path from 'node:path';
6
+ import os from 'node:os';
7
+ import net from 'node:net';
8
+ import { signSkillFile } from './skill/signing.js';
9
+ import { deriveKey } from './auth/crypto.js';
10
+ import { getMachineId } from './auth/manager.js';
11
+ const SKILLS_DIR = path.join(os.homedir(), '.apitap', 'skills');
12
+ const VERSION = '1.0.0';
13
+ // Sign skill JSON using the CLI's HMAC signing infrastructure
14
+ async function signSkillJson(skillJson) {
15
+ try {
16
+ const skill = JSON.parse(skillJson);
17
+ const machineId = await getMachineId();
18
+ const key = deriveKey(machineId);
19
+ const signed = signSkillFile(skill, key);
20
+ return JSON.stringify(signed);
21
+ }
22
+ catch {
23
+ return skillJson; // Return unsigned if signing fails
24
+ }
25
+ }
26
+ // Domain validation — must match src/skill/store.ts conventions
27
+ function isValidDomain(domain) {
28
+ if (!domain || domain.length === 0 || domain.length > 253)
29
+ return false;
30
+ if (domain.includes('/') || domain.includes('\\'))
31
+ return false;
32
+ if (domain.includes('..'))
33
+ return false;
34
+ if (domain.startsWith('.') || domain.startsWith('-'))
35
+ return false;
36
+ if (!/^[a-zA-Z0-9._-]+$/.test(domain))
37
+ return false;
38
+ return true;
39
+ }
40
+ export async function handleNativeMessage(request, skillsDir = SKILLS_DIR) {
41
+ try {
42
+ if (request.action === 'ping') {
43
+ return {
44
+ success: true,
45
+ action: 'pong',
46
+ version: VERSION,
47
+ skillsDir,
48
+ };
49
+ }
50
+ if (request.action === 'save_skill') {
51
+ if (!request.domain || !isValidDomain(request.domain)) {
52
+ return { success: false, error: `Invalid domain: ${request.domain}` };
53
+ }
54
+ if (!request.skillJson) {
55
+ return { success: false, error: 'Missing skillJson' };
56
+ }
57
+ // Validate JSON
58
+ try {
59
+ JSON.parse(request.skillJson);
60
+ }
61
+ catch {
62
+ return { success: false, error: 'Invalid JSON in skillJson' };
63
+ }
64
+ await fs.mkdir(skillsDir, { recursive: true });
65
+ const filePath = path.join(skillsDir, `${request.domain}.json`);
66
+ // Sign the skill file on receive (CLI is the signing authority)
67
+ const signed = await signSkillJson(request.skillJson);
68
+ await fs.writeFile(filePath, signed, 'utf-8');
69
+ return { success: true, path: filePath };
70
+ }
71
+ if (request.action === 'save_batch') {
72
+ if (!Array.isArray(request.skills) || request.skills.length === 0) {
73
+ return { success: false, error: 'Missing or empty skills array' };
74
+ }
75
+ await fs.mkdir(skillsDir, { recursive: true });
76
+ const paths = [];
77
+ for (const { domain, skillJson } of request.skills) {
78
+ if (!isValidDomain(domain)) {
79
+ return { success: false, error: `Invalid domain: ${domain}` };
80
+ }
81
+ try {
82
+ JSON.parse(skillJson);
83
+ }
84
+ catch {
85
+ return { success: false, error: `Invalid JSON for domain ${domain}` };
86
+ }
87
+ const filePath = path.join(skillsDir, `${domain}.json`);
88
+ const signed = await signSkillJson(skillJson);
89
+ await fs.writeFile(filePath, signed, 'utf-8');
90
+ paths.push(filePath);
91
+ }
92
+ return { success: true, paths };
93
+ }
94
+ return { success: false, error: `Unknown action: ${request.action}` };
95
+ }
96
+ catch (err) {
97
+ return { success: false, error: String(err) };
98
+ }
99
+ }
100
+ // --- Relay handler ---
101
+ // Actions handled locally by the native host (filesystem operations)
102
+ const LOCAL_ACTIONS = new Set(['save_skill', 'save_batch', 'ping']);
103
+ // Actions relayed to the extension (browser operations)
104
+ const EXTENSION_ACTIONS = new Set(['capture_request']);
105
+ export function createRelayHandler(sendToExtension, skillsDir = SKILLS_DIR) {
106
+ return async (message) => {
107
+ if (LOCAL_ACTIONS.has(message.action)) {
108
+ return handleNativeMessage(message, skillsDir);
109
+ }
110
+ if (EXTENSION_ACTIONS.has(message.action)) {
111
+ try {
112
+ return await sendToExtension(message);
113
+ }
114
+ catch (err) {
115
+ return { success: false, error: String(err) };
116
+ }
117
+ }
118
+ return { success: false, error: `Unknown action: ${message.action}` };
119
+ };
120
+ }
121
+ let socketServer = null;
122
+ export async function startSocketServer(socketPath, handler) {
123
+ // Clean up stale socket
124
+ try {
125
+ await fs.unlink(socketPath);
126
+ }
127
+ catch { /* doesn't exist — fine */ }
128
+ return new Promise((resolve, reject) => {
129
+ socketServer = net.createServer((conn) => {
130
+ let buffer = '';
131
+ conn.on('data', (chunk) => {
132
+ buffer += chunk.toString();
133
+ const newlineIdx = buffer.indexOf('\n');
134
+ if (newlineIdx === -1)
135
+ return;
136
+ const line = buffer.slice(0, newlineIdx);
137
+ buffer = buffer.slice(newlineIdx + 1);
138
+ let request;
139
+ try {
140
+ request = JSON.parse(line);
141
+ }
142
+ catch {
143
+ conn.end(JSON.stringify({ success: false, error: 'Invalid JSON' }) + '\n');
144
+ return;
145
+ }
146
+ handler(request).then((response) => conn.end(JSON.stringify(response) + '\n'), (err) => conn.end(JSON.stringify({ success: false, error: String(err) }) + '\n'));
147
+ });
148
+ conn.on('error', () => { });
149
+ });
150
+ socketServer.on('error', reject);
151
+ socketServer.listen(socketPath, () => resolve());
152
+ });
153
+ }
154
+ export async function stopSocketServer() {
155
+ if (!socketServer)
156
+ return;
157
+ return new Promise((resolve) => {
158
+ socketServer.close(() => resolve());
159
+ socketServer = null;
160
+ });
161
+ }
162
+ // --- stdio framing (only runs when executed directly, not when imported for tests) ---
163
+ function readMessage() {
164
+ return new Promise((resolve) => {
165
+ const headerBuf = Buffer.alloc(4);
166
+ let headerRead = 0;
167
+ function onData(chunk) {
168
+ let offset = 0;
169
+ // Read header
170
+ if (headerRead < 4) {
171
+ const needed = 4 - headerRead;
172
+ const toCopy = Math.min(needed, chunk.length);
173
+ chunk.copy(headerBuf, headerRead, 0, toCopy);
174
+ headerRead += toCopy;
175
+ offset = toCopy;
176
+ if (headerRead < 4)
177
+ return; // need more data for header
178
+ }
179
+ const messageLength = headerBuf.readUInt32LE(0);
180
+ if (messageLength > 1024 * 1024) {
181
+ process.stderr.write(`Message too large: ${messageLength}\n`);
182
+ resolve(null);
183
+ return;
184
+ }
185
+ // Accumulate message body
186
+ const bodyBuf = Buffer.alloc(messageLength);
187
+ let bodyRead = 0;
188
+ if (offset < chunk.length) {
189
+ const remaining = chunk.subarray(offset);
190
+ const toCopy = Math.min(remaining.length, messageLength);
191
+ remaining.copy(bodyBuf, 0, 0, toCopy);
192
+ bodyRead = toCopy;
193
+ }
194
+ if (bodyRead >= messageLength) {
195
+ process.stdin.removeListener('data', onData);
196
+ try {
197
+ resolve(JSON.parse(bodyBuf.toString('utf-8')));
198
+ }
199
+ catch {
200
+ resolve(null);
201
+ }
202
+ return;
203
+ }
204
+ // Need more data
205
+ function onMoreData(moreChunk) {
206
+ const toCopy = Math.min(moreChunk.length, messageLength - bodyRead);
207
+ moreChunk.copy(bodyBuf, bodyRead, 0, toCopy);
208
+ bodyRead += toCopy;
209
+ if (bodyRead >= messageLength) {
210
+ process.stdin.removeListener('data', onMoreData);
211
+ process.stdin.removeListener('data', onData);
212
+ try {
213
+ resolve(JSON.parse(bodyBuf.toString('utf-8')));
214
+ }
215
+ catch {
216
+ resolve(null);
217
+ }
218
+ }
219
+ }
220
+ process.stdin.on('data', onMoreData);
221
+ }
222
+ process.stdin.on('data', onData);
223
+ process.stdin.on('end', () => resolve(null));
224
+ });
225
+ }
226
+ function sendMessage(message) {
227
+ const json = Buffer.from(JSON.stringify(message), 'utf-8');
228
+ const header = Buffer.alloc(4);
229
+ header.writeUInt32LE(json.length, 0);
230
+ process.stdout.write(header);
231
+ process.stdout.write(json);
232
+ }
233
+ // Main loop — only runs when executed as a script
234
+ const isMainModule = process.argv[1] &&
235
+ (process.argv[1].endsWith('native-host.ts') || process.argv[1].endsWith('native-host.js'));
236
+ if (isMainModule) {
237
+ const bridgeDir = path.join(os.homedir(), '.apitap');
238
+ const socketPath = path.join(bridgeDir, 'bridge.sock');
239
+ // Pending CLI requests waiting for extension responses
240
+ const pendingRequests = new Map();
241
+ let requestCounter = 0;
242
+ // Send a message to the extension via stdout and wait for response
243
+ function sendToExtension(message) {
244
+ return new Promise((resolve) => {
245
+ const id = String(++requestCounter);
246
+ const timer = setTimeout(() => {
247
+ pendingRequests.delete(id);
248
+ resolve({ success: false, error: 'approval_timeout' });
249
+ }, 60_000);
250
+ pendingRequests.set(id, { resolve, timer });
251
+ // Tag message with ID so we can match the response
252
+ sendMessage({ ...message, _relayId: id });
253
+ });
254
+ }
255
+ const handler = createRelayHandler(sendToExtension);
256
+ (async () => {
257
+ // Ensure bridge directory exists
258
+ await fs.mkdir(bridgeDir, { recursive: true });
259
+ // Start socket server for CLI connections
260
+ await startSocketServer(socketPath, handler);
261
+ // Read messages from extension via stdin
262
+ while (true) {
263
+ const message = await readMessage();
264
+ if (!message)
265
+ break;
266
+ // Check if this is a response to a relayed request
267
+ const relayId = message._relayId;
268
+ if (relayId && pendingRequests.has(relayId)) {
269
+ const pending = pendingRequests.get(relayId);
270
+ clearTimeout(pending.timer);
271
+ pendingRequests.delete(relayId);
272
+ const { _relayId, ...response } = message;
273
+ pending.resolve(response);
274
+ continue;
275
+ }
276
+ // Otherwise, handle as a direct extension message (save_skill, etc.)
277
+ const response = await handleNativeMessage(message);
278
+ sendMessage(response);
279
+ }
280
+ // Extension disconnected — clean up
281
+ await stopSocketServer();
282
+ try {
283
+ await fs.unlink(socketPath);
284
+ }
285
+ catch { /* already gone */ }
286
+ })();
287
+ }
288
+ //# sourceMappingURL=native-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-host.js","sourceRoot":"","sources":["../src/native-host.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,10 @@ export interface BrowseOptions {
8
8
  maxBytes?: number;
9
9
  /** @internal Skip SSRF check — for testing only */
10
10
  _skipSsrfCheck?: boolean;
11
+ /** @internal Override bridge socket path — for testing only */
12
+ _bridgeSocketPath?: string;
13
+ /** @internal Override bridge timeout — for testing only */
14
+ _bridgeTimeout?: number;
11
15
  }
12
16
  export interface BrowseSuccess {
13
17
  success: true;
@@ -16,7 +20,7 @@ export interface BrowseSuccess {
16
20
  domain: string;
17
21
  endpointId: string;
18
22
  tier: string;
19
- skillSource: 'disk' | 'discovered' | 'captured';
23
+ skillSource: 'disk' | 'discovered' | 'captured' | 'bridge';
20
24
  capturedAt: string;
21
25
  task?: string;
22
26
  truncated?: boolean;
@@ -1,6 +1,99 @@
1
1
  import { readSkillFile } from '../skill/store.js';
2
2
  import { replayEndpoint } from '../replay/engine.js';
3
3
  import { read } from '../read/index.js';
4
+ import { bridgeAvailable, requestBridgeCapture, DEFAULT_SOCKET } from '../bridge/client.js';
5
+ /**
6
+ * Try escalating to the Chrome extension bridge for authenticated capture.
7
+ * Returns a BrowseResult if the bridge handled it, or null to fall through.
8
+ */
9
+ async function tryBridgeCapture(domain, fullUrl, options) {
10
+ const socketPath = options._bridgeSocketPath ?? DEFAULT_SOCKET;
11
+ if (!await bridgeAvailable(socketPath))
12
+ return null;
13
+ const result = await requestBridgeCapture(domain, socketPath, { timeout: options._bridgeTimeout });
14
+ if (result.success && result.skillFiles && result.skillFiles.length > 0) {
15
+ const skillFiles = result.skillFiles;
16
+ // Save each skill file to disk
17
+ try {
18
+ const { writeSkillFile: writeSF } = await import('../skill/store.js');
19
+ for (const skill of skillFiles) {
20
+ await writeSF(skill, options.skillsDir);
21
+ }
22
+ }
23
+ catch {
24
+ // Saving failed — still have the data in memory
25
+ }
26
+ // Find the skill file matching the requested domain
27
+ const primarySkill = skillFiles.find((s) => s.domain === domain)
28
+ ?? skillFiles[0];
29
+ if (primarySkill?.endpoints?.length > 0) {
30
+ // Pick the best endpoint and replay it
31
+ let urlPath = '/';
32
+ try {
33
+ urlPath = new URL(fullUrl).pathname;
34
+ }
35
+ catch { /* use default */ }
36
+ const endpoint = pickEndpoint(primarySkill, urlPath);
37
+ if (endpoint) {
38
+ try {
39
+ const replayResult = await replayEndpoint(primarySkill, endpoint.id, {
40
+ maxBytes: options.maxBytes,
41
+ _skipSsrfCheck: options._skipSsrfCheck,
42
+ });
43
+ if (replayResult.status >= 200 && replayResult.status < 300) {
44
+ return {
45
+ success: true,
46
+ data: replayResult.data,
47
+ status: replayResult.status,
48
+ domain,
49
+ endpointId: endpoint.id,
50
+ tier: endpoint.replayability?.tier ?? 'unknown',
51
+ skillSource: 'bridge',
52
+ capturedAt: primarySkill.capturedAt ?? new Date().toISOString(),
53
+ task: options.task,
54
+ ...(replayResult.truncated ? { truncated: true } : {}),
55
+ };
56
+ }
57
+ }
58
+ catch {
59
+ // Replay failed — but skill file is saved for next time
60
+ }
61
+ }
62
+ }
63
+ // Skill file saved but replay didn't work
64
+ return {
65
+ success: false,
66
+ reason: 'bridge_capture_saved',
67
+ suggestion: `Captured ${skillFiles.length} skill file(s) from browser. Replay failed — try 'apitap replay ${domain}'.`,
68
+ domain,
69
+ url: fullUrl,
70
+ task: options.task,
71
+ };
72
+ }
73
+ // Bridge returned an error
74
+ if (result.error === 'user_denied') {
75
+ return {
76
+ success: false,
77
+ reason: 'user_denied',
78
+ suggestion: `User denied browser access to ${domain}. Use 'apitap auth request ${domain}' for manual login instead.`,
79
+ domain,
80
+ url: fullUrl,
81
+ task: options.task,
82
+ };
83
+ }
84
+ if (result.error === 'approval_timeout') {
85
+ return {
86
+ success: false,
87
+ reason: 'approval_timeout',
88
+ suggestion: `User approval pending for ${domain}. Click Allow in the ApiTap extension and try again.`,
89
+ domain,
90
+ url: fullUrl,
91
+ task: options.task,
92
+ };
93
+ }
94
+ // Other bridge errors — fall through to existing fallback
95
+ return null;
96
+ }
4
97
  /**
5
98
  * High-level browse: check cache → disk → discover → replay.
6
99
  * Auto-escalates cheap steps. Returns guidance for expensive ones.
@@ -75,6 +168,10 @@ export async function browse(url, options = {}) {
75
168
  catch {
76
169
  // Read failed — fall through to capture_needed
77
170
  }
171
+ // Try extension bridge before giving up
172
+ const bridgeResult1 = await tryBridgeCapture(domain, fullUrl, options);
173
+ if (bridgeResult1)
174
+ return bridgeResult1;
78
175
  return {
79
176
  success: false,
80
177
  reason: 'no_replayable_endpoints',
@@ -113,6 +210,10 @@ export async function browse(url, options = {}) {
113
210
  // Read failed — fall through to capture_needed
114
211
  }
115
212
  }
213
+ // Try extension bridge before giving up
214
+ const bridgeResult2 = await tryBridgeCapture(domain, fullUrl, options);
215
+ if (bridgeResult2)
216
+ return bridgeResult2;
116
217
  return {
117
218
  success: false,
118
219
  reason: 'no_skill_file',
@@ -125,6 +226,10 @@ export async function browse(url, options = {}) {
125
226
  // Step 4: Pick best endpoint
126
227
  const endpoint = pickEndpoint(skill, urlPath);
127
228
  if (!endpoint) {
229
+ // Try extension bridge before giving up
230
+ const bridgeResult3 = await tryBridgeCapture(domain, fullUrl, options);
231
+ if (bridgeResult3)
232
+ return bridgeResult3;
128
233
  return {
129
234
  success: false,
130
235
  reason: 'no_replayable_endpoints',
@@ -165,6 +270,10 @@ export async function browse(url, options = {}) {
165
270
  };
166
271
  }
167
272
  catch {
273
+ // Try extension bridge before giving up
274
+ const bridgeResult4 = await tryBridgeCapture(domain, fullUrl, options);
275
+ if (bridgeResult4)
276
+ return bridgeResult4;
168
277
  return {
169
278
  success: false,
170
279
  reason: 'replay_failed',
@@ -1 +1 @@
1
- {"version":3,"file":"browse.js","sourceRoot":"","sources":["../../src/orchestration/browse.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"browse.js","sourceRoot":"","sources":["../../src/orchestration/browse.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AA0C5F;;;GAGG;AACH,KAAK,UAAU,gBAAgB,CAC7B,MAAc,EACd,OAAe,EACf,OAAsB;IAEtB,MAAM,UAAU,GAAG,OAAO,CAAC,iBAAiB,IAAI,cAAc,CAAC;IAC/D,IAAI,CAAC,MAAM,eAAe,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpD,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAEnG,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxE,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QACrC,+BAA+B;QAC/B,IAAI,CAAC;YACH,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;YACtE,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;gBAC/B,MAAM,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,gDAAgD;QAClD,CAAC;QAED,oDAAoD;QACpD,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC;eAChE,UAAU,CAAC,CAAC,CAAC,CAAC;QAEnB,IAAI,YAAY,EAAE,SAAS,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;YACxC,uCAAuC;YACvC,IAAI,OAAO,GAAG,GAAG,CAAC;YAClB,IAAI,CAAC;gBAAC,OAAO,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;YACxE,MAAM,QAAQ,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;YAErD,IAAI,QAAQ,EAAE,CAAC;gBACb,IAAI,CAAC;oBACH,MAAM,YAAY,GAAG,MAAM,cAAc,CAAC,YAAY,EAAE,QAAQ,CAAC,EAAE,EAAE;wBACnE,QAAQ,EAAE,OAAO,CAAC,QAAQ;wBAC1B,cAAc,EAAE,OAAO,CAAC,cAAc;qBACvC,CAAC,CAAC;oBACH,IAAI,YAAY,CAAC,MAAM,IAAI,GAAG,IAAI,YAAY,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;wBAC5D,OAAO;4BACL,OAAO,EAAE,IAAI;4BACb,IAAI,EAAE,YAAY,CAAC,IAAI;4BACvB,MAAM,EAAE,YAAY,CAAC,MAAM;4BAC3B,MAAM;4BACN,UAAU,EAAE,QAAQ,CAAC,EAAE;4BACvB,IAAI,EAAE,QAAQ,CAAC,aAAa,EAAE,IAAI,IAAI,SAAS;4BAC/C,WAAW,EAAE,QAAQ;4BACrB,UAAU,EAAE,YAAY,CAAC,UAAU,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;4BAC/D,IAAI,EAAE,OAAO,CAAC,IAAI;4BAClB,GAAG,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;yBACvD,CAAC;oBACJ,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,wDAAwD;gBAC1D,CAAC;YACH,CAAC;QACH,CAAC;QAED,0CAA0C;QAC1C,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,sBAAsB;YAC9B,UAAU,EAAE,YAAY,UAAU,CAAC,MAAM,mEAAmE,MAAM,IAAI;YACtH,MAAM;YACN,GAAG,EAAE,OAAO;YACZ,IAAI,EAAE,OAAO,CAAC,IAAI;SACnB,CAAC;IACJ,CAAC;IAED,2BAA2B;IAC3B,IAAI,MAAM,CAAC,KAAK,KAAK,aAAa,EAAE,CAAC;QACnC,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,aAAa;YACrB,UAAU,EAAE,iCAAiC,MAAM,8BAA8B,MAAM,6BAA6B;YACpH,MAAM;YACN,GAAG,EAAE,OAAO;YACZ,IAAI,EAAE,OAAO,CAAC,IAAI;SACnB,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,KAAK,KAAK,kBAAkB,EAAE,CAAC;QACxC,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,kBAAkB;YAC1B,UAAU,EAAE,6BAA6B,MAAM,sDAAsD;YACrG,MAAM;YACN,GAAG,EAAE,OAAO;YACZ,IAAI,EAAE,OAAO,CAAC,IAAI;SACnB,CAAC;IACJ,CAAC;IAED,0DAA0D;IAC1D,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,GAAW,EACX,UAAyB,EAAE;IAE3B,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC;IAC7E,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,GAAG,EAAE,CAAC;IAEhE,IAAI,MAAc,CAAC;IACnB,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;QAChC,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC;QACzB,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,aAAa;YACrB,UAAU,EAAE,mBAAmB;YAC/B,MAAM,EAAE,EAAE;YACV,GAAG,EAAE,OAAO;YACZ,IAAI;SACL,CAAC;IACJ,CAAC;IAED,8BAA8B;IAC9B,IAAI,KAAK,GAAqB,IAAI,CAAC;IACnC,IAAI,MAAM,GAAuC,MAAM,CAAC;IAExD,IAAI,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC,SAAS,CAAC;QACrC,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC,MAAM,CAAC;IACrC,CAAC;IAED,qBAAqB;IACrB,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAC/C,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,GAAG,MAAM,CAAC;YAChB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED,wBAAwB;IACxB,IAAI,CAAC,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;YAC3D,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC;YAE1C,IAAI,SAAS,CAAC,SAAS,IAAI,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;gBAC/D,CAAC,SAAS,CAAC,UAAU,KAAK,MAAM,IAAI,SAAS,CAAC,UAAU,KAAK,QAAQ,CAAC,EAAE,CAAC;gBAC3E,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC;gBAC5B,MAAM,GAAG,YAAY,CAAC;gBAEtB,eAAe;gBACf,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;gBACtE,MAAM,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;gBAChC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;YAC1C,CAAC;iBAAM,CAAC;gBACN,iEAAiE;gBACjE,IAAI,CAAC;oBACH,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;oBACrD,IAAI,UAAU,IAAI,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;wBACrG,OAAO;4BACL,OAAO,EAAE,IAAI;4BACb,IAAI,EAAE,UAAU;4BAChB,MAAM,EAAE,GAAG;4BACX,MAAM;4BACN,UAAU,EAAE,MAAM;4BAClB,IAAI,EAAE,OAAO;4BACb,WAAW,EAAE,YAAY;4BACzB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;4BACpC,IAAI;yBACL,CAAC;oBACJ,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,+CAA+C;gBACjD,CAAC;gBACD,wCAAwC;gBACxC,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;gBACvE,IAAI,aAAa;oBAAE,OAAO,aAAa,CAAC;gBAExC,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,MAAM,EAAE,yBAAyB;oBACjC,mBAAmB,EAAE,SAAS,CAAC,UAAU;oBACzC,UAAU,EAAE,gBAAgB;oBAC5B,MAAM;oBACN,GAAG,EAAE,OAAO;oBACZ,IAAI;iBACL,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,8CAA8C;QAChD,CAAC;IACH,CAAC;IAED,6DAA6D;IAC7D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,IAAI,CAAC;gBACH,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACrD,IAAI,UAAU,IAAI,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;oBACrG,OAAO;wBACL,OAAO,EAAE,IAAI;wBACb,IAAI,EAAE,UAAU;wBAChB,MAAM,EAAE,GAAG;wBACX,MAAM;wBACN,UAAU,EAAE,MAAM;wBAClB,IAAI,EAAE,OAAO;wBACb,WAAW,EAAE,YAAY;wBACzB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;wBACpC,IAAI;qBACL,CAAC;gBACJ,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,+CAA+C;YACjD,CAAC;QACH,CAAC;QACD,wCAAwC;QACxC,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACvE,IAAI,aAAa;YAAE,OAAO,aAAa,CAAC;QAExC,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,eAAe;YACvB,UAAU,EAAE,gBAAgB;YAC5B,MAAM;YACN,GAAG,EAAE,OAAO;YACZ,IAAI;SACL,CAAC;IACJ,CAAC;IAED,6BAA6B;IAC7B,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC9C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,wCAAwC;QACxC,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACvE,IAAI,aAAa;YAAE,OAAO,aAAa,CAAC;QAExC,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,yBAAyB;YACjC,UAAU,EAAE,gBAAgB;YAC5B,MAAM;YACN,GAAG,EAAE,OAAO;YACZ,IAAI;SACL,CAAC;IACJ,CAAC;IAED,iBAAiB;IACjB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;QAC9G,MAAM,WAAW,GAAG,MAAM,CAAC;QAE3B,6DAA6D;QAC7D,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QACzD,IAAI,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YACtC,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,kBAAkB;gBAC1B,mBAAmB,EAAE,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;gBACnE,UAAU,EAAE,gBAAgB;gBAC5B,MAAM;gBACN,GAAG,EAAE,OAAO;gBACZ,IAAI;aACL,CAAC;QACJ,CAAC;QAED,OAAO;YACL,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,MAAM;YACN,UAAU,EAAE,QAAQ,CAAC,EAAE;YACvB,IAAI,EAAE,QAAQ,CAAC,aAAa,EAAE,IAAI,IAAI,SAAS;YAC/C,WAAW;YACX,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,IAAI;YACJ,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACjD,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,wCAAwC;QACxC,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACvE,IAAI,aAAa;YAAE,OAAO,aAAa,CAAC;QAExC,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,eAAe;YACvB,UAAU,EAAE,gBAAgB;YAC5B,MAAM;YACN,GAAG,EAAE,OAAO;YACZ,IAAI;SACL,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;AAEjE;;;;;GAKG;AACH,SAAS,YAAY,CAAC,KAAgB,EAAE,OAAe;IACrD,MAAM,UAAU,GAAG,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAC7C,EAAE,CAAC,MAAM,KAAK,KAAK;QACnB,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,aAAa,EAAE,IAAI,IAAI,SAAS,CAAC,CAC1D,CAAC;IAEF,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzC,sBAAsB;IACtB,IAAI,OAAO,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;QAC5F,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;IAC1B,CAAC;IAED,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;AACvB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apitap/core",
3
- "version": "1.0.22",
3
+ "version": "1.2.0",
4
4
  "description": "Intercept web API traffic during browsing. Generate portable skill files so AI agents can call APIs directly instead of scraping.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -10,6 +10,7 @@
10
10
  },
11
11
  "scripts": {
12
12
  "build": "tsc",
13
+ "postbuild": "chmod +x dist/native-host.js 2>/dev/null || true",
13
14
  "dev": "tsx src/cli.ts",
14
15
  "test": "node --import tsx --test 'test/**/*.test.ts'",
15
16
  "typecheck": "tsc --noEmit",
@@ -0,0 +1,67 @@
1
+ import net from 'node:net';
2
+ import { promises as fs } from 'node:fs';
3
+ import path from 'node:path';
4
+ import os from 'node:os';
5
+
6
+ export const DEFAULT_SOCKET = path.join(os.homedir(), '.apitap', 'bridge.sock');
7
+
8
+ export interface BridgeCaptureResult {
9
+ success: boolean;
10
+ skillFiles?: any[];
11
+ error?: string;
12
+ }
13
+
14
+ /**
15
+ * Fast check: does the bridge socket exist?
16
+ * Returns false if the file doesn't exist (costs ~0.1ms).
17
+ * Returns true if the file exists (doesn't verify it's connectable).
18
+ */
19
+ export async function bridgeAvailable(socketPath: string = DEFAULT_SOCKET): Promise<boolean> {
20
+ try {
21
+ await fs.access(socketPath);
22
+ return true;
23
+ } catch {
24
+ return false;
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Send a capture_request to the extension via the native host bridge.
30
+ * Returns skill files on success, or a structured error.
31
+ */
32
+ export async function requestBridgeCapture(
33
+ domain: string,
34
+ socketPath: string = DEFAULT_SOCKET,
35
+ options: { timeout?: number } = {},
36
+ ): Promise<BridgeCaptureResult> {
37
+ const timeout = options.timeout ?? 120_000; // 2 minutes (capture can take time)
38
+
39
+ return new Promise((resolve) => {
40
+ const timer = setTimeout(() => {
41
+ client.destroy();
42
+ resolve({ success: false, error: 'timeout' });
43
+ }, timeout);
44
+
45
+ const client = net.createConnection(socketPath, () => {
46
+ const message = JSON.stringify({ action: 'capture_request', domain }) + '\n';
47
+ client.write(message);
48
+ });
49
+
50
+ let data = '';
51
+ client.on('data', (chunk) => { data += chunk.toString(); });
52
+
53
+ client.on('end', () => {
54
+ clearTimeout(timer);
55
+ try {
56
+ resolve(JSON.parse(data));
57
+ } catch {
58
+ resolve({ success: false, error: 'invalid response from bridge' });
59
+ }
60
+ });
61
+
62
+ client.on('error', (err) => {
63
+ clearTimeout(timer);
64
+ resolve({ success: false, error: `bridge connection failed: ${err.message}` });
65
+ });
66
+ });
67
+ }
package/src/cli.ts CHANGED
@@ -20,7 +20,7 @@ import { discover } from './discovery/index.js';
20
20
  import { peek } from './read/peek.js';
21
21
  import { read } from './read/index.js';
22
22
  import { homedir } from 'node:os';
23
- import { join } from 'node:path';
23
+ import { join, resolve, dirname } from 'node:path';
24
24
  import { readFileSync } from 'node:fs';
25
25
  import { fileURLToPath } from 'node:url';
26
26
  import { createMcpServer } from './mcp.js';
@@ -80,6 +80,7 @@ function printUsage(): void {
80
80
  apitap peek <url> Zero-cost triage (HEAD only)
81
81
  apitap read <url> Extract content without a browser
82
82
  apitap stats Show token savings report
83
+ apitap extension install Register native messaging host for Chrome
83
84
 
84
85
  Discover options:
85
86
  --json Output machine-readable JSON
@@ -983,6 +984,48 @@ async function handleRead(positional: string[], flags: Record<string, string | b
983
984
  console.log();
984
985
  }
985
986
 
987
+ async function handleExtension(positional: string[], flags: Record<string, string | boolean>): Promise<void> {
988
+ const subcommand = positional[0];
989
+
990
+ if (subcommand === 'install') {
991
+ const extensionId = flags['extension-id'];
992
+ if (!extensionId || typeof extensionId !== 'string') {
993
+ console.error('Usage: apitap extension install --extension-id <id>');
994
+ console.error('');
995
+ console.error('Find your extension ID at chrome://extensions (enable Developer mode)');
996
+ process.exit(1);
997
+ }
998
+
999
+ // Resolve the native host script path (always use dist/ — compiled output)
1000
+ const hostPath = resolve(dirname(fileURLToPath(import.meta.url)), '../dist/native-host.js').replace(/\/src\/\.\.\/dist\//, '/dist/');
1001
+
1002
+ const { installNativeHost } = await import('./extension/install.js');
1003
+ const { installed, errors } = await installNativeHost(hostPath, extensionId);
1004
+
1005
+ if (installed.length > 0) {
1006
+ console.log('Native messaging host installed:');
1007
+ for (const p of installed) {
1008
+ console.log(` ✓ ${p}`);
1009
+ }
1010
+ }
1011
+ if (errors.length > 0) {
1012
+ console.error('Errors:');
1013
+ for (const e of errors) {
1014
+ console.error(` ✗ ${e}`);
1015
+ }
1016
+ }
1017
+ if (installed.length === 0) {
1018
+ console.error('No browsers found. Are you on Linux or macOS?');
1019
+ process.exit(1);
1020
+ }
1021
+ return;
1022
+ }
1023
+
1024
+ console.error(`Unknown extension subcommand: ${subcommand}`);
1025
+ console.error('Usage: apitap extension install --extension-id <id>');
1026
+ process.exit(1);
1027
+ }
1028
+
986
1029
  async function main(): Promise<void> {
987
1030
  const { command, positional, flags } = parseArgs(process.argv.slice(2));
988
1031
 
@@ -1041,6 +1084,9 @@ async function main(): Promise<void> {
1041
1084
  case 'read':
1042
1085
  await handleRead(positional, flags);
1043
1086
  break;
1087
+ case 'extension':
1088
+ await handleExtension(positional, flags);
1089
+ break;
1044
1090
  default:
1045
1091
  printUsage();
1046
1092
  }