@livedesk/hub 0.1.16 → 0.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livedesk/hub",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "description": "LiveDesk local Hub API and browser frame bridge",
5
5
  "type": "module",
6
6
  "main": "src/server.js",
@@ -94,15 +94,6 @@ export function createAgentManager({
94
94
  async deleteApiKey() {
95
95
  return publicSettings();
96
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
97
  async testConnection() {
107
98
  if (!runtime) throw new AgentProviderError('codex-sdk-not-installed', 'Codex SDK is not installed.', { status: 503 });
108
99
  statusCache = { expiresAt: 0, value: null };
@@ -4,14 +4,11 @@ import path from 'node:path';
4
4
 
5
5
  export const AGENT_PROVIDER_CODEX = 'codex';
6
6
  export const DEFAULT_AGENT_PROVIDER = AGENT_PROVIDER_CODEX;
7
- export const DEFAULT_CODEX_MODEL_ID = '';
8
7
  export const DEFAULT_AGENT_WORKSPACE = path.join(os.homedir(), '.livedesk', 'agent-workspace');
9
8
  export const DEFAULT_AGENT_SETTINGS = Object.freeze({
10
- settingsVersion: 3,
9
+ settingsVersion: 4,
11
10
  enabled: true,
12
11
  provider: DEFAULT_AGENT_PROVIDER,
13
- codexModelId: DEFAULT_CODEX_MODEL_ID,
14
- codexReasoningEffort: 'medium',
15
12
  codexSandboxMode: 'read-only',
16
13
  codexApprovalPolicy: 'never',
17
14
  codexWorkingDirectory: DEFAULT_AGENT_WORKSPACE,
@@ -25,20 +22,6 @@ export const DEFAULT_AGENT_SETTINGS = Object.freeze({
25
22
  maxConcurrentRequests: 2
26
23
  });
27
24
 
28
- const REASONING_EFFORTS = new Set(['minimal', 'low', 'medium', 'high', 'xhigh']);
29
- const SANDBOX_MODES = new Set(['read-only', 'workspace-write', 'danger-full-access']);
30
- const APPROVAL_POLICIES = new Set(['never', 'on-request', 'on-failure', 'untrusted']);
31
- const WEB_SEARCH_MODES = new Set(['disabled', 'cached', 'live']);
32
-
33
- export class AgentSettingsError extends Error {
34
- constructor(code, message) {
35
- super(message);
36
- this.name = 'AgentSettingsError';
37
- this.code = code;
38
- this.status = 400;
39
- }
40
- }
41
-
42
25
  function booleanValue(value, fallback) {
43
26
  return typeof value === 'boolean' ? value : fallback;
44
27
  }
@@ -50,18 +33,7 @@ function numberValue(value, min, max, fallback, integer = false) {
50
33
  return integer ? Math.round(clamped) : clamped;
51
34
  }
52
35
 
53
- function stringValue(value, fallback, maxLength = 240) {
54
- if (typeof value !== 'string') return fallback;
55
- return value.trim().slice(0, maxLength);
56
- }
57
-
58
- function enumValue(value, allowed, fallback, code) {
59
- const normalized = stringValue(value, fallback, 80).toLowerCase();
60
- if (!allowed.has(normalized)) throw new AgentSettingsError(code, `Invalid agent setting: ${normalized}.`);
61
- return normalized;
62
- }
63
-
64
- function normalizeWorkingDirectory(value) {
36
+ function normalizeWorkingDirectory() {
65
37
  // The agent runtime owns this directory. Do not allow a browser/API caller
66
38
  // to move Codex into a user project or an arbitrary filesystem root.
67
39
  return DEFAULT_AGENT_WORKSPACE;
@@ -70,18 +42,16 @@ function normalizeWorkingDirectory(value) {
70
42
  export function normalizeAgentSettings(value = {}) {
71
43
  const source = value && typeof value === 'object' && !Array.isArray(value) ? value : {};
72
44
  return {
73
- settingsVersion: 3,
45
+ settingsVersion: 4,
74
46
  enabled: booleanValue(source.enabled, DEFAULT_AGENT_SETTINGS.enabled),
75
47
  // LiveDesk has one Agent runtime. Old provider values are deliberately
76
48
  // normalized to Codex so an upgrade cannot reactivate a retired provider.
77
49
  provider: AGENT_PROVIDER_CODEX,
78
- codexModelId: stringValue(source.codexModelId, DEFAULT_AGENT_SETTINGS.codexModelId, 160),
79
- codexReasoningEffort: enumValue(source.codexReasoningEffort, REASONING_EFFORTS, DEFAULT_AGENT_SETTINGS.codexReasoningEffort, 'agent-invalid-reasoning-effort'),
80
50
  // These are safety settings, not user-controlled execution toggles. They
81
51
  // are accepted for compatibility but always normalized to the safe floor.
82
52
  codexSandboxMode: 'read-only',
83
53
  codexApprovalPolicy: 'never',
84
- codexWorkingDirectory: normalizeWorkingDirectory(source.codexWorkingDirectory),
54
+ codexWorkingDirectory: normalizeWorkingDirectory(),
85
55
  codexTaskTimeoutMs: numberValue(source.codexTaskTimeoutMs, 30000, 1800000, DEFAULT_AGENT_SETTINGS.codexTaskTimeoutMs, true),
86
56
  codexMaxTurns: numberValue(source.codexMaxTurns, 1, 40, DEFAULT_AGENT_SETTINGS.codexMaxTurns, true),
87
57
  codexMaxToolCalls: numberValue(source.codexMaxToolCalls, 1, 100, DEFAULT_AGENT_SETTINGS.codexMaxToolCalls, true),
@@ -66,15 +66,13 @@ function normalizeCodexError(error) {
66
66
  return new AgentProviderError('codex-run-failed', message, { status: 502, retryable: true });
67
67
  }
68
68
 
69
- function codexThreadOptions(settings, workspace) {
70
- return {
71
- model: settings.codexModelId || undefined,
72
- sandboxMode: 'read-only',
73
- approvalPolicy: 'never',
74
- workingDirectory: workspace,
75
- skipGitRepoCheck: true,
76
- modelReasoningEffort: settings.codexReasoningEffort,
77
- networkAccessEnabled: false,
69
+ function codexThreadOptions(workspace) {
70
+ return {
71
+ sandboxMode: 'read-only',
72
+ approvalPolicy: 'never',
73
+ workingDirectory: workspace,
74
+ skipGitRepoCheck: true,
75
+ networkAccessEnabled: false,
78
76
  webSearchMode: 'disabled',
79
77
  webSearchEnabled: false,
80
78
  additionalDirectories: []
@@ -417,10 +415,10 @@ export function createCodexAgentRuntime({
417
415
  const controller = new AbortController();
418
416
  const timer = setTimeout(() => controller.abort(), Math.min(30000, settings.codexTaskTimeoutMs));
419
417
  try {
420
- const thread = codex.startThread(codexThreadOptions(settings, workspace));
421
- const turn = await thread.run('Reply with the single word READY. Do not use tools.', { signal: controller.signal });
422
- if (!String(turn.finalResponse || '').trim()) throw new AgentProviderError('codex-empty-response', 'Codex returned an empty response.', { status: 502 });
423
- return { ok: true, modelId: settings.codexModelId || 'Codex default', modelName: settings.codexModelId || 'Codex default', latencyMs: Date.now() - startedAt, threadId: thread.id || '' };
418
+ const thread = codex.startThread(codexThreadOptions(workspace));
419
+ const turn = await thread.run('Reply with the single word READY. Do not use tools.', { signal: controller.signal });
420
+ if (!String(turn.finalResponse || '').trim()) throw new AgentProviderError('codex-empty-response', 'Codex returned an empty response.', { status: 502 });
421
+ return { ok: true, latencyMs: Date.now() - startedAt, threadId: thread.id || '' };
424
422
  } catch (error) {
425
423
  throw normalizeCodexError(error);
426
424
  } finally {
@@ -531,7 +529,7 @@ export function createCodexAgentRuntime({
531
529
  if (run.abortReason === 'timeout') throw codexAbortError('codex-run-timeout', 'The Codex task exceeded its timeout.');
532
530
  throw Object.assign(new Error('The Codex task was cancelled.'), { name: 'AbortError' });
533
531
  }
534
- const threadOptions = codexThreadOptions(settings, workspace);
532
+ const threadOptions = codexThreadOptions(workspace);
535
533
  run.status = 'running';
536
534
  run.updatedAt = new Date().toISOString();
537
535
  for (let attempt = 0; attempt < 2; attempt += 1) {
package/src/server.js CHANGED
@@ -2955,14 +2955,14 @@ app.delete('/api/settings/agent/api-key', async (_req, res) => {
2955
2955
  }
2956
2956
  });
2957
2957
 
2958
- app.get('/api/settings/agent/models', async (_req, res) => {
2959
- noStore(res);
2960
- try {
2961
- res.json({ ok: true, models: await agentManager.getModels() });
2962
- } catch (error) {
2963
- sendAgentError(res, error);
2964
- }
2965
- });
2958
+ app.get('/api/settings/agent/models', async (_req, res) => {
2959
+ noStore(res);
2960
+ res.status(410).json({
2961
+ ok: false,
2962
+ error: 'agent-model-catalog-retired',
2963
+ message: 'LiveDesk uses the Codex SDK defaults and does not manage models.'
2964
+ });
2965
+ });
2966
2966
 
2967
2967
  app.post('/api/settings/agent/test', async (_req, res) => {
2968
2968
  noStore(res);