@aion0/forge 0.8.1 → 0.8.2

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 (45) hide show
  1. package/RELEASE_NOTES.md +25 -6
  2. package/app/api/connectors/[id]/settings/route.ts +31 -37
  3. package/app/api/connectors/[id]/test/route.ts +260 -0
  4. package/app/api/connectors/install-local/route.ts +211 -0
  5. package/app/api/connectors/marketplace/route.ts +79 -0
  6. package/app/api/connectors/route.ts +41 -46
  7. package/app/api/jobs/route.ts +1 -0
  8. package/app/api/skills/install-local/route.ts +282 -0
  9. package/components/ConnectorsPanel.tsx +526 -211
  10. package/components/SettingsModal.tsx +1 -0
  11. package/components/SkillsPanel.tsx +42 -1
  12. package/lib/agents/claude-adapter.ts +4 -0
  13. package/lib/agents/types.ts +6 -0
  14. package/lib/chat/agent-loop.ts +13 -22
  15. package/lib/chat/protocols/http.ts +1 -1
  16. package/lib/chat/protocols/shell.ts +1 -1
  17. package/lib/chat/tool-dispatcher.ts +20 -20
  18. package/lib/connectors/migration.ts +110 -0
  19. package/lib/connectors/registry.ts +328 -0
  20. package/lib/connectors/sync.ts +305 -0
  21. package/lib/connectors/types.ts +253 -0
  22. package/lib/help-docs/00-overview.md +1 -0
  23. package/lib/help-docs/17-connectors.md +241 -189
  24. package/lib/help-docs/21-build-connector.md +314 -0
  25. package/lib/help-docs/CLAUDE.md +4 -2
  26. package/lib/init.ts +25 -0
  27. package/lib/jobs/dispatcher.ts +28 -8
  28. package/lib/jobs/scheduler.ts +21 -3
  29. package/lib/jobs/store.ts +11 -2
  30. package/lib/jobs/types.ts +12 -0
  31. package/lib/pipeline-scheduler.ts +3 -2
  32. package/lib/pipeline.ts +135 -13
  33. package/lib/plugins/registry.ts +9 -42
  34. package/lib/plugins/types.ts +4 -129
  35. package/lib/settings.ts +7 -0
  36. package/lib/skills.ts +27 -1
  37. package/lib/task-manager.ts +62 -2
  38. package/package.json +3 -1
  39. package/src/core/db/database.ts +4 -0
  40. package/lib/builtin-plugins/github-api.yaml +0 -93
  41. package/lib/builtin-plugins/gitlab.yaml +0 -860
  42. package/lib/builtin-plugins/mantis.probe.js +0 -176
  43. package/lib/builtin-plugins/mantis.yaml +0 -964
  44. package/lib/builtin-plugins/pmdb.yaml +0 -178
  45. package/lib/builtin-plugins/teams.yaml +0 -913
