@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.
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Jira content adapter (SPEC §15.2): recognize `/browse/<ISSUE-KEY>` style
3
+ * URLs, fetch the issue through the Jira REST API with the SAME authenticated
4
+ * transport (so network policy, credentials, and limits apply unchanged), and
5
+ * normalize the response into compact Markdown text — one dense block of the
6
+ * fields the model actually needs instead of a page of application chrome.
7
+ * Server/Data Center issues carry wiki-markup descriptions; Cloud issues
8
+ * carry Atlassian Document Format bodies; both convert to Markdown here.
9
+ * @module adapters/jira
10
+ */
11
+ import type { ResolvedAdapter, ResolvedRule } from '../types.js';
12
+ import type { ResolvedAuthSecrets } from '../auth/index.js';
13
+ import type { TransportGlobals } from '../transport/fetch.js';
14
+ /** REST JSON payload the adapter consumes. */
15
+ export type FetchJson = (url: URL) => Promise<{
16
+ statusCode: number;
17
+ data: unknown;
18
+ }>;
19
+ /** Everything an adapter needs beyond the URL; mirrors the transport options. */
20
+ export interface AdapterRequestContext {
21
+ readonly rule: ResolvedRule;
22
+ readonly globals: TransportGlobals;
23
+ readonly resolveSecrets: (rule: ResolvedRule) => Promise<ResolvedAuthSecrets>;
24
+ readonly signal?: AbortSignal;
25
+ }
26
+ /**
27
+ * Extract an issue key from a URL path. Recognizes `/browse/KEY` at any depth
28
+ * (deployments under `/jira/browse/…`) and `/issues/KEY`. Returns `undefined`
29
+ * for URLs the adapter cannot map, so the caller falls back to raw HTML.
30
+ */
31
+ export declare function extractIssueKey(pathname: string): string | undefined;
32
+ /** Build the REST issue URL for the configured flavor. */
33
+ export declare function issueApiUrl(origin: string, key: string, adapter: ResolvedAdapter, includeQuery?: boolean): URL;
34
+ /** REST paging path of the issue's comments, used by the tester's diagnostics. */
35
+ export declare function commentApiPath(key: string, adapter: ResolvedAdapter): string;
36
+ /** Fetch a Jira issue and normalize it into Markdown text (SPEC §15.2). */
37
+ export declare function fetchIssueMarkdown(requestUrl: URL, adapter: ResolvedAdapter, fetchJson: FetchJson): Promise<{
38
+ statusCode: number;
39
+ markdown: string;
40
+ }>;
41
+ /** Convert a description body (wiki markup or ADF) into Markdown. */
42
+ export declare function renderDescription(body: unknown): string;
43
+ /**
44
+ * Convert Jira wiki markup to Markdown. Handles the heading, list, table,
45
+ * block, and code constructs that occur in issue descriptions; inline markup
46
+ * converts conservatively and unknown macros pass through as text.
47
+ */
48
+ export declare function wikiMarkupToMarkdown(source: string): string;
49
+ /**
50
+ * Convert an ADF document to Markdown. Recognizes the standard text block
51
+ * structure (paragraphs, headings, lists, code, quotes, tables); unknown node
52
+ * types render their descendant text so content is never silently dropped.
53
+ */
54
+ export declare function adfToMarkdown(document: unknown): string;
55
+ //# sourceMappingURL=jira.d.ts.map
@@ -0,0 +1,31 @@
1
+ /**
2
+ * A tiny well-formed XML/XHTML reader for content adapters (SPEC §15.2).
3
+ * Confluence storage bodies are well-formed XHTML, so a strict recursive
4
+ * descent parser without external dependencies is enough; anything malformed
5
+ * surfaces as a thrown `Error` the adapter maps to a structured failure.
6
+ * Pure text in, node tree out — no Node or DOM dependencies.
7
+ * @module adapters/markup
8
+ */
9
+ /** A parsed markup node: an element, a text run, or a comment. */
10
+ export type MarkupNode = MarkupElement | MarkupText;
11
+ export interface MarkupElement {
12
+ readonly kind: 'element';
13
+ readonly name: string;
14
+ readonly attrs: Readonly<Record<string, string>>;
15
+ readonly children: MarkupNode[];
16
+ }
17
+ export interface MarkupText {
18
+ readonly kind: 'text';
19
+ readonly value: string;
20
+ }
21
+ export declare function isElement(node: MarkupNode | undefined): node is MarkupElement;
22
+ export declare function isText(node: MarkupNode | undefined): node is MarkupText;
23
+ /** Decode the XML built-in entities plus numeric references; unknown ones pass through. */
24
+ export declare function decodeEntities(text: string): string;
25
+ /** Parse a well-formed XML/XHTML document fragment into a node tree. */
26
+ export declare function parseMarkup(source: string): MarkupNode[];
27
+ /** Concatenated descendant text of a subtree, with block-ish whitespace collapsed. */
28
+ export declare function textContent(nodes: readonly MarkupNode[]): string;
29
+ /** First descendant element with the given (lower-case) name, depth-first. */
30
+ export declare function findElement(nodes: readonly MarkupNode[], name: string): MarkupElement | undefined;
31
+ //# sourceMappingURL=markup.d.ts.map
@@ -5,17 +5,23 @@
5
5
  * asks the credentials domain only for configured/writable facts.
