@karmaniverous/jeeves 0.5.12 → 0.6.0-0

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/index.d.ts CHANGED
@@ -2,13 +2,94 @@ import { Command } from '@commander-js/extra-typings';
2
2
  import { z } from 'zod';
3
3
 
4
4
  /**
5
- * Core types for the OpenClaw plugin SDK.
5
+ * Structural types for OpenClaw's `before_prompt_build` hook and plugin
6
+ * lifecycle API (subset, OpenClaw v2026.9.6).
6
7
  *
7
8
  * @remarks
8
- * These types define the contract between plugins and the OpenClaw gateway.
9
- * They unify the various `PluginApi` definitions previously duplicated
10
- * across component plugins into a single canonical source.
9
+ * `PromptBuildResult` deliberately omits `systemPrompt`: in OpenClaw it
10
+ * REPLACES the entire system prompt (first value wins). Jeeves plugins must
11
+ * only append, via `appendSystemContext` (runbook D5).
12
+ *
13
+ * @module
14
+ */
15
+ /** Event passed to `before_prompt_build` handlers (subset). */
16
+ interface PromptBuildEvent {
17
+ /** Current prompt text. */
18
+ prompt: string;
19
+ /** Session messages prepared for this run. */
20
+ messages: unknown[];
21
+ }
22
+ /** Agent context passed to hook handlers (subset). */
23
+ interface PromptBuildContext {
24
+ /** Agent id. */
25
+ agentId?: string;
26
+ /** Session key. */
27
+ sessionKey?: string;
28
+ /** Workspace directory for this run. */
29
+ workspaceDir?: string;
30
+ /** Channel/plugin id for channel-originated runs. */
31
+ channel?: string;
32
+ /** What triggered this turn (e.g. `user`, `heartbeat`, `cron`). */
33
+ trigger?: string;
34
+ }
35
+ /**
36
+ * Result a Jeeves `before_prompt_build` handler may return.
37
+ *
38
+ * @remarks
39
+ * `appendSystemContext` is appended after the prompt-cache boundary in an
40
+ * "OpenClaw plugin-injected system context" block; text from several plugins
41
+ * is concatenated in priority order and does not count toward
42
+ * `bootstrapMaxChars`.
11
43
  */
44
+ interface PromptBuildResult {
45
+ /** Text appended to the agent system prompt. */
46
+ appendSystemContext?: string;
47
+ }
48
+ /** A `before_prompt_build` handler. */
49
+ type PromptBuildHandler = (event: PromptBuildEvent, ctx: PromptBuildContext) => Promise<PromptBuildResult | undefined> | PromptBuildResult | undefined;
50
+ /** Hook registration options (subset). */
51
+ interface HookRegistrationOptions {
52
+ /** Ordering among handlers; higher runs first. */
53
+ priority?: number;
54
+ /** Stable id for this registration. */
55
+ registrationId?: string;
56
+ /** Per-handler timeout in ms (OpenClaw default for this hook: 15 000). */
57
+ timeoutMs?: number;
58
+ }
59
+ /** Plugin-owned lifecycle API (subset of `api.lifecycle`). */
60
+ interface PluginLifecycleApi {
61
+ /** Aborted when the plugin instance is retired. */
62
+ readonly signal?: AbortSignal;
63
+ /**
64
+ * Register a disposer run when the plugin instance is retired.
65
+ *
66
+ * @returns A function that unregisters the disposer.
67
+ */
68
+ onDispose?: (dispose: () => void | Promise<void>) => () => void;
69
+ /** Register named cleanup for plugin-owned background work. */
70
+ registerRuntimeLifecycle?: (registration: {
71
+ /** Registration id. */
72
+ id: string;
73
+ /** Human-readable description. */
74
+ description?: string;
75
+ /** Release resources. */
76
+ dispose?: () => void | Promise<void>;
77
+ }) => void;
78
+ }
79
+
80
+ /**
81
+ * Structural subset of the OpenClaw plugin API used by Jeeves plugins.
82
+ *
83
+ * @remarks
84
+ * Mirrors the shapes in OpenClaw's plugin SDK (v2026.9.6:
85
+ * `src/plugins/plugin-api.types.ts`, `hook-types.ts`,
86
+ * `hook-before-agent-start.types.ts`, `plugin-instance.types.ts`) without
87
+ * depending on OpenClaw. Only the members Jeeves uses are declared; optional
88
+ * members degrade gracefully on older hosts.
89
+ *
90
+ * @module
91
+ */
92
+
12
93
  /** Result shape returned by tool executions. */
