@indykish/oracle 0.9.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.
Files changed (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +215 -0
  3. package/assets-oracle-icon.png +0 -0
  4. package/dist/bin/oracle-cli.js +1252 -0
  5. package/dist/bin/oracle-mcp.js +6 -0
  6. package/dist/scripts/agent-send.js +147 -0
  7. package/dist/scripts/browser-tools.js +536 -0
  8. package/dist/scripts/check.js +21 -0
  9. package/dist/scripts/debug/extract-chatgpt-response.js +53 -0
  10. package/dist/scripts/docs-list.js +110 -0
  11. package/dist/scripts/git-policy.js +125 -0
  12. package/dist/scripts/run-cli.js +14 -0
  13. package/dist/scripts/runner.js +1378 -0
  14. package/dist/scripts/test-browser.js +103 -0
  15. package/dist/scripts/test-remote-chrome.js +68 -0
  16. package/dist/src/bridge/connection.js +103 -0
  17. package/dist/src/bridge/userConfigFile.js +28 -0
  18. package/dist/src/browser/actions/assistantResponse.js +1067 -0
  19. package/dist/src/browser/actions/attachmentDataTransfer.js +138 -0
  20. package/dist/src/browser/actions/attachments.js +1910 -0
  21. package/dist/src/browser/actions/domEvents.js +19 -0
  22. package/dist/src/browser/actions/modelSelection.js +485 -0
  23. package/dist/src/browser/actions/navigation.js +445 -0
  24. package/dist/src/browser/actions/promptComposer.js +485 -0
  25. package/dist/src/browser/actions/remoteFileTransfer.js +37 -0
  26. package/dist/src/browser/actions/thinkingTime.js +206 -0
  27. package/dist/src/browser/chromeLifecycle.js +344 -0
  28. package/dist/src/browser/config.js +103 -0
  29. package/dist/src/browser/constants.js +71 -0
  30. package/dist/src/browser/cookies.js +191 -0
  31. package/dist/src/browser/detect.js +164 -0
  32. package/dist/src/browser/domDebug.js +36 -0
  33. package/dist/src/browser/index.js +1741 -0
  34. package/dist/src/browser/modelStrategy.js +13 -0
  35. package/dist/src/browser/pageActions.js +5 -0
  36. package/dist/src/browser/policies.js +43 -0
  37. package/dist/src/browser/profileState.js +280 -0
  38. package/dist/src/browser/prompt.js +152 -0
  39. package/dist/src/browser/promptSummary.js +20 -0
  40. package/dist/src/browser/reattach.js +186 -0
  41. package/dist/src/browser/reattachHelpers.js +382 -0
  42. package/dist/src/browser/sessionRunner.js +119 -0
  43. package/dist/src/browser/types.js +1 -0
  44. package/dist/src/browser/utils.js +122 -0
  45. package/dist/src/browserMode.js +1 -0
  46. package/dist/src/cli/bridge/claudeConfig.js +54 -0
  47. package/dist/src/cli/bridge/client.js +73 -0
  48. package/dist/src/cli/bridge/codexConfig.js +43 -0
  49. package/dist/src/cli/bridge/doctor.js +107 -0
  50. package/dist/src/cli/bridge/host.js +259 -0
  51. package/dist/src/cli/browserConfig.js +278 -0
  52. package/dist/src/cli/browserDefaults.js +81 -0
  53. package/dist/src/cli/bundleWarnings.js +9 -0
  54. package/dist/src/cli/clipboard.js +10 -0
  55. package/dist/src/cli/detach.js +11 -0
  56. package/dist/src/cli/dryRun.js +105 -0
  57. package/dist/src/cli/duplicatePromptGuard.js +14 -0
  58. package/dist/src/cli/engine.js +41 -0
  59. package/dist/src/cli/errorUtils.js +9 -0
  60. package/dist/src/cli/format.js +13 -0
  61. package/dist/src/cli/help.js +77 -0
  62. package/dist/src/cli/hiddenAliases.js +22 -0
  63. package/dist/src/cli/markdownBundle.js +17 -0
  64. package/dist/src/cli/markdownRenderer.js +97 -0
  65. package/dist/src/cli/notifier.js +306 -0
  66. package/dist/src/cli/options.js +281 -0
  67. package/dist/src/cli/oscUtils.js +2 -0
  68. package/dist/src/cli/promptRequirement.js +17 -0
  69. package/dist/src/cli/renderFlags.js +9 -0
  70. package/dist/src/cli/renderOutput.js +26 -0
  71. package/dist/src/cli/rootAlias.js +30 -0
  72. package/dist/src/cli/runOptions.js +78 -0
  73. package/dist/src/cli/sessionCommand.js +111 -0
  74. package/dist/src/cli/sessionDisplay.js +567 -0
  75. package/dist/src/cli/sessionRunner.js +602 -0
  76. package/dist/src/cli/sessionTable.js +92 -0
  77. package/dist/src/cli/tagline.js +258 -0
  78. package/dist/src/cli/tui/index.js +486 -0
  79. package/dist/src/cli/writeOutputPath.js +21 -0
  80. package/dist/src/config.js +26 -0
  81. package/dist/src/gemini-web/client.js +328 -0
  82. package/dist/src/gemini-web/executor.js +285 -0
  83. package/dist/src/gemini-web/index.js +1 -0
  84. package/dist/src/gemini-web/types.js +1 -0
  85. package/dist/src/heartbeat.js +43 -0
  86. package/dist/src/mcp/server.js +40 -0
  87. package/dist/src/mcp/tools/consult.js +290 -0
  88. package/dist/src/mcp/tools/sessionResources.js +75 -0
  89. package/dist/src/mcp/tools/sessions.js +105 -0
  90. package/dist/src/mcp/types.js +22 -0
  91. package/dist/src/mcp/utils.js +37 -0
  92. package/dist/src/oracle/background.js +141 -0
  93. package/dist/src/oracle/claude.js +101 -0
  94. package/dist/src/oracle/client.js +197 -0
  95. package/dist/src/oracle/config.js +227 -0
  96. package/dist/src/oracle/errors.js +132 -0
  97. package/dist/src/oracle/files.js +378 -0
  98. package/dist/src/oracle/finishLine.js +32 -0
  99. package/dist/src/oracle/format.js +30 -0
  100. package/dist/src/oracle/fsAdapter.js +10 -0
  101. package/dist/src/oracle/gemini.js +195 -0
  102. package/dist/src/oracle/logging.js +36 -0
  103. package/dist/src/oracle/markdown.js +46 -0
  104. package/dist/src/oracle/modelResolver.js +183 -0
  105. package/dist/src/oracle/multiModelRunner.js +153 -0
  106. package/dist/src/oracle/oscProgress.js +24 -0
  107. package/dist/src/oracle/promptAssembly.js +13 -0
  108. package/dist/src/oracle/request.js +50 -0
  109. package/dist/src/oracle/run.js +596 -0
  110. package/dist/src/oracle/runUtils.js +31 -0
  111. package/dist/src/oracle/tokenEstimate.js +37 -0
  112. package/dist/src/oracle/tokenStats.js +39 -0
  113. package/dist/src/oracle/tokenStringifier.js +24 -0
  114. package/dist/src/oracle/types.js +1 -0
  115. package/dist/src/oracle.js +12 -0
  116. package/dist/src/oracleHome.js +13 -0
  117. package/dist/src/remote/client.js +129 -0
  118. package/dist/src/remote/health.js +113 -0
  119. package/dist/src/remote/remoteServiceConfig.js +31 -0
  120. package/dist/src/remote/server.js +533 -0
  121. package/dist/src/remote/types.js +1 -0
  122. package/dist/src/sessionManager.js +637 -0
  123. package/dist/src/sessionStore.js +56 -0
  124. package/dist/src/version.js +39 -0
  125. package/dist/vendor/oracle-notifier/OracleNotifier.swift +45 -0
  126. package/dist/vendor/oracle-notifier/README.md +24 -0
  127. package/dist/vendor/oracle-notifier/build-notifier.sh +93 -0
  128. package/package.json +115 -0
  129. package/vendor/oracle-notifier/OracleNotifier.swift +45 -0
  130. package/vendor/oracle-notifier/README.md +24 -0
  131. package/vendor/oracle-notifier/build-notifier.sh +93 -0
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env bun
2
+ import process from 'node:process';
3
+ const buildConfig = {
4
+ entrypoints: ['./bin/oracle-cli.js'],
5
+ outdir: './.bun-check',
6
+ target: 'bun',
7
+ minify: false,
8
+ write: false,
9
+ };
10
+ const result = await Bun.build(buildConfig);
11
+ if (!result.success) {
12
+ console.error('Build failed while checking syntax:');
13
+ for (const log of result.logs) {
14
+ console.error(log.message);
15
+ if (log.position) {
16
+ console.error(`\tat ${log.position.file}:${log.position.line}:${log.position.column}`);
17
+ }
18
+ }
19
+ process.exit(1);
20
+ }
21
+ console.log('Syntax OK');
@@ -0,0 +1,53 @@
1
+ import puppeteer from 'puppeteer-core';
2
+ const port = parseInt(process.argv[2] || '52990', 10);
3
+ async function main() {
4
+ const browser = await puppeteer.connect({
5
+ browserURL: `http://127.0.0.1:${port}`,
6
+ defaultViewport: null,
7
+ });
8
+ const pages = await browser.pages();
9
+ let targetPage = null;
10
+ for (const page of pages) {
11
+ const url = page.url();
12
+ if (url.includes('chatgpt.com/c/')) {
13
+ targetPage = page;
14
+ break;
15
+ }
16
+ }
17
+ if (!targetPage) {
18
+ console.error('ChatGPT conversation page not found');
19
+ process.exit(1);
20
+ }
21
+ console.error('Found page:', await targetPage.url());
22
+ // Extract the last assistant message
23
+ const content = (await targetPage.evaluate(() => {
24
+ // Try multiple selectors for ChatGPT's assistant messages
25
+ const selectors = [
26
+ '[data-message-author-role="assistant"] .markdown',
27
+ '[data-message-author-role="assistant"]',
28
+ '.agent-turn .markdown',
29
+ '.agent-turn',
30
+ ];
31
+ for (const selector of selectors) {
32
+ const elements = document.querySelectorAll(selector);
33
+ if (elements.length > 0) {
34
+ const lastEl = elements[elements.length - 1];
35
+ return {
36
+ selector,
37
+ count: elements.length,
38
+ text: lastEl.innerText,
39
+ };
40
+ }
41
+ }
42
+ // Debug: show what's on the page
43
+ const body = document.body.innerHTML;
44
+ return { error: 'No messages found', bodyLength: body.length, sample: body.slice(0, 2000) };
45
+ }));
46
+ if ('error' in content) {
47
+ console.error('Error:', JSON.stringify(content, null, 2));
48
+ process.exit(1);
49
+ }
50
+ console.log(content.text);
51
+ browser.disconnect();
52
+ }
53
+ main().catch(console.error);
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env tsx
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
+ const docsListFile = fileURLToPath(import.meta.url);
7
+ const docsListDir = dirname(docsListFile);
8
+ const DOCS_DIR = join(docsListDir, '..', 'docs');
9
+ const EXCLUDED_DIRS = new Set(['archive', 'research']);
10
+ function walkMarkdownFiles(dir, base = dir) {
11
+ const entries = readdirSync(dir, { withFileTypes: true });
12
+ const files = [];
13
+ for (const entry of entries) {
14
+ if (entry.name.startsWith('.')) {
15
+ continue;
16
+ }
17
+ const fullPath = join(dir, entry.name);
18
+ if (entry.isDirectory()) {
19
+ if (EXCLUDED_DIRS.has(entry.name)) {
20
+ continue;
21
+ }
22
+ files.push(...walkMarkdownFiles(fullPath, base));
23
+ }
24
+ else if (entry.isFile() && entry.name.endsWith('.md')) {
25
+ files.push(relative(base, fullPath));
26
+ }
27
+ }
28
+ return files.sort((a, b) => a.localeCompare(b));
29
+ }
30
+ function extractMetadata(fullPath) {
31
+ const content = readFileSync(fullPath, 'utf8');
32
+ if (!content.startsWith('---')) {
33
+ return { summary: null, readWhen: [], error: 'missing front matter' };
34
+ }
35
+ const endIndex = content.indexOf('\n---', 3);
36
+ if (endIndex === -1) {
37
+ return { summary: null, readWhen: [], error: 'unterminated front matter' };
38
+ }
39
+ const frontMatter = content.slice(3, endIndex).trim();
40
+ const lines = frontMatter.split('\n');
41
+ let summaryLine = null;
42
+ const readWhen = [];
43
+ let collectingField = null;
44
+ for (const rawLine of lines) {
45
+ const line = rawLine.trim();
46
+ if (line.startsWith('summary:')) {
47
+ summaryLine = line;
48
+ collectingField = null;
49
+ continue;
50
+ }
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
+ try {
56
+ const parsed = JSON.parse(inline.replace(/'/g, '"'));
57
+ if (Array.isArray(parsed)) {
58
+ readWhen.push(...compact(parsed.map((item) => String(item).trim())));
59
+ }
60
+ }
61
+ catch {
62
+ // ignore malformed inline arrays
63
+ }
64
+ }
65
+ continue;
66
+ }
67
+ if (collectingField === 'read_when') {
68
+ if (line.startsWith('- ')) {
69
+ const hint = line.slice(2).trim();
70
+ if (hint) {
71
+ readWhen.push(hint);
72
+ }
73
+ }
74
+ else if (line === '') {
75
+ }
76
+ else {
77
+ collectingField = null;
78
+ }
79
+ }
80
+ }
81
+ if (!summaryLine) {
82
+ return { summary: null, readWhen, error: 'summary key missing' };
83
+ }
84
+ const summaryValue = summaryLine.slice('summary:'.length).trim();
85
+ const normalized = summaryValue
86
+ .replace(/^['"]|['"]$/g, '')
87
+ .replace(/\s+/g, ' ')
88
+ .trim();
89
+ if (!normalized) {
90
+ return { summary: null, readWhen, error: 'summary is empty' };
91
+ }
92
+ return { summary: normalized, readWhen };
93
+ }
94
+ console.log('Listing all markdown files in docs folder:');
95
+ const markdownFiles = walkMarkdownFiles(DOCS_DIR);
96
+ for (const relativePath of markdownFiles) {
97
+ const fullPath = join(DOCS_DIR, relativePath);
98
+ const { summary, readWhen, error } = extractMetadata(fullPath);
99
+ if (summary) {
100
+ console.log(`${relativePath} - ${summary}`);
101
+ if (readWhen.length > 0) {
102
+ console.log(` Read when: ${readWhen.join('; ')}`);
103
+ }
104
+ }
105
+ else {
106
+ const reason = error ? ` - [${error}]` : '';
107
+ console.log(`${relativePath}${reason}`);
108
+ }
109
+ }
110
+ console.log('\nReminder: keep docs up to date as behavior changes. When your task matches any "Read when" hint above (React hooks, cache directives, database work, tests, etc.), read that doc before coding, and suggest new coverage when it is missing.');
@@ -0,0 +1,125 @@
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
+ const DESTRUCTIVE_SUBCOMMANDS = new Set([
5
+ 'reset',
6
+ 'checkout',
7
+ 'clean',
8
+ 'restore',
9
+ 'switch',
10
+ 'stash',
11
+ 'branch',
12
+ 'filter-branch',
13
+ 'fast-import',
14
+ ]);
15
+ export function extractGitInvocation(commandArgs) {
16
+ for (const [index, token] of commandArgs.entries()) {
17
+ if (token === 'git' || token.endsWith('/git')) {
18
+ return { index, argv: commandArgs.slice(index) };
19
+ }
20
+ }
21
+ return null;
22
+ }
23
+ export function findGitSubcommand(commandArgs) {
24
+ if (commandArgs.length <= 1) {
25
+ return null;
26
+ }
27
+ const optionsWithValue = new Set(['-C', '--git-dir', '--work-tree', '-c']);
28
+ let index = 1;
29
+ while (index < commandArgs.length) {
30
+ const token = commandArgs[index];
31
+ if (token === undefined) {
32
+ break;
33
+ }
34
+ if (token === '--') {
35
+ const next = commandArgs[index + 1];
36
+ return next ? { name: next, index: index + 1 } : null;
37
+ }
38
+ if (!token.startsWith('-')) {
39
+ return { name: token, index };
40
+ }
41
+ if (token.includes('=')) {
42
+ index += 1;
43
+ continue;
44
+ }
45
+ if (optionsWithValue.has(token)) {
46
+ index += 2;
47
+ continue;
48
+ }
49
+ index += 1;
50
+ }
51
+ return null;
52
+ }
53
+ export function determineGitWorkdir(baseDir, gitArgs, command) {
54
+ let workDir = baseDir;
55
+ const limit = command ? command.index : gitArgs.length;
56
+ let index = 1;
57
+ while (index < limit) {
58
+ const token = gitArgs[index];
59
+ if (token === undefined) {
60
+ break;
61
+ }
62
+ if (token === '-C') {
63
+ const next = gitArgs[index + 1];
64
+ if (next) {
65
+ workDir = resolve(workDir, next);
66
+ }
67
+ index += 2;
68
+ continue;
69
+ }
70
+ if (token.startsWith('-C')) {
71
+ const pathSegment = token.slice(2);
72
+ if (pathSegment.length > 0) {
73
+ workDir = resolve(workDir, pathSegment);
74
+ }
75
+ }
76
+ index += 1;
77
+ }
78
+ return workDir;
79
+ }
80
+ export function analyzeGitExecution(commandArgs, workspaceDir) {
81
+ const invocation = extractGitInvocation(commandArgs);
82
+ const command = invocation ? findGitSubcommand(invocation.argv) : null;
83
+ const workDir = invocation ? determineGitWorkdir(workspaceDir, invocation.argv, command) : workspaceDir;
84
+ return {
85
+ invocation,
86
+ command,
87
+ subcommand: command?.name ?? null,
88
+ workDir,
89
+ };
90
+ }
91
+ export function requiresCommitHelper(subcommand) {
92
+ if (!subcommand) {
93
+ return false;
94
+ }
95
+ return COMMIT_HELPER_SUBCOMMANDS.has(subcommand);
96
+ }
97
+ export function requiresExplicitGitConsent(subcommand) {
98
+ if (!subcommand) {
99
+ return false;
100
+ }
101
+ return GUARDED_SUBCOMMANDS.has(subcommand);
102
+ }
103
+ export function isDestructiveGitSubcommand(command, gitArgv) {
104
+ if (!command) {
105
+ return false;
106
+ }
107
+ const subcommand = command.name;
108
+ if (DESTRUCTIVE_SUBCOMMANDS.has(subcommand)) {
109
+ return true;
110
+ }
111
+ if (subcommand === 'bisect') {
112
+ const action = gitArgv[command.index + 1] ?? '';
113
+ return action === 'reset';
114
+ }
115
+ return false;
116
+ }
117
+ export function evaluateGitPolicies(context) {
118
+ const invocationArgv = context.invocation?.argv;
119
+ const normalizedArgv = Array.isArray(invocationArgv) ? invocationArgv : [];
120
+ return {
121
+ requiresCommitHelper: requiresCommitHelper(context.subcommand),
122
+ requiresExplicitConsent: requiresExplicitGitConsent(context.subcommand),
123
+ isDestructive: isDestructiveGitSubcommand(context.command, normalizedArgv),
124
+ };
125
+ }
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ import { spawn } from 'node:child_process';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ const rawArgs = process.argv.slice(2);
6
+ const args = rawArgs[0] === '--' ? rawArgs.slice(1) : rawArgs;
7
+ const here = path.dirname(fileURLToPath(import.meta.url));
8
+ const cliEntry = path.join(here, '../bin/oracle-cli.js');
9
+ const child = spawn(process.execPath, ['--', cliEntry, ...args], {
10
+ stdio: 'inherit',
11
+ });
12
+ child.on('exit', (code) => {
13
+ process.exit(code ?? 0);
14
+ });