@goplus/agentguard 1.1.18 → 1.1.26

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.
Files changed (71) hide show
  1. package/README.md +6 -1
  2. package/dist/adapters/engine.d.ts.map +1 -1
  3. package/dist/adapters/engine.js +10 -0
  4. package/dist/adapters/engine.js.map +1 -1
  5. package/dist/adapters/openclaw-plugin.d.ts.map +1 -1
  6. package/dist/adapters/openclaw-plugin.js +24 -3
  7. package/dist/adapters/openclaw-plugin.js.map +1 -1
  8. package/dist/adapters/openclaw.d.ts.map +1 -1
  9. package/dist/adapters/openclaw.js +7 -2
  10. package/dist/adapters/openclaw.js.map +1 -1
  11. package/dist/cli.js +254 -72
  12. package/dist/cli.js.map +1 -1
  13. package/dist/config.d.ts +5 -0
  14. package/dist/config.d.ts.map +1 -1
  15. package/dist/config.js +13 -0
  16. package/dist/config.js.map +1 -1
  17. package/dist/feed/cron.d.ts +17 -0
  18. package/dist/feed/cron.d.ts.map +1 -1
  19. package/dist/feed/cron.js +197 -18
  20. package/dist/feed/cron.js.map +1 -1
  21. package/dist/feed/selfcheck.d.ts.map +1 -1
  22. package/dist/feed/selfcheck.js +205 -54
  23. package/dist/feed/selfcheck.js.map +1 -1
  24. package/dist/index.d.ts +1 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +7 -1
  27. package/dist/index.js.map +1 -1
  28. package/dist/installers.d.ts.map +1 -1
  29. package/dist/installers.js +91 -5
  30. package/dist/installers.js.map +1 -1
  31. package/dist/runtime/approvals.d.ts +38 -0
  32. package/dist/runtime/approvals.d.ts.map +1 -0
  33. package/dist/runtime/approvals.js +227 -0
  34. package/dist/runtime/approvals.js.map +1 -0
  35. package/dist/runtime/evaluator.d.ts.map +1 -1
  36. package/dist/runtime/evaluator.js +54 -0
  37. package/dist/runtime/evaluator.js.map +1 -1
  38. package/dist/runtime/protect.d.ts +2 -0
  39. package/dist/runtime/protect.d.ts.map +1 -1
  40. package/dist/runtime/protect.js +81 -9
  41. package/dist/runtime/protect.js.map +1 -1
  42. package/dist/runtime/self-command.d.ts +2 -0
  43. package/dist/runtime/self-command.d.ts.map +1 -0
  44. package/dist/runtime/self-command.js +93 -0
  45. package/dist/runtime/self-command.js.map +1 -0
  46. package/dist/tests/adapter.test.js +8 -0
  47. package/dist/tests/adapter.test.js.map +1 -1
  48. package/dist/tests/cli-connect.test.js +118 -1
  49. package/dist/tests/cli-connect.test.js.map +1 -1
  50. package/dist/tests/cli-init.test.js +123 -0
  51. package/dist/tests/cli-init.test.js.map +1 -1
  52. package/dist/tests/cli-subscribe.test.js +176 -0
  53. package/dist/tests/cli-subscribe.test.js.map +1 -1
  54. package/dist/tests/feed-cron.test.js +236 -0
  55. package/dist/tests/feed-cron.test.js.map +1 -1
  56. package/dist/tests/feed-selfcheck.test.js +81 -0
  57. package/dist/tests/feed-selfcheck.test.js.map +1 -1
  58. package/dist/tests/installer.test.js +78 -2
  59. package/dist/tests/installer.test.js.map +1 -1
  60. package/dist/tests/integration.test.js +64 -0
  61. package/dist/tests/integration.test.js.map +1 -1
  62. package/dist/tests/runtime-cloud.test.js +406 -0
  63. package/dist/tests/runtime-cloud.test.js.map +1 -1
  64. package/docs/claude-code.md +3 -2
  65. package/docs/cloud-connect.md +16 -3
  66. package/docs/cloud-native-api.md +26 -118
  67. package/docs/codex.md +13 -1
  68. package/docs/openclaw.md +32 -1
  69. package/docs/privacy-boundary.md +0 -1
  70. package/package.json +1 -1
  71. package/skills/agentguard/SKILL.md +14 -4