@@ -1,176 +0,0 @@
1
- // Mantis selector probe — paste into DevTools Console on a Mantis page
2
- // (my_view_page.php / view_all_bug_page.php) to discover stable
3
- // selectors for THIS Mantis instance / theme.
4
- //
5
- // Handles both URL styles:
6
- // - Mantis 1.x classic: /bug_view_page.php?bug_id=N (Forge, older self-hosted)
7
- // - Mantis 2.x modern: /view.php?id=N
8
- //
9
- // Output:
10
- // - Tables containing bug links, sorted by count
11
- // - Per-table: first-row classes, cell breakdown, sample data
12
- // - Suggested selectors block, paste-ready for the connector handler
13
- //
14
- // Re-run on each page the connector touches and after Mantis upgrades.
15
-
16
- (async () => {
17
- // Anchors that look like a bug-view link
18
- const BUG_LINK_SELECTOR =
19
- 'a[href*="view.php?id="], a[href*="bug_view_page.php?bug_id="]';
20
- // Extract numeric bug ID from a href
21
- const BUG_ID_RE = /(?:[?&](?:bug_)?id=)(\d+)/;
22
- // Row marker — checkbox carrying the bug id directly (old themes)
23
- const ROW_CHECKBOX_SELECTOR = 'input[type="checkbox"][value][name*="bug"]';
24
-
25
- const getBugId = (el) => {
26
- if (!el) return null;
27
- if (el.tagName === 'INPUT') return Number(el.value) || null;
28
- const m = (el.href || '').match(BUG_ID_RE);
29
- return m ? Number(m[1]) : null;
30
- };
31
-
32
- const describe = (el) => el.id ? `#${el.id}`
33
- : el.className ? `${el.tagName.toLowerCase()}.${el.className.split(/\s+/).filter(Boolean).slice(0,2).join('.')}`
34
- : el.tagName.toLowerCase();
35
- const log = (k, v) => console.log(`%c${k}`, 'color:#06f;font-weight:bold', v);
36
- const hr = () => console.log('━'.repeat(60));
37
-
38
- console.group('🐞 Mantis selector probe');
39
- log('Page', location.pathname);
40
-
41
- const tables = [...document.querySelectorAll('table')].map((t, i) => {
42
- const bugLinks = t.querySelectorAll(BUG_LINK_SELECTOR);
43
- const checkboxes = t.querySelectorAll(ROW_CHECKBOX_SELECTOR);
44
- return {
45
- idx: i, el: t,
46
- selector: describe(t),
47
- rows: t.querySelectorAll('tr').length,
48
- bugLinks: bugLinks.length,
49
- bugCheckboxes: checkboxes.length,
50
- nearestHeading: t.closest('section, div')?.querySelector('h1,h2,h3,h4,legend,.widget-title')?.innerText?.trim().slice(0,40) || ''
51
- };
52
- }).filter(t => t.bugLinks > 0 || t.bugCheckboxes > 0).sort((a,b) => (b.bugLinks + b.bugCheckboxes) - (a.bugLinks + a.bugCheckboxes));
53
-
54
- if (!tables.length) {
55
- console.warn('No bug-bearing table found. Either no bugs visible, or the markup uses a pattern this probe does not know about.');
56
- console.log('Try the recon snippet at the bottom of this file (commented).');
57
- console.groupEnd(); return;
58
- }
59
-
60
- log(`Tables with bug rows (${tables.length})`, '');
61
- console.table(tables.map(({el, ...rest}) => rest));
62
- hr();
63
-
64
- tables.forEach((t, n) => {
65
- console.groupCollapsed(`📋 Table #${n}: ${t.selector} (${t.bugLinks} links / ${t.bugCheckboxes} checkboxes, section: "${t.nearestHeading}")`);
66
- // Bug row = any <tr> containing either a bug link or a bug checkbox
67
- const bugRows = [...t.el.querySelectorAll('tr')].filter(r =>
68
- r.querySelector(BUG_LINK_SELECTOR) || r.querySelector(ROW_CHECKBOX_SELECTOR)
69
- );
70
- log('Bug rows', bugRows.length);
71
- if (!bugRows.length) { console.groupEnd(); return; }
72
-
73
- const r1 = bugRows[0];
74
- log('First row classes', r1.className || '(none)');
75
- log('First row attrs (non-class)', Object.fromEntries(
76
- [...r1.attributes].filter(a => a.name !== 'class').map(a => [a.name, a.value])
77
- ));
78
-
79
- const cells = [...r1.querySelectorAll('td')];
80
- console.table(cells.map((c, i) => ({
81
- cell: i,
82
- classes: c.className || '',
83
- text: c.innerText.trim().slice(0, 45),
84
- link: c.querySelector('a')?.href?.match(/(view\.php\?id=\d+|bug_view_page\.php\?bug_id=\d+|status_id=\d+|set_project[^&]+)/)?.[0] || '',
85
- ckbox: c.querySelector(ROW_CHECKBOX_SELECTOR)?.value || ''
86
- })));
87
-
88
- const sample = bugRows.slice(0, 5).map(r => {
89
- const link = r.querySelector(BUG_LINK_SELECTOR);
90
- const checkbox = r.querySelector(ROW_CHECKBOX_SELECTOR);
91
- const id = getBugId(link) || getBugId(checkbox);
92
- return {
93
- id,
94
- summary: link?.title?.trim() || link?.textContent?.trim() || '',
95
- statusText: [...r.querySelectorAll('td')].map(c => c.innerText.trim()).find(t => /open|closed|resolved|assigned|new|feedback|acknowledged|confirmed/i.test(t)) || '',
96
- bgcolor: r.getAttribute('bgcolor') || '',
97
- rowClass: r.className || '',
98
- url: link?.href || ''
99
- };
100
- });
101
- log('Sample (first 5 rows)', sample);
102
- console.groupEnd();
103
- });
104
-
105
- hr();
106
-
107
- const best = tables[0];
108
- // Pick the more reliable strategy
109
- const useCheckbox = best.bugCheckboxes >= best.bugLinks;
110
- const rowSelector = useCheckbox
111
- ? `${best.selector} tr:has(${ROW_CHECKBOX_SELECTOR})`
112
- : `${best.selector} tr:has(${BUG_LINK_SELECTOR.split(', ')[0]}), ${best.selector} tr:has(${BUG_LINK_SELECTOR.split(', ')[1]})`;
113
-
114
- console.log('%c✅ Suggested selectors for mantis.ts:', 'color:#0a0;font-weight:bold');
115
- console.log(` bugTable: '${best.selector}'`);
116
- console.log(` bugRow: '${rowSelector}'`);
117
- console.log(` idSource: ${useCheckbox ? "row checkbox value (input[name*='bug'])" : 'href regex'}`);
118
- console.log(` idAnchor: '${BUG_LINK_SELECTOR}'`);
119
- console.log(` idRegex: ${BUG_ID_RE}`);
120
- console.log(` rowCheckbox: '${ROW_CHECKBOX_SELECTOR}'`);
121
- console.log(` status/severity: inspect "classes" + "text" columns above to identify which td holds them`);
122
- console.groupEnd();
123
-
124
- const out = {
125
- page: location.pathname,
126
- tableSelector: best.selector,
127
- rowSelector,
128
- idSource: useCheckbox ? 'checkbox' : 'href',
129
- bugLinkSelector: BUG_LINK_SELECTOR,
130
- bugIdRegex: BUG_ID_RE.source,
131
- rowCheckboxSelector: ROW_CHECKBOX_SELECTOR,
132
- sectionsFound: tables.length,
133
- // Capture first-row cell layout so Claude can map column indices
134
- firstRowCells: (() => {
135
- const r1 = [...best.el.querySelectorAll('tr')].find(r =>
136
- r.querySelector(BUG_LINK_SELECTOR) || r.querySelector(ROW_CHECKBOX_SELECTOR));
137
- if (!r1) return [];
138
- return [...r1.querySelectorAll('td')].map((c, i) => ({
139
- cell: i,
140
- classes: c.className || '',
141
- text: c.innerText.trim().slice(0, 80),
142
- }));
143
- })(),
144
- };
145
-
146
- // Auto-copy to clipboard — single Cmd+V to share
147
- try {
148
- await navigator.clipboard.writeText(JSON.stringify(out, null, 2));
149
- console.log('%c📋 Copied to clipboard — paste to share', 'color:#0a0;font-weight:bold');
150
- } catch (e) {
151
- console.warn('Clipboard write failed (page may not have focus). Result still returned below.');
152
- }
153
-
154
- return out;
155
- })();
156
-
157
- // ----------------------------------------------------------------------
158
- // Fallback recon — uncomment + paste if the main probe finds nothing
159
- // ----------------------------------------------------------------------
160
- // (() => {
161
- // console.group('🔍 Page recon');
162
- // console.log('URL:', location.href);
163
- // console.log('Iframes:', document.querySelectorAll('iframe').length);
164
- // console.log('Tables:', document.querySelectorAll('table').length);
165
- // const anchors = [...document.querySelectorAll('a[href]')];
166
- // console.log('Anchors with numeric-only text:', anchors.filter(a => /^\d{3,}$/.test(a.textContent.trim())).length);
167
- // const patterns = new Set();
168
- // anchors.forEach(a => {
169
- // try {
170
- // const u = new URL(a.href);
171
- // patterns.add(u.pathname.replace(/\d+/g, 'N') + (u.search ? '?' + [...u.searchParams.keys()].sort().join('&') : ''));
172
- // } catch {}
173
- // });
174
- // console.log('Unique href patterns:'); [...patterns].sort().forEach(p => console.log(' ', p));
175
- // console.groupEnd();
176
- // })();