@steipete/oracle 0.9.0 → 0.11.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 +1 -1
- package/README.md +107 -49
- package/dist/bin/oracle-cli.js +551 -410
- package/dist/bin/oracle-mcp.js +2 -2
- package/dist/bin/oracle.js +165 -279
- package/dist/scripts/agent-send.js +31 -31
- package/dist/scripts/check.js +6 -6
- package/dist/scripts/debug/extract-chatgpt-response.js +10 -10
- package/dist/scripts/docs-list.js +30 -30
- package/dist/scripts/git-policy.js +25 -23
- package/dist/scripts/run-cli.js +8 -8
- package/dist/scripts/runner.js +203 -195
- package/dist/scripts/test-browser.js +21 -18
- package/dist/scripts/test-remote-chrome.js +20 -20
- package/dist/src/bridge/connection.js +18 -18
- package/dist/src/bridge/userConfigFile.js +7 -7
- package/dist/src/browser/actions/archiveConversation.js +224 -0
- package/dist/src/browser/actions/assistantResponse.js +175 -101
- package/dist/src/browser/actions/attachmentDataTransfer.js +49 -47
- package/dist/src/browser/actions/attachments.js +246 -150
- package/dist/src/browser/actions/deepResearch.js +662 -0
- package/dist/src/browser/actions/domEvents.js +2 -2
- package/dist/src/browser/actions/modelSelection.js +342 -119
- package/dist/src/browser/actions/navigation.js +183 -137
- package/dist/src/browser/actions/projectSources.js +491 -0
- package/dist/src/browser/actions/promptComposer.js +152 -91
- package/dist/src/browser/actions/remoteFileTransfer.js +10 -10
- package/dist/src/browser/actions/thinkingStatus.js +391 -0
- package/dist/src/browser/actions/thinkingTime.js +207 -110
- package/dist/src/browser/artifacts.js +150 -0
- package/dist/src/browser/attachRunning.js +31 -0
- package/dist/src/browser/chatgptImages.js +315 -0
- package/dist/src/browser/chromeLifecycle.js +276 -63
- package/dist/src/browser/config.js +59 -16
- package/dist/src/browser/constants.js +25 -12
- package/dist/src/browser/controlPlan.js +81 -0
- package/dist/src/browser/cookies.js +19 -19
- package/dist/src/browser/detect.js +250 -77
- package/dist/src/browser/domDebug.js +50 -1
- package/dist/src/browser/index.js +1559 -692
- package/dist/src/browser/liveTabs.js +434 -0
- package/dist/src/browser/modelStrategy.js +1 -1
- package/dist/src/browser/pageActions.js +5 -5
- package/dist/src/browser/policies.js +16 -13
- package/dist/src/browser/profileState.js +127 -42
- package/dist/src/browser/projectSourcesRunner.js +366 -0
- package/dist/src/browser/prompt.js +72 -42
- package/dist/src/browser/promptSummary.js +5 -5
- package/dist/src/browser/providerDomFlow.js +1 -1
- package/dist/src/browser/providers/chatgptDomProvider.js +9 -9
- package/dist/src/browser/providers/geminiDeepThinkDomProvider.js +51 -42
- package/dist/src/browser/providers/index.js +2 -2
- package/dist/src/browser/reattach.js +178 -73
- package/dist/src/browser/reattachHelpers.js +32 -27
- package/dist/src/browser/sessionRunner.js +89 -25
- package/dist/src/browser/tabLeaseRegistry.js +182 -0
- package/dist/src/browser/utils.js +9 -9
- package/dist/src/browserMode.js +1 -1
- package/dist/src/cli/bridge/claudeConfig.js +24 -20
- package/dist/src/cli/bridge/client.js +28 -20
- package/dist/src/cli/bridge/codexConfig.js +16 -16
- package/dist/src/cli/bridge/doctor.js +47 -39
- package/dist/src/cli/bridge/host.js +58 -56
- package/dist/src/cli/browserConfig.js +102 -48
- package/dist/src/cli/browserDefaults.js +51 -26
- package/dist/src/cli/browserTabs.js +228 -0
- package/dist/src/cli/bundleWarnings.js +1 -1
- package/dist/src/cli/clipboard.js +11 -2
- package/dist/src/cli/detach.js +2 -2
- package/dist/src/cli/dryRun.js +62 -26
- package/dist/src/cli/duplicatePromptGuard.js +12 -4
- package/dist/src/cli/engine.js +9 -9
- package/dist/src/cli/errorUtils.js +1 -1
- package/dist/src/cli/fileSize.js +3 -3
- package/dist/src/cli/format.js +2 -2
- package/dist/src/cli/help.js +28 -28
- package/dist/src/cli/hiddenAliases.js +3 -3
- package/dist/src/cli/markdownBundle.js +7 -7
- package/dist/src/cli/markdownRenderer.js +15 -15
- package/dist/src/cli/notifier.js +77 -67
- package/dist/src/cli/options.js +131 -106
- package/dist/src/cli/oscUtils.js +1 -1
- package/dist/src/cli/projectSources.js +116 -0
- package/dist/src/cli/promptRequirement.js +2 -2
- package/dist/src/cli/renderOutput.js +1 -1
- package/dist/src/cli/rootAlias.js +1 -1
- package/dist/src/cli/runOptions.js +32 -28
- package/dist/src/cli/sessionCommand.js +82 -21
- package/dist/src/cli/sessionDisplay.js +213 -87
- package/dist/src/cli/sessionLineage.js +6 -2
- package/dist/src/cli/sessionRunner.js +149 -95
- package/dist/src/cli/sessionTable.js +26 -23
- package/dist/src/cli/stdin.js +22 -0
- package/dist/src/cli/tagline.js +121 -124
- package/dist/src/cli/tui/index.js +139 -128
- package/dist/src/cli/writeOutputPath.js +5 -5
- package/dist/src/config.js +7 -7
- package/dist/src/gemini-web/browserSessionManager.js +19 -15
- package/dist/src/gemini-web/client.js +76 -70
- package/dist/src/gemini-web/executionMode.js +6 -8
- package/dist/src/gemini-web/executor.js +98 -93
- package/dist/src/gemini-web/index.js +1 -1
- package/dist/src/mcp/consultPresets.js +19 -0
- package/dist/src/mcp/server.js +18 -12
- package/dist/src/mcp/tools/consult.js +246 -67
- package/dist/src/mcp/tools/projectSources.js +123 -0
- package/dist/src/mcp/tools/sessionResources.js +12 -12
- package/dist/src/mcp/tools/sessions.js +26 -17
- package/dist/src/mcp/types.js +12 -5
- package/dist/src/mcp/utils.js +21 -8
- package/dist/src/oracle/background.js +15 -15
- package/dist/src/oracle/claude.js +53 -25
- package/dist/src/oracle/client.js +50 -41
- package/dist/src/oracle/config.js +96 -66
- package/dist/src/oracle/errors.js +38 -38
- package/dist/src/oracle/files.js +55 -46
- package/dist/src/oracle/finishLine.js +10 -8
- package/dist/src/oracle/format.js +3 -3
- package/dist/src/oracle/gemini.js +37 -33
- package/dist/src/oracle/logging.js +7 -7
- package/dist/src/oracle/markdown.js +28 -28
- package/dist/src/oracle/modelResolver.js +16 -16
- package/dist/src/oracle/multiModelRunner.js +12 -12
- package/dist/src/oracle/oscProgress.js +8 -8
- package/dist/src/oracle/promptAssembly.js +6 -3
- package/dist/src/oracle/request.js +16 -13
- package/dist/src/oracle/run.js +160 -135
- package/dist/src/oracle/runUtils.js +8 -5
- package/dist/src/oracle/tokenEstimate.js +6 -6
- package/dist/src/oracle/tokenStats.js +5 -5
- package/dist/src/oracle/tokenStringifier.js +5 -5
- package/dist/src/oracle.js +12 -12
- package/dist/src/oracleHome.js +3 -3
- package/dist/src/projectSources/plan.js +27 -0
- package/dist/src/projectSources/url.js +23 -0
- package/dist/src/remote/client.js +25 -25
- package/dist/src/remote/health.js +20 -20
- package/dist/src/remote/remoteServiceConfig.js +9 -9
- package/dist/src/remote/server.js +129 -118
- package/dist/src/sessionManager.js +78 -75
- package/dist/src/sessionStore.js +3 -3
- package/dist/src/version.js +10 -10
- package/dist/vendor/oracle-notifier/README.md +2 -0
- package/package.json +67 -62
- package/vendor/oracle-notifier/README.md +2 -0
- package/dist/markdansi/types/index.js +0 -4
- package/dist/oracle/bin/oracle-cli.js +0 -472
- package/dist/oracle/src/browser/actions/assistantResponse.js +0 -471
- package/dist/oracle/src/browser/actions/attachments.js +0 -82
- package/dist/oracle/src/browser/actions/modelSelection.js +0 -190
- package/dist/oracle/src/browser/actions/navigation.js +0 -75
- package/dist/oracle/src/browser/actions/promptComposer.js +0 -167
- package/dist/oracle/src/browser/chromeLifecycle.js +0 -104
- package/dist/oracle/src/browser/config.js +0 -33
- package/dist/oracle/src/browser/constants.js +0 -40
- package/dist/oracle/src/browser/cookies.js +0 -210
- package/dist/oracle/src/browser/domDebug.js +0 -36
- package/dist/oracle/src/browser/index.js +0 -331
- package/dist/oracle/src/browser/pageActions.js +0 -5
- package/dist/oracle/src/browser/prompt.js +0 -88
- package/dist/oracle/src/browser/promptSummary.js +0 -20
- package/dist/oracle/src/browser/sessionRunner.js +0 -80
- package/dist/oracle/src/browser/utils.js +0 -62
- package/dist/oracle/src/browserMode.js +0 -1
- package/dist/oracle/src/cli/browserConfig.js +0 -44
- package/dist/oracle/src/cli/dryRun.js +0 -59
- package/dist/oracle/src/cli/engine.js +0 -17
- package/dist/oracle/src/cli/errorUtils.js +0 -9
- package/dist/oracle/src/cli/help.js +0 -70
- package/dist/oracle/src/cli/markdownRenderer.js +0 -15
- package/dist/oracle/src/cli/options.js +0 -103
- package/dist/oracle/src/cli/promptRequirement.js +0 -14
- package/dist/oracle/src/cli/rootAlias.js +0 -30
- package/dist/oracle/src/cli/sessionCommand.js +0 -77
- package/dist/oracle/src/cli/sessionDisplay.js +0 -270
- package/dist/oracle/src/cli/sessionRunner.js +0 -94
- package/dist/oracle/src/heartbeat.js +0 -43
- package/dist/oracle/src/oracle/client.js +0 -48
- package/dist/oracle/src/oracle/config.js +0 -29
- package/dist/oracle/src/oracle/errors.js +0 -101
- package/dist/oracle/src/oracle/files.js +0 -220
- package/dist/oracle/src/oracle/format.js +0 -33
- package/dist/oracle/src/oracle/fsAdapter.js +0 -7
- package/dist/oracle/src/oracle/oscProgress.js +0 -60
- package/dist/oracle/src/oracle/request.js +0 -48
- package/dist/oracle/src/oracle/run.js +0 -444
- package/dist/oracle/src/oracle/tokenStats.js +0 -39
- package/dist/oracle/src/oracle/types.js +0 -1
- package/dist/oracle/src/oracle.js +0 -9
- package/dist/oracle/src/sessionManager.js +0 -205
- package/dist/oracle/src/version.js +0 -39
- package/dist/scripts/chrome/browser-tools.js +0 -295
- package/dist/src/browser/profileSync.js +0 -141
- /package/dist/{oracle/src/browser → src/projectSources}/types.js +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { z } from
|
|
2
|
-
import { getCliVersion } from
|
|
3
|
-
import { LoggingMessageNotificationParamsSchema } from
|
|
4
|
-
import { ensureBrowserAvailable, mapConsultToRunOptions } from
|
|
5
|
-
import { sessionStore } from
|
|
6
|
-
import { resolveRemoteServiceConfig } from
|
|
7
|
-
import { createRemoteBrowserExecutor } from
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { getCliVersion } from "../../version.js";
|
|
3
|
+
import { LoggingMessageNotificationParamsSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
4
|
+
import { ensureBrowserAvailable, mapConsultToRunOptions } from "../utils.js";
|
|
5
|
+
import { sessionStore } from "../../sessionStore.js";
|
|
6
|
+
import { resolveRemoteServiceConfig } from "../../remote/remoteServiceConfig.js";
|
|
7
|
+
import { createRemoteBrowserExecutor } from "../../remote/client.js";
|
|
8
8
|
async function readSessionLogTail(sessionId, maxBytes) {
|
|
9
9
|
try {
|
|
10
10
|
const log = await sessionStore.readLog(sessionId);
|
|
@@ -17,62 +17,85 @@ async function readSessionLogTail(sessionId, maxBytes) {
|
|
|
17
17
|
return null;
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
|
-
import { performSessionRun } from
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
20
|
+
import { performSessionRun } from "../../cli/sessionRunner.js";
|
|
21
|
+
import { runDryRunSummary } from "../../cli/dryRun.js";
|
|
22
|
+
import { CHATGPT_URL } from "../../browser/constants.js";
|
|
23
|
+
import { CONSULT_PRESETS, consultInputSchema } from "../types.js";
|
|
24
|
+
import { applyConsultPreset } from "../consultPresets.js";
|
|
25
|
+
import { loadUserConfig } from "../../config.js";
|
|
26
|
+
import { resolveNotificationSettings } from "../../cli/notifier.js";
|
|
27
|
+
import { mapModelToBrowserLabel, resolveBrowserModelLabel } from "../../cli/browserConfig.js";
|
|
26
28
|
// Use raw shapes so the MCP SDK (with its bundled Zod) wraps them and emits valid JSON Schema.
|
|
27
29
|
const consultInputShape = {
|
|
28
|
-
|
|
29
|
-
.
|
|
30
|
-
.
|
|
31
|
-
.describe('
|
|
30
|
+
preset: z
|
|
31
|
+
.enum(CONSULT_PRESETS)
|
|
32
|
+
.optional()
|
|
33
|
+
.describe('Optional MCP convenience preset. "chatgpt-pro-heavy" selects ChatGPT browser mode, the current Pro model alias, and Pro Extended thinking unless overridden.'),
|
|
34
|
+
prompt: z.string().min(1, "Prompt is required.").describe("User prompt to run."),
|
|
32
35
|
files: z
|
|
33
36
|
.array(z.string())
|
|
34
37
|
.default([])
|
|
35
|
-
.describe(
|
|
38
|
+
.describe("Optional file paths or glob patterns (like the CLI `--file`). Resolved relative to the MCP server working directory."),
|
|
36
39
|
model: z
|
|
37
40
|
.string()
|
|
38
41
|
.optional()
|
|
39
|
-
.describe(
|
|
42
|
+
.describe("Single model name/label. If `engine` is omitted, Oracle follows CLI defaults: config/ORACLE_ENGINE first, then `api` when OPENAI_API_KEY is set, otherwise `browser`. Prefer setting `engine` explicitly to avoid default surprises."),
|
|
40
43
|
models: z
|
|
41
44
|
.array(z.string())
|
|
42
45
|
.optional()
|
|
43
|
-
.describe(
|
|
46
|
+
.describe("Multi-model fan-out (API engine only). Cannot be combined with browser automation."),
|
|
44
47
|
engine: z
|
|
45
|
-
.enum([
|
|
48
|
+
.enum(["api", "browser"])
|
|
46
49
|
.optional()
|
|
47
|
-
.describe(
|
|
50
|
+
.describe("Execution engine. `api` uses OpenAI/other providers. `browser` automates the ChatGPT web UI (supports attachments and ChatGPT-only model labels). When omitted, Oracle follows CLI defaults: config/ORACLE_ENGINE first, then `api` when OPENAI_API_KEY is set, otherwise `browser`."),
|
|
48
51
|
browserModelLabel: z
|
|
49
52
|
.string()
|
|
50
53
|
.optional()
|
|
51
54
|
.describe('Browser-only: explicit ChatGPT UI label to select (overrides model mapping). Example: "GPT-5.2 Thinking".'),
|
|
52
55
|
browserAttachments: z
|
|
53
|
-
.enum([
|
|
56
|
+
.enum(["auto", "never", "always"])
|
|
54
57
|
.optional()
|
|
55
58
|
.describe('Browser-only: how to deliver `files`. Use "always" for real ChatGPT file uploads (including images/PDFs). Use "never" to paste file contents inline. "auto" chooses based on prompt size.'),
|
|
56
59
|
browserBundleFiles: z
|
|
57
60
|
.boolean()
|
|
58
61
|
.optional()
|
|
59
|
-
.describe(
|
|
62
|
+
.describe("Browser-only: bundle many files into a single upload (helps with upload limits)."),
|
|
60
63
|
browserThinkingTime: z
|
|
61
|
-
.enum([
|
|
64
|
+
.enum(["light", "standard", "extended", "heavy"])
|
|
65
|
+
.optional()
|
|
66
|
+
.describe("Browser-only: set ChatGPT thinking time when supported by the chosen model."),
|
|
67
|
+
browserModelStrategy: z
|
|
68
|
+
.enum(["select", "current", "ignore"])
|
|
62
69
|
.optional()
|
|
63
|
-
.describe(
|
|
70
|
+
.describe("Browser-only: model picker strategy. Mirrors the CLI --browser-model-strategy flag."),
|
|
71
|
+
browserResearchMode: z
|
|
72
|
+
.enum(["deep"])
|
|
73
|
+
.optional()
|
|
74
|
+
.describe("Browser-only: activate ChatGPT Deep Research mode for broad web research."),
|
|
75
|
+
browserArchive: z
|
|
76
|
+
.enum(["auto", "always", "never"])
|
|
77
|
+
.optional()
|
|
78
|
+
.describe('Browser-only: archive completed ChatGPT conversations after local artifacts are saved. "auto" archives successful non-project one-shots only.'),
|
|
79
|
+
browserFollowUps: z
|
|
80
|
+
.array(z.string())
|
|
81
|
+
.optional()
|
|
82
|
+
.describe("Browser-only: additional prompts to submit sequentially in the same ChatGPT conversation after the initial answer."),
|
|
64
83
|
browserKeepBrowser: z
|
|
65
84
|
.boolean()
|
|
66
85
|
.optional()
|
|
67
|
-
.describe(
|
|
86
|
+
.describe("Browser-only: keep Chrome running after completion (useful for debugging)."),
|
|
87
|
+
dryRun: z
|
|
88
|
+
.boolean()
|
|
89
|
+
.optional()
|
|
90
|
+
.describe("Preview the resolved Oracle run without creating a session or touching the browser."),
|
|
68
91
|
search: z
|
|
69
92
|
.boolean()
|
|
70
93
|
.optional()
|
|
71
|
-
.describe(
|
|
94
|
+
.describe("API-only: enable/disable the provider search tool (browser engine ignores this)."),
|
|
72
95
|
slug: z
|
|
73
96
|
.string()
|
|
74
97
|
.optional()
|
|
75
|
-
.describe(
|
|
98
|
+
.describe("Optional human-friendly session id (used for later `oracle sessions` lookups)."),
|
|
76
99
|
};
|
|
77
100
|
const consultModelSummaryShape = z.object({
|
|
78
101
|
model: z.string(),
|
|
@@ -103,10 +126,34 @@ const consultModelSummaryShape = z.object({
|
|
|
103
126
|
.optional(),
|
|
104
127
|
logPath: z.string().optional(),
|
|
105
128
|
});
|
|
129
|
+
const consultDryRunResolvedShape = z.object({
|
|
130
|
+
resolvedEngine: z.enum(["api", "browser"]),
|
|
131
|
+
model: z.string(),
|
|
132
|
+
models: z.array(z.string()).optional(),
|
|
133
|
+
files: z.array(z.string()),
|
|
134
|
+
followUpCount: z.number(),
|
|
135
|
+
browser: z
|
|
136
|
+
.object({
|
|
137
|
+
desiredModel: z.string().nullable().optional(),
|
|
138
|
+
thinkingTime: z.string().nullable().optional(),
|
|
139
|
+
modelStrategy: z.string().nullable().optional(),
|
|
140
|
+
researchMode: z.string().nullable().optional(),
|
|
141
|
+
attachments: z.string().optional(),
|
|
142
|
+
bundleFiles: z.boolean().optional(),
|
|
143
|
+
keepBrowser: z.boolean().optional(),
|
|
144
|
+
manualLogin: z.boolean().optional(),
|
|
145
|
+
profileDir: z.string().nullable().optional(),
|
|
146
|
+
chatgptUrl: z.string().nullable().optional(),
|
|
147
|
+
})
|
|
148
|
+
.optional(),
|
|
149
|
+
guidance: z.array(z.string()),
|
|
150
|
+
});
|
|
106
151
|
const consultOutputShape = {
|
|
107
|
-
sessionId: z.string(),
|
|
152
|
+
sessionId: z.string().optional(),
|
|
108
153
|
status: z.string(),
|
|
109
154
|
output: z.string(),
|
|
155
|
+
dryRun: z.boolean().optional(),
|
|
156
|
+
resolved: consultDryRunResolvedShape.optional(),
|
|
110
157
|
models: z.array(consultModelSummaryShape).optional(),
|
|
111
158
|
};
|
|
112
159
|
export function summarizeModelRunsForConsult(runs) {
|
|
@@ -129,7 +176,7 @@ export function summarizeModelRunsForConsult(runs) {
|
|
|
129
176
|
: undefined;
|
|
130
177
|
return {
|
|
131
178
|
model: run.model,
|
|
132
|
-
status: run.status ??
|
|
179
|
+
status: run.status ?? "unknown",
|
|
133
180
|
startedAt: run.startedAt,
|
|
134
181
|
completedAt: run.completedAt,
|
|
135
182
|
usage: run.usage,
|
|
@@ -139,17 +186,17 @@ export function summarizeModelRunsForConsult(runs) {
|
|
|
139
186
|
};
|
|
140
187
|
});
|
|
141
188
|
}
|
|
142
|
-
export function buildConsultBrowserConfig({ userConfig, env, runModel, inputModel, browserModelLabel, browserThinkingTime, browserKeepBrowser, }) {
|
|
189
|
+
export function buildConsultBrowserConfig({ userConfig, env, runModel, inputModel, browserModelLabel, browserThinkingTime, browserModelStrategy, browserResearchMode, browserArchive, browserKeepBrowser, }) {
|
|
143
190
|
const configuredBrowser = userConfig.browser ?? {};
|
|
144
|
-
const envProfileDir = (env.ORACLE_BROWSER_PROFILE_DIR ??
|
|
191
|
+
const envProfileDir = (env.ORACLE_BROWSER_PROFILE_DIR ?? "").trim();
|
|
145
192
|
const hasProfileDir = envProfileDir.length > 0;
|
|
146
193
|
const preferredLabel = (browserModelLabel ?? inputModel)?.trim();
|
|
147
|
-
const isChatGptModel = runModel.startsWith(
|
|
194
|
+
const isChatGptModel = runModel.startsWith("gpt-") && !runModel.includes("codex");
|
|
148
195
|
const desiredModelLabel = isChatGptModel
|
|
149
196
|
? mapModelToBrowserLabel(runModel)
|
|
150
197
|
: resolveBrowserModelLabel(preferredLabel, runModel);
|
|
151
198
|
const configuredUrl = configuredBrowser.chatgptUrl ?? configuredBrowser.url ?? CHATGPT_URL;
|
|
152
|
-
const manualLogin = hasProfileDir ? true : configuredBrowser.manualLogin ?? false;
|
|
199
|
+
const manualLogin = hasProfileDir ? true : (configuredBrowser.manualLogin ?? false);
|
|
153
200
|
return {
|
|
154
201
|
...configuredBrowser,
|
|
155
202
|
url: configuredUrl,
|
|
@@ -159,21 +206,112 @@ export function buildConsultBrowserConfig({ userConfig, env, runModel, inputMode
|
|
|
159
206
|
hideWindow: configuredBrowser.hideWindow ?? false,
|
|
160
207
|
keepBrowser: browserKeepBrowser ?? configuredBrowser.keepBrowser ?? false,
|
|
161
208
|
manualLogin,
|
|
162
|
-
manualLoginProfileDir: manualLogin
|
|
209
|
+
manualLoginProfileDir: manualLogin
|
|
210
|
+
? ((envProfileDir || configuredBrowser.manualLoginProfileDir) ?? null)
|
|
211
|
+
: null,
|
|
163
212
|
thinkingTime: browserThinkingTime ?? configuredBrowser.thinkingTime,
|
|
213
|
+
modelStrategy: browserModelStrategy ?? configuredBrowser.modelStrategy,
|
|
214
|
+
researchMode: browserResearchMode ?? configuredBrowser.researchMode,
|
|
215
|
+
archiveConversations: browserArchive ?? configuredBrowser.archiveConversations,
|
|
164
216
|
desiredModel: desiredModelLabel || mapModelToBrowserLabel(runModel),
|
|
165
217
|
};
|
|
166
218
|
}
|
|
219
|
+
export function buildConsultDryRunResolved({ resolvedEngine, runOptions, browserConfig, }) {
|
|
220
|
+
const guidance = [];
|
|
221
|
+
const followUpCount = runOptions.browserFollowUps?.filter((entry) => entry.trim()).length ?? 0;
|
|
222
|
+
if (resolvedEngine === "api") {
|
|
223
|
+
guidance.push('API engine requires provider credentials. If the operator has ChatGPT Pro but no API key, retry with engine:"browser" or preset:"chatgpt-pro-heavy".');
|
|
224
|
+
}
|
|
225
|
+
if (resolvedEngine === "browser") {
|
|
226
|
+
guidance.push("Browser engine uses the signed-in ChatGPT profile; run dryRun:true before live use.");
|
|
227
|
+
}
|
|
228
|
+
const desiredModel = browserConfig?.desiredModel ?? null;
|
|
229
|
+
const thinkingTime = browserConfig?.thinkingTime ?? null;
|
|
230
|
+
if (runOptions.model === "gpt-5.5-pro" && thinkingTime === "heavy") {
|
|
231
|
+
guidance.push('gpt-5.5-pro should normally use Pro Extended. Use model:"gpt-5.5" with browserThinkingTime:"heavy" only when you explicitly want Thinking Heavy.');
|
|
232
|
+
}
|
|
233
|
+
const chatgptUrl = browserConfig?.chatgptUrl ?? browserConfig?.url ?? null;
|
|
234
|
+
if (chatgptUrl?.includes("/project")) {
|
|
235
|
+
guidance.push("This ChatGPT project URL is persistent. Project Sources should be mutated only by the project_sources tool with confirmMutation:true.");
|
|
236
|
+
}
|
|
237
|
+
if (followUpCount > 0) {
|
|
238
|
+
guidance.push("This is a multi-turn browser consult; all follow-ups stay in one ChatGPT conversation.");
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
resolvedEngine,
|
|
242
|
+
model: runOptions.model,
|
|
243
|
+
models: runOptions.models,
|
|
244
|
+
files: runOptions.file ?? [],
|
|
245
|
+
followUpCount,
|
|
246
|
+
browser: resolvedEngine === "browser"
|
|
247
|
+
? {
|
|
248
|
+
desiredModel,
|
|
249
|
+
thinkingTime,
|
|
250
|
+
modelStrategy: browserConfig?.modelStrategy ?? null,
|
|
251
|
+
researchMode: browserConfig?.researchMode ?? null,
|
|
252
|
+
attachments: runOptions.browserAttachments,
|
|
253
|
+
bundleFiles: runOptions.browserBundleFiles,
|
|
254
|
+
keepBrowser: browserConfig?.keepBrowser,
|
|
255
|
+
manualLogin: browserConfig?.manualLogin,
|
|
256
|
+
profileDir: browserConfig?.manualLoginProfileDir ?? null,
|
|
257
|
+
chatgptUrl,
|
|
258
|
+
}
|
|
259
|
+
: undefined,
|
|
260
|
+
guidance,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
export function formatConsultDryRunResolved(details) {
|
|
264
|
+
const lines = [
|
|
265
|
+
"[dry-run] MCP resolved request:",
|
|
266
|
+
` engine: ${details.resolvedEngine}`,
|
|
267
|
+
` model: ${details.model}`,
|
|
268
|
+
];
|
|
269
|
+
if (details.models && details.models.length > 0) {
|
|
270
|
+
lines.push(` models: ${details.models.join(", ")}`);
|
|
271
|
+
}
|
|
272
|
+
lines.push(` files: ${details.files.length}`);
|
|
273
|
+
if (details.browser) {
|
|
274
|
+
lines.push(` browser desired model: ${details.browser.desiredModel ?? "(default)"}`);
|
|
275
|
+
lines.push(` browser thinking time: ${details.browser.thinkingTime ?? "(default)"}`);
|
|
276
|
+
lines.push(` browser model strategy: ${details.browser.modelStrategy ?? "(default)"}`);
|
|
277
|
+
lines.push(` browser research mode: ${details.browser.researchMode ?? "off"}`);
|
|
278
|
+
lines.push(` browser attachments: ${details.browser.attachments ?? "auto"}`);
|
|
279
|
+
lines.push(` browser bundle files: ${details.browser.bundleFiles ? "yes" : "no"}`);
|
|
280
|
+
lines.push(` browser keep browser: ${details.browser.keepBrowser ? "yes" : "no"}`);
|
|
281
|
+
lines.push(` browser manual login: ${details.browser.manualLogin ? "yes" : "no"}`);
|
|
282
|
+
if (details.browser.profileDir) {
|
|
283
|
+
lines.push(` browser profile: ${details.browser.profileDir}`);
|
|
284
|
+
}
|
|
285
|
+
if (details.browser.chatgptUrl) {
|
|
286
|
+
lines.push(` ChatGPT URL: ${details.browser.chatgptUrl}`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
lines.push(` follow-ups: ${details.followUpCount}`);
|
|
290
|
+
for (const guidance of details.guidance) {
|
|
291
|
+
lines.push(` guidance: ${guidance}`);
|
|
292
|
+
}
|
|
293
|
+
return lines;
|
|
294
|
+
}
|
|
167
295
|
export function registerConsultTool(server) {
|
|
168
|
-
server.registerTool(
|
|
169
|
-
title:
|
|
170
|
-
description: 'Run
|
|
296
|
+
server.registerTool("consult", {
|
|
297
|
+
title: "Run an oracle session",
|
|
298
|
+
description: 'Run an Oracle session (API or ChatGPT browser automation). Use `files` to attach project context. If `engine` is omitted, Oracle follows CLI defaults: config/ORACLE_ENGINE first, then API when OPENAI_API_KEY is set, otherwise browser. Browser GPT-5.5 Pro consults can take many minutes; use `dryRun:true` first when configuring an agent and inspect `sessions`/`oracle status` before retrying. For browser-based image/file uploads, set `browserAttachments:"always"`. Browser consults can include `browserFollowUps` for a multi-turn ChatGPT review in one conversation. Sessions are stored under `ORACLE_HOME_DIR` (shared with the CLI).',
|
|
171
299
|
// Cast to any to satisfy SDK typings across differing Zod versions.
|
|
172
300
|
inputSchema: consultInputShape,
|
|
173
301
|
outputSchema: consultOutputShape,
|
|
174
302
|
}, async (input) => {
|
|
175
|
-
const textContent = (text) => [{ type:
|
|
176
|
-
|
|
303
|
+
const textContent = (text) => [{ type: "text", text }];
|
|
304
|
+
let parsedInput;
|
|
305
|
+
try {
|
|
306
|
+
parsedInput = applyConsultPreset(consultInputSchema.parse(input));
|
|
307
|
+
}
|
|
308
|
+
catch (error) {
|
|
309
|
+
return {
|
|
310
|
+
isError: true,
|
|
311
|
+
content: textContent(error instanceof Error ? error.message : String(error)),
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
const { prompt, files, model, models, engine, search, browserModelLabel, browserAttachments, browserBundleFiles, browserThinkingTime, browserModelStrategy, browserResearchMode, browserArchive, browserFollowUps, browserKeepBrowser, dryRun, slug, } = parsedInput;
|
|
177
315
|
const { config: userConfig } = await loadUserConfig();
|
|
178
316
|
const { runOptions, resolvedEngine } = mapConsultToRunOptions({
|
|
179
317
|
prompt,
|
|
@@ -184,20 +322,77 @@ export function registerConsultTool(server) {
|
|
|
184
322
|
search,
|
|
185
323
|
browserAttachments,
|
|
186
324
|
browserBundleFiles,
|
|
325
|
+
browserFollowUps,
|
|
187
326
|
userConfig,
|
|
188
327
|
env: process.env,
|
|
189
328
|
});
|
|
190
329
|
const cwd = process.cwd();
|
|
330
|
+
const sendLog = (text, level = "info") => server.server
|
|
331
|
+
.sendLoggingMessage(LoggingMessageNotificationParamsSchema.parse({
|
|
332
|
+
level,
|
|
333
|
+
data: { text, bytes: Buffer.byteLength(text, "utf8") },
|
|
334
|
+
}))
|
|
335
|
+
.catch(() => { });
|
|
191
336
|
const resolvedRemote = resolveRemoteServiceConfig({ userConfig, env: process.env });
|
|
192
|
-
|
|
193
|
-
if (resolvedEngine ===
|
|
337
|
+
let browserConfig;
|
|
338
|
+
if (resolvedEngine === "browser") {
|
|
339
|
+
browserConfig = buildConsultBrowserConfig({
|
|
340
|
+
userConfig,
|
|
341
|
+
env: process.env,
|
|
342
|
+
runModel: runOptions.model,
|
|
343
|
+
inputModel: model,
|
|
344
|
+
browserModelLabel,
|
|
345
|
+
browserThinkingTime,
|
|
346
|
+
browserModelStrategy,
|
|
347
|
+
browserResearchMode,
|
|
348
|
+
browserArchive,
|
|
349
|
+
browserKeepBrowser,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
if (dryRun) {
|
|
353
|
+
const lines = [];
|
|
354
|
+
const log = (line) => {
|
|
355
|
+
lines.push(line);
|
|
356
|
+
sendLog(line);
|
|
357
|
+
};
|
|
358
|
+
const resolved = buildConsultDryRunResolved({
|
|
359
|
+
resolvedEngine,
|
|
360
|
+
runOptions,
|
|
361
|
+
browserConfig,
|
|
362
|
+
});
|
|
363
|
+
await runDryRunSummary({
|
|
364
|
+
engine: resolvedEngine,
|
|
365
|
+
runOptions,
|
|
366
|
+
cwd,
|
|
367
|
+
version: getCliVersion(),
|
|
368
|
+
log,
|
|
369
|
+
browserConfig,
|
|
370
|
+
});
|
|
371
|
+
for (const line of formatConsultDryRunResolved(resolved)) {
|
|
372
|
+
log(line);
|
|
373
|
+
}
|
|
374
|
+
const output = lines.join("\n").trim();
|
|
375
|
+
return {
|
|
376
|
+
content: textContent(output),
|
|
377
|
+
structuredContent: {
|
|
378
|
+
status: "dry-run",
|
|
379
|
+
output,
|
|
380
|
+
dryRun: true,
|
|
381
|
+
resolved,
|
|
382
|
+
},
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
const browserGuard = ensureBrowserAvailable(resolvedEngine, {
|
|
386
|
+
remoteHost: resolvedRemote.host,
|
|
387
|
+
});
|
|
388
|
+
if (resolvedEngine === "browser" && browserGuard) {
|
|
194
389
|
return {
|
|
195
390
|
isError: true,
|
|
196
391
|
content: textContent(browserGuard),
|
|
197
392
|
};
|
|
198
393
|
}
|
|
199
394
|
let browserDeps;
|
|
200
|
-
if (resolvedEngine ===
|
|
395
|
+
if (resolvedEngine === "browser" && resolvedRemote.host) {
|
|
201
396
|
if (!resolvedRemote.token) {
|
|
202
397
|
return {
|
|
203
398
|
isError: true,
|
|
@@ -205,21 +400,12 @@ export function registerConsultTool(server) {
|
|
|
205
400
|
};
|
|
206
401
|
}
|
|
207
402
|
browserDeps = {
|
|
208
|
-
executeBrowser: createRemoteBrowserExecutor({
|
|
403
|
+
executeBrowser: createRemoteBrowserExecutor({
|
|
404
|
+
host: resolvedRemote.host,
|
|
405
|
+
token: resolvedRemote.token,
|
|
406
|
+
}),
|
|
209
407
|
};
|
|
210
408
|
}
|
|
211
|
-
let browserConfig;
|
|
212
|
-
if (resolvedEngine === 'browser') {
|
|
213
|
-
browserConfig = buildConsultBrowserConfig({
|
|
214
|
-
userConfig,
|
|
215
|
-
env: process.env,
|
|
216
|
-
runModel: runOptions.model,
|
|
217
|
-
inputModel: model,
|
|
218
|
-
browserModelLabel,
|
|
219
|
-
browserThinkingTime,
|
|
220
|
-
browserKeepBrowser,
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
409
|
const notifications = resolveNotificationSettings({
|
|
224
410
|
cliNotify: undefined,
|
|
225
411
|
cliNotifySound: undefined,
|
|
@@ -234,13 +420,6 @@ export function registerConsultTool(server) {
|
|
|
234
420
|
waitPreference: true,
|
|
235
421
|
}, cwd, notifications);
|
|
236
422
|
const logWriter = sessionStore.createLogWriter(sessionMeta.id);
|
|
237
|
-
// Best-effort: emit MCP logging notifications for live chunks but never block the run.
|
|
238
|
-
const sendLog = (text, level = 'info') => server.server
|
|
239
|
-
.sendLoggingMessage(LoggingMessageNotificationParamsSchema.parse({
|
|
240
|
-
level,
|
|
241
|
-
data: { text, bytes: Buffer.byteLength(text, 'utf8') },
|
|
242
|
-
}))
|
|
243
|
-
.catch(() => { });
|
|
244
423
|
// Stream logs to both the session log and MCP logging notifications, but avoid buffering in memory
|
|
245
424
|
const log = (line) => {
|
|
246
425
|
logWriter.logLine(line);
|
|
@@ -250,7 +429,7 @@ export function registerConsultTool(server) {
|
|
|
250
429
|
};
|
|
251
430
|
const write = (chunk) => {
|
|
252
431
|
logWriter.writeChunk(chunk);
|
|
253
|
-
sendLog(chunk,
|
|
432
|
+
sendLog(chunk, "debug");
|
|
254
433
|
return true;
|
|
255
434
|
};
|
|
256
435
|
try {
|
|
@@ -284,11 +463,11 @@ export function registerConsultTool(server) {
|
|
|
284
463
|
const logTail = await readSessionLogTail(sessionMeta.id, 4000);
|
|
285
464
|
const modelsSummary = summarizeModelRunsForConsult(finalMeta.models);
|
|
286
465
|
return {
|
|
287
|
-
content: textContent([summary, logTail ||
|
|
466
|
+
content: textContent([summary, logTail || "(log empty)"].join("\n").trim()),
|
|
288
467
|
structuredContent: {
|
|
289
468
|
sessionId: sessionMeta.id,
|
|
290
469
|
status: finalMeta.status,
|
|
291
|
-
output: logTail ??
|
|
470
|
+
output: logTail ?? "",
|
|
292
471
|
models: modelsSummary,
|
|
293
472
|
},
|
|
294
473
|
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { loadUserConfig } from "../../config.js";
|
|
3
|
+
import { resolveRemoteServiceConfig } from "../../remote/remoteServiceConfig.js";
|
|
4
|
+
import { runBrowserProjectSources } from "../../browser/projectSourcesRunner.js";
|
|
5
|
+
import { normalizeProjectSourcesUrl } from "../../projectSources/url.js";
|
|
6
|
+
import { buildProjectSourcesBrowserConfig, resolveProjectSourceFiles, } from "../../cli/projectSources.js";
|
|
7
|
+
import { resolveConfiguredMaxFileSizeBytes } from "../../cli/fileSize.js";
|
|
8
|
+
const projectSourceEntryShape = z.object({
|
|
9
|
+
name: z.string(),
|
|
10
|
+
index: z.number(),
|
|
11
|
+
status: z.enum(["ready", "processing", "unknown"]).optional(),
|
|
12
|
+
});
|
|
13
|
+
const projectSourceUploadPlanShape = z.object({
|
|
14
|
+
path: z.string(),
|
|
15
|
+
displayPath: z.string(),
|
|
16
|
+
name: z.string(),
|
|
17
|
+
sizeBytes: z.number().optional(),
|
|
18
|
+
batch: z.number(),
|
|
19
|
+
});
|
|
20
|
+
const projectSourcesInputShape = {
|
|
21
|
+
operation: z
|
|
22
|
+
.enum(["list", "add"])
|
|
23
|
+
.describe("Project Sources operation. v1 intentionally supports only non-destructive list/add."),
|
|
24
|
+
chatgptUrl: z
|
|
25
|
+
.string()
|
|
26
|
+
.optional()
|
|
27
|
+
.describe("ChatGPT project URL ending in /project. Falls back to browser.chatgptUrl config."),
|
|
28
|
+
files: z
|
|
29
|
+
.array(z.string())
|
|
30
|
+
.default([])
|
|
31
|
+
.describe("Local file paths or globs to add as persistent ChatGPT Project Sources."),
|
|
32
|
+
dryRun: z
|
|
33
|
+
.boolean()
|
|
34
|
+
.optional()
|
|
35
|
+
.describe("Validate files and return an upload plan without touching the browser."),
|
|
36
|
+
confirmMutation: z
|
|
37
|
+
.boolean()
|
|
38
|
+
.optional()
|
|
39
|
+
.describe("Required for mutating add operations so agents do not modify project state accidentally."),
|
|
40
|
+
browserKeepBrowser: z.boolean().optional().describe("Keep Chrome running after completion."),
|
|
41
|
+
};
|
|
42
|
+
const projectSourcesOutputShape = {
|
|
43
|
+
status: z.enum(["ok", "dry-run"]),
|
|
44
|
+
operation: z.enum(["list", "add"]),
|
|
45
|
+
projectUrl: z.string(),
|
|
46
|
+
dryRun: z.boolean(),
|
|
47
|
+
sourcesBefore: z.array(projectSourceEntryShape).optional(),
|
|
48
|
+
sourcesAfter: z.array(projectSourceEntryShape).optional(),
|
|
49
|
+
plannedUploads: z.array(projectSourceUploadPlanShape).optional(),
|
|
50
|
+
added: z.array(projectSourceEntryShape).optional(),
|
|
51
|
+
warnings: z.array(z.string()),
|
|
52
|
+
tookMs: z.number(),
|
|
53
|
+
};
|
|
54
|
+
const projectSourcesInputSchema = z.object(projectSourcesInputShape);
|
|
55
|
+
export function registerProjectSourcesTool(server) {
|
|
56
|
+
server.registerTool("project_sources", {
|
|
57
|
+
title: "Manage ChatGPT Project Sources",
|
|
58
|
+
description: "List or append files to a ChatGPT Project's persistent Sources tab. This is useful for Developer Mode workflows where chats do not share memory, but explicit project sources provide shared context. Destructive delete/replace/sync operations are intentionally not included in v1.",
|
|
59
|
+
inputSchema: projectSourcesInputShape,
|
|
60
|
+
outputSchema: projectSourcesOutputShape,
|
|
61
|
+
}, async (input) => {
|
|
62
|
+
const textContent = (text) => [{ type: "text", text }];
|
|
63
|
+
let parsed;
|
|
64
|
+
try {
|
|
65
|
+
parsed = projectSourcesInputSchema.parse(input);
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
return {
|
|
69
|
+
isError: true,
|
|
70
|
+
content: textContent(error instanceof Error ? error.message : String(error)),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const { config: userConfig } = await loadUserConfig();
|
|
74
|
+
const resolvedRemote = resolveRemoteServiceConfig({ userConfig, env: process.env });
|
|
75
|
+
if (resolvedRemote.host) {
|
|
76
|
+
return {
|
|
77
|
+
isError: true,
|
|
78
|
+
content: textContent("project_sources v1 must run on the signed-in browser host; remote oracle serve support is not enabled yet."),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const projectUrl = normalizeProjectSourcesUrl(parsed.chatgptUrl ?? userConfig.browser?.chatgptUrl ?? userConfig.browser?.url ?? "");
|
|
82
|
+
if (parsed.operation === "add" && !parsed.dryRun && parsed.confirmMutation !== true) {
|
|
83
|
+
return {
|
|
84
|
+
isError: true,
|
|
85
|
+
content: textContent("project_sources add modifies persistent ChatGPT Project Sources. Retry with `confirmMutation: true` or use `dryRun: true` first."),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const maxFileSizeBytes = resolveConfiguredMaxFileSizeBytes(userConfig, process.env);
|
|
89
|
+
const files = parsed.operation === "add"
|
|
90
|
+
? await resolveProjectSourceFiles(parsed.files ?? [], {
|
|
91
|
+
cwd: process.cwd(),
|
|
92
|
+
maxFileSizeBytes,
|
|
93
|
+
})
|
|
94
|
+
: [];
|
|
95
|
+
const browserConfig = await buildProjectSourcesBrowserConfig({
|
|
96
|
+
options: {
|
|
97
|
+
chatgptUrl: projectUrl,
|
|
98
|
+
browserKeepBrowser: parsed.browserKeepBrowser,
|
|
99
|
+
},
|
|
100
|
+
projectUrl,
|
|
101
|
+
configuredBrowser: userConfig.browser ?? {},
|
|
102
|
+
});
|
|
103
|
+
const result = await runBrowserProjectSources({
|
|
104
|
+
operation: parsed.operation,
|
|
105
|
+
chatgptUrl: projectUrl,
|
|
106
|
+
files,
|
|
107
|
+
dryRun: parsed.dryRun,
|
|
108
|
+
config: browserConfig,
|
|
109
|
+
log: (message) => {
|
|
110
|
+
server.server
|
|
111
|
+
.sendLoggingMessage({ level: "info", data: { text: message } })
|
|
112
|
+
.catch(() => undefined);
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
const output = result.status === "dry-run"
|
|
116
|
+
? `Project Sources ${result.operation} dry run: ${result.plannedUploads?.length ?? 0} planned upload(s).`
|
|
117
|
+
: `Project Sources ${result.operation} completed: ${result.sourcesAfter?.length ?? 0} source(s).`;
|
|
118
|
+
return {
|
|
119
|
+
content: textContent(output),
|
|
120
|
+
structuredContent: result,
|
|
121
|
+
};
|
|
122
|
+
});
|
|
123
|
+
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { ResourceTemplate } from
|
|
2
|
-
import fs from
|
|
3
|
-
import { sessionStore } from
|
|
1
|
+
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import { sessionStore } from "../../sessionStore.js";
|
|
4
4
|
// URIs:
|
|
5
5
|
// - oracle-session://<id>/metadata
|
|
6
6
|
// - oracle-session://<id>/log
|
|
7
7
|
// - oracle-session://<id>/request
|
|
8
8
|
export function registerSessionResources(server) {
|
|
9
|
-
const template = new ResourceTemplate(
|
|
10
|
-
server.registerResource(
|
|
11
|
-
title:
|
|
12
|
-
description:
|
|
9
|
+
const template = new ResourceTemplate("oracle-session://{id}/{kind}", { list: undefined });
|
|
10
|
+
server.registerResource("oracle-session", template, {
|
|
11
|
+
title: "oracle session resources",
|
|
12
|
+
description: "Read stored session metadata, log, or request payload.",
|
|
13
13
|
}, async (uri, variables) => {
|
|
14
14
|
const idRaw = variables?.id;
|
|
15
15
|
const kindRaw = variables?.kind;
|
|
@@ -17,10 +17,10 @@ export function registerSessionResources(server) {
|
|
|
17
17
|
const id = Array.isArray(idRaw) ? idRaw[0] : idRaw;
|
|
18
18
|
const kind = Array.isArray(kindRaw) ? kindRaw[0] : kindRaw;
|
|
19
19
|
if (!id || !kind) {
|
|
20
|
-
throw new Error(
|
|
20
|
+
throw new Error("Missing id or kind");
|
|
21
21
|
}
|
|
22
22
|
switch (kind) {
|
|
23
|
-
case
|
|
23
|
+
case "metadata": {
|
|
24
24
|
const metadata = await sessionStore.readSession(id);
|
|
25
25
|
if (!metadata) {
|
|
26
26
|
throw new Error(`Session "${id}" not found.`);
|
|
@@ -34,7 +34,7 @@ export function registerSessionResources(server) {
|
|
|
34
34
|
],
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
|
-
case
|
|
37
|
+
case "log": {
|
|
38
38
|
const log = await sessionStore.readLog(id);
|
|
39
39
|
return {
|
|
40
40
|
contents: [
|
|
@@ -45,7 +45,7 @@ export function registerSessionResources(server) {
|
|
|
45
45
|
],
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
|
-
case
|
|
48
|
+
case "request": {
|
|
49
49
|
const request = await sessionStore.readRequest(id);
|
|
50
50
|
if (request) {
|
|
51
51
|
return {
|
|
@@ -58,7 +58,7 @@ export function registerSessionResources(server) {
|
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
60
|
const paths = await sessionStore.getPaths(id);
|
|
61
|
-
const raw = await fs.readFile(paths.request,
|
|
61
|
+
const raw = await fs.readFile(paths.request, "utf8");
|
|
62
62
|
return {
|
|
63
63
|
contents: [
|
|
64
64
|
{
|