@webpresso/agent-kit 0.21.5 → 0.24.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.
Files changed (132) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +87 -124
  4. package/bin/_run.js +143 -1
  5. package/bin/runtime-manifest.json +40 -0
  6. package/catalog/AGENTS.md.tpl +7 -6
  7. package/catalog/agent/commands/plan-refine.md +3 -3
  8. package/catalog/agent/commands/pll.md +2 -0
  9. package/catalog/agent/guides/parallel-execution.md +2 -0
  10. package/catalog/agent/rules/extraction-parity.md +27 -1
  11. package/catalog/agent/rules/public-package-safety.md +24 -1
  12. package/catalog/agent/skills/pll/SKILL.md +1 -0
  13. package/catalog/base-kit/.github/workflows/ci.webpresso.yml.tmpl +33 -0
  14. package/catalog/base-kit/stryker.config.ts.tmpl +2 -2
  15. package/catalog/docs/templates/blueprint.md +1 -0
  16. package/catalog/docs/templates/blueprint.yaml +10 -12
  17. package/commands/blueprint.md +8 -43
  18. package/dist/esm/audit/blueprint-db-consistency.d.ts +1 -1
  19. package/dist/esm/audit/blueprint-db-consistency.js +6 -8
  20. package/dist/esm/audit/blueprint-lifecycle-sql.js +10 -3
  21. package/dist/esm/audit/cloudflare-deploy-contract.d.ts +3 -0
  22. package/dist/esm/audit/cloudflare-deploy-contract.js +80 -0
  23. package/dist/esm/audit/no-legacy-cli-bin.d.ts +3 -0
  24. package/dist/esm/audit/no-legacy-cli-bin.js +100 -0
  25. package/dist/esm/audit/package-surface.js +14 -1
  26. package/dist/esm/audit/repo-guardrails.js +40 -13
  27. package/dist/esm/audit/roadmap-links.js +23 -10
  28. package/dist/esm/blueprint/core/schema.d.ts +8 -8
  29. package/dist/esm/blueprint/core/schema.js +2 -2
  30. package/dist/esm/blueprint/db/enums.d.ts +1 -1
  31. package/dist/esm/blueprint/db/ingester.js +18 -10
  32. package/dist/esm/blueprint/lifecycle/audit.js +9 -2
  33. package/dist/esm/blueprint/lifecycle/local.js +15 -4
  34. package/dist/esm/blueprint/service/BlueprintCreationService.js +11 -6
  35. package/dist/esm/blueprint/service/BlueprintService.js +37 -19
  36. package/dist/esm/blueprint/service/scanner.js +73 -9
  37. package/dist/esm/blueprint/tracked-document/schema.d.ts +2 -2
  38. package/dist/esm/blueprint/utils/document-paths.d.ts +23 -0
  39. package/dist/esm/blueprint/utils/document-paths.js +91 -0
  40. package/dist/esm/build/package-manifest.js +7 -0
  41. package/dist/esm/build/release-policy.d.ts +27 -0
  42. package/dist/esm/build/release-policy.js +29 -0
  43. package/dist/esm/build/runtime-targets.d.ts +13 -0
  44. package/dist/esm/build/runtime-targets.js +48 -0
  45. package/dist/esm/cli/auto-update/detect-pm.d.ts +15 -0
  46. package/dist/esm/cli/auto-update/detect-pm.js +24 -9
  47. package/dist/esm/cli/auto-update/skip.js +9 -1
  48. package/dist/esm/cli/bundle/agent-command-inventory.d.ts +120 -0
  49. package/dist/esm/cli/bundle/agent-command-inventory.js +100 -0
  50. package/dist/esm/cli/bundle/index.d.ts +17 -0
  51. package/dist/esm/cli/bundle/index.js +15 -0
  52. package/dist/esm/cli/cli.d.ts +1 -1
  53. package/dist/esm/cli/cli.js +49 -5
  54. package/dist/esm/cli/commands/audit-core.d.ts +1 -1
  55. package/dist/esm/cli/commands/audit.js +2 -0
  56. package/dist/esm/cli/commands/blueprint/router.js +11 -8
  57. package/dist/esm/cli/commands/hook.d.ts +8 -0
  58. package/dist/esm/cli/commands/hook.js +47 -0
  59. package/dist/esm/cli/commands/init/index.js +35 -1
  60. package/dist/esm/cli/commands/init/scaffold-base-kit.js +1 -1
  61. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/codex-ownership.js +9 -1
  62. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/index.js +130 -20
  63. package/dist/esm/cli/commands/init/scaffolders/agent-kit-global/index.d.ts +65 -0
  64. package/dist/esm/cli/commands/init/scaffolders/agent-kit-global/index.js +64 -0
  65. package/dist/esm/cli/commands/package-manager.d.ts +15 -0
  66. package/dist/esm/cli/commands/package-manager.js +42 -0
  67. package/dist/esm/cli/commands/test.d.ts +1 -0
  68. package/dist/esm/cli/commands/test.js +2 -1
  69. package/dist/esm/cli/commands/typecheck.js +5 -20
  70. package/dist/esm/cli/package-scripts.d.ts +12 -0
  71. package/dist/esm/cli/package-scripts.js +59 -0
  72. package/dist/esm/cli/utils.js +3 -22
  73. package/dist/esm/cli/wp-extensions.d.ts +14 -0
  74. package/dist/esm/cli/wp-extensions.js +34 -0
  75. package/dist/esm/config/docs-lint/schemas/common.d.ts +1 -1
  76. package/dist/esm/config/docs-lint/schemas/implementation-plan.d.ts +2 -2
  77. package/dist/esm/config/docs-lint/schemas/parent-roadmap.d.ts +1 -1
  78. package/dist/esm/config/stryker/index.d.ts +85 -0
  79. package/dist/esm/config/stryker/index.js +31 -0
  80. package/dist/esm/e2e/command-builder.js +11 -2
  81. package/dist/esm/e2e/config.d.ts +65 -0
  82. package/dist/esm/e2e/config.js +126 -0
  83. package/dist/esm/e2e/execution.js +4 -0
  84. package/dist/esm/e2e/load-host-adapter.d.ts +6 -1
  85. package/dist/esm/e2e/load-host-adapter.js +27 -9
  86. package/dist/esm/e2e/run-planner.js +1 -0
  87. package/dist/esm/e2e/types.d.ts +2 -0
  88. package/dist/esm/format/index.js +1 -3
  89. package/dist/esm/hooks/guard-switch/index.d.ts +1 -1
  90. package/dist/esm/hooks/guard-switch/index.js +22 -14
  91. package/dist/esm/hooks/post-tool/lint-after-edit.d.ts +1 -0
  92. package/dist/esm/hooks/post-tool/lint-after-edit.js +5 -2
  93. package/dist/esm/hooks/pretool-guard/validators/file-conventions.js +1 -1
  94. package/dist/esm/hooks/pretool-guard/validators/forbidden-commands.d.ts +6 -0
  95. package/dist/esm/hooks/pretool-guard/validators/forbidden-commands.js +27 -2
  96. package/dist/esm/hooks/pretool-guard/validators/path-contract.d.ts +2 -1
  97. package/dist/esm/hooks/pretool-guard/validators/path-contract.js +59 -34
  98. package/dist/esm/hooks/pretool-guard/validators/plan-frontmatter.js +3 -3
  99. package/dist/esm/hooks/shared/routing-block.js +18 -4
  100. package/dist/esm/hooks/shared/validators/blueprint.js +3 -0
  101. package/dist/esm/hooks/stop/qa-changed-files.d.ts +1 -0
  102. package/dist/esm/hooks/stop/qa-changed-files.js +5 -2
  103. package/dist/esm/lint/index.js +1 -1
  104. package/dist/esm/mcp/auto-discover.d.ts +2 -0
  105. package/dist/esm/mcp/auto-discover.js +14 -6
  106. package/dist/esm/mcp/blueprint-server.js +30 -26
  107. package/dist/esm/mcp/cli.js +21 -0
  108. package/dist/esm/mcp/runners/test.js +15 -0
  109. package/dist/esm/mcp/server.d.ts +7 -0
  110. package/dist/esm/mcp/server.js +16 -27
  111. package/dist/esm/mcp/tools/_registry.d.ts +3 -0
  112. package/dist/esm/mcp/tools/_registry.js +21 -0
  113. package/dist/esm/mcp/tools/audit.d.ts +1 -0
  114. package/dist/esm/mcp/tools/audit.js +11 -0
  115. package/dist/esm/mcp/tools/e2e.d.ts +1 -1
  116. package/dist/esm/mcp/tools/typecheck.js +4 -2
  117. package/dist/esm/mutation/affected.d.ts +9 -0
  118. package/dist/esm/mutation/affected.js +36 -0
  119. package/dist/esm/package.json +5 -0
  120. package/dist/esm/runtime/package-version.d.ts +2 -0
  121. package/dist/esm/runtime/package-version.js +43 -0
  122. package/dist/esm/test/command-builder.d.ts +3 -0
  123. package/dist/esm/test/command-builder.js +22 -3
  124. package/dist/esm/tool-runtime/index.d.ts +2 -2
  125. package/dist/esm/tool-runtime/index.js +2 -1
  126. package/dist/esm/tool-runtime/resolve-runner.d.ts +3 -0
  127. package/dist/esm/tool-runtime/resolve-runner.js +7 -5
  128. package/dist/esm/typecheck/index.js +4 -2
  129. package/dist/esm/wp-extension/index.d.ts +50 -0
  130. package/dist/esm/wp-extension/index.js +268 -0
  131. package/package.json +67 -31
  132. package/skills/pll/SKILL.md +1 -0