13
94
  interface ToolResult {
14
95
  /** Content blocks — typically a single text block. */
@@ -72,6 +153,27 @@ interface PluginApi {
72
153
  * Present on newer OpenClaw builds; optional for backwards compatibility.
73
154
  */
74
155
  resolvePath?: (input: string) => string;
156
+ /** Plugin-scoped config (`plugins.entries.<id>.config`), when provided. */
157
+ pluginConfig?: Record<string, unknown>;
158
+ /** Host logger, when provided. */
159
+ logger?: {
160
+ /** Log a warning. */
161
+ warn: (message: string) => void;
162
+ };
163
+ /**
164
+ * Plugin-owned lifecycle: disposal signal and cleanup registration.
165
+ * Present on OpenClaw 2026.9.x.
166
+ */
167
+ lifecycle?: PluginLifecycleApi;
168
+ /**
169
+ * Register a typed hook handler. Jeeves only uses `before_prompt_build`
170
+ * (see {@link registerPromptContext}).
171
+ *
172
+ * @param hookName - Hook name.
173
+ * @param handler - Hook handler.
174
+ * @param opts - Registration options.
175
+ */
176
+ on?(hookName: 'before_prompt_build', handler: PromptBuildHandler, opts?: HookRegistrationOptions): void;
75
177
  /**
76
178
  * Register a tool with the OpenClaw gateway.
77
179
  *
@@ -85,18 +187,14 @@ interface PluginApi {
85
187
  * Zod schema for the Jeeves component descriptor.
86
188
  *
87
189
  * @remarks
88
- * The descriptor replaces the v0.4.0 `JeevesComponent` interface with a
89
- * Zod-first approach. The TypeScript type is inferred via `z.infer<>`.
90
- * Validates at parse time: prime interval, callable functions.
91
- */
92
-
93
- /**
94
- * Check whether a number is prime.
190
+ * Zod-first: the TypeScript type is inferred via `z.infer<>`. The descriptor
191
+ * drives the service CLI, service manager, config handlers, and standard
192
+ * plugin toolset. v1 removed the TOOLS.md writer fields (`sectionId`,
193
+ * `refreshIntervalSeconds`, `generateToolsContent`, `dependencies`).
95
194
  *
96
- * @param n - Number to check.
97
- * @returns `true` if n is prime.
195
+ * @module
98
196
  */
99
- declare function isPrime(n: number): boolean;
197
+
100
198
  /**
101
199
  * Zod schema for the Jeeves component descriptor.
102
200
  *
@@ -119,13 +217,6 @@ declare const jeevesComponentDescriptorSchema: z.ZodObject<{
119
217
  customMerge: z.ZodOptional<z.ZodFunction<z.ZodTuple<readonly [z.ZodRecord<z.ZodString, z.ZodUnknown>, z.ZodRecord<z.ZodString, z.ZodUnknown>], null>, z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
120
218
  startCommand: z.ZodFunction<z.ZodTuple<readonly [z.ZodString], null>, z.ZodArray<z.ZodString>>;
121
219
  run: z.ZodFunction<z.ZodTuple<readonly [z.ZodString], null>, z.ZodPromise<z.ZodVoid>>;
122
- sectionId: z.ZodString;
123
- refreshIntervalSeconds: z.ZodNumber;
124
- generateToolsContent: z.ZodFunction<z.ZodTuple<readonly [], null>, z.ZodString>;
125
- dependencies: z.ZodOptional<z.ZodObject<{
126
- hard: z.ZodArray<z.ZodString>;
127
- soft: z.ZodArray<z.ZodString>;
128
- }, z.core.$strip>>;
129
220
  customCliCommands: z.ZodOptional<z.ZodFunction<z.ZodTuple<readonly [z.ZodCustom<Command<[], {}, {}>, Command<[], {}, {}>>], null>, z.ZodVoid>>;
130
221
  customPluginTools: z.ZodOptional<z.ZodFunction<z.ZodTuple<readonly [z.ZodCustom<PluginApi, PluginApi>], null>, z.ZodArray<z.ZodUnknown>>>;
131
222
  }, z.core.$strip>;
@@ -189,6 +280,8 @@ declare function createConfigApplyHandler(descriptor: JeevesComponentDescriptor,
189
280
  * Provides a transport-agnostic config query function that can be
190
281
  * used by any Jeeves component's HTTP API. Returns the full config
191
282
  * document or filters it via JSONPath expressions.
283
+ *
284
+ * @module
192
285
  */
193
286
  /** Response shape for config query results. */
194
287
  interface ConfigQueryResponse {
@@ -223,9 +316,11 @@ declare function createConfigQueryHandler(getConfig: () => unknown): ConfigQuery
223
316
  * Factory for a framework-agnostic `/status` HTTP handler.
224
317
  *
225
318
  * @remarks
226
- * Returns a standard status response shape consumed by HEARTBEAT
227
- * orchestration and the `{name}_status` plugin tool.
319
+ * Returns a standard status response shape consumed by `jeeves status` and
320
+ * the `{name}_status` plugin tool.
228
321
  * Tracks process start time internally for uptime calculation.
322
+ *
323
+ * @module
229
324
  */
230
325
  /** Options for creating a status handler. */
231
326
  interface CreateStatusHandlerOptions {
@@ -295,11 +390,13 @@ declare function substituteEnvVars<T>(value: T): T;
295
390
  * Workspace-level shared configuration: `jeeves.config.json`.
296
391
  *
297
392
  * @remarks
298
- * Lives at the OpenClaw workspace root alongside TOOLS.md and SOUL.md.
393
+ * Lives at the OpenClaw workspace root alongside SOUL.md and AGENTS.md.
299
394
  * Provides namespaced shared defaults consumed by the root Jeeves CLI.
300
395
  * Resolution precedence: CLI flags → env vars → jeeves.config.json → defaults.
301
396
  *
302
397
  * This does not replace component-owned config schemas (Decision 41).
398
+ *
399
+ * @module
303
400
  */
304
401
 
305
402
  /** Workspace config file name. */
@@ -429,35 +526,6 @@ interface ResolvedCliConfig {
429
526
  */
430
527
  declare function buildEffectiveConfig(opts: WorkspaceOptions): ResolvedCliConfig;
431
528
 
432
- /**
433
- * Factory for the standard `-openclaw` plugin installer CLI.
434
- *
435
- * @module
436
- */
437
-
438
- /** Options for creating a plugin installer CLI. */
439
- interface CreatePluginCliOptions {
440
- /** Plugin identifier (e.g., 'jeeves-watcher-openclaw'). */
441
- pluginId: string;
442
- /** `import.meta.url` for the calling plugin CLI module. */
443
- importMetaUrl: string;
444
- /** npm package name for the plugin. */
445
- pluginPackage: string;
446
- /** Component name (e.g., 'watcher'). Derived from pluginId if omitted. */
447
- componentName?: string;
448
- /** Workspace root (defaults to OpenClaw workspace). */
449
- workspace?: string;
450
- /** Config root (defaults to 'j:/config'). */
451
- configRoot?: string;
452
- }
453
- /**
454
- * Create a standard plugin installer CLI program.
455
- *
456
- * @param options - Plugin CLI configuration.
457
- * @returns A Commander program ready for `.parse()`.
458
- */
459
- declare function createPluginCli(options: CreatePluginCliOptions): Command;
460
-
461
529
  /**
462
530
  * Factory for the standard Jeeves service CLI.
463
531
  *
@@ -491,336 +559,30 @@ declare function createPluginCli(options: CreatePluginCliOptions): Command;
491
559
  declare function createServiceCli(descriptor: JeevesComponentDescriptor): Command;
492
560
 
493
561
  /**
494
- * Shared component version state file management.
562
+ * Platform component registry.
495
563
  *
496
564
  * @remarks
497
- * Each `ComponentWriter` cycle writes its component's entry to
498
- * `{coreConfigDir}/component-versions.json`. The Platform Handlebars
499
- * template reads this file to populate ALL rows in the service health
500
- * table, not just the calling component's.
501
- */
502
- /** Version entry for a single component. */
503
- interface ComponentVersionEntry {
504
- /** Plugin version (the OpenClaw plugin package version). */
505
- pluginVersion?: string;
506
- /** npm package name for the service. */
507
- servicePackage?: string;
508
- /** npm package name for the plugin. */
509
- pluginPackage?: string;
510
- /** ISO timestamp of last update. */
511
- updatedAt: string;
512
- }
513
- /** Shape of the component-versions.json file. */
514
- type ComponentVersionsState = Record<string, ComponentVersionEntry>;
515
- /**
516
- * Read the component versions state file.
565
+ * The four essential components that constitute the Jeeves platform.
517
566
  *
518
- * @param coreConfigDir - Path to the core config directory.
519
- * @returns The parsed state, or an empty object if the file doesn't exist.
520
- */
521
- declare function readComponentVersions(coreConfigDir: string): ComponentVersionsState;
522
- /** Options for writing a component version entry. */
523
- interface WriteComponentVersionOptions {
524
- /** Component name. */
525
- componentName: string;
526
- /** Plugin version. */
527
- pluginVersion?: string;
528
- /** Service npm package name. */
529
- servicePackage?: string;
530
- /** Plugin npm package name. */
531
- pluginPackage?: string;
532
- }
533
- /**
534
- * Write a component's version entry to the shared state file.
535
- *
536
- * @remarks
537
- * Reads the existing file, merges the new entry, and writes atomically.
538
- *
539
- * @param coreConfigDir - Path to the core config directory.
540
- * @param options - Component version data to write.
541
- */
542
- declare function writeComponentVersion(coreConfigDir: string, options: WriteComponentVersionOptions): void;
543
- /**
544
- * Remove a component's version entry from the shared state file.
545
- *
546
- * @remarks
547
- * Called during plugin uninstall to prevent the HEARTBEAT writer from
548
- * probing a service that's intentionally gone. If the component isn't
549
- * in the file, this is a no-op.
550
- *
551
- * @param coreConfigDir - Path to the core config directory.
552
- * @param componentName - The component name to remove.
553
- */
554
- declare function removeComponentVersion(coreConfigDir: string, componentName: string): void;
555
-
556
- /**
557
- * Timer-based orchestrator for managed content writing.
558
- *
559
- * @remarks
560
- * `ComponentWriter` manages a component's TOOLS.md section writes
561
- * and platform content maintenance (SOUL.md, AGENTS.md, Platform section)
562
- * on a configurable prime-interval timer cycle.
563
- */
564
-
565
- /** Options for ComponentWriter construction. */
566
- interface ComponentWriterOptions {
567
- /**
568
- * Gateway URL for cleanup escalation (e.g., 'http://localhost:3000').
569
- * When provided, the writer will attempt to spawn a cleanup session
570
- * via the gateway when orphaned content is detected.
571
- * When omitted, cleanup escalation is silently skipped.
572
- */
573
- gatewayUrl?: string;
574
- }
575
- /**
576
- * Orchestrates managed content writing for a single Jeeves component.
577
- *
578
- * @remarks
579
- * Created via {@link createComponentWriter}. Manages a timer that fires
580
- * at the component's prime-interval, calling `generateToolsContent()`
581
- * and `refreshPlatformContent()` on each cycle.
582
- */
583
- declare class ComponentWriter {
584
- private timer;
585
- private jitterTimeout;
586
- private readonly component;
587
- private readonly configDir;
588
- private readonly gatewayUrl;
589
- private readonly pendingCleanups;
590
- private cyclePromise;
591
- private stopped;
592
- /** @internal */
593
- constructor(component: JeevesComponentDescriptor, options?: ComponentWriterOptions);
594
- /** The component's config directory path. */
595
- get componentConfigDir(): string;
596
- /** Whether the writer timer is currently running or pending its first cycle. */
597
- get isRunning(): boolean;
598
- /**
599
- * Start the writer timer.
600
- *
601
- * @remarks
602
- * Delays the first cycle by a random jitter (0 to one full interval) to
603
- * spread initial writes across all component plugins and reduce EPERM
604
- * contention on startup.
605
- */
606
- start(): void;
607
- /** Stop the writer timer. */
608
- stop(): void;
609
- private scheduleNextCycle;
610
- /**
611
- * Execute a single write cycle.
612
- *
613
- * @remarks
614
- * 1. Write the component's TOOLS.md section.
615
- * 2. Refresh shared platform content (SOUL.md, AGENTS.md, Platform section).
616
- * 3. Scan for cleanup flags and escalate if a gateway URL is configured.
617
- * 4. Run HEARTBEAT health orchestration.
618
- */
619
- cycle(): Promise<void>;
620
- private runCycle;
621
- }
622
-
623
- /**
624
- * Creates a synchronous content accessor backed by an async data source.
625
- *
626
- * @remarks
627
- * Solves the sync/async gap in `JeevesComponentDescriptor.generateToolsContent()`:
628
- * the interface is synchronous, but most components fetch live data from
629
- * their HTTP service. This utility returns a sync `() => string` that
630
- * serves the last successfully fetched value while kicking off a background
631
- * refresh on each call.
632
- *
633
- * First call returns `placeholder`. Subsequent calls return the last
634
- * successfully fetched content. If a refresh fails, the previous good
635
- * value is retained.
636
- *
637
- * @example
638
- * ```typescript
639
- * const getContent = createAsyncContentCache({
640
- * fetch: async () => {
641
- * const res = await fetch('http://127.0.0.1:1936/status');
642
- * return formatWatcherStatus(await res.json());
643
- * },
644
- * placeholder: '> Initializing watcher status...',
645
- * });
646
- *
647
- * const writer = createComponentWriter({
648
- * // ...
649
- * generateToolsContent: getContent,
650
- * });
651
- * ```
652
- */
653
- /** Options for {@link createAsyncContentCache}. */
654
- interface AsyncContentCacheOptions {
655
- /**
656
- * Async function that fetches fresh content.
657
- * Errors are caught and logged; the previous value is retained.
658
- */
659
- fetch: () => Promise<string>;
660
- /**
661
- * Content returned before the first successful fetch.
662
- *
663
- * @defaultValue `'> Initializing...'`
664
- */
665
- placeholder?: string;
666
- /**
667
- * Optional error handler. Called when `fetch` throws.
668
- * Defaults to a handler that logs transient network errors as
669
- * concise warnings and unexpected errors with full details.
670
- */
671
- onError?: (error: unknown) => void;
672
- }
673
- /**
674
- * Creates a synchronous content accessor backed by an async data source.
675
- *
676
- * @param options - Cache configuration.
677
- * @returns A sync `() => string` suitable for `generateToolsContent`.
678
- */
679
- declare function createAsyncContentCache(options: AsyncContentCacheOptions): () => string;
680
-
681
- /**
682
- * Factory function for creating a ComponentWriter from a descriptor.
683
- *
684
- * @remarks
685
- * Validates the descriptor via Zod schema and creates a ComponentWriter.
686
- * Accepts `JeevesComponentDescriptor` (v0.5.0) only. The v0.4.0
687
- * `JeevesComponent` interface is no longer accepted.
688
- */
689
-
690
- /**
691
- * Create a ComponentWriter for a validated component descriptor.
692
- *
693
- * @remarks
694
- * The descriptor is validated via the Zod schema at runtime.
695
- * This replaces the v0.4.0 `createComponentWriter(JeevesComponent)`.
696
- *
697
- * @param descriptor - The component descriptor to validate and wrap.
698
- * @param options - Optional writer configuration (e.g., gatewayUrl for cleanup escalation).
699
- * @returns A new `ComponentWriter` instance.
700
- * @throws ZodError if the descriptor is invalid.
701
- */
702
- declare function createComponentWriter(descriptor: JeevesComponentDescriptor, options?: ComponentWriterOptions): ComponentWriter;
703
-
704
- /**
705
- * Heading-based HEARTBEAT section writer.
706
- *
707
- * @remarks
708
- * Manages the `# Jeeves Platform Status` section in HEARTBEAT.md.
709
- * Unlike TOOLS/SOUL/AGENTS (which use HTML comment markers), HEARTBEAT
710
- * uses markdown headings as markers — this ensures the file passes
711
- * OpenClaw's heartbeat emptiness check when only headings remain.
712
- *
713
- * The section is always at the bottom of the file (H1 to EOF).
714
- * User heartbeat items above the section are preserved.
715
- */
716
- /** The H1 heading that anchors the platform status section. */
717
- declare const HEARTBEAT_HEADING = "# Jeeves Platform Status";
718
- /** A single component entry in the HEARTBEAT section. */
719
- interface HeartbeatEntry {
720
- /** Component name (e.g., 'runner', 'watcher'). */
721
- name: string;
722
- /** Whether the component is declined. */
723
- declined: boolean;
724
- /** Alert content (list items). Empty string if healthy or declined. */
725
- content: string;
726
- }
727
- /** Result of parsing the HEARTBEAT section. */
728
- interface ParsedHeartbeat {
729
- /** Content above the `# Jeeves Platform Status` heading (user zone). */
730
- userContent: string;
731
- /** Whether the heading was found. */
732
- found: boolean;
733
- /** Parsed component entries. */
734
- entries: HeartbeatEntry[];
735
- }
736
- /**
737
- * Parse the HEARTBEAT.md file content.
738
- *
739
- * @param fileContent - Full file content.
740
- * @returns Parsed result with user zone and component entries.
741
- */
742
- declare function parseHeartbeat(fileContent: string): ParsedHeartbeat;
743
- /**
744
- * Build the HEARTBEAT section content from entries.
745
- *
746
- * @param entries - Component entries to write.
747
- * @returns The full section string (H1 + H2s).
748
- */
749
- declare function buildHeartbeatSection(entries: HeartbeatEntry[]): string;
750
- /**
751
- * Write the HEARTBEAT section to a file.
752
- *
753
- * @remarks
754
- * Replaces everything from `# Jeeves Platform Status` to EOF.
755
- * Preserves user content above the heading.
756
- *
757
- * @param filePath - Absolute path to HEARTBEAT.md.
758
- * @param entries - Component entries to write.
759
- */
760
- declare function writeHeartbeatSection(filePath: string, entries: HeartbeatEntry[]): Promise<void>;
761
-
762
- /**
763
- * HEARTBEAT health orchestration.
764
- *
765
- * @remarks
766
- * Determines the state of each platform component and generates
767
- * HEARTBEAT entries with actionable alert text. Applies the dependency
768
- * graph for alert suppression and auto-decline.
769
- */
770
-
771
- /** Component state as determined by the orchestrator. */
772
- type ComponentState = 'not_installed' | 'deps_missing' | 'config_missing' | 'service_not_installed' | 'service_stopped' | 'healthy' | 'update_available';
773
- /** Options for the orchestrator. */
774
- interface OrchestrateHeartbeatOptions {
775
- /** Path to the core config directory. */
776
- coreConfigDir: string;
777
- /** Path to the config root. */
778
- configRoot: string;
779
- /** Existing declined component names (from parsing current HEARTBEAT). */
780
- declinedNames: Set<string>;
781
- }
782
- /**
783
- * Orchestrate HEARTBEAT entries for all platform components.
784
- *
785
- * @param options - Orchestration configuration.
786
- * @returns Array of HeartbeatEntry for writeHeartbeatSection.
567
+ * @module
787
568
  */
788
- declare function orchestrateHeartbeat(options: OrchestrateHeartbeatOptions): Promise<HeartbeatEntry[]>;
569
+ /** The four essential platform components. */
570
+ declare const PLATFORM_COMPONENTS: readonly ["runner", "watcher", "server", "meta"];
571
+ /** A platform component name. */
572
+ type PlatformComponent = (typeof PLATFORM_COMPONENTS)[number];
789
573
 
790
574
  /**
791
- * Component interface types for the Jeeves platform.
575
+ * Comment markers delimiting Jeeves managed content blocks in SOUL.md and AGENTS.md.
792
576
  *
793
577
  * @remarks
794
- * These types support the platform's HEARTBEAT orchestration and
795
- * dependency graph resolution.
796
- */
797
- /** Component dependency declarations. */
798
- interface ComponentDependencies {
799
- /**
800
- * Hard dependencies — the component cannot function without these.
801
- * If a hard dep is not healthy, suppress all alerts for this component
802
- * except a "waiting for dependency" message. If a hard dep is declined,
803
- * auto-decline this component.
804
- */
805
- hard: string[];
806
- /**
807
- * Soft dependencies — the component works without these but with reduced
808
- * functionality. When the component is healthy and a soft dep is missing,
809
- * generate an informational alert. No alert when a soft dep is declined.
810
- */
811
- soft: string[];
812
- }
813
-
814
- /**
815
- * Comment markers for managed content blocks.
578
+ * Managed content is enclosed in HTML comment markers so that re-rendering by
579
+ * `jeeves install` can replace the Jeeves block in place while leaving user content
580
+ * outside the markers untouched. Marker text is unchanged from v0.x so that
581
+ * blocks written by earlier versions are recognised and replaced.
816
582
  *
817
- * @remarks
818
- * Managed content in TOOLS.md, SOUL.md, and AGENTS.md is enclosed
819
- * in HTML comment markers. Content between markers is refreshed
820
- * atomically on each writer cycle. User content outside the markers
821
- * is never touched.
583
+ * @module
822
584
  */
823
- /** Shape of managed content markers used by updateManagedSection and removeManagedSection. */
585
+ /** Shape of a managed content marker set. */
824
586
  interface ManagedMarkers {
825
587
  /** BEGIN comment marker text. */
826
588
  begin: string;
@@ -829,65 +591,61 @@ interface ManagedMarkers {
829
591
  /** Optional H1 title prepended inside the managed block. */
830
592
  title?: string;
831
593
  /**
832
- * Position of the managed block within the file.
833
- * - `'top'`: managed block first, user content below (current default).
594
+ * Position of a newly inserted managed block within the file.
595
+ * - `'top'`: managed block first, user content below.
834
596
  * - `'bottom'`: user content first, managed block at end.
835
597
  *
836
598
  * @defaultValue `'top'`
837
599
  */
838
600
  position?: 'top' | 'bottom';
839
601
  }
840
- /** Default markers for TOOLS.md managed block. */
841
- declare const TOOLS_MARKERS: ManagedMarkers;
842
- /** Default markers for SOUL.md managed block. */
602
+ /** Markers for the SOUL.md managed block. */
843
603
  declare const SOUL_MARKERS: ManagedMarkers;
844
- /** Default markers for AGENTS.md managed block. */
604
+ /** Markers for the AGENTS.md managed block. */
845
605
  declare const AGENTS_MARKERS: ManagedMarkers;
846
606
  /**
847
- * Regex pattern to extract version stamp from a BEGIN marker comment.
607
+ * Markers for the legacy (v0.x) TOOLS.md managed block.
608
+ *
609
+ * @remarks
610
+ * OpenClaw 2026.9.6 no longer loads TOOLS.md, and Jeeves no longer writes it.
611
+ * Retained only so that tooling can recognise and strip blocks written by
612
+ * earlier versions (e.g. `jeeves uninstall`).
613
+ */
614
+ declare const LEGACY_TOOLS_MARKERS: ManagedMarkers;
615
+ /**
616
+ * Regex pattern to extract the version stamp from a BEGIN marker comment.
848
617
  *
849
618
  * @remarks
850
619
  * Format: `\<!-- BEGIN MARKER | core:X.Y.Z | ISO-TIMESTAMP --\>`
851
620
  * Captures: [1] marker text, [2] version, [3] timestamp
852
621
  */
853
622
  declare const VERSION_STAMP_PATTERN: RegExp;
854
- /** Staleness threshold for version-stamp convergence in milliseconds. */
855
- declare const STALENESS_THRESHOLD_MS: number;
856
- /** Warning text injected inside managed block when cleanup is needed. */
857
- declare const CLEANUP_FLAG = "> \u26A0\uFE0F CLEANUP NEEDED: Orphaned Jeeves content detected outside this managed block. Review the file and remove any content outside the BEGIN/END markers that duplicates what appears inside them.";
858
623
 
859
624
  /**
860
625
  * Directory and file path conventions for the Jeeves platform.
626
+ *
627
+ * @module
861
628
  */
862
629
  /** Core config directory name within the config root. */
863
630
  declare const CORE_CONFIG_DIR = "jeeves-core";
864
631
  /** Prefix for component config directories: `jeeves-{name}`. */
865
632
  declare const COMPONENT_CONFIG_PREFIX = "jeeves-";
866
- /** Default workspace file names. */
633
+ /** Workspace file names that Jeeves renders into or reads. */
867
634
  declare const WORKSPACE_FILES: {
868
- /** TOOLS.md — live platform state and component sections. */
869
- readonly tools: "TOOLS.md";
870
635
  /** SOUL.md — professional discipline and behavioral foundations. */
871
636
  readonly soul: "SOUL.md";
872
- /** AGENTS.md — operational protocols and memory architecture. */
637
+ /** AGENTS.md — operational protocols. */
873
638
  readonly agents: "AGENTS.md";
874
- /** HEARTBEAT.md — platform status and health alerts. */
875
- readonly heartbeat: "HEARTBEAT.md";
876
639
  /** MEMORY.md — curated long-term memory. */
877
640
  readonly memory: "MEMORY.md";
641
+ /**
642
+ * TOOLS.md — legacy (v0.x) only. No longer loaded by OpenClaw and no longer
643
+ * written by Jeeves; retained so tooling can strip legacy managed blocks.
644
+ */
645
+ readonly legacyTools: "TOOLS.md";
878
646
  };
879
- /** Skill directory name within workspace. */
880
- declare const SKILLS_DIR = "skills";
881
- /** Jeeves skill directory name. */
882
- declare const JEEVES_SKILL_DIR = "jeeves";
883
- /** Templates directory name within core config. */
884
- declare const TEMPLATES_DIR = "templates";
885
- /** Registry cache file name. */
886
- declare const REGISTRY_CACHE_FILE = "registry-cache.json";
887
647
  /** Core config file name. */
888
648
  declare const CONFIG_FILE = "config.json";
889
- /** Component versions state file name. */
890
- declare const COMPONENT_VERSIONS_FILE = "component-versions.json";
891
649
 
892
650
  /**
893
651
  * Default port assignments for Jeeves platform services.
@@ -910,47 +668,6 @@ declare const META_PORT = 1938;
910
668
  /** Map of service names to their default ports. */
911
669
  declare const DEFAULT_PORTS: Record<string, number>;
912
670
 
913
- /**
914
- * Managed section IDs, stable ordering, and platform component registry.
915
- *
916
- * @remarks
917
- * Section ordering is fixed to prevent diff churn regardless of which
918
- * component writes last. Sections always appear in this order.
919
- */
920
- /** Known section IDs for TOOLS.md managed block. */
921
- declare const SECTION_IDS: {
922
- /** Platform health and guidance section. */
923
- readonly Platform: "Platform";
924
- /** Watcher index stats and search configuration. */
925
- readonly Watcher: "Watcher";
926
- /** Server export capabilities and connected services. */
927
- readonly Server: "Server";
928
- /** Runner job status and active scripts. */
929
- readonly Runner: "Runner";
930
- /** Meta synthesis entity summary and tools. */
931
- readonly Meta: "Meta";
932
- };
933
- /** Section ID type. */
934
- type SectionId = (typeof SECTION_IDS)[keyof typeof SECTION_IDS];
935
- /**
936
- * Stable ordering of sections within the managed TOOLS.md block.
937
- * Sections always appear in this order regardless of write order.
938
- */
939
- declare const SECTION_ORDER: readonly string[];
940
- /**
941
- * The four essential platform components.
942
- *
943
- * @remarks
944
- * These components constitute the Jeeves platform. `jeeves install` writes
945
- * initial HEARTBEAT "Not installed" alerts for all of them. The HEARTBEAT
946
- * writer generates "Not installed" alerts only for platform components not
947
- * in `component-versions.json`. Optional future components (not in this list)
948
- * appear in HEARTBEAT only after explicit install.
949
- */
950
- declare const PLATFORM_COMPONENTS: readonly ["runner", "watcher", "server", "meta"];
951
- /** A platform component name. */
952
- type PlatformComponent = (typeof PLATFORM_COMPONENTS)[number];
953
-
954
671
  /**
955
672
  * Core library version, inlined at build time.
956
673
  *
@@ -973,6 +690,11 @@ declare const CORE_VERSION: string;
973
690
  * 1. Component's own config file
974
691
  * 2. Core config file
975
692
  * 3. Hardcoded library defaults
693
+ *
694
+ * Unknown keys are stripped on parse, so files that still carry retired
695
+ * keys (e.g. v0.x `registryCache`) keep validating.
696
+ *
697
+ * @module
976
698
  */
977
699
 
978
700
  /** Default bind address for all Jeeves services. */
@@ -985,9 +707,6 @@ declare const coreConfigSchema: z.ZodObject<{
985
707
  services: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
986
708
  url: z.ZodURL;
987
709
  }, z.core.$strip>>>;
988
- registryCache: z.ZodPrefault<z.ZodObject<{
989
- ttlSeconds: z.ZodDefault<z.ZodNumber>;
990
- }, z.core.$strip>>;
991
710
  }, z.core.$strip>;
992
711
  /** Core config type derived from the Zod schema. */
993
712
  type CoreConfig = z.infer<typeof coreConfigSchema>;
@@ -1053,23 +772,6 @@ declare function getServiceState(serviceName: string): ServiceState;
1053
772
  */
1054
773
  declare function getServiceUrl(serviceName: string, consumerName?: string): string;
1055
774
 
1056
- /**
1057
- * Registry version cache for npm package update awareness.
1058
- *
1059
- * @remarks
1060
- * Caches the latest npm registry version in a local JSON file
1061
- * to avoid expensive `npm view` calls on every refresh cycle.
1062
- */
1063
- /**
1064
- * Check the npm registry for the latest version of a package.
1065
- *
1066
- * @param packageName - The npm package name (e.g., '\@karmaniverous/jeeves').
1067
- * @param cacheDir - Directory to store the cache file.
1068
- * @param ttlSeconds - Cache TTL in seconds (default 3600).
1069
- * @returns The latest version string, or undefined if the check fails.
1070
- */
1071
- declare function checkRegistryVersion(packageName: string, cacheDir: string, ttlSeconds?: number): string | undefined;
1072
-
1073
775
  /**
1074
776
  * Workspace and config root initialization.
1075
777
  *
@@ -1160,50 +862,53 @@ declare function getComponentConfigPath(componentName: string): string | undefin
1160
862
  declare function resetInit(): void;
1161
863
 
1162
864
  /**
1163
- * Similarity-based cleanup detection for orphaned managed content.
865
+ * Cross-process advisory file lock using an atomic `mkdir` of `{file}.lock`.
1164
866
  *
1165
867
  * @remarks
1166
- * Uses Jaccard similarity on 3-word shingles (Decision 22) to detect
1167
- * when orphaned managed content exists in the user content zone.
1168
- */
1169
- /**
1170
- * Generate a set of n-word shingles from text.
868
+ * Replaces `proper-lockfile`, whose `signal-exit` dependency registered
869
+ * process-level SIGINT/SIGTERM/... handlers at import time in every process
870
+ * that loaded this library (including the OpenClaw gateway and CLI, via the
871
+ * Jeeves plugins). This implementation registers no process handlers and
872
+ * starts no timers, so it cannot keep a process alive.
1171
873
  *
1172
- * @param text - Input text.
1173
- * @param n - Shingle size (default 3).
1174
- * @returns Set of n-word shingles.
1175
- */
1176
- declare function shingles(text: string, n?: number): Set<string>;
1177
- /**
1178
- * Compute Jaccard similarity between two sets.
874
+ * The lock directory name (`{file}.lock`) matches proper-lockfile's
875
+ * convention, so v0.x holders and this implementation exclude each other
876
+ * during a mixed-version rollout. A lock whose mtime is older than
877
+ * {@link STALE_LOCK_MS} is considered abandoned and is taken over; takeovers
878
+ * are serialised through a `{file}.lock.takeover` guard so a freshly
879
+ * re-taken lock is never deleted. The lock's mtime is not refreshed while it
880
+ * is held (that would need a timer), so callbacks must finish well within
881
+ * the stale threshold: they are meant to be a short read-modify-write.
1179
882
  *
1180
- * @param a - First set.
1181
- * @param b - Second set.
1182
- * @returns Jaccard similarity coefficient (0 to 1).
883
+ * @module
1183
884
  */
1184
- declare function jaccard(a: Set<string>, b: Set<string>): number;
885
+ /** Stale lock threshold in ms (2 minutes). */
886
+ declare const STALE_LOCK_MS = 120000;
1185
887
  /**
1186
- * Check whether user content contains orphaned managed content.
888
+ * Execute a callback while holding an exclusive lock on a file.
889
+ *
890
+ * @remarks
891
+ * Fails fast (no retries) with an `ELOCKED` error when the lock is held,
892
+ * matching the v0.x behaviour. The lock is always released in a `finally`
893
+ * block. The target file need not exist. `fn` must complete well within
894
+ * `staleMs`: the lock is not refreshed while held, so a longer callback can
895
+ * be taken over by another process.
1187
896
  *
1188
- * @param managedContent - The current managed block content.
1189
- * @param userContent - Content below the END marker.
1190
- * @param threshold - Jaccard threshold (default 0.15).
1191
- * @returns `true` if cleanup is needed.
897
+ * @param filePath - Absolute path to the file to lock.
898
+ * @param fn - Callback to execute while holding the lock.
899
+ * @param staleMs - Stale threshold in ms. Defaults to {@link STALE_LOCK_MS}.
1192
900
  */
1193
- declare function needsCleanup(managedContent: string, userContent: string, threshold?: number): boolean;
901
+ declare function withFileLock(filePath: string, fn: () => void | Promise<void>, staleMs?: number): Promise<void>;
1194
902
 
1195
903
  /**
1196
- * Shared file I/O helpers for managed section operations.
904
+ * Atomic file write (temp file + rename) with Windows EPERM retry.
1197
905
  *
1198
906
  * @remarks
1199
- * Extracts the atomic write pattern and file-level locking into
1200
- * reusable utilities, eliminating duplication between
1201
- * `updateManagedSection` and `removeManagedSection`.
907
+ * Synchronous; touches only the target directory. Used by service-side config
908
+ * persistence and by `jeeves install`.
909
+ *
910
+ * @module
1202
911
  */
1203
- /** Stale lock threshold in ms (2 minutes). */
1204
- declare const STALE_LOCK_MS = 120000;
1205
- /** Default core version when none provided. */
1206
- declare const DEFAULT_CORE_VERSION: string;
1207
912
  /**
1208
913
  * Write content to a file atomically via a temp file + rename.
1209
914
  *
@@ -1211,168 +916,127 @@ declare const DEFAULT_CORE_VERSION: string;
1211
916
  * Retries the rename up to three times on EPERM (Windows file-handle
1212
917
  * contention) with a 100 ms synchronous delay between attempts.
1213
918
  *
919
+ * When `options.mode` is given, the temp file gets exactly that mode before
920
+ * the rename (so a secret-bearing file is never visible with wider
921
+ * permissions); on Windows only the read-only bit is affected.
922
+ *
1214
923
  * @param filePath - Absolute path to the target file.
1215
924
  * @param content - Content to write.
925
+ * @param options - Optional file mode for the written file.
1216
926
  */
1217
- declare function atomicWrite(filePath: string, content: string): void;
927
+ declare function atomicWrite(filePath: string, content: string, options?: {
928
+ mode?: number;
929
+ }): void;
930
+
1218
931
  /**
1219
- * Execute a callback while holding a file lock.
932
+ * Pure string transforms that render, insert, replace, and remove a Jeeves
933
+ * managed block in workspace file content. No I/O.
1220
934
  *
1221
935
  * @remarks
1222
- * Acquires a lock on the file, executes the callback, and releases
1223
- * the lock in a finally block. The lock uses a 2-minute stale threshold
1224
- * and retries up to 5 times.
936
+ * Used by `jeeves install` / `jeeves uninstall`; exported for any tool that
937
+ * edits a managed block with its own marker set. An existing block is replaced in
938
+ * place; a new block is inserted at the marker set's configured position.
939
+ * User content outside the markers is preserved verbatim (trimmed).
1225
940
  *
1226
- * @param filePath - Absolute path to the file to lock.
1227
- * @param fn - Async callback to execute while holding the lock.
941
+ * @module
1228
942
  */
1229
- declare function withFileLock(filePath: string, fn: () => void | Promise<void>): Promise<void>;
1230
943
 
1231
- /**
1232
- * Parse managed block from file content.
1233
- *
1234
- * @remarks
1235
- * Extracts managed content delimited by comment markers, parses H2
1236
- * sections within the block, and returns the structured result plus
1237
- * user content outside the markers.
1238
- */
1239
- /** A parsed H2 section within the managed block. */
1240
- interface ManagedSection {
1241
- /** Section heading text (without the `## ` prefix). */
1242
- id: string;
1243
- /** Content below the heading (trimmed). */
1244
- content: string;
1245
- }
1246
- /** Version stamp extracted from the BEGIN marker. */
1247
- interface VersionStamp {
1248
- /** Core library version (semver). */
944
+ /** Options controlling the version stamp on a rendered BEGIN marker. */
945
+ interface ManagedBlockStampOptions {
946
+ /** Core library version written into the stamp. */
1249
947
  version: string;
1250
- /** ISO timestamp of last write. */
1251
- timestamp: string;
1252
- }
1253
- /** Result of parsing a managed block from file content. */
1254
- interface ParseManagedResult {
1255
- /** Whether valid markers were found. */
1256
- found: boolean;
1257
- /** Version stamp from the BEGIN marker, if present. */
1258
- versionStamp: VersionStamp | undefined;
1259
- /** Raw managed block content (between markers, excluding markers). */
1260
- managedContent: string;
1261
- /** Parsed H2 sections within the managed block. */
1262
- sections: ManagedSection[];
1263
- /** Content before the BEGIN marker. */
1264
- beforeContent: string;
1265
- /** Content after the END marker (user content). */
1266
- userContent: string;
948
+ /** Render time written into the stamp. Defaults to now. */
949
+ now?: Date;
1267
950
  }
1268
951
  /**
1269
- * Parse a managed block from file content.
952
+ * Format the BEGIN marker comment with a version stamp.
1270
953
  *
1271
- * @param fileContent - Full file content.
1272
- * @param markers - Optional custom markers (defaults to TOOLS markers).
1273
- * @returns Parsed result with sections, version stamp, and user content.
954
+ * @param markerText - The marker text.
955
+ * @param version - The core library version.
956
+ * @param now - Render time. Defaults to now.
957
+ * @returns Formatted comment line.
1274
958
  */
1275
- declare function parseManaged(fileContent: string, markers?: {
1276
- begin: string;
1277
- end: string;
1278
- }): ParseManagedResult;
1279
-
959
+ declare function formatBeginMarker(markerText: string, version: string, now?: Date): string;
1280
960
  /**
1281
- * Remove a managed section or entire managed block from a file.
1282
- *
1283
- * @remarks
1284
- * Supports two modes:
1285
- * - No `sectionId`: Remove the entire managed block (markers + content),
1286
- * leaving user content intact.
1287
- * - With `sectionId`: Remove a specific H2 section from within the
1288
- * managed block. If it was the last section, remove the entire block.
961
+ * Format the END marker comment.
1289
962
  *
1290
- * Provides file-level locking and atomic writes (temp file + rename).
1291
- * Missing markers or nonexistent sections are no-ops (no error thrown).
963
+ * @param markerText - The marker text.
964
+ * @returns Formatted comment line.
1292
965
  */
1293
-
1294
- /** Options for removeManagedSection. */
1295
- interface RemoveManagedSectionOptions {
1296
- /** Section ID to remove. If omitted, removes the entire managed block. */
1297
- sectionId?: string;
1298
- /** Custom markers. Defaults to TOOLS markers. */
1299
- markers?: ManagedMarkers;
1300
- }
966
+ declare function formatEndMarker(markerText: string): string;
1301
967
  /**
1302
- * Remove a managed section or entire managed block from a file.
968
+ * Render a complete managed block (BEGIN marker, optional H1 title, body,
969
+ * END marker).
1303
970
  *
1304
- * @param filePath - Absolute path to the target file.
1305
- * @param options - Optional section ID and custom markers.
971
+ * @param markers - Marker set.
972
+ * @param body - Managed body (Markdown).
973
+ * @param stamp - Version stamp options.
974
+ * @returns The managed block, without a trailing newline.
1306
975
  */
1307
- declare function removeManagedSection(filePath: string, options?: RemoveManagedSectionOptions): Promise<void>;
1308
-
976
+ declare function renderManagedBlock(markers: ManagedMarkers, body: string, stamp: ManagedBlockStampOptions): string;
1309
977
  /**
1310
- * Generic managed-section writer with block and section modes.
978
+ * Insert or replace the managed block in file content.
1311
979
  *
1312
980
  * @remarks
1313
- * Supports two modes:
1314
- * - `block`: Replaces the entire managed block (SOUL.md, AGENTS.md).
1315
- * - `section`: Upserts a named H2 section within the managed block (TOOLS.md).
981
+ * If a block with these markers exists, it is replaced in place. Otherwise
982
+ * the block is inserted at `markers.position` (default `'top'`), and any
983
+ * orphaned BEGIN marker of the same type is stripped from user content so it
984
+ * cannot pair with the new END marker later.
1316
985
  *
1317
- * Provides version-stamp convergence and atomic writes.
986
+ * @param fileContent - Existing file content (empty string for a new file).
987
+ * @param markers - Marker set.
988
+ * @param body - Managed body (Markdown).
989
+ * @param stamp - Version stamp options.
990
+ * @returns The new file content.
1318
991
  */
1319
-
1320
- /** Options for updateManagedSection. */
1321
- interface UpdateManagedSectionOptions {
1322
- /** Write mode. Default: 'block'. */
1323
- mode?: 'block' | 'section';
1324
- /** Section ID — required when mode is 'section'. */
1325
- sectionId?: string;
1326
- /** Custom markers. Defaults to TOOLS markers. */
1327
- markers?: ManagedMarkers;
1328
- /** Core library version for version-stamp convergence. */
1329
- coreVersion?: string;
1330
- /** Staleness threshold in ms for version-stamp convergence. */
1331
- stalenessThresholdMs?: number;
1332
- }
992
+ declare function upsertManagedBlock(fileContent: string, markers: ManagedMarkers, body: string, stamp: ManagedBlockStampOptions): string;
1333
993
  /**
1334
- * Update a managed section in a file.
994
+ * Remove the managed block from file content, keeping user content.
1335
995
  *
1336
- * @param filePath - Absolute path to the target file.
1337
- * @param content - New content to write.
1338
- * @param options - Write mode and optional configuration.
996
+ * @param fileContent - Existing file content.
997
+ * @param markers - Marker set.
998
+ * @returns The new file content (unchanged if no block is present).
1339
999
  */
1340
- declare function updateManagedSection(filePath: string, content: string, options?: UpdateManagedSectionOptions): Promise<void>;
1000
+ declare function removeManagedBlock(fileContent: string, markers: Pick<ManagedMarkers, 'begin' | 'end'>): string;
1341
1001
 
1342
1002
  /**
1343
- * Version-stamp parsing and convergence logic.
1003
+ * Parse a Jeeves managed block out of workspace file content (pure).
1344
1004
  *
1345
1005
  * @remarks
1346
- * When multiple component plugins bundle different core library versions,
1347
- * they independently maintain shared managed content. The version-stamp
1348
- * mechanism ensures convergence without coordination state.
1349
- */
1350
-
1351
- /**
1352
- * Format the BEGIN marker comment with a version stamp.
1006
+ * Locates the BEGIN/END comment markers, extracts the managed content and its
1007
+ * version stamp, and returns the user content before and after the block.
1353
1008
  *
1354
- * @param markerText - The marker text (e.g., 'BEGIN JEEVES PLATFORM TOOLS').
1355
- * @param version - The core library version.
1356
- * @returns Formatted comment line.
1357
- */
1358
- declare function formatBeginMarker(markerText: string, version: string): string;
1359
- /**
1360
- * Format the END marker comment.
1361
- *
1362
- * @param markerText - The marker text (e.g., 'END JEEVES PLATFORM TOOLS').
1363
- * @returns Formatted comment line.
1009
+ * @module
1364
1010
  */
1365
- declare function formatEndMarker(markerText: string): string;
1011
+
1012
+ /** Version stamp extracted from the BEGIN marker. */
1013
+ interface VersionStamp {
1014
+ /** Core library version (semver). */
1015
+ version: string;
1016
+ /** ISO timestamp of the render. */
1017
+ timestamp: string;
1018
+ }
1019
+ /** Result of parsing a managed block from file content. */
1020
+ interface ParseManagedResult {
1021
+ /** Whether a valid BEGIN/END marker pair was found. */
1022
+ found: boolean;
1023
+ /** Version stamp from the BEGIN marker, if present. */
1024
+ versionStamp: VersionStamp | undefined;
1025
+ /** Raw managed block content (between markers, excluding markers). */
1026
+ managedContent: string;
1027
+ /** Content before the BEGIN marker (trimmed). */
1028
+ beforeContent: string;
1029
+ /** Content after the END marker (trimmed), or the whole file if not found. */
1030
+ userContent: string;
1031
+ }
1366
1032
  /**
1367
- * Determine whether this writer should proceed based on version-stamp
1368
- * convergence rules.
1033
+ * Parse a managed block from file content.
1369
1034
  *
1370
- * @param myVersion - The current core library version.
1371
- * @param existing - The existing version stamp (if any).
1372
- * @param stalenessThresholdMs - Staleness threshold in ms (default: 5 min).
1373
- * @returns `true` if the writer should proceed with the write.
1035
+ * @param fileContent - Full file content.
1036
+ * @param markers - BEGIN/END marker pair to look for.
1037
+ * @returns Parsed result with version stamp and surrounding user content.
1374
1038
  */
1375
- declare function shouldWrite(myVersion: string, existing: VersionStamp | undefined, stalenessThresholdMs?: number): boolean;
1039
+ declare function parseManaged(fileContent: string, markers: Pick<ManagedMarkers, 'begin' | 'end'>): ParseManagedResult;
1376
1040
 
1377
1041
  /**
1378
1042
  * Memory budget accounting for MEMORY.md.
@@ -1415,123 +1079,58 @@ interface MemoryHygieneOptions {
1415
1079
  declare function analyzeMemory(options: MemoryHygieneOptions): MemoryHygieneResult;
1416
1080
 
1417
1081
  /**
1418
- * HEARTBEAT integration for memory hygiene.
1082
+ * Build/test-time check that a plugin's `package.json` declares the OpenClaw
1083
+ * conversation hooks it registers (e.g. via `registerPromptContext`), as
1084
+ * `"jeeves": { "conversationHooks": [...] }`. Pure apart from calling the
1085
+ * plugin's own `register` with a recording API.
1419
1086
  *
1420
1087
  * @remarks
1421
- * Calls `analyzeMemory()` and converts the result into a `HeartbeatEntry`
1422
- * suitable for inclusion in the HEARTBEAT.md platform status section.
1423
- * Returns `undefined` when MEMORY.md is healthy (no alert needed).
1424
- *
1425
- * Uses the `## MEMORY.md` heading (Decision 50) to distinguish memory
1426
- * alerts from component alerts (`## jeeves-{name}`).
1427
- */
1428
-
1429
- /** The HEARTBEAT heading name for memory alerts. */
1430
- declare const MEMORY_HEARTBEAT_NAME = "MEMORY.md";
1431
- /**
1432
- * Check memory health and return a HEARTBEAT entry if unhealthy.
1088
+ * OpenClaw blocks every conversation hook of a non-bundled plugin unless
1089
+ * `plugins.entries.<id>.hooks.allowConversationAccess` is `true`, and it has
1090
+ * no static record of the typed hooks a plugin registers. `jeeves install` /
1091
+ * `jeeves update` therefore grant access only to plugins whose `package.json`
1092
+ * declares such hooks. A plugin that registers one without declaring it
1093
+ * installs cleanly and then silently never runs the hook, so plugins should
1094
+ * run {@link validateConversationHooks} in a test or build step:
1433
1095
  *
1434
- * @param options - Memory hygiene options (workspacePath, budget, etc.).
1435
- * @returns A `HeartbeatEntry` when memory needs attention, `undefined` when healthy.
1436
- */
1437
- declare function checkMemoryHealth(options: MemoryHygieneOptions): HeartbeatEntry | undefined;
1438
-
1439
- /**
1440
- * Internal function to maintain SOUL.md, AGENTS.md, and TOOLS.md Platform section.
1441
- *
1442
- * @remarks
1443
- * Called by `ComponentWriter` on each cycle. Not directly exposed to components.
1444
- * Reads content files from the package's `content/` directory, renders the
1445
- * Platform template with live data, and writes managed sections using
1446
- * `updateManagedSection`.
1447
- */
1448
-
1449
- /** Options for refreshPlatformContent. */
1450
- interface RefreshPlatformContentOptions {
1451
- /** Core library version for version-stamp convergence. */
1452
- coreVersion: string;
1453
- /** Component name (for registry cache directory). */
1454
- componentName?: string;
1455
- /** Component plugin version (e.g., '0.2.0'). */
1456
- componentVersion?: string;
1457
- /** npm package name for the service (for registry update check). */
1458
- servicePackage?: string;
1459
- /** npm package name for the plugin (for registry update check). */
1460
- pluginPackage?: string;
1461
- /** Staleness threshold override in ms. */
1462
- stalenessThresholdMs?: number;
1463
- /** Pre-loaded workspace config (avoids redundant reads when caller already loaded it). */
1464
- workspaceConfig?: WorkspaceConfig;
1465
- }
1466
- /**
1467
- * Refresh platform content: SOUL.md, AGENTS.md, and TOOLS.md Platform section.
1468
- *
1469
- * @param options - Configuration for the refresh cycle.
1470
- */
1471
- declare function refreshPlatformContent(options: RefreshPlatformContentOptions): Promise<void>;
1472
-
1473
- /**
1474
- * One-shot content seeding used by the CLI install command.
1475
- *
1476
- * @remarks
1477
- * Seeds SOUL.md, AGENTS.md, and TOOLS.md Platform section using the same
1478
- * `updateManagedSection()` code path as writer cycles. Also copies templates
1479
- * and creates core config with defaults if missing.
1480
- */
1481
- /** Options for seeding content. */
1482
- interface SeedContentOptions {
1483
- /** Core library version for version-stamp convergence. */
1484
- coreVersion: string;
1485
- }
1486
- /**
1487
- * Seed all platform content into the workspace.
1488
- *
1489
- * @remarks
1490
- * Uses the same `updateManagedSection()` code path as writer cycles.
1491
- * Creates core config with defaults if missing. Copies templates.
1492
- * Writes initial HEARTBEAT with "Not installed" alerts for all platform components.
1493
- * Jaccard cleanup detection runs automatically via `updateManagedSection`.
1494
- *
1495
- * @param options - Seeding configuration.
1496
- */
1497
- declare function seedContent(options: SeedContentOptions): Promise<void>;
1498
-
1499
- /**
1500
- * Backward-compatible re-export of `seedSkills`.
1501
- *
1502
- * @remarks
1503
- * Delegates to `seedSkills` which seeds all bundled platform skills.
1504
- * Retained for API compatibility with existing component plugins.
1096
+ * ```typescript
1097
+ * const hooks = await recordRegisteredHooks(register);
1098
+ * validateConversationHooks(JSON.parse(readFileSync('package.json', 'utf-8')), hooks);
1099
+ * ```
1505
1100
  *
1506
1101
  * @module
1507
1102
  */
1103
+
1508
1104
  /**
1509
- * Seed all bundled platform skills into the workspace.
1510
- *
1511
- * @param workspacePath - Workspace root directory.
1105
+ * OpenClaw's conversation hooks: the typed hooks gated by
1106
+ * `allowConversationAccess` (v2026.9.6 `src/plugins/hook-types.ts`
1107
+ * `CONVERSATION_HOOK_NAMES`).
1512
1108
  */
1513
- declare function seedSkill(workspacePath: string): void;
1514
-
1109
+ declare const CONVERSATION_HOOK_NAMES: readonly string[];
1515
1110
  /**
1516
- * Skill seeding: write all bundled platform skills to the workspace.
1517
- *
1518
- * @remarks
1519
- * Skill files are entirely generated — no user-authored content (Decision 48).
1520
- * Every installer (core CLI and component plugins) writes them unconditionally.
1521
- * Content is inlined at build time via `rollup-plugin-md.ts`.
1111
+ * Run a plugin's `register(api)` against a recording API and return the
1112
+ * typed hook names it registers with `api.on` (e.g. `before_prompt_build`
1113
+ * from `registerPromptContext`).
1522
1114
  *
1523
- * @module
1115
+ * @param register - The plugin's register function.
1116
+ * @param api - Extra API members the plugin needs at registration (config,
1117
+ * logger, ...). `on` is always the recorder; `registerTool` defaults to a
1118
+ * no-op.
1119
+ * @returns Registered hook names, in registration order.
1524
1120
  */
1121
+ declare function recordRegisteredHooks(register: (api: PluginApi) => unknown, api?: Partial<PluginApi>): Promise<string[]>;
1525
1122
  /**
1526
- * Seed all bundled platform skills into the workspace.
1527
- *
1528
- * @remarks
1529
- * Writes each skill to `{workspace}/skills/{name}/SKILL.md`, creating
1530
- * directories as needed. Overwrites existing content unconditionally.
1123
+ * Check that `package.json` declares exactly the conversation hooks a plugin
1124
+ * registers.
1531
1125
  *
1532
- * @param workspacePath - Workspace root directory.
1126
+ * @param packageJson - Parsed `package.json` of the plugin package.
1127
+ * @param registeredHooks - Hook names the plugin registers (see
1128
+ * {@link recordRegisteredHooks}); non-conversation hooks are ignored.
1129
+ * @returns The declared conversation hooks.
1130
+ * @throws Error when the field is malformed, a registered conversation hook
1131
+ * is not declared, or a declared hook is not a registered conversation hook.
1533
1132
  */
1534
- declare function seedSkills(workspacePath: string): void;
1133
+ declare function validateConversationHooks(packageJson: unknown, registeredHooks: readonly string[]): string[];
1535
1134
 
1536
1135
  /**
1537
1136
  * Factory for the standard plugin tool set.
@@ -1616,63 +1215,84 @@ declare function fetchJson(url: string, init?: RequestInit): Promise<unknown>;
1616
1215
  declare function postJson(url: string, body: unknown): Promise<unknown>;
1617
1216
 
1618
1217
  /**
1619
- * OpenClaw configuration helpers for plugin CLI installers.
1218
+ * Tie plugin-owned resources (timers, sockets, clients) to the OpenClaw
1219
+ * plugin lifecycle so a process that loads the plugin can exit.
1620
1220
  *
1621
1221
  * @remarks
1622
- * Provides resolution of OpenClaw home directory and config file path,
1623
- * plus idempotent config patching for plugin install/uninstall.
1222
+ * Plugins must not install process-level signal handlers or leave live
1223
+ * timers/handles behind: `openclaw plugins inspect` and other CLI commands
1224
+ * load plugin code and must exit on their own, and the gateway force-retires
1225
+ * plugins that do not release work on shutdown (runbook S1).
1226
+ *
1227
+ * @module
1624
1228
  */
1229
+
1625
1230
  /**
1626
- * Resolve the OpenClaw home directory.
1231
+ * Register a disposer with the host plugin lifecycle.
1627
1232
  *
1628
1233
  * @remarks
1629
- * Resolution order:
1630
- * 1. `OPENCLAW_CONFIG` env var → dirname of the config file path
1631
- * 2. `OPENCLAW_HOME` env var → resolved path
1632
- * 3. Default: `~/.openclaw`
1234
+ * Prefers `api.lifecycle.onDispose` (instance retirement); falls back to
1235
+ * `api.lifecycle.registerRuntimeLifecycle({ id, dispose })`.
1633
1236
  *
1634
- * @returns Absolute path to the OpenClaw home directory.
1237
+ * @param api - The OpenClaw plugin API passed to `register(api)`.
1238
+ * @param id - Stable id for the resource (used by the fallback path).
1239
+ * @param dispose - Releases the resource. Must be idempotent.
1240
+ * @returns `true` if registered; `false` if the host exposes no lifecycle API
1241
+ * (the caller should then avoid starting long-lived work).
1635
1242
  */
1636
- declare function resolveOpenClawHome(): string;
1243
+ declare function onPluginDispose(api: PluginApi, id: string, dispose: () => void | Promise<void>): boolean;
1244
+
1637
1245
  /**
1638
- * Resolve the OpenClaw config file path.
1246
+ * Register always-in-context plugin rules via OpenClaw's `before_prompt_build`
1247
+ * hook, returning `{ appendSystemContext }` (never `systemPrompt`).
1639
1248
  *
1640
1249
  * @remarks
1641
- * If `OPENCLAW_CONFIG` is set, uses that directly.
1642
- * Otherwise defaults to `{home}/openclaw.json`.
1643
- *
1644
- * @param home - The OpenClaw home directory.
1645
- * @returns Absolute path to the config file.
1646
- */
1647
- declare function resolveConfigPath(home: string): string;
1648
- /** Options for writing a plugin install provenance record. */
1649
- interface PluginInstallRecord {
1650
- /** Absolute path to the extensions directory where the plugin was installed. */
1651
- installPath: string;
1652
- /** Plugin version string from package.json, if known. */
1653
- version?: string;
1654
- /** ISO timestamp of installation. Defaults to `new Date().toISOString()`. */
1655
- installedAt?: string;
1656
- }
1657
- /**
1658
- * Patch an OpenClaw config for plugin install.
1250
+ * Runbook D5 / spike S2: `appendSystemContext` is appended after the prompt
1251
+ * cache boundary, concatenated across plugins in priority order, and does not
1252
+ * count toward `bootstrapMaxChars`. `systemPrompt` would replace the whole
1253
+ * prompt, so the result type here cannot express it.
1254
+ *
1255
+ * **Host config gate:** OpenClaw only runs this hook for non-bundled plugins
1256
+ * when `plugins.entries.<id>.hooks.allowConversationAccess` is `true`.
1257
+ * `openclaw plugins install --accept-capabilities` does NOT set it;
1258
+ * `jeeves install` / `jeeves update` grant it to plugins that declare the
1259
+ * hook in `package.json` `jeeves.conversationHooks`.
1659
1260
  *
1660
- * @param config - The parsed OpenClaw config object (mutated in place).
1661
- * @param pluginId - The plugin identifier.
1662
- * @param mode - Install mode.
1663
- * @param installRecord - Install provenance record.
1664
- * @returns Array of log messages describing changes made.
1261
+ * @module
1665
1262
  */
1666
- declare function patchConfig(config: Record<string, unknown>, pluginId: string, mode: 'add', installRecord: PluginInstallRecord): string[];
1263
+
1264
+ /** Produces prompt context text; empty/undefined means "inject nothing". */
1265
+ type PromptContextProvider = (ctx: PromptBuildContext) => string | undefined | Promise<string | undefined>;
1266
+ /** Zod schema for {@link registerPromptContext} options. */
1267
+ declare const promptContextOptionsSchema: z.ZodObject<{
1268
+ content: z.ZodUnion<readonly [z.ZodString, z.ZodCustom<PromptContextProvider, PromptContextProvider>]>;
1269
+ priority: z.ZodOptional<z.ZodNumber>;
1270
+ registrationId: z.ZodOptional<z.ZodString>;
1271
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
1272
+ }, z.core.$strip>;
1273
+ /** Options for {@link registerPromptContext}. */
1274
+ type PromptContextOptions = z.infer<typeof promptContextOptionsSchema>;
1667
1275
  /**
1668
- * Patch an OpenClaw config for plugin uninstall.
1276
+ * Register plugin rules that must always be in the agent's context.
1669
1277
  *
1670
- * @param config - The parsed OpenClaw config object (mutated in place).
1671
- * @param pluginId - The plugin identifier.
1672
- * @param mode - Uninstall mode.
1673
- * @returns Array of log messages describing changes made.
1278
+ * @remarks
1279
+ * Provider errors are logged (via `api.logger` when present) and yield no
1280
+ * injection for that turn; they never fail the prompt build. Registers no
1281
+ * timers or process handlers.
1282
+ *
1283
+ * @example
1284
+ * ```typescript
1285
+ * export default function register(api: PluginApi): void {
1286
+ * registerPromptContext(api, { content: WATCHER_RULES, priority: 10 });
1287
+ * }
1288
+ * ```
1289
+ *
1290
+ * @param api - The OpenClaw plugin API passed to `register(api)`.
1291
+ * @param options - Content and registration options.
1292
+ * @returns `true` if registered; `false` if the host has no `api.on`.
1293
+ * @throws ZodError if options are invalid.
1674
1294
  */
1675
- declare function patchConfig(config: Record<string, unknown>, pluginId: string, mode: 'remove'): string[];
1295
+ declare function registerPromptContext(api: PluginApi, options: PromptContextOptions): boolean;
1676
1296
 
1677
1297
  /**
1678
1298
  * Plugin resolution helpers for the OpenClaw plugin SDK.
@@ -1759,6 +1379,32 @@ declare function fail(error: unknown): ToolResult;
1759
1379
  */
1760
1380
  declare function connectionFail(error: unknown, baseUrl: string, pluginId: string): ToolResult;
1761
1381
 
1382
+ /**
1383
+ * Minimal validation of SKILL.md frontmatter (`name` and `description`).
1384
+ *
1385
+ * @remarks
1386
+ * OpenClaw skips skills without `name`/`description` frontmatter. Plugins
1387
+ * can call this from a build or test step to enforce it (runbook D4). Pure.
1388
+ *
1389
+ * @module
1390
+ */
1391
+ /** Parsed required frontmatter fields. */
1392
+ interface SkillFrontmatter {
1393
+ /** Skill name. */
1394
+ name: string;
1395
+ /** Skill description (block scalars are folded to one line). */
1396
+ description: string;
1397
+ }
1398
+ /**
1399
+ * Validate that SKILL.md content carries non-empty `name` and `description`
1400
+ * frontmatter.
1401
+ *
1402
+ * @param content - Full SKILL.md content.
1403
+ * @returns The parsed fields.
1404
+ * @throws Error describing the first missing requirement.
1405
+ */
1406
+ declare function validateSkillFrontmatter(content: string): SkillFrontmatter;
1407
+
1762
1408
  /**
1763
1409
  * Shared filesystem utilities for runner job scripts.
1764
1410
  *
@@ -1970,5 +1616,5 @@ declare function getErrorMessage(err: unknown): string;
1970
1616
  */
1971
1617
  declare function isTransientError(err: unknown): boolean;
1972
1618
 
1973
- export { AGENTS_MARKERS, CLEANUP_FLAG, COMPONENT_CONFIG_PREFIX, COMPONENT_VERSIONS_FILE, CONFIG_FILE, CORE_CONFIG_DIR, CORE_VERSION, ComponentWriter, DEFAULT_BIND_ADDRESS, DEFAULT_CORE_VERSION, DEFAULT_PORTS, HEARTBEAT_HEADING, JEEVES_SKILL_DIR, MEMORY_HEARTBEAT_NAME, META_PORT, PLATFORM_COMPONENTS, REGISTRY_CACHE_FILE, RUNNER_PORT, SECTION_IDS, SECTION_ORDER, SERVER_PORT, SKILLS_DIR, SOUL_MARKERS, STALENESS_THRESHOLD_MS, STALE_LOCK_MS, TEMPLATES_DIR, TOOLS_MARKERS, VERSION_STAMP_PATTERN, WATCHER_PORT, WORKSPACE_CONFIG_DEFAULTS, WORKSPACE_CONFIG_FILE, WORKSPACE_FILES, analyzeMemory, appendJsonl, atomicWrite, buildEffectiveConfig, buildHeartbeatSection, checkMemoryHealth, checkNodeVersion, checkRegistryVersion, connectionFail, coreConfigSchema, createAsyncContentCache, createComponentWriter, createConfigApplyHandler, createConfigQueryHandler, createGoogleAuth, createPluginCli, createPluginToolset, createServiceCli, createServiceManager, createStatusHandler, ensureDir, fail, fetchJson, fetchWithTimeout, formatBeginMarker, formatEndMarker, generateJsonSchema, generateWorkspaceJsonSchema, getArg, getBindAddress, getChannelWorkspace, getComponentConfigDir, getComponentConfigPath, getConfigRoot, getCoreConfigDir, getCoreConfigFile, getEffectiveServiceName, getErrorMessage, getPackageRoot, getPackageVersion, getServiceState, getServiceUrl, getWorkspacePath, init, isPrime, isTransientError, jaccard, jeevesComponentDescriptorSchema, loadEnvFile, loadWorkspaceConfig, needsCleanup, nowIso, ok, orchestrateHeartbeat, parseArgs, parseHeartbeat, parseManaged, patchConfig, postJson, readComponentVersions, readJson, readJsonl, refreshPlatformContent, registerComponentConfigPath, rejectWindowsDrivePath, removeComponentVersion, removeManagedSection, resetInit, resolveConfigPath, resolveConfigValue, resolveOpenClawHome, resolveOptionalPluginSetting, resolvePluginSetting, resolveWorkspacePath, run, runScript, runWithRetry, saveCache, seedContent, seedSkill, seedSkills, shingles, shouldWrite, sleepAsync, sleepMs, substituteEnvVars, updateManagedSection, uuid, withFileLock, workspaceConfigSchema, writeComponentVersion, writeHeartbeatSection, writeJsonAtomic, writeJsonl };
1974
- export type { AccountConfig, AsyncContentCacheOptions, ComponentDependencies, ComponentState, ComponentVersionEntry, ComponentVersionsState, ComponentWriterOptions, ConfigApplyHandler, ConfigApplyRequest, ConfigApplyResult, ConfigProvenance, ConfigQueryHandler, ConfigQueryResponse, CoreConfig, CreatePluginCliOptions, CreateStatusHandlerOptions, GoogleAuthOptions, HeartbeatEntry, InitOptions, JeevesComponentDescriptor, ManagedMarkers, ManagedSection, MemoryHygieneOptions, MemoryHygieneResult, OrchestrateHeartbeatOptions, ParseManagedResult, ParsedHeartbeat, PlatformComponent, PluginApi, PluginInstallRecord, RefreshPlatformContentOptions, RemoveManagedSectionOptions, ResolvedCliConfig, ResolvedValue, RetryOptions, RunOptions, SectionId, SeedContentOptions, ServiceAccountFileConfig, ServiceManager, ServiceManagerOptions, ServiceState, SlackWorkspaceOptions, StatusHandler, StatusHandlerResult, StatusResponse, ToolDescriptor, ToolRegistrationOptions, ToolResult, UpdateManagedSectionOptions, VersionStamp, WorkspaceConfig, WorkspaceOptions, WriteComponentVersionOptions };
1619
+ export { AGENTS_MARKERS, COMPONENT_CONFIG_PREFIX, CONFIG_FILE, CONVERSATION_HOOK_NAMES, CORE_CONFIG_DIR, CORE_VERSION, DEFAULT_BIND_ADDRESS, DEFAULT_PORTS, LEGACY_TOOLS_MARKERS, META_PORT, PLATFORM_COMPONENTS, RUNNER_PORT, SERVER_PORT, SOUL_MARKERS, STALE_LOCK_MS, VERSION_STAMP_PATTERN, WATCHER_PORT, WORKSPACE_CONFIG_DEFAULTS, WORKSPACE_CONFIG_FILE, WORKSPACE_FILES, analyzeMemory, appendJsonl, atomicWrite, buildEffectiveConfig, checkNodeVersion, connectionFail, coreConfigSchema, createConfigApplyHandler, createConfigQueryHandler, createGoogleAuth, createPluginToolset, createServiceCli, createServiceManager, createStatusHandler, ensureDir, fail, fetchJson, fetchWithTimeout, formatBeginMarker, formatEndMarker, generateJsonSchema, generateWorkspaceJsonSchema, getArg, getBindAddress, getChannelWorkspace, getComponentConfigDir, getComponentConfigPath, getConfigRoot, getCoreConfigDir, getCoreConfigFile, getEffectiveServiceName, getErrorMessage, getPackageRoot, getPackageVersion, getServiceState, getServiceUrl, getWorkspacePath, init, isTransientError, jeevesComponentDescriptorSchema, loadEnvFile, loadWorkspaceConfig, nowIso, ok, onPluginDispose, parseArgs, parseManaged, postJson, promptContextOptionsSchema, readJson, readJsonl, recordRegisteredHooks, registerComponentConfigPath, registerPromptContext, rejectWindowsDrivePath, removeManagedBlock, renderManagedBlock, resetInit, resolveConfigValue, resolveOptionalPluginSetting, resolvePluginSetting, resolveWorkspacePath, run, runScript, runWithRetry, saveCache, sleepAsync, sleepMs, substituteEnvVars, upsertManagedBlock, uuid, validateConversationHooks, validateSkillFrontmatter, withFileLock, workspaceConfigSchema, writeJsonAtomic, writeJsonl };
1620
+ export type { AccountConfig, ConfigApplyHandler, ConfigApplyRequest, ConfigApplyResult, ConfigProvenance, ConfigQueryHandler, ConfigQueryResponse, CoreConfig, CreateStatusHandlerOptions, GoogleAuthOptions, HookRegistrationOptions, InitOptions, JeevesComponentDescriptor, ManagedBlockStampOptions, ManagedMarkers, MemoryHygieneOptions, MemoryHygieneResult, ParseManagedResult, PlatformComponent, PluginApi, PluginLifecycleApi, PromptBuildContext, PromptBuildEvent, PromptBuildHandler, PromptBuildResult, PromptContextOptions, PromptContextProvider, ResolvedCliConfig, ResolvedValue, RetryOptions, RunOptions, ServiceAccountFileConfig, ServiceManager, ServiceManagerOptions, ServiceState, SkillFrontmatter, SlackWorkspaceOptions, StatusHandler, StatusHandlerResult, StatusResponse, ToolDescriptor, ToolRegistrationOptions, ToolResult, VersionStamp, WorkspaceConfig, WorkspaceOptions };