@electriccitizen/bolt 0.1.0 → 0.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.
Files changed (84) hide show
  1. package/README.md +93 -14
  2. package/dist/ai/agent.d.ts +66 -0
  3. package/dist/ai/agent.js +232 -0
  4. package/dist/ai/agent.js.map +1 -0
  5. package/dist/ai/knowledge/composer.md +90 -0
  6. package/dist/ai/knowledge/config-safety.md +46 -0
  7. package/dist/ai/knowledge/ddev-operations.md +41 -0
  8. package/dist/ai/knowledge/drupal-internals.md +52 -0
  9. package/dist/ai/knowledge/drupal-updates.md +90 -0
  10. package/dist/ai/knowledge/knowledge/composer.md +90 -0
  11. package/dist/ai/knowledge/knowledge/config-safety.md +46 -0
  12. package/dist/ai/knowledge/knowledge/ddev-operations.md +41 -0
  13. package/dist/ai/knowledge/knowledge/drupal-debugging.md +89 -0
  14. package/dist/ai/knowledge/knowledge/drupal-internals.md +52 -0
  15. package/dist/ai/knowledge/knowledge/drupal-updates.md +90 -0
  16. package/dist/ai/prompts/analyze-ticket.d.ts +30 -0
  17. package/dist/ai/prompts/analyze-ticket.js +116 -0
  18. package/dist/ai/prompts/analyze-ticket.js.map +1 -0
  19. package/dist/ai/prompts/fix-ticket.d.ts +27 -0
  20. package/dist/ai/prompts/fix-ticket.js +129 -0
  21. package/dist/ai/prompts/fix-ticket.js.map +1 -0
  22. package/dist/ai/prompts/pr-description.d.ts +19 -0
  23. package/dist/ai/prompts/pr-description.js +56 -0
  24. package/dist/ai/prompts/pr-description.js.map +1 -0
  25. package/dist/ai/prompts/update-package.d.ts +25 -0
  26. package/dist/ai/prompts/update-package.js +87 -0
  27. package/dist/ai/prompts/update-package.js.map +1 -0
  28. package/dist/ai/prompts/update-plan.d.ts +20 -0
  29. package/dist/ai/prompts/update-plan.js +66 -0
  30. package/dist/ai/prompts/update-plan.js.map +1 -0
  31. package/dist/ai/schemas/analysis-result.d.ts +44 -0
  32. package/dist/ai/schemas/analysis-result.js +101 -0
  33. package/dist/ai/schemas/analysis-result.js.map +1 -0
  34. package/dist/ai/schemas/fix-result.d.ts +34 -0
  35. package/dist/ai/schemas/fix-result.js +55 -0
  36. package/dist/ai/schemas/fix-result.js.map +1 -0
  37. package/dist/ai/schemas/pr-body.d.ts +12 -0
  38. package/dist/ai/schemas/pr-body.js +18 -0
  39. package/dist/ai/schemas/pr-body.js.map +1 -0
  40. package/dist/ai/schemas/update-plan.d.ts +20 -0
  41. package/dist/ai/schemas/update-plan.js +33 -0
  42. package/dist/ai/schemas/update-plan.js.map +1 -0
  43. package/dist/ai/schemas/update-result.d.ts +22 -0
  44. package/dist/ai/schemas/update-result.js +30 -0
  45. package/dist/ai/schemas/update-result.js.map +1 -0
  46. package/dist/cli.js +63 -1
  47. package/dist/cli.js.map +1 -1
  48. package/dist/commands/analyze.d.ts +25 -0
  49. package/dist/commands/analyze.js +377 -0
  50. package/dist/commands/analyze.js.map +1 -0
  51. package/dist/commands/doctor.js +61 -13
  52. package/dist/commands/doctor.js.map +1 -1
  53. package/dist/commands/fix.d.ts +35 -0
  54. package/dist/commands/fix.js +480 -0
  55. package/dist/commands/fix.js.map +1 -0
  56. package/dist/commands/init.d.ts +3 -2
  57. package/dist/commands/init.js +117 -160
  58. package/dist/commands/init.js.map +1 -1
  59. package/dist/commands/pr.d.ts +4 -0
  60. package/dist/commands/pr.js +121 -3
  61. package/dist/commands/pr.js.map +1 -1
  62. package/dist/commands/refresh.js +10 -57
  63. package/dist/commands/refresh.js.map +1 -1
  64. package/dist/commands/update.d.ts +2 -0
  65. package/dist/commands/update.js +463 -64
  66. package/dist/commands/update.js.map +1 -1
  67. package/dist/config.d.ts +16 -0
  68. package/dist/config.js +57 -0
  69. package/dist/config.js.map +1 -1
  70. package/dist/runner.js +12 -0
  71. package/dist/runner.js.map +1 -1
  72. package/dist/safety.d.ts +63 -0
  73. package/dist/safety.js +192 -0
  74. package/dist/safety.js.map +1 -0
  75. package/dist/types.d.ts +2 -0
  76. package/package.json +2 -3
  77. package/modules/bolt_inspect/bolt_inspect.info.yml +0 -6
  78. package/modules/bolt_inspect/bolt_inspect.services.yml +0 -22
  79. package/modules/bolt_inspect/composer.json +0 -16
  80. package/modules/bolt_inspect/drush.services.yml +0 -10
  81. package/modules/bolt_inspect/src/Drush/Commands/BoltInspectCommands.php +0 -203
  82. package/modules/bolt_inspect/src/Service/ContentGenerator.php +0 -586
  83. package/modules/bolt_inspect/src/Service/SiteProfiler.php +0 -362
  84. package/modules/bolt_inspect/src/Service/TestEntityTracker.php +0 -98
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electriccitizen/bolt",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "CLI tool for Drupal 11+ site testing and operations",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -13,12 +13,11 @@
13
13
  },
