@ours.network/fleet 1.1.4 → 1.2.0-nightly.1

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.
Files changed (48) hide show
  1. package/README.md +137 -1
  2. package/dist/briefing.js +4 -3
  3. package/dist/build-info.json +5 -5
  4. package/dist/cli.d.ts +1 -0
  5. package/dist/cli.js +13 -6
  6. package/dist/client-profile.d.ts +17 -0
  7. package/dist/client-profile.js +115 -0
  8. package/dist/creation.js +10 -7
  9. package/dist/daemon-recovery.d.ts +2 -0
  10. package/dist/daemon-recovery.js +53 -2
  11. package/dist/docs.d.ts +1 -1
  12. package/dist/docs.js +23 -2
  13. package/dist/doctor.js +62 -6
  14. package/dist/harness/acp-mcp.d.ts +14 -0
  15. package/dist/harness/acp-mcp.js +68 -0
  16. package/dist/harness/claude-code.js +1 -69
  17. package/dist/harness/codex.js +4 -0
  18. package/dist/harness/hermes-compatibility.d.ts +24 -0
  19. package/dist/harness/hermes-compatibility.js +191 -0
  20. package/dist/harness/hermes-config.d.ts +12 -0
  21. package/dist/harness/hermes-config.js +367 -0
  22. package/dist/harness/hermes-permissions.d.ts +4 -0
  23. package/dist/harness/hermes-permissions.js +36 -0
  24. package/dist/harness/hermes-session.d.ts +24 -0
  25. package/dist/harness/hermes-session.js +85 -0
  26. package/dist/harness/hermes-startup.d.ts +3 -0
  27. package/dist/harness/hermes-startup.js +21 -0
  28. package/dist/harness/hermes.d.ts +5 -0
  29. package/dist/harness/hermes.js +62 -0
  30. package/dist/harness/registry.js +1 -1
  31. package/dist/index.d.ts +1 -0
  32. package/dist/index.js +1 -0
  33. package/dist/init-wizard.d.ts +11 -6
  34. package/dist/init-wizard.js +33 -0
  35. package/dist/monitor.d.ts +34 -3
  36. package/dist/monitor.js +174 -74
  37. package/dist/owner-channel/channel.js +4 -2
  38. package/dist/owner-channel/ours-client.d.ts +12 -5
  39. package/dist/owner-channel/ours-client.js +48 -12
  40. package/dist/runner.js +21 -7
  41. package/dist/session/acp.d.ts +15 -0
  42. package/dist/session/acp.js +22 -7
  43. package/dist/session/codex-app-server.js +31 -5
  44. package/dist/spawn.d.ts +1 -0
  45. package/dist/spawn.js +1 -0
  46. package/dist/supervisor/launchd.js +8 -1
  47. package/examples/fleet/brains/hermes.yaml +5 -0
  48. package/package.json +5 -4
