crewly 1.20.206 → 1.20.208
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/config/hooks/credential-guard/guard.sh +243 -0
- package/dist/backend/backend/src/constants.d.ts +63 -2
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +67 -1
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/agent-hooks/agent-hooks.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/agent-hooks/agent-hooks.controller.js +17 -1
- package/dist/backend/backend/src/controllers/agent-hooks/agent-hooks.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.d.ts +19 -5
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.js +71 -5
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.routes.js +4 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js +4 -0
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/session/session.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/session/session.controller.js +2 -0
- package/dist/backend/backend/src/controllers/session/session.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/workspace/workspace.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/workspace/workspace.routes.js +10 -2
- package/dist/backend/backend/src/controllers/workspace/workspace.routes.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts +8 -0
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +54 -2
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js +16 -2
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/codex-daemon.utils.d.ts +16 -0
- package/dist/backend/backend/src/services/agent/codex-daemon.utils.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/codex-daemon.utils.js +44 -0
- package/dist/backend/backend/src/services/agent/codex-daemon.utils.js.map +1 -1
- package/dist/backend/backend/src/services/agent/control-plane-guard.service.d.ts +14 -2
- package/dist/backend/backend/src/services/agent/control-plane-guard.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/control-plane-guard.service.js +18 -3
- package/dist/backend/backend/src/services/agent/control-plane-guard.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/credential-guard.service.d.ts +153 -0
- package/dist/backend/backend/src/services/agent/credential-guard.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/credential-guard.service.js +314 -0
- package/dist/backend/backend/src/services/agent/credential-guard.service.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js +5 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.d.ts +39 -0
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js +132 -3
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js.map +1 -1
- package/dist/backend/backend/src/services/core/credential-files.d.ts +26 -0
- package/dist/backend/backend/src/services/core/credential-files.d.ts.map +1 -0
- package/dist/backend/backend/src/services/core/credential-files.js +60 -0
- package/dist/backend/backend/src/services/core/credential-files.js.map +1 -0
- package/dist/backend/backend/src/services/google/docs.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/google/docs.service.js +14 -1
- package/dist/backend/backend/src/services/google/docs.service.js.map +1 -1
- package/dist/backend/backend/src/services/google/drive.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/google/drive.service.js +6 -4
- package/dist/backend/backend/src/services/google/drive.service.js.map +1 -1
- package/dist/backend/backend/src/services/google/google-api.client.d.ts +8 -3
- package/dist/backend/backend/src/services/google/google-api.client.d.ts.map +1 -1
- package/dist/backend/backend/src/services/google/google-api.client.js +5 -2
- package/dist/backend/backend/src/services/google/google-api.client.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/input-blocked-retry.service.d.ts +10 -0
- package/dist/backend/backend/src/services/messaging/input-blocked-retry.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/input-blocked-retry.service.js +16 -0
- package/dist/backend/backend/src/services/messaging/input-blocked-retry.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.d.ts +10 -0
- package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.js +21 -0
- package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.js.map +1 -1
- package/dist/backend/backend/src/services/monitoring/credential-guard-alerts.d.ts +68 -0
- package/dist/backend/backend/src/services/monitoring/credential-guard-alerts.d.ts.map +1 -0
- package/dist/backend/backend/src/services/monitoring/credential-guard-alerts.js +95 -0
- package/dist/backend/backend/src/services/monitoring/credential-guard-alerts.js.map +1 -0
- package/dist/backend/backend/src/services/session/input-ledger.d.ts +115 -0
- package/dist/backend/backend/src/services/session/input-ledger.d.ts.map +1 -0
- package/dist/backend/backend/src/services/session/input-ledger.js +144 -0
- package/dist/backend/backend/src/services/session/input-ledger.js.map +1 -0
- package/dist/backend/backend/src/services/session/session-command-helper.d.ts +26 -0
- package/dist/backend/backend/src/services/session/session-command-helper.d.ts.map +1 -1
- package/dist/backend/backend/src/services/session/session-command-helper.js +156 -37
- package/dist/backend/backend/src/services/session/session-command-helper.js.map +1 -1
- package/dist/backend/backend/src/services/session/tui-input-guard.d.ts +40 -0
- package/dist/backend/backend/src/services/session/tui-input-guard.d.ts.map +1 -1
- package/dist/backend/backend/src/services/session/tui-input-guard.js +95 -0
- package/dist/backend/backend/src/services/session/tui-input-guard.js.map +1 -1
- package/dist/backend/backend/src/websocket/terminal.gateway.d.ts.map +1 -1
- package/dist/backend/backend/src/websocket/terminal.gateway.js +4 -1
- package/dist/backend/backend/src/websocket/terminal.gateway.js.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +63 -2
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +67 -1
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.js +16 -2
- package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/codex-daemon.utils.d.ts +16 -0
- package/dist/cli/backend/src/services/agent/codex-daemon.utils.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/codex-daemon.utils.js +44 -0
- package/dist/cli/backend/src/services/agent/codex-daemon.utils.js.map +1 -1
- package/dist/cli/backend/src/services/agent/control-plane-guard.service.d.ts +14 -2
- package/dist/cli/backend/src/services/agent/control-plane-guard.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/control-plane-guard.service.js +18 -3
- package/dist/cli/backend/src/services/agent/control-plane-guard.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/credential-guard.service.d.ts +153 -0
- package/dist/cli/backend/src/services/agent/credential-guard.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/agent/credential-guard.service.js +314 -0
- package/dist/cli/backend/src/services/agent/credential-guard.service.js.map +1 -0
- package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js +5 -0
- package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.d.ts +39 -0
- package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.js +132 -3
- package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.js.map +1 -1
- package/dist/cli/backend/src/services/core/credential-files.d.ts +26 -0
- package/dist/cli/backend/src/services/core/credential-files.d.ts.map +1 -0
- package/dist/cli/backend/src/services/core/credential-files.js +60 -0
- package/dist/cli/backend/src/services/core/credential-files.js.map +1 -0
- package/dist/cli/backend/src/services/messaging/input-blocked-retry.service.d.ts +10 -0
- package/dist/cli/backend/src/services/messaging/input-blocked-retry.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/messaging/input-blocked-retry.service.js +16 -0
- package/dist/cli/backend/src/services/messaging/input-blocked-retry.service.js.map +1 -1
- package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.d.ts +10 -0
- package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.js +21 -0
- package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.js.map +1 -1
- package/dist/cli/backend/src/services/session/input-ledger.d.ts +115 -0
- package/dist/cli/backend/src/services/session/input-ledger.d.ts.map +1 -0
- package/dist/cli/backend/src/services/session/input-ledger.js +144 -0
- package/dist/cli/backend/src/services/session/input-ledger.js.map +1 -0
- package/dist/cli/backend/src/services/session/session-command-helper.d.ts +26 -0
- package/dist/cli/backend/src/services/session/session-command-helper.d.ts.map +1 -1
- package/dist/cli/backend/src/services/session/session-command-helper.js +156 -37
- package/dist/cli/backend/src/services/session/session-command-helper.js.map +1 -1
- package/dist/cli/backend/src/services/session/tui-input-guard.d.ts +40 -0
- package/dist/cli/backend/src/services/session/tui-input-guard.d.ts.map +1 -1
- package/dist/cli/backend/src/services/session/tui-input-guard.js +95 -0
- package/dist/cli/backend/src/services/session/tui-input-guard.js.map +1 -1
- package/dist/cli/backend/src/websocket/terminal.gateway.d.ts.map +1 -1
- package/dist/cli/backend/src/websocket/terminal.gateway.js +4 -1
- package/dist/cli/backend/src/websocket/terminal.gateway.js.map +1 -1
- package/package.json +1 -1
- package/packages/crewly-agent/src/runtime/credential-guard.test.ts +48 -0
- package/packages/crewly-agent/src/runtime/credential-guard.ts +56 -0
- package/packages/crewly-agent/src/runtime/tool-registry.ts +15 -0
- package/packages/crewly-agent/src/runtime/web-search.tool.test.ts +18 -0
- package/packages/crewly-agent/src/runtime/web-search.tool.ts +36 -14
|
@@ -52,6 +52,7 @@ function completionResult(summary: string, evidence: CompletionEvidenceInput | u
|
|
|
52
52
|
return { summary, ...(evidence && evidence.length > 0 ? { evidence } : {}) };
|
|
53
53
|
}
|
|
54
54
|
import { createWebSearchTool } from './web-search.tool.js';
|
|
55
|
+
import { checkCredentialAccess } from './credential-guard.js';
|
|
55
56
|
import { createComputerTool } from './computer.tool.js';
|
|
56
57
|
import { createDesktopTaskTool } from './desktop-task.tool.js';
|
|
57
58
|
import { checkInteractiveLoginCommand } from './interactive-login-guard.js';
|
|
@@ -1455,6 +1456,9 @@ export function createTools(client: CrewlyApiClient, sessionName: string, projec
|
|
|
1455
1456
|
}),
|
|
1456
1457
|
execute: async ({ file_path, offset, limit }) => {
|
|
1457
1458
|
const fp = expandPath(file_path as string, projectPath);
|
|
1459
|
+
// specs/2026-10-04-agent-credential-isolation.md: never Crewly's own credentials.
|
|
1460
|
+
const credentialRefusal = checkCredentialAccess('Read', { file_path: fp }, projectPath || process.cwd());
|
|
1461
|
+
if (credentialRefusal) return { success: false, error: credentialRefusal };
|
|
1458
1462
|
try {
|
|
1459
1463
|
// Check if this is an image file
|
|
1460
1464
|
const ext = fp.split('.').pop()?.toLowerCase() || '';
|
|
@@ -1543,6 +1547,8 @@ export function createTools(client: CrewlyApiClient, sessionName: string, projec
|
|
|
1543
1547
|
ignore: z.array(z.string()).optional().describe('Additional directory names to ignore (node_modules, .git, dist are always ignored)'),
|
|
1544
1548
|
}),
|
|
1545
1549
|
execute: async ({ pattern, path: searchPath, ignore }) => {
|
|
1550
|
+
const globRefusal = checkCredentialAccess('Glob', { pattern, path: searchPath ?? '' }, projectPath || process.cwd());
|
|
1551
|
+
if (globRefusal) return { success: false, error: globRefusal };
|
|
1546
1552
|
try {
|
|
1547
1553
|
const rootDir = expandPath((searchPath as string | undefined) || projectPath || process.cwd());
|
|
1548
1554
|
const stat = await fsPromises.stat(rootDir);
|
|
@@ -1589,6 +1595,8 @@ export function createTools(client: CrewlyApiClient, sessionName: string, projec
|
|
|
1589
1595
|
ignore: z.array(z.string()).optional().describe('Additional directory names to ignore'),
|
|
1590
1596
|
}),
|
|
1591
1597
|
execute: async ({ pattern: searchPattern, path: searchPath, file_pattern, context_lines, case_insensitive, max_matches, ignore }) => {
|
|
1598
|
+
const grepRefusal = checkCredentialAccess('Grep', { path: searchPath ?? '', glob: file_pattern ?? '' }, projectPath || process.cwd());
|
|
1599
|
+
if (grepRefusal) return { success: false, error: grepRefusal };
|
|
1592
1600
|
try {
|
|
1593
1601
|
const patternStr = searchPattern as string;
|
|
1594
1602
|
const flags = (case_insensitive as boolean) ? 'gi' : 'g';
|
|
@@ -1857,6 +1865,13 @@ export function createTools(client: CrewlyApiClient, sessionName: string, projec
|
|
|
1857
1865
|
execute: async ({ command, cwd, timeout }) => {
|
|
1858
1866
|
const cmd = command as string;
|
|
1859
1867
|
|
|
1868
|
+
// Crewly's own credentials are not available to agents
|
|
1869
|
+
// (specs/2026-10-04-agent-credential-isolation.md).
|
|
1870
|
+
const credentialRefusal = checkCredentialAccess('Bash', { command: cmd }, (cwd as string | undefined) || projectPath || process.cwd());
|
|
1871
|
+
if (credentialRefusal) {
|
|
1872
|
+
return { success: false, exitCode: 126, stdout: '', stderr: credentialRefusal, error: credentialRefusal };
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1860
1875
|
// Interactive harness logins die with this one-shot call; the owner's
|
|
1861
1876
|
// pasted code would go stale (2026-09-26). Point at harness-login.
|
|
1862
1877
|
const loginRefusal = checkInteractiveLoginCommand(cmd);
|
|
@@ -51,6 +51,24 @@ describe('createWebSearchTool', () => {
|
|
|
51
51
|
expect(result.error).toMatch(/Crewly Cloud is not connected/);
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
+
it('by default goes through the local backend with the agent badge, never a Cloud token', async () => {
|
|
55
|
+
const fetchSpy = vi.fn().mockResolvedValue(
|
|
56
|
+
jsonResponse({ success: true, answer: 'via backend', sources: [] }),
|
|
57
|
+
);
|
|
58
|
+
const tool = createWebSearchTool({
|
|
59
|
+
fetchImpl: fetchSpy as unknown as typeof fetch,
|
|
60
|
+
env: { CREWLY_SESSION_NAME: 'ruth', CREWLY_AGENT_BADGE: 'badge-1', CREWLY_API_URL: 'http://127.0.0.1:9999/' },
|
|
61
|
+
});
|
|
62
|
+
const result = (await tool.execute({ query: 'q' })) as { success: boolean; result?: string };
|
|
63
|
+
expect(result.success).toBe(true);
|
|
64
|
+
const [url, init] = fetchSpy.mock.calls[0] as [string, RequestInit];
|
|
65
|
+
expect(url).toBe('http://127.0.0.1:9999/api/cloud/search');
|
|
66
|
+
const headers = init.headers as Record<string, string>;
|
|
67
|
+
expect(headers['X-Agent-Session']).toBe('ruth');
|
|
68
|
+
expect(headers['X-Agent-Badge']).toBe('badge-1');
|
|
69
|
+
expect(headers.Authorization).toBeUndefined();
|
|
70
|
+
});
|
|
71
|
+
|
|
54
72
|
it('sends the query + bearer token to the configured endpoint', async () => {
|
|
55
73
|
const fetchSpy = vi.fn().mockResolvedValue(
|
|
56
74
|
jsonResponse({
|
|
@@ -15,9 +15,11 @@
|
|
|
15
15
|
|
|
16
16
|
import { z } from 'zod';
|
|
17
17
|
import type { ToolDefinition } from './types.js';
|
|
18
|
-
import {
|
|
18
|
+
import { CloudNotLoggedInError, type CloudConfig } from './cloud-config.js';
|
|
19
19
|
|
|
20
20
|
const SEARCH_PATH = '/api/v1/search';
|
|
21
|
+
/** The local backend's proxy for Cloud search (it holds the Cloud token; agents never see it). */
|
|
22
|
+
const BACKEND_SEARCH_PATH = '/api/cloud/search';
|
|
21
23
|
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
22
24
|
|
|
23
25
|
interface SearchSource {
|
|
@@ -35,13 +37,25 @@ interface SearchResponse {
|
|
|
35
37
|
|
|
36
38
|
/** Injectable IO for tests. */
|
|
37
39
|
export interface WebSearchDeps {
|
|
40
|
+
/**
|
|
41
|
+
* Direct mode: read the Cloud token and call Cloud. Only for tests and
|
|
42
|
+
* tools outside an agent. Without it the tool goes through the local
|
|
43
|
+
* backend (specs/2026-10-04-agent-credential-isolation.md): the Cloud
|
|
44
|
+
* credentials are sealed and are not available to agents.
|
|
45
|
+
*/
|
|
38
46
|
loadConfig?: () => Promise<CloudConfig>;
|
|
47
|
+
/** Backend base URL for the default mode (default CREWLY_API_URL or http://localhost:8787). */
|
|
48
|
+
apiBaseUrl?: string;
|
|
49
|
+
/** Environment for the agent's session + badge headers (default process.env). */
|
|
50
|
+
env?: NodeJS.ProcessEnv;
|
|
39
51
|
fetchImpl?: typeof fetch;
|
|
40
52
|
timeoutMs?: number;
|
|
41
53
|
}
|
|
42
54
|
|
|
43
55
|
export function createWebSearchTool(deps: WebSearchDeps = {}): ToolDefinition {
|
|
44
|
-
const loadConfig = deps.loadConfig
|
|
56
|
+
const loadConfig = deps.loadConfig;
|
|
57
|
+
const env = deps.env ?? process.env;
|
|
58
|
+
const apiBaseUrl = (deps.apiBaseUrl ?? env.CREWLY_API_URL ?? 'http://localhost:8787').replace(/\/$/, '');
|
|
45
59
|
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
46
60
|
const timeoutMs = deps.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
47
61
|
|
|
@@ -61,26 +75,34 @@ export function createWebSearchTool(deps: WebSearchDeps = {}): ToolDefinition {
|
|
|
61
75
|
execute: async (args) => {
|
|
62
76
|
const { query, max_results } = args as { query: string; max_results?: number };
|
|
63
77
|
|
|
64
|
-
let
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
78
|
+
let url: string;
|
|
79
|
+
const headers: Record<string, string> = { 'Content-Type': 'application/json' };
|
|
80
|
+
if (loadConfig) {
|
|
81
|
+
let config: CloudConfig;
|
|
82
|
+
try {
|
|
83
|
+
config = await loadConfig();
|
|
84
|
+
} catch (err) {
|
|
85
|
+
if (err instanceof CloudNotLoggedInError) {
|
|
86
|
+
return { success: false, error: err.message };
|
|
87
|
+
}
|
|
88
|
+
throw err;
|
|
70
89
|
}
|
|
71
|
-
|
|
90
|
+
url = `${config.cloudUrl}${SEARCH_PATH}`;
|
|
91
|
+
headers.Authorization = `Bearer ${config.token}`;
|
|
92
|
+
} else {
|
|
93
|
+
// Through the backend, identified by this agent's session + badge.
|
|
94
|
+
url = `${apiBaseUrl}${BACKEND_SEARCH_PATH}`;
|
|
95
|
+
if (env.CREWLY_SESSION_NAME) headers['X-Agent-Session'] = env.CREWLY_SESSION_NAME;
|
|
96
|
+
if (env.CREWLY_AGENT_BADGE) headers['X-Agent-Badge'] = env.CREWLY_AGENT_BADGE;
|
|
72
97
|
}
|
|
73
98
|
|
|
74
99
|
const controller = new AbortController();
|
|
75
100
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
76
101
|
let resp: Response;
|
|
77
102
|
try {
|
|
78
|
-
resp = await fetchImpl(
|
|
103
|
+
resp = await fetchImpl(url, {
|
|
79
104
|
method: 'POST',
|
|
80
|
-
headers
|
|
81
|
-
'Content-Type': 'application/json',
|
|
82
|
-
Authorization: `Bearer ${config.token}`,
|
|
83
|
-
},
|
|
105
|
+
headers,
|
|
84
106
|
body: JSON.stringify(
|
|
85
107
|
max_results !== undefined ? { query, max_results } : { query },
|
|
86
108
|
),
|