14
14
  "files": [
15
15
  "dist/",
16
- "modules/bolt_inspect/",
17
16
  "scripts/setup.sh",
18
17
  "README.md"
19
18
  ],
20
19
  "scripts": {
21
- "build": "tsc",
20
+ "build": "tsc && cp -r src/ai/knowledge dist/ai/knowledge",
22
21
  "dev": "tsc --watch",
23
22
  "test": "vitest run",
24
23
  "test:watch": "vitest",
@@ -1,6 +0,0 @@
1
- name: 'Bolt Inspect'
2
- type: module
3
- description: 'Site introspection and test content management for Bolt CLI.'
4
- core_version_requirement: ^11
5
- package: Development
6
- version: '0.1.0'
@@ -1,22 +0,0 @@
1
- services:
2
- bolt_inspect.site_profiler:
3
- class: Drupal\bolt_inspect\Service\SiteProfiler
4
- arguments:
5
- - '@entity_type.manager'
6
- - '@entity_field.manager'
7
- - '@extension.list.module'
8
- - '@router.route_provider'
9
- - '@menu.link_tree'
10
-
11
- bolt_inspect.content_generator:
12
- class: Drupal\bolt_inspect\Service\ContentGenerator
13
- arguments:
14
- - '@entity_type.manager'
15
- - '@entity_field.manager'
16
- - '@bolt_inspect.entity_tracker'
17
-
18
- bolt_inspect.entity_tracker:
19
- class: Drupal\bolt_inspect\Service\TestEntityTracker
20
- arguments:
21
- - '@state'
22
- - '@entity_type.manager'
@@ -1,16 +0,0 @@
1
- {
2
- "name": "bolt/bolt_inspect",
3
- "description": "Drupal site introspection and test content management for Bolt CLI",
4
- "type": "drupal-module",
5
- "license": "GPL-2.0-or-later",
6
- "require": {
7
- "drupal/core": "^11"
8
- },
9
- "extra": {
10
- "drush": {
11
- "services": {
12
- "drush.services.yml": "^13"
13
- }
14
- }
15
- }
16
- }
@@ -1,10 +0,0 @@
1
- services:
2
- bolt_inspect.commands:
3
- class: Drupal\bolt_inspect\Drush\Commands\BoltInspectCommands
4
- arguments:
5
- - '@bolt_inspect.site_profiler'
6
- - '@bolt_inspect.content_generator'
7
- - '@bolt_inspect.entity_tracker'
8
- - '@entity_type.manager'
9
- tags:
10
- - { name: drush.command }
@@ -1,203 +0,0 @@
1
- <?php
2
-
3
- declare(strict_types=1);
4
-
5
- namespace Drupal\bolt_inspect\Drush\Commands;
6
-
7
- use Drupal\bolt_inspect\Service\ContentGenerator;
8
- use Drupal\bolt_inspect\Service\SiteProfiler;
9
- use Drupal\bolt_inspect\Service\TestEntityTracker;
10
- use Drupal\Core\Entity\EntityTypeManagerInterface;
11
- use Drush\Attributes as CLI;
12
- use Drush\Commands\DrushCommands;
13
-
14
- /**
15
- * Drush commands for Bolt site inspection and test content management.
16
- */
17
- class BoltInspectCommands extends DrushCommands {
18
-
19
- public function __construct(
20
- private readonly SiteProfiler $profiler,
21
- private readonly ContentGenerator $generator,
22
- private readonly TestEntityTracker $tracker,
23
- private readonly EntityTypeManagerInterface $entityTypeManager,
24
- ) {
25
- parent::__construct();
26
- }
27
-
28
- /**
29
- * Return full site structure as JSON.
30
- */
31
- #[CLI\Command(name: 'bolt-inspect:profile')]
32
- #[CLI\Usage(name: 'drush bolt-inspect:profile', description: 'Output site profile as JSON')]
33
- public function profile(): void {
34
- $profile = $this->profiler->profile();
35
- $this->output()->writeln(json_encode($profile, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
36
- }
37
-
38
- /**
39
- * Generate test content — one node per content type with required fields.
40
- */
41
- #[CLI\Command(name: 'bolt-inspect:generate')]
42
- #[CLI\Usage(name: 'drush bolt-inspect:generate', description: 'Create test content for all content types')]
43
- public function generate(): void {
44
- if ($this->tracker->hasTracked()) {
45
- $this->logger()->notice('Test content already exists. Run bolt-inspect:cleanup first or use existing content.');
46
- $this->listTracked();
47
- return;
48
- }
49
-
50
- $this->logger()->notice('Generating test content...');
51
- $results = $this->generator->generateAll();
52
-
53
- $rows = [];
54
- $errors = 0;
55
- foreach ($results as $bundle => $result) {
56
- if ($result['status'] === 'created') {
57
- $rows[] = [$bundle, 'CREATED', $result['nid'], $result['label']];
58
- }
59
- else {
60
- $rows[] = [$bundle, 'ERROR', '', $result['error'] ?? 'Unknown error'];
61
- $errors++;
62
- }
63
- }
64
-
65
- $this->io()->table(['Content Type', 'Status', 'NID', 'Detail'], $rows);
66
-
67
- $total = count($results);
68
- $created = $total - $errors;
69
- $this->logger()->success("Generated {$created}/{$total} content types.");
70
-
71
- if ($errors > 0) {
72
- $this->logger()->warning("{$errors} content type(s) had errors.");
73
- }
74
- }
75
-
76
- /**
77
- * Remove all generated test content.
78
- */
79
- #[CLI\Command(name: 'bolt-inspect:cleanup')]
80
- #[CLI\Usage(name: 'drush bolt-inspect:cleanup', description: 'Remove all bolt test content')]
81
- public function cleanup(): void {
82
- if (!$this->tracker->hasTracked()) {
83
- $this->logger()->notice('No test content to clean up.');
84
- return;
85
- }
86
-
87
- $tracked = $this->tracker->getTracked();
88
- $count = count($tracked);
89
- $this->logger()->notice("Cleaning up {$count} tracked entities...");
90
-
91
- $counts = $this->tracker->cleanupAll();
92
-
93
- $rows = [];
94
- foreach ($counts as $type => $deleted) {
95
- $rows[] = [$type, $deleted];
96
- }
97
- $this->io()->table(['Entity Type', 'Deleted'], $rows);
98
-
99
- $total = array_sum($counts);
100
- $this->logger()->success("Cleaned up {$total} entities.");
101
- }
102
-
103
- /**
104
- * List all currently tracked test entities.
105
- */
106
- #[CLI\Command(name: 'bolt-inspect:list')]
107
- #[CLI\Usage(name: 'drush bolt-inspect:list', description: 'List tracked test entities')]
108
- public function listTracked(): void {
109
- $tracked = $this->tracker->getTracked();
110
-
111
- if (empty($tracked)) {
112
- $this->logger()->notice('No tracked test entities.');
113
- return;
114
- }
115
-
116
- $rows = [];
117
- foreach ($tracked as $entry) {
118
- $rows[] = [
119
- $entry['entity_type'],
120
- $entry['id'],
121
- $entry['label'],
122
- date('Y-m-d H:i:s', $entry['created']),
123
- ];
124
- }
125
-
126
- $this->io()->table(['Entity Type', 'ID', 'Label', 'Created'], $rows);
127
- $this->logger()->notice(count($tracked) . ' tracked entities.');
128
- }
129
-
130
- /**
131
- * Render test nodes and report status per content type.
132
- *
133
- * Loads each unpublished test node, renders it in isolation, and returns
134
- * a JSON array with status, nid, title, html_length, or error per bundle.
135
- */
136
- #[CLI\Command(name: 'bolt-inspect:render-check')]
137
- #[CLI\Usage(name: 'drush bolt-inspect:render-check', description: 'Render-check all generated test nodes')]
138
- public function renderCheck(): void {
139
- $nodeStorage = $this->entityTypeManager->getStorage('node');
140
- $viewBuilder = $this->entityTypeManager->getViewBuilder('node');
141
- $renderer = \Drupal::service('renderer');
142
-
143
- $nodeTypes = $this->entityTypeManager->getStorage('node_type')->loadMultiple();
144
- $results = [];
145
-
146
- foreach ($nodeTypes as $nodeType) {
147
- $bundle = $nodeType->id();
148
-
149
- // Find the test node for this bundle.
150
- $nodes = $nodeStorage->loadByProperties([
151
- 'type' => $bundle,
152
- 'status' => 0,
153
- 'uid' => 1,
154
- ]);
155
-
156
- // Filter to bolt-generated nodes.
157
- $node = NULL;
158
- foreach ($nodes as $candidate) {
159
- $title = $candidate->label() ?? '';
160
- if (str_starts_with($title, 'Bolt Test:') || str_starts_with($title, 'Bolt test')) {
161
- $node = $candidate;
162
- break;
163
- }
164
- }
165
-
166
- if (!$node) {
167
- $results[] = [
168
- 'bundle' => $bundle,
169
- 'label' => $nodeType->label(),
170
- 'status' => 'missing',
171
- ];
172
- continue;
173
- }
174
-
175
- try {
176
- $build = $viewBuilder->view($node, 'full');
177
- $html = $renderer->renderInIsolation($build);
178
- $len = strlen((string) $html);
179
-
180
- $results[] = [
181
- 'bundle' => $bundle,
182
- 'label' => $nodeType->label(),
183
- 'status' => 'ok',
184
- 'nid' => (int) $node->id(),
185
- 'title' => $node->label(),
186
- 'html_length' => $len,
187
- ];
188
- }
189
- catch (\Throwable $e) {
190
- $results[] = [
191
- 'bundle' => $bundle,
192
- 'label' => $nodeType->label(),
193
- 'status' => 'error',
194
- 'nid' => (int) $node->id(),
195
- 'error' => $e->getMessage(),
196
- ];
197
- }
198
- }
199
-
200
- $this->output()->writeln(json_encode($results, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
201
- }
202
-
203
- }