neoagent 2.3.1-beta.16 → 2.3.1-beta.17
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/.env.example +20 -0
- package/lib/manager.js +4 -0
- package/package.json +1 -1
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/services/ai/providers/openai.js +2 -1
- package/server/services/ai/providers/openaiCodex.js +6 -1
- package/server/services/desktop/screenRecorder.js +54 -8
package/.env.example
CHANGED
|
@@ -98,6 +98,18 @@ GOOGLE_AI_KEY=your-google-ai-key-here
|
|
|
98
98
|
# • MiniMax-M2.7 via the Anthropic-compatible MiniMax endpoint
|
|
99
99
|
MINIMAX_API_KEY=your-minimax-api-key-here
|
|
100
100
|
|
|
101
|
+
# GitHub Copilot OAuth token — used for:
|
|
102
|
+
# • Copilot-backed chat/coding models (gpt-5.3, gpt-4.1)
|
|
103
|
+
# Set via: neoagent login github-copilot
|
|
104
|
+
GITHUB_COPILOT_ACCESS_TOKEN=
|
|
105
|
+
|
|
106
|
+
# OpenAI Codex OAuth token — used for:
|
|
107
|
+
# • Codex-backed chat/coding models (gpt-5.3-codex, gpt-4.1-codex)
|
|
108
|
+
# Set via: neoagent login openai-codex
|
|
109
|
+
OPENAI_CODEX_ACCESS_TOKEN=
|
|
110
|
+
# Optional refresh token if your login flow returns it.
|
|
111
|
+
OPENAI_CODEX_REFRESH_TOKEN=
|
|
112
|
+
|
|
101
113
|
########################################
|
|
102
114
|
# Provider endpoint overrides
|
|
103
115
|
########################################
|
|
@@ -105,6 +117,10 @@ MINIMAX_API_KEY=your-minimax-api-key-here
|
|
|
105
117
|
# OPENAI_BASE_URL=https://your-openai-compatible-endpoint/v1
|
|
106
118
|
# ANTHROPIC_BASE_URL=https://your-anthropic-compatible-endpoint
|
|
107
119
|
# XAI_BASE_URL=https://api.x.ai/v1
|
|
120
|
+
# OPENAI_CODEX_BASE_URL=https://chatgpt.com/backend-api/codex
|
|
121
|
+
# OPENAI_CODEX_EDITOR_VERSION=vscode/1.99.0
|
|
122
|
+
# OPENAI_CODEX_EDITOR_PLUGIN_VERSION=neoagent/1.0.0
|
|
123
|
+
# OPENAI_CODEX_USER_AGENT=NeoAgent/1.0.0
|
|
108
124
|
|
|
109
125
|
########################################
|
|
110
126
|
# Official integrations
|
|
@@ -176,6 +192,10 @@ DEEPGRAM_LANGUAGE=multi
|
|
|
176
192
|
|
|
177
193
|
OLLAMA_URL=http://localhost:11434
|
|
178
194
|
|
|
195
|
+
# Local screen OCR capture (macOS desktop context recorder).
|
|
196
|
+
# Set to false to disable background screen capture/OCR polling.
|
|
197
|
+
NEOAGENT_SCREEN_RECORDER_ENABLED=true
|
|
198
|
+
|
|
179
199
|
########################################
|
|
180
200
|
# Messaging and voice integrations
|
|
181
201
|
########################################
|
package/lib/manager.js
CHANGED
|
@@ -726,6 +726,8 @@ async function cmdLogin(args = []) {
|
|
|
726
726
|
if (data.access_token) {
|
|
727
727
|
upsertEnvValue('GITHUB_COPILOT_ACCESS_TOKEN', data.access_token);
|
|
728
728
|
logOk('Successfully authenticated and saved GitHub Copilot access token to .env');
|
|
729
|
+
logInfo('Applying updated provider credentials by restarting NeoAgent...');
|
|
730
|
+
cmdRestart();
|
|
729
731
|
return;
|
|
730
732
|
} else if (data.error === 'authorization_pending') {
|
|
731
733
|
// Continue polling
|
|
@@ -830,6 +832,8 @@ async function cmdLogin(args = []) {
|
|
|
830
832
|
upsertEnvValue('OPENAI_CODEX_REFRESH_TOKEN', exchangeData.refresh_token);
|
|
831
833
|
}
|
|
832
834
|
logOk('Successfully authenticated and saved OpenAI Codex tokens to .env');
|
|
835
|
+
logInfo('Applying updated provider credentials by restarting NeoAgent...');
|
|
836
|
+
cmdRestart();
|
|
833
837
|
} else {
|
|
834
838
|
throw new Error('OpenAI token exchange succeeded but did not return an access token.');
|
|
835
839
|
}
|
package/package.json
CHANGED
|
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"59aa584fdf100e6c78c785d8a5b565d1de4b48
|
|
|
37
37
|
|
|
38
38
|
_flutter.loader.load({
|
|
39
39
|
serviceWorkerSettings: {
|
|
40
|
-
serviceWorkerVersion: "
|
|
40
|
+
serviceWorkerVersion: "2875227471" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
|
|
41
41
|
}
|
|
42
42
|
});
|
|
@@ -29,7 +29,8 @@ class OpenAIProvider extends BaseProvider {
|
|
|
29
29
|
};
|
|
30
30
|
this.client = new OpenAI({
|
|
31
31
|
apiKey: config.apiKey || process.env.OPENAI_API_KEY,
|
|
32
|
-
baseURL: config.baseUrl || process.env.OPENAI_BASE_URL || undefined
|
|
32
|
+
baseURL: config.baseUrl || process.env.OPENAI_BASE_URL || undefined,
|
|
33
|
+
defaultHeaders: config.defaultHeaders || undefined
|
|
33
34
|
});
|
|
34
35
|
}
|
|
35
36
|
|
|
@@ -14,7 +14,12 @@ class OpenAICodexProvider extends OpenAIProvider {
|
|
|
14
14
|
super({
|
|
15
15
|
...config,
|
|
16
16
|
apiKey: config.apiKey || process.env.OPENAI_CODEX_ACCESS_TOKEN,
|
|
17
|
-
baseUrl
|
|
17
|
+
baseUrl,
|
|
18
|
+
defaultHeaders: {
|
|
19
|
+
'Editor-Version': process.env.OPENAI_CODEX_EDITOR_VERSION || 'vscode/1.99.0',
|
|
20
|
+
'Editor-Plugin-Version': process.env.OPENAI_CODEX_EDITOR_PLUGIN_VERSION || 'neoagent/1.0.0',
|
|
21
|
+
'User-Agent': process.env.OPENAI_CODEX_USER_AGENT || 'NeoAgent/1.0.0'
|
|
22
|
+
}
|
|
18
23
|
});
|
|
19
24
|
this.name = 'openai-codex';
|
|
20
25
|
}
|
|
@@ -19,9 +19,42 @@ class ScreenRecorder {
|
|
|
19
19
|
this.isRecording = false;
|
|
20
20
|
this.isProcessing = false;
|
|
21
21
|
this.tempFilePath = path.join(os.tmpdir(), `neoagent-screen-${Date.now()}.png`);
|
|
22
|
+
this.lastBenignSkipAt = 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
_isCaptureInactiveApp(appName) {
|
|
26
|
+
const normalized = String(appName || '').trim().toLowerCase();
|
|
27
|
+
return normalized === '' || normalized === 'loginwindow' || normalized === 'screensaverengine';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
_isBenignCaptureError(message) {
|
|
31
|
+
const text = String(message || '').toLowerCase();
|
|
32
|
+
return (
|
|
33
|
+
text.includes('operation not permitted') ||
|
|
34
|
+
text.includes('not authorized') ||
|
|
35
|
+
text.includes('user canceled') ||
|
|
36
|
+
text.includes('cgwindowlistcreateimage') ||
|
|
37
|
+
text.includes('screencapture') ||
|
|
38
|
+
text.includes('timed out')
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
_logBenignSkip(reason) {
|
|
43
|
+
const now = Date.now();
|
|
44
|
+
if (now - this.lastBenignSkipAt < 5 * 60 * 1000) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
this.lastBenignSkipAt = now;
|
|
48
|
+
console.warn(`[ScreenRecorder] Capture skipped: ${reason}`);
|
|
22
49
|
}
|
|
23
50
|
|
|
24
51
|
start() {
|
|
52
|
+
const enabledEnv = String(process.env.NEOAGENT_SCREEN_RECORDER_ENABLED || '').trim().toLowerCase();
|
|
53
|
+
if (enabledEnv === '0' || enabledEnv === 'false' || enabledEnv === 'off' || enabledEnv === 'no') {
|
|
54
|
+
console.log('[ScreenRecorder] Not starting: disabled by NEOAGENT_SCREEN_RECORDER_ENABLED.');
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
25
58
|
if (process.platform !== 'darwin') {
|
|
26
59
|
console.log('[ScreenRecorder] Not starting: Screen recording is currently macOS only.');
|
|
27
60
|
return;
|
|
@@ -61,6 +94,20 @@ class ScreenRecorder {
|
|
|
61
94
|
this.isProcessing = true;
|
|
62
95
|
|
|
63
96
|
try {
|
|
97
|
+
// Skip capture when the desktop session is inactive (e.g. locked screen).
|
|
98
|
+
let frontmostApp = '';
|
|
99
|
+
try {
|
|
100
|
+
const { stdout } = await execAsync(`osascript -e 'tell application "System Events" to get name of first application process whose frontmost is true'`);
|
|
101
|
+
frontmostApp = (stdout || '').trim();
|
|
102
|
+
} catch {
|
|
103
|
+
frontmostApp = '';
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (this._isCaptureInactiveApp(frontmostApp)) {
|
|
107
|
+
this._logBenignSkip('no active frontmost app');
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
64
111
|
// Capture screen silently (-x) to file
|
|
65
112
|
await execAsync(`screencapture -x "${this.tempFilePath}"`);
|
|
66
113
|
|
|
@@ -80,13 +127,7 @@ class ScreenRecorder {
|
|
|
80
127
|
const userRow = db.prepare('SELECT id FROM users ORDER BY id ASC LIMIT 1').get();
|
|
81
128
|
if (userRow) {
|
|
82
129
|
// Identify the active foreground app via AppleScript
|
|
83
|
-
let appName = 'Unknown';
|
|
84
|
-
try {
|
|
85
|
-
const { stdout } = await execAsync(`osascript -e 'tell application "System Events" to get name of first application process whose frontmost is true'`);
|
|
86
|
-
appName = stdout.trim();
|
|
87
|
-
} catch (e) {
|
|
88
|
-
// Ignore AppleScript errors
|
|
89
|
-
}
|
|
130
|
+
let appName = frontmostApp || 'Unknown';
|
|
90
131
|
|
|
91
132
|
db.prepare(`
|
|
92
133
|
INSERT INTO screen_history (user_id, app_name, text_content)
|
|
@@ -96,7 +137,12 @@ class ScreenRecorder {
|
|
|
96
137
|
}
|
|
97
138
|
|
|
98
139
|
} catch (err) {
|
|
99
|
-
|
|
140
|
+
const errorMessage = getErrorMessage(err);
|
|
141
|
+
if (this._isBenignCaptureError(errorMessage)) {
|
|
142
|
+
this._logBenignSkip(errorMessage);
|
|
143
|
+
} else {
|
|
144
|
+
console.error('[ScreenRecorder] Capture/OCR failed:', errorMessage);
|
|
145
|
+
}
|
|
100
146
|
} finally {
|
|
101
147
|
// Always cleanup the screenshot image immediately
|
|
102
148
|
try {
|