@aria-cli/tools 1.0.12 → 1.0.14
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/dist/index.js +378 -70
- package/dist/network-runtime/index.js +8 -12
- package/dist-cjs/index.js +400 -435
- package/dist-cjs/network-runtime/index.js +8 -172
- package/package.json +8 -6
- package/dist/.tsbuildinfo +0 -1
- package/dist/ask-user-interaction.js +0 -22
- package/dist/cache/web-cache.js +0 -66
- package/dist/definitions/arion.js +0 -104
- package/dist/definitions/browser/browser.js +0 -418
- package/dist/definitions/browser/index.js +0 -4
- package/dist/definitions/browser/pw-downloads.js +0 -114
- package/dist/definitions/browser/pw-interactions.js +0 -199
- package/dist/definitions/browser/pw-responses.js +0 -76
- package/dist/definitions/browser/pw-session.js +0 -310
- package/dist/definitions/browser/pw-shared.js +0 -66
- package/dist/definitions/browser/pw-snapshot.js +0 -301
- package/dist/definitions/browser/pw-state.js +0 -62
- package/dist/definitions/browser/types.js +0 -4
- package/dist/definitions/code-intelligence.js +0 -470
- package/dist/definitions/core.js +0 -109
- package/dist/definitions/delegation.js +0 -512
- package/dist/definitions/deploy.js +0 -65
- package/dist/definitions/filesystem.js +0 -196
- package/dist/definitions/frg.js +0 -63
- package/dist/definitions/index.js +0 -20
- package/dist/definitions/memory.js +0 -123
- package/dist/definitions/messaging.js +0 -625
- package/dist/definitions/meta.js +0 -349
- package/dist/definitions/network.js +0 -159
- package/dist/definitions/outlook.js +0 -277
- package/dist/definitions/patch/apply-patch.js +0 -184
- package/dist/definitions/patch/fuzzy-match.js +0 -166
- package/dist/definitions/patch/index.js +0 -1
- package/dist/definitions/patch/patch-parser.js +0 -207
- package/dist/definitions/patch/sandbox-paths.js +0 -105
- package/dist/definitions/process/index.js +0 -4
- package/dist/definitions/process/process-registry.js +0 -213
- package/dist/definitions/process/process.js +0 -386
- package/dist/definitions/process/pty-keys.js +0 -254
- package/dist/definitions/process/session-slug.js +0 -142
- package/dist/definitions/quip.js +0 -195
- package/dist/definitions/search.js +0 -60
- package/dist/definitions/session-history.js +0 -69
- package/dist/definitions/shell.js +0 -181
- package/dist/definitions/slack.js +0 -180
- package/dist/definitions/web.js +0 -109
- package/dist/executors/apply-patch.js +0 -901
- package/dist/executors/arion.js +0 -119
- package/dist/executors/code-intelligence.js +0 -882
- package/dist/executors/deploy.js +0 -848
- package/dist/executors/filesystem.js +0 -1122
- package/dist/executors/frg-freshness.js +0 -576
- package/dist/executors/frg.js +0 -298
- package/dist/executors/index.js +0 -46
- package/dist/executors/learning-meta.js +0 -1146
- package/dist/executors/lsp-client.js +0 -296
- package/dist/executors/memory.js +0 -750
- package/dist/executors/meta.js +0 -220
- package/dist/executors/process-registry.js +0 -465
- package/dist/executors/pty-session-store.js +0 -30
- package/dist/executors/pty.js +0 -271
- package/dist/executors/restart.js +0 -119
- package/dist/executors/search-freshness.js +0 -195
- package/dist/executors/search-types.js +0 -52
- package/dist/executors/search.js +0 -66
- package/dist/executors/self-diagnose.js +0 -398
- package/dist/executors/session-history.js +0 -283
- package/dist/executors/shell-safety.js +0 -473
- package/dist/executors/shell.js +0 -954
- package/dist/executors/utils.js +0 -33
- package/dist/executors/web.js +0 -542
- package/dist/extraction/content-extraction.js +0 -235
- package/dist/extraction/index.js +0 -4
- package/dist/headless-control-contract.js +0 -967
- package/dist/local-control-http-auth.js +0 -2
- package/dist/mcp/client.js +0 -181
- package/dist/mcp/connection.js +0 -480
- package/dist/mcp/index.js +0 -10
- package/dist/mcp/jsonrpc.js +0 -144
- package/dist/mcp/types.js +0 -7
- package/dist/network-control-adapter.js +0 -72
- package/dist/network-runtime/address-types.js +0 -165
- package/dist/network-runtime/db-owner-fencing.js +0 -69
- package/dist/network-runtime/delivery-receipts.js +0 -267
- package/dist/network-runtime/direct-endpoint-authority.js +0 -25
- package/dist/network-runtime/local-control-contract.js +0 -627
- package/dist/network-runtime/node-store-contract.js +0 -34
- package/dist/network-runtime/pair-route-contract.js +0 -77
- package/dist/network-runtime/peer-capabilities.js +0 -28
- package/dist/network-runtime/peer-principal-ref.js +0 -12
- package/dist/network-runtime/peer-state-machine.js +0 -121
- package/dist/network-runtime/protocol-schemas.js +0 -205
- package/dist/network-runtime/runtime-bootstrap-contract.js +0 -60
- package/dist/outlook/desktop-session.js +0 -279
- package/dist/policy.js +0 -149
- package/dist/providers/brave.js +0 -62
- package/dist/providers/duckduckgo.js +0 -176
- package/dist/providers/exa.js +0 -63
- package/dist/providers/firecrawl.js +0 -55
- package/dist/providers/index.js +0 -7
- package/dist/providers/jina.js +0 -49
- package/dist/providers/router.js +0 -96
- package/dist/providers/search-provider.js +0 -32
- package/dist/providers/tavily.js +0 -54
- package/dist/quip/desktop-session.js +0 -317
- package/dist/registry/index.js +0 -1
- package/dist/registry/registry.js +0 -756
- package/dist/runtime-socket-local-control-client.js +0 -330
- package/dist/security/dns-normalization.js +0 -19
- package/dist/security/dns-pinning.js +0 -123
- package/dist/security/external-content.js +0 -91
- package/dist/security/ssrf.js +0 -181
- package/dist/slack/desktop-session.js +0 -324
- package/dist/tool-factory.js +0 -47
- package/dist/types.js +0 -7
- package/dist/utils/retry.js +0 -132
- package/dist/utils/safe-parse-json.js +0 -160
- package/dist/utils/url.js +0 -19
- package/dist-cjs/.tsbuildinfo +0 -1
- package/dist-cjs/ask-user-interaction.js +0 -27
- package/dist-cjs/cache/web-cache.js +0 -70
- package/dist-cjs/definitions/arion.js +0 -107
- package/dist-cjs/definitions/browser/browser.js +0 -421
- package/dist-cjs/definitions/browser/index.js +0 -8
- package/dist-cjs/definitions/browser/pw-downloads.js +0 -117
- package/dist-cjs/definitions/browser/pw-interactions.js +0 -213
- package/dist-cjs/definitions/browser/pw-responses.js +0 -84
- package/dist-cjs/definitions/browser/pw-session.js +0 -326
- package/dist-cjs/definitions/browser/pw-shared.js +0 -72
- package/dist-cjs/definitions/browser/pw-snapshot.js +0 -307
- package/dist-cjs/definitions/browser/pw-state.js +0 -70
- package/dist-cjs/definitions/browser/types.js +0 -5
- package/dist-cjs/definitions/code-intelligence.js +0 -473
- package/dist-cjs/definitions/core.js +0 -133
- package/dist-cjs/definitions/delegation.js +0 -515
- package/dist-cjs/definitions/deploy.js +0 -68
- package/dist-cjs/definitions/filesystem.js +0 -199
- package/dist-cjs/definitions/frg.js +0 -66
- package/dist-cjs/definitions/index.js +0 -43
- package/dist-cjs/definitions/memory.js +0 -126
- package/dist-cjs/definitions/messaging.js +0 -631
- package/dist-cjs/definitions/meta.js +0 -352
- package/dist-cjs/definitions/network.js +0 -162
- package/dist-cjs/definitions/outlook.js +0 -280
- package/dist-cjs/definitions/patch/apply-patch.js +0 -191
- package/dist-cjs/definitions/patch/fuzzy-match.js +0 -172
- package/dist-cjs/definitions/patch/index.js +0 -5
- package/dist-cjs/definitions/patch/patch-parser.js +0 -215
- package/dist-cjs/definitions/patch/sandbox-paths.js +0 -113
- package/dist-cjs/definitions/process/index.js +0 -8
- package/dist-cjs/definitions/process/process-registry.js +0 -231
- package/dist-cjs/definitions/process/process.js +0 -389
- package/dist-cjs/definitions/process/pty-keys.js +0 -259
- package/dist-cjs/definitions/process/session-slug.js +0 -145
- package/dist-cjs/definitions/quip.js +0 -198
- package/dist-cjs/definitions/search.js +0 -63
- package/dist-cjs/definitions/session-history.js +0 -72
- package/dist-cjs/definitions/shell.js +0 -184
- package/dist-cjs/definitions/slack.js +0 -183
- package/dist-cjs/definitions/web.js +0 -112
- package/dist-cjs/executors/apply-patch.js +0 -938
- package/dist-cjs/executors/arion.js +0 -125
- package/dist-cjs/executors/code-intelligence.js +0 -925
- package/dist-cjs/executors/deploy.js +0 -869
- package/dist-cjs/executors/filesystem.js +0 -1167
- package/dist-cjs/executors/frg-freshness.js +0 -627
- package/dist-cjs/executors/frg.js +0 -334
- package/dist-cjs/executors/index.js +0 -143
- package/dist-cjs/executors/learning-meta.js +0 -1165
- package/dist-cjs/executors/lsp-client.js +0 -310
- package/dist-cjs/executors/memory.js +0 -796
- package/dist-cjs/executors/meta.js +0 -226
- package/dist-cjs/executors/process-registry.js +0 -469
- package/dist-cjs/executors/pty-session-store.js +0 -34
- package/dist-cjs/executors/pty.js +0 -312
- package/dist-cjs/executors/restart.js +0 -155
- package/dist-cjs/executors/search-freshness.js +0 -234
- package/dist-cjs/executors/search-types.js +0 -56
- package/dist-cjs/executors/search.js +0 -102
- package/dist-cjs/executors/self-diagnose.js +0 -434
- package/dist-cjs/executors/session-history.js +0 -320
- package/dist-cjs/executors/shell-safety.js +0 -478
- package/dist-cjs/executors/shell.js +0 -1001
- package/dist-cjs/executors/utils.js +0 -73
- package/dist-cjs/executors/web.js +0 -547
- package/dist-cjs/extraction/content-extraction.js +0 -243
- package/dist-cjs/extraction/index.js +0 -8
- package/dist-cjs/headless-control-contract.js +0 -972
- package/dist-cjs/local-control-http-auth.js +0 -5
- package/dist-cjs/mcp/client.js +0 -185
- package/dist-cjs/mcp/connection.js +0 -484
- package/dist-cjs/mcp/index.js +0 -30
- package/dist-cjs/mcp/jsonrpc.js +0 -148
- package/dist-cjs/mcp/types.js +0 -8
- package/dist-cjs/network-control-adapter.js +0 -77
- package/dist-cjs/network-runtime/address-types.js +0 -168
- package/dist-cjs/network-runtime/db-owner-fencing.js +0 -76
- package/dist-cjs/network-runtime/delivery-receipts.js +0 -276
- package/dist-cjs/network-runtime/direct-endpoint-authority.js +0 -29
- package/dist-cjs/network-runtime/local-control-contract.js +0 -633
- package/dist-cjs/network-runtime/node-store-contract.js +0 -38
- package/dist-cjs/network-runtime/pair-route-contract.js +0 -80
- package/dist-cjs/network-runtime/peer-capabilities.js +0 -37
- package/dist-cjs/network-runtime/peer-principal-ref.js +0 -15
- package/dist-cjs/network-runtime/peer-state-machine.js +0 -129
- package/dist-cjs/network-runtime/protocol-schemas.js +0 -212
- package/dist-cjs/network-runtime/runtime-bootstrap-contract.js +0 -63
- package/dist-cjs/outlook/desktop-session.js +0 -318
- package/dist-cjs/policy.js +0 -155
- package/dist-cjs/providers/brave.js +0 -66
- package/dist-cjs/providers/duckduckgo.js +0 -180
- package/dist-cjs/providers/exa.js +0 -67
- package/dist-cjs/providers/firecrawl.js +0 -59
- package/dist-cjs/providers/index.js +0 -17
- package/dist-cjs/providers/jina.js +0 -53
- package/dist-cjs/providers/router.js +0 -100
- package/dist-cjs/providers/search-provider.js +0 -36
- package/dist-cjs/providers/tavily.js +0 -58
- package/dist-cjs/quip/desktop-session.js +0 -353
- package/dist-cjs/registry/index.js +0 -6
- package/dist-cjs/registry/registry.js +0 -761
- package/dist-cjs/runtime-socket-local-control-client.js +0 -367
- package/dist-cjs/security/dns-normalization.js +0 -22
- package/dist-cjs/security/dns-pinning.js +0 -160
- package/dist-cjs/security/external-content.js +0 -95
- package/dist-cjs/security/ssrf.js +0 -221
- package/dist-cjs/slack/desktop-session.js +0 -366
- package/dist-cjs/tool-factory.js +0 -50
- package/dist-cjs/types.js +0 -8
- package/dist-cjs/utils/retry.js +0 -169
- package/dist-cjs/utils/safe-parse-json.js +0 -164
- package/dist-cjs/utils/url.js +0 -23
package/dist/providers/exa.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { createProviderAbortSignal, resolveSearchProviderEnv } from "./search-provider.js";
|
|
2
|
-
export class ExaSearchProvider {
|
|
3
|
-
env;
|
|
4
|
-
name = "exa";
|
|
5
|
-
requiresApiKey = true;
|
|
6
|
-
priority = 3;
|
|
7
|
-
constructor(env = process.env) {
|
|
8
|
-
this.env = env;
|
|
9
|
-
}
|
|
10
|
-
isAvailable() {
|
|
11
|
-
const apiKey = resolveSearchProviderEnv(this.env).EXA_API_KEY;
|
|
12
|
-
return Boolean(apiKey && apiKey.trim().length > 0);
|
|
13
|
-
}
|
|
14
|
-
async search(query, options) {
|
|
15
|
-
const apiKey = resolveSearchProviderEnv(this.env).EXA_API_KEY;
|
|
16
|
-
if (!apiKey) {
|
|
17
|
-
throw new Error("EXA_API_KEY environment variable is not set");
|
|
18
|
-
}
|
|
19
|
-
const limit = options?.limit ?? 5;
|
|
20
|
-
const body = {
|
|
21
|
-
query,
|
|
22
|
-
numResults: limit,
|
|
23
|
-
useAutoprompt: true,
|
|
24
|
-
contents: {
|
|
25
|
-
text: true,
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
|
-
// Domain filtering
|
|
29
|
-
if (options?.domains) {
|
|
30
|
-
body.includeDomains = options.domains;
|
|
31
|
-
}
|
|
32
|
-
if (options?.excludeDomains) {
|
|
33
|
-
body.excludeDomains = options.excludeDomains;
|
|
34
|
-
}
|
|
35
|
-
const { signal, cleanup } = createProviderAbortSignal(30_000, options?.signal);
|
|
36
|
-
try {
|
|
37
|
-
const response = await fetch("https://api.exa.ai/search", {
|
|
38
|
-
method: "POST",
|
|
39
|
-
headers: {
|
|
40
|
-
"Content-Type": "application/json",
|
|
41
|
-
"x-api-key": apiKey,
|
|
42
|
-
},
|
|
43
|
-
body: JSON.stringify(body),
|
|
44
|
-
signal,
|
|
45
|
-
});
|
|
46
|
-
if (!response.ok) {
|
|
47
|
-
throw new Error(`Exa Search API error: ${response.status} ${response.statusText}`);
|
|
48
|
-
}
|
|
49
|
-
const json = await response.json();
|
|
50
|
-
const results = (json.results || []);
|
|
51
|
-
return results.map((r) => ({
|
|
52
|
-
title: r.title,
|
|
53
|
-
url: r.url,
|
|
54
|
-
content: r.text || "",
|
|
55
|
-
score: r.score,
|
|
56
|
-
publishedDate: r.publishedDate,
|
|
57
|
-
}));
|
|
58
|
-
}
|
|
59
|
-
finally {
|
|
60
|
-
cleanup();
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { createProviderAbortSignal, resolveSearchProviderEnv } from "./search-provider.js";
|
|
2
|
-
export class FirecrawlSearchProvider {
|
|
3
|
-
env;
|
|
4
|
-
name = "firecrawl";
|
|
5
|
-
requiresApiKey = true;
|
|
6
|
-
priority = 2;
|
|
7
|
-
constructor(env = process.env) {
|
|
8
|
-
this.env = env;
|
|
9
|
-
}
|
|
10
|
-
isAvailable() {
|
|
11
|
-
const apiKey = resolveSearchProviderEnv(this.env).FIRECRAWL_API_KEY;
|
|
12
|
-
return Boolean(apiKey && apiKey.trim().length > 0);
|
|
13
|
-
}
|
|
14
|
-
async search(query, options) {
|
|
15
|
-
const apiKey = resolveSearchProviderEnv(this.env).FIRECRAWL_API_KEY;
|
|
16
|
-
if (!apiKey) {
|
|
17
|
-
throw new Error("FIRECRAWL_API_KEY environment variable is not set");
|
|
18
|
-
}
|
|
19
|
-
const limit = options?.limit ?? 5;
|
|
20
|
-
const body = {
|
|
21
|
-
query,
|
|
22
|
-
limit,
|
|
23
|
-
};
|
|
24
|
-
const { signal, cleanup } = createProviderAbortSignal(30_000, options?.signal);
|
|
25
|
-
try {
|
|
26
|
-
const response = await fetch("https://api.firecrawl.dev/v1/search", {
|
|
27
|
-
method: "POST",
|
|
28
|
-
headers: {
|
|
29
|
-
"Content-Type": "application/json",
|
|
30
|
-
Authorization: `Bearer ${apiKey}`,
|
|
31
|
-
},
|
|
32
|
-
body: JSON.stringify(body),
|
|
33
|
-
signal,
|
|
34
|
-
});
|
|
35
|
-
if (!response.ok) {
|
|
36
|
-
throw new Error(`Firecrawl Search API error: ${response.status} ${response.statusText}`);
|
|
37
|
-
}
|
|
38
|
-
const json = await response.json();
|
|
39
|
-
// Firecrawl can return 200 with success: false
|
|
40
|
-
if (json.success === false) {
|
|
41
|
-
throw new Error(`Firecrawl API error: ${json.error || "Unknown error"}`);
|
|
42
|
-
}
|
|
43
|
-
const results = (json.data || []);
|
|
44
|
-
return results.map((r) => ({
|
|
45
|
-
title: r.title,
|
|
46
|
-
url: r.url,
|
|
47
|
-
content: r.markdown || "",
|
|
48
|
-
score: r.score,
|
|
49
|
-
}));
|
|
50
|
-
}
|
|
51
|
-
finally {
|
|
52
|
-
cleanup();
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
package/dist/providers/index.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { JinaSearchProvider } from "./jina.js";
|
|
2
|
-
export { DuckDuckGoSearchProvider } from "./duckduckgo.js";
|
|
3
|
-
export { TavilySearchProvider } from "./tavily.js";
|
|
4
|
-
export { BraveSearchProvider } from "./brave.js";
|
|
5
|
-
export { ExaSearchProvider } from "./exa.js";
|
|
6
|
-
export { FirecrawlSearchProvider } from "./firecrawl.js";
|
|
7
|
-
export { SearchProviderRouter } from "./router.js";
|
package/dist/providers/jina.js
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { createProviderAbortSignal, resolveSearchProviderEnv } from "./search-provider.js";
|
|
2
|
-
export class JinaSearchProvider {
|
|
3
|
-
env;
|
|
4
|
-
name = "jina";
|
|
5
|
-
requiresApiKey = false;
|
|
6
|
-
priority = 5;
|
|
7
|
-
constructor(env = process.env) {
|
|
8
|
-
this.env = env;
|
|
9
|
-
}
|
|
10
|
-
isAvailable() {
|
|
11
|
-
// Jina works without an API key (20 req/min), or with a key (200 req/min)
|
|
12
|
-
return true;
|
|
13
|
-
}
|
|
14
|
-
async search(query, options) {
|
|
15
|
-
const apiKey = resolveSearchProviderEnv(this.env).JINA_API_KEY;
|
|
16
|
-
const limit = options?.limit ?? 5;
|
|
17
|
-
const url = new URL("https://s.jina.ai/");
|
|
18
|
-
url.searchParams.set("q", query);
|
|
19
|
-
const headers = {
|
|
20
|
-
Accept: "application/json",
|
|
21
|
-
};
|
|
22
|
-
if (apiKey) {
|
|
23
|
-
headers.Authorization = `Bearer ${apiKey}`;
|
|
24
|
-
}
|
|
25
|
-
const { signal, cleanup } = createProviderAbortSignal(30_000, options?.signal);
|
|
26
|
-
try {
|
|
27
|
-
const response = await fetch(url.toString(), {
|
|
28
|
-
method: "GET",
|
|
29
|
-
headers,
|
|
30
|
-
signal,
|
|
31
|
-
});
|
|
32
|
-
if (!response.ok) {
|
|
33
|
-
throw new Error(`Jina Search API error: ${response.status} ${response.statusText}`);
|
|
34
|
-
}
|
|
35
|
-
const json = await response.json();
|
|
36
|
-
const results = (json.data || []);
|
|
37
|
-
// Apply limit client-side
|
|
38
|
-
return results.slice(0, limit).map((r) => ({
|
|
39
|
-
title: r.title,
|
|
40
|
-
url: r.url,
|
|
41
|
-
content: r.content,
|
|
42
|
-
score: r.score,
|
|
43
|
-
}));
|
|
44
|
-
}
|
|
45
|
-
finally {
|
|
46
|
-
cleanup();
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
package/dist/providers/router.js
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { log } from "@aria-cli/types";
|
|
2
|
-
import { resolveSearchProviderEnv } from "./search-provider.js";
|
|
3
|
-
export class SearchProviderRouter {
|
|
4
|
-
_providers;
|
|
5
|
-
env;
|
|
6
|
-
constructor(_providers, env = process.env) {
|
|
7
|
-
this._providers = _providers;
|
|
8
|
-
this.env = env;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Resolves the best available search provider.
|
|
12
|
-
* Priority:
|
|
13
|
-
* 1. Explicit override via ARIA_SEARCH_PROVIDER env var
|
|
14
|
-
* 2. Highest-priority available provider (lowest priority number)
|
|
15
|
-
* @throws {Error} if no providers are available or override is invalid
|
|
16
|
-
*/
|
|
17
|
-
resolve() {
|
|
18
|
-
const env = resolveSearchProviderEnv(this.env);
|
|
19
|
-
// 1. Check for explicit override
|
|
20
|
-
const override = env.ARIA_SEARCH_PROVIDER;
|
|
21
|
-
if (override) {
|
|
22
|
-
const provider = this._providers.find((p) => p.name === override);
|
|
23
|
-
if (!provider) {
|
|
24
|
-
throw new Error(`ARIA_SEARCH_PROVIDER override '${override}' not found in provider registry`);
|
|
25
|
-
}
|
|
26
|
-
// Verify the overridden provider is actually available (e.g., has API key)
|
|
27
|
-
if (!provider.isAvailable()) {
|
|
28
|
-
// Fall through to default priority-based routing
|
|
29
|
-
log.debug(`[SearchProviderRouter] ARIA_SEARCH_PROVIDER override '${override}' is not available, falling back to priority routing`);
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
return provider;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
// 2. Select first available provider by priority (lower number = higher priority)
|
|
36
|
-
const sorted = [...this._providers].sort((a, b) => a.priority - b.priority);
|
|
37
|
-
const available = sorted.find((p) => p.isAvailable());
|
|
38
|
-
if (!available) {
|
|
39
|
-
throw new Error("No search providers available. Set at least one API key (BRAVE_API_KEY, TAVILY_API_KEY, etc.)");
|
|
40
|
-
}
|
|
41
|
-
return available;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Performs a search with automatic fallback.
|
|
45
|
-
* Tries providers in priority order (resolved provider first, then others).
|
|
46
|
-
* Circuit breaker: stops at first successful response.
|
|
47
|
-
* @throws {AggregateError} if all providers fail
|
|
48
|
-
*/
|
|
49
|
-
async search(query, options) {
|
|
50
|
-
if (options?.signal?.aborted) {
|
|
51
|
-
throw new Error("Search aborted");
|
|
52
|
-
}
|
|
53
|
-
const env = resolveSearchProviderEnv(this.env);
|
|
54
|
-
// Get all available providers sorted by priority
|
|
55
|
-
const availableProviders = [...this._providers]
|
|
56
|
-
.filter((p) => p.isAvailable())
|
|
57
|
-
.sort((a, b) => a.priority - b.priority);
|
|
58
|
-
if (availableProviders.length === 0) {
|
|
59
|
-
throw new Error("No search providers available");
|
|
60
|
-
}
|
|
61
|
-
// Honor ARIA_SEARCH_PROVIDER override: try the override provider first
|
|
62
|
-
const override = env.ARIA_SEARCH_PROVIDER;
|
|
63
|
-
if (override) {
|
|
64
|
-
const overrideProvider = availableProviders.find((p) => p.name === override);
|
|
65
|
-
if (overrideProvider) {
|
|
66
|
-
// Move override provider to front of the list
|
|
67
|
-
const reordered = [
|
|
68
|
-
overrideProvider,
|
|
69
|
-
...availableProviders.filter((p) => p.name !== override),
|
|
70
|
-
];
|
|
71
|
-
availableProviders.length = 0;
|
|
72
|
-
availableProviders.push(...reordered);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
const errors = [];
|
|
76
|
-
// Try each provider in order
|
|
77
|
-
for (const provider of availableProviders) {
|
|
78
|
-
if (options?.signal?.aborted) {
|
|
79
|
-
throw new Error("Search aborted");
|
|
80
|
-
}
|
|
81
|
-
try {
|
|
82
|
-
const results = await provider.search(query, options);
|
|
83
|
-
return results; // Circuit breaker: return on first success
|
|
84
|
-
}
|
|
85
|
-
catch (error) {
|
|
86
|
-
if (options?.signal?.aborted) {
|
|
87
|
-
throw error instanceof Error ? error : new Error("Search aborted");
|
|
88
|
-
}
|
|
89
|
-
errors.push(error instanceof Error ? error : new Error(`Unknown error from ${provider.name}`));
|
|
90
|
-
// Continue to next provider
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
// All providers failed
|
|
94
|
-
throw new AggregateError(errors, `All search providers failed (tried ${availableProviders.length} providers)`);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
export function resolveSearchProviderEnv(env = process.env) {
|
|
2
|
-
return {
|
|
3
|
-
ARIA_SEARCH_PROVIDER: env.ARIA_SEARCH_PROVIDER,
|
|
4
|
-
BRAVE_API_KEY: env.BRAVE_API_KEY,
|
|
5
|
-
FIRECRAWL_API_KEY: env.FIRECRAWL_API_KEY,
|
|
6
|
-
EXA_API_KEY: env.EXA_API_KEY,
|
|
7
|
-
TAVILY_API_KEY: env.TAVILY_API_KEY,
|
|
8
|
-
JINA_API_KEY: env.JINA_API_KEY,
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
export function createProviderAbortSignal(timeoutMs, callerSignal) {
|
|
12
|
-
const controller = new AbortController();
|
|
13
|
-
const onCallerAbort = () => controller.abort();
|
|
14
|
-
if (callerSignal) {
|
|
15
|
-
if (callerSignal.aborted) {
|
|
16
|
-
controller.abort();
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
callerSignal.addEventListener("abort", onCallerAbort, { once: true });
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
23
|
-
return {
|
|
24
|
-
signal: controller.signal,
|
|
25
|
-
cleanup: () => {
|
|
26
|
-
clearTimeout(timeout);
|
|
27
|
-
if (callerSignal) {
|
|
28
|
-
callerSignal.removeEventListener("abort", onCallerAbort);
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
}
|
package/dist/providers/tavily.js
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { createProviderAbortSignal, resolveSearchProviderEnv } from "./search-provider.js";
|
|
2
|
-
export class TavilySearchProvider {
|
|
3
|
-
env;
|
|
4
|
-
name = "tavily";
|
|
5
|
-
requiresApiKey = true;
|
|
6
|
-
priority = 4;
|
|
7
|
-
constructor(env = process.env) {
|
|
8
|
-
this.env = env;
|
|
9
|
-
}
|
|
10
|
-
isAvailable() {
|
|
11
|
-
const apiKey = resolveSearchProviderEnv(this.env).TAVILY_API_KEY;
|
|
12
|
-
return Boolean(apiKey && apiKey.trim().length > 0);
|
|
13
|
-
}
|
|
14
|
-
async search(query, options) {
|
|
15
|
-
const apiKey = resolveSearchProviderEnv(this.env).TAVILY_API_KEY;
|
|
16
|
-
if (!apiKey) {
|
|
17
|
-
throw new Error("TAVILY_API_KEY environment variable is not set");
|
|
18
|
-
}
|
|
19
|
-
const limit = options?.limit ?? 5;
|
|
20
|
-
const body = {
|
|
21
|
-
api_key: apiKey,
|
|
22
|
-
query,
|
|
23
|
-
max_results: limit,
|
|
24
|
-
...(options?.topic && { topic: options.topic }),
|
|
25
|
-
...(options?.domains && { include_domains: options.domains }),
|
|
26
|
-
...(options?.excludeDomains && { exclude_domains: options.excludeDomains }),
|
|
27
|
-
};
|
|
28
|
-
const { signal, cleanup } = createProviderAbortSignal(30_000, options?.signal);
|
|
29
|
-
try {
|
|
30
|
-
const response = await fetch("https://api.tavily.com/search", {
|
|
31
|
-
method: "POST",
|
|
32
|
-
headers: {
|
|
33
|
-
"Content-Type": "application/json",
|
|
34
|
-
},
|
|
35
|
-
body: JSON.stringify(body),
|
|
36
|
-
signal,
|
|
37
|
-
});
|
|
38
|
-
if (!response.ok) {
|
|
39
|
-
throw new Error(`Tavily Search API error: ${response.status} ${response.statusText}`);
|
|
40
|
-
}
|
|
41
|
-
const json = await response.json();
|
|
42
|
-
const results = (json.results || []);
|
|
43
|
-
return results.map((r) => ({
|
|
44
|
-
title: r.title,
|
|
45
|
-
url: r.url,
|
|
46
|
-
content: r.content,
|
|
47
|
-
score: r.score,
|
|
48
|
-
}));
|
|
49
|
-
}
|
|
50
|
-
finally {
|
|
51
|
-
cleanup();
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
@@ -1,317 +0,0 @@
|
|
|
1
|
-
import { execFile } from "node:child_process";
|
|
2
|
-
import { promisify } from "node:util";
|
|
3
|
-
const execFileAsync = promisify(execFile);
|
|
4
|
-
const QUIP_API_BASE = "https://platform.quip.com/1";
|
|
5
|
-
const DEFAULT_BOOTSTRAP_TIMEOUT_MS = 30_000;
|
|
6
|
-
// ── HTML → Markdown conversion (regex-based, no deps) ───────────────
|
|
7
|
-
function htmlToMarkdown(html) {
|
|
8
|
-
let md = html;
|
|
9
|
-
// Block elements first
|
|
10
|
-
md = md.replace(/<h1[^>]*>([\s\S]*?)<\/h1>/gi, "\n# $1\n");
|
|
11
|
-
md = md.replace(/<h2[^>]*>([\s\S]*?)<\/h2>/gi, "\n## $1\n");
|
|
12
|
-
md = md.replace(/<h3[^>]*>([\s\S]*?)<\/h3>/gi, "\n### $1\n");
|
|
13
|
-
md = md.replace(/<h4[^>]*>([\s\S]*?)<\/h4>/gi, "\n#### $1\n");
|
|
14
|
-
md = md.replace(/<br\s*\/?>/gi, "\n");
|
|
15
|
-
md = md.replace(/<\/p>/gi, "\n\n");
|
|
16
|
-
md = md.replace(/<p[^>]*>/gi, "");
|
|
17
|
-
md = md.replace(/<li[^>]*>([\s\S]*?)<\/li>/gi, "- $1\n");
|
|
18
|
-
md = md.replace(/<\/?(ul|ol)[^>]*>/gi, "\n");
|
|
19
|
-
md = md.replace(/<blockquote[^>]*>([\s\S]*?)<\/blockquote>/gi, (_, content) => content
|
|
20
|
-
.split("\n")
|
|
21
|
-
.map((line) => `> ${line}`)
|
|
22
|
-
.join("\n"));
|
|
23
|
-
md = md.replace(/<pre[^>]*>([\s\S]*?)<\/pre>/gi, "\n```\n$1\n```\n");
|
|
24
|
-
md = md.replace(/<code[^>]*>([\s\S]*?)<\/code>/gi, "`$1`");
|
|
25
|
-
// Inline formatting
|
|
26
|
-
md = md.replace(/<(b|strong)[^>]*>([\s\S]*?)<\/\1>/gi, "**$2**");
|
|
27
|
-
md = md.replace(/<(i|em)[^>]*>([\s\S]*?)<\/\1>/gi, "*$2*");
|
|
28
|
-
md = md.replace(/<(s|del|strike)[^>]*>([\s\S]*?)<\/\1>/gi, "~~$2~~");
|
|
29
|
-
md = md.replace(/<a\s+href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/gi, "[$2]($1)");
|
|
30
|
-
// Strip remaining tags
|
|
31
|
-
md = md.replace(/<[^>]+>/g, "");
|
|
32
|
-
// Decode common HTML entities
|
|
33
|
-
md = md.replace(/&/g, "&");
|
|
34
|
-
md = md.replace(/</g, "<");
|
|
35
|
-
md = md.replace(/>/g, ">");
|
|
36
|
-
md = md.replace(/"/g, '"');
|
|
37
|
-
md = md.replace(/'/g, "'");
|
|
38
|
-
md = md.replace(/ /g, " ");
|
|
39
|
-
// Collapse excessive blank lines
|
|
40
|
-
md = md.replace(/\n{3,}/g, "\n\n");
|
|
41
|
-
return md.trim();
|
|
42
|
-
}
|
|
43
|
-
async function extractKeychainDesktopToken() {
|
|
44
|
-
try {
|
|
45
|
-
// Use python3 to parse the bplist from Keychain — macOS ships python3
|
|
46
|
-
// and plutil requires a temp file; python3 one-liner is cleaner.
|
|
47
|
-
const { stdout } = await execFileAsync("python3", [
|
|
48
|
-
"-c",
|
|
49
|
-
`
|
|
50
|
-
import subprocess, plistlib, sys
|
|
51
|
-
from datetime import datetime, timedelta
|
|
52
|
-
try:
|
|
53
|
-
raw = subprocess.check_output([
|
|
54
|
-
'security', 'find-generic-password', '-s', 'Quip', '-a', 'MultiAccount', '-g'
|
|
55
|
-
], stderr=subprocess.STDOUT).decode()
|
|
56
|
-
import re
|
|
57
|
-
hex_match = re.search(r'password: 0x([0-9A-Fa-f]+)', raw)
|
|
58
|
-
if not hex_match:
|
|
59
|
-
sys.exit(1)
|
|
60
|
-
data = bytes.fromhex(hex_match.group(1))
|
|
61
|
-
plist = plistlib.loads(data)
|
|
62
|
-
import json
|
|
63
|
-
for uid, info in plist.get('accounts', {}).items():
|
|
64
|
-
exp = info.get('session_expiration', 0)
|
|
65
|
-
exp_date = datetime(2001, 1, 1) + timedelta(seconds=exp)
|
|
66
|
-
if exp_date > datetime.now():
|
|
67
|
-
json.dump({"token": info["session_id"], "userId": uid}, sys.stdout)
|
|
68
|
-
sys.exit(0)
|
|
69
|
-
sys.exit(1)
|
|
70
|
-
except:
|
|
71
|
-
sys.exit(1)
|
|
72
|
-
`.trim(),
|
|
73
|
-
]);
|
|
74
|
-
const parsed = JSON.parse(stdout.trim());
|
|
75
|
-
if (parsed.token && parsed.userId) {
|
|
76
|
-
return parsed;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
catch {
|
|
80
|
-
// Keychain extraction failed — fall through
|
|
81
|
-
}
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
84
|
-
async function extractManualKeychainToken() {
|
|
85
|
-
try {
|
|
86
|
-
const { stdout } = await execFileAsync("security", [
|
|
87
|
-
"find-generic-password",
|
|
88
|
-
"-a",
|
|
89
|
-
"aria",
|
|
90
|
-
"-s",
|
|
91
|
-
"quip-token",
|
|
92
|
-
"-w",
|
|
93
|
-
]);
|
|
94
|
-
const token = stdout.trim();
|
|
95
|
-
return token || null;
|
|
96
|
-
}
|
|
97
|
-
catch {
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
async function extractPlaywrightToken(timeoutMs) {
|
|
102
|
-
const playwright = await import("playwright");
|
|
103
|
-
const browser = await playwright.chromium.launch({ headless: true });
|
|
104
|
-
try {
|
|
105
|
-
const context = await browser.newContext();
|
|
106
|
-
const page = await context.newPage();
|
|
107
|
-
const tokenPromise = new Promise((resolve, reject) => {
|
|
108
|
-
const timer = setTimeout(() => {
|
|
109
|
-
page.off("request", handleRequest);
|
|
110
|
-
reject(new Error("Timed out waiting for Quip API token via Playwright."));
|
|
111
|
-
}, timeoutMs);
|
|
112
|
-
const handleRequest = (request) => {
|
|
113
|
-
const url = request.url();
|
|
114
|
-
if (!url.includes("platform.quip.com"))
|
|
115
|
-
return;
|
|
116
|
-
const authHeader = request.headers()["authorization"];
|
|
117
|
-
if (!authHeader?.startsWith("Bearer "))
|
|
118
|
-
return;
|
|
119
|
-
clearTimeout(timer);
|
|
120
|
-
page.off("request", handleRequest);
|
|
121
|
-
resolve(authHeader.slice(7));
|
|
122
|
-
};
|
|
123
|
-
page.on("request", handleRequest);
|
|
124
|
-
});
|
|
125
|
-
await page.goto("https://quip.com", {
|
|
126
|
-
waitUntil: "domcontentloaded",
|
|
127
|
-
timeout: timeoutMs,
|
|
128
|
-
});
|
|
129
|
-
const token = await tokenPromise;
|
|
130
|
-
// Get user ID from /users/current
|
|
131
|
-
const resp = await context.request.get(`${QUIP_API_BASE}/users/current`, {
|
|
132
|
-
headers: { Authorization: `Bearer ${token}` },
|
|
133
|
-
});
|
|
134
|
-
const userData = (await resp.json());
|
|
135
|
-
const userId = typeof userData.id === "string" ? userData.id : "unknown";
|
|
136
|
-
await page.close().catch(() => undefined);
|
|
137
|
-
await context.close().catch(() => undefined);
|
|
138
|
-
await browser.close().catch(() => undefined);
|
|
139
|
-
return { token, userId };
|
|
140
|
-
}
|
|
141
|
-
catch (error) {
|
|
142
|
-
await browser.close().catch(() => undefined);
|
|
143
|
-
throw error;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
// ── Thread/document helpers ─────────────────────────────────────────
|
|
147
|
-
function toDocumentSummary(thread) {
|
|
148
|
-
return {
|
|
149
|
-
threadId: typeof thread.id === "string" ? thread.id : "",
|
|
150
|
-
title: typeof thread.title === "string" ? thread.title : "",
|
|
151
|
-
link: typeof thread.link === "string" ? thread.link : "",
|
|
152
|
-
updatedUsec: typeof thread.updated_usec === "number" ? thread.updated_usec : 0,
|
|
153
|
-
createdUsec: typeof thread.created_usec === "number" ? thread.created_usec : 0,
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
// ── Client factory ──────────────────────────────────────────────────
|
|
157
|
-
export async function createQuipDesktopClient(options) {
|
|
158
|
-
const timeoutMs = options?.bootstrapTimeoutMs ?? DEFAULT_BOOTSTRAP_TIMEOUT_MS;
|
|
159
|
-
// Priority 1: Keychain desktop token (auto from Quip desktop app)
|
|
160
|
-
let keychainResult = await extractKeychainDesktopToken();
|
|
161
|
-
// Priority 2: Playwright web session (SSO handles auth)
|
|
162
|
-
if (!keychainResult) {
|
|
163
|
-
try {
|
|
164
|
-
keychainResult = await extractPlaywrightToken(timeoutMs);
|
|
165
|
-
}
|
|
166
|
-
catch {
|
|
167
|
-
// Playwright extraction failed — fall through
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
// Priority 3: Manual keychain token
|
|
171
|
-
let token;
|
|
172
|
-
let userId;
|
|
173
|
-
if (keychainResult) {
|
|
174
|
-
token = keychainResult.token;
|
|
175
|
-
userId = keychainResult.userId;
|
|
176
|
-
}
|
|
177
|
-
else {
|
|
178
|
-
const manualToken = await extractManualKeychainToken();
|
|
179
|
-
if (!manualToken) {
|
|
180
|
-
throw new Error("No Quip token available. Install the Quip desktop app, or add a manual token:\n" +
|
|
181
|
-
' security add-generic-password -a aria -s quip-token -w "<token>"\n' +
|
|
182
|
-
"Get a token from https://quip.com/dev/token");
|
|
183
|
-
}
|
|
184
|
-
token = manualToken;
|
|
185
|
-
userId = "unknown";
|
|
186
|
-
}
|
|
187
|
-
// Verify token and resolve userId if unknown
|
|
188
|
-
const invokeApi = async (method, endpoint, body) => {
|
|
189
|
-
const url = `${QUIP_API_BASE}${endpoint}`;
|
|
190
|
-
const headers = {
|
|
191
|
-
Authorization: `Bearer ${token}`,
|
|
192
|
-
};
|
|
193
|
-
const fetchOptions = { method, headers };
|
|
194
|
-
if (body) {
|
|
195
|
-
headers["Content-Type"] = "application/x-www-form-urlencoded";
|
|
196
|
-
fetchOptions.body = new URLSearchParams(Object.entries(body).map(([k, v]) => [k, String(v)])).toString();
|
|
197
|
-
}
|
|
198
|
-
const resp = await fetch(url, fetchOptions);
|
|
199
|
-
const text = await resp.text();
|
|
200
|
-
let json;
|
|
201
|
-
try {
|
|
202
|
-
json = JSON.parse(text);
|
|
203
|
-
}
|
|
204
|
-
catch {
|
|
205
|
-
throw new Error(`Quip API ${endpoint} returned non-JSON (HTTP ${resp.status}).`);
|
|
206
|
-
}
|
|
207
|
-
if (!resp.ok) {
|
|
208
|
-
const errorCode = typeof json.error_code === "number" ? json.error_code : resp.status;
|
|
209
|
-
const errorMsg = typeof json.error_description === "string" ? json.error_description : `HTTP ${resp.status}`;
|
|
210
|
-
throw new Error(`Quip API ${endpoint} failed (${errorCode}): ${errorMsg}`);
|
|
211
|
-
}
|
|
212
|
-
return json;
|
|
213
|
-
};
|
|
214
|
-
// Resolve userId on first use if unknown
|
|
215
|
-
if (userId === "unknown") {
|
|
216
|
-
const user = await invokeApi("GET", "/users/current");
|
|
217
|
-
userId = typeof user.id === "string" ? user.id : "unknown";
|
|
218
|
-
}
|
|
219
|
-
return {
|
|
220
|
-
getUserId: () => userId,
|
|
221
|
-
listRecentDocuments: async ({ limit = 20 }) => {
|
|
222
|
-
const data = await invokeApi("GET", `/threads/recent?count=${Math.min(limit, 50)}`);
|
|
223
|
-
const threads = Array.isArray(data)
|
|
224
|
-
? data
|
|
225
|
-
: typeof data === "object" && data !== null
|
|
226
|
-
? Object.values(data)
|
|
227
|
-
: [];
|
|
228
|
-
const documents = [];
|
|
229
|
-
for (const entry of threads) {
|
|
230
|
-
if (!entry || typeof entry !== "object")
|
|
231
|
-
continue;
|
|
232
|
-
const thread = "thread" in entry
|
|
233
|
-
? entry.thread
|
|
234
|
-
: entry;
|
|
235
|
-
documents.push(toDocumentSummary(thread));
|
|
236
|
-
}
|
|
237
|
-
return { documents: documents.slice(0, limit) };
|
|
238
|
-
},
|
|
239
|
-
searchDocuments: async ({ query, limit = 20 }) => {
|
|
240
|
-
const params = new URLSearchParams({ query, count: String(Math.min(limit, 50)) });
|
|
241
|
-
const data = await invokeApi("GET", `/threads/search?${params}`);
|
|
242
|
-
const threads = Array.isArray(data)
|
|
243
|
-
? data
|
|
244
|
-
: typeof data === "object" && data !== null
|
|
245
|
-
? Object.values(data)
|
|
246
|
-
: [];
|
|
247
|
-
const documents = [];
|
|
248
|
-
for (const entry of threads) {
|
|
249
|
-
if (!entry || typeof entry !== "object")
|
|
250
|
-
continue;
|
|
251
|
-
const thread = "thread" in entry
|
|
252
|
-
? entry.thread
|
|
253
|
-
: entry;
|
|
254
|
-
documents.push(toDocumentSummary(thread));
|
|
255
|
-
}
|
|
256
|
-
return { documents: documents.slice(0, limit) };
|
|
257
|
-
},
|
|
258
|
-
readDocument: async ({ threadId }) => {
|
|
259
|
-
const data = await invokeApi("GET", `/threads/${threadId}`);
|
|
260
|
-
const thread = typeof data.thread === "object" && data.thread !== null
|
|
261
|
-
? data.thread
|
|
262
|
-
: data;
|
|
263
|
-
const rawHtml = typeof data.html === "string" ? data.html : "";
|
|
264
|
-
return {
|
|
265
|
-
threadId: typeof thread.id === "string" ? thread.id : threadId,
|
|
266
|
-
title: typeof thread.title === "string" ? thread.title : "",
|
|
267
|
-
link: typeof thread.link === "string" ? thread.link : "",
|
|
268
|
-
markdown: htmlToMarkdown(rawHtml),
|
|
269
|
-
updatedUsec: typeof thread.updated_usec === "number" ? thread.updated_usec : 0,
|
|
270
|
-
createdUsec: typeof thread.created_usec === "number" ? thread.created_usec : 0,
|
|
271
|
-
authorId: typeof thread.author_id === "string" ? thread.author_id : "",
|
|
272
|
-
};
|
|
273
|
-
},
|
|
274
|
-
createDocument: async ({ title, content, format = "markdown", folderId }) => {
|
|
275
|
-
const body = { title, content, format };
|
|
276
|
-
if (folderId)
|
|
277
|
-
body.member_ids = folderId;
|
|
278
|
-
const data = await invokeApi("POST", "/threads/new-document", body);
|
|
279
|
-
const thread = typeof data.thread === "object" && data.thread !== null
|
|
280
|
-
? data.thread
|
|
281
|
-
: data;
|
|
282
|
-
return {
|
|
283
|
-
threadId: typeof thread.id === "string" ? thread.id : "",
|
|
284
|
-
title: typeof thread.title === "string" ? thread.title : title,
|
|
285
|
-
link: typeof thread.link === "string" ? thread.link : "",
|
|
286
|
-
};
|
|
287
|
-
},
|
|
288
|
-
addComment: async ({ threadId, content }) => {
|
|
289
|
-
const data = await invokeApi("POST", "/messages/new", {
|
|
290
|
-
thread_id: threadId,
|
|
291
|
-
content,
|
|
292
|
-
});
|
|
293
|
-
return {
|
|
294
|
-
threadId,
|
|
295
|
-
commentId: typeof data.id === "string" ? data.id : "",
|
|
296
|
-
};
|
|
297
|
-
},
|
|
298
|
-
listComments: async ({ threadId }) => {
|
|
299
|
-
const data = await invokeApi("GET", `/messages/${threadId}`);
|
|
300
|
-
const rawMessages = Array.isArray(data) ? data : [];
|
|
301
|
-
const comments = rawMessages
|
|
302
|
-
.filter((m) => !!m && typeof m === "object")
|
|
303
|
-
.map((m) => ({
|
|
304
|
-
id: typeof m.id === "string" ? m.id : "",
|
|
305
|
-
authorId: typeof m.author_id === "string" ? m.author_id : "",
|
|
306
|
-
authorName: typeof m.author_name === "string" ? m.author_name : "",
|
|
307
|
-
text: typeof m.text === "string" ? m.text : "",
|
|
308
|
-
createdUsec: typeof m.created_usec === "number" ? m.created_usec : 0,
|
|
309
|
-
}));
|
|
310
|
-
return { threadId, comments };
|
|
311
|
-
},
|
|
312
|
-
close: async () => {
|
|
313
|
-
// No persistent resources to clean up (unlike Slack which keeps a browser open).
|
|
314
|
-
// Token-based client is stateless.
|
|
315
|
-
},
|
|
316
|
-
};
|
|
317
|
-
}
|
package/dist/registry/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { ToolRegistry, validateToolInput } from "./registry.js";
|