6
6
  * @module client/sections
7
7
  */
8
- import type { IApiClient } from '@deepseek-ai/dsh-client-connection/client';
9
- import type { SettingsScope } from '@deepseek-ai/dsh-client-runtime/client';
8
+ import type { CredentialInfo } from '@deepseek-ai/dsh-credentials/types';
9
+ import type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client';
10
10
  import type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol';
11
11
  import type { DiagnoseReport, ProviderStatusReport, RuleTestReport, WebFetchAuthConfig, AuthenticatedFetchRule } from '../types.js';
12
+ /** Client face of the Host `credentials` Remote namespace (values never ride it). */
13
+ export interface CredentialsRemote {
14
+ describe(refs: string[]): Promise<RemoteResult<Record<string, CredentialInfo>>>;
15
+ set(ref: string, value: string): Promise<RemoteResult<void>>;
16
+ unset(ref: string): Promise<RemoteResult<void>>;
17
+ }
12
18
  /** Client face injected into the card. */
13
19
  export interface CardFace {
14
20
  scope: SettingsScope<WebFetchAuthConfig>;
15
21
  status: () => Promise<RemoteResult<ProviderStatusReport>>;
16
22
  testRule: (ruleId: string, url?: string) => Promise<RemoteResult<RuleTestReport>>;
17
23
  diagnose: (url: string) => Promise<RemoteResult<DiagnoseReport>>;
18
- credentials: IApiClient['credentials'];
24
+ credentials: CredentialsRemote;
19
25
  }
20
26
  /** Provider overview: status, selection, counts, config errors (SPEC §6.1). */