@@ -0,0 +1,24 @@
1
+ import type * as acp from '@agentclientprotocol/sdk';
2
+ import type { ResolvedRole } from '../config.js';
3
+ import type { SessionPrep } from './types.js';
4
+ import type { AgentSessionAdapter, AgentSessionStartOptions, BrainSelection } from './agent-session.js';
5
+ import type { AcpSessionTransport } from './acp-session-transport.js';
6
+ /** Native provider resolution and executable compatibility remain harness-owned. */
7
+ export interface HermesStartupChecks {
8
+ /** Independently resolved native provider identity, never copied from the ACP report. */
9
+ expectedProvider(role: ResolvedRole, prep: SessionPrep): string | Promise<string>;
10
+ validateArtifact(initialized: acp.InitializeResponse): void | Promise<void>;
11
+ /** Inspect the executable using the completed child environment before spawning it. */
12
+ preflight?(options: AgentSessionStartOptions, env: Record<string, string>): void | Promise<void>;
13
+ }
14
+ /** Fresh-only Hermes implementation of Fleet's existing live-session factory. */
15
+ export declare class HermesAgentSessionAdapter implements AgentSessionAdapter {
16
+ private readonly transport;
17
+ private readonly checks?;
18
+ constructor(transport?: AcpSessionTransport, checks?: HermesStartupChecks | undefined);
19
+ resolveBrain(brain: BrainSelection): ReturnType<AgentSessionAdapter['resolveBrain']>;
20
+ modelEnvironmentVariable(): string | undefined;
21
+ prepareLaunch(role: ResolvedRole, prep: SessionPrep): ReturnType<AgentSessionAdapter['prepareLaunch']>;
22
+ sessionConfigSelections(role: ResolvedRole): ReturnType<AgentSessionAdapter['sessionConfigSelections']>;
23
+ start(options: AgentSessionStartOptions): ReturnType<AgentSessionAdapter['start']>;
24
+ }
@@ -0,0 +1,85 @@
1
+ import { AcpSession } from '../session/acp.js';
2
+ import { hermesChildEnvironment, hermesMcpServers, validateHermesOptions, validateHermesRole } from './hermes-config.js';
3
+ import { hermesPermissionMode } from './hermes-permissions.js';
4
+ function requireValid(errors) {
5
+ if (errors.length)
6
+ throw new Error(errors.map(error => `${error.path}: ${error.message}`).join('; '));
7
+ }
8
+ function requireModel(model) {
9
+ if (typeof model !== 'string' || !model.trim())
10
+ throw new Error('Hermes requires an explicit non-empty Brain model');
11
+ return model.trim();
12
+ }
13
+ function preparedHome(prep) {
14
+ if (!prep.env.HERMES_HOME?.trim())
15
+ throw new Error('Hermes requires a prepared runtime home');
16
+ return prep.env.HERMES_HOME;
17
+ }
18
+ /** Fresh-only Hermes implementation of Fleet's existing live-session factory. */
19
+ export class HermesAgentSessionAdapter {
20
+ transport;
21
+ checks;
22
+ constructor(transport = AcpSession.start, checks) {
23
+ this.transport = transport;
24
+ this.checks = checks;
25
+ }
26
+ resolveBrain(brain) {
27
+ const model = requireModel(brain.model);
28
+ if (brain.effort != null)
29
+ throw new Error('Hermes does not support effort');
30
+ requireValid(validateHermesOptions(brain.harnessOptions));
31
+ return { model, ...(brain.harnessOptions ? { harnessOptions: brain.harnessOptions } : {}) };
32
+ }
33
+ modelEnvironmentVariable() { return undefined; }
34
+ prepareLaunch(role, prep) {
35
+ requireValid(validateHermesRole(role));
36
+ preparedHome(prep);
37
+ const command = role.session_options?.acp?.command;
38
+ const argv = Array.isArray(command) ? [...command]
39
+ : typeof command === 'string' ? ['sh', '-c', command] : ['hermes-acp'];
40
+ return { argv, env: { ...prep.env } };
41
+ }
42
+ sessionConfigSelections(role) {
43
+ requireValid(validateHermesRole(role));
44
+ return [];
45
+ }
46
+ async start(options) {
47
+ const { role, prep, launch } = options;
48
+ requireValid(validateHermesRole({ ...role, permissions: options.permissions }));
49
+ const model = requireModel(role.model);
50
+ if (!this.checks)
51
+ throw new Error('Hermes startup checks are required before launching a managed session');
52
+ // Reapply the complete environment boundary after runner routing/isolation
53
+ // composition; no second ambient merge may reintroduce provider secrets.
54
+ const env = hermesChildEnvironment(role, preparedHome(prep), launch.env, launch.env);
55
+ delete env.OURS_AUTOSTART;
56
+ await this.checks.preflight?.(options, env);
57
+ const nativeProvider = await this.checks.expectedProvider(role, prep);
58
+ if (typeof nativeProvider !== 'string' || !nativeProvider.trim())
59
+ throw new Error('Hermes requires an independently resolved native provider');
60
+ const provider = nativeProvider.trim().toLowerCase();
61
+ // model_catalog.encode_model_choice preserves model colons; its catalog
62
+ // constructor promotes Ollama to the named custom provider identity.
63
+ const expectedModelId = `${provider === 'ollama' ? 'custom:ollama' : provider}:${model}`;
64
+ const modeId = hermesPermissionMode(options.permissions);
65
+ return this.transport({
66
+ name: role.name, harness: 'hermes', argv: launch.argv, cwd: options.cwd, env,
67
+ inheritEnvironment: false, stateDir: options.stateDir, mode: 'fresh',
68
+ permissions: options.permissions, modeId, requireMode: true,
69
+ permissionMode: { fleetMode: options.permissionMode.fleetMode, nativeMode: modeId },
70
+ permissionTimeoutMs: 50_000,
71
+ mcpServers: hermesMcpServers(role, env),
72
+ scrubObsoleteOursAutostart: true,
73
+ validateStartupResponse: async (initialized, created) => {
74
+ await this.checks.validateArtifact(initialized);
75
+ if (typeof created.models?.currentModelId !== 'string'
76
+ || created.models.currentModelId !== expectedModelId)
77
+ throw new Error('Hermes fresh-session model/provider report does not match the Brain model and provisioned provider');
78
+ },
79
+ ...(role.monitor?.mode === 'fleet' && role.monitor.stall_recovery ? {
80
+ stallRecovery: { timeoutMs: role.monitor.stall_timeout_ms },
81
+ } : {}),
82
+ log: options.log,
83
+ });
84
+ }
85
+ }
@@ -0,0 +1,3 @@
1
+ export { validateHermesInitialize as validateHermesHandshake } from './hermes-compatibility.js';
2
+ /** Compare a native provisioned identity, never infer it from the child's report. */
3
+ export declare function hermesConfiguredProvider(home: string): string;
@@ -0,0 +1,21 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import YAML from 'yaml';
4
+ export { validateHermesInitialize as validateHermesHandshake } from './hermes-compatibility.js';
5
+ /** Compare a native provisioned identity, never infer it from the child's report. */
6
+ export function hermesConfiguredProvider(home) {
7
+ let provider;
8
+ try {
9
+ provider = YAML.parse(readFileSync(join(home, 'config.yaml'), 'utf8'))?.model?.provider;
10
+ }
11
+ catch {
12
+ throw new Error('Cannot read Hermes native provider; repair config.yaml in the stopped role home');
13
+ }
14
+ if (typeof provider !== 'string' || !provider.trim() || provider.trim().toLowerCase() === 'auto' || provider.includes('${'))
15
+ throw new Error('Hermes requires a literal native model.provider in the stopped role home so startup can detect provider fallback');
16
+ const canonical = provider.trim().toLowerCase();
17
+ // The tested runtime collapses named custom endpoints to custom, while its
18
+ // ACP model catalog reports Ollama under custom:ollama.
19
+ return canonical === 'ollama' || canonical === 'custom:ollama' ? 'custom:ollama'
20
+ : canonical.startsWith('custom:') ? 'custom' : canonical;
21
+ }
@@ -0,0 +1,5 @@
1
+ import { type Exec } from '../exec.js';
2
+ import type { AcpSessionTransport } from './acp-session-transport.js';
3
+ import type { HarnessAdapter } from './types.js';
4
+ export declare function makeHermesAdapter(exec?: Exec, transport?: AcpSessionTransport): HarnessAdapter;
5
+ export declare const hermesAdapter: HarnessAdapter;
@@ -0,0 +1,62 @@
1
+ import { realExec } from '../exec.js';
2
+ import { HermesAgentSessionAdapter } from './hermes-session.js';
3
+ import { inspectHermesCompatibility } from './hermes-compatibility.js';
4
+ import { hermesConfiguredProvider, validateHermesHandshake } from './hermes-startup.js';
5
+ import { prepareHermesConfig, validateHermesOptions, validateHermesRole } from './hermes-config.js';
6
+ import { hermesPermissionMode, translateHermesPermissions } from './hermes-permissions.js';
7
+ import { registerAdapter } from './registry.js';
8
+ const wakeNote = 'Your mail wake-ups are delivered by the fleet supervisor as `[fleet-monitor]` lines. '
9
+ + 'Call **get_messages**, handle the mail, and reply with send_message. '
10
+ + 'Do NOT arm arm_monitor, foreground_monitor or a native Hermes monitor.';
11
+ export function makeHermesAdapter(exec = realExec, transport) {
12
+ return {
13
+ id: 'hermes',
14
+ agentSession: new HermesAgentSessionAdapter(transport, {
15
+ expectedProvider: (_role, prep) => hermesConfiguredProvider(prep.env.HERMES_HOME),
16
+ validateArtifact: validateHermesHandshake,
17
+ async preflight(options, env) {
18
+ const original = new HermesAgentSessionAdapter().prepareLaunch(options.role, options.prep);
19
+ const report = await inspectHermesCompatibility({ argv: original.argv, env, home: options.prep.env.HERMES_HOME }, exec);
20
+ options.log(`Hermes ${report.artifact.hermesVersion}, ACP ${report.artifact.acpVersion}; fresh conversation, MCP availability unverified until actual use`);
21
+ },
22
+ }),
23
+ supportsResume: false,
24
+ async checkPrereqs() {
25
+ const result = await exec('hermes-acp', ['--help'], { timeout: 10_000 });
26
+ const ok = result.code === 0;
27
+ return { ok, checks: [{ name: 'hermes-acp', ok, detail: ok
28
+ ? 'Hermes ACP executable found; launch still requires a tested compatible artifact, an explicit Brain model and provider/credentials provisioned in the exact stopped role home. Home/plugin MCP providers must be disabled.'
29
+ : 'hermes-acp unavailable; install the tested Hermes artifact and provision provider/credentials in the exact stopped role home.' }] };
30
+ },
31
+ validateOptions(options, role) {
32
+ return role ? validateHermesRole({ ...role, harness_options: options })
33
+ : validateHermesOptions(options);
34
+ },
35
+ prepareSession: prepareHermesConfig,
36
+ // The selected home is already beneath the role state directory, which
37
+ // Fleet mounts writable. No operator home or credential path is shared.
38
+ isolationPaths: () => ({ shared: [] }),
39
+ nativePermissionOverrides: () => ({}),
40
+ translatePermissions: translateHermesPermissions,
41
+ effectivePermissions: role => translateHermesPermissions(role.permissions),
42
+ effectivePermissionMode(role) {
43
+ const nativeMode = hermesPermissionMode(role.permissions);
44
+ return { fleetMode: role.permissions.approval, nativeMode };
45
+ },
46
+ vocabulary: {
47
+ bindTool: 'choose_identity', createTool: 'create_identity',
48
+ temporaryCreateTool: 'create_temporary_identity', setBioTool: 'set_bio',
49
+ setPersonaTool: 'set_persona', currentIdentityTool: 'current_identity',
50
+ sendTool: 'send_message', getMessagesTool: 'get_messages',
51
+ listHistoryTool: 'list_history', getHistoryItemTool: 'get_history_item',
52
+ monitorInstruction: () => wakeNote,
53
+ supervisedWakeNote: () => wakeNote,
54
+ launchNote: name => `You were launched as Fleet role ${name} in a fresh Hermes ACP conversation. Confirm you are running.`,
55
+ restartPrompt: (identity, worklog) => `This is a fresh Hermes conversation. Follow the full role briefing, bind identity "${identity}" without force, `
56
+ + `and continue from ${worklog}. Native memory and skills persist; the previous conversation is not restored. ${wakeNote}`,
57
+ },
58
+ exitPolicy: { cleanExitIsFresh: true, fastFailSecs: 20 },
59
+ };
60
+ }
61
+ export const hermesAdapter = makeHermesAdapter();
62
+ registerAdapter(hermesAdapter);
@@ -29,7 +29,7 @@ export function knownAdapters() {
29
29
  * registry" is not the same question — this is the set doctor falls back to
30
30
  * when a broken configuration names no harness at all.
31
31
  */
32
- const PRODUCTION_ADAPTERS = ['claude-code', 'codex'];
32
+ const PRODUCTION_ADAPTERS = ['claude-code', 'codex', 'hermes'];
33
33
  /** Production adapters actually registered in this process. */
34
34
  export function productionAdapters() {
35
35
  return PRODUCTION_ADAPTERS.filter(id => adapters.has(id));
package/dist/index.d.ts CHANGED
@@ -9,6 +9,7 @@ export { OwnerChannel } from './owner-channel/channel.js';
9
9
  export { registerAdapter, getAdapter, knownAdapters } from './harness/registry.js';
10
10
  export { claudeCodeAdapter, makeClaudeCodeAdapter } from './harness/claude-code.js';
11
11
  export { codexAdapter, makeCodexAdapter } from './harness/codex.js';
12
+ export { hermesAdapter, makeHermesAdapter } from './harness/hermes.js';
12
13
  export { generateBriefing } from './briefing.js';
13
14
  export { effectivePermissionMode } from './permissions.js';
14
15
  export { pickBackend } from './supervisor/index.js';
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@ export { OwnerChannel } from './owner-channel/channel.js';
6
6
  export { registerAdapter, getAdapter, knownAdapters } from './harness/registry.js';
7
7
  export { claudeCodeAdapter, makeClaudeCodeAdapter } from './harness/claude-code.js';
8
8
  export { codexAdapter, makeCodexAdapter } from './harness/codex.js';
9
+ export { hermesAdapter, makeHermesAdapter } from './harness/hermes.js';
9
10
  export { generateBriefing } from './briefing.js';
10
11
  export { effectivePermissionMode } from './permissions.js';
11
12
  export { pickBackend } from './supervisor/index.js';
@@ -42,18 +42,23 @@ export interface InitPublishResult {
42
42
  manifestExisted: boolean;
43
43
  rootExisted: boolean;
44
44
  }
45
+ export interface InitExecutionDeps {
46
+ hostSetup(): Promise<void>;
47
+ publish(configuration: string, setup: GeneratedSetup): Promise<InitPublishResult>;
48
+ generate?(answers: InitAnswers): GeneratedSetup;
49
+ preflight?(configuration: string): InitPathState;
50
+ }
45
51
  export declare function validateCatalog(value: BrainCatalog, path?: string): BrainCatalog;
52
+ /** Read and validate the complete public InitAnswers JSON shape without side effects. */
53
+ export declare function readInitSettings(path: string): InitAnswers;
46
54
  export declare function askInitQuestions(prompter: InitPrompter, configuration: string): Promise<InitAnswers | undefined>;
47
55
  export declare function formatSetupSummary(answers: InitAnswers, configuration: string): string;
48
56
  /** Build the exact, deterministic default experience without writing to disk. */
49
57
  export declare function generateSetup(answers: InitAnswers): GeneratedSetup;
50
58
  /** Run the mutation boundary only after the complete questionnaire is accepted. */
51
- export declare function executeInitWizard(prompter: InitPrompter, configuration: string, deps: {
52
- hostSetup(): Promise<void>;
53
- publish(configuration: string, setup: GeneratedSetup): Promise<InitPublishResult>;
54
- generate?(answers: InitAnswers): GeneratedSetup;
55
- preflight?(configuration: string): InitPathState;
56
- }): Promise<InitPublishResult | undefined>;
59
+ export declare function executeInitWizard(prompter: InitPrompter, configuration: string, deps: InitExecutionDeps): Promise<InitPublishResult | undefined>;
60
+ /** Execute already-collected answers through the same validation and mutation boundary. */
61
+ export declare function executeInitAnswers(answers: InitAnswers, configuration: string, deps: InitExecutionDeps): Promise<InitPublishResult>;
57
62
  export interface InitPathInspectionDeps {
58
63
  exists?(path: string): boolean;
59
64
  lstat?(path: string): Stats;
@@ -49,6 +49,35 @@ function catalog() {
49
49
  const path = join(packagedPresetRoot(), 'brain-catalog.json');
50
50
  return validateCatalog(JSON.parse(readFileSync(path, 'utf8')), path);
51
51
  }
52
+ const hasExactKeys = (value, keys) => Object.keys(value).sort().join('\0') === [...keys].sort().join('\0');
53
+ /** Read and validate the complete public InitAnswers JSON shape without side effects. */
54
+ export function readInitSettings(path) {
55
+ let value;
56
+ try {
57
+ value = JSON.parse(readFileSync(resolve(path), 'utf8'));
58
+ }
59
+ catch (error) {
60
+ throw new Error(`cannot read valid Fleet init settings ${path}: ${error.message}`, { cause: error });
61
+ }
62
+ if (!value || typeof value !== 'object' || Array.isArray(value)
63
+ || !hasExactKeys(value, ['subscriptions', 'assignmentStrategy', 'models', 'reasoning']))
64
+ throw new Error('Fleet init settings must contain exactly subscriptions, assignmentStrategy, models, and reasoning');
65
+ const candidate = value;
66
+ const models = candidate.models;
67
+ if (!models || typeof models !== 'object' || Array.isArray(models)
68
+ || !hasExactKeys(models, WORK_KINDS))
69
+ throw new Error('Fleet init settings models must contain exactly development, review, and coordination');
70
+ for (const work of WORK_KINDS) {
71
+ const model = models[work];
72
+ if (!model || typeof model !== 'object' || Array.isArray(model)
73
+ || !hasExactKeys(model, ['harness', 'session', 'model', 'efforts']))
74
+ throw new Error(`Fleet init settings ${work} model must contain exactly harness, session, model, and efforts`);
75
+ }
76
+ const answers = value;
77
+ // Generation is the single semantic/catalog validator for wizard and file input.
78
+ generateSetup(answers);
79
+ return answers;
80
+ }
52
81
  const subscriptionFor = (model) => model.harness === 'codex' ? 'codex' : 'claude';
53
82
  export async function askInitQuestions(prompter, configuration) {
54
83
  const configPath = resolve(configuration);
@@ -216,6 +245,10 @@ export async function executeInitWizard(prompter, configuration, deps) {
216
245
  const answers = await askInitQuestions(prompter, configuration);
217
246
  if (!answers)
218
247
  return undefined;
248
+ return executeInitAnswers(answers, configuration, deps);
249
+ }
250
+ /** Execute already-collected answers through the same validation and mutation boundary. */
251
+ export async function executeInitAnswers(answers, configuration, deps) {
219
252
  // Resolve every catalog/preset dependency before crossing the first mutation
220
253
  // boundary. Production owns this new map; the optional seam forces failures
221
254
  // deterministically in tests.
package/dist/monitor.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { type AttachOursClientOptions } from '@ours.network/sdk/client';
1
2
  import type { MonitorConfig, MonitorInterrupt, NotifyEventType } from './config.js';
2
3
  import { type FailureEvidence } from './model-recovery.js';
3
4
  /** A content-free arrival event as the daemon serves it over the notifications API. */
@@ -26,6 +27,28 @@ export type FetchLike = (url: string, init?: {
26
27
  headers?: Record<string, string>;
27
28
  signal?: AbortSignal;
28
29
  }) => Promise<FetchResponse>;
30
+ export interface MonitorPageClient {
31
+ readNotificationPage(identity: string, options?: {
32
+ since?: number | 'tip';
33
+ signal?: AbortSignal;
34
+ requestTimeoutMs?: number;
35
+ }): Promise<{
36
+ cursor: number;
37
+ events: Array<Record<string, unknown>>;
38
+ }>;
39
+ close(): Promise<void>;
40
+ }
41
+ export interface IdentityProbeClient {
42
+ identities(): Promise<Array<string | {
43
+ name?: unknown;
44
+ temporary?: unknown;
45
+ stale?: unknown;
46
+ }>>;
47
+ close(): Promise<void>;
48
+ }
49
+ export interface IdentityProbeDeps {
50
+ attachClient?(options: AttachOursClientOptions): IdentityProbeClient | Promise<IdentityProbeClient>;
51
+ }
29
52
  export interface MonitorDeps {
30
53
  fetch: FetchLike;
31
54
  isAlive(pid: number): boolean;
@@ -37,6 +60,8 @@ export interface MonitorDeps {
37
60
  set(fn: () => void, ms: number): ReturnType<typeof setTimeout>;
38
61
  clear(t: ReturnType<typeof setTimeout>): void;
39
62
  };
63
+ /** Test seam; production attaches through the SDK's verified selection path. */
64
+ attachClient?(options: AttachOursClientOptions): MonitorPageClient | Promise<MonitorPageClient>;
40
65
  /**
41
66
  * Structured prompt delivery used by agent sessions.
42
67
  * `succeeded` is the turn's TERMINAL result, not merely that the session took
@@ -101,13 +126,13 @@ export type IdentityPresence = {
101
126
  detail: string;
102
127
  };
103
128
  /** Resolve the daemon endpoint + auth header from env → config → defaults. */
104
- export declare function resolveEndpoint(env: NodeJS.ProcessEnv): DaemonEndpoint;
129
+ export declare function resolveEndpoint(env: NodeJS.ProcessEnv, includeToken?: boolean): DaemonEndpoint;
105
130
  /**
106
131
  * Ask the daemon's authoritative identity index. The notifications endpoint is
107
132
  * intentionally unsuitable for lifecycle: it serves an empty 200 page for a
108
133
  * valid but missing identity, which made a closed temp identity look healthy.
109
134
  */
110
- export declare function probeIdentityPresence(name: string, fetch: FetchLike, env: NodeJS.ProcessEnv): Promise<IdentityPresence>;
135
+ export declare function probeIdentityPresence(name: string, fetch: FetchLike, env: NodeJS.ProcessEnv, deps?: IdentityProbeDeps): Promise<IdentityPresence>;
111
136
  /** Actionable, secret-free description of every token source for this profile. */
112
137
  export declare function authResolutionHint(ep: DaemonEndpoint): string;
113
138
  /** Keep only the events whose type the role asked to wake on. */
@@ -171,7 +196,11 @@ export declare class Monitor {
171
196
  private readonly identity;
172
197
  private readonly cfg;
173
198
  private readonly deps;
174
- private readonly ep;
199
+ private readonly ep?;
200
+ private readonly profile?;
201
+ private readonly profileKey;
202
+ private readonly monitorLeaseToken;
203
+ private profileClientPromise?;
175
204
  private readonly statusPath;
176
205
  private readonly cursorPath;
177
206
  private readonly statePath;
@@ -212,6 +241,8 @@ export declare class Monitor {
212
241
  * no-ops (delivery is still verified downstream).
213
242
  */
214
243
  private doFetch;
244
+ private profileClient;
245
+ private disposeProfileClient;
215
246
  private advance;
216
247
  private persistCursor;
217
248
  private readPersistedCursor;