@yadsh/dsh-web-fetch-authenticated 0.2.0 → 0.3.1
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 +66 -3
- package/compatibility.json +2 -2
- package/lib/adapters/confluence.js +406 -0
- package/lib/adapters/confluence.js.map +1 -0
- package/lib/adapters/index.js +65 -0
- package/lib/adapters/index.js.map +1 -0
- package/lib/adapters/jira.js +511 -0
- package/lib/adapters/jira.js.map +1 -0
- package/lib/adapters/markup.js +221 -0
- package/lib/adapters/markup.js.map +1 -0
- package/lib/client/index.js +5 -4
- package/lib/client/index.js.map +1 -1
- package/lib/client/sections.js +43 -16
- package/lib/client/sections.js.map +1 -1
- package/lib/client.js +149 -29
- package/lib/client.js.map +1 -1
- package/lib/config.js +15 -0
- package/lib/config.js.map +1 -1
- package/lib/errors.js +5 -0
- package/lib/errors.js.map +1 -1
- package/lib/index.js +10 -9
- package/lib/index.js.map +1 -1
- package/lib/provider.js +7 -3
- package/lib/provider.js.map +1 -1
- package/lib/rule-validation.js +22 -0
- package/lib/rule-validation.js.map +1 -1
- package/lib/testing.js +7 -5
- package/lib/testing.js.map +1 -1
- package/lib/typert.host.js +6 -4
- package/lib/typert.remote-client.js +5 -3
- package/lib/types/adapters/confluence.d.ts +46 -0
- package/lib/types/adapters/index.d.ts +30 -0
- package/lib/types/adapters/jira.d.ts +55 -0
- package/lib/types/adapters/markup.d.ts +31 -0
- package/lib/types/client/sections.d.ts +9 -3
- package/lib/types/errors.d.ts +3 -0
- package/lib/types/index.d.ts +1 -1
- package/lib/types/types.d.ts +31 -0
- package/package.json +30 -27
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# @yadsh/dsh-web-fetch-authenticated
|
|
2
2
|
|
|
3
|
+
[Русский гайд: настройка Jira и Confluence](https://github.com/xarleyn/dsh-plugins/blob/main/plugins/dsh-web-fetch-authenticated/docs/JIRA-CONFLUENCE.ru.md)
|
|
4
|
+
|
|
3
5
|
An authenticated, policy-gated [`WebFetchProvider`](../../docs/) for the
|
|
4
6
|
DeepSeek Harness web capability seam (`ctx.web`). It lets the existing
|
|
5
7
|
model-facing `web_fetch(url)` tool retrieve content from approved
|
|
@@ -11,6 +13,24 @@ prompts, or the browser UI**.
|
|
|
11
13
|
> which credential may be used for it, how authentication is attached, and
|
|
12
14
|
> whether redirects are safe. The model never supplies or receives secrets.
|
|
13
15
|
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
Install the published npm package by name:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
dsh plugin --profile web add @yadsh/dsh-web-fetch-authenticated
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
To remove the plugin:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
dsh plugin --profile web remove @yadsh/dsh-web-fetch-authenticated
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Then pin the provider in the profile patch (`fetchProvider: authenticated`) so
|
|
31
|
+
the model-facing `web_fetch` tool routes through this plugin; without the pin
|
|
32
|
+
the plugin stays inert.
|
|
33
|
+
|
|
14
34
|
## How it works
|
|
15
35
|
|
|
16
36
|
```text
|
|
@@ -24,6 +44,7 @@ web_fetch(url)
|
|
|
24
44
|
-> request with DNS pinning
|
|
25
45
|
-> per-hop redirect re-validation
|
|
26
46
|
-> bounded body read
|
|
47
|
+
-> content adapter (optional: REST fetch + normalization, see below)
|
|
27
48
|
-> WebFetchResult (existing dsh-tool-web HTML -> Markdown)
|
|
28
49
|
```
|
|
29
50
|
|
|
@@ -79,6 +100,11 @@ Secrets are stored through the DSH credential store (`$DSH_HOME` credential
|
|
|
79
100
|
backend) under POSIX-style reference names (`JIRA_TOKEN`); configuration keeps
|
|
80
101
|
only the reference. Use the UI (or `api.credentials.set`) to store the value.
|
|
81
102
|
|
|
103
|
+
For an end-to-end corporate setup, including provider selection, credentials,
|
|
104
|
+
private-network policy, Jira/Confluence Cloud and Server/Data Center examples,
|
|
105
|
+
testing, and troubleshooting, see the
|
|
106
|
+
[Russian Jira and Confluence guide](https://github.com/xarleyn/dsh-plugins/blob/main/plugins/dsh-web-fetch-authenticated/docs/JIRA-CONFLUENCE.ru.md).
|
|
107
|
+
|
|
82
108
|
### Security defaults
|
|
83
109
|
|
|
84
110
|
| Policy | Default |
|
|
@@ -95,6 +121,42 @@ answers are resolved, all candidates are classified, one denied answer denies
|
|
|
95
121
|
the whole set (DNS-rebinding defense), and the socket is pinned to the
|
|
96
122
|
approved addresses.
|
|
97
123
|
|
|
124
|
+
## Content adapters (Jira / Confluence)
|
|
125
|
+
|
|
126
|
+
Raw HTML from enterprise apps converts to Markdown with all the application
|
|
127
|
+
chrome attached. A rule can instead select a **content adapter**: recognized
|
|
128
|
+
URLs are re-fetched from the product's REST API through the same authenticated
|
|
129
|
+
transport (same network policy, credentials, redirect policy, and limits) and
|
|
130
|
+
normalized into compact Markdown text — issue fields, description, and optional
|
|
131
|
+
comments/links for Jira; page metadata and the storage-format body for
|
|
132
|
+
Confluence. Unrecognized URLs fall back to raw HTTP/HTML.
|
|
133
|
+
|
|
134
|
+
- **Jira** — `/browse/ISSUE-KEY` at any deployment depth and `/issues/KEY`.
|
|
135
|
+
`jiraFlavor: server` (default) uses REST v2 and converts wiki-markup bodies;
|
|
136
|
+
`jiraFlavor: cloud` uses REST v3 and converts Atlassian Document Format.
|
|
137
|
+
`includeComments` and `includeLinks` add comments and issue links (off by
|
|
138
|
+
default).
|
|
139
|
+
- **Confluence** — `/pages/<id>/…` (Server and Cloud, including `/wiki/…`
|
|
140
|
+
paths) fetch directly; `/display/<SPACE>/<Title>` resolves via the title
|
|
141
|
+
lookup. Storage-format XHTML becomes Markdown: headings, lists, tables,
|
|
142
|
+
links, entities, code/noformat/panel/expand macros (unknown macros leave a
|
|
143
|
+
visible placeholder instead of vanishing).
|
|
144
|
+
|
|
145
|
+
Configured in the rule editor ("Content adapter") or declaratively:
|
|
146
|
+
|
|
147
|
+
```yaml
|
|
148
|
+
adapter:
|
|
149
|
+
type: jira
|
|
150
|
+
jiraFlavor: server
|
|
151
|
+
includeComments: true
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Non-2xx REST responses stay results (the seam never throws for status codes):
|
|
155
|
+
the model sees a short `[Jira]`/`[Confluence]` HTTP-status note. Malformed or
|
|
156
|
+
non-JSON REST bodies fail with `AUTH_FETCH_ADAPTER_FAILED`. The generated text
|
|
157
|
+
is capped by the rule's `maxBodyChars`, and the connection tester runs the
|
|
158
|
+
adapter too, so Test shows the exact normalized text the model will get.
|
|
159
|
+
|
|
98
160
|
## Error codes
|
|
99
161
|
|
|
100
162
|
`AUTH_FETCH_NO_MATCHING_RULE`, `AUTH_FETCH_AMBIGUOUS_MATCH`,
|
|
@@ -102,7 +164,8 @@ approved addresses.
|
|
|
102
164
|
`AUTH_FETCH_CREDENTIAL_INVALID`, `AUTH_FETCH_NETWORK_DENIED`,
|
|
103
165
|
`AUTH_FETCH_DNS_POLICY_DENIED`, `AUTH_FETCH_REDIRECT_DENIED`,
|
|
104
166
|
`AUTH_FETCH_RESPONSE_TOO_LARGE`, `AUTH_FETCH_UNSUPPORTED_CONTENT`,
|
|
105
|
-
`AUTH_FETCH_TIMEOUT`, `AUTH_FETCH_INVALID_URL`, `AUTH_FETCH_PROVIDER_ERROR
|
|
167
|
+
`AUTH_FETCH_TIMEOUT`, `AUTH_FETCH_INVALID_URL`, `AUTH_FETCH_PROVIDER_ERROR`,
|
|
168
|
+
`AUTH_FETCH_ADAPTER_FAILED` —
|
|
106
169
|
surfaced as `WebError` codes through the existing `web_fetch` error metadata.
|
|
107
170
|
|
|
108
171
|
## Development
|
|
@@ -115,8 +178,8 @@ pnpm --filter @yadsh/dsh-web-fetch-authenticated check # lint + typecheck + te
|
|
|
115
178
|
```
|
|
116
179
|
|
|
117
180
|
`INVESTIGATE.md` documents the exact DSH APIs and integration assumptions
|
|
118
|
-
(SPEC phase 0).
|
|
119
|
-
|
|
181
|
+
(SPEC phase 0). Cookies/OAuth and advanced auth remain excluded (SPEC §29
|
|
182
|
+
phase 5); the Jira/Confluence content adapters (phase 4) are implemented.
|
|
120
183
|
|
|
121
184
|
## License
|
|
122
185
|
|
package/compatibility.json
CHANGED
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Confluence content adapter (SPEC §15.2/§16): recognize page URLs, fetch the
|
|
3
|
+
* page through the Confluence REST API with the SAME authenticated transport,
|
|
4
|
+
* and normalize the storage-format XHTML body into compact Markdown text —
|
|
5
|
+
* page metadata plus the readable content, without theme chrome or macros.
|
|
6
|
+
* Page-id URLs (`/pages/<id>`) fetch directly; `/display/<SPACE>/<Title>`
|
|
7
|
+
* URLs resolve the page by space key and title first.
|
|
8
|
+
* @module adapters/confluence
|
|
9
|
+
*/
|
|
10
|
+
import * as errors from '../errors.js';
|
|
11
|
+
import { isElement, isText, parseMarkup, textContent } from './markup.js';
|
|
12
|
+
/**
|
|
13
|
+
* Extract a page reference from a URL path. Recognizes:
|
|
14
|
+
* - `/**\/pages/<id>/**` (Server and Cloud; Cloud paths carry a `/wiki` prefix),
|
|
15
|
+
* - `/**\/display/<SPACE>/<Title+With+Plus>` (Server display URLs).
|
|
16
|
+
* Returns `undefined` for URLs the adapter cannot map.
|
|
17
|
+
*/
|
|
18
|
+
export function extractPageRef(pathname) {
|
|
19
|
+
const segments = pathname.split('/').filter(segment => segment.length > 0);
|
|
20
|
+
const pagesIndex = segments.lastIndexOf('pages');
|
|
21
|
+
if (pagesIndex >= 0) {
|
|
22
|
+
const id = segments[pagesIndex + 1];
|
|
23
|
+
if (id !== undefined && /^\d+$/u.test(id))
|
|
24
|
+
return { id };
|
|
25
|
+
}
|
|
26
|
+
const displayIndex = segments.lastIndexOf('display');
|
|
27
|
+
if (displayIndex >= 0) {
|
|
28
|
+
const spaceKey = segments[displayIndex + 1];
|
|
29
|
+
const title = segments.slice(displayIndex + 2).join('/');
|
|
30
|
+
if (spaceKey !== undefined && title.length > 0) {
|
|
31
|
+
return { spaceKey: spaceKey.toUpperCase(), title: decodeURIComponent(title).replace(/\+/gu, ' ') };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* REST base path prefix: Cloud paths live under `/wiki` and so does its REST
|
|
38
|
+
* API; Server instances serve `/rest/api` at the origin root.
|
|
39
|
+
*/
|
|
40
|
+
export function restPrefix(pathname) {
|
|
41
|
+
return /^\/wiki(?:\/|$)/u.test(pathname) ? '/wiki/rest/api' : '/rest/api';
|
|
42
|
+
}
|
|
43
|
+
/** REST URL of one content item with the expansions the renderer needs. */
|
|
44
|
+
export function contentApiUrl(origin, prefix, id) {
|
|
45
|
+
const url = new URL(`${prefix}/content/${id}`, origin);
|
|
46
|
+
url.searchParams.set('expand', 'body.storage,space,version');
|
|
47
|
+
return url;
|
|
48
|
+
}
|
|
49
|
+
/** REST URL of the space-key + title lookup used by `/display/` URLs. */
|
|
50
|
+
export function contentLookupUrl(origin, prefix, spaceKey, title) {
|
|
51
|
+
const url = new URL(`${prefix}/content`, origin);
|
|
52
|
+
url.searchParams.set('spaceKey', spaceKey);
|
|
53
|
+
url.searchParams.set('title', title);
|
|
54
|
+
url.searchParams.set('expand', 'body.storage,space,version');
|
|
55
|
+
return url;
|
|
56
|
+
}
|
|
57
|
+
/** Fetch a Confluence page and normalize it into Markdown text. */
|
|
58
|
+
export async function fetchPageMarkdown(requestUrl, adapter, fetchJson) {
|
|
59
|
+
const ref = extractPageRef(requestUrl.pathname);
|
|
60
|
+
if (ref === undefined)
|
|
61
|
+
throw errors.adapterFailed(`URL path "${requestUrl.pathname}" is not a recognizable Confluence page URL`);
|
|
62
|
+
const prefix = restPrefix(requestUrl.pathname);
|
|
63
|
+
let response;
|
|
64
|
+
if (ref.id !== undefined) {
|
|
65
|
+
response = await fetchJson(contentApiUrl(requestUrl.origin, prefix, ref.id));
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
response = await fetchJson(contentLookupUrl(requestUrl.origin, prefix, ref.spaceKey ?? '', ref.title ?? ''));
|
|
69
|
+
}
|
|
70
|
+
if (response.statusCode < 200 || response.statusCode >= 300) {
|
|
71
|
+
// Non-2xx stays a RESULT (the seam contract), like the Jira adapter.
|
|
72
|
+
const target = ref.id !== undefined ? `page ${ref.id}` : `"${ref.title}" in space ${ref.spaceKey}`;
|
|
73
|
+
return {
|
|
74
|
+
statusCode: response.statusCode,
|
|
75
|
+
markdown: `[Confluence] The Confluence REST API returned HTTP ${response.statusCode} for ${target} at ${requestUrl.origin}${prefix}.`,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const page = asContent(response.data);
|
|
79
|
+
const markdown = renderPage(page);
|
|
80
|
+
return { statusCode: response.statusCode, markdown };
|
|
81
|
+
}
|
|
82
|
+
function asContent(data) {
|
|
83
|
+
// The title lookup returns a results envelope; direct fetches return the page.
|
|
84
|
+
const record = data;
|
|
85
|
+
if (Array.isArray(record.results)) {
|
|
86
|
+
const first = record.results[0];
|
|
87
|
+
if (typeof first !== 'object' || first === null) {
|
|
88
|
+
throw errors.adapterFailed('Confluence REST lookup returned no page for the requested title');
|
|
89
|
+
}
|
|
90
|
+
return first;
|
|
91
|
+
}
|
|
92
|
+
return record;
|
|
93
|
+
}
|
|
94
|
+
function renderPage(page) {
|
|
95
|
+
const lines = [];
|
|
96
|
+
const title = typeof page.title === 'string' && page.title.length > 0 ? page.title : 'Untitled page';
|
|
97
|
+
const space = typeof page.space?.name === 'string' ? page.space.name : typeof page.space?.key === 'string' ? page.space.key : undefined;
|
|
98
|
+
const updated = typeof page.version?.when === 'string' ? page.version.when.slice(0, 10) : undefined;
|
|
99
|
+
lines.push(`# ${title}`);
|
|
100
|
+
lines.push('');
|
|
101
|
+
const facts = [];
|
|
102
|
+
if (space !== undefined)
|
|
103
|
+
facts.push(`Space: ${space}`);
|
|
104
|
+
if (updated !== undefined)
|
|
105
|
+
facts.push(`Updated: ${updated}`);
|
|
106
|
+
if (facts.length > 0) {
|
|
107
|
+
for (const fact of facts)
|
|
108
|
+
lines.push(`- ${fact}`);
|
|
109
|
+
lines.push('');
|
|
110
|
+
}
|
|
111
|
+
const storage = page.body?.storage?.value;
|
|
112
|
+
if (typeof storage === 'string' && storage.trim().length > 0) {
|
|
113
|
+
lines.push(storageToMarkdown(storage));
|
|
114
|
+
lines.push('');
|
|
115
|
+
}
|
|
116
|
+
return lines.join('\n').trimEnd();
|
|
117
|
+
}
|
|
118
|
+
// ---- Confluence storage-format XHTML → Markdown ----
|
|
119
|
+
/** Convert a Confluence storage body (XHTML + `ac:` macros) into Markdown. */
|
|
120
|
+
export function storageToMarkdown(storage) {
|
|
121
|
+
const nodes = parseMarkup(storage);
|
|
122
|
+
const blocks = renderBlocks(nodes);
|
|
123
|
+
return blocks.join('\n\n').replace(/\n{3,}/gu, '\n\n').trim();
|
|
124
|
+
}
|
|
125
|
+
/** Elements whose rendered content stays on the current block. */
|
|
126
|
+
const INLINE_ELEMENTS = new Set([
|
|
127
|
+
'span', 'a', 'strong', 'b', 'em', 'i', 'u', 's', 'strike', 'code', 'sub', 'sup', 'tt',
|
|
128
|
+
'br', 'ac:link', 'ac:emoticon', 'ac:plain-text-link-body', 'ac:link-body', 'ac:image', 'ri:attachment', 'ri:page', 'ri:user', 'ac:placeholder',
|
|
129
|
+
]);
|
|
130
|
+
function renderBlocks(nodes) {
|
|
131
|
+
const out = [];
|
|
132
|
+
let inlineBuffer = [];
|
|
133
|
+
const flush = () => {
|
|
134
|
+
const text = inlineBuffer.join('').trim();
|
|
135
|
+
inlineBuffer = [];
|
|
136
|
+
if (text.length > 0)
|
|
137
|
+
out.push(text);
|
|
138
|
+
};
|
|
139
|
+
for (const node of nodes) {
|
|
140
|
+
if (isText(node)) {
|
|
141
|
+
inlineBuffer.push(collapseWhitespace(node.value));
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (INLINE_ELEMENTS.has(node.name)) {
|
|
145
|
+
inlineBuffer.push(renderInlineElement(node));
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
flush();
|
|
149
|
+
out.push(...renderBlockElement(node));
|
|
150
|
+
}
|
|
151
|
+
flush();
|
|
152
|
+
return out.filter(block => block.length > 0);
|
|
153
|
+
}
|
|
154
|
+
function renderBlockElement(node) {
|
|
155
|
+
switch (node.name) {
|
|
156
|
+
case 'p': {
|
|
157
|
+
const text = renderInline(node.children).replace(/\s+/gu, ' ').trim();
|
|
158
|
+
return text.length === 0 ? [] : [text];
|
|
159
|
+
}
|
|
160
|
+
case 'h1':
|
|
161
|
+
case 'h2':
|
|
162
|
+
case 'h3':
|
|
163
|
+
case 'h4':
|
|
164
|
+
case 'h5':
|
|
165
|
+
case 'h6': {
|
|
166
|
+
const text = renderInline(node.children).trim();
|
|
167
|
+
return text.length === 0 ? [] : [`${'#'.repeat(Number(node.name.slice(1)))} ${text}`];
|
|
168
|
+
}
|
|
169
|
+
case 'ul':
|
|
170
|
+
case 'ol':
|
|
171
|
+
return renderList(node, node.name === 'ol' ? 1 : 0, 0);
|
|
172
|
+
case 'blockquote': {
|
|
173
|
+
const inner = renderBlocks(node.children).join('\n\n');
|
|
174
|
+
return inner.length === 0 ? [] : [inner.split('\n').map(line => `> ${line}`).join('\n')];
|
|
175
|
+
}
|
|
176
|
+
case 'pre':
|
|
177
|
+
return ['```\n' + textContent(node.children).replace(/\n$/u, '') + '\n```'];
|
|
178
|
+
case 'table':
|
|
179
|
+
return renderTable(node);
|
|
180
|
+
case 'hr':
|
|
181
|
+
return ['---'];
|
|
182
|
+
case 'ac:structured-macro':
|
|
183
|
+
return [renderMacro(node)].filter(block => block.length > 0);
|
|
184
|
+
case 'ac:layout':
|
|
185
|
+
case 'ac:layout-section':
|
|
186
|
+
case 'ac:layout-cell':
|
|
187
|
+
case 'div':
|
|
188
|
+
case 'section':
|
|
189
|
+
case 'article':
|
|
190
|
+
case 'tbody':
|
|
191
|
+
case 'thead':
|
|
192
|
+
case 'tfoot':
|
|
193
|
+
return renderBlocks(node.children);
|
|
194
|
+
default:
|
|
195
|
+
// Unknown block elements: keep their text so content is never dropped.
|
|
196
|
+
return renderBlocks(node.children);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
function renderInlineElement(node) {
|
|
200
|
+
switch (node.name) {
|
|
201
|
+
case 'br':
|
|
202
|
+
return ' \n';
|
|
203
|
+
case 'a': {
|
|
204
|
+
const href = node.attrs.href ?? '';
|
|
205
|
+
const text = renderInline(node.children).trim();
|
|
206
|
+
if (href.length === 0)
|
|
207
|
+
return text;
|
|
208
|
+
return `[${text.length > 0 ? text : href}](${href})`;
|
|
209
|
+
}
|
|
210
|
+
case 'strong':
|
|
211
|
+
case 'b': {
|
|
212
|
+
const text = renderInline(node.children).trim();
|
|
213
|
+
return text.length === 0 ? '' : `**${text}**`;
|
|
214
|
+
}
|
|
215
|
+
case 'em':
|
|
216
|
+
case 'i': {
|
|
217
|
+
const text = renderInline(node.children).trim();
|
|
218
|
+
return text.length === 0 ? '' : `*${text}*`;
|
|
219
|
+
}
|
|
220
|
+
case 's':
|
|
221
|
+
case 'strike': {
|
|
222
|
+
const text = renderInline(node.children).trim();
|
|
223
|
+
return text.length === 0 ? '' : `~~${text}~~`;
|
|
224
|
+
}
|
|
225
|
+
case 'code':
|
|
226
|
+
case 'tt': {
|
|
227
|
+
const text = textContent(node.children);
|
|
228
|
+
return text.length === 0 ? '' : '`' + text + '`';
|
|
229
|
+
}
|
|
230
|
+
case 'ac:emoticon':
|
|
231
|
+
return node.attrs['ac:name'] ?? '';
|
|
232
|
+
case 'ac:link':
|
|
233
|
+
return renderAcLink(node);
|
|
234
|
+
case 'ac:placeholder':
|
|
235
|
+
return '';
|
|
236
|
+
case 'ac:image':
|
|
237
|
+
case 'ri:attachment': {
|
|
238
|
+
const name = node.attrs['ri:filename'] ?? findDescendantAttr(node, 'ri:attachment', 'ri:filename') ?? 'attachment';
|
|
239
|
+
return `_[${name}]_`;
|
|
240
|
+
}
|
|
241
|
+
default:
|
|
242
|
+
return renderInline(node.children);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
function renderAcLink(node) {
|
|
246
|
+
const body = node.children.find(child => isElement(child) && (child.name === 'ac:link-body' || child.name === 'ac:plain-text-link-body'));
|
|
247
|
+
let label;
|
|
248
|
+
if (isElement(body)) {
|
|
249
|
+
label = body.name === 'ac:plain-text-link-body'
|
|
250
|
+
? textContent(body.children).trim()
|
|
251
|
+
: renderInline(body.children).trim();
|
|
252
|
+
}
|
|
253
|
+
const pageRef = findDescendantAttr(node, 'ri:page', 'ri:content-title');
|
|
254
|
+
const anchor = node.attrs['ac:anchor'];
|
|
255
|
+
if (label !== undefined && label.length > 0)
|
|
256
|
+
return label;
|
|
257
|
+
if (typeof pageRef === 'string' && pageRef.length > 0)
|
|
258
|
+
return pageRef;
|
|
259
|
+
if (typeof anchor === 'string' && anchor.length > 0)
|
|
260
|
+
return anchor;
|
|
261
|
+
return '';
|
|
262
|
+
}
|
|
263
|
+
function findDescendantAttr(node, name, attr) {
|
|
264
|
+
for (const child of node.children) {
|
|
265
|
+
if (!isElement(child))
|
|
266
|
+
continue;
|
|
267
|
+
if (child.name === name) {
|
|
268
|
+
const value = child.attrs[attr];
|
|
269
|
+
if (typeof value === 'string')
|
|
270
|
+
return value;
|
|
271
|
+
}
|
|
272
|
+
const found = findDescendantAttr(child, name, attr);
|
|
273
|
+
if (found !== undefined)
|
|
274
|
+
return found;
|
|
275
|
+
}
|
|
276
|
+
return undefined;
|
|
277
|
+
}
|
|
278
|
+
/** Render one `ac:structured-macro` to a Markdown block. */
|
|
279
|
+
function renderMacro(node) {
|
|
280
|
+
const name = node.attrs['ac:name'] ?? 'macro';
|
|
281
|
+
const parameter = (parameterName) => {
|
|
282
|
+
for (const child of node.children) {
|
|
283
|
+
if (isElement(child) && child.name === 'ac:parameter' && child.attrs['ac:name'] === parameterName) {
|
|
284
|
+
return textContent(child.children).trim();
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return undefined;
|
|
288
|
+
};
|
|
289
|
+
// Code macros are the ones the model actually needs verbatim.
|
|
290
|
+
if (name === 'code') {
|
|
291
|
+
const language = parameter('language') ?? parameter('syntaxhighlighter-parameter') ?? '';
|
|
292
|
+
const bodyElement = node.children.find(child => isElement(child) && child.name === 'ac:plain-text-body');
|
|
293
|
+
const body = bodyElement === undefined || !isElement(bodyElement) ? '' : textContent(bodyElement.children).replace(/\n$/u, '');
|
|
294
|
+
if (body.trim().length === 0)
|
|
295
|
+
return '';
|
|
296
|
+
return '```' + language + '\n' + body + '\n```';
|
|
297
|
+
}
|
|
298
|
+
if (name === 'noformat') {
|
|
299
|
+
const bodyElement = node.children.find(child => isElement(child) && child.name === 'ac:plain-text-body');
|
|
300
|
+
const body = bodyElement === undefined || !isElement(bodyElement) ? '' : textContent(bodyElement.children).replace(/\n$/u, '');
|
|
301
|
+
if (body.trim().length === 0)
|
|
302
|
+
return '';
|
|
303
|
+
return '```\n' + body + '\n```';
|
|
304
|
+
}
|
|
305
|
+
if (name === 'panel' || name === 'info' || name === 'note' || name === 'warning' || name === 'tip') {
|
|
306
|
+
const inner = renderBlocks(node.children).join('\n\n');
|
|
307
|
+
return inner.length === 0 ? '' : inner.split('\n').map(line => `> ${line}`).join('\n');
|
|
308
|
+
}
|
|
309
|
+
if (name === 'expand') {
|
|
310
|
+
const title = parameter('title');
|
|
311
|
+
const inner = renderBlocks(node.children).join('\n\n');
|
|
312
|
+
const header = title !== undefined && title.length > 0 ? `**${title}**` : '';
|
|
313
|
+
return [header, inner].filter(part => part.length > 0).join('\n\n');
|
|
314
|
+
}
|
|
315
|
+
if (name === 'toc' || name === 'toc-zone' || name === 'recently-updated' || name === 'children' || name === 'page-tree') {
|
|
316
|
+
return '';
|
|
317
|
+
}
|
|
318
|
+
// Every other macro: keep a visible placeholder so the model knows
|
|
319
|
+
// structured content existed here instead of silently dropping it.
|
|
320
|
+
const inline = renderInline(node.children).trim();
|
|
321
|
+
return `_[macro: ${name}${inline.length > 0 ? ` — ${inline}` : ''}]_`;
|
|
322
|
+
}
|
|
323
|
+
function renderList(node, ordered, depth) {
|
|
324
|
+
const out = [];
|
|
325
|
+
let index = 0;
|
|
326
|
+
for (const child of node.children) {
|
|
327
|
+
if (!isElement(child) || child.name !== 'li')
|
|
328
|
+
continue;
|
|
329
|
+
index += 1;
|
|
330
|
+
const marker = ordered === 0 ? '-' : `${ordered + index - 1}.`;
|
|
331
|
+
const inline = [];
|
|
332
|
+
const nested = [];
|
|
333
|
+
for (const part of child.children) {
|
|
334
|
+
if (!isElement(part)) {
|
|
335
|
+
const text = collapseWhitespace(part.value).trim();
|
|
336
|
+
if (text.length > 0)
|
|
337
|
+
inline.push(text);
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
if (INLINE_ELEMENTS.has(part.name) || part.name === 'p')
|
|
341
|
+
inline.push(renderInlineElement(part));
|
|
342
|
+
else if (part.name === 'ul' || part.name === 'ol')
|
|
343
|
+
nested.push(...renderList(part, part.name === 'ol' ? 1 : 0, depth + 1));
|
|
344
|
+
else
|
|
345
|
+
nested.push(...renderBlockElement(part));
|
|
346
|
+
}
|
|
347
|
+
const text = inline.join('').trim();
|
|
348
|
+
out.push(`${' '.repeat(depth)}${marker} ${text}`);
|
|
349
|
+
out.push(...nested);
|
|
350
|
+
}
|
|
351
|
+
return out;
|
|
352
|
+
}
|
|
353
|
+
function renderTable(node) {
|
|
354
|
+
const rows = [];
|
|
355
|
+
for (const child of node.children) {
|
|
356
|
+
if (!isElement(child) || child.name !== 'tr') {
|
|
357
|
+
if (isElement(child) && (child.name === 'thead' || child.name === 'tbody' || child.name === 'tfoot')) {
|
|
358
|
+
for (const row of child.children) {
|
|
359
|
+
if (isElement(row) && row.name === 'tr')
|
|
360
|
+
rows.push(rowCells(row));
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
365
|
+
rows.push(rowCells(child));
|
|
366
|
+
}
|
|
367
|
+
if (rows.length === 0)
|
|
368
|
+
return [];
|
|
369
|
+
const width = Math.max(...rows.map(row => row.length), 1);
|
|
370
|
+
const emit = (cells) => `| ${Array.from({ length: width }, (_, index) => (cells[index] ?? '').trim()).join(' | ')} |`;
|
|
371
|
+
const out = [emit(rows[0] ?? []), `| ${Array.from({ length: width }, () => '---').join(' | ')} |`];
|
|
372
|
+
for (const row of rows.slice(1))
|
|
373
|
+
out.push(emit(row));
|
|
374
|
+
return out;
|
|
375
|
+
}
|
|
376
|
+
function rowCells(row) {
|
|
377
|
+
const cells = [];
|
|
378
|
+
for (const child of row.children) {
|
|
379
|
+
if (isElement(child) && (child.name === 'td' || child.name === 'th'))
|
|
380
|
+
cells.push(child);
|
|
381
|
+
}
|
|
382
|
+
return cells.map(cell => {
|
|
383
|
+
const blocks = renderBlocks(cell.children);
|
|
384
|
+
return blocks.join(' ').replace(/\|/gu, '\\|').trim();
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
/** Render any inline run of nodes to text (paragraph bodies, headings). */
|
|
388
|
+
function renderInline(nodes) {
|
|
389
|
+
let out = '';
|
|
390
|
+
for (const node of nodes) {
|
|
391
|
+
if (isText(node)) {
|
|
392
|
+
out += node.value;
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
if (INLINE_ELEMENTS.has(node.name)) {
|
|
396
|
+
out += renderInlineElement(node);
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
out += renderInline(node.children);
|
|
400
|
+
}
|
|
401
|
+
return out;
|
|
402
|
+
}
|
|
403
|
+
function collapseWhitespace(text) {
|
|
404
|
+
return text.replace(/[ \t\r\n]+/gu, ' ');
|
|
405
|
+
}
|
|
406
|
+
//# sourceMappingURL=confluence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confluence.js","sourceRoot":"","sources":["../../src/adapters/confluence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content adapter application seam (SPEC §15.2/§16): one entry point the
|
|
3
|
+
* provider and the tester call after a rule matched. An adapter rewrites the
|
|
4
|
+
* recognized URL to the product's REST API and fetches it through the SAME
|
|
5
|
+
* `authenticatedFetch` transport — network policy, DNS pinning, credentials,
|
|
6
|
+
* redirects, and byte/char limits all apply to the REST hop unchanged; only
|
|
7
|
+
* the presentation differs. An adapter that cannot map the URL falls through
|
|
8
|
+
* (`undefined`), leaving the raw HTTP/HTML behavior untouched.
|
|
9
|
+
* @module adapters
|
|
10
|
+
*/
|
|
11
|
+
import { authenticatedFetch } from '../transport/fetch.js';
|
|
12
|
+
import * as errors from '../errors.js';
|
|
13
|
+
import { fetchIssueMarkdown } from './jira.js';
|
|
14
|
+
import { fetchPageMarkdown } from './confluence.js';
|
|
15
|
+
/**
|
|
16
|
+
* Apply the rule's content adapter to a validated request URL. Returns the
|
|
17
|
+
* normalized result, or `undefined` when the rule has no adapter or the URL
|
|
18
|
+
* is not one the adapter recognizes (callers fall through to raw transport).
|
|
19
|
+
*/
|
|
20
|
+
export async function applyAdapter(url, context, fetchImpl = (restUrl, restContext) => authenticatedFetch({ url: restUrl, ...restContext })) {
|
|
21
|
+
const adapter = context.rule.adapter;
|
|
22
|
+
if (adapter.type === 'none')
|
|
23
|
+
return undefined;
|
|
24
|
+
if (!adapterApplies(adapter, url))
|
|
25
|
+
return undefined;
|
|
26
|
+
const fetchJson = async (restUrl) => {
|
|
27
|
+
const result = await fetchImpl(restUrl, context);
|
|
28
|
+
if (!isJsonBody(result.body.kind)) {
|
|
29
|
+
throw errors.adapterFailed(`the REST endpoint ${restUrl.pathname} did not return JSON (content was ${result.body.kind})`);
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
return { statusCode: result.statusCode, data: JSON.parse(result.body.content) };
|
|
33
|
+
}
|
|
34
|
+
catch (cause) {
|
|
35
|
+
throw errors.adapterFailed(`the REST endpoint ${restUrl.pathname} returned malformed JSON`, cause);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const { statusCode, markdown } = adapter.type === 'jira'
|
|
39
|
+
? await fetchIssueMarkdown(url, adapter, fetchJson)
|
|
40
|
+
: await fetchPageMarkdown(url, adapter, fetchJson);
|
|
41
|
+
// The REST hop already passed through the transport's byte cap; cap the
|
|
42
|
+
// generated text by the same char limit so a huge issue stays bounded.
|
|
43
|
+
const maxChars = context.rule.limits.maxBodyChars;
|
|
44
|
+
const truncated = markdown.length > maxChars;
|
|
45
|
+
const content = truncated ? markdown.slice(0, maxChars) : markdown;
|
|
46
|
+
return {
|
|
47
|
+
url: url.toString(),
|
|
48
|
+
statusCode,
|
|
49
|
+
body: { kind: 'text', content },
|
|
50
|
+
truncated,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/** Whether the adapter recognizes this URL shape (unrecognized → fall through). */
|
|
54
|
+
function adapterApplies(adapter, url) {
|
|
55
|
+
if (adapter.type === 'jira') {
|
|
56
|
+
// Jira: /browse/<KEY> at any deployment depth and /issues/<KEY>.
|
|
57
|
+
return /(?:^|\/)(?:browse|issues)\/[A-Z][A-Z0-9]*-\d+$/iu.test(url.pathname);
|
|
58
|
+
}
|
|
59
|
+
// Confluence: any `/pages/<digits>/...` or `/display/<SPACE>/<title>` path.
|
|
60
|
+
return /(?:^|\/)(?:pages\/\d+|display\/[^/]+\/\S)/iu.test(url.pathname);
|
|
61
|
+
}
|
|
62
|
+
function isJsonBody(kind) {
|
|
63
|
+
return kind === 'text';
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAE1D,OAAO,KAAK,MAAM,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAcnD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAQ,EAAE,OAA8B,EAAE,SAAS,GAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,CAAC,kBAAkB,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,WAAW,EAAE,CAAC;IACrL,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAA;IACpC,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,SAAS,CAAA;IAC7C,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,GAAG,CAAC;QAAE,OAAO,SAAS,CAAA;IAEnD,MAAM,SAAS,GAAG,KAAK,EAAE,OAAY,EAAkD,EAAE;QACvF,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QAChD,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,MAAM,MAAM,CAAC,aAAa,CAAC,qBAAqB,OAAO,CAAC,QAAQ,qCAAqC,MAAM,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAA;QAC3H,CAAC;QACD,IAAI,CAAC;YACH,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAY,EAAE,CAAA;QAC5F,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,MAAM,CAAC,aAAa,CAAC,qBAAqB,OAAO,CAAC,QAAQ,0BAA0B,EAAE,KAAK,CAAC,CAAA;QACpG,CAAC;IACH,CAAC,CAAA;IAED,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,KAAK,MAAM;QACtD,CAAC,CAAC,MAAM,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,CAAC;QACnD,CAAC,CAAC,MAAM,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,CAAC,CAAA;IAEpD,wEAAwE;IACxE,uEAAuE;IACvE,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAA;IACjD,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAA;IAC5C,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAA;IAClE,OAAO;QACL,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE;QACnB,UAAU;QACV,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;QAC/B,SAAS;KACV,CAAA;AACH,CAAC;AAED,mFAAmF;AACnF,SAAS,cAAc,CAAC,OAAwB,EAAE,GAAQ;IACxD,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC5B,iEAAiE;QACjE,OAAO,kDAAkD,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IAC9E,CAAC;IACD,4EAA4E;IAC5E,OAAO,6CAA6C,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;AACzE,CAAC;AAED,SAAS,UAAU,CAAC,IAAqB;IACvC,OAAO,IAAI,KAAK,MAAM,CAAA;AACxB,CAAC"}
|