@adhdev/daemon-core 0.9.82-rc.164 → 0.9.82-rc.166

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.
@@ -9,7 +9,7 @@
9
9
  * offending field without guessing.
10
10
  *
11
11
  * Validation lives in the SDK layer (not in provider-loader) so dashboards,
12
- * registry workers, and the marketplace publish flow can all reuse the
12
+ * registry workers, and the provider publish flow can all reuse the
13
13
  * same code path and produce identical error messages.
14
14
  */
15
15
 
@@ -2,7 +2,7 @@
2
2
  * Static taint analyzer for extended-tier override JS.
3
3
  *
4
4
  * Goal: classify the override JS shipped with an extended-tier provider into
5
- * one of three risk tiers, so the marketplace + daemon trust prompt can
5
+ * one of three risk tiers, so the dashboard + daemon trust prompt can
6
6
  * surface accurate language to the operator instead of a single generic
7
7
  * "this provider contains JS" warning.
8
8
  *
@@ -30,6 +30,15 @@ export class SpecCliAdapter implements CliAdapter {
30
30
  readonly cliType: string;
31
31
  readonly cliName: string;
32
32
  readonly workingDir: string;
33
+ /**
34
+ * Marker the daemon's finalization gate checks: `getStatus()` returns
35
+ * `messages: []` by design here (chat history lives in the daemon's
36
+ * native-history pipeline, not the adapter). Without this flag,
37
+ * cli-provider-instance's `missing_final_assistant` gate would stall
38
+ * every turn until the 30s safety timeout because it expects the
39
+ * adapter to surface the final assistant message.
40
+ */
41
+ readonly chatMessagesOwnedExternally = true as const;
33
42
 
34
43
  private driver: SpecDriver;
35
44
  private spec: CliSpec;
@@ -256,9 +256,20 @@ function expandPath(template: string, input: NativeHistoryInput): string | null
256
256
  // Re-expand ~ in case the fallback used it.
257
257
  if (out.startsWith('~/')) out = path.join(os.homedir(), out.slice(2));
258
258
  const now = new Date();
259
+ // claude (and a couple of other Anthropic-CLI–style providers) writes
260
+ // its per-cwd transcript under the *resolved* path
261
+ // (/private/tmp/foo, not /tmp/foo on macOS where /tmp -> /private/tmp).
262
+ // Without realpath, the spec template `~/.claude/projects/{cwd_dashed}/…`
263
+ // builds `-tmp-foo` and never finds the actual `-private-tmp-foo` dir.
264
+ const workspaceRaw = input.workspace ?? '';
265
+ let workspaceResolved = workspaceRaw;
266
+ if (workspaceRaw) {
267
+ try { workspaceResolved = fs.realpathSync(workspaceRaw); }
268
+ catch { /* path may not exist yet — keep the raw value */ }
269
+ }
259
270
  const vars: Record<string, string> = {
260
- cwd: input.workspace ?? '',
261
- cwd_dashed: (input.workspace ?? '').replace(/\//g, '-'),
271
+ cwd: workspaceResolved,
272
+ cwd_dashed: workspaceResolved.replace(/\//g, '-'),
262
273
  session_id: input.providerSessionId || input.sessionId || input.historySessionId || '',
263
274
  yyyy: String(now.getUTCFullYear()),
264
275
  mm: String(now.getUTCMonth() + 1).padStart(2, '0'),
@@ -525,7 +525,39 @@ export interface AvailableProviderInfo {
525
525
  lastVerification?: MachineProviderCheckResult;
526
526
  /** Provider-declared Repo Mesh coordinator/MCP behavior. */
527
527
  meshCoordinator?: ProviderMeshCoordinatorConfig;
528
- }
528
+ /**
529
+ * Provider trust classification — derived from the on-disk layer the
530
+ * manifest came from and the shape of the manifest. Dashboards use
531
+ * this to render a trust badge and gate activation of
532
+ * `external-untrusted` providers behind a confirm modal.
533
+ */
534
+ trust?: ProviderTrust;
535
+ /** Daemon-side human-readable description of the trust value. */
536
+ trustDescription?: string;
537
+ /** True when activation needs a user-side confirmation step. */
538
+ requiresConfirmation?: boolean;
539
+ /** Which on-disk layer the manifest lives in. */
540
+ sourceLayer?: 'user' | 'upstream' | 'external';
541
+ /** For external providers, the source-name namespace it came from. */
542
+ sourceName?: string | null;
543
+ /** Manifest-declared version, e.g. "1.2.1". */
544
+ providerVersion?: string;
545
+ /** Underlying executable name (CLI/binary providers). */
546
+ binary?: string;
547
+ /** Lifecycle label from the manifest: "Stable", "Beta", … */
548
+ status?: string;
549
+ /** One-line provider description from the manifest. */
550
+ details?: string;
551
+ /** Manifest-declared links: homepage, docs, repo, … */
552
+ links?: Record<string, string>;
553
+ }
554
+
555
+ export type ProviderTrust =
556
+ | 'user-custom'
557
+ | 'trusted'
558
+ | 'trusted-with-scripts'
559
+ | 'external-safe'
560
+ | 'external-untrusted';
529
561
 
530
562
  export interface MachineProviderCheckResult {
531
563
  ok: boolean;
@@ -145,21 +145,56 @@ function buildAvailableProviders(
145
145
  lastDetection?: AvailableProviderInfo['lastDetection'];
146
146
  lastVerification?: AvailableProviderInfo['lastVerification'];
147
147
  meshCoordinator?: AvailableProviderInfo['meshCoordinator'];
148
+ _sourceTrust?: AvailableProviderInfo['trust'];
149
+ _sourceLayer?: AvailableProviderInfo['sourceLayer'];
150
+ _sourceName?: string | null;
151
+ providerVersion?: string;
152
+ binary?: string;
153
+ status?: string;
154
+ details?: string;
155
+ links?: Record<string, string>;
148
156
  }> = providerLoader.getAvailableProviderInfos?.() || providerLoader.getAll();
149
- return providers.map((provider) => ({
150
- type: provider.type,
151
- name: provider.displayName || provider.type,
152
- displayName: provider.displayName || provider.type,
153
- icon: provider.icon || '💻',
154
- category: provider.category,
155
- ...(provider.installed !== undefined ? { installed: provider.installed } : {}),
156
- ...(provider.detectedPath !== undefined ? { detectedPath: provider.detectedPath } : {}),
157
- ...(provider.enabled !== undefined ? { enabled: provider.enabled } : {}),
158
- ...(provider.machineStatus !== undefined ? { machineStatus: provider.machineStatus } : {}),
159
- ...(provider.lastDetection !== undefined ? { lastDetection: provider.lastDetection } : {}),
160
- ...(provider.lastVerification !== undefined ? { lastVerification: provider.lastVerification } : {}),
161
- ...(provider.meshCoordinator !== undefined ? { meshCoordinator: provider.meshCoordinator } : {}),
162
- }));
157
+ // Trust helpers come from daemon-core; resolve them lazily so the
158
+ // status snapshot path stays loadable in older bundles that don't
159
+ // ship provider-trust yet.
160
+ let describeTrust: (trust: AvailableProviderInfo['trust']) => string = () => '';
161
+ let requiresConfirmation: (trust: AvailableProviderInfo['trust']) => boolean = () => false;
162
+ try {
163
+ const mod = require('../providers/provider-trust.js') as typeof import('../providers/provider-trust.js');
164
+ describeTrust = mod.describeTrust as typeof describeTrust;
165
+ requiresConfirmation = mod.requiresConfirmation as typeof requiresConfirmation;
166
+ } catch { /* enrichment only */ }
167
+ return providers.map((provider) => {
168
+ const trust = (provider as any)._sourceTrust as AvailableProviderInfo['trust'] | undefined;
169
+ const sourceLayer = (provider as any)._sourceLayer as AvailableProviderInfo['sourceLayer'] | undefined;
170
+ const sourceName = (provider as any)._sourceName as string | null | undefined;
171
+ return {
172
+ type: provider.type,
173
+ name: provider.displayName || provider.type,
174
+ displayName: provider.displayName || provider.type,
175
+ icon: provider.icon || '💻',
176
+ category: provider.category,
177
+ ...(provider.installed !== undefined ? { installed: provider.installed } : {}),
178
+ ...(provider.detectedPath !== undefined ? { detectedPath: provider.detectedPath } : {}),
179
+ ...(provider.enabled !== undefined ? { enabled: provider.enabled } : {}),
180
+ ...(provider.machineStatus !== undefined ? { machineStatus: provider.machineStatus } : {}),
181
+ ...(provider.lastDetection !== undefined ? { lastDetection: provider.lastDetection } : {}),
182
+ ...(provider.lastVerification !== undefined ? { lastVerification: provider.lastVerification } : {}),
183
+ ...(provider.meshCoordinator !== undefined ? { meshCoordinator: provider.meshCoordinator } : {}),
184
+ ...(trust ? {
185
+ trust,
186
+ trustDescription: describeTrust(trust),
187
+ requiresConfirmation: requiresConfirmation(trust),
188
+ } : {}),
189
+ ...(sourceLayer ? { sourceLayer } : {}),
190
+ ...(sourceName ? { sourceName } : {}),
191
+ ...(provider.providerVersion ? { providerVersion: provider.providerVersion } : {}),
192
+ ...(provider.binary ? { binary: provider.binary } : {}),
193
+ ...(provider.status ? { status: provider.status } : {}),
194
+ ...(provider.details ? { details: provider.details } : {}),
195
+ ...(provider.links ? { links: provider.links } : {}),
196
+ };
197
+ });
163
198
  }
164
199
 
165
200
  export function buildMachineInfo(profile: 'full' | 'live' | 'metadata' = 'full'): MachineInfo {