21
27
  export declare function StatusSection({ status: report, warnings }: {
@@ -22,6 +22,7 @@ export declare const AUTH_FETCH_ERROR_CODES: {
22
22
  readonly timeout: 'AUTH_FETCH_TIMEOUT';
23
23
  readonly invalidUrl: 'AUTH_FETCH_INVALID_URL';
24
24
  readonly providerError: 'AUTH_FETCH_PROVIDER_ERROR';
25
+ readonly adapterFailed: 'AUTH_FETCH_ADAPTER_FAILED';
25
26
  };
26
27
  /** Scrub free text before it enters an error message. */
27
28
  export declare function sanitizedDetail(error: unknown, maxLength?: number): string;
@@ -40,4 +41,6 @@ export declare function unsupportedCharset(charset: string): WebError;
40
41
  export declare function timeout(): WebError;
41
42
  export declare function aborted(cause?: unknown): WebError;
42
43
  export declare function providerError(detail: string, cause?: unknown): WebError;
44
+ /** A content adapter could not produce its normalized text (SPEC §15.2). */
45
+ export declare function adapterFailed(detail: string, cause?: unknown): WebError;
43
46
  //# sourceMappingURL=errors.d.ts.map
@@ -26,7 +26,7 @@ declare module '@deepseek-ai/cordis' {
26
26
  /** Cordis plugin ID. */
27
27
  export declare const name = "web-fetch-authenticated";
28
28
  export declare const inject: string[];
29
- export declare const WEB_FETCH_AUTH_SETTINGS_NAMESPACE: import("@deepseek-ai/dsh-settings").SettingsNamespace;
29
+ export declare const WEB_FETCH_AUTH_SETTINGS_NAMESPACE = "web-fetch-authenticated";
30
30
  export type Config = WebFetchAuthConfig;
31
31
  export declare const Config: import("@deepseek-ai/schemastery").default<WebFetchAuthConfig>;
32
32
  /** The host-side Remote face the browser card calls. */
@@ -70,6 +70,32 @@ export type AuthConfig = {
70
70
  readonly credential: string;
71
71
  readonly prefix?: string;
72
72
  };
73
+ /**
74
+ * Per-rule content adapter (SPEC §15.2): `none` returns the raw response to
75
+ * `dsh-tool-web` (HTML → Markdown conversion upstream); `jira` and
76
+ * `confluence` rewrite a recognized URL to the product's REST API, fetch it
77
+ * through the same authenticated transport, and normalize the response into
78
+ * compact Markdown text.
79
+ */
80
+ export type AdapterType = 'none' | 'jira' | 'confluence';
81
+ /** Which Jira REST dialect to speak (SPEC §15.2: Server/DC/Cloud differ). */
82
+ export type JiraFlavor = 'server' | 'cloud';
83
+ export interface AdapterConfig {
84
+ readonly type: AdapterType;
85
+ /** Jira only: REST API flavor. Default `server` (REST v2, wiki-markup bodies). */
86
+ readonly jiraFlavor?: JiraFlavor;
87
+ /** Jira only: include issue comments in the normalized text. Default `false`. */
88
+ readonly includeComments?: boolean;
89
+ /** Jira only: include issue links (blocks/duplicates/…) in the text. Default `false`. */
90
+ readonly includeLinks?: boolean;
91
+ }
92
+ /** Fully resolved adapter settings of a rule (defaults applied). */
93
+ export interface ResolvedAdapter {
94
+ readonly type: AdapterType;
95
+ readonly jiraFlavor: JiraFlavor;
96
+ readonly includeComments: boolean;
97
+ readonly includeLinks: boolean;
98
+ }
73
99
  /** Match section of a rule (SPEC §7/§9): exact hosts, glob paths. */
74
100
  export interface RuleMatch {
75
101
  /** Default `['https']`. */
@@ -97,6 +123,8 @@ export interface AuthenticatedFetchRule {
97
123
  networkPolicy?: NetworkPolicy;
98
124
  redirects?: RedirectPolicy;
99
125
  limits?: FetchLimits;
126
+ /** Optional content adapter (SPEC §15.2). Omitted = raw HTTP/HTML passthrough. */
127
+ adapter?: AdapterConfig;
100
128
  }
101
129
  /** What happens when no rule matches (SPEC §17). v1 supports `block` only. */
102
130
  export type UnmatchedPolicy = 'block';
@@ -143,6 +171,7 @@ export interface ResolvedRule {
143
171
  readonly networkPolicy: ResolvedNetworkPolicy;
144
172
  readonly redirects: ResolvedRedirectPolicy;
145
173
  readonly limits: ResolvedLimits;
174
+ readonly adapter: ResolvedAdapter;
146
175
  }
147
176
  export interface ResolvedConfig {
148
177
  readonly configVersion: number;
@@ -199,6 +228,8 @@ export interface RuleTestReport {
199
228
  readonly detail?: string;
200
229
  /** Short secret-scrubbed response preview. */
201
230
  readonly preview?: string;
231
+ /** Adapter applied for the request (`jira`/`confluence`) when the rule selects one. */
232
+ readonly adapter?: string;
202
233
  readonly truncated: boolean;
203
234
  }
204
235
  /** Sanitized match/policy diagnosis without performing the HTTP request (SPEC §6.4). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yadsh/dsh-web-fetch-authenticated",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "description": "Authenticated, policy-gated WebFetchProvider for the DeepSeek Harness web capability seam (ctx.web)",
5
5
  "repository": {
6
6
  "type": "git",
@@ -48,7 +48,6 @@
48
48
  "inject": [
49
49
  "@deepseek-ai/dsh-api-gateway",
50
50
  "@deepseek-ai/dsh-client-connection",
51
- "@deepseek-ai/dsh-client-runtime",
52
51
  "@deepseek-ai/dsh-client-ui-settings",
53
52
  "@deepseek-ai/dsh-client-ui-settings-plugins"
54
53
  ],
@@ -66,45 +65,49 @@
66
65
  "LICENSE"
67
66
  ],
68
67
  "keywords": [
68
+ "deepseek",
69
69
  "deepseek-harness",
70
70
  "dsh",
71
+ "dsh-plugin",
72
+ "cordis",
71
73
  "web-fetch",
72
74
  "ssrf",
73
75
  "credentials",
74
- "cordis"
76
+ "security",
77
+ "fetch"
75
78
  ],
76
79
  "license": "MIT",
77
80
  "peerDependencies": {
78
- "@deepseek-ai/cordis": "^4.0.1",
79
- "@deepseek-ai/dsh-client-connection": ">=0.1.1-rc.2 <0.2.0",
80
- "@deepseek-ai/dsh-client-runtime": ">=0.1.1-rc.2 <0.2.0",
81
- "@deepseek-ai/dsh-client-ui-settings": ">=0.1.1-rc.2 <0.2.0",
82
- "@deepseek-ai/dsh-client-ui-settings-plugins": ">=0.1.1-rc.2 <0.2.0",
83
- "@deepseek-ai/dsh-client-ui-slots": ">=0.1.1-rc.2 <0.2.0",
84
- "@deepseek-ai/dsh-credentials": ">=0.1.1-rc.2 <0.2.0",
85
- "@deepseek-ai/dsh-settings": ">=0.1.1-rc.2 <0.2.0",
86
- "@deepseek-ai/dsh-typert-protocol": ">=0.1.1-rc.2 <0.2.0",
87
- "@deepseek-ai/dsh-web": ">=0.1.1-rc.2 <0.2.0",
88
- "@deepseek-ai/schemastery": "^3.18.1",
81
+ "@deepseek-ai/cordis": "^4.0.2",
82
+ "@deepseek-ai/dsh-client-connection": ">=0.1.5-rc.2 <0.2.0",
83
+ "@deepseek-ai/dsh-client-ui-renderer": ">=0.1.5-rc.2 <0.2.0",
84
+ "@deepseek-ai/dsh-client-ui-settings": ">=0.1.5-rc.2 <0.2.0",
85
+ "@deepseek-ai/dsh-client-ui-settings-plugins": ">=0.1.5-rc.2 <0.2.0",
86
+ "@deepseek-ai/dsh-client-ui-slots": ">=0.1.5-rc.2 <0.2.0",
87
+ "@deepseek-ai/dsh-credentials": ">=0.1.5-rc.2 <0.2.0",
88
+ "@deepseek-ai/dsh-settings": ">=0.1.5-rc.2 <0.2.0",
89
+ "@deepseek-ai/dsh-typert-protocol": ">=0.1.5-rc.2 <0.2.0",
90
+ "@deepseek-ai/dsh-web": ">=0.1.5-rc.2 <0.2.0",
91
+ "@deepseek-ai/schemastery": "^3.18.2",
89
92
  "react": "^18.2.0"
90
93
  },
91
94
  "dependencies": {
92
95
  "zod": "^4.4.3",
93
- "@yadsh/dsh-plugin-log": "^0.2.1"
96
+ "@yadsh/dsh-plugin-log": "^0.3.0"
94
97
  },
95
98
  "devDependencies": {
96
- "@deepseek-ai/cordis": "4.0.1",
97
- "@deepseek-ai/dsh-client-connection": "0.1.1-rc.2",
98
- "@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
99
- "@deepseek-ai/dsh-client-ui-settings": "0.1.1-rc.2",
100
- "@deepseek-ai/dsh-client-ui-settings-plugins": "0.1.1-rc.2",
101
- "@deepseek-ai/dsh-client-ui-slots": "0.1.1-rc.2",
102
- "@deepseek-ai/dsh-credentials": "0.1.1-rc.2",
103
- "@deepseek-ai/dsh-settings": "0.1.1-rc.2",
104
- "@deepseek-ai/dsh-typert-generator": "0.1.1-rc.2",
105
- "@deepseek-ai/dsh-typert-protocol": "0.1.1-rc.2",
106
- "@deepseek-ai/dsh-web": "0.1.1-rc.2",
107
- "@deepseek-ai/schemastery": "3.18.1",
99
+ "@deepseek-ai/cordis": "4.0.2",
100
+ "@deepseek-ai/dsh-client-connection": "0.1.5-rc.2",
101
+ "@deepseek-ai/dsh-client-ui-renderer": "0.1.5-rc.2",
102
+ "@deepseek-ai/dsh-client-ui-settings": "0.1.5-rc.2",
103
+ "@deepseek-ai/dsh-client-ui-settings-plugins": "0.1.5-rc.2",
104
+ "@deepseek-ai/dsh-client-ui-slots": "0.1.5-rc.2",
105
+ "@deepseek-ai/dsh-credentials": "0.1.5-rc.2",
106
+ "@deepseek-ai/dsh-settings": "0.1.5-rc.2",
107
+ "@deepseek-ai/dsh-typert-generator": "0.1.5-rc.2",
108
+ "@deepseek-ai/dsh-typert-protocol": "0.1.5-rc.2",
109
+ "@deepseek-ai/dsh-web": "0.1.5-rc.2",
110
+ "@deepseek-ai/schemastery": "3.18.2",
108
111
  "@types/node": "^26.4.0",
109
112
  "@types/react": "18.3.28",
110
113
  "eslint": "10.9.1",