@livedesk/hub 0.1.14 → 0.1.16
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/package.json +1 -1
- package/src/agents/agent-manager.js +132 -175
- package/src/agents/agent-settings.js +7 -68
- package/src/agents/agent-tool-registry.js +1 -1
- package/src/agents/codex-agent-runtime.js +2 -2
- package/src/remote-hub.js +92 -124
- package/src/server.js +50 -38
- package/src/transport/relay-hub-control.js +48 -7
- package/src/agents/opencode-go-provider.js +0 -260
- package/src/agents/secret-store.js +0 -165
package/package.json
CHANGED
|
@@ -1,175 +1,132 @@
|
|
|
1
|
-
import os from 'node:os';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import { AgentSettingsStore, AGENT_PROVIDER_CODEX
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
},
|
|
134
|
-
async testConnection() {
|
|
135
|
-
const { current, active } = await currentProvider();
|
|
136
|
-
if (current.provider === AGENT_PROVIDER_CODEX) {
|
|
137
|
-
if (!active) throw new AgentProviderError('codex-sdk-not-installed', 'Codex SDK is not installed.', { status: 503 });
|
|
138
|
-
statusCache = { expiresAt: 0, value: null };
|
|
139
|
-
return active.testConnection();
|
|
140
|
-
}
|
|
141
|
-
return active.testConnection(current, await legacyApiKey());
|
|
142
|
-
},
|
|
143
|
-
async createPlan(input) {
|
|
144
|
-
const { current, active } = await currentProvider();
|
|
145
|
-
if (!current.enabled) throw new AgentProviderError('agent-ai-disabled', 'Agent AI is disabled in Settings.', { status: 409 });
|
|
146
|
-
if (current.provider === AGENT_PROVIDER_CODEX) {
|
|
147
|
-
throw new AgentProviderError('agent-codex-run-required', 'Codex runs use the LiveDesk tool loop.', { status: 409 });
|
|
148
|
-
}
|
|
149
|
-
return active.createPlan(input, current, await legacyApiKey());
|
|
150
|
-
},
|
|
151
|
-
async createSummary(input) {
|
|
152
|
-
const { current, active } = await currentProvider();
|
|
153
|
-
if (!current.enabled || !current.generateSummary) throw new AgentProviderError('agent-summary-disabled', 'Agent summaries are disabled in Settings.', { status: 409 });
|
|
154
|
-
if (current.provider === AGENT_PROVIDER_CODEX) {
|
|
155
|
-
const source = input && typeof input === 'object' ? input : {};
|
|
156
|
-
const results = Array.isArray(source.results) ? source.results : [];
|
|
157
|
-
return { summary: String(results.length ? `${source.completed || 0} completed, ${source.failed || 0} failed.` : 'LiveDesk Agent run completed.').slice(0, 1200), modelId: current.codexModelId || 'Codex default' };
|
|
158
|
-
}
|
|
159
|
-
const source = input && typeof input === 'object' ? input : {};
|
|
160
|
-
const results = Array.isArray(source.results) ? source.results : [];
|
|
161
|
-
const safeResults = current.includeRawDeviceDetails
|
|
162
|
-
? results.map(result => ({ deviceName: String(result?.deviceName || '').slice(0, 120), status: String(result?.status || '').slice(0, 40), result: String(result?.result || '').slice(0, 1200), error: String(result?.error || '').slice(0, 500) }))
|
|
163
|
-
: results.map(result => ({ deviceName: String(result?.deviceName || '').slice(0, 120), status: String(result?.status || '').slice(0, 40), hasResult: Boolean(result?.result), hasError: Boolean(result?.error) }));
|
|
164
|
-
return active.createSummary({ instruction: String(source.instruction || '').slice(0, 500), operation: String(source.operation || '').slice(0, 80), summary: { total: Number(source.total || results.length), completed: Number(source.completed || 0), failed: Number(source.failed || 0), results: safeResults } }, current, await legacyApiKey());
|
|
165
|
-
},
|
|
166
|
-
async startRun(input) {
|
|
167
|
-
const current = await settings.get();
|
|
168
|
-
if (current.provider !== AGENT_PROVIDER_CODEX || !runtime) throw new AgentProviderError('agent-codex-not-active', 'Codex SDK is not the active Agent provider.', { status: 409 });
|
|
169
|
-
return runtime.start(input);
|
|
170
|
-
},
|
|
171
|
-
getRun(runId) { return runtime?.get(runId) || null; },
|
|
172
|
-
cancelRun(runId) { return runtime?.cancel(runId) || null; },
|
|
173
|
-
cancelAllRuns() { return runtime?.cancelAll?.() || 0; }
|
|
174
|
-
};
|
|
175
|
-
}
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { AgentSettingsStore, AGENT_PROVIDER_CODEX } from './agent-settings.js';
|
|
4
|
+
import { AgentProviderError } from './provider-errors.js';
|
|
5
|
+
|
|
6
|
+
function publicCodexStatus(status = {}) {
|
|
7
|
+
return {
|
|
8
|
+
installed: status.installed === true,
|
|
9
|
+
authenticated: ['signed-in', 'not-signed-in'].includes(status.authenticated) ? status.authenticated : 'unknown',
|
|
10
|
+
status: String(status.status || 'unknown').slice(0, 40),
|
|
11
|
+
codexPath: String(status.codexPath || '').slice(0, 500),
|
|
12
|
+
detail: String(status.detail || '').slice(0, 300)
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function createAgentManager({
|
|
17
|
+
dataDir = path.join(os.homedir(), '.livedesk'),
|
|
18
|
+
settingsStore,
|
|
19
|
+
codexRuntime
|
|
20
|
+
} = {}) {
|
|
21
|
+
const settings = settingsStore || new AgentSettingsStore({ dataDir });
|
|
22
|
+
const runtime = codexRuntime;
|
|
23
|
+
let statusCache = { expiresAt: 0, value: null };
|
|
24
|
+
|
|
25
|
+
async function getCodexStatus() {
|
|
26
|
+
if (!runtime) return { installed: false, authenticated: 'unknown', status: 'unavailable', codexPath: '' };
|
|
27
|
+
if (statusCache.value && statusCache.expiresAt > Date.now()) return statusCache.value;
|
|
28
|
+
let value;
|
|
29
|
+
try {
|
|
30
|
+
value = publicCodexStatus(await runtime.getStatus());
|
|
31
|
+
} catch (error) {
|
|
32
|
+
value = publicCodexStatus({
|
|
33
|
+
installed: true,
|
|
34
|
+
authenticated: 'unknown',
|
|
35
|
+
status: error?.code || 'security-unavailable',
|
|
36
|
+
detail: error?.message || 'Codex security isolation is unavailable.'
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
statusCache = { value, expiresAt: Date.now() + 10000 };
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function publicSettings() {
|
|
44
|
+
const current = await settings.get();
|
|
45
|
+
const { codexMaxTurns: _codexMaxTurns, ...exposedSettings } = current;
|
|
46
|
+
const codex = await getCodexStatus();
|
|
47
|
+
const securityStatus = runtime?.getSecurityStatus?.() || {
|
|
48
|
+
isolatedCodexHome: false,
|
|
49
|
+
restrictedEnvironment: false,
|
|
50
|
+
livedeskMcpOnly: false,
|
|
51
|
+
selectedDeviceScopeEnforced: false,
|
|
52
|
+
failClosed: true,
|
|
53
|
+
verified: false,
|
|
54
|
+
state: 'unavailable'
|
|
55
|
+
};
|
|
56
|
+
return {
|
|
57
|
+
...exposedSettings,
|
|
58
|
+
provider: AGENT_PROVIDER_CODEX,
|
|
59
|
+
codexInstallation: codex.installed ? 'installed' : 'not-installed',
|
|
60
|
+
codexAuth: codex.authenticated,
|
|
61
|
+
codexStatus: codex.status,
|
|
62
|
+
codexPath: codex.codexPath,
|
|
63
|
+
agentWorkspacePath: current.codexWorkingDirectory,
|
|
64
|
+
securityStatus
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
getSettings: publicSettings,
|
|
70
|
+
async updateSettings(patch = {}) {
|
|
71
|
+
const nextPatch = { ...patch };
|
|
72
|
+
const requestedProvider = String(nextPatch.provider || AGENT_PROVIDER_CODEX).trim().toLowerCase();
|
|
73
|
+
const suppliedLegacyKey = typeof nextPatch.apiKey === 'string' && nextPatch.apiKey.trim().length > 0;
|
|
74
|
+
delete nextPatch.provider;
|
|
75
|
+
delete nextPatch.apiKey;
|
|
76
|
+
if (requestedProvider !== AGENT_PROVIDER_CODEX || suppliedLegacyKey) {
|
|
77
|
+
throw new AgentProviderError(
|
|
78
|
+
'agent-provider-retired',
|
|
79
|
+
'LiveDesk uses the Hub-hosted Codex Agent and does not configure alternate model providers.',
|
|
80
|
+
{ status: 400 }
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
await settings.update({ ...nextPatch, provider: AGENT_PROVIDER_CODEX });
|
|
84
|
+
statusCache = { expiresAt: 0, value: null };
|
|
85
|
+
return publicSettings();
|
|
86
|
+
},
|
|
87
|
+
async resetSettings() {
|
|
88
|
+
await settings.reset();
|
|
89
|
+
statusCache = { expiresAt: 0, value: null };
|
|
90
|
+
return publicSettings();
|
|
91
|
+
},
|
|
92
|
+
// Kept as a harmless compatibility endpoint for an older cached web UI.
|
|
93
|
+
// No credential is read, written, or returned by the current Hub.
|
|
94
|
+
async deleteApiKey() {
|
|
95
|
+
return publicSettings();
|
|
96
|
+
},
|
|
97
|
+
async getModels() {
|
|
98
|
+
return [{
|
|
99
|
+
id: '',
|
|
100
|
+
name: 'Codex default',
|
|
101
|
+
protocol: 'codex-sdk',
|
|
102
|
+
available: true,
|
|
103
|
+
capabilities: { supportsReasoningLevel: true, supportsStreaming: true, supportsTools: true }
|
|
104
|
+
}];
|
|
105
|
+
},
|
|
106
|
+
async testConnection() {
|
|
107
|
+
if (!runtime) throw new AgentProviderError('codex-sdk-not-installed', 'Codex SDK is not installed.', { status: 503 });
|
|
108
|
+
statusCache = { expiresAt: 0, value: null };
|
|
109
|
+
return runtime.testConnection();
|
|
110
|
+
},
|
|
111
|
+
async createPlan() {
|
|
112
|
+
throw new AgentProviderError('agent-codex-run-required', 'Codex Agent requests use the LiveDesk tool loop.', { status: 409 });
|
|
113
|
+
},
|
|
114
|
+
async createSummary(input) {
|
|
115
|
+
const source = input && typeof input === 'object' ? input : {};
|
|
116
|
+
const results = Array.isArray(source.results) ? source.results : [];
|
|
117
|
+
return {
|
|
118
|
+
summary: String(results.length ? `${source.completed || 0} completed, ${source.failed || 0} failed.` : 'LiveDesk Agent run completed.').slice(0, 1200)
|
|
119
|
+
};
|
|
120
|
+
},
|
|
121
|
+
async startRun(input) {
|
|
122
|
+
const current = await settings.get();
|
|
123
|
+
if (current.provider !== AGENT_PROVIDER_CODEX || !runtime) {
|
|
124
|
+
throw new AgentProviderError('agent-codex-not-active', 'Codex SDK is not the active Agent runtime.', { status: 409 });
|
|
125
|
+
}
|
|
126
|
+
return runtime.start(input);
|
|
127
|
+
},
|
|
128
|
+
getRun(runId) { return runtime?.get(runId) || null; },
|
|
129
|
+
cancelRun(runId) { return runtime?.cancel(runId) || null; },
|
|
130
|
+
cancelAllRuns() { return runtime?.cancelAll?.() || 0; }
|
|
131
|
+
};
|
|
132
|
+
}
|
|
@@ -3,13 +3,11 @@ import os from 'node:os';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
|
|
5
5
|
export const AGENT_PROVIDER_CODEX = 'codex';
|
|
6
|
-
export const AGENT_PROVIDER_OPENCODE_GO = 'opencode-go';
|
|
7
6
|
export const DEFAULT_AGENT_PROVIDER = AGENT_PROVIDER_CODEX;
|
|
8
|
-
export const DEFAULT_AGENT_BASE_URL = 'https://opencode.ai/zen/go/v1';
|
|
9
7
|
export const DEFAULT_CODEX_MODEL_ID = '';
|
|
10
8
|
export const DEFAULT_AGENT_WORKSPACE = path.join(os.homedir(), '.livedesk', 'agent-workspace');
|
|
11
9
|
export const DEFAULT_AGENT_SETTINGS = Object.freeze({
|
|
12
|
-
settingsVersion:
|
|
10
|
+
settingsVersion: 3,
|
|
13
11
|
enabled: true,
|
|
14
12
|
provider: DEFAULT_AGENT_PROVIDER,
|
|
15
13
|
codexModelId: DEFAULT_CODEX_MODEL_ID,
|
|
@@ -24,34 +22,13 @@ export const DEFAULT_AGENT_SETTINGS = Object.freeze({
|
|
|
24
22
|
codexShowDetailedEvents: true,
|
|
25
23
|
codexNetworkAccessEnabled: false,
|
|
26
24
|
codexWebSearchMode: 'disabled',
|
|
27
|
-
|
|
28
|
-
generateSummary: true,
|
|
29
|
-
fallbackSummary: true,
|
|
30
|
-
includeRawDeviceDetails: false,
|
|
31
|
-
maxConcurrentRequests: 2,
|
|
32
|
-
baseUrl: DEFAULT_AGENT_BASE_URL,
|
|
33
|
-
defaultModelId: 'deepseek-v4-flash',
|
|
34
|
-
planModelId: '',
|
|
35
|
-
summaryModelId: '',
|
|
36
|
-
reasoningLevel: 'auto',
|
|
37
|
-
planTemperature: 0.1,
|
|
38
|
-
summaryTemperature: 0.2,
|
|
39
|
-
topP: 1,
|
|
40
|
-
planMaxOutputTokens: 1024,
|
|
41
|
-
summaryMaxOutputTokens: 1024,
|
|
42
|
-
planTimeoutMs: 60000,
|
|
43
|
-
summaryTimeoutMs: 60000,
|
|
44
|
-
retryCount: 1,
|
|
45
|
-
retryDelayMs: 1000,
|
|
46
|
-
streamSummary: false
|
|
25
|
+
maxConcurrentRequests: 2
|
|
47
26
|
});
|
|
48
27
|
|
|
49
|
-
const PROVIDERS = new Set([AGENT_PROVIDER_CODEX, AGENT_PROVIDER_OPENCODE_GO]);
|
|
50
28
|
const REASONING_EFFORTS = new Set(['minimal', 'low', 'medium', 'high', 'xhigh']);
|
|
51
29
|
const SANDBOX_MODES = new Set(['read-only', 'workspace-write', 'danger-full-access']);
|
|
52
30
|
const APPROVAL_POLICIES = new Set(['never', 'on-request', 'on-failure', 'untrusted']);
|
|
53
31
|
const WEB_SEARCH_MODES = new Set(['disabled', 'cached', 'live']);
|
|
54
|
-
const LEGACY_REASONING_LEVELS = new Set(['auto', 'low', 'medium', 'high']);
|
|
55
32
|
|
|
56
33
|
export class AgentSettingsError extends Error {
|
|
57
34
|
constructor(code, message) {
|
|
@@ -84,19 +61,6 @@ function enumValue(value, allowed, fallback, code) {
|
|
|
84
61
|
return normalized;
|
|
85
62
|
}
|
|
86
63
|
|
|
87
|
-
function normalizeBaseUrl(value) {
|
|
88
|
-
const candidate = stringValue(value, DEFAULT_AGENT_SETTINGS.baseUrl, 500).replace(/\/+$/, '');
|
|
89
|
-
try {
|
|
90
|
-
const parsed = new URL(candidate);
|
|
91
|
-
if (!['http:', 'https:'].includes(parsed.protocol) || !parsed.hostname) throw new Error('invalid protocol');
|
|
92
|
-
parsed.hash = '';
|
|
93
|
-
parsed.search = '';
|
|
94
|
-
return parsed.toString().replace(/\/+$/, '');
|
|
95
|
-
} catch {
|
|
96
|
-
throw new AgentSettingsError('agent-invalid-base-url', 'Base URL must be a valid HTTP or HTTPS URL.');
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
64
|
function normalizeWorkingDirectory(value) {
|
|
101
65
|
// The agent runtime owns this directory. Do not allow a browser/API caller
|
|
102
66
|
// to move Codex into a user project or an arbitrary filesystem root.
|
|
@@ -105,18 +69,12 @@ function normalizeWorkingDirectory(value) {
|
|
|
105
69
|
|
|
106
70
|
export function normalizeAgentSettings(value = {}) {
|
|
107
71
|
const source = value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
108
|
-
// The pre-Codex settings file was written by LiveDesk itself and had no
|
|
109
|
-
// migration marker. Keep the legacy values but move that first-run config
|
|
110
|
-
// to the new Codex default.
|
|
111
|
-
const migratingLegacy = Number(source.settingsVersion || 0) < 2 && source.provider === AGENT_PROVIDER_OPENCODE_GO;
|
|
112
|
-
const provider = migratingLegacy
|
|
113
|
-
? DEFAULT_AGENT_PROVIDER
|
|
114
|
-
: enumValue(source.provider, PROVIDERS, DEFAULT_AGENT_PROVIDER, 'agent-unsupported-provider');
|
|
115
|
-
const reasoningLevel = enumValue(source.reasoningLevel, LEGACY_REASONING_LEVELS, DEFAULT_AGENT_SETTINGS.reasoningLevel, 'agent-invalid-reasoning-level');
|
|
116
72
|
return {
|
|
117
|
-
settingsVersion:
|
|
73
|
+
settingsVersion: 3,
|
|
118
74
|
enabled: booleanValue(source.enabled, DEFAULT_AGENT_SETTINGS.enabled),
|
|
119
|
-
provider
|
|
75
|
+
// LiveDesk has one Agent runtime. Old provider values are deliberately
|
|
76
|
+
// normalized to Codex so an upgrade cannot reactivate a retired provider.
|
|
77
|
+
provider: AGENT_PROVIDER_CODEX,
|
|
120
78
|
codexModelId: stringValue(source.codexModelId, DEFAULT_AGENT_SETTINGS.codexModelId, 160),
|
|
121
79
|
codexReasoningEffort: enumValue(source.codexReasoningEffort, REASONING_EFFORTS, DEFAULT_AGENT_SETTINGS.codexReasoningEffort, 'agent-invalid-reasoning-effort'),
|
|
122
80
|
// These are safety settings, not user-controlled execution toggles. They
|
|
@@ -131,26 +89,7 @@ export function normalizeAgentSettings(value = {}) {
|
|
|
131
89
|
codexShowDetailedEvents: booleanValue(source.codexShowDetailedEvents, DEFAULT_AGENT_SETTINGS.codexShowDetailedEvents),
|
|
132
90
|
codexNetworkAccessEnabled: false,
|
|
133
91
|
codexWebSearchMode: 'disabled',
|
|
134
|
-
|
|
135
|
-
generateSummary: booleanValue(source.generateSummary, DEFAULT_AGENT_SETTINGS.generateSummary),
|
|
136
|
-
fallbackSummary: booleanValue(source.fallbackSummary, DEFAULT_AGENT_SETTINGS.fallbackSummary),
|
|
137
|
-
includeRawDeviceDetails: booleanValue(source.includeRawDeviceDetails, DEFAULT_AGENT_SETTINGS.includeRawDeviceDetails),
|
|
138
|
-
maxConcurrentRequests: numberValue(source.maxConcurrentRequests, 1, 8, DEFAULT_AGENT_SETTINGS.maxConcurrentRequests, true),
|
|
139
|
-
baseUrl: normalizeBaseUrl(source.baseUrl ?? DEFAULT_AGENT_SETTINGS.baseUrl),
|
|
140
|
-
defaultModelId: stringValue(source.defaultModelId, DEFAULT_AGENT_SETTINGS.defaultModelId, 160),
|
|
141
|
-
planModelId: stringValue(source.planModelId, DEFAULT_AGENT_SETTINGS.planModelId, 160),
|
|
142
|
-
summaryModelId: stringValue(source.summaryModelId, DEFAULT_AGENT_SETTINGS.summaryModelId, 160),
|
|
143
|
-
reasoningLevel,
|
|
144
|
-
planTemperature: numberValue(source.planTemperature, 0, 2, DEFAULT_AGENT_SETTINGS.planTemperature),
|
|
145
|
-
summaryTemperature: numberValue(source.summaryTemperature, 0, 2, DEFAULT_AGENT_SETTINGS.summaryTemperature),
|
|
146
|
-
topP: numberValue(source.topP, 0, 1, DEFAULT_AGENT_SETTINGS.topP),
|
|
147
|
-
planMaxOutputTokens: numberValue(source.planMaxOutputTokens, 128, 16384, DEFAULT_AGENT_SETTINGS.planMaxOutputTokens, true),
|
|
148
|
-
summaryMaxOutputTokens: numberValue(source.summaryMaxOutputTokens, 128, 16384, DEFAULT_AGENT_SETTINGS.summaryMaxOutputTokens, true),
|
|
149
|
-
planTimeoutMs: numberValue(source.planTimeoutMs, 5000, 180000, DEFAULT_AGENT_SETTINGS.planTimeoutMs, true),
|
|
150
|
-
summaryTimeoutMs: numberValue(source.summaryTimeoutMs, 5000, 180000, DEFAULT_AGENT_SETTINGS.summaryTimeoutMs, true),
|
|
151
|
-
retryCount: numberValue(source.retryCount, 0, 4, DEFAULT_AGENT_SETTINGS.retryCount, true),
|
|
152
|
-
retryDelayMs: numberValue(source.retryDelayMs, 100, 10000, DEFAULT_AGENT_SETTINGS.retryDelayMs, true),
|
|
153
|
-
streamSummary: booleanValue(source.streamSummary, DEFAULT_AGENT_SETTINGS.streamSummary)
|
|
92
|
+
maxConcurrentRequests: numberValue(source.maxConcurrentRequests, 1, 8, DEFAULT_AGENT_SETTINGS.maxConcurrentRequests, true)
|
|
154
93
|
};
|
|
155
94
|
}
|
|
156
95
|
|
|
@@ -79,7 +79,7 @@ export const AGENT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
79
79
|
},
|
|
80
80
|
{
|
|
81
81
|
name: 'livedesk.list_processes',
|
|
82
|
-
description: 'Read process status from the selected Clients. Use processName
|
|
82
|
+
description: 'Read process status from the selected Clients. Use processName when the request names a specific process.',
|
|
83
83
|
category: 'read',
|
|
84
84
|
readOnly: true,
|
|
85
85
|
mutating: false,
|
|
@@ -472,7 +472,7 @@ export function createCodexAgentRuntime({
|
|
|
472
472
|
'Never use arbitrary MCP servers, change permissions, forge approvals, request credentials, or invent a tool result.',
|
|
473
473
|
`The Hub has fixed this run to permission mode ${permissionPolicy?.mode || 'ask'} and enforces the policy independently of your instructions.`,
|
|
474
474
|
'Use only the selected connected device IDs below. If the Hub asks for user approval, wait for that approval result and do not work around it.',
|
|
475
|
-
'You may perform multiple safe read-only checks when the request requires a sequence. For example, find Clients
|
|
475
|
+
'You may perform multiple safe read-only checks when the request requires a sequence. For example, find Clients missing a named process, then check a related service only on those Clients.',
|
|
476
476
|
`Selected device IDs: ${JSON.stringify(deviceIds)}`,
|
|
477
477
|
'Return a concise Korean or English summary grounded only in tool results. Do not invent results.',
|
|
478
478
|
`User request: ${safeText(instruction, 4000)}`
|
|
@@ -649,7 +649,7 @@ export function createCodexAgentRuntime({
|
|
|
649
649
|
const deviceIds = safeAgentDeviceIds(input.deviceIds);
|
|
650
650
|
if (deviceIds.length === 0) throw new AgentProviderError('agent-no-target-devices', 'Select at least one connected device.', { status: 400 });
|
|
651
651
|
const settings = await settingsStore.get();
|
|
652
|
-
if (!settings.enabled) throw new AgentProviderError('agent-ai-disabled', 'Agent
|
|
652
|
+
if (!settings.enabled) throw new AgentProviderError('agent-ai-disabled', 'Codex Agent is disabled in Settings.', { status: 409 });
|
|
653
653
|
assertSecurityConfiguration();
|
|
654
654
|
pruneRuns();
|
|
655
655
|
if (runs.size >= MAX_RUNS) throw new AgentProviderError('agent-run-limit', 'The LiveDesk Agent run history is full.', { status: 429, retryable: true });
|