@@ -11,6 +11,7 @@ import { resolve as pathResolve } from 'node:path';
11
11
  import { fileURLToPath } from 'node:url';
12
12
  import { bootstrapAk } from './bootstrap.js';
13
13
  import { formatUnknownCommandError, normalizeArgv, readPackageVersion } from './utils.js';
14
+ import { registerWpExtensions, resolveWpCommandAlias } from './wp-extensions.js';
14
15
  const VERSION = readPackageVersion(import.meta.url);
15
16
  const SUPPORTED_COMMANDS = [
16
17
  'blueprint',
@@ -37,9 +38,16 @@ const SUPPORTED_COMMANDS = [
37
38
  'tech-debt',
38
39
  'worktree',
39
40
  'mcp',
41
+ 'hook',
40
42
  'hooks',
41
43
  'gain',
42
44
  'bench',
45
+ 'install',
46
+ 'add',
47
+ 'remove',
48
+ 'update',
49
+ 'exec',
50
+ 'run',
43
51
  ];
44
52
  const ROOT_HELP = [
45
53
  'Usage: wp [command] [options]',
@@ -52,6 +60,12 @@ const ROOT_HELP = [
52
60
  ' gain Show token savings from RTK — run after any AI session',
53
61
  ' sync Sync agent rules + skills across IDE surfaces (--kind, --check)',
54
62
  ' bench Run the session-memory benchmark harness',
63
+ ' install Install dependencies through the managed vp facade',
64
+ ' add Add dependencies through the managed vp facade',
65
+ ' remove Remove dependencies through the managed vp facade',
66
+ ' update Update dependencies through the managed vp facade',
67
+ ' exec Run a binary through the managed vp facade',
68
+ ' run Run a package script through the managed vp facade',
55
69
  '',
56
70
  'Quality:',
57
71
  ' audit Run packaged audits (bundle budgets, repo guardrails, TPH, tech-debt)',
@@ -123,7 +137,17 @@ export async function main() {
123
137
  return 0;
124
138
  }
125
139
  await bootstrapAk(VERSION, argv);
126
- switch (command) {
140
+ const extensionRuntime = await registerWpExtensions({
141
+ cli,
142
+ cwd: process.cwd(),
143
+ env: process.env,
144
+ hostVersion: VERSION,
145
+ baseCommands: [...SUPPORTED_COMMANDS],
146
+ });
147
+ for (const warning of extensionRuntime.warnings)
148
+ console.error(warning);
149
+ const resolvedCommand = resolveWpCommandAlias(command, extensionRuntime.aliasMap);
150
+ switch (resolvedCommand) {
127
151
  case 'blueprint': {
128
152
  const { registerBlueprintRouter } = await import('./commands/blueprint/router.js');
129
153
  registerBlueprintRouter(cli);
@@ -177,7 +201,7 @@ export async function main() {
177
201
  case 'setup':
178
202
  case 'init': {
179
203
  const { registerInitCommand } = await import('./commands/init/index.js');
180
- registerInitCommand(cli, command);
204
+ registerInitCommand(cli, resolvedCommand);
181
205
  break;
182
206
  }
183
207
  case 'dev': {
@@ -235,6 +259,11 @@ export async function main() {
235
259
  registerMcpCommand(cli);
236
260
  break;
237
261
  }
262
+ case 'hook': {
263
+ const { registerHookCommand } = await import('./commands/hook.js');
264
+ registerHookCommand(cli);
265
+ break;
266
+ }
238
267
  case 'hooks': {
239
268
  const { registerHooksCommand } = await import('./commands/hooks.js');
240
269
  registerHooksCommand(cli);
@@ -250,20 +279,35 @@ export async function main() {
250
279
  registerBenchCommand(cli);
251
280
  break;
252
281
  }
282
+ case 'install':
283
+ case 'add':
284
+ case 'remove':
285
+ case 'update':
286
+ case 'exec':
287
+ case 'run': {
288
+ const { registerPackageManagerCommand } = await import('./commands/package-manager.js');
289
+ registerPackageManagerCommand(cli, resolvedCommand);
290
+ break;
291
+ }
253
292
  case 'worktree': {
254
293
  const { registerWorktreeRouter } = await import('./commands/worktree/router.js');
255
294
  registerWorktreeRouter(cli);
256
295
  break;
257
296
  }
258
297
  default: {
259
- console.error(formatUnknownCommandError(command, SUPPORTED_COMMANDS));
260
- return 1;
298
+ if (!resolvedCommand || !extensionRuntime.commandNames.includes(resolvedCommand)) {
299
+ console.error(formatUnknownCommandError(command, SUPPORTED_COMMANDS));
300
+ return 1;
301
+ }
261
302
  }
262
303
  }
263
304
  cli.help();
264
305
  cli.version(VERSION);
265
306
  try {
266
- cli.parse(argv, { run: false });
307
+ const effectiveArgv = resolvedCommand && resolvedCommand !== command
308
+ ? [argv[0] ?? 'node', argv[1] ?? 'wp', resolvedCommand, ...argv.slice(3)]
309
+ : argv;
310
+ cli.parse(effectiveArgv, { run: false });
267
311
  const result = await cli.runMatchedCommand();
268
312
  return typeof result === 'number' ? result : 0;
269
313
  }
@@ -1,5 +1,5 @@
1
1
  import type { RepoAuditResult } from '#audit/repo-guardrails';
2
- export type AuditKind = 'tph' | 'tph-e2e' | 'bundle-budget' | 'commit-message' | 'blueprint-lifecycle' | 'roadmap-links' | 'docs-frontmatter' | 'catalog-drift' | 'package-surface' | 'agents' | 'tech-debt' | 'no-relative-parent-imports' | 'no-link-protocol' | 'vision' | 'bucket-boundary' | 'skill-sizes' | 'broken-refs' | 'memory-rotation' | 'gitignore-agent-surfaces' | 'memory-unified' | 'compile-drift' | 'architecture-drift' | 'absolute-path-policy' | 'agent-cost' | 'blueprint-db-consistency' | 'blueprint-lifecycle-sql' | 'tech-debt-cadence' | 'cross-repo-correlation' | 'ai-contracts' | 'mutation' | 'quality' | 'guardrails' | 'hook-surface' | 'no-relative-package-scripts';
2
+ export type AuditKind = 'tph' | 'tph-e2e' | 'bundle-budget' | 'commit-message' | 'blueprint-lifecycle' | 'roadmap-links' | 'docs-frontmatter' | 'catalog-drift' | 'package-surface' | 'agents' | 'tech-debt' | 'no-relative-parent-imports' | 'no-link-protocol' | 'vision' | 'bucket-boundary' | 'skill-sizes' | 'broken-refs' | 'memory-rotation' | 'gitignore-agent-surfaces' | 'memory-unified' | 'compile-drift' | 'architecture-drift' | 'cloudflare-deploy-contract' | 'absolute-path-policy' | 'agent-cost' | 'blueprint-db-consistency' | 'blueprint-lifecycle-sql' | 'tech-debt-cadence' | 'cross-repo-correlation' | 'ai-contracts' | 'mutation' | 'quality' | 'guardrails' | 'hook-surface' | 'no-relative-package-scripts';
3
3
  export type AuditOutcome = {
4
4
  kind: 'invalid-usage';
5
5
  message: string;
@@ -56,7 +56,9 @@ const REPO_AUDIT_REGISTRY = {
56
56
  'gitignore-agent-surfaces': async (root) => (await import('#audit/gitignore-agent-surfaces')).auditGitignoreAgentSurfaces(root),
57
57
  'memory-unified': async (root) => (await import('#audit/memory-unified')).auditMemoryUnified(root),
58
58
  'compile-drift': async (root) => (await import('#audit/compile-drift')).auditCompileDrift(root),
59
+ 'no-legacy-cli-bin': async (root) => (await import('#audit/no-legacy-cli-bin')).auditNoLegacyCliBin(root),
59
60
  'architecture-drift': async (root) => (await import('#audit/architecture-drift')).auditArchitectureDrift(root),
61
+ 'cloudflare-deploy-contract': async (root) => (await import('#audit/cloudflare-deploy-contract')).auditCloudflareDeployContract(root),
60
62
  'absolute-path-policy': async (root) => (await import('#audit/absolute-path-policy')).auditAbsolutePathPolicy(root),
61
63
  'agent-cost': async (root) => (await import('#audit/agent-cost')).auditAgentCost(root),
62
64
  'blueprint-db-consistency': async (root) => (await import('#audit/blueprint-db-consistency')).auditBlueprintDbConsistency(root),
@@ -5,6 +5,7 @@ import { parseBlueprintForDb } from '#db/parser/blueprint-db-parser';
5
5
  import { blueprintToSpecKit } from '#export/spec-kit/index';
6
6
  import { getProjectRoot } from '#cli/utils';
7
7
  import { resolveBlueprintRoot } from '#utils/blueprint-root';
8
+ import { getBlueprintDocumentPaths } from '#utils/document-paths.js';
8
9
  import { applyBlueprintLifecycleToFile, BlueprintCreationService, BlueprintService, complexitySchema, relativeBlueprintSlug, parseBlueprint, planStatusSchema, runBlueprintAudit, resolveBlueprintFile, serializeBlueprint, validateAllTasksDone, } from '#local';
9
10
  import { resolvePackageAssetPreferred } from '#utils/package-assets';
10
11
  import { describeBlueprintExecutionRuntime, buildBlueprintLaunchSpec, buildStoppedRuntimeEvidence, controlBlueprintExecution, initializeBlueprintExecutionProgressBridge, launchBlueprintExecution, persistBlueprintExecutionArtifacts, persistBlueprintExecutionMetadata, recordLaunchFailure, reconcileBlueprintRuntimeSnapshot, readBlueprintExecutionState, syncBlueprintExecutionProgress, writeBlueprintRuntimeSnapshot, } from './execution.js';
@@ -309,10 +310,12 @@ export async function moveBlueprint(slug, status, options = {}) {
309
310
  const projectRoot = resolveProjectRoot(options.projectRoot);
310
311
  const nextStatus = normalizeBlueprintStatus(status);
311
312
  const location = await resolveBlueprintLocation(slug, projectRoot);
313
+ const isFlatFile = path.basename(location.path) !== '_overview.md';
312
314
  const sourceDir = path.dirname(location.path);
313
- const targetDir = path.join(resolveBlueprintRoot(projectRoot), nextStatus, relativeBlueprintSlug(location.slug));
314
- const targetPath = path.join(targetDir, '_overview.md');
315
- if (sourceDir === targetDir && location.blueprint.status === nextStatus) {
315
+ const targetPaths = getBlueprintDocumentPaths(resolveBlueprintRoot(projectRoot), nextStatus, relativeBlueprintSlug(location.slug));
316
+ const targetDir = targetPaths.directory;
317
+ const targetPath = isFlatFile ? targetPaths.flat : targetPaths.folder;
318
+ if (location.path === targetPath && location.blueprint.status === nextStatus) {
316
319
  return {
317
320
  fromPath: location.path,
318
321
  fromStatus: location.blueprint.status,
@@ -328,18 +331,18 @@ export async function moveBlueprint(slug, status, options = {}) {
328
331
  throw new Error('Blueprint move is recovery-only. Use wp blueprint start/task/finalize for normal lifecycle changes, or pass --force-recovery.');
329
332
  }
330
333
  assertBlueprintCanMoveToStatus(location.blueprint, nextStatus);
331
- if (sourceDir !== targetDir) {
332
- await mkdir(path.dirname(targetDir), { recursive: true });
333
- await rename(sourceDir, targetDir);
334
+ if (location.path !== targetPath) {
335
+ await mkdir(path.dirname(targetPath), { recursive: true });
336
+ await rename(isFlatFile ? location.path : sourceDir, isFlatFile ? targetPath : targetDir);
334
337
  }
335
338
  const updated = await writeBlueprintWithStatus(targetPath, location.blueprint, nextStatus);
336
339
  return {
337
340
  fromPath: location.path,
338
341
  fromStatus: location.blueprint.status,
339
- message: sourceDir === targetDir
342
+ message: location.path === targetPath
340
343
  ? `Updated blueprint ${location.slug} to ${nextStatus}.`
341
344
  : `Moved blueprint ${location.slug} to ${nextStatus}.`,
342
- moved: sourceDir !== targetDir,
345
+ moved: location.path !== targetPath,
343
346
  slug: location.slug,
344
347
  toPath: targetPath,
345
348
  toStatus: nextStatus,
@@ -0,0 +1,8 @@
1
+ import type { CAC } from 'cac';
2
+ declare const HOOK_NAMES: readonly ["pretool-guard", "post-tool", "stop-qa", "guard-switch", "sessionstart-routing"];
3
+ export type HookName = (typeof HOOK_NAMES)[number];
4
+ export declare function isHookName(value: string): value is HookName;
5
+ export declare function runHookCommand(name: string): Promise<void>;
6
+ export declare function registerHookCommand(cli: CAC): void;
7
+ export {};
8
+ //# sourceMappingURL=hook.d.ts.map
@@ -0,0 +1,47 @@
1
+ const HOOK_NAMES = [
2
+ 'pretool-guard',
3
+ 'post-tool',
4
+ 'stop-qa',
5
+ 'guard-switch',
6
+ 'sessionstart-routing',
7
+ ];
8
+ const HOOK_HANDLERS = {
9
+ 'pretool-guard': async () => {
10
+ const { main } = await import('#hooks/pretool-guard/index');
11
+ await main();
12
+ },
13
+ 'post-tool': async () => {
14
+ const { main } = await import('#hooks/post-tool/lint-after-edit');
15
+ await main();
16
+ },
17
+ 'stop-qa': async () => {
18
+ const { main } = await import('#hooks/stop/qa-changed-files');
19
+ await main();
20
+ },
21
+ 'guard-switch': async () => {
22
+ const { main } = await import('#hooks/guard-switch/index');
23
+ await main();
24
+ },
25
+ 'sessionstart-routing': async () => {
26
+ const { main } = await import('#hooks/sessionstart/index');
27
+ await main();
28
+ },
29
+ };
30
+ export function isHookName(value) {
31
+ return value in HOOK_HANDLERS;
32
+ }
33
+ export async function runHookCommand(name) {
34
+ if (!isHookName(name)) {
35
+ throw new Error(`Unknown hook "${name}". Expected one of: ${HOOK_NAMES.join(', ')}`);
36
+ }
37
+ await HOOK_HANDLERS[name]();
38
+ }
39
+ export function registerHookCommand(cli) {
40
+ cli
41
+ .command('hook <name>', 'Run an internal plugin hook entrypoint')
42
+ .action(async (name) => {
43
+ await runHookCommand(name);
44
+ return 0;
45
+ });
46
+ }
47
+ //# sourceMappingURL=hook.js.map
@@ -30,6 +30,7 @@ import { BASE_KIT_QUALITY_TARGETS, collectRuntimeContractGuidance, scaffoldBaseK
30
30
  import { scaffoldMonorepoNav } from './scaffold-monorepo-nav.js';
31
31
  import { REQUIRED_CORE_CAPABILITIES, auditHostSkillVisibility, parseAgentHosts, serializeHostVisibility, summarizeHostVisibility, } from './host-visibility.js';
32
32
  import { scaffoldAgentHooks, trustCodexWebpressoHooksForRepo, trustCodexPresetHooksForUser, } from './scaffolders/agent-hooks/index.js';
33
+ import { ensureAgentKitGlobal } from './scaffolders/agent-kit-global/index.js';
33
34
  import { scaffoldAuditHooks } from './scaffolders/audit-hooks/index.js';
34
35
  import { ensureClaudeCodeUserPlugin } from './scaffolders/claude-plugin/index.js';
35
36
  import { scaffoldClaudeRules } from './scaffolders/claude-rules/index.js';
@@ -495,6 +496,37 @@ export async function runInit(flags) {
495
496
  console.log(` codex webpresso mcp: ⚠ no install root found (checked ${webpressoMcpResult.checked.length} paths). Install webpresso globally (\`bun add -g webpresso\`) or via the Claude plugin to wire up codex MCP.`);
496
497
  break;
497
498
  }
499
+ // Self-update the ONE globally-distributed agent-kit binary (PATH `wp`,
500
+ // plugin MCP, hooks all resolve to it), mirroring omx/omc/codex/claude.
501
+ // Non-fatal: a failed refresh never fails consumer setup, and it skips
502
+ // cleanly on a source/git clone, on `WP_SKIP_AUTO_INSTALL=1`, and in CI.
503
+ if (isCiEnvironment) {
504
+ console.log(' agent-kit global: - skipped (CI environment)');
505
+ }
506
+ else {
507
+ const agentKitGlobalResult = ensureAgentKitGlobal({ options });
508
+ switch (agentKitGlobalResult.kind) {
509
+ case 'agent-kit-global-updated':
510
+ console.log(' agent-kit global: ✓ refreshed via vp install -g');
511
+ break;
512
+ case 'agent-kit-global-skipped-dry-run':
513
+ console.log(' agent-kit global: skipped (--dry-run)');
514
+ break;
515
+ case 'agent-kit-global-skipped-opt-out':
516
+ console.log(' agent-kit global: skipped (WP_SKIP_AUTO_INSTALL=1)');
517
+ break;
518
+ case 'agent-kit-global-skipped-source-clone':
519
+ console.log(` agent-kit global: - skipped (running from source clone ${agentKitGlobalResult.repoRoot})`);
520
+ break;
521
+ case 'agent-kit-global-skipped-no-vp':
522
+ console.warn(` agent-kit global: ⚠ ${agentKitGlobalResult.hint}`);
523
+ break;
524
+ case 'agent-kit-global-failed':
525
+ console.warn(` agent-kit global: ⚠ \`${agentKitGlobalResult.command.join(' ')}\` exited with ${agentKitGlobalResult.exitCode}; ` +
526
+ 'the existing global binary is unchanged. Re-run `wp setup` once the registry is reachable.');
527
+ break;
528
+ }
529
+ }
498
530
  const claudePluginResult = ensureClaudeCodeUserPlugin({
499
531
  options,
500
532
  packageRoot,
@@ -697,7 +729,9 @@ export async function runInit(flags) {
697
729
  }
698
730
  }
699
731
  }
700
- printRuntimeContractGuidance(options.dryRun ? consumer.packageJson : readPackageJsonSafe(consumer.repoRoot) ?? consumer.packageJson);
732
+ printRuntimeContractGuidance(options.dryRun
733
+ ? consumer.packageJson
734
+ : (readPackageJsonSafe(consumer.repoRoot) ?? consumer.packageJson));
701
735
  console.log('\nwp init: setup phases finished.');
702
736
  if (omxFailure === 'not-found')
703
737
  return EXIT_SETUP_FAIL;
@@ -119,7 +119,7 @@ function mergePackageJson(repoRoot, options, globalInstall = false) {
119
119
  const hasTestMutationScript = typeof scripts['test:mutation'] === 'string';
120
120
  const hasE2eScript = typeof scripts['e2e'] === 'string';
121
121
  const hasQaScript = typeof scripts['qa'] === 'string';
122
- const verifyPathsScript = 'WP_SKIP_UPDATE_CHECK=1 wp audit absolute-path-policy --root .';
122
+ const verifyPathsScript = 'wp audit absolute-path-policy --root .';
123
123
  const verifySecretsScript = 'bun scripts/check-no-dev-vars.ts';
124
124
  const secretQuarantineAuditScript = 'bun scripts/audit-secret-provider-quarantine.ts';
125
125
  const lintScript = 'wp lint src e2e *.config.ts';
@@ -10,6 +10,8 @@ export const KNOWN_WEBPRESSO_CODEX_BINS = [
10
10
  const KNOWN_WEBPRESSO_CODEX_BIN_SET = new Set(KNOWN_WEBPRESSO_CODEX_BINS);
11
11
  const NODE_MODULES_BIN_PATTERN = /^(?:\.\/|\/.*\/)?node_modules\/\.bin\/([\w-]+)$/u;
12
12
  const GUARDED_NODE_MODULES_BIN_PATTERN = /^\[ -x (["']?)((?:\.\/|\/.*\/)?node_modules\/\.bin\/([\w-]+))\1 \] && \1\2\1 \|\| (?:true|printf .+)$/u;
13
+ const MANAGED_LAUNCHER_PATTERN = /^(?:["']?)((?:\.\/|\/.*\/)?\.codex\/managed-hooks\/((?:wp|ak)-[\w-]+)\.sh)(?:["']?)$/u;
14
+ const GUARDED_MANAGED_LAUNCHER_PATTERN = /^\[ -x (["']?)((?:\.\/|\/.*\/)?\.codex\/managed-hooks\/((?:wp|ak)-[\w-]+)\.sh)\1 \] && \1\2\1 \|\| (?:true|printf .+)$/u;
13
15
  export function isWebpressoOwnedCodexHook(metadata, expectedSourcePaths) {
14
16
  if (!isObject(metadata))
15
17
  return false;
@@ -46,8 +48,14 @@ function extractDirectNodeModulesBin(command) {
46
48
  const match = NODE_MODULES_BIN_PATTERN.exec(normalizedCommand);
47
49
  if (match?.[1])
48
50
  return match[1];
51
+ const managedLauncherMatch = MANAGED_LAUNCHER_PATTERN.exec(normalizedCommand);
52
+ if (managedLauncherMatch?.[2])
53
+ return managedLauncherMatch[2];
49
54
  const guardedMatch = GUARDED_NODE_MODULES_BIN_PATTERN.exec(command.trim());
50
- return guardedMatch?.[3] ?? null;
55
+ if (guardedMatch?.[3])
56
+ return guardedMatch[3];
57
+ const guardedManagedLauncherMatch = GUARDED_MANAGED_LAUNCHER_PATTERN.exec(command.trim());
58
+ return guardedManagedLauncherMatch?.[3] ?? null;
51
59
  }
52
60
  function stripSingleShellQuotePair(value) {
53
61
  if (value.length < 2)
@@ -9,9 +9,10 @@
9
9
  *
10
10
  * Runs by default on every `wp setup`.
11
11
  */
12
- import { chmodSync, existsSync, mkdirSync, writeFileSync } from 'node:fs';
12
+ import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
13
13
  import { homedir } from 'node:os';
14
- import { join, resolve } from 'node:path';
14
+ import { dirname, join, resolve } from 'node:path';
15
+ import { fileURLToPath } from 'node:url';
15
16
  import { patchJsonFile } from '#cli/commands/init/merge';
16
17
  import { CodexAppServerClient } from '#codex/app-server/client.js';
17
18
  import { normalizeGlobalCodexHooksFile, resolveBinaryOnPath, } from '#cli/commands/init/scaffolders/agent-hooks/codex-global-normalize';
@@ -28,16 +29,32 @@ import { buildSkillTag, extractSkillHooks, isTaggedSkillHook, } from './skill-ho
28
29
  // bypass when the guard binary is missing/non-executable.
29
30
  const PRETOOL_GUARD_BIN = 'wp-pretool-guard';
30
31
  const PRETOOL_GUARD_MISSING_DENY = `printf '%s\\n' '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"wp-pretool-guard is unavailable. Run vp install or wp setup."}}'`;
32
+ const CLAUDE_MANAGED_HOOK_SUBDIR = '.claude/hooks/managed';
33
+ const CODEX_MANAGED_HOOK_SUBDIR = '.codex/managed-hooks';
34
+ function claudeManagedHookLauncherPath(name) {
35
+ return `$CLAUDE_PROJECT_DIR/${CLAUDE_MANAGED_HOOK_SUBDIR}/${name}.sh`;
36
+ }
37
+ function codexManagedHookLauncherPath(repoRoot, name) {
38
+ return resolve(repoRoot, CODEX_MANAGED_HOOK_SUBDIR, `${name}.sh`);
39
+ }
40
+ function quoteShell(value) {
41
+ return `'${value.replaceAll("'", "'\\''")}'`;
42
+ }
43
+ function quoteHookCommandPath(value) {
44
+ if (value.startsWith('$CLAUDE_PROJECT_DIR/'))
45
+ return `"${value}"`;
46
+ return quoteShell(value);
47
+ }
31
48
  function buildGuardedHookCommand(binPath, name) {
49
+ const quotedBinPath = quoteHookCommandPath(binPath);
32
50
  if (name === PRETOOL_GUARD_BIN) {
33
- return `[ -x "${binPath}" ] && "${binPath}" || ${PRETOOL_GUARD_MISSING_DENY}`;
51
+ return `[ -x ${quotedBinPath} ] && ${quotedBinPath} || ${PRETOOL_GUARD_MISSING_DENY}`;
34
52
  }
35
- return `[ -x "${binPath}" ] && "${binPath}" || true`;
53
+ return `[ -x ${quotedBinPath} ] && ${quotedBinPath} || true`;
36
54
  }
37
- const CC_BIN = (name) => buildGuardedHookCommand(`$CLAUDE_PROJECT_DIR/node_modules/.bin/${name}`, name);
55
+ const CC_BIN = (name) => buildGuardedHookCommand(claudeManagedHookLauncherPath(name), name);
38
56
  const CODEX_BIN = (repoRoot) => (name) => {
39
- const binPath = resolve(repoRoot, 'node_modules', '.bin', name);
40
- return buildGuardedHookCommand(binPath, name);
57
+ return buildGuardedHookCommand(codexManagedHookLauncherPath(repoRoot, name), name);
41
58
  };
42
59
  // Canonical hook event names recognised by both Claude Code and Codex CLI.
43
60
  // Used by `hoistTopLevelEvents` to identify legacy flat-form keys to migrate.
@@ -77,6 +94,8 @@ const DIRECT_NODE_MODULES_BIN_PATTERN = /^(?:\.\/|\/.*\/)?node_modules\/\.bin\/(
77
94
  const GUARDED_NODE_MODULES_BIN_PATTERN = /^\[ -x (["']?)((?:\.\/|\/.*\/)?node_modules\/\.bin\/([\w-]+))\1 \] && \1\2\1 \|\| (?:true|printf .+)$/u;
78
95
  const DIRECT_CLAUDE_NODE_MODULES_BIN_PATTERN = /^["']?\$CLAUDE_PROJECT_DIR\/node_modules\/\.bin\/([\w-]+)["']?$/u;
79
96
  const GUARDED_CLAUDE_NODE_MODULES_BIN_PATTERN = /^\[ -x (["']?)\$CLAUDE_PROJECT_DIR\/node_modules\/\.bin\/([\w-]+)\1 \] && \1\$CLAUDE_PROJECT_DIR\/node_modules\/\.bin\/\2\1 \|\| (?:true|printf .+)$/u;
97
+ const DIRECT_MANAGED_HOOK_LAUNCHER_PATTERN = /^(?:["']?)((?:\$CLAUDE_PROJECT_DIR\/\.claude\/hooks\/managed|(?:\.\/|\/.*\/)?\.claude\/hooks\/managed|(?:\.\/|\/.*\/)?\.codex\/managed-hooks)\/((?:wp|ak)-[\w-]+)\.sh)(?:["']?)$/u;
98
+ const GUARDED_MANAGED_HOOK_LAUNCHER_PATTERN = /^\[ -x (["']?)((?:\$CLAUDE_PROJECT_DIR\/\.claude\/hooks\/managed|(?:\.\/|\/.*\/)?\.claude\/hooks\/managed|(?:\.\/|\/.*\/)?\.codex\/managed-hooks)\/((?:wp|ak)-[\w-]+)\.sh)\1 \] && \1\2\1 \|\| (?:true|printf .+)$/u;
80
99
  // Capture the basename of any path that ends in a known script extension.
81
100
  // Handles trailing chars (quote, space, end-of-string).
82
101
  const SCRIPT_BASENAME_PATTERN = new RegExp(String.raw `([\w-]+\.(?:${SCRIPT_EXTENSIONS.join('|')}))(?=$|["'\s])`, 'u');
@@ -110,9 +129,15 @@ function extractAgentKitCodexBinName(command) {
110
129
  const directBinMatch = DIRECT_NODE_MODULES_BIN_PATTERN.exec(normalizedCommand);
111
130
  if (directBinMatch !== null)
112
131
  return directBinMatch[1] ?? null;
132
+ const directManagedLauncherMatch = DIRECT_MANAGED_HOOK_LAUNCHER_PATTERN.exec(normalizedCommand);
133
+ if (directManagedLauncherMatch !== null)
134
+ return directManagedLauncherMatch[2] ?? null;
113
135
  const guardedBinMatch = GUARDED_NODE_MODULES_BIN_PATTERN.exec(command.trim());
114
136
  if (guardedBinMatch !== null)
115
137
  return guardedBinMatch[3] ?? null;
138
+ const guardedManagedLauncherMatch = GUARDED_MANAGED_HOOK_LAUNCHER_PATTERN.exec(command.trim());
139
+ if (guardedManagedLauncherMatch !== null)
140
+ return guardedManagedLauncherMatch[3] ?? null;
116
141
  return null;
117
142
  }
118
143
  function extractClaudeBinName(command) {
@@ -120,9 +145,15 @@ function extractClaudeBinName(command) {
120
145
  const directBinMatch = DIRECT_CLAUDE_NODE_MODULES_BIN_PATTERN.exec(normalizedCommand);
121
146
  if (directBinMatch !== null)
122
147
  return directBinMatch[1] ?? null;
148
+ const directManagedLauncherMatch = DIRECT_MANAGED_HOOK_LAUNCHER_PATTERN.exec(normalizedCommand);
149
+ if (directManagedLauncherMatch !== null)
150
+ return directManagedLauncherMatch[2] ?? null;
123
151
  const guardedBinMatch = GUARDED_CLAUDE_NODE_MODULES_BIN_PATTERN.exec(command.trim());
124
152
  if (guardedBinMatch !== null)
125
153
  return guardedBinMatch[2] ?? null;
154
+ const guardedManagedLauncherMatch = GUARDED_MANAGED_HOOK_LAUNCHER_PATTERN.exec(command.trim());
155
+ if (guardedManagedLauncherMatch !== null)
156
+ return guardedManagedLauncherMatch[3] ?? null;
126
157
  return null;
127
158
  }
128
159
  function stripSingleShellQuotePair(value) {
@@ -305,20 +336,33 @@ function normalizeCodexAgentKitCommands(hooks, repoRoot) {
305
336
  }
306
337
  return normalized;
307
338
  }
308
- function pruneLegacyClaudeAgentKitCommands(hooks) {
339
+ function normalizeClaudeAgentKitCommands(hooks) {
309
340
  const normalized = {};
310
341
  for (const [event, groups] of Object.entries(hooks)) {
311
- const keptGroups = groups
312
- .map((group) => {
313
- const keptHooks = group.hooks.filter((hook) => {
314
- const classification = classifyWebpressoHookBin(extractClaudeBinName(hook.command));
315
- return classification === null || classification.kind !== 'legacy';
316
- });
317
- return keptHooks.length > 0 ? { ...group, hooks: keptHooks } : null;
318
- })
319
- .filter((group) => group !== null);
320
- if (keptGroups.length > 0)
321
- normalized[event] = keptGroups;
342
+ const normalizedGroups = groups.reduce((dedupedGroups, group) => {
343
+ const nextGroup = {
344
+ ...group,
345
+ hooks: group.hooks.flatMap((hook) => {
346
+ const command = hook.command;
347
+ if (typeof command !== 'string')
348
+ return hook;
349
+ const classification = classifyWebpressoHookBin(extractClaudeBinName(command));
350
+ if (classification === null)
351
+ return hook;
352
+ if (classification.kind === 'legacy')
353
+ return [];
354
+ return {
355
+ ...hook,
356
+ command: CC_BIN(classification.binName),
357
+ };
358
+ }),
359
+ };
360
+ if (nextGroup.hooks.length === 0)
361
+ return dedupedGroups;
362
+ return ensureGroup(dedupedGroups, nextGroup);
363
+ }, []);
364
+ if (normalizedGroups.length > 0)
365
+ normalized[event] = normalizedGroups;
322
366
  }
323
367
  return normalized;
324
368
  }
@@ -380,7 +424,7 @@ function patchClaudeUserSettings(existing) {
380
424
  return next;
381
425
  }
382
426
  function patchClaudeSettings(existing, skillHooks) {
383
- const existingHooks = pruneLegacyClaudeAgentKitCommands((existing.hooks ?? {}));
427
+ const existingHooks = normalizeClaudeAgentKitCommands((existing.hooks ?? {}));
384
428
  const withSkills = mergeSkillHooks(existingHooks, skillHooks);
385
429
  const webpresso = buildWebpressoHookGroups({
386
430
  resolveBin: CC_BIN,
@@ -560,8 +604,74 @@ function ensureGstackHooks(repoRoot, options = {}) {
560
604
  chmodSync(sessionPath, 0o755);
561
605
  }
562
606
  }
607
+ function resolveProjectHookBinPath(repoRoot, binName) {
608
+ return resolve(repoRoot, 'node_modules', '@webpresso', 'agent-kit', 'bin', `${binName}.js`);
609
+ }
610
+ function resolvePackageHookBin(binName) {
611
+ return join(resolvePackageRoot(), 'bin', `${binName}.js`);
612
+ }
613
+ function resolvePackageRoot() {
614
+ let dir = dirname(fileURLToPath(import.meta.url));
615
+ for (let depth = 0; depth < 10; depth++) {
616
+ if (existsSync(join(dir, 'package.json')) && existsSync(join(dir, 'bin', 'wp.js'))) {
617
+ return dir;
618
+ }
619
+ const parent = dirname(dir);
620
+ if (parent === dir)
621
+ break;
622
+ dir = parent;
623
+ }
624
+ throw new Error('wp setup: could not locate @webpresso/agent-kit package root for hook launchers.');
625
+ }
626
+ function renderManagedWebpressoHookLauncher(repoRoot, binName) {
627
+ const nodeBinary = quoteShell(process.execPath);
628
+ const projectBinPath = quoteShell(resolveProjectHookBinPath(repoRoot, binName));
629
+ const fallbackBinPath = quoteShell(resolvePackageHookBin(binName));
630
+ const missingFallback = binName === PRETOOL_GUARD_BIN ? PRETOOL_GUARD_MISSING_DENY : 'exit 0';
631
+ return `#!/bin/sh
632
+ NODE_BINARY=${nodeBinary}
633
+ PROJECT_BIN_PATH=${projectBinPath}
634
+ FALLBACK_BIN_PATH=${fallbackBinPath}
635
+
636
+ if [ ! -x "$NODE_BINARY" ]; then
637
+ ${missingFallback}
638
+ exit 0
639
+ fi
640
+
641
+ if [ -f "$PROJECT_BIN_PATH" ]; then
642
+ exec "$NODE_BINARY" "$PROJECT_BIN_PATH" "$@"
643
+ fi
644
+
645
+ if [ -f "$FALLBACK_BIN_PATH" ]; then
646
+ exec "$NODE_BINARY" "$FALLBACK_BIN_PATH" "$@"
647
+ fi
648
+
649
+ ${missingFallback}
650
+ exit 0
651
+ `;
652
+ }
653
+ function ensureManagedWebpressoHookLaunchers(repoRoot, options = {}) {
654
+ if (options.dryRun)
655
+ return;
656
+ const launcherTargets = [
657
+ join(repoRoot, CLAUDE_MANAGED_HOOK_SUBDIR),
658
+ join(repoRoot, CODEX_MANAGED_HOOK_SUBDIR),
659
+ ];
660
+ for (const directory of launcherTargets) {
661
+ mkdirSync(directory, { recursive: true });
662
+ for (const binName of WEBPRESSO_HOOK_BIN_NAMES) {
663
+ const launcherPath = join(directory, `${binName}.sh`);
664
+ const content = renderManagedWebpressoHookLauncher(repoRoot, binName);
665
+ if (!existsSync(launcherPath) || readFileSync(launcherPath, 'utf8') !== content) {
666
+ writeFileSync(launcherPath, content, 'utf8');
667
+ }
668
+ chmodSync(launcherPath, 0o755);
669
+ }
670
+ }
671
+ }
563
672
  export async function scaffoldAgentHooks(input) {
564
673
  ensureGstackHooks(input.repoRoot, input.options);
674
+ ensureManagedWebpressoHookLaunchers(input.repoRoot, input.options);
565
675
  const skillHooks = extractSkillHooks(join(input.repoRoot, '.agent', 'skills'));
566
676
  const result = {
567
677
  claude: patchJsonFile(join(input.repoRoot, '.claude', 'settings.json'), (existing) => patchClaudeSettings(existing, skillHooks), input.options),
@@ -0,0 +1,65 @@
1
+ /**
2
+ * `agent-kit-global` self-update scaffolder.
3
+ *
4
+ * Keeps the ONE globally-distributed `@webpresso/agent-kit` binary fresh on
5
+ * every `wp setup`, mirroring how omx / omc / codex / claude self-update their
6
+ * own global installs. The PATH `wp`, the Claude plugin MCP, and the agent
7
+ * hooks all resolve to this single global binary, so refreshing it here means
8
+ * the next invocation everywhere runs the latest published release.
9
+ *
10
+ * Uses the exact same command the auto-update installer infers
11
+ * (`buildVpGlobalInstallCommand` — single source of truth), so there is no
12
+ * second place that can drift on the install incantation.
13
+ *
14
+ * Skipped (no-op, non-fatal) when:
15
+ * - `--dry-run` (no writes anywhere),
16
+ * - `WP_SKIP_AUTO_INSTALL=1` (the documented opt-out, surfaced in the update
17
+ * banner),
18
+ * - the running binary resolves into a webpresso source/git clone — a global
19
+ * install would clobber the developer's working clone with a published
20
+ * tarball (`detectGitInstall`),
21
+ * - `vp` is not on PATH (nothing to install with).
22
+ *
23
+ * A failed refresh is reported but NEVER fails consumer setup: keeping the
24
+ * global tool current is ancillary to scaffolding the consumer repo (same
25
+ * warn-only contract as the codex-cli scaffolder).
26
+ */
27
+ import { spawnSync } from 'node:child_process';
28
+ import type { MergeOptions } from '#cli/commands/init/merge';
29
+ import { type SpinnerFactory } from '#cli/commands/init/scaffolders/spinner';
30
+ export interface EnsureAgentKitGlobalInput {
31
+ options: MergeOptions;
32
+ /** DI seam for child_process.spawnSync. */
33
+ spawn?: typeof spawnSync;
34
+ /** DI seam for environment-backed opt-out. */
35
+ env?: NodeJS.ProcessEnv;
36
+ /** The running binary path (defaults to process.argv[1]). Used for source-clone detection. */
37
+ argv1?: string;
38
+ /** DI seam for source/git-clone detection. */
39
+ detectGit?: (argv1: string) => string | null;
40
+ /** DI seam for spinner. Defaults to noop when !process.stdout.isTTY. */
41
+ spinnerFactory?: SpinnerFactory;
42
+ }
43
+ export type EnsureAgentKitGlobalResult = {
44
+ kind: 'agent-kit-global-updated';
45
+ command: readonly string[];
46
+ } | {
47
+ kind: 'agent-kit-global-skipped-dry-run';
48
+ } | {
49
+ kind: 'agent-kit-global-skipped-opt-out';
50
+ } | {
51
+ kind: 'agent-kit-global-skipped-source-clone';
52
+ repoRoot: string;
53
+ } | {
54
+ kind: 'agent-kit-global-skipped-no-vp';
55
+ hint: string;
56
+ } | {
57
+ kind: 'agent-kit-global-failed';
58
+ exitCode: number;
59
+ command: readonly string[];
60
+ };
61
+ /**
62
+ * Refresh the single global `@webpresso/agent-kit` install via `vp install -g`.
63
+ */
64
+ export declare function ensureAgentKitGlobal(input: EnsureAgentKitGlobalInput): EnsureAgentKitGlobalResult;
65
+ //# sourceMappingURL=index.d.ts.map