package/dist/cli.js CHANGED
@@ -10,6 +10,7 @@ const client_js_1 = require("./cloud/client.js");
10
10
  const config_js_1 = require("./config.js");
11
11
  const index_js_1 = require("./scanner/index.js");
12
12
  const protect_js_1 = require("./runtime/protect.js");
13
+ const approvals_js_1 = require("./runtime/approvals.js");
13
14
  const policy_js_1 = require("./runtime/policy.js");
14
15
  const installers_js_1 = require("./installers.js");
15
16
  const version_js_1 = require("./version.js");
@@ -101,10 +102,11 @@ async function main() {
101
102
  .action(async (options) => {
102
103
  const apiKey = options.key || options.apiKey || process.env.AGENTGUARD_API_KEY;
103
104
  if (!apiKey) {
104
- const config = (0, config_js_1.ensureConfig)();
105
+ let config = (0, config_js_1.ensureConfig)();
105
106
  if (!isOpenClawAgentConfigured(config)) {
106
- throw new Error('Missing API key. Pass --key, --api-key, set AGENTGUARD_API_KEY, or run `agentguard init --agent openclaw` before using Agent JWT registration.');
107
+ throw new Error('AgentGuard Cloud connect supports API-key auth or OpenClaw Agent JWT registration. No API key was provided, and OpenClaw has not been initialized. Run `agentguard init --agent openclaw`, then rerun `agentguard connect`; or pass --key, --api-key, or AGENTGUARD_API_KEY for API-key auth.');
107
108
  }
109
+ config = withDetectedOpenClawAgentHost(config);
108
110
  const cloudUrl = (0, config_js_1.normalizeCloudUrl)(options.cloud || options.url || config.cloudUrl || 'https://agentguard.gopluslabs.io');
109
111
  if (config.agentId && config.agentJwt) {
110
112
  const existingConfig = { ...config, cloudUrl };
@@ -117,10 +119,11 @@ async function main() {
117
119
  agentRegisterUrl: config.agentRegisterUrl,
118
120
  cloudUrl,
119
121
  });
120
- (0, policy_js_1.saveCachedPolicy)(savedConfig.policyCachePath, policy);
121
- console.log(`Connected to AgentGuard Cloud (${savedConfig.cloudUrl}).`);
122
- console.log(`Agent JWT is active for local agent ${savedConfig.agentId}.`);
123
- console.log(`Cached policy ${policy.policyVersion} at ${savedConfig.policyCachePath}.`);
122
+ const activeConfig = (0, config_js_1.clearAgentRegisterUrl)(savedConfig);
123
+ (0, policy_js_1.saveCachedPolicy)(activeConfig.policyCachePath, policy);
124
+ console.log(`Connected to AgentGuard Cloud (${activeConfig.cloudUrl}).`);
125
+ console.log(`Agent JWT is active for local agent ${activeConfig.agentId}.`);
126
+ console.log(`Cached policy ${policy.policyVersion} at ${activeConfig.policyCachePath}.`);
124
127
  return;
125
128
  }
126
129
  catch (err) {
@@ -131,14 +134,20 @@ async function main() {
131
134
  }
132
135
  }
133
136
  }
134
- const registration = await registerAgentCredential({
135
- cloudUrl,
136
- reason: 'connect',
137
- notifyOpenClaw: true,
138
- resetExistingJwt: true,
139
- });
137
+ let registration;
138
+ try {
139
+ registration = await registerAgentCredential({
140
+ cloudUrl,
141
+ reason: 'connect',
142
+ notifyOpenClaw: false,
143
+ resetExistingJwt: true,
144
+ });
145
+ }
146
+ catch (err) {
147
+ throw new Error(`Could not register AgentGuard agent: ${err instanceof Error ? err.message : String(err)}`);
148
+ }
140
149
  console.log(`Registered local AgentGuard agent (${registration.config.agentId}).`);
141
- console.log('Open this link to bind AgentGuard Cloud to your email:');
150
+ console.log('Open this link to bind this agent to your account:');
142
151
  console.log(registration.registerUrl);
143
152
  if (registration.openClawNotification.notified) {
144
153
  console.log('Sent the activation link to the last OpenClaw channel.');
@@ -164,25 +173,30 @@ async function main() {
164
173
  program
165
174
  .command('disconnect')
166
175
  .description('Disconnect local AgentGuard from AgentGuard Cloud')
167
- .action(() => {
176
+ .action(async () => {
177
+ const currentConfig = (0, config_js_1.ensureConfig)();
178
+ const cronRemoval = await (0, cron_js_1.removeThreatFeedCron)({
179
+ name: currentConfig.threatFeedCronName || 'agentguard-threat-feed',
180
+ backend: 'auto',
181
+ agentHost: resolveCronAgentHost(currentConfig),
182
+ agentGuardHome: (0, config_js_1.getAgentGuardPaths)().home,
183
+ });
168
184
  const config = (0, config_js_1.disconnectCloud)();
169
185
  console.log('Disconnected from AgentGuard Cloud.');
170
186
  console.log('Removed local Cloud API key, Agent JWT, connection timestamp, pending event spool, and cached Cloud policy.');
187
+ printCronRemovalSummary(cronRemoval);
171
188
  console.log(`Local protection remains active using the built-in policy. Audit log: ${config.auditPath}`);
172
189
  });
173
190
  program
174
191
  .command('status')
175
192
  .description('Show local and Cloud connection status')
176
- .action(() => {
177
- const config = (0, config_js_1.ensureConfig)();
193
+ .action(async () => {
194
+ const config = await refreshAgentAccountBinding((0, config_js_1.ensureConfig)());
178
195
  const paths = (0, config_js_1.getAgentGuardPaths)();
179
196
  console.log(`Config: ${paths.configPath}`);
180
197
  console.log(`Protection level: ${config.level}`);
181
198
  console.log(`Cloud URL: ${config.cloudUrl || 'not configured'}`);
182
- console.log(`API key: ${(0, config_js_1.maskApiKey)(config.apiKey)}`);
183
- console.log(`Agent ID: ${config.agentId || 'not configured'}`);
184
- console.log(`Agent JWT: ${config.agentJwt ? 'configured' : 'not configured'}`);
185
- console.log(`Agent activation URL: ${config.agentRegisterUrl || 'not configured'}`);
199
+ printCloudAuthStatus(config);
186
200
  console.log(`Agent host: ${config.agentHost || 'not configured'}`);
187
201
  console.log(`Agent hosts: ${config.agentHosts?.join(', ') || 'not configured'}`);
188
202
  console.log(`Policy cache: ${config.policyCachePath}`);
@@ -324,6 +338,55 @@ async function main() {
324
338
  }
325
339
  process.exitCode = result.risk_level === 'critical' ? 2 : 0;
326
340
  });
341
+ program
342
+ .command('approve')
343
+ .description('Approve one pending runtime action')
344
+ .option('--action-id <id>', 'Pending action id returned by agentguard protect')
345
+ .option('--last', 'Approve the most recent unambiguous pending action')
346
+ .option('--once', 'Approve only the next matching retry')
347
+ .option('--json', 'Print JSON output')
348
+ .action((options) => {
349
+ if (!options.once) {
350
+ throw new Error('Approvals must be scoped with --once.');
351
+ }
352
+ const config = (0, config_js_1.ensureConfig)();
353
+ const approved = (0, approvals_js_1.approvePendingApproval)(config.approvalStorePath, {
354
+ actionId: options.actionId,
355
+ last: Boolean(options.last),
356
+ once: true,
357
+ sessionId: process.env.AGENTGUARD_SESSION_ID,
358
+ });
359
+ if (options.json) {
360
+ console.log(JSON.stringify({ success: true, approval: approved }, null, 2));
361
+ }
362
+ else {
363
+ console.log(`Approved once: ${approved.actionId}`);
364
+ console.log(`Expires: ${approved.expiresAt}`);
365
+ }
366
+ });
367
+ const approvals = program
368
+ .command('approvals')
369
+ .description('Inspect pending runtime approvals');
370
+ approvals
371
+ .command('list')
372
+ .description('List unexpired pending approvals')
373
+ .option('--json', 'Print JSON output')
374
+ .action((options) => {
375
+ const config = (0, config_js_1.ensureConfig)();
376
+ const pending = (0, approvals_js_1.listPendingApprovals)(config.approvalStorePath);
377
+ if (options.json) {
378
+ console.log(JSON.stringify({ success: true, approvals: pending }, null, 2));
379
+ }
380
+ else if (pending.length === 0) {
381
+ console.log('No pending approvals.');
382
+ }
383
+ else {
384
+ for (const approval of pending) {
385
+ console.log(`${approval.actionId} ${approval.actionType} ${approval.toolName} expires=${approval.expiresAt}`);
386
+ console.log(` ${approval.inputPreview}`);
387
+ }
388
+ }
389
+ });
327
390
  program
328
391
  .command('protect')
329
392
  .description('Evaluate one runtime action from stdin or hook environment')
@@ -370,6 +433,7 @@ async function main() {
370
433
  const since = options.since;
371
434
  const quiet = Boolean(options.quiet);
372
435
  const cronNotifyRun = Boolean(options.cronNotifyRun);
436
+ const cronInternalRun = Boolean(options.cronRun || options.cronNotifyRun);
373
437
  const cronTarget = validateCronTarget(options.cronTarget);
374
438
  const cronRunSendsToOpenClaw = Boolean(options.cronRun) && cronAgentHost === 'openclaw';
375
439
  const cronExpression = options.cron && !options.cronRun
@@ -411,47 +475,39 @@ async function main() {
411
475
  return;
412
476
  }
413
477
  }
414
- try {
415
- await client.subscribeFeed();
416
- }
417
- catch (err) {
418
- if (err instanceof client_js_2.CloudRequestError && err.status === 401) {
419
- if (!isOpenClawAgentConfigured(config)) {
420
- console.error('! AgentGuard Cloud credential was rejected. Run `agentguard connect --key <key>` again.');
421
- process.exitCode = 1;
422
- return;
423
- }
424
- try {
425
- registration = await registerAgentCredential({
426
- cloudUrl: config.cloudUrl,
427
- reason: 'subscribe',
428
- notifyOpenClaw: resolveCronAgentHost(config) === 'openclaw',
429
- resetExistingJwt: true,
430
- });
431
- config = registration.config;
432
- client = registration.client;
433
- await client.subscribeFeed();
434
- }
435
- catch (retryErr) {
436
- if (cronNotifyRun) {
437
- console.log('NO_REPLY');
438
- process.exitCode = 0;
478
+ if (!cronInternalRun) {
479
+ try {
480
+ await client.subscribeFeed();
481
+ }
482
+ catch (err) {
483
+ if (err instanceof client_js_2.CloudRequestError && err.status === 401) {
484
+ if (!isOpenClawAgentConfigured(config)) {
485
+ console.error('! AgentGuard Cloud credential was rejected. Run `agentguard connect --key <key>` again.');
486
+ process.exitCode = 1;
487
+ return;
488
+ }
489
+ try {
490
+ registration = await registerAgentCredential({
491
+ cloudUrl: config.cloudUrl,
492
+ reason: 'subscribe',
493
+ notifyOpenClaw: resolveCronAgentHost(config) === 'openclaw',
494
+ resetExistingJwt: true,
495
+ });
496
+ config = registration.config;
497
+ client = registration.client;
498
+ await client.subscribeFeed();
499
+ }
500
+ catch (retryErr) {
501
+ printAgentActivationRequired(registration, retryErr);
502
+ process.exitCode = 1;
439
503
  return;
440
504
  }
441
- printAgentActivationRequired(registration, retryErr);
442
- process.exitCode = 1;
443
- return;
444
505
  }
445
- }
446
- else {
447
- if (cronNotifyRun) {
448
- console.log('NO_REPLY');
449
- process.exitCode = 0;
506
+ else {
507
+ console.error(`! Could not subscribe to AgentGuard Cloud feed: ${err.message}`);
508
+ process.exitCode = 1;
450
509
  return;
451
510
  }
452
- console.error(`! Could not subscribe to AgentGuard Cloud feed: ${err.message}`);
453
- process.exitCode = 1;
454
- return;
455
511
  }
456
512
  }
457
513
  if (registration && !cronNotifyRun && !quiet && !options.json) {
@@ -463,6 +519,11 @@ async function main() {
463
519
  }
464
520
  catch (err) {
465
521
  if (err instanceof client_js_2.CloudRequestError && err.status === 401) {
522
+ if (cronInternalRun) {
523
+ await printSubscribeConnectRequired(options, cronRunSendsToOpenClaw);
524
+ process.exitCode = 1;
525
+ return;
526
+ }
466
527
  if (!isOpenClawAgentConfigured(config)) {
467
528
  console.error('! AgentGuard Cloud credential was rejected. Run `agentguard connect --key <key>` again.');
468
529
  process.exitCode = 1;
@@ -545,22 +606,35 @@ async function main() {
545
606
  // match, we must NOT mark the advisory seen, otherwise a
546
607
  // transient network blip silently buries a real hit.
547
608
  try {
548
- const reportResult = await runCloudRequestWithAgentJwtReauth({
549
- config,
550
- client,
551
- reason: 'reauth',
552
- notifyOpenClaw: resolveCronAgentHost(config) === 'openclaw',
553
- operation: (activeClient) => activeClient.reportSelfCheck(advisory.id, result.matchedArtifacts, {
609
+ if (cronInternalRun) {
610
+ await client.reportSelfCheck(advisory.id, result.matchedArtifacts, {
554
611
  elapsedMs: result.elapsedMs,
555
612
  warnings: result.warnings,
556
- }),
557
- });
558
- config = reportResult.config;
559
- client = reportResult.client;
560
- if (reportResult.registration)
561
- registration = reportResult.registration;
613
+ });
614
+ }
615
+ else {
616
+ const reportResult = await runCloudRequestWithAgentJwtReauth({
617
+ config,
618
+ client,
619
+ reason: 'reauth',
620
+ notifyOpenClaw: resolveCronAgentHost(config) === 'openclaw',
621
+ operation: (activeClient) => activeClient.reportSelfCheck(advisory.id, result.matchedArtifacts, {
622
+ elapsedMs: result.elapsedMs,
623
+ warnings: result.warnings,
624
+ }),
625
+ });
626
+ config = reportResult.config;
627
+ client = reportResult.client;
628
+ if (reportResult.registration)
629
+ registration = reportResult.registration;
630
+ }
562
631
  }
563
632
  catch (err) {
633
+ if (cronInternalRun && err instanceof client_js_2.CloudRequestError && err.status === 401) {
634
+ await printSubscribeConnectRequired(options, cronRunSendsToOpenClaw);
635
+ process.exitCode = 1;
636
+ return;
637
+ }
564
638
  console.error(`! Failed to report self-check for ${advisory.id}: ${err.message}`);
565
639
  processed = false;
566
640
  hardFailures += 1;
@@ -611,6 +685,13 @@ async function main() {
611
685
  backend: cronTarget,
612
686
  agentHost: resolveCronAgentHost(config),
613
687
  agentGuardHome: (0, config_js_1.getAgentGuardPaths)().home,
688
+ }, {
689
+ gateway: resolveOpenClawGatewayOptionsFromEnv(),
690
+ });
691
+ (0, config_js_1.saveConfig)({
692
+ ...config,
693
+ threatFeedCronName: summary.cron.result.name,
694
+ threatFeedCronInstalledAt: new Date().toISOString(),
614
695
  });
615
696
  summary.cron.installed = true;
616
697
  }
@@ -663,8 +744,8 @@ async function main() {
663
744
  if (!quiet && fresh.length > 0) {
664
745
  console.log(summary.notification?.body ?? formatNewAdvisoryNotification(fresh));
665
746
  }
666
- else if (quiet && fresh.length > 0) {
667
- console.log(`Self-check found ${totalMatches} match(es) across the new advisories.`);
747
+ else if (quiet && (fresh.length > 0 || summary.cron.result)) {
748
+ console.log(`Self-check found ${totalMatches} match(es) across ${fresh.length} new advisory record(s).`);
668
749
  for (const r of results) {
669
750
  if (r.matchedArtifacts.length === 0)
670
751
  continue;
@@ -844,6 +925,85 @@ function printInitGuidanceIfNeeded(config) {
844
925
  console.log('Required next step:');
845
926
  console.log(` ${REQUIRED_INIT_COMMAND}`);
846
927
  }
928
+ function printCloudAuthStatus(config) {
929
+ if (config.agentJwt) {
930
+ console.log('Cloud auth: connected via Agent JWT');
931
+ console.log('API key: not used for this connection');
932
+ console.log(`Agent ID: ${config.agentId || 'configured'}`);
933
+ console.log('Agent JWT: configured');
934
+ if (config.agentRegisterUrl) {
935
+ console.log('Agent account: not bound (activation required)');
936
+ console.log(`Agent activation URL: ${config.agentRegisterUrl}`);
937
+ }
938
+ else {
939
+ console.log('Agent account: bound');
940
+ console.log('Agent activation URL: not required');
941
+ }
942
+ return;
943
+ }
944
+ if (config.apiKey) {
945
+ console.log('Cloud auth: connected via API key');
946
+ console.log(`API key: ${(0, config_js_1.maskApiKey)(config.apiKey)}`);
947
+ console.log('Agent JWT: not used for this connection');
948
+ return;
949
+ }
950
+ console.log('Cloud auth: not connected');
951
+ console.log('API key: not configured');
952
+ console.log('Agent JWT: not configured');
953
+ }
954
+ async function printSubscribeConnectRequired(options, notifyOpenClaw) {
955
+ const message = 'AgentGuard Cloud credential was rejected. Run `agentguard connect` again before the next subscribe cron run.';
956
+ if (notifyOpenClaw) {
957
+ const notification = await (0, openclaw_notify_js_1.notifyOpenClawMessage)(message, resolveOpenClawGatewayOptionsFromEnv(), {
958
+ idempotencyKeyPrefix: 'agentguard-subscribe-auth',
959
+ });
960
+ if (notification.notified) {
961
+ console.log('NO_REPLY');
962
+ return;
963
+ }
964
+ console.error(`! Could not send OpenClaw cron auth notification: ${notification.reason ?? 'Unknown error'}`);
965
+ return;
966
+ }
967
+ if (options.cronNotifyRun) {
968
+ console.log(message);
969
+ }
970
+ else if (options.json) {
971
+ console.log(JSON.stringify({ success: false, error: message }, null, 2));
972
+ }
973
+ else {
974
+ console.error(`! ${message}`);
975
+ }
976
+ }
977
+ async function refreshAgentAccountBinding(config) {
978
+ if (!config.agentJwt || !config.agentRegisterUrl)
979
+ return config;
980
+ const client = new client_js_1.AgentGuardCloudClient(config);
981
+ try {
982
+ const policy = await client.fetchEffectivePolicy();
983
+ const activeConfig = (0, config_js_1.clearAgentRegisterUrl)(config);
984
+ (0, policy_js_1.saveCachedPolicy)(activeConfig.policyCachePath, policy);
985
+ return activeConfig;
986
+ }
987
+ catch {
988
+ return config;
989
+ }
990
+ }
991
+ function printCronRemovalSummary(results) {
992
+ const removed = results.filter((result) => result.removed);
993
+ if (removed.length > 0) {
994
+ console.log(`Removed AgentGuard subscribe cron job "${removed[0].name}" from: ${removed.map((result) => result.backend).join(', ')}.`);
995
+ return;
996
+ }
997
+ const errors = results.filter((result) => result.error);
998
+ if (errors.length > 0) {
999
+ console.log('No AgentGuard subscribe cron job was removed; some cron backends were unavailable.');
1000
+ for (const result of errors) {
1001
+ console.error(`! ${result.backend}: ${result.error}`);
1002
+ }
1003
+ return;
1004
+ }
1005
+ console.log('No AgentGuard subscribe cron job was found.');
1006
+ }
847
1007
  function resolveCronAgentHost(config) {
848
1008
  return config.agentHost ?? config.agentHosts?.[0];
849
1009
  }
@@ -1200,16 +1360,37 @@ function printAgentActivationRequired(registration, err) {
1200
1360
  console.error(`! AgentGuard Cloud authorization is not active yet. ${message}`);
1201
1361
  const registerUrl = registration?.registerUrl || (0, config_js_1.ensureConfig)().agentRegisterUrl;
1202
1362
  if (registerUrl) {
1203
- console.error('Open this link to bind this agent to your email, then rerun the command:');
1363
+ console.error('Open this link to bind this agent to your account, then rerun the command:');
1204
1364
  console.error(registerUrl);
1205
1365
  }
1206
1366
  }
1207
1367
  function isOpenClawAgentConfigured(config) {
1208
- return config.agentHost === 'openclaw' || config.agentHosts?.includes('openclaw') === true;
1368
+ return config.agentHost === 'openclaw' || config.agentHosts?.includes('openclaw') === true || detectOpenClawRuntime();
1369
+ }
1370
+ function withDetectedOpenClawAgentHost(config) {
1371
+ if (hasSavedAgentHost(config) || !detectOpenClawRuntime())
1372
+ return config;
1373
+ const next = {
1374
+ ...config,
1375
+ agentHost: 'openclaw',
1376
+ agentHosts: appendAgentHost(config.agentHosts, 'openclaw'),
1377
+ };
1378
+ (0, config_js_1.saveConfig)(next);
1379
+ return next;
1380
+ }
1381
+ function detectOpenClawRuntime() {
1382
+ const configPath = process.env.OPENCLAW_CONFIG_PATH?.trim();
1383
+ if (configPath && (0, node_fs_1.existsSync)(configPath))
1384
+ return true;
1385
+ const stateDir = process.env.OPENCLAW_STATE_DIR?.trim();
1386
+ if (stateDir && ((0, node_fs_1.existsSync)(stateDir) || (0, node_fs_1.existsSync)((0, node_path_1.join)(stateDir, 'openclaw.json'))))
1387
+ return true;
1388
+ return (0, node_fs_1.existsSync)((0, node_path_1.join)((0, node_os_1.homedir)(), '.openclaw', 'openclaw.json'));
1209
1389
  }
1210
1390
  function resolveOpenClawGatewayOptionsFromEnv() {
1211
1391
  const url = process.env.AGENTGUARD_OPENCLAW_GATEWAY_URL?.trim();
1212
1392
  const host = process.env.AGENTGUARD_OPENCLAW_GATEWAY_HOST?.trim();
1393
+ const token = process.env.AGENTGUARD_OPENCLAW_GATEWAY_TOKEN?.trim();
1213
1394
  const portRaw = process.env.AGENTGUARD_OPENCLAW_GATEWAY_PORT?.trim();
1214
1395
  const timeoutRaw = process.env.AGENTGUARD_OPENCLAW_GATEWAY_TIMEOUT_MS?.trim();
1215
1396
  const port = portRaw ? Number(portRaw) : undefined;
@@ -1217,6 +1398,7 @@ function resolveOpenClawGatewayOptionsFromEnv() {
1217
1398
  return {
1218
1399
  ...(url ? { url } : {}),
1219
1400
  ...(host ? { host } : {}),
1401
+ ...(token ? { token } : {}),
1220
1402
  ...(Number.isFinite(port) ? { port } : {}),
1221
1403
  ...(Number.isFinite(timeoutMs) ? { timeoutMs } : {}),
1222
1404
  };