@steipete/oracle 0.9.0 → 0.10.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 +61 -48
- package/dist/bin/oracle-cli.js +455 -402
- 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/assistantResponse.js +149 -101
- package/dist/src/browser/actions/attachmentDataTransfer.js +49 -47
- package/dist/src/browser/actions/attachments.js +246 -150
- package/dist/src/browser/actions/domEvents.js +2 -2
- package/dist/src/browser/actions/modelSelection.js +275 -117
- package/dist/src/browser/actions/navigation.js +161 -137
- package/dist/src/browser/actions/promptComposer.js +100 -64
- package/dist/src/browser/actions/remoteFileTransfer.js +10 -10
- package/dist/src/browser/actions/thinkingTime.js +207 -110
- package/dist/src/browser/chromeLifecycle.js +62 -60
- package/dist/src/browser/config.js +34 -15
- package/dist/src/browser/constants.js +17 -12
- package/dist/src/browser/cookies.js +19 -19
- package/dist/src/browser/detect.js +62 -62
- package/dist/src/browser/domDebug.js +1 -1
- package/dist/src/browser/index.js +390 -295
- 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 +44 -39
- 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 +67 -34
- package/dist/src/browser/reattachHelpers.js +31 -26
- package/dist/src/browser/sessionRunner.js +37 -25
- package/dist/src/browser/utils.js +9 -9
- package/dist/src/browserMode.js +1 -1
- package/dist/src/cli/bridge/claudeConfig.js +16 -16
- 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 +62 -48
- package/dist/src/cli/browserDefaults.js +27 -26
- 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 +29 -25
- package/dist/src/cli/duplicatePromptGuard.js +3 -3
- 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 +127 -106
- package/dist/src/cli/oscUtils.js +1 -1
- 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 +31 -21
- package/dist/src/cli/sessionDisplay.js +95 -81
- package/dist/src/cli/sessionLineage.js +6 -2
- package/dist/src/cli/sessionRunner.js +103 -93
- 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/server.js +16 -12
- package/dist/src/mcp/tools/consult.js +51 -47
- package/dist/src/mcp/tools/sessionResources.js +12 -12
- package/dist/src/mcp/tools/sessions.js +26 -17
- package/dist/src/mcp/types.js +5 -5
- package/dist/src/mcp/utils.js +15 -7
- 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 +156 -134
- 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/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 +77 -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 +66 -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/types.js +0 -1
- 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/src/cli/dryRun.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import chalk from
|
|
2
|
-
import { MODEL_CONFIGS, TOKENIZER_OPTIONS, DEFAULT_SYSTEM_PROMPT, buildPrompt, readFiles, getFileTokenStats, printFileTokenStats, } from
|
|
3
|
-
import { isKnownModel } from
|
|
4
|
-
import { assembleBrowserPrompt } from
|
|
5
|
-
import { buildTokenEstimateSuffix, formatAttachmentLabel } from
|
|
6
|
-
import { buildCookiePlan } from
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { MODEL_CONFIGS, TOKENIZER_OPTIONS, DEFAULT_SYSTEM_PROMPT, buildPrompt, readFiles, getFileTokenStats, printFileTokenStats, } from "../oracle.js";
|
|
3
|
+
import { isKnownModel } from "../oracle/modelResolver.js";
|
|
4
|
+
import { assembleBrowserPrompt } from "../browser/prompt.js";
|
|
5
|
+
import { buildTokenEstimateSuffix, formatAttachmentLabel } from "../browser/promptSummary.js";
|
|
6
|
+
import { buildCookiePlan } from "../browser/policies.js";
|
|
7
7
|
export async function runDryRunSummary({ engine, runOptions, cwd, version, log, browserConfig, }, deps = {}) {
|
|
8
|
-
if (engine ===
|
|
8
|
+
if (engine === "browser") {
|
|
9
9
|
await runBrowserDryRun({ runOptions, cwd, version, log, browserConfig }, deps);
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
@@ -15,17 +15,19 @@ async function runApiDryRun({ runOptions, cwd, version, log, }, deps) {
|
|
|
15
15
|
const readFilesImpl = deps.readFilesImpl ?? readFiles;
|
|
16
16
|
const files = await readFilesImpl(runOptions.file ?? [], { cwd });
|
|
17
17
|
const systemPrompt = runOptions.system?.trim() || DEFAULT_SYSTEM_PROMPT;
|
|
18
|
-
const combinedPrompt = buildPrompt(runOptions.prompt ??
|
|
19
|
-
const modelConfig = isKnownModel(runOptions.model)
|
|
18
|
+
const combinedPrompt = buildPrompt(runOptions.prompt ?? "", files, cwd);
|
|
19
|
+
const modelConfig = isKnownModel(runOptions.model)
|
|
20
|
+
? MODEL_CONFIGS[runOptions.model]
|
|
21
|
+
: MODEL_CONFIGS["gpt-5.1"];
|
|
20
22
|
const tokenizer = modelConfig.tokenizer;
|
|
21
23
|
const estimatedInputTokens = tokenizer([
|
|
22
|
-
{ role:
|
|
23
|
-
{ role:
|
|
24
|
+
{ role: "system", content: systemPrompt },
|
|
25
|
+
{ role: "user", content: combinedPrompt },
|
|
24
26
|
], TOKENIZER_OPTIONS);
|
|
25
27
|
const headerLine = `[dry-run] Oracle (${version}) would call ${runOptions.model} with ~${estimatedInputTokens.toLocaleString()} tokens and ${files.length} files.`;
|
|
26
28
|
log(chalk.cyan(headerLine));
|
|
27
29
|
if (files.length === 0) {
|
|
28
|
-
log(chalk.dim(
|
|
30
|
+
log(chalk.dim("[dry-run] No files matched the provided --file patterns."));
|
|
29
31
|
return;
|
|
30
32
|
}
|
|
31
33
|
const inputBudget = runOptions.maxInput ?? modelConfig.inputLimit;
|
|
@@ -43,8 +45,8 @@ async function runBrowserDryRun({ runOptions, cwd, version, log, browserConfig,
|
|
|
43
45
|
const suffix = buildTokenEstimateSuffix(artifacts);
|
|
44
46
|
const headerLine = `[dry-run] Oracle (${version}) would launch browser mode (${runOptions.model}) with ~${artifacts.estimatedInputTokens.toLocaleString()} tokens${suffix}.`;
|
|
45
47
|
log(chalk.cyan(headerLine));
|
|
46
|
-
logBrowserCookieStrategy(browserConfig, log,
|
|
47
|
-
logBrowserFileSummary(artifacts, log,
|
|
48
|
+
logBrowserCookieStrategy(browserConfig, log, "dry-run");
|
|
49
|
+
logBrowserFileSummary(artifacts, log, "dry-run");
|
|
48
50
|
}
|
|
49
51
|
function logBrowserCookieStrategy(browserConfig, log, label) {
|
|
50
52
|
if (!browserConfig)
|
|
@@ -54,7 +56,9 @@ function logBrowserCookieStrategy(browserConfig, log, label) {
|
|
|
54
56
|
}
|
|
55
57
|
function logBrowserFileSummary(artifacts, log, label) {
|
|
56
58
|
if (artifacts.attachments.length > 0) {
|
|
57
|
-
const prefix = artifacts.bundled
|
|
59
|
+
const prefix = artifacts.bundled
|
|
60
|
+
? `[${label}] Bundled upload:`
|
|
61
|
+
: `[${label}] Attachments to upload:`;
|
|
58
62
|
log(chalk.bold(prefix));
|
|
59
63
|
artifacts.attachments.forEach((attachment) => {
|
|
60
64
|
log(` • ${formatAttachmentLabel(attachment)}`);
|
|
@@ -66,7 +70,7 @@ function logBrowserFileSummary(artifacts, log, label) {
|
|
|
66
70
|
}
|
|
67
71
|
if (artifacts.inlineFileCount > 0) {
|
|
68
72
|
log(chalk.bold(`[${label}] Inline file content:`));
|
|
69
|
-
log(` • ${artifacts.inlineFileCount} file${artifacts.inlineFileCount === 1 ?
|
|
73
|
+
log(` • ${artifacts.inlineFileCount} file${artifacts.inlineFileCount === 1 ? "" : "s"} pasted directly into the composer.`);
|
|
70
74
|
return;
|
|
71
75
|
}
|
|
72
76
|
log(chalk.dim(`[${label}] No files attached.`));
|
|
@@ -77,8 +81,8 @@ export async function runBrowserPreview({ runOptions, cwd, version, previewMode,
|
|
|
77
81
|
const suffix = buildTokenEstimateSuffix(artifacts);
|
|
78
82
|
const headerLine = `[preview] Oracle (${version}) browser mode (${runOptions.model}) with ~${artifacts.estimatedInputTokens.toLocaleString()} tokens${suffix}.`;
|
|
79
83
|
log(chalk.cyan(headerLine));
|
|
80
|
-
logBrowserFileSummary(artifacts, log,
|
|
81
|
-
if (previewMode ===
|
|
84
|
+
logBrowserFileSummary(artifacts, log, "preview");
|
|
85
|
+
if (previewMode === "json" || previewMode === "full") {
|
|
82
86
|
const attachmentSummary = artifacts.attachments.map((attachment) => ({
|
|
83
87
|
path: attachment.path,
|
|
84
88
|
displayPath: attachment.displayPath,
|
|
@@ -86,20 +90,20 @@ export async function runBrowserPreview({ runOptions, cwd, version, previewMode,
|
|
|
86
90
|
}));
|
|
87
91
|
const previewPayload = {
|
|
88
92
|
model: runOptions.model,
|
|
89
|
-
engine:
|
|
93
|
+
engine: "browser",
|
|
90
94
|
composerText: artifacts.composerText,
|
|
91
95
|
attachments: attachmentSummary,
|
|
92
96
|
inlineFileCount: artifacts.inlineFileCount,
|
|
93
97
|
bundled: artifacts.bundled,
|
|
94
98
|
tokenEstimate: artifacts.estimatedInputTokens,
|
|
95
99
|
};
|
|
96
|
-
log(
|
|
97
|
-
log(chalk.bold(
|
|
100
|
+
log("");
|
|
101
|
+
log(chalk.bold("Preview JSON"));
|
|
98
102
|
log(JSON.stringify(previewPayload, null, 2));
|
|
99
103
|
}
|
|
100
|
-
if (previewMode ===
|
|
101
|
-
log(
|
|
102
|
-
log(chalk.bold(
|
|
103
|
-
log(artifacts.composerText || chalk.dim(
|
|
104
|
+
if (previewMode === "full") {
|
|
105
|
+
log("");
|
|
106
|
+
log(chalk.bold("Composer Text"));
|
|
107
|
+
log(artifacts.composerText || chalk.dim("(empty prompt)"));
|
|
104
108
|
}
|
|
105
109
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import chalk from
|
|
1
|
+
import chalk from "chalk";
|
|
2
2
|
export async function shouldBlockDuplicatePrompt({ prompt, force, sessionStore, log = console.log, }) {
|
|
3
3
|
if (force)
|
|
4
4
|
return false;
|
|
5
5
|
const normalized = prompt?.trim();
|
|
6
6
|
if (!normalized)
|
|
7
7
|
return false;
|
|
8
|
-
const running = (await sessionStore.listSessions()).filter((entry) => entry.status ===
|
|
9
|
-
const duplicate = running.find((entry) => (entry.options?.prompt?.trim?.() ??
|
|
8
|
+
const running = (await sessionStore.listSessions()).filter((entry) => entry.status === "running");
|
|
9
|
+
const duplicate = running.find((entry) => (entry.options?.prompt?.trim?.() ?? "") === normalized);
|
|
10
10
|
if (!duplicate)
|
|
11
11
|
return false;
|
|
12
12
|
log(chalk.yellow(`A session with the same prompt is already running (${duplicate.id}). Reattach with "oracle session ${duplicate.id}" or rerun with --force to start another run.`));
|
package/dist/src/cli/engine.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { isProModel } from
|
|
1
|
+
import { isProModel } from "../oracle/modelResolver.js";
|
|
2
2
|
export function defaultWaitPreference(model, engine) {
|
|
3
3
|
// Pro-class API runs can take a long time; prefer non-blocking unless explicitly overridden.
|
|
4
|
-
if (engine ===
|
|
4
|
+
if (engine === "api" && isProModel(model)) {
|
|
5
5
|
return false;
|
|
6
6
|
}
|
|
7
7
|
return true; // browser or non-pro models are fast enough to block by default
|
|
@@ -17,7 +17,7 @@ export function defaultWaitPreference(model, engine) {
|
|
|
17
17
|
*/
|
|
18
18
|
export function resolveEngine({ engine, browserFlag, env, }) {
|
|
19
19
|
if (browserFlag) {
|
|
20
|
-
return
|
|
20
|
+
return "browser";
|
|
21
21
|
}
|
|
22
22
|
if (engine) {
|
|
23
23
|
return engine;
|
|
@@ -26,16 +26,16 @@ export function resolveEngine({ engine, browserFlag, env, }) {
|
|
|
26
26
|
if (envEngine) {
|
|
27
27
|
return envEngine;
|
|
28
28
|
}
|
|
29
|
-
return env.OPENAI_API_KEY ?
|
|
29
|
+
return env.OPENAI_API_KEY ? "api" : "browser";
|
|
30
30
|
}
|
|
31
31
|
function normalizeEngineMode(raw) {
|
|
32
|
-
if (typeof raw !==
|
|
32
|
+
if (typeof raw !== "string") {
|
|
33
33
|
return null;
|
|
34
34
|
}
|
|
35
35
|
const normalized = raw.trim().toLowerCase();
|
|
36
|
-
if (normalized ===
|
|
37
|
-
return
|
|
38
|
-
if (normalized ===
|
|
39
|
-
return
|
|
36
|
+
if (normalized === "api")
|
|
37
|
+
return "api";
|
|
38
|
+
if (normalized === "browser")
|
|
39
|
+
return "browser";
|
|
40
40
|
return null;
|
|
41
41
|
}
|
package/dist/src/cli/fileSize.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { normalizeMaxFileSizeBytes } from
|
|
1
|
+
import { normalizeMaxFileSizeBytes } from "../oracle/files.js";
|
|
2
2
|
export function resolveConfiguredMaxFileSizeBytes(userConfig, env = process.env) {
|
|
3
3
|
const envValue = env.ORACLE_MAX_FILE_SIZE_BYTES?.trim();
|
|
4
4
|
if (envValue) {
|
|
5
|
-
return normalizeMaxFileSizeBytes(envValue,
|
|
5
|
+
return normalizeMaxFileSizeBytes(envValue, "ORACLE_MAX_FILE_SIZE_BYTES");
|
|
6
6
|
}
|
|
7
7
|
if (userConfig?.maxFileSizeBytes !== undefined) {
|
|
8
|
-
return normalizeMaxFileSizeBytes(userConfig.maxFileSizeBytes,
|
|
8
|
+
return normalizeMaxFileSizeBytes(userConfig.maxFileSizeBytes, "config.maxFileSizeBytes");
|
|
9
9
|
}
|
|
10
10
|
return undefined;
|
|
11
11
|
}
|
package/dist/src/cli/format.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export function formatCompactNumber(value) {
|
|
2
2
|
if (Number.isNaN(value) || !Number.isFinite(value))
|
|
3
|
-
return
|
|
3
|
+
return "0";
|
|
4
4
|
const abs = Math.abs(value);
|
|
5
|
-
const stripTrailingZero = (text) => text.replace(/\.0$/,
|
|
5
|
+
const stripTrailingZero = (text) => text.replace(/\.0$/, "");
|
|
6
6
|
if (abs >= 1_000_000) {
|
|
7
7
|
return `${stripTrailingZero((value / 1_000_000).toFixed(1))}m`;
|
|
8
8
|
}
|
package/dist/src/cli/help.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import kleur from
|
|
1
|
+
import kleur from "kleur";
|
|
2
2
|
const createColorWrapper = (isTty) => (styler) => (text) => isTty ? styler(text) : text;
|
|
3
3
|
export function applyHelpStyling(program, version, isTty) {
|
|
4
4
|
const wrap = createColorWrapper(isTty);
|
|
@@ -34,44 +34,44 @@ export function applyHelpStyling(program, version, isTty) {
|
|
|
34
34
|
return colors.argument(text);
|
|
35
35
|
},
|
|
36
36
|
});
|
|
37
|
-
program.addHelpText(
|
|
38
|
-
program.addHelpText(
|
|
37
|
+
program.addHelpText("beforeAll", () => renderHelpBanner(version, colors));
|
|
38
|
+
program.addHelpText("after", () => renderHelpFooter(program, colors));
|
|
39
39
|
}
|
|
40
40
|
function renderHelpBanner(version, colors) {
|
|
41
|
-
const subtitle =
|
|
41
|
+
const subtitle = "Prompt + files required — GPT-5.5 Pro/GPT-5.5 for tough questions with code/file context.";
|
|
42
42
|
return `${colors.banner(`Oracle CLI v${version}`)} ${colors.subtitle(`— ${subtitle}`)}\n`;
|
|
43
43
|
}
|
|
44
44
|
function renderHelpFooter(program, colors) {
|
|
45
45
|
const tips = [
|
|
46
|
-
`${colors.bullet(
|
|
47
|
-
`${colors.bullet(
|
|
48
|
-
`${colors.bullet(
|
|
49
|
-
`${colors.bullet(
|
|
50
|
-
`${colors.bullet(
|
|
51
|
-
`${colors.bullet(
|
|
52
|
-
`${colors.bullet(
|
|
53
|
-
`${colors.bullet(
|
|
54
|
-
`${colors.bullet(
|
|
55
|
-
`${colors.bullet(
|
|
56
|
-
`${colors.bullet(
|
|
57
|
-
`${colors.bullet(
|
|
58
|
-
`${colors.bullet(
|
|
59
|
-
`${colors.bullet(
|
|
60
|
-
].join(
|
|
46
|
+
`${colors.bullet("•")} Required: always pass a prompt AND ${colors.accent("--file …")} (directories/globs are fine); Oracle cannot see your project otherwise.`,
|
|
47
|
+
`${colors.bullet("•")} Attach lots of source (whole directories beat single files) and keep total input under ~196k tokens.`,
|
|
48
|
+
`${colors.bullet("•")} Oracle starts empty—open with a short project briefing (stack, services, build steps), spell out the question and prior attempts, and why it matters; the more explanation and context you provide, the better the response will be.`,
|
|
49
|
+
`${colors.bullet("•")} Spell out the project + platform + version requirements (repo name, target OS/toolchain versions, API dependencies) so Oracle doesn’t guess defaults.`,
|
|
50
|
+
`${colors.bullet("•")} When comparing multiple repos/files, spell out each repo + path + role (e.g., “Project A SettingsView → apps/project-a/Sources/SettingsView.swift; Project B SettingsView → ../project-b/mac/...”) so the model knows exactly which file is which.`,
|
|
51
|
+
`${colors.bullet("•")} Best results: 6–30 sentences plus key source files; very short prompts often yield generic answers.`,
|
|
52
|
+
`${colors.bullet("•")} Oracle is one-shot by default. For OpenAI/Azure API runs, you can chain follow-ups by passing ${colors.accent("--followup <sessionId|responseId>")} (continues via Responses API previous_response_id).`,
|
|
53
|
+
`${colors.bullet("•")} Run ${colors.accent("--files-report")} to inspect token spend before hitting the API.`,
|
|
54
|
+
`${colors.bullet("•")} Non-preview runs spawn detached sessions (especially gpt-5.5-pro API). If the CLI times out, do not re-run — reattach with ${colors.accent("oracle session <slug>")} to resume/inspect the existing run.`,
|
|
55
|
+
`${colors.bullet("•")} Set a memorable 3–5 word slug via ${colors.accent('--slug "<words>"')} to keep session IDs tidy.`,
|
|
56
|
+
`${colors.bullet("•")} Finished sessions auto-hide preamble logs when reattached; raw timestamps remain in the saved log file.`,
|
|
57
|
+
`${colors.bullet("•")} Need hidden flags? Run ${colors.accent(`${program.name()} --help --verbose`)} to list search/token/browser overrides.`,
|
|
58
|
+
`${colors.bullet("•")} If any Oracle session is already running, do not start new API runs. Attach to the existing browser session instead; only trigger API calls when you explicitly mean to.`,
|
|
59
|
+
`${colors.bullet("•")} Duplicate prompt guard: if the same prompt is already running, new runs are blocked unless you pass ${colors.accent("--force")}—prefer reattaching instead of spawning duplicates.`,
|
|
60
|
+
].join("\n");
|
|
61
61
|
const formatExample = (command, description) => `${colors.command(` ${command}`)}\n${colors.muted(` ${description}`)}`;
|
|
62
62
|
const examples = [
|
|
63
|
-
formatExample(`${program.name()} --render --copy --prompt "Review the TS data layer for schema drift" --file "src/**/*.ts,*/*.test.ts"`,
|
|
64
|
-
formatExample(`${program.name()} --prompt "Cross-check the data layer assumptions" --models gpt-5.2-pro,gemini-3-pro --file "src/**/*.ts"`,
|
|
65
|
-
formatExample(`${program.name()} status --hours 72 --limit 50`,
|
|
66
|
-
formatExample(`${program.name()} session <sessionId>`,
|
|
67
|
-
formatExample(`${program.name()} --prompt "Ship review" --slug "release-readiness-audit"`,
|
|
68
|
-
formatExample(`${program.name()} --prompt "Tabs frozen: compare Project A SettingsView (apps/project-a/Sources/SettingsView.swift) vs Project B SettingsView (../project-b/mac/App/Presentation/Views/SettingsView.swift)" --file apps/project-a/Sources/SettingsView.swift --file ../project-b/mac/App/Presentation/Views/SettingsView.swift`,
|
|
69
|
-
].join(
|
|
63
|
+
formatExample(`${program.name()} --render --copy --prompt "Review the TS data layer for schema drift" --file "src/**/*.ts,*/*.test.ts"`, "Build the bundle, print it, and copy it for manual paste into ChatGPT."),
|
|
64
|
+
formatExample(`${program.name()} --prompt "Cross-check the data layer assumptions" --models gpt-5.2-pro,gemini-3-pro --file "src/**/*.ts"`, "Run multiple API models in one go and aggregate cost/usage."),
|
|
65
|
+
formatExample(`${program.name()} status --hours 72 --limit 50`, "Show sessions from the last 72h (capped at 50 entries)."),
|
|
66
|
+
formatExample(`${program.name()} session <sessionId>`, "Attach to a running/completed session and stream the saved transcript."),
|
|
67
|
+
formatExample(`${program.name()} --prompt "Ship review" --slug "release-readiness-audit"`, "Encourage the model to hand you a 3–5 word slug and pass it along with --slug."),
|
|
68
|
+
formatExample(`${program.name()} --prompt "Tabs frozen: compare Project A SettingsView (apps/project-a/Sources/SettingsView.swift) vs Project B SettingsView (../project-b/mac/App/Presentation/Views/SettingsView.swift)" --file apps/project-a/Sources/SettingsView.swift --file ../project-b/mac/App/Presentation/Views/SettingsView.swift`, "Spell out what each attached file is (repo + path + role) before asking for comparisons so the model knows exactly what it is reading."),
|
|
69
|
+
].join("\n\n");
|
|
70
70
|
return `
|
|
71
|
-
${colors.section(
|
|
71
|
+
${colors.section("Tips")}
|
|
72
72
|
${tips}
|
|
73
73
|
|
|
74
|
-
${colors.section(
|
|
74
|
+
${colors.section("Examples")}
|
|
75
75
|
${examples}
|
|
76
76
|
`;
|
|
77
77
|
}
|
|
@@ -9,14 +9,14 @@ export function applyHiddenAliases(options, setOptionValue) {
|
|
|
9
9
|
if (options.include && options.include.length > 0) {
|
|
10
10
|
const mergedFiles = [...(options.file ?? []), ...options.include];
|
|
11
11
|
options.file = mergedFiles;
|
|
12
|
-
setOptionValue?.(
|
|
12
|
+
setOptionValue?.("file", mergedFiles);
|
|
13
13
|
}
|
|
14
14
|
if (!options.prompt && options.message) {
|
|
15
15
|
options.prompt = options.message;
|
|
16
|
-
setOptionValue?.(
|
|
16
|
+
setOptionValue?.("prompt", options.message);
|
|
17
17
|
}
|
|
18
18
|
if (!options.engine && options.mode) {
|
|
19
19
|
options.engine = options.mode;
|
|
20
|
-
setOptionValue?.(
|
|
20
|
+
setOptionValue?.("engine", options.mode);
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import fs from
|
|
2
|
-
import { DEFAULT_SYSTEM_PROMPT } from
|
|
3
|
-
import { buildPrompt } from
|
|
4
|
-
import { createFileSections, readFiles } from
|
|
5
|
-
import { createFsAdapter } from
|
|
6
|
-
import { buildPromptMarkdown } from
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import { DEFAULT_SYSTEM_PROMPT } from "../oracle/config.js";
|
|
3
|
+
import { buildPrompt } from "../oracle/request.js";
|
|
4
|
+
import { createFileSections, readFiles } from "../oracle/files.js";
|
|
5
|
+
import { createFsAdapter } from "../oracle/fsAdapter.js";
|
|
6
|
+
import { buildPromptMarkdown } from "../oracle/promptAssembly.js";
|
|
7
7
|
export async function buildMarkdownBundle(options, deps = {}) {
|
|
8
8
|
const cwd = deps.cwd ?? process.cwd();
|
|
9
9
|
const fsModule = deps.fs ?? createFsAdapter(fs);
|
|
@@ -14,7 +14,7 @@ export async function buildMarkdownBundle(options, deps = {}) {
|
|
|
14
14
|
});
|
|
15
15
|
const sections = createFileSections(files, cwd);
|
|
16
16
|
const systemPrompt = options.system?.trim() || DEFAULT_SYSTEM_PROMPT;
|
|
17
|
-
const userPrompt = (options.prompt ??
|
|
17
|
+
const userPrompt = (options.prompt ?? "").trim();
|
|
18
18
|
const markdown = buildPromptMarkdown(systemPrompt, userPrompt, sections);
|
|
19
19
|
const promptWithFiles = buildPrompt(userPrompt, files, cwd);
|
|
20
20
|
return { markdown, promptWithFiles, systemPrompt, files };
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import chalk from
|
|
2
|
-
import { render as renderMarkdown } from
|
|
3
|
-
import { bundledLanguages, bundledThemes, createHighlighter
|
|
4
|
-
const DEFAULT_THEME =
|
|
5
|
-
const HIGHLIGHT_LANGS = [
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { render as renderMarkdown } from "markdansi";
|
|
3
|
+
import { bundledLanguages, bundledThemes, createHighlighter } from "shiki";
|
|
4
|
+
const DEFAULT_THEME = "github-dark";
|
|
5
|
+
const HIGHLIGHT_LANGS = ["ts", "tsx", "js", "jsx", "json", "swift"];
|
|
6
6
|
const SUPPORTED_LANG_ALIASES = {
|
|
7
|
-
ts:
|
|
8
|
-
typescript:
|
|
9
|
-
tsx:
|
|
10
|
-
js:
|
|
11
|
-
javascript:
|
|
12
|
-
jsx:
|
|
13
|
-
json:
|
|
14
|
-
swift:
|
|
7
|
+
ts: "ts",
|
|
8
|
+
typescript: "ts",
|
|
9
|
+
tsx: "tsx",
|
|
10
|
+
js: "js",
|
|
11
|
+
javascript: "js",
|
|
12
|
+
jsx: "jsx",
|
|
13
|
+
json: "json",
|
|
14
|
+
swift: "swift",
|
|
15
15
|
};
|
|
16
16
|
const shikiPromise = createHighlighter({
|
|
17
17
|
themes: [bundledThemes[DEFAULT_THEME]],
|
|
@@ -70,8 +70,8 @@ function shikiHighlighter(code, lang) {
|
|
|
70
70
|
const colored = token.color ? chalk.hex(token.color)(token.content) : token.content;
|
|
71
71
|
return styleToken(colored, token.fontStyle);
|
|
72
72
|
})
|
|
73
|
-
.join(
|
|
74
|
-
.join(
|
|
73
|
+
.join(""))
|
|
74
|
+
.join("\n");
|
|
75
75
|
}
|
|
76
76
|
catch {
|
|
77
77
|
return code;
|