@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
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
* --escape Send ESC before typing (to interrupt/resume)
|
|
13
13
|
* --wait-ms N Extra wait (ms) after typing before Enter
|
|
14
14
|
*/
|
|
15
|
-
import { spawnSync } from
|
|
16
|
-
import { sleepSync } from
|
|
15
|
+
import { spawnSync } from "node:child_process";
|
|
16
|
+
import { sleepSync } from "bun";
|
|
17
17
|
function usage(message) {
|
|
18
18
|
if (message) {
|
|
19
19
|
console.error(`Error: ${message}`);
|
|
@@ -29,44 +29,44 @@ Examples:
|
|
|
29
29
|
}
|
|
30
30
|
function parseArgs(argv) {
|
|
31
31
|
let session;
|
|
32
|
-
let entry =
|
|
32
|
+
let entry = "single";
|
|
33
33
|
let shouldEscape = false;
|
|
34
34
|
let waitMs = 400;
|
|
35
|
-
const literalSeparator = argv.indexOf(
|
|
35
|
+
const literalSeparator = argv.indexOf("--");
|
|
36
36
|
const optionPart = literalSeparator === -1 ? argv : argv.slice(0, literalSeparator);
|
|
37
37
|
const literalPart = literalSeparator === -1 ? [] : argv.slice(literalSeparator + 1);
|
|
38
38
|
for (let i = 0; i < optionPart.length; i += 1) {
|
|
39
39
|
const token = optionPart[i];
|
|
40
|
-
if (!token.startsWith(
|
|
40
|
+
if (!token.startsWith("--")) {
|
|
41
41
|
usage(`Unexpected argument: ${token}`);
|
|
42
42
|
}
|
|
43
43
|
const key = token.slice(2);
|
|
44
44
|
switch (key) {
|
|
45
|
-
case
|
|
45
|
+
case "session": {
|
|
46
46
|
const value = optionPart[i + 1];
|
|
47
47
|
if (!value)
|
|
48
|
-
usage(
|
|
48
|
+
usage("--session requires a value");
|
|
49
49
|
session = value;
|
|
50
50
|
i += 1;
|
|
51
51
|
break;
|
|
52
52
|
}
|
|
53
|
-
case
|
|
53
|
+
case "entry": {
|
|
54
54
|
const value = optionPart[i + 1];
|
|
55
|
-
if (value !==
|
|
55
|
+
if (value !== "single" && value !== "double" && value !== "none") {
|
|
56
56
|
usage(`Unknown entry mode: ${value}`);
|
|
57
57
|
}
|
|
58
58
|
entry = value;
|
|
59
59
|
i += 1;
|
|
60
60
|
break;
|
|
61
61
|
}
|
|
62
|
-
case
|
|
62
|
+
case "escape": {
|
|
63
63
|
shouldEscape = true;
|
|
64
64
|
break;
|
|
65
65
|
}
|
|
66
|
-
case
|
|
66
|
+
case "wait-ms": {
|
|
67
67
|
const value = optionPart[i + 1];
|
|
68
68
|
if (!value || Number.isNaN(Number.parseInt(value, 10))) {
|
|
69
|
-
usage(
|
|
69
|
+
usage("--wait-ms requires an integer value");
|
|
70
70
|
}
|
|
71
71
|
waitMs = Number.parseInt(value, 10);
|
|
72
72
|
i += 1;
|
|
@@ -76,30 +76,30 @@ function parseArgs(argv) {
|
|
|
76
76
|
usage(`Unknown option: --${key}`);
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
|
-
const message = literalPart.join(
|
|
79
|
+
const message = literalPart.join(" ").trim();
|
|
80
80
|
if (!session)
|
|
81
|
-
usage(
|
|
81
|
+
usage("Missing --session");
|
|
82
82
|
if (!message)
|
|
83
|
-
usage(
|
|
83
|
+
usage("Missing message (provide text after -- separator)");
|
|
84
84
|
return { session, entry, escape: shouldEscape, waitMs, message };
|
|
85
85
|
}
|
|
86
86
|
function runTmux(args, allowFailure = false) {
|
|
87
|
-
const result = spawnSync(
|
|
87
|
+
const result = spawnSync("tmux", args, { encoding: "utf8" });
|
|
88
88
|
if (result.error) {
|
|
89
89
|
if (allowFailure)
|
|
90
|
-
return
|
|
90
|
+
return "";
|
|
91
91
|
throw result.error;
|
|
92
92
|
}
|
|
93
93
|
if (result.status !== 0) {
|
|
94
94
|
if (allowFailure)
|
|
95
|
-
return result.stderr?.trim() ??
|
|
96
|
-
throw new Error(`tmux ${args.join(
|
|
95
|
+
return result.stderr?.trim() ?? "";
|
|
96
|
+
throw new Error(`tmux ${args.join(" ")} failed: ${result.stderr?.trim()}`);
|
|
97
97
|
}
|
|
98
|
-
return result.stdout?.trimEnd() ??
|
|
98
|
+
return result.stdout?.trimEnd() ?? "";
|
|
99
99
|
}
|
|
100
100
|
function ensureSession(target) {
|
|
101
|
-
const session = target.split(
|
|
102
|
-
const result = spawnSync(
|
|
101
|
+
const session = target.split(":")[0] ?? target;
|
|
102
|
+
const result = spawnSync("tmux", ["has-session", "-t", session]);
|
|
103
103
|
if (result.status !== 0) {
|
|
104
104
|
usage(`tmux session '${session}' not found. Start it first (e.g., tmux new-session -s ${session} ...)`);
|
|
105
105
|
}
|
|
@@ -107,35 +107,35 @@ function ensureSession(target) {
|
|
|
107
107
|
function sendMessage(options) {
|
|
108
108
|
ensureSession(options.session);
|
|
109
109
|
if (options.escape) {
|
|
110
|
-
runTmux([
|
|
110
|
+
runTmux(["send-keys", "-t", options.session, "Escape"], true);
|
|
111
111
|
sleepSync(200);
|
|
112
112
|
}
|
|
113
113
|
// Clear existing prompt
|
|
114
|
-
runTmux([
|
|
114
|
+
runTmux(["send-keys", "-t", options.session, "Escape"], true);
|
|
115
115
|
sleepSync(120);
|
|
116
|
-
runTmux([
|
|
116
|
+
runTmux(["send-keys", "-t", options.session, "C-u"], true);
|
|
117
117
|
sleepSync(120);
|
|
118
118
|
// Type the message
|
|
119
|
-
runTmux([
|
|
119
|
+
runTmux(["send-keys", "-t", options.session, "-l", options.message], true);
|
|
120
120
|
sleepSync(Math.max(120, options.waitMs));
|
|
121
121
|
// Send Enter(s)
|
|
122
|
-
const pressEnter = () => runTmux([
|
|
122
|
+
const pressEnter = () => runTmux(["send-keys", "-t", options.session, "C-m"], true);
|
|
123
123
|
switch (options.entry) {
|
|
124
|
-
case
|
|
124
|
+
case "single":
|
|
125
125
|
pressEnter();
|
|
126
126
|
break;
|
|
127
|
-
case
|
|
127
|
+
case "double":
|
|
128
128
|
pressEnter();
|
|
129
129
|
sleepSync(200);
|
|
130
130
|
pressEnter();
|
|
131
131
|
break;
|
|
132
|
-
case
|
|
132
|
+
case "none":
|
|
133
133
|
break;
|
|
134
134
|
default:
|
|
135
135
|
usage(`Unsupported entry mode: ${options.entry}`);
|
|
136
136
|
}
|
|
137
137
|
sleepSync(600);
|
|
138
|
-
const tail = runTmux([
|
|
138
|
+
const tail = runTmux(["capture-pane", "-pt", options.session, "-S", "-6"], true);
|
|
139
139
|
console.log(tail);
|
|
140
140
|
}
|
|
141
141
|
try {
|
package/dist/scripts/check.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import process from
|
|
2
|
+
import process from "node:process";
|
|
3
3
|
const buildConfig = {
|
|
4
|
-
entrypoints: [
|
|
5
|
-
outdir:
|
|
6
|
-
target:
|
|
4
|
+
entrypoints: ["./bin/oracle-cli.js"],
|
|
5
|
+
outdir: "./.bun-check",
|
|
6
|
+
target: "bun",
|
|
7
7
|
minify: false,
|
|
8
8
|
write: false,
|
|
9
9
|
};
|
|
10
10
|
const result = await Bun.build(buildConfig);
|
|
11
11
|
if (!result.success) {
|
|
12
|
-
console.error(
|
|
12
|
+
console.error("Build failed while checking syntax:");
|
|
13
13
|
for (const log of result.logs) {
|
|
14
14
|
console.error(log.message);
|
|
15
15
|
if (log.position) {
|
|
@@ -18,4 +18,4 @@ if (!result.success) {
|
|
|
18
18
|
}
|
|
19
19
|
process.exit(1);
|
|
20
20
|
}
|
|
21
|
-
console.log(
|
|
21
|
+
console.log("Syntax OK");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import puppeteer from
|
|
2
|
-
const port = parseInt(process.argv[2] ||
|
|
1
|
+
import puppeteer from "puppeteer-core";
|
|
2
|
+
const port = parseInt(process.argv[2] || "52990", 10);
|
|
3
3
|
async function main() {
|
|
4
4
|
const browser = await puppeteer.connect({
|
|
5
5
|
browserURL: `http://127.0.0.1:${port}`,
|
|
@@ -9,24 +9,24 @@ async function main() {
|
|
|
9
9
|
let targetPage = null;
|
|
10
10
|
for (const page of pages) {
|
|
11
11
|
const url = page.url();
|
|
12
|
-
if (url.includes(
|
|
12
|
+
if (url.includes("chatgpt.com/c/")) {
|
|
13
13
|
targetPage = page;
|
|
14
14
|
break;
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
if (!targetPage) {
|
|
18
|
-
console.error(
|
|
18
|
+
console.error("ChatGPT conversation page not found");
|
|
19
19
|
process.exit(1);
|
|
20
20
|
}
|
|
21
|
-
console.error(
|
|
21
|
+
console.error("Found page:", await targetPage.url());
|
|
22
22
|
// Extract the last assistant message
|
|
23
23
|
const content = (await targetPage.evaluate(() => {
|
|
24
24
|
// Try multiple selectors for ChatGPT's assistant messages
|
|
25
25
|
const selectors = [
|
|
26
26
|
'[data-message-author-role="assistant"] .markdown',
|
|
27
27
|
'[data-message-author-role="assistant"]',
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
".agent-turn .markdown",
|
|
29
|
+
".agent-turn",
|
|
30
30
|
];
|
|
31
31
|
for (const selector of selectors) {
|
|
32
32
|
const elements = document.querySelectorAll(selector);
|
|
@@ -41,10 +41,10 @@ async function main() {
|
|
|
41
41
|
}
|
|
42
42
|
// Debug: show what's on the page
|
|
43
43
|
const body = document.body.innerHTML;
|
|
44
|
-
return { error:
|
|
44
|
+
return { error: "No messages found", bodyLength: body.length, sample: body.slice(0, 2000) };
|
|
45
45
|
}));
|
|
46
|
-
if (
|
|
47
|
-
console.error(
|
|
46
|
+
if ("error" in content) {
|
|
47
|
+
console.error("Error:", JSON.stringify(content, null, 2));
|
|
48
48
|
process.exit(1);
|
|
49
49
|
}
|
|
50
50
|
console.log(content.text);
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
|
-
import { readdirSync, readFileSync } from
|
|
3
|
-
import { dirname, join, relative } from
|
|
4
|
-
import { fileURLToPath } from
|
|
5
|
-
import { compact } from
|
|
2
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join, relative } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { compact } from "es-toolkit";
|
|
6
6
|
const docsListFile = fileURLToPath(import.meta.url);
|
|
7
7
|
const docsListDir = dirname(docsListFile);
|
|
8
|
-
const DOCS_DIR = join(docsListDir,
|
|
9
|
-
const EXCLUDED_DIRS = new Set([
|
|
8
|
+
const DOCS_DIR = join(docsListDir, "..", "docs");
|
|
9
|
+
const EXCLUDED_DIRS = new Set(["archive", "research"]);
|
|
10
10
|
function walkMarkdownFiles(dir, base = dir) {
|
|
11
11
|
const entries = readdirSync(dir, { withFileTypes: true });
|
|
12
12
|
const files = [];
|
|
13
13
|
for (const entry of entries) {
|
|
14
|
-
if (entry.name.startsWith(
|
|
14
|
+
if (entry.name.startsWith(".")) {
|
|
15
15
|
continue;
|
|
16
16
|
}
|
|
17
17
|
const fullPath = join(dir, entry.name);
|
|
@@ -21,37 +21,37 @@ function walkMarkdownFiles(dir, base = dir) {
|
|
|
21
21
|
}
|
|
22
22
|
files.push(...walkMarkdownFiles(fullPath, base));
|
|
23
23
|
}
|
|
24
|
-
else if (entry.isFile() && entry.name.endsWith(
|
|
24
|
+
else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
25
25
|
files.push(relative(base, fullPath));
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
return files.sort((a, b) => a.localeCompare(b));
|
|
29
29
|
}
|
|
30
30
|
function extractMetadata(fullPath) {
|
|
31
|
-
const content = readFileSync(fullPath,
|
|
32
|
-
if (!content.startsWith(
|
|
33
|
-
return { summary: null, readWhen: [], error:
|
|
31
|
+
const content = readFileSync(fullPath, "utf8");
|
|
32
|
+
if (!content.startsWith("---")) {
|
|
33
|
+
return { summary: null, readWhen: [], error: "missing front matter" };
|
|
34
34
|
}
|
|
35
|
-
const endIndex = content.indexOf(
|
|
35
|
+
const endIndex = content.indexOf("\n---", 3);
|
|
36
36
|
if (endIndex === -1) {
|
|
37
|
-
return { summary: null, readWhen: [], error:
|
|
37
|
+
return { summary: null, readWhen: [], error: "unterminated front matter" };
|
|
38
38
|
}
|
|
39
39
|
const frontMatter = content.slice(3, endIndex).trim();
|
|
40
|
-
const lines = frontMatter.split(
|
|
40
|
+
const lines = frontMatter.split("\n");
|
|
41
41
|
let summaryLine = null;
|
|
42
42
|
const readWhen = [];
|
|
43
43
|
let collectingField = null;
|
|
44
44
|
for (const rawLine of lines) {
|
|
45
45
|
const line = rawLine.trim();
|
|
46
|
-
if (line.startsWith(
|
|
46
|
+
if (line.startsWith("summary:")) {
|
|
47
47
|
summaryLine = line;
|
|
48
48
|
collectingField = null;
|
|
49
49
|
continue;
|
|
50
50
|
}
|
|
51
|
-
if (line.startsWith(
|
|
52
|
-
collectingField =
|
|
53
|
-
const inline = line.slice(
|
|
54
|
-
if (inline.startsWith(
|
|
51
|
+
if (line.startsWith("read_when:")) {
|
|
52
|
+
collectingField = "read_when";
|
|
53
|
+
const inline = line.slice("read_when:".length).trim();
|
|
54
|
+
if (inline.startsWith("[") && inline.endsWith("]")) {
|
|
55
55
|
try {
|
|
56
56
|
const parsed = JSON.parse(inline.replace(/'/g, '"'));
|
|
57
57
|
if (Array.isArray(parsed)) {
|
|
@@ -64,14 +64,14 @@ function extractMetadata(fullPath) {
|
|
|
64
64
|
}
|
|
65
65
|
continue;
|
|
66
66
|
}
|
|
67
|
-
if (collectingField ===
|
|
68
|
-
if (line.startsWith(
|
|
67
|
+
if (collectingField === "read_when") {
|
|
68
|
+
if (line.startsWith("- ")) {
|
|
69
69
|
const hint = line.slice(2).trim();
|
|
70
70
|
if (hint) {
|
|
71
71
|
readWhen.push(hint);
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
-
else if (line ===
|
|
74
|
+
else if (line === "") {
|
|
75
75
|
}
|
|
76
76
|
else {
|
|
77
77
|
collectingField = null;
|
|
@@ -79,19 +79,19 @@ function extractMetadata(fullPath) {
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
if (!summaryLine) {
|
|
82
|
-
return { summary: null, readWhen, error:
|
|
82
|
+
return { summary: null, readWhen, error: "summary key missing" };
|
|
83
83
|
}
|
|
84
|
-
const summaryValue = summaryLine.slice(
|
|
84
|
+
const summaryValue = summaryLine.slice("summary:".length).trim();
|
|
85
85
|
const normalized = summaryValue
|
|
86
|
-
.replace(/^['"]|['"]$/g,
|
|
87
|
-
.replace(/\s+/g,
|
|
86
|
+
.replace(/^['"]|['"]$/g, "")
|
|
87
|
+
.replace(/\s+/g, " ")
|
|
88
88
|
.trim();
|
|
89
89
|
if (!normalized) {
|
|
90
|
-
return { summary: null, readWhen, error:
|
|
90
|
+
return { summary: null, readWhen, error: "summary is empty" };
|
|
91
91
|
}
|
|
92
92
|
return { summary: normalized, readWhen };
|
|
93
93
|
}
|
|
94
|
-
console.log(
|
|
94
|
+
console.log("Listing all markdown files in docs folder:");
|
|
95
95
|
const markdownFiles = walkMarkdownFiles(DOCS_DIR);
|
|
96
96
|
for (const relativePath of markdownFiles) {
|
|
97
97
|
const fullPath = join(DOCS_DIR, relativePath);
|
|
@@ -99,11 +99,11 @@ for (const relativePath of markdownFiles) {
|
|
|
99
99
|
if (summary) {
|
|
100
100
|
console.log(`${relativePath} - ${summary}`);
|
|
101
101
|
if (readWhen.length > 0) {
|
|
102
|
-
console.log(` Read when: ${readWhen.join(
|
|
102
|
+
console.log(` Read when: ${readWhen.join("; ")}`);
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
else {
|
|
106
|
-
const reason = error ? ` - [${error}]` :
|
|
106
|
+
const reason = error ? ` - [${error}]` : "";
|
|
107
107
|
console.log(`${relativePath}${reason}`);
|
|
108
108
|
}
|
|
109
109
|
}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { resolve } from
|
|
2
|
-
const COMMIT_HELPER_SUBCOMMANDS = new Set([
|
|
3
|
-
const GUARDED_SUBCOMMANDS = new Set([
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
const COMMIT_HELPER_SUBCOMMANDS = new Set(["add", "commit"]);
|
|
3
|
+
const GUARDED_SUBCOMMANDS = new Set(["push", "pull", "merge", "rebase", "cherry-pick"]);
|
|
4
4
|
const DESTRUCTIVE_SUBCOMMANDS = new Set([
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
"reset",
|
|
6
|
+
"checkout",
|
|
7
|
+
"clean",
|
|
8
|
+
"restore",
|
|
9
|
+
"switch",
|
|
10
|
+
"stash",
|
|
11
|
+
"branch",
|
|
12
|
+
"filter-branch",
|
|
13
|
+
"fast-import",
|
|
14
14
|
]);
|
|
15
15
|
export function extractGitInvocation(commandArgs) {
|
|
16
16
|
for (const [index, token] of commandArgs.entries()) {
|
|
17
|
-
if (token ===
|
|
17
|
+
if (token === "git" || token.endsWith("/git")) {
|
|
18
18
|
return { index, argv: commandArgs.slice(index) };
|
|
19
19
|
}
|
|
20
20
|
}
|
|
@@ -24,21 +24,21 @@ export function findGitSubcommand(commandArgs) {
|
|
|
24
24
|
if (commandArgs.length <= 1) {
|
|
25
25
|
return null;
|
|
26
26
|
}
|
|
27
|
-
const optionsWithValue = new Set([
|
|
27
|
+
const optionsWithValue = new Set(["-C", "--git-dir", "--work-tree", "-c"]);
|
|
28
28
|
let index = 1;
|
|
29
29
|
while (index < commandArgs.length) {
|
|
30
30
|
const token = commandArgs[index];
|
|
31
31
|
if (token === undefined) {
|
|
32
32
|
break;
|
|
33
33
|
}
|
|
34
|
-
if (token ===
|
|
34
|
+
if (token === "--") {
|
|
35
35
|
const next = commandArgs[index + 1];
|
|
36
36
|
return next ? { name: next, index: index + 1 } : null;
|
|
37
37
|
}
|
|
38
|
-
if (!token.startsWith(
|
|
38
|
+
if (!token.startsWith("-")) {
|
|
39
39
|
return { name: token, index };
|
|
40
40
|
}
|
|
41
|
-
if (token.includes(
|
|
41
|
+
if (token.includes("=")) {
|
|
42
42
|
index += 1;
|
|
43
43
|
continue;
|
|
44
44
|
}
|
|
@@ -59,7 +59,7 @@ export function determineGitWorkdir(baseDir, gitArgs, command) {
|
|
|
59
59
|
if (token === undefined) {
|
|
60
60
|
break;
|
|
61
61
|
}
|
|
62
|
-
if (token ===
|
|
62
|
+
if (token === "-C") {
|
|
63
63
|
const next = gitArgs[index + 1];
|
|
64
64
|
if (next) {
|
|
65
65
|
workDir = resolve(workDir, next);
|
|
@@ -67,7 +67,7 @@ export function determineGitWorkdir(baseDir, gitArgs, command) {
|
|
|
67
67
|
index += 2;
|
|
68
68
|
continue;
|
|
69
69
|
}
|
|
70
|
-
if (token.startsWith(
|
|
70
|
+
if (token.startsWith("-C")) {
|
|
71
71
|
const pathSegment = token.slice(2);
|
|
72
72
|
if (pathSegment.length > 0) {
|
|
73
73
|
workDir = resolve(workDir, pathSegment);
|
|
@@ -80,7 +80,9 @@ export function determineGitWorkdir(baseDir, gitArgs, command) {
|
|
|
80
80
|
export function analyzeGitExecution(commandArgs, workspaceDir) {
|
|
81
81
|
const invocation = extractGitInvocation(commandArgs);
|
|
82
82
|
const command = invocation ? findGitSubcommand(invocation.argv) : null;
|
|
83
|
-
const workDir = invocation
|
|
83
|
+
const workDir = invocation
|
|
84
|
+
? determineGitWorkdir(workspaceDir, invocation.argv, command)
|
|
85
|
+
: workspaceDir;
|
|
84
86
|
return {
|
|
85
87
|
invocation,
|
|
86
88
|
command,
|
|
@@ -108,9 +110,9 @@ export function isDestructiveGitSubcommand(command, gitArgv) {
|
|
|
108
110
|
if (DESTRUCTIVE_SUBCOMMANDS.has(subcommand)) {
|
|
109
111
|
return true;
|
|
110
112
|
}
|
|
111
|
-
if (subcommand ===
|
|
112
|
-
const action = gitArgv[command.index + 1] ??
|
|
113
|
-
return action ===
|
|
113
|
+
if (subcommand === "bisect") {
|
|
114
|
+
const action = gitArgv[command.index + 1] ?? "";
|
|
115
|
+
return action === "reset";
|
|
114
116
|
}
|
|
115
117
|
return false;
|
|
116
118
|
}
|
package/dist/scripts/run-cli.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { spawn } from
|
|
3
|
-
import path from
|
|
4
|
-
import { fileURLToPath } from
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
5
|
const rawArgs = process.argv.slice(2);
|
|
6
|
-
const args = rawArgs[0] ===
|
|
6
|
+
const args = rawArgs[0] === "--" ? rawArgs.slice(1) : rawArgs;
|
|
7
7
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
const cliEntry = path.join(here,
|
|
9
|
-
const child = spawn(process.execPath, [
|
|
10
|
-
stdio:
|
|
8
|
+
const cliEntry = path.join(here, "../bin/oracle-cli.js");
|
|
9
|
+
const child = spawn(process.execPath, ["--", cliEntry, ...args], {
|
|
10
|
+
stdio: "inherit",
|
|
11
11
|
});
|
|
12
|
-
child.on(
|
|
12
|
+
child.on("exit", (code) => {
|
|
13
13
|
process.exit(code ?? 0);
|
|
14
14
|
});
|