@getunblocked/sdk 0.1.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.
- package/LICENSE +21 -0
- package/README.md +211 -0
- package/dist/agents.d.ts +301 -0
- package/dist/agents.d.ts.map +1 -0
- package/dist/agents.js +262 -0
- package/dist/agents.js.map +1 -0
- package/dist/client.d.ts +39 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +76 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +70 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +96 -0
- package/dist/errors.js.map +1 -0
- package/dist/http.d.ts +16 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +222 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/timing.d.ts +9 -0
- package/dist/timing.d.ts.map +1 -0
- package/dist/timing.js +86 -0
- package/dist/timing.js.map +1 -0
- package/dist/types.d.ts +273 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +14 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +22 -0
- package/dist/version.js.map +1 -0
- package/docs/README.md +28 -0
- package/docs/agent-frameworks.md +84 -0
- package/docs/api-design.md +53 -0
- package/docs/authentication.md +71 -0
- package/docs/configuration.md +67 -0
- package/docs/context.md +131 -0
- package/docs/contributing.md +51 -0
- package/docs/errors-and-retries.md +135 -0
- package/docs/getting-started.md +62 -0
- package/docs/low-level-requests.md +72 -0
- package/docs/pagination.md +29 -0
- package/docs/release.md +73 -0
- package/docs/runtime-and-packaging.md +57 -0
- package/docs/typescript.md +102 -0
- package/examples/context-research-tool.ts +10 -0
- package/package.json +51 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK version. Keep in sync with the `version` field in package.json when
|
|
3
|
+
* cutting a release; it is sent on the User-Agent header for telemetry.
|
|
4
|
+
*/
|
|
5
|
+
export declare const VERSION = "0.1.0";
|
|
6
|
+
/**
|
|
7
|
+
* Builds the User-Agent value sent on every request, e.g.
|
|
8
|
+
* `@getunblocked/sdk/0.1.0 node/20.11.0`. The runtime suffix is best-effort.
|
|
9
|
+
*
|
|
10
|
+
* Browsers treat User-Agent as a forbidden header name and silently drop it,
|
|
11
|
+
* which is harmless: the backend only logs the value for debugging.
|
|
12
|
+
*/
|
|
13
|
+
export declare function getUserAgent(): string;
|
|
14
|
+
//# sourceMappingURL=version.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,OAAO,UAAU,CAAC;AAE/B;;;;;;GAMG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAQrC"}
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK version. Keep in sync with the `version` field in package.json when
|
|
3
|
+
* cutting a release; it is sent on the User-Agent header for telemetry.
|
|
4
|
+
*/
|
|
5
|
+
export const VERSION = "0.1.0";
|
|
6
|
+
/**
|
|
7
|
+
* Builds the User-Agent value sent on every request, e.g.
|
|
8
|
+
* `@getunblocked/sdk/0.1.0 node/20.11.0`. The runtime suffix is best-effort.
|
|
9
|
+
*
|
|
10
|
+
* Browsers treat User-Agent as a forbidden header name and silently drop it,
|
|
11
|
+
* which is harmless: the backend only logs the value for debugging.
|
|
12
|
+
*/
|
|
13
|
+
export function getUserAgent() {
|
|
14
|
+
const parts = [`@getunblocked/sdk/${VERSION}`];
|
|
15
|
+
const nodeVersion = globalThis.process?.versions
|
|
16
|
+
?.node;
|
|
17
|
+
if (nodeVersion) {
|
|
18
|
+
parts.push(`node/${nodeVersion}`);
|
|
19
|
+
}
|
|
20
|
+
return parts.join(" ");
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B;;;;;;GAMG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,KAAK,GAAG,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAC;IAC/C,MAAM,WAAW,GAAI,UAA6D,CAAC,OAAO,EAAE,QAAQ;QAClG,EAAE,IAAI,CAAC;IACT,IAAI,WAAW,EAAE,CAAC;QAChB,KAAK,CAAC,IAAI,CAAC,QAAQ,WAAW,EAAE,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC"}
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Documentation
|
|
2
|
+
|
|
3
|
+
This directory contains the SDK documentation for people installing, integrating, and maintaining `@getunblocked/sdk`.
|
|
4
|
+
|
|
5
|
+
## Start Here
|
|
6
|
+
|
|
7
|
+
- [Getting Started](./getting-started.md) - install the package and make the first API calls.
|
|
8
|
+
- [Authentication](./authentication.md) - use Personal Access Tokens, Team Access Tokens, environment variables, and token providers.
|
|
9
|
+
- [Configuration](./configuration.md) - configure base URLs, fetch, headers, timeouts, and retries.
|
|
10
|
+
|
|
11
|
+
## API Guides
|
|
12
|
+
|
|
13
|
+
- [Context](./context.md) - research, search, query, and fetch context from the connected engine.
|
|
14
|
+
- [Pagination](./pagination.md) - parse Link headers manually when using low-level list requests.
|
|
15
|
+
- [Low-Level Requests](./low-level-requests.md) - call API paths that do not yet have first-class helpers.
|
|
16
|
+
|
|
17
|
+
## Integration Guides
|
|
18
|
+
|
|
19
|
+
- [Agent Frameworks](./agent-frameworks.md) - adapt the SDK to TypeScript agent tool systems.
|
|
20
|
+
- [Runtime and Packaging](./runtime-and-packaging.md) - supported runtimes and package publishing behavior.
|
|
21
|
+
- [TypeScript Guide](./typescript.md) - exported types and recommended typing patterns.
|
|
22
|
+
|
|
23
|
+
## Operations
|
|
24
|
+
|
|
25
|
+
- [Errors and Retries](./errors-and-retries.md) - handle API errors, timeouts, and retry behavior.
|
|
26
|
+
- [Contributing](./contributing.md) - local development workflow for this SDK.
|
|
27
|
+
- [Release Guide](./release.md) - versioning and publishing checklist.
|
|
28
|
+
- [API Design Notes](./api-design.md) - rationale behind the public interface.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Agent Frameworks
|
|
2
|
+
|
|
3
|
+
The SDK is designed to be adapted into TypeScript-first agent frameworks without taking a runtime dependency on those frameworks.
|
|
4
|
+
|
|
5
|
+
## Built-In Tool Helpers
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import {
|
|
9
|
+
createUnblockedTools,
|
|
10
|
+
unblockedToolSchemas,
|
|
11
|
+
} from "@getunblocked/sdk";
|
|
12
|
+
|
|
13
|
+
const tools = createUnblockedTools({
|
|
14
|
+
apiKey: process.env.UNBLOCKED_API_TOKEN,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export const research = {
|
|
18
|
+
...unblockedToolSchemas.research,
|
|
19
|
+
execute: tools.research,
|
|
20
|
+
};
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The same pattern works for frameworks that expect a schema plus an `execute` function. If a framework uses a different naming convention, wrap the `tools.research` function in that framework's tool registration API.
|
|
24
|
+
|
|
25
|
+
## Available Tool Functions
|
|
26
|
+
|
|
27
|
+
`createUnblockedTools` returns one function per context method, and `unblockedToolSchemas` exposes a matching JSON-schema descriptor for each:
|
|
28
|
+
|
|
29
|
+
| Function | Purpose |
|
|
30
|
+
| --- | --- |
|
|
31
|
+
| `research` | Unified multi-source research that synthesizes an answer with references. |
|
|
32
|
+
| `searchCode` | Search the connected codebase. |
|
|
33
|
+
| `searchPrs` | Search pull requests. |
|
|
34
|
+
| `searchIssues` | Search issues. |
|
|
35
|
+
| `searchDocumentation` | Search connected documentation. |
|
|
36
|
+
| `searchMessages` | Search connected messages and conversations. |
|
|
37
|
+
| `queryIssues` | Query issues scoped by projects and/or user. |
|
|
38
|
+
| `queryPrs` | Query pull requests scoped by projects and/or user. |
|
|
39
|
+
| `getUrls` | Fetch and summarize the content of specific URLs. |
|
|
40
|
+
| `getRules` | Get coding rules and conventions for a repository. |
|
|
41
|
+
|
|
42
|
+
`research` resolves to a `ContextResearchResponse` (`summary`, `sources`, `effort`). Search, query, and get functions resolve to responses carrying a `sources` array.
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
const research = await tools.research({
|
|
46
|
+
query: "Where is rate limiting implemented?",
|
|
47
|
+
effort: "high",
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
console.log(research.summary);
|
|
51
|
+
for (const source of research.sources) {
|
|
52
|
+
console.log(source.content, source.url);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const code = await tools.searchCode({ query: "rate limiter middleware" });
|
|
56
|
+
console.log(code.sources.map((source) => source.content));
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Custom Tool Names
|
|
60
|
+
|
|
61
|
+
Frameworks often prefer short action names. Keep the SDK call hidden inside a small adapter.
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
export const searchCodebaseKnowledge = {
|
|
65
|
+
description: "Ask Unblocked about the connected codebase.",
|
|
66
|
+
parameters: unblockedToolSchemas.research.parameters,
|
|
67
|
+
execute: tools.research,
|
|
68
|
+
};
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Recommended Agent Instructions
|
|
72
|
+
|
|
73
|
+
When exposing `research` to an agent, give the agent guidance about when to call it:
|
|
74
|
+
|
|
75
|
+
```md
|
|
76
|
+
Use research when you need repository, docs, issue, pull request, or team-context information that is not present in the current prompt or local files.
|
|
77
|
+
Prefer specific questions. Include relevant file paths, symbol names, error messages, or URLs when available.
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Example Module
|
|
81
|
+
|
|
82
|
+
See [`../examples/context-research-tool.ts`](../examples/context-research-tool.ts).
|
|
83
|
+
|
|
84
|
+
For a complete local Flue demo that shows implementation preflight and bug triage with organizational memory, see [`../examples/flue-bug-triage`](../examples/flue-bug-triage/README.md). For a deployable Eve GitHub-App-webhook agent that makes Unblocked context a required PR-triage step, see [`../examples/eve-pr-triage`](../examples/eve-pr-triage/README.md).
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# API Design Notes
|
|
2
|
+
|
|
3
|
+
The SDK intentionally exposes two layers:
|
|
4
|
+
|
|
5
|
+
1. Resource clients for normal application and agent-framework use:
|
|
6
|
+
`unblocked.context` and its nested `search`, `query`, and `get` groups.
|
|
7
|
+
2. A low-level `unblocked.request()` escape hatch for early adopters who need a
|
|
8
|
+
new endpoint before a first-class wrapper exists.
|
|
9
|
+
|
|
10
|
+
## Principles
|
|
11
|
+
|
|
12
|
+
- Keep the primary client small and branded. `new Unblocked()` is the recommended
|
|
13
|
+
entry point, while `UnblockedClient` remains available for callers who prefer a
|
|
14
|
+
descriptive class name.
|
|
15
|
+
- Model the public API's resources directly, but hide fetch details, bearer-token
|
|
16
|
+
headers, retry timing, response parsing, and link-header parsing.
|
|
17
|
+
- Prefer object parameters for request bodies and option bags so future fields can
|
|
18
|
+
be added without positional-argument churn.
|
|
19
|
+
- Make invalid calls harder to write. Context inputs require the fields the API
|
|
20
|
+
needs, such as `query` on research and search or `urls` on `get.urls`.
|
|
21
|
+
- Keep retries conservative. Only replay idempotent methods by default.
|
|
22
|
+
- Keep package boundaries explicit through `exports`, generated declarations, and
|
|
23
|
+
a narrow `files` allowlist.
|
|
24
|
+
- Avoid runtime dependencies so the package works in Node, edge runtimes, and
|
|
25
|
+
TypeScript agent harnesses.
|
|
26
|
+
|
|
27
|
+
## Chosen Surface
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import Unblocked from "@getunblocked/sdk";
|
|
31
|
+
|
|
32
|
+
const unblocked = new Unblocked({
|
|
33
|
+
apiKey: process.env.UNBLOCKED_API_TOKEN,
|
|
34
|
+
timeoutMs: 30_000,
|
|
35
|
+
maxRetries: 2,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const code = await unblocked.context.search.code({
|
|
39
|
+
query: "rate limiting",
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const research = await unblocked.context.research({
|
|
43
|
+
query: "How does auth work?",
|
|
44
|
+
});
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Considered Alternatives
|
|
48
|
+
|
|
49
|
+
The design pass considered a single `invoke("tool_name", input)` interface, a
|
|
50
|
+
pure OpenAPI-generated REST client, and framework-specific adapters for Flue or
|
|
51
|
+
Eve. The selected surface keeps the common path readable, avoids coupling to a
|
|
52
|
+
framework that may change quickly, and still leaves an escape hatch for advanced
|
|
53
|
+
callers.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Authentication
|
|
2
|
+
|
|
3
|
+
The SDK uses the same authentication model as the Unblocked Public API. Each request includes:
|
|
4
|
+
|
|
5
|
+
```http
|
|
6
|
+
Authorization: Bearer <token>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Token Types
|
|
10
|
+
|
|
11
|
+
Unblocked supports two API token styles:
|
|
12
|
+
|
|
13
|
+
- Personal Access Tokens for user-scoped automation, testing, and development workflows.
|
|
14
|
+
- Team Access Tokens for organization-wide automation.
|
|
15
|
+
|
|
16
|
+
Use the narrowest token that can perform the job. For agent workflows, prefer data-source-scoped tokens when possible.
|
|
17
|
+
|
|
18
|
+
## Passing a Token
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import Unblocked from "@getunblocked/sdk";
|
|
22
|
+
|
|
23
|
+
const unblocked = new Unblocked({
|
|
24
|
+
apiKey: "unb_...",
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`token` is an alias for `apiKey`:
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
const unblocked = new Unblocked({
|
|
32
|
+
token: "unb_...",
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Environment Variables
|
|
37
|
+
|
|
38
|
+
If no token is passed, the client reads environment variables in this order:
|
|
39
|
+
|
|
40
|
+
1. `UNBLOCKED_API_TOKEN`
|
|
41
|
+
2. `UNBLOCKED_API_KEY`
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
export UNBLOCKED_API_TOKEN="unb_..."
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
const unblocked = new Unblocked();
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Async Token Providers
|
|
52
|
+
|
|
53
|
+
Use a token provider when the token comes from a secrets manager or short-lived credential service.
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
const unblocked = new Unblocked({
|
|
57
|
+
apiKey: async () => {
|
|
58
|
+
return await getTokenFromSecretManager();
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The provider is called before each request, so it can refresh or rotate credentials.
|
|
64
|
+
|
|
65
|
+
## Security Notes
|
|
66
|
+
|
|
67
|
+
- Do not commit tokens to source control.
|
|
68
|
+
- Do not expose team tokens in browser code.
|
|
69
|
+
- Prefer server-side or agent-runtime usage for SDK calls.
|
|
70
|
+
- Rotate tokens when they are no longer needed.
|
|
71
|
+
- Scope tokens to the minimum data sources required by the workflow.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
Create a client with `UnblockedClientOptions`.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import Unblocked from "@getunblocked/sdk";
|
|
7
|
+
|
|
8
|
+
const unblocked = new Unblocked({
|
|
9
|
+
apiKey: process.env.UNBLOCKED_API_TOKEN,
|
|
10
|
+
baseUrl: "https://getunblocked.com/api",
|
|
11
|
+
timeoutMs: 30_000,
|
|
12
|
+
maxRetries: 2,
|
|
13
|
+
retryDelayMs: 500,
|
|
14
|
+
headers: {
|
|
15
|
+
"User-Agent": "my-agent/1.0",
|
|
16
|
+
},
|
|
17
|
+
fetch: globalThis.fetch,
|
|
18
|
+
});
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Options
|
|
22
|
+
|
|
23
|
+
`apiKey`:
|
|
24
|
+
API token string or async token provider. If omitted, the SDK reads `UNBLOCKED_API_TOKEN` and then `UNBLOCKED_API_KEY`.
|
|
25
|
+
|
|
26
|
+
`token`:
|
|
27
|
+
Alias for `apiKey`.
|
|
28
|
+
|
|
29
|
+
`baseUrl`:
|
|
30
|
+
Base URL for the public API. Defaults to `https://getunblocked.com/api`.
|
|
31
|
+
|
|
32
|
+
`fetch`:
|
|
33
|
+
Fetch implementation. Defaults to `globalThis.fetch`.
|
|
34
|
+
|
|
35
|
+
`headers`:
|
|
36
|
+
Headers included on every request. The SDK still controls `Authorization`, `Accept`, and `Content-Type` for JSON requests. The SDK also sets a default `User-Agent` (e.g. `@getunblocked/sdk/0.1.0 node/20.x`) that you can override here. Browsers ignore custom `User-Agent` values.
|
|
37
|
+
|
|
38
|
+
`timeoutMs`:
|
|
39
|
+
Maximum time for each HTTP request before the request is aborted. Defaults to `60000` (60 seconds).
|
|
40
|
+
|
|
41
|
+
`maxRetries`:
|
|
42
|
+
Maximum number of retry attempts for retriable requests. Defaults to `2`.
|
|
43
|
+
|
|
44
|
+
`retryDelayMs`:
|
|
45
|
+
Base delay used for exponential backoff. Defaults to `500`.
|
|
46
|
+
|
|
47
|
+
`dangerouslyAllowBrowser`:
|
|
48
|
+
By default the client throws if constructed in a browser-like environment, to keep your API token out of client-side bundles. Set to `true` only if you understand the risk (e.g. you proxy the API or use a restricted token).
|
|
49
|
+
|
|
50
|
+
## Per-Request Options
|
|
51
|
+
|
|
52
|
+
Most methods accept request options as the final argument.
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
await unblocked.context.research(
|
|
56
|
+
{
|
|
57
|
+
query: "How does auth work?",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
timeoutMs: 10_000,
|
|
61
|
+
maxRetries: 1,
|
|
62
|
+
signal: abortController.signal,
|
|
63
|
+
},
|
|
64
|
+
);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Per-request options override client-level options for that call.
|
package/docs/context.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Context
|
|
2
|
+
|
|
3
|
+
The `client.context` resource is the SDK's interface to Unblocked's context engine. Every context method sends a `POST` to a `/tools/context/*` endpoint (under the `https://getunblocked.com/api` base URL) and resolves to a response carrying `sources`.
|
|
4
|
+
|
|
5
|
+
## Response Shape
|
|
6
|
+
|
|
7
|
+
Search, query, and get methods return a response with a `sources` array. `research` additionally returns a `summary` and the `effort` that was used.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
interface ContextSearchSource {
|
|
11
|
+
content: string;
|
|
12
|
+
title?: string;
|
|
13
|
+
url?: string;
|
|
14
|
+
sourceType?: "code" | "pull_request" | "issue" | "messages" | "documentation" | "rules";
|
|
15
|
+
provider?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface ContextSearchResponse {
|
|
19
|
+
toolCallId?: string;
|
|
20
|
+
sources: ContextSearchSource[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface ContextResearchResponse {
|
|
24
|
+
toolCallId?: string;
|
|
25
|
+
summary: string;
|
|
26
|
+
sources: ContextSearchSource[];
|
|
27
|
+
effort: "low" | "medium" | "high";
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`ContextQueryResponse` and `ContextGetResponse` have the same shape as `ContextSearchResponse` (`{ toolCallId?, sources }`).
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
const result = await unblocked.context.research({
|
|
35
|
+
query: "How does the user authentication system work?",
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
console.log(result.summary);
|
|
39
|
+
for (const source of result.sources) {
|
|
40
|
+
console.log(source.content);
|
|
41
|
+
if (source.url) {
|
|
42
|
+
console.log(source.url);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Common Request Fields
|
|
48
|
+
|
|
49
|
+
Every request accepts optional `toolCallId` and `sessionId` strings that correlate a call with its originating tool call and group related context calls. They are always optional.
|
|
50
|
+
|
|
51
|
+
## Effort Levels
|
|
52
|
+
|
|
53
|
+
Only `research` accepts an optional `effort` that trades breadth for latency:
|
|
54
|
+
|
|
55
|
+
- `low` - quick lookup, fastest and narrowest.
|
|
56
|
+
- `medium` - normal, balanced depth (the server default when `effort` is omitted).
|
|
57
|
+
- `high` - broad cross-system research, slowest and most thorough.
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import type { ContextSearchEffort } from "@getunblocked/sdk";
|
|
61
|
+
|
|
62
|
+
const effort: ContextSearchEffort = "high";
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Research
|
|
66
|
+
|
|
67
|
+
`client.context.research(request, options?)` runs unified multi-source research and synthesizes an answer with references.
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
await unblocked.context.research({
|
|
71
|
+
query: "How does the user authentication system work?",
|
|
72
|
+
instruction: "Focus on token refresh.",
|
|
73
|
+
effort: "high",
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Request fields: `query` (required), `instruction` (optional), `effort` (optional), plus optional `toolCallId` and `sessionId`. Returns `ContextResearchResponse` (`summary`, `sources`, `effort`).
|
|
78
|
+
|
|
79
|
+
## Search
|
|
80
|
+
|
|
81
|
+
`client.context.search.*` searches a single source. Each method takes `{ query, instruction? }` (plus optional `toolCallId`/`sessionId`) and returns `ContextSearchResponse`.
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
await unblocked.context.search.code({ query: "rate limiting" });
|
|
85
|
+
await unblocked.context.search.prs({ query: "auth refactor" });
|
|
86
|
+
await unblocked.context.search.issues({ query: "logout after workspace switch" });
|
|
87
|
+
await unblocked.context.search.documentation({ query: "session lifecycle" });
|
|
88
|
+
await unblocked.context.search.messages({ query: "incident 2024-05" });
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
| Method | Endpoint |
|
|
92
|
+
| --- | --- |
|
|
93
|
+
| `search.code` | `/tools/context/search/code` |
|
|
94
|
+
| `search.prs` | `/tools/context/search/prs` |
|
|
95
|
+
| `search.documentation` | `/tools/context/search/documentation` |
|
|
96
|
+
| `search.issues` | `/tools/context/search/issues` |
|
|
97
|
+
| `search.messages` | `/tools/context/search/messages` |
|
|
98
|
+
|
|
99
|
+
## Query
|
|
100
|
+
|
|
101
|
+
`client.context.query.*` queries issues or pull requests, optionally scoped by `projects` and/or `user_name`. Each method takes `{ query, projects?, user_name? }` (plus optional `toolCallId`/`sessionId`) and returns `ContextQueryResponse`.
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
await unblocked.context.query.issues({ query: "open bugs", projects: ["web"], user_name: "alice" });
|
|
105
|
+
await unblocked.context.query.prs({ query: "recent auth changes", projects: ["api"] });
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Get
|
|
109
|
+
|
|
110
|
+
`client.context.get.*` fetches specific resources.
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
await unblocked.context.get.urls({ urls: ["https://example.com/docs"] });
|
|
114
|
+
await unblocked.context.get.rules({ repoName: "acme/web", task: "add endpoint", language: "typescript", paths: ["src/auth"] });
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
- `get.urls` takes `{ urls }` (required) plus optional `toolCallId`/`sessionId`, and summarizes the content of specific URLs. Returns `ContextGetResponse`.
|
|
118
|
+
- `get.rules` takes `{ repoName }` (required) plus optional `ruleId`, `task`, `language`, `paths`, `toolCallId`, and `sessionId`, and returns the coding rules and conventions for a repository. Returns `ContextGetResponse`.
|
|
119
|
+
|
|
120
|
+
## Request Options
|
|
121
|
+
|
|
122
|
+
Every method accepts an optional second `RequestOptions` argument for per-call `headers`, `signal`, `timeoutMs`, `maxRetries`, and `retryDelayMs`; because context methods use `POST`, retry options are accepted but do not trigger retries.
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
await unblocked.context.research(
|
|
126
|
+
{ query: "How does auth work?" },
|
|
127
|
+
{ timeoutMs: 90_000 },
|
|
128
|
+
);
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Context methods use `POST` and are never retried. See [Errors and Retries](./errors-and-retries.md).
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
## Setup
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Build
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm run build
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Test
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm test
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The test command builds the package and runs Node's built-in test runner against the emitted `dist` files.
|
|
22
|
+
|
|
23
|
+
## Package Dry Run
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm pack --dry-run
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
If your local npm cache has permission issues, use a temporary cache:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm --cache /private/tmp/unblocked-typescript-sdk-npm-cache pack --dry-run
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Development Guidelines
|
|
36
|
+
|
|
37
|
+
- Keep runtime dependencies at zero unless there is a strong reason to add one.
|
|
38
|
+
- Prefer resource methods for stable public API endpoints.
|
|
39
|
+
- Use `request` and `requestRaw` as escape hatches, not as the primary documented path.
|
|
40
|
+
- Add or update tests for request construction, auth headers, retries, errors, and type exports.
|
|
41
|
+
- Keep docs in `docs/` updated when changing public behavior.
|
|
42
|
+
- Do not commit generated package tarballs.
|
|
43
|
+
|
|
44
|
+
## Source Layout
|
|
45
|
+
|
|
46
|
+
- `src/client.ts` - public resource clients.
|
|
47
|
+
- `src/http.ts` - fetch transport, retries, timeouts, and pagination parsing.
|
|
48
|
+
- `src/types.ts` - exported public types.
|
|
49
|
+
- `src/errors.ts` - exported error classes.
|
|
50
|
+
- `src/agents.ts` - framework-neutral agent tool helpers.
|
|
51
|
+
- `tests/` - tests against built `dist` output.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Errors and Retries
|
|
2
|
+
|
|
3
|
+
## API Errors
|
|
4
|
+
|
|
5
|
+
Non-2xx responses throw `UnblockedApiError`.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { UnblockedApiError } from "@getunblocked/sdk";
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
await unblocked.context.research({ query: "How does auth work?" });
|
|
12
|
+
} catch (error) {
|
|
13
|
+
if (error instanceof UnblockedApiError) {
|
|
14
|
+
console.error(error.status);
|
|
15
|
+
console.error(error.statusText);
|
|
16
|
+
console.error(error.body);
|
|
17
|
+
console.error(error.requestId); // X-Request-ID, useful for support
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`UnblockedApiError` includes:
|
|
23
|
+
|
|
24
|
+
- `status`
|
|
25
|
+
- `statusText`
|
|
26
|
+
- `url`
|
|
27
|
+
- `method`
|
|
28
|
+
- `body` — the parsed `ApiError` body (`status`, optional `title`, `detail`, `url`, `urlLabel`, `cause`)
|
|
29
|
+
- `headers`
|
|
30
|
+
- `requestId` — the `X-Request-ID` response header, when present
|
|
31
|
+
|
|
32
|
+
The error `message` includes the `title`/`detail` from the response body when the API provides them.
|
|
33
|
+
|
|
34
|
+
## Error Subclasses
|
|
35
|
+
|
|
36
|
+
The thrown error is a status-specific subclass of `UnblockedApiError`, so you can match on the case you care about:
|
|
37
|
+
|
|
38
|
+
| Status | Class |
|
|
39
|
+
| --- | --- |
|
|
40
|
+
| 400 | `UnblockedBadRequestError` |
|
|
41
|
+
| 401 | `UnblockedAuthenticationError` |
|
|
42
|
+
| 403 | `UnblockedPermissionDeniedError` |
|
|
43
|
+
| 404 | `UnblockedNotFoundError` |
|
|
44
|
+
| 429 | `UnblockedRateLimitError` |
|
|
45
|
+
| 5xx | `UnblockedServerError` |
|
|
46
|
+
|
|
47
|
+
Any other non-2xx status throws the base `UnblockedApiError`.
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import { UnblockedRateLimitError } from "@getunblocked/sdk";
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
await unblocked.context.research({ query: "How does auth work?" });
|
|
54
|
+
} catch (error) {
|
|
55
|
+
if (error instanceof UnblockedRateLimitError) {
|
|
56
|
+
// Rate limit exceeded — back off and retry later.
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Timeouts
|
|
62
|
+
|
|
63
|
+
HTTP request timeouts throw `UnblockedTimeoutError`.
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import { UnblockedTimeoutError } from "@getunblocked/sdk";
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
await unblocked.context.research(
|
|
70
|
+
{ query: "How does auth work?" },
|
|
71
|
+
{ timeoutMs: 30_000 },
|
|
72
|
+
);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
if (error instanceof UnblockedTimeoutError) {
|
|
75
|
+
console.error(error.message);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Retry Behavior
|
|
81
|
+
|
|
82
|
+
The SDK retries transient network failures and these response statuses:
|
|
83
|
+
|
|
84
|
+
- `408`
|
|
85
|
+
- `429`
|
|
86
|
+
- `500`
|
|
87
|
+
- `502`
|
|
88
|
+
- `503`
|
|
89
|
+
- `504`
|
|
90
|
+
|
|
91
|
+
Only `GET`, `PUT`, and `DELETE` are retried by default. `POST` and `PATCH` are never retried because they are not generally safe to replay. All `client.context.*` methods use `POST`, so `maxRetries` has no effect on context calls.
|
|
92
|
+
|
|
93
|
+
The default retry settings are:
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
{
|
|
97
|
+
maxRetries: 2,
|
|
98
|
+
retryDelayMs: 500,
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
`Retry-After` response headers are respected when present.
|
|
103
|
+
|
|
104
|
+
## Override Retries
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
const unblocked = new Unblocked({
|
|
108
|
+
apiKey: process.env.UNBLOCKED_API_TOKEN,
|
|
109
|
+
maxRetries: 0,
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Per request:
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
await unblocked.request("GET", "/some/idempotent/path", {
|
|
117
|
+
maxRetries: 1,
|
|
118
|
+
retryDelayMs: 250,
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Context methods use `POST` and are never retried. Passing `maxRetries` to `client.context.*` only records an option the retry loop will not use; retry options affect idempotent low-level `GET`, `PUT`, and `DELETE` requests through `request`/`requestRaw`.
|
|
123
|
+
|
|
124
|
+
## Abort Signals
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
const controller = new AbortController();
|
|
128
|
+
|
|
129
|
+
setTimeout(() => controller.abort(), 5_000);
|
|
130
|
+
|
|
131
|
+
await unblocked.context.research(
|
|
132
|
+
{ query: "How does auth work?" },
|
|
133
|
+
{ signal: controller.signal },
|
|
134
|
+
);
|
|
135
|
+
```
|