@adhdev/daemon-core 0.8.57 → 0.8.59
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/dist/agent-stream/types.d.ts +3 -4
- package/dist/boot/daemon-lifecycle.d.ts +1 -0
- package/dist/commands/handler.d.ts +1 -0
- package/dist/commands/router.d.ts +1 -0
- package/dist/commands/stream-commands.d.ts +3 -0
- package/dist/config/chat-history.d.ts +3 -0
- package/dist/config/config.d.ts +3 -0
- package/dist/config/provider-source-config.d.ts +23 -0
- package/dist/config/recent-activity.d.ts +2 -1
- package/dist/config/saved-sessions.d.ts +2 -1
- package/dist/daemon/dev-server-types.d.ts +1 -0
- package/dist/daemon/dev-server.d.ts +4 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +876 -337
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +875 -337
- package/dist/index.mjs.map +1 -1
- package/dist/providers/acp-provider-instance.d.ts +8 -2
- package/dist/providers/cli-provider-instance.d.ts +10 -0
- package/dist/providers/contracts.d.ts +4 -2
- package/dist/providers/extension-provider-instance.d.ts +1 -2
- package/dist/providers/provider-instance.d.ts +3 -4
- package/dist/providers/provider-loader.d.ts +14 -1
- package/dist/providers/provider-patch-state.d.ts +23 -0
- package/dist/providers/summary-metadata.d.ts +22 -0
- package/dist/shared-types.d.ts +15 -9
- package/dist/status/snapshot.d.ts +16 -1
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/agent-stream/forward.ts +1 -2
- package/src/agent-stream/manager.ts +2 -1
- package/src/agent-stream/provider-adapter.ts +7 -3
- package/src/agent-stream/types.d.ts +3 -4
- package/src/agent-stream/types.ts +3 -4
- package/src/boot/daemon-lifecycle.ts +13 -3
- package/src/commands/cli-manager.ts +10 -5
- package/src/commands/handler.ts +3 -0
- package/src/commands/router.ts +160 -26
- package/src/commands/stream-commands.ts +60 -2
- package/src/config/chat-history.ts +39 -0
- package/src/config/config.d.ts +3 -0
- package/src/config/config.ts +19 -3
- package/src/config/provider-source-config.ts +42 -0
- package/src/config/recent-activity.d.ts +2 -1
- package/src/config/recent-activity.ts +12 -1
- package/src/config/saved-sessions.d.ts +2 -1
- package/src/config/saved-sessions.ts +12 -2
- package/src/daemon/dev-auto-implement.ts +1 -14
- package/src/daemon/dev-cli-debug.ts +0 -1
- package/src/daemon/dev-server-types.ts +1 -0
- package/src/daemon/dev-server.ts +46 -21
- package/src/daemon/scaffold-template.ts +8 -1
- package/src/index.d.ts +1 -1
- package/src/index.ts +4 -0
- package/src/providers/acp-provider-instance.d.ts +8 -2
- package/src/providers/acp-provider-instance.ts +80 -23
- package/src/providers/cli-provider-instance.ts +42 -22
- package/src/providers/contracts.d.ts +3 -2
- package/src/providers/contracts.ts +7 -4
- package/src/providers/control-effects.ts +3 -4
- package/src/providers/extension-provider-instance.d.ts +1 -2
- package/src/providers/extension-provider-instance.ts +26 -14
- package/src/providers/ide-provider-instance.ts +28 -15
- package/src/providers/provider-instance.d.ts +3 -4
- package/src/providers/provider-instance.ts +6 -7
- package/src/providers/provider-loader.d.ts +4 -1
- package/src/providers/provider-loader.ts +61 -23
- package/src/providers/provider-patch-state.ts +91 -0
- package/src/providers/provider-schema.ts +3 -0
- package/src/providers/summary-metadata.ts +118 -0
- package/src/shared-types.d.ts +15 -9
- package/src/shared-types.ts +17 -9
- package/src/status/builders.ts +18 -13
- package/src/status/reporter.ts +2 -4
- package/src/status/snapshot.ts +60 -2
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* - Common across all categories (cli, ide, extension)
|
|
7
7
|
* - User custom providers use the same contracts
|
|
8
8
|
*/
|
|
9
|
+
import type { ProviderSummaryMetadata } from '../shared-types.js';
|
|
9
10
|
export interface ReadChatResult {
|
|
10
11
|
messages: ChatMessage[];
|
|
11
12
|
status: AgentStatus;
|
|
@@ -21,10 +22,10 @@ export interface ReadChatResult {
|
|
|
21
22
|
isVisible?: boolean;
|
|
22
23
|
isWelcomeScreen?: boolean;
|
|
23
24
|
inputContent?: string;
|
|
24
|
-
model?: string;
|
|
25
|
-
autoApprove?: string;
|
|
26
25
|
/** Explicit dynamic control values returned by the provider */
|
|
27
26
|
controlValues?: Record<string, string | number | boolean>;
|
|
27
|
+
/** Flexible always-visible metadata for compact/live surfaces. */
|
|
28
|
+
summaryMetadata?: ProviderSummaryMetadata;
|
|
28
29
|
/** Provider-driven UI effects derived from chat state */
|
|
29
30
|
effects?: ProviderEffect[];
|
|
30
31
|
}
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
// ─── readChat() return value ───────────────────────────
|
|
11
11
|
|
|
12
|
+
import type { ProviderSummaryMetadata } from '../shared-types.js';
|
|
13
|
+
|
|
12
14
|
export interface ReadChatResult {
|
|
13
15
|
messages: ChatMessage[];
|
|
14
16
|
status: AgentStatus;
|
|
@@ -20,15 +22,15 @@ export interface ReadChatResult {
|
|
|
20
22
|
agentType?: string;
|
|
21
23
|
agentName?: string;
|
|
22
24
|
extensionId?: string;
|
|
23
|
-
|
|
25
|
+
/** Status metadata */
|
|
24
26
|
isVisible?: boolean;
|
|
25
27
|
isWelcomeScreen?: boolean;
|
|
26
28
|
inputContent?: string;
|
|
27
|
-
model?: string;
|
|
28
|
-
autoApprove?: string;
|
|
29
29
|
/** Explicit dynamic control values returned by the provider */
|
|
30
30
|
controlValues?: Record<string, string | number | boolean>;
|
|
31
|
-
/**
|
|
31
|
+
/** Flexible always-visible metadata for compact/live surfaces. */
|
|
32
|
+
summaryMetadata?: ProviderSummaryMetadata;
|
|
33
|
+
/** Provider-driven UI effects derived from chat state */
|
|
32
34
|
effects?: ProviderEffect[];
|
|
33
35
|
}
|
|
34
36
|
|
|
@@ -414,6 +416,7 @@ export interface ProviderModule {
|
|
|
414
416
|
/** How the CLI adapter decides when to submit typed input */
|
|
415
417
|
submitStrategy?: 'wait_for_echo' | 'immediate';
|
|
416
418
|
/** Keep this provider out of the upstream auto-updated bundle */
|
|
419
|
+
/** @deprecated Machine-level provider source policy now lives in config.providerSourceMode. Local overrides shadow upstream by root precedence and should not rely on provider-level disableUpstream. */
|
|
417
420
|
disableUpstream?: boolean;
|
|
418
421
|
approvalKeys?: Record<number, string>;
|
|
419
422
|
patterns?: {
|
|
@@ -32,9 +32,6 @@ export function extractProviderControlValues(
|
|
|
32
32
|
values[ctrl.id] = normalizeControlValue(rawValue);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
if (data.model !== undefined && values.model === undefined) values.model = normalizeControlValue(data.model);
|
|
36
|
-
if (data.mode !== undefined && values.mode === undefined) values.mode = normalizeControlValue(data.mode);
|
|
37
|
-
|
|
38
35
|
return Object.keys(values).length > 0 ? values : undefined;
|
|
39
36
|
}
|
|
40
37
|
|
|
@@ -171,7 +168,9 @@ function normalizeControlOption(option: unknown): ProviderControlOption | null {
|
|
|
171
168
|
const record = option as Record<string, unknown>;
|
|
172
169
|
const value = typeof record.value === 'string'
|
|
173
170
|
? record.value
|
|
174
|
-
: (typeof record.id === 'string'
|
|
171
|
+
: (typeof record.id === 'string'
|
|
172
|
+
? record.id
|
|
173
|
+
: (typeof record.name === 'string' ? record.name : null));
|
|
175
174
|
if (!value) return null;
|
|
176
175
|
const label = typeof record.label === 'string'
|
|
177
176
|
? record.label
|
|
@@ -18,9 +18,8 @@ export declare class ExtensionProviderInstance implements ProviderInstance {
|
|
|
18
18
|
private messages;
|
|
19
19
|
private prevMessageHashes;
|
|
20
20
|
private activeModal;
|
|
21
|
-
private currentModel;
|
|
22
|
-
private currentMode;
|
|
23
21
|
private controlValues;
|
|
22
|
+
private summaryMetadata;
|
|
24
23
|
private appliedEffectKeys;
|
|
25
24
|
private runtimeMessages;
|
|
26
25
|
private lastAgentStatus;
|
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
import type { ProviderModule } from './contracts.js';
|
|
9
9
|
import type { ProviderInstance, ProviderState, ProviderEvent, InstanceContext } from './provider-instance.js';
|
|
10
10
|
import { StatusMonitor } from './status-monitor.js';
|
|
11
|
-
import {
|
|
11
|
+
import { normalizeProviderEffects } from './control-effects.js';
|
|
12
12
|
import { ChatHistoryWriter } from '../config/chat-history.js';
|
|
13
13
|
import type { ChatMessage } from '../types.js';
|
|
14
|
+
import { mergeProviderPatchState, resolveProviderStateSurface } from './provider-patch-state.js';
|
|
14
15
|
|
|
15
16
|
export class ExtensionProviderInstance implements ProviderInstance {
|
|
16
17
|
readonly type: string;
|
|
@@ -27,9 +28,8 @@ export class ExtensionProviderInstance implements ProviderInstance {
|
|
|
27
28
|
private messages: any[] = [];
|
|
28
29
|
private prevMessageHashes = new Map<string, number>();
|
|
29
30
|
private activeModal: any = null;
|
|
30
|
-
private currentModel: string = '';
|
|
31
|
-
private currentMode: string = '';
|
|
32
31
|
private controlValues: Record<string, string | number | boolean> = {};
|
|
32
|
+
private summaryMetadata: unknown = undefined;
|
|
33
33
|
private appliedEffectKeys = new Set<string>();
|
|
34
34
|
private runtimeMessages: Array<{ key: string; message: ChatMessage }> = [];
|
|
35
35
|
private lastAgentStatus: string = 'idle';
|
|
@@ -76,6 +76,11 @@ export class ExtensionProviderInstance implements ProviderInstance {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
getState(): ProviderState {
|
|
79
|
+
const surface = resolveProviderStateSurface({
|
|
80
|
+
summaryMetadata: this.summaryMetadata as any,
|
|
81
|
+
controlValues: this.controlValues,
|
|
82
|
+
})
|
|
83
|
+
|
|
79
84
|
return {
|
|
80
85
|
type: this.type,
|
|
81
86
|
name: this.provider.name,
|
|
@@ -89,10 +94,9 @@ export class ExtensionProviderInstance implements ProviderInstance {
|
|
|
89
94
|
activeModal: this.activeModal,
|
|
90
95
|
inputContent: '',
|
|
91
96
|
} : null,
|
|
92
|
-
|
|
93
|
-
currentPlan: this.currentMode || undefined,
|
|
94
|
-
controlValues: this.controlValues,
|
|
97
|
+
controlValues: surface.controlValues,
|
|
95
98
|
providerControls: this.provider.controls,
|
|
99
|
+
summaryMetadata: surface.summaryMetadata as any,
|
|
96
100
|
agentStreams: this.agentStreams,
|
|
97
101
|
instanceId: this.instanceId,
|
|
98
102
|
lastUpdated: Date.now(),
|
|
@@ -107,10 +111,14 @@ export class ExtensionProviderInstance implements ProviderInstance {
|
|
|
107
111
|
if (data?.streams) this.agentStreams = data.streams;
|
|
108
112
|
if (data?.messages) this.messages = this.assignReceivedAt(data.messages);
|
|
109
113
|
if (data?.activeModal !== undefined) this.activeModal = data.activeModal;
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
+
const patchedState = mergeProviderPatchState({
|
|
115
|
+
providerControls: this.provider.controls,
|
|
116
|
+
data,
|
|
117
|
+
currentControlValues: this.controlValues,
|
|
118
|
+
currentSummaryMetadata: this.summaryMetadata,
|
|
119
|
+
});
|
|
120
|
+
this.controlValues = patchedState.controlValues;
|
|
121
|
+
this.summaryMetadata = patchedState.summaryMetadata;
|
|
114
122
|
if (typeof data?.sessionId === 'string' && data.sessionId.trim()) this.chatId = data.sessionId;
|
|
115
123
|
if (typeof data?.title === 'string' && data.title.trim()) this.chatTitle = data.title;
|
|
116
124
|
if (typeof data?.agentName === 'string' && data.agentName.trim()) this.agentName = data.agentName;
|
|
@@ -231,8 +239,14 @@ export class ExtensionProviderInstance implements ProviderInstance {
|
|
|
231
239
|
private applyProviderResponse(data: any, options: { phase: 'immediate' | 'turn_completed' }): void {
|
|
232
240
|
if (!data || typeof data !== 'object') return;
|
|
233
241
|
|
|
234
|
-
const
|
|
235
|
-
|
|
242
|
+
const patchedState = mergeProviderPatchState({
|
|
243
|
+
providerControls: this.provider.controls,
|
|
244
|
+
data,
|
|
245
|
+
currentControlValues: this.controlValues,
|
|
246
|
+
currentSummaryMetadata: this.summaryMetadata,
|
|
247
|
+
});
|
|
248
|
+
this.controlValues = patchedState.controlValues;
|
|
249
|
+
this.summaryMetadata = patchedState.summaryMetadata;
|
|
236
250
|
|
|
237
251
|
const effects = normalizeProviderEffects(data);
|
|
238
252
|
for (const effect of effects) {
|
|
@@ -406,8 +420,6 @@ export class ExtensionProviderInstance implements ProviderInstance {
|
|
|
406
420
|
this.messages = [];
|
|
407
421
|
this.prevMessageHashes.clear();
|
|
408
422
|
this.activeModal = null;
|
|
409
|
-
this.currentModel = '';
|
|
410
|
-
this.currentMode = '';
|
|
411
423
|
this.controlValues = {};
|
|
412
424
|
this.currentStatus = 'idle';
|
|
413
425
|
this.chatId = null;
|
|
@@ -17,9 +17,10 @@ import { ExtensionProviderInstance } from './extension-provider-instance.js';
|
|
|
17
17
|
import { StatusMonitor } from './status-monitor.js';
|
|
18
18
|
import { ChatHistoryWriter } from '../config/chat-history.js';
|
|
19
19
|
import { LOG } from '../logging/logger.js';
|
|
20
|
-
import {
|
|
20
|
+
import { normalizeProviderEffects } from './control-effects.js';
|
|
21
21
|
import type { ChatMessage } from '../types.js';
|
|
22
22
|
import { formatAutoApprovalMessage, pickApprovalButton } from './approval-utils.js';
|
|
23
|
+
import { mergeProviderPatchState, resolveProviderStateSurface } from './provider-patch-state.js';
|
|
23
24
|
|
|
24
25
|
type ReadChatModal = {
|
|
25
26
|
message?: string;
|
|
@@ -134,6 +135,11 @@ export class IdeProviderInstance implements ProviderInstance {
|
|
|
134
135
|
extensionStates.push(ext.getState());
|
|
135
136
|
}
|
|
136
137
|
|
|
138
|
+
const surface = resolveProviderStateSurface({
|
|
139
|
+
summaryMetadata: this.cachedChat?.summaryMetadata,
|
|
140
|
+
controlValues: this.cachedChat?.controlValues,
|
|
141
|
+
});
|
|
142
|
+
|
|
137
143
|
return {
|
|
138
144
|
type: this.type,
|
|
139
145
|
name: this.provider.name,
|
|
@@ -152,11 +158,9 @@ export class IdeProviderInstance implements ProviderInstance {
|
|
|
152
158
|
workspace: this.workspace || null,
|
|
153
159
|
extensions: extensionStates,
|
|
154
160
|
cdpConnected: cdp?.isConnected || false,
|
|
155
|
-
|
|
156
|
-
currentPlan: this.cachedChat?.mode || undefined,
|
|
157
|
-
currentAutoApprove: this.cachedChat?.autoApprove || undefined,
|
|
158
|
-
controlValues: this.cachedChat?.controlValues || undefined,
|
|
161
|
+
controlValues: surface.controlValues,
|
|
159
162
|
providerControls: this.provider.controls,
|
|
163
|
+
summaryMetadata: surface.summaryMetadata as any,
|
|
160
164
|
instanceId: this.instanceId,
|
|
161
165
|
lastUpdated: Date.now(),
|
|
162
166
|
settings: this.settings,
|
|
@@ -348,8 +352,13 @@ export class IdeProviderInstance implements ProviderInstance {
|
|
|
348
352
|
}
|
|
349
353
|
}
|
|
350
354
|
|
|
351
|
-
const
|
|
352
|
-
|
|
355
|
+
const patchedState = mergeProviderPatchState({
|
|
356
|
+
providerControls: this.provider.controls,
|
|
357
|
+
data: chat,
|
|
358
|
+
mergeWithCurrent: false,
|
|
359
|
+
});
|
|
360
|
+
chat.controlValues = Object.keys(patchedState.controlValues).length > 0 ? patchedState.controlValues : undefined;
|
|
361
|
+
chat.summaryMetadata = patchedState.summaryMetadata;
|
|
353
362
|
|
|
354
363
|
this.cachedChat = { ...chat, activeModal };
|
|
355
364
|
this.detectAgentTransitions(chat, now);
|
|
@@ -464,14 +473,18 @@ export class IdeProviderInstance implements ProviderInstance {
|
|
|
464
473
|
private applyProviderResponse(data: any, options: { phase: 'immediate' | 'turn_completed' }): void {
|
|
465
474
|
if (!data || typeof data !== 'object') return;
|
|
466
475
|
|
|
467
|
-
const
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
476
|
+
const patchedState = mergeProviderPatchState({
|
|
477
|
+
providerControls: this.provider.controls,
|
|
478
|
+
data,
|
|
479
|
+
currentControlValues: this.cachedChat?.controlValues,
|
|
480
|
+
currentSummaryMetadata: this.cachedChat?.summaryMetadata,
|
|
481
|
+
});
|
|
482
|
+
this.cachedChat = {
|
|
483
|
+
...(this.cachedChat || {}),
|
|
484
|
+
...data,
|
|
485
|
+
controlValues: Object.keys(patchedState.controlValues).length > 0 ? patchedState.controlValues : undefined,
|
|
486
|
+
summaryMetadata: patchedState.summaryMetadata,
|
|
487
|
+
};
|
|
475
488
|
|
|
476
489
|
const effects = normalizeProviderEffects(data);
|
|
477
490
|
for (const effect of effects) {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Each Instance manages its own status.
|
|
9
9
|
*/
|
|
10
10
|
import type { ProviderResumeCapability } from './contracts.js';
|
|
11
|
-
import type { AcpConfigOption, AcpMode, ProviderControlSchema } from '../shared-types.js';
|
|
11
|
+
import type { AcpConfigOption, AcpMode, ProviderControlSchema, ProviderSummaryMetadata } from '../shared-types.js';
|
|
12
12
|
import type { ChatMessage } from '../types.js';
|
|
13
13
|
export type ProviderStatus = 'idle' | 'generating' | 'waiting_approval' | 'error' | 'stopped' | 'starting';
|
|
14
14
|
export interface ProviderRuntimeWriteOwner {
|
|
@@ -54,8 +54,6 @@ interface ProviderStateBase {
|
|
|
54
54
|
/** Workspace — project path or name (all categories) */
|
|
55
55
|
workspace?: string | null;
|
|
56
56
|
/** Runtime info (real-time detection) */
|
|
57
|
-
currentModel?: string;
|
|
58
|
-
currentPlan?: string;
|
|
59
57
|
/** Error details (when status === 'error') */
|
|
60
58
|
errorMessage?: string;
|
|
61
59
|
errorReason?: ProviderErrorReason;
|
|
@@ -72,6 +70,8 @@ interface ProviderStateBase {
|
|
|
72
70
|
controlValues?: Record<string, string | number | boolean>;
|
|
73
71
|
/** Provider-declared controls schema (from provider.controls) */
|
|
74
72
|
providerControls?: ProviderControlSchema[];
|
|
73
|
+
/** Flexible always-visible metadata for compact/live surfaces. */
|
|
74
|
+
summaryMetadata?: ProviderSummaryMetadata;
|
|
75
75
|
}
|
|
76
76
|
/** IDE provider state */
|
|
77
77
|
export interface IdeProviderState extends ProviderStateBase {
|
|
@@ -79,7 +79,6 @@ export interface IdeProviderState extends ProviderStateBase {
|
|
|
79
79
|
cdpConnected: boolean;
|
|
80
80
|
/** IDE child Extension Instance status */
|
|
81
81
|
extensions: ProviderState[];
|
|
82
|
-
currentAutoApprove?: string;
|
|
83
82
|
}
|
|
84
83
|
/** CLI provider state */
|
|
85
84
|
export interface CliProviderState extends ProviderStateBase {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import type { ProviderModule, ProviderSettingDef, ProviderResumeCapability } from './contracts.js';
|
|
12
|
-
import type { AcpConfigOption, AcpMode, ProviderControlSchema } from '../shared-types.js';
|
|
12
|
+
import type { AcpConfigOption, AcpMode, ProviderControlSchema, ProviderSummaryMetadata } from '../shared-types.js';
|
|
13
13
|
import type { ChatMessage } from '../types.js';
|
|
14
14
|
|
|
15
15
|
// ─── ProviderState — Discriminated union by category ─────────────
|
|
@@ -68,10 +68,8 @@ interface ProviderStateBase {
|
|
|
68
68
|
activeChat: ActiveChatData | null;
|
|
69
69
|
/** Workspace — project path or name (all categories) */
|
|
70
70
|
workspace?: string | null;
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
currentPlan?: string;
|
|
74
|
-
/** Error details (when status === 'error') */
|
|
71
|
+
/** Runtime info (real-time detection) */
|
|
72
|
+
/** Error details (when status === 'error') */
|
|
75
73
|
errorMessage?: string;
|
|
76
74
|
errorReason?: ProviderErrorReason;
|
|
77
75
|
/** meta */
|
|
@@ -85,8 +83,10 @@ interface ProviderStateBase {
|
|
|
85
83
|
resume?: ProviderResumeCapability;
|
|
86
84
|
/** Dynamic control current values */
|
|
87
85
|
controlValues?: Record<string, string | number | boolean>;
|
|
88
|
-
|
|
86
|
+
/** Provider-declared controls schema (from provider.controls) */
|
|
89
87
|
providerControls?: ProviderControlSchema[];
|
|
88
|
+
/** Flexible always-visible metadata for compact/live surfaces. */
|
|
89
|
+
summaryMetadata?: ProviderSummaryMetadata;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
/** IDE provider state */
|
|
@@ -95,7 +95,6 @@ export interface IdeProviderState extends ProviderStateBase {
|
|
|
95
95
|
cdpConnected: boolean;
|
|
96
96
|
/** IDE child Extension Instance status */
|
|
97
97
|
extensions: ProviderState[];
|
|
98
|
-
currentAutoApprove?: string;
|
|
99
98
|
}
|
|
100
99
|
|
|
101
100
|
/** CLI provider state */
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { VersionArchive } from './version-archive.js';
|
|
16
16
|
import type { ProviderModule, ProviderCategory, ProviderSettingSchema, ResolvedProvider } from './contracts.js';
|
|
17
|
+
import type { ProviderSourceMode } from '../config/config.js';
|
|
17
18
|
export declare class ProviderLoader {
|
|
18
19
|
private providers;
|
|
19
20
|
private providerAvailability;
|
|
@@ -31,7 +32,9 @@ export declare class ProviderLoader {
|
|
|
31
32
|
constructor(options?: {
|
|
32
33
|
userDir?: string;
|
|
33
34
|
logFn?: (msg: string) => void;
|
|
34
|
-
/**
|
|
35
|
+
/** Explicit machine-level provider source policy */
|
|
36
|
+
sourceMode?: ProviderSourceMode;
|
|
37
|
+
/** Deprecated alias for sourceMode='no-upstream' */
|
|
35
38
|
disableUpstream?: boolean;
|
|
36
39
|
});
|
|
37
40
|
private log;
|
|
@@ -30,6 +30,8 @@ import type {
|
|
|
30
30
|
ResolvedProvider,
|
|
31
31
|
} from './contracts.js';
|
|
32
32
|
import { validateProviderDefinition } from './provider-schema.js';
|
|
33
|
+
import type { ProviderSourceMode } from '../config/config.js';
|
|
34
|
+
import type { ProviderSourceConfigSnapshot } from '../config/provider-source-config.js';
|
|
33
35
|
|
|
34
36
|
interface ProviderAvailabilityState {
|
|
35
37
|
installed: boolean;
|
|
@@ -39,8 +41,11 @@ interface ProviderAvailabilityState {
|
|
|
39
41
|
export class ProviderLoader {
|
|
40
42
|
private providers = new Map<string, ProviderModule>();
|
|
41
43
|
private providerAvailability = new Map<string, ProviderAvailabilityState>();
|
|
44
|
+
private defaultProvidersDir: string;
|
|
45
|
+
private explicitProviderDir: string | null = null;
|
|
42
46
|
private userDir: string;
|
|
43
47
|
private upstreamDir: string;
|
|
48
|
+
private sourceMode: ProviderSourceMode = 'normal';
|
|
44
49
|
private disableUpstream: boolean;
|
|
45
50
|
private watchers: any[] = [];
|
|
46
51
|
private logFn: (msg: string) => void;
|
|
@@ -58,32 +63,24 @@ export class ProviderLoader {
|
|
|
58
63
|
constructor(options?: {
|
|
59
64
|
userDir?: string;
|
|
60
65
|
logFn?: (msg: string) => void;
|
|
61
|
-
/**
|
|
66
|
+
/** Explicit machine-level provider source policy */
|
|
67
|
+
sourceMode?: ProviderSourceMode;
|
|
68
|
+
/** Deprecated alias for sourceMode='no-upstream' */
|
|
62
69
|
disableUpstream?: boolean;
|
|
63
70
|
}) {
|
|
64
71
|
this.logFn = options?.logFn || LOG.forComponent('Provider').asLogFn();
|
|
65
72
|
|
|
66
73
|
// Default directory for auto-downloads
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
this.log(`Auto-detected local public repository: ${this.userDir} (Dev workspace speedup)`);
|
|
78
|
-
} else {
|
|
79
|
-
this.userDir = defaultProvidersDir;
|
|
80
|
-
this.log(`Using default user providers directory: ${this.userDir}`);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Upstream auto-download directory is always in the default location
|
|
85
|
-
this.upstreamDir = path.join(defaultProvidersDir, '.upstream');
|
|
86
|
-
this.disableUpstream = options?.disableUpstream ?? false;
|
|
74
|
+
this.defaultProvidersDir = path.join(os.homedir(), '.adhdev', 'providers');
|
|
75
|
+
this.userDir = this.defaultProvidersDir;
|
|
76
|
+
this.upstreamDir = path.join(this.defaultProvidersDir, '.upstream');
|
|
77
|
+
this.disableUpstream = false;
|
|
78
|
+
|
|
79
|
+
this.applySourceConfig({
|
|
80
|
+
userDir: options?.userDir,
|
|
81
|
+
sourceMode: options?.sourceMode,
|
|
82
|
+
disableUpstream: options?.disableUpstream,
|
|
83
|
+
});
|
|
87
84
|
}
|
|
88
85
|
|
|
89
86
|
private log(msg: string): void {
|
|
@@ -114,6 +111,47 @@ export class ProviderLoader {
|
|
|
114
111
|
return [this.userDir, this.upstreamDir];
|
|
115
112
|
}
|
|
116
113
|
|
|
114
|
+
getSourceConfig(): ProviderSourceConfigSnapshot {
|
|
115
|
+
return {
|
|
116
|
+
sourceMode: this.sourceMode,
|
|
117
|
+
disableUpstream: this.disableUpstream,
|
|
118
|
+
explicitProviderDir: this.explicitProviderDir,
|
|
119
|
+
userDir: this.userDir,
|
|
120
|
+
upstreamDir: this.upstreamDir,
|
|
121
|
+
providerRoots: this.getProviderRoots(),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
applySourceConfig(options?: {
|
|
126
|
+
userDir?: string;
|
|
127
|
+
sourceMode?: ProviderSourceMode;
|
|
128
|
+
disableUpstream?: boolean;
|
|
129
|
+
}): ProviderSourceConfigSnapshot {
|
|
130
|
+
const nextSourceMode = options?.sourceMode === 'no-upstream'
|
|
131
|
+
? 'no-upstream'
|
|
132
|
+
: (options?.sourceMode === 'normal'
|
|
133
|
+
? 'normal'
|
|
134
|
+
: (options?.disableUpstream ? 'no-upstream' : this.sourceMode || 'normal'));
|
|
135
|
+
|
|
136
|
+
if (options && Object.prototype.hasOwnProperty.call(options, 'userDir')) {
|
|
137
|
+
this.explicitProviderDir = options.userDir?.trim() ? options.userDir : null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
this.sourceMode = nextSourceMode;
|
|
141
|
+
this.userDir = this.explicitProviderDir || this.defaultProvidersDir;
|
|
142
|
+
this.upstreamDir = path.join(this.defaultProvidersDir, '.upstream');
|
|
143
|
+
this.disableUpstream = this.sourceMode === 'no-upstream';
|
|
144
|
+
|
|
145
|
+
if (this.explicitProviderDir) {
|
|
146
|
+
this.log(`Config 'providerDir' applied: ${this.userDir}`);
|
|
147
|
+
} else {
|
|
148
|
+
this.log(`Using default user providers directory: ${this.userDir}`);
|
|
149
|
+
}
|
|
150
|
+
this.log(`Provider source config: mode=${this.sourceMode} explicitProviderDir=${this.explicitProviderDir || '-'} userDir=${this.userDir} upstreamDir=${this.upstreamDir}`);
|
|
151
|
+
|
|
152
|
+
return this.getSourceConfig();
|
|
153
|
+
}
|
|
154
|
+
|
|
117
155
|
/**
|
|
118
156
|
* Canonical provider directory shape for a given root.
|
|
119
157
|
*/
|
|
@@ -171,7 +209,7 @@ export class ProviderLoader {
|
|
|
171
209
|
this.log(`Loaded ${upstreamCount} upstream providers (auto-updated)`);
|
|
172
210
|
}
|
|
173
211
|
} else if (this.disableUpstream) {
|
|
174
|
-
this.log('Upstream loading disabled (
|
|
212
|
+
this.log('Upstream loading disabled (sourceMode=no-upstream)');
|
|
175
213
|
}
|
|
176
214
|
|
|
177
215
|
// 2. Load user custom (excluding .upstream — highest priority, never auto-updated)
|
|
@@ -760,7 +798,7 @@ export class ProviderLoader {
|
|
|
760
798
|
*/
|
|
761
799
|
async fetchLatest(): Promise<{ updated: boolean; error?: string }> {
|
|
762
800
|
if (this.disableUpstream) {
|
|
763
|
-
this.log('Upstream fetch skipped (
|
|
801
|
+
this.log('Upstream fetch skipped (sourceMode=no-upstream)');
|
|
764
802
|
return { updated: false };
|
|
765
803
|
}
|
|
766
804
|
const https = require('https') as typeof import('https');
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { ProviderControlDef } from './contracts.js'
|
|
2
|
+
import { extractProviderControlValues } from './control-effects.js'
|
|
3
|
+
import { resolveProviderStateSummaryMetadata } from './summary-metadata.js'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export type ProviderControlValue = string | number | boolean
|
|
7
|
+
export type ProviderControlValueMap = Record<string, ProviderControlValue>
|
|
8
|
+
|
|
9
|
+
function isControlValue(value: unknown): value is ProviderControlValue {
|
|
10
|
+
return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function asControlValueMap(value: unknown): ProviderControlValueMap | undefined {
|
|
14
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined
|
|
15
|
+
|
|
16
|
+
const result: ProviderControlValueMap = {}
|
|
17
|
+
for (const [entryKey, entryValue] of Object.entries(value as Record<string, unknown>)) {
|
|
18
|
+
if (isControlValue(entryValue)) result[entryKey] = entryValue
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return Object.keys(result).length > 0 ? result : undefined
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function getLegacyModelModeValues(data: any): ProviderControlValueMap | undefined {
|
|
25
|
+
if (!data || typeof data !== 'object') return undefined
|
|
26
|
+
|
|
27
|
+
const legacy: ProviderControlValueMap = {}
|
|
28
|
+
if (typeof data.model === 'string' && data.model.trim()) legacy.model = data.model.trim()
|
|
29
|
+
if (typeof data.mode === 'string' && data.mode.trim()) legacy.mode = data.mode.trim()
|
|
30
|
+
|
|
31
|
+
return Object.keys(legacy).length > 0 ? legacy : undefined
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function mergeProviderPatchState(params: {
|
|
35
|
+
providerControls?: ProviderControlDef[]
|
|
36
|
+
data: any
|
|
37
|
+
currentControlValues?: ProviderControlValueMap
|
|
38
|
+
currentSummaryMetadata?: unknown
|
|
39
|
+
mergeWithCurrent?: boolean
|
|
40
|
+
}): {
|
|
41
|
+
controlValues: ProviderControlValueMap
|
|
42
|
+
summaryMetadata: unknown
|
|
43
|
+
} {
|
|
44
|
+
const {
|
|
45
|
+
providerControls,
|
|
46
|
+
data,
|
|
47
|
+
currentControlValues,
|
|
48
|
+
currentSummaryMetadata,
|
|
49
|
+
mergeWithCurrent = true,
|
|
50
|
+
} = params
|
|
51
|
+
|
|
52
|
+
const sources = [
|
|
53
|
+
mergeWithCurrent ? asControlValueMap(currentControlValues) : undefined,
|
|
54
|
+
asControlValueMap(data?.controlValues),
|
|
55
|
+
asControlValueMap(extractProviderControlValues(providerControls, data)),
|
|
56
|
+
getLegacyModelModeValues(data),
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
const controlValues = Object.assign({}, ...sources.filter(Boolean)) as ProviderControlValueMap
|
|
60
|
+
return {
|
|
61
|
+
controlValues,
|
|
62
|
+
summaryMetadata: data?.summaryMetadata !== undefined ? data.summaryMetadata : currentSummaryMetadata,
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function normalizeProviderStateControlValues(
|
|
67
|
+
controlValues: ProviderControlValueMap | undefined,
|
|
68
|
+
): ProviderControlValueMap | undefined {
|
|
69
|
+
return controlValues && Object.keys(controlValues).length > 0 ? controlValues : undefined
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function resolveProviderStateSurface(params: {
|
|
73
|
+
controlValues?: ProviderControlValueMap
|
|
74
|
+
summaryMetadata?: unknown
|
|
75
|
+
modelLabel?: string | null
|
|
76
|
+
modeLabel?: string | null
|
|
77
|
+
}): {
|
|
78
|
+
controlValues: ProviderControlValueMap | undefined
|
|
79
|
+
summaryMetadata: unknown
|
|
80
|
+
} {
|
|
81
|
+
const controlValues = normalizeProviderStateControlValues(params.controlValues)
|
|
82
|
+
return {
|
|
83
|
+
controlValues,
|
|
84
|
+
summaryMetadata: resolveProviderStateSummaryMetadata({
|
|
85
|
+
summaryMetadata: params.summaryMetadata as any,
|
|
86
|
+
controlValues,
|
|
87
|
+
modelLabel: params.modelLabel,
|
|
88
|
+
modeLabel: params.modeLabel,
|
|
89
|
+
}),
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -83,6 +83,9 @@ export function validateProviderDefinition(raw: unknown): ProviderValidationResu
|
|
|
83
83
|
warnings.push(`Unknown provider field: ${key}`)
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
|
+
if (provider.disableUpstream !== undefined) {
|
|
87
|
+
warnings.push('disableUpstream is deprecated in provider definitions; use machine-level provider source policy instead')
|
|
88
|
+
}
|
|
86
89
|
|
|
87
90
|
const category = provider.category
|
|
88
91
|
if ((category === 'cli' || category === 'acp')) {
|