agent-permission 0.1.6 → 0.1.7

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.
package/README.md CHANGED
@@ -4,8 +4,20 @@ Give AI agents a permission gate before they touch external URLs.
4
4
 
5
5
  ## Quickstart
6
6
 
7
+ For one personal Codex setup that works across repositories:
8
+
9
+ ```bash
10
+ npx -y agent-permission@latest install --adapter codex
11
+ node "$HOME/.config/agent-permission/agent-permission.mjs" config set api-key <YOUR_API_KEY>
12
+ node "$HOME/.config/agent-permission/agent-permission.mjs" config doctor
13
+ ```
14
+
15
+ `install --adapter codex` defaults to user scope, writes personal Codex instructions under your Agent Permission config directory, and installs a reusable runner there. The install output prints the exact runner command for your machine.
16
+
17
+ For a repository-owned instruction block:
18
+
7
19
  ```bash
8
- npx -y agent-permission@latest install --adapter auto
20
+ npx -y agent-permission@latest install --adapter auto --scope project
9
21
  ```
10
22
 
11
23
  This adds an Agent Permission block to the local agent instruction file, such as `AGENTS.md`, `CLAUDE.md`, or `agent-permission.chatgpt.md`, depending on the selected adapter. It also writes a tiny project-local runner at `.agent-permission/agent-permission.mjs` so repeated checks do not need npm registry access.
@@ -13,20 +25,20 @@ This adds an Agent Permission block to the local agent instruction file, such as
13
25
  To install instructions and configure live checks in one step:
14
26
 
15
27
  ```bash
16
- npx -y agent-permission@latest install --adapter auto --api-key <YOUR_API_KEY>
28
+ npx -y agent-permission@latest install --adapter codex --api-key <YOUR_API_KEY>
17
29
  ```
18
30
 
19
- To avoid installing a project runner in every repository, install once at user scope:
31
+ To force a project-local Codex install instead:
20
32
 
21
33
  ```bash
22
- npx -y agent-permission@latest install --adapter codex --scope user
34
+ npx -y agent-permission@latest install --adapter codex --scope project
23
35
  ```
24
36
 
25
37
  Add an API key when you want live checks from the command line, CI, or agent runs:
26
38
 
27
39
  ```bash
28
- node .agent-permission/agent-permission.mjs config set api-key <YOUR_API_KEY>
29
- node .agent-permission/agent-permission.mjs check https://example.com/blog-post --action summarize --exit-code
40
+ node "$HOME/.config/agent-permission/agent-permission.mjs" config set api-key <YOUR_API_KEY>
41
+ node "$HOME/.config/agent-permission/agent-permission.mjs" check https://example.com/blog-post --action summarize --exit-code
30
42
  ```
31
43
 
32
44
  ## What the Agent Runs
@@ -34,16 +46,16 @@ node .agent-permission/agent-permission.mjs check https://example.com/blog-post
34
46
  After install, project instructions tell compatible agents to run:
35
47
 
36
48
  ```bash
37
- node .agent-permission/agent-permission.mjs check <url> --action <crawl|summarize|extract|train|transact|post> --exit-code
49
+ node <installed-runner-path> check <url> --action <crawl|summarize|extract|train|transact|post> --exit-code
38
50
  ```
39
51
 
40
52
  If the runner is missing, the installed instructions tell the agent to stop and ask you to repair the installation once:
41
53
 
42
54
  ```bash
43
- npx -y agent-permission@latest install --adapter auto --scope project
55
+ npx -y agent-permission@latest install --adapter codex --scope user
44
56
  ```
45
57
 
46
- The generated preflight block does not tell agents to run `npx ... check` during a URL request, so repeated checks do not need registry access or unpinned-code approval.
58
+ If the API key is missing, the generated instructions tell the agent to stop and ask you to run the exact `config set api-key` command for that installed runner. The generated preflight block does not tell agents to run `npx ... check` during a URL request, so repeated checks do not need registry access or unpinned-code approval.
47
59
 
48
60
  ## Commands
49
61
 
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAKA,OAAO,EAAyD,KAAK,EAAuD,OAAO,EAAE,MAAM,YAAY,CAAC;AAExJ,UAAU,WAAW;IACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;IACxC,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CA6BzF;AAmID,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,WAAW,CA2BtD"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAKA,OAAO,EAAyD,KAAK,EAAuD,OAAO,EAAE,MAAM,YAAY,CAAC;AAExJ,UAAU,WAAW;IACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;IACxC,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CA6BzF;AA6ID,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,WAAW,CA2BtD"}
package/dist/cli.js CHANGED
@@ -8,7 +8,7 @@ export async function runCli(argv, runtime, io) {
8
8
  const invoked = argv[1] || 'agent-permission';
9
9
  const args = argv.slice(2);
10
10
  if (isSkillsInvocation(invoked, args)) {
11
- return runCli([argv[0], argv[1], 'install', '--adapter', 'auto'], runtime, io);
11
+ return runCli([argv[0], argv[1], 'install', '--adapter', 'codex', '--scope', 'user'], runtime, io);
12
12
  }
13
13
  const command = args[0];
14
14
  const rest = args.slice(1);
@@ -42,7 +42,14 @@ async function runCheck(args, runtime, io) {
42
42
  if (!url || !action) {
43
43
  throw new Error('Usage: agent-permission check <url> --action <crawl|summarize|extract|train|transact|post>');
44
44
  }
45
+ const localDecision = localUrlDecision(url, action);
46
+ if (localDecision) {
47
+ const format = outputFormat(parsed);
48
+ io.stdout(format === 'json' ? JSON.stringify(localDecision, null, 2) : formatCheckHuman(localDecision));
49
+ return parsed.flags['exit-code'] ? decisionExitCode(localDecision.decision) : 0;
50
+ }
45
51
  const config = await resolveConfig(runtime);
52
+ ensureApiKeyConfigured(config.apiKey, invokedRunnerCommand(runtime));
46
53
  const params = {
47
54
  url,
48
55
  action,
@@ -66,6 +73,7 @@ async function runBatch(args, runtime, io) {
66
73
  throw new Error('Usage: agent-permission batch --file checks.json');
67
74
  }
68
75
  const config = await resolveConfig(runtime);
76
+ ensureApiKeyConfigured(config.apiKey, invokedRunnerCommand(runtime));
69
77
  const batch = JSON.parse(await readFile(file, 'utf8'));
70
78
  const result = await batchCheckPermissions(batch, {
71
79
  apiUrl: stringFlag(parsed, 'api-url') || config.apiUrl,
@@ -98,11 +106,12 @@ async function runVerify(args, runtime, io) {
98
106
  async function runInstall(args, runtime, io) {
99
107
  const parsed = parseFlags(args);
100
108
  const adapter = parseAdapter(stringFlag(parsed, 'adapter') || parsed.positionals[0] || 'auto');
101
- const scope = parseScope(stringFlag(parsed, 'scope') || 'project');
109
+ const scope = parseScope(stringFlag(parsed, 'scope') || defaultInstallScope(adapter));
102
110
  const result = await installAgentInstructions(adapter, scope, runtime);
103
111
  const messages = [
104
112
  `Installed Agent Permission instructions for ${result.adapter} at ${result.path}`,
105
113
  `Installed local Agent Permission runner at ${result.runnerPath}`,
114
+ `Agent preflight command: ${result.checkCommand}`,
106
115
  ];
107
116
  const apiKey = stringFlag(parsed, 'api-key');
108
117
  if (apiKey) {
@@ -113,7 +122,7 @@ async function runInstall(args, runtime, io) {
113
122
  else {
114
123
  const config = await resolveConfig(runtime);
115
124
  if (!config.apiKey) {
116
- messages.push(`API key is not configured. Live checks will fail until you run \`${result.runnerCommand} config set api-key <YOUR_API_KEY>\` or set AGENT_PERMISSION_API_KEY.`, `Verify setup with \`${result.runnerCommand} config doctor\`.`);
125
+ messages.push(`API key is not configured. Live checks will fail until you run \`${result.apiKeyCommand}\` or set AGENT_PERMISSION_API_KEY.`, `Verify setup with \`${result.doctorCommand}\`.`);
117
126
  }
118
127
  }
119
128
  io.stdout(messages.join('\n'));
@@ -197,6 +206,89 @@ function parseScope(value) {
197
206
  return value;
198
207
  throw new Error('Scope must be project or user.');
199
208
  }
209
+ function ensureApiKeyConfigured(apiKey, runnerCommand) {
210
+ if (!apiKey) {
211
+ throw new Error(`Missing API key. Set AGENT_PERMISSION_API_KEY or run \`${runnerCommand} config set api-key <key>\`.`);
212
+ }
213
+ }
214
+ function invokedRunnerCommand(runtime) {
215
+ return runtime.env.AGENT_PERMISSION_RUNNER_COMMAND || 'agent-permission';
216
+ }
217
+ function defaultInstallScope(adapter) {
218
+ return adapter === 'codex' ? 'user' : 'project';
219
+ }
220
+ function localUrlDecision(url, action) {
221
+ const localKind = localUrlKind(url);
222
+ if (!localKind)
223
+ return undefined;
224
+ const issuedAt = new Date().toISOString();
225
+ return {
226
+ id: 'local_url_check',
227
+ decision: 'allow',
228
+ confidence: 'high',
229
+ risk: 'low',
230
+ reasons: [
231
+ `${localKind} URL was not sent to the Agent Permission API; local development and in-app browser URLs are allowed without external preflight.`,
232
+ ],
233
+ sources: [
234
+ {
235
+ type: 'local_url',
236
+ url,
237
+ fetched_at: issuedAt,
238
+ evidence: localKind,
239
+ },
240
+ ],
241
+ receipt: {
242
+ receipt_id: 'local_only_no_external_receipt',
243
+ check_id: 'local_url_check',
244
+ url_hash: 'local_only',
245
+ action,
246
+ decision: 'allow',
247
+ source_hashes: [],
248
+ issued_at: issuedAt,
249
+ account_id: 'local',
250
+ signature_alg: 'none',
251
+ signature: 'not_signed',
252
+ },
253
+ };
254
+ }
255
+ function localUrlKind(value) {
256
+ let parsed;
257
+ try {
258
+ parsed = new URL(value);
259
+ }
260
+ catch {
261
+ return undefined;
262
+ }
263
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:')
264
+ return undefined;
265
+ const hostname = parsed.hostname.toLowerCase().replace(/^\[|\]$/g, '');
266
+ if (hostname === 'localhost' || hostname.endsWith('.localhost'))
267
+ return 'localhost';
268
+ if (hostname === '::1')
269
+ return 'loopback';
270
+ if (hostname.startsWith('127.'))
271
+ return 'loopback';
272
+ if (hostname === '0.0.0.0')
273
+ return 'local bind address';
274
+ if (hostname.endsWith('.local'))
275
+ return 'local network';
276
+ const parts = hostname.split('.').map((part) => Number(part));
277
+ if (parts.length === 4 && parts.every((part) => Number.isInteger(part) && part >= 0 && part <= 255)) {
278
+ const [first, second] = parts;
279
+ if (first === 10)
280
+ return 'private network';
281
+ if (first === 172 && second >= 16 && second <= 31)
282
+ return 'private network';
283
+ if (first === 192 && second === 168)
284
+ return 'private network';
285
+ if (first === 169 && second === 254)
286
+ return 'link-local';
287
+ }
288
+ if (hostname.startsWith('fc') || hostname.startsWith('fd') || hostname.startsWith('fe80:'))
289
+ return 'private network';
290
+ return undefined;
291
+ }
200
292
  function isSkillsInvocation(invoked, args) {
201
293
  const name = invoked.split('/').pop() || invoked;
202
294
  return name === 'skills' && args[0] === 'add' && args[1] === 'agent-permission';
package/dist/install.d.ts CHANGED
@@ -4,8 +4,16 @@ export interface InstallResult {
4
4
  path: string;
5
5
  runnerPath: string;
6
6
  runnerCommand: string;
7
+ checkCommand: string;
8
+ apiKeyCommand: string;
9
+ doctorCommand: string;
10
+ repairCommand: string;
7
11
  }
8
12
  export declare function installAgentInstructions(adapter: Adapter, scope: InstallScope, runtime: Runtime): Promise<InstallResult>;
9
13
  export declare function upsertBlock(existing: string, blockBody: string): string;
10
- export declare function buildInstructionBlock(adapter: Exclude<Adapter, 'auto'>, runnerCommand?: string, repairCommand?: string): string;
14
+ export declare function buildInstructionBlock(adapter: Exclude<Adapter, 'auto'>, commands?: {
15
+ checkCommand?: string;
16
+ apiKeyCommand?: string;
17
+ repairCommand?: string;
18
+ }): string;
11
19
  //# sourceMappingURL=install.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAmB,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAM7E,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAsB,wBAAwB,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,CAiB9H;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,UAU9D;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,EACjC,aAAa,SAAgC,EAC7C,aAAa,SAAgF,UA4B9F"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAmB,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAM7E,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAsB,wBAAwB,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,CAiC9H;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,UAU9D;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,EACjC,QAAQ,GAAE;IACR,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CACnB,UAqCP"}
package/dist/install.js CHANGED
@@ -10,16 +10,32 @@ export async function installAgentInstructions(adapter, scope, runtime) {
10
10
  const runner = getRunnerPath(scope, runtime);
11
11
  const runnerCommand = getRunnerCommand(scope, runner);
12
12
  const repairCommand = getRepairCommand(resolved, scope);
13
+ const checkCommand = `${runnerCommand} check <url> --action <crawl|summarize|extract|train|transact|post> --exit-code`;
14
+ const apiKeyCommand = `${runnerCommand} config set api-key <YOUR_API_KEY>`;
15
+ const doctorCommand = `${runnerCommand} config doctor`;
13
16
  const existing = await readFile(path, 'utf8').catch((err) => {
14
17
  if (err && typeof err === 'object' && 'code' in err && err.code === 'ENOENT')
15
18
  return '';
16
19
  throw err;
17
20
  });
18
- const next = upsertBlock(existing, buildInstructionBlock(resolved, runnerCommand, repairCommand));
21
+ const next = upsertBlock(existing, buildInstructionBlock(resolved, {
22
+ checkCommand,
23
+ apiKeyCommand,
24
+ repairCommand,
25
+ }));
19
26
  await mkdir(dirname(path), { recursive: true });
20
27
  await writeLocalRunner(runner, runnerCommand);
21
28
  await writeFile(path, next);
22
- return { adapter: resolved, path, runnerPath: runner, runnerCommand };
29
+ return {
30
+ adapter: resolved,
31
+ path,
32
+ runnerPath: runner,
33
+ runnerCommand,
34
+ checkCommand,
35
+ apiKeyCommand,
36
+ doctorCommand,
37
+ repairCommand,
38
+ };
23
39
  }
24
40
  export function upsertBlock(existing, blockBody) {
25
41
  const block = `${BLOCK_START}\n${blockBody.trim()}\n${BLOCK_END}`;
@@ -30,13 +46,16 @@ export function upsertBlock(existing, blockBody) {
30
46
  const prefix = existing.trimEnd();
31
47
  return prefix ? `${prefix}\n\n${block}\n` : `${block}\n`;
32
48
  }
33
- export function buildInstructionBlock(adapter, runnerCommand = `node ${PROJECT_RUNNER_PATH}`, repairCommand = `npx -y agent-permission@latest install --adapter ${adapter} --scope project`) {
49
+ export function buildInstructionBlock(adapter, commands = {}) {
34
50
  const agentName = {
35
51
  codex: 'Codex',
36
52
  claude: 'Claude',
37
53
  chatgpt: 'ChatGPT',
38
54
  openclaw: 'OpenClaw',
39
55
  }[adapter];
56
+ const checkCommand = commands.checkCommand || `node ${PROJECT_RUNNER_PATH} check <url> --action <crawl|summarize|extract|train|transact|post> --exit-code`;
57
+ const apiKeyCommand = commands.apiKeyCommand || `node ${PROJECT_RUNNER_PATH} config set api-key <YOUR_API_KEY>`;
58
+ const repairCommand = commands.repairCommand || `npx -y agent-permission@latest install --adapter ${adapter} --scope project`;
40
59
  return `# Agent Permission
41
60
 
42
61
  These instructions equip ${agentName} with Agent Permission preflight checks.
@@ -44,7 +63,7 @@ These instructions equip ${agentName} with Agent Permission preflight checks.
44
63
  Before crawling, summarizing, extracting, training on, transacting with, or posting to a URL, run:
45
64
 
46
65
  \`\`\`bash
47
- ${runnerCommand} check <url> --action <crawl|summarize|extract|train|transact|post> --exit-code
66
+ ${checkCommand}
48
67
  \`\`\`
49
68
 
50
69
  Do not use npm while handling an individual URL request. If the runner command is missing or cannot start, stop and ask the user to repair the installation once with:
@@ -53,6 +72,12 @@ Do not use npm while handling an individual URL request. If the runner command i
53
72
  ${repairCommand}
54
73
  \`\`\`
55
74
 
75
+ If the runner reports that the API key is missing, stop and ask the user to configure it with:
76
+
77
+ \`\`\`bash
78
+ ${apiKeyCommand}
79
+ \`\`\`
80
+
56
81
  Use \`crawl\` for fetching or indexing pages, \`summarize\` for compacting page content, \`extract\` for structured data pulls, \`train\` for model training or dataset creation, \`transact\` for purchase/account-changing actions, and \`post\` for creating or modifying remote content.
57
82
 
58
83
  Treat \`allow\` as permitted, \`deny\` as blocked, and \`escalate\` as requiring human approval before continuing. Preserve the returned receipt ID in task notes when a permission decision affects user-visible work.`;
@@ -168,6 +193,12 @@ async function runCheck(args) {
168
193
  throw new Error('Usage: agent-permission check <url> --action <crawl|summarize|extract|train|transact|post>');
169
194
  }
170
195
 
196
+ const localDecision = localUrlDecision(url, action);
197
+ if (localDecision) {
198
+ console.log(parsed.flags.json ? JSON.stringify(localDecision, null, 2) : formatCheckHuman(localDecision));
199
+ return parsed.flags['exit-code'] ? decisionExitCode(localDecision.decision) : 0;
200
+ }
201
+
171
202
  const config = await resolveConfig();
172
203
  const result = await checkPermission({
173
204
  url,
@@ -327,6 +358,73 @@ function decisionExitCode(decision) {
327
358
  return 1;
328
359
  }
329
360
 
361
+ function localUrlDecision(url, action) {
362
+ const localKind = localUrlKind(url);
363
+ if (!localKind) return undefined;
364
+
365
+ const issuedAt = new Date().toISOString();
366
+ return {
367
+ id: 'local_url_check',
368
+ decision: 'allow',
369
+ confidence: 'high',
370
+ risk: 'low',
371
+ reasons: [
372
+ \`\${localKind} URL was not sent to the Agent Permission API; local development and in-app browser URLs are allowed without external preflight.\`,
373
+ ],
374
+ sources: [
375
+ {
376
+ type: 'local_url',
377
+ url,
378
+ fetched_at: issuedAt,
379
+ evidence: localKind,
380
+ },
381
+ ],
382
+ receipt: {
383
+ receipt_id: 'local_only_no_external_receipt',
384
+ check_id: 'local_url_check',
385
+ url_hash: 'local_only',
386
+ action,
387
+ decision: 'allow',
388
+ source_hashes: [],
389
+ issued_at: issuedAt,
390
+ account_id: 'local',
391
+ signature_alg: 'none',
392
+ signature: 'not_signed',
393
+ },
394
+ };
395
+ }
396
+
397
+ function localUrlKind(value) {
398
+ let parsed;
399
+ try {
400
+ parsed = new URL(value);
401
+ } catch {
402
+ return undefined;
403
+ }
404
+
405
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return undefined;
406
+
407
+ const hostname = parsed.hostname.toLowerCase().replace(/^\\[|\\]$/g, '');
408
+ if (hostname === 'localhost' || hostname.endsWith('.localhost')) return 'localhost';
409
+ if (hostname === '::1') return 'loopback';
410
+ if (hostname.startsWith('127.')) return 'loopback';
411
+ if (hostname === '0.0.0.0') return 'local bind address';
412
+ if (hostname.endsWith('.local')) return 'local network';
413
+
414
+ const parts = hostname.split('.').map((part) => Number(part));
415
+ if (parts.length === 4 && parts.every((part) => Number.isInteger(part) && part >= 0 && part <= 255)) {
416
+ const [first, second] = parts;
417
+ if (first === 10) return 'private network';
418
+ if (first === 172 && second >= 16 && second <= 31) return 'private network';
419
+ if (first === 192 && second === 168) return 'private network';
420
+ if (first === 169 && second === 254) return 'link-local';
421
+ }
422
+
423
+ if (hostname.startsWith('fc') || hostname.startsWith('fd') || hostname.startsWith('fe80:')) return 'private network';
424
+
425
+ return undefined;
426
+ }
427
+
330
428
  function getConfigPath() {
331
429
  if (process.env.AGENT_PERMISSION_CONFIG) return process.env.AGENT_PERMISSION_CONFIG;
332
430
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-permission",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Public CLI for Agent Permission checks and agent workspace installation.",
5
5
  "type": "module",
6
6
  "bin": "./dist/index.js",