@lincoln504/pi-research 0.1.13 → 1.0.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 (248) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +55 -138
  3. package/dist/cli.mjs +23375 -0
  4. package/dist/prompts/research-knowledge-relevance-triage.md +35 -0
  5. package/dist/prompts/research-knowledge-search-extractor.md +41 -0
  6. package/dist/prompts/research-tool-usage.md +92 -0
  7. package/dist/prompts/researcher.md +89 -0
  8. package/dist/prompts/system-coordinator.md +75 -0
  9. package/dist/prompts/system-lead-evaluator.md +118 -0
  10. package/dist/thread-worker.mjs +2611 -0
  11. package/dist/webgpu-probe.mjs +80 -0
  12. package/docs/AGENT-SKILL.md +130 -0
  13. package/docs/ARCHITECTURE.md +306 -80
  14. package/docs/CONFIGURATION.md +249 -0
  15. package/docs/KNOWLEDGE-STORE.md +211 -0
  16. package/docs/PI-EXTENSION.md +91 -0
  17. package/docs/SDK.md +122 -0
  18. package/docs/THIRD-PARTY-NOTICES.md +66 -0
  19. package/package.json +102 -36
  20. package/scripts/build.cjs +140 -0
  21. package/scripts/cleanup.cjs +149 -0
  22. package/scripts/prepare.cjs +28 -0
  23. package/scripts/setup.cjs +134 -0
  24. package/skills/pi-research/README.md +90 -0
  25. package/skills/pi-research/SKILL.md +102 -0
  26. package/skills/pi-research/references/configuration.md +77 -0
  27. package/skills/pi-research/scripts/run.mjs +237 -0
  28. package/src/cleanup/research-cleanup.ts +140 -0
  29. package/src/cli.ts +1195 -0
  30. package/src/config.ts +1032 -155
  31. package/src/constants.ts +115 -84
  32. package/src/core/health-check-service.ts +265 -0
  33. package/src/core/interfaces/health-check-interfaces.ts +50 -0
  34. package/src/core/interfaces/knowledge-interfaces.ts +190 -0
  35. package/src/core/interfaces/observer-interfaces.ts +67 -0
  36. package/src/core/interfaces/orchestration-interfaces.ts +86 -0
  37. package/src/core/interfaces/planning-interfaces.ts +100 -0
  38. package/src/core/interfaces/process-interfaces.ts +37 -0
  39. package/src/core/interfaces/research-plan-types.ts +52 -0
  40. package/src/core/interfaces/scheduler-interfaces.ts +91 -0
  41. package/src/core/interfaces/service-names.ts +39 -0
  42. package/src/core/interfaces/state-manager-interfaces.ts +29 -0
  43. package/src/core/interfaces/steering-interfaces.ts +31 -0
  44. package/src/core/llm/agentic-repair.ts +169 -0
  45. package/src/core/llm/inject-date.ts +52 -0
  46. package/src/core/llm/llm-timeout.ts +64 -0
  47. package/src/core/llm/llm-utils.ts +86 -0
  48. package/src/core/llm/model-registry-factory.ts +287 -0
  49. package/src/core/llm/pi-ai-completion.ts +29 -0
  50. package/src/core/llm/prompts.ts +50 -0
  51. package/src/core/llm/research-model-resolver.ts +91 -0
  52. package/src/core/planning-constants.ts +13 -0
  53. package/src/core/planning-service.ts +649 -0
  54. package/src/core/planning-utils.ts +299 -0
  55. package/src/core/scheduler-factory.ts +48 -0
  56. package/src/core/scheduler-service.ts +123 -0
  57. package/src/core/service-initialization.ts +194 -0
  58. package/src/core/service-interfaces.ts +48 -0
  59. package/src/core/service-registry.ts +659 -0
  60. package/src/healthcheck/index.ts +271 -265
  61. package/src/healthcheck/registry.ts +130 -0
  62. package/src/index.ts +639 -50
  63. package/src/infrastructure/browser/browser-cleanup.ts +309 -0
  64. package/src/infrastructure/browser/browser-client.ts +199 -0
  65. package/src/infrastructure/browser/browser-error-utils.ts +160 -0
  66. package/src/infrastructure/browser/browser-lifecycle.ts +120 -0
  67. package/src/infrastructure/browser/browser-server.ts +174 -0
  68. package/src/infrastructure/browser/browser-task-scheduler.ts +461 -0
  69. package/src/infrastructure/browser/cleanup-utils.ts +155 -0
  70. package/src/infrastructure/browser/client-agent.ts +31 -0
  71. package/src/infrastructure/browser/config.ts +288 -0
  72. package/src/infrastructure/browser/ensure-browser.ts +205 -0
  73. package/src/infrastructure/browser/index.ts +37 -0
  74. package/src/infrastructure/browser/priority-task-queue.ts +226 -0
  75. package/src/infrastructure/browser/scheduler-factory.ts +354 -0
  76. package/src/infrastructure/browser/task-execution-service.ts +209 -0
  77. package/src/infrastructure/browser/thread-worker-browser.ts +282 -0
  78. package/src/infrastructure/browser/thread-worker-lifecycle.ts +323 -0
  79. package/src/infrastructure/browser/thread-worker-messaging.ts +662 -0
  80. package/src/infrastructure/browser/thread-worker-types.ts +25 -0
  81. package/src/infrastructure/browser/thread-worker.mjs +2611 -0
  82. package/src/infrastructure/browser/thread-worker.ts +168 -0
  83. package/src/infrastructure/browser/worker-pool-manager.ts +449 -0
  84. package/src/infrastructure/embedding/embedding-client.ts +205 -0
  85. package/src/infrastructure/embedding/embedding-factory.ts +324 -0
  86. package/src/infrastructure/embedding/embedding-server.ts +535 -0
  87. package/src/infrastructure/file-lock-service.ts +592 -0
  88. package/src/infrastructure/gpu-resource-service.ts +191 -0
  89. package/src/infrastructure/knowledge-store-service.ts +475 -0
  90. package/src/infrastructure/metrics-service.ts +129 -0
  91. package/src/infrastructure/process-lifecycle-service.ts +253 -0
  92. package/src/infrastructure/scheduler-factory-service.ts +58 -0
  93. package/src/infrastructure/service-initialization.ts +292 -0
  94. package/src/infrastructure/state/state-backup-manager.ts +290 -0
  95. package/src/infrastructure/state/state-browser-api.ts +62 -0
  96. package/src/infrastructure/state/state-browser-manager.ts +70 -0
  97. package/src/infrastructure/state/state-manager-service.ts +264 -0
  98. package/src/infrastructure/state/state-manager.ts +547 -0
  99. package/src/infrastructure/state/state-metrics.ts +92 -0
  100. package/src/infrastructure/state/state-migration.ts +103 -0
  101. package/src/infrastructure/state/state-path-configuration.ts +119 -0
  102. package/src/infrastructure/state/state-session-api.ts +94 -0
  103. package/src/infrastructure/state/state-session-manager.ts +127 -0
  104. package/src/infrastructure/state/state-validator.ts +93 -0
  105. package/src/infrastructure/types/state-types.ts +85 -0
  106. package/src/knowledge/chunker.ts +157 -0
  107. package/src/knowledge/embedder-init.ts +413 -0
  108. package/src/knowledge/embedder-utils.ts +296 -0
  109. package/src/knowledge/embedder.ts +592 -0
  110. package/src/knowledge/index.ts +126 -0
  111. package/src/knowledge/lancedb-loader.ts +35 -0
  112. package/src/knowledge/migration.ts +17 -0
  113. package/src/knowledge/model-config.ts +132 -0
  114. package/src/knowledge/onnx-env.ts +48 -0
  115. package/src/knowledge/store-operations.ts +291 -0
  116. package/src/knowledge/store-schema.ts +79 -0
  117. package/src/knowledge/store.ts +1251 -0
  118. package/src/knowledge/transformers-loader.ts +31 -0
  119. package/src/knowledge/webgpu-probe.mjs +80 -0
  120. package/src/knowledge/webgpu-viability.ts +255 -0
  121. package/src/knowledge/writer-queue.ts +252 -0
  122. package/src/logger.ts +316 -122
  123. package/src/observers/research-observer-impl.ts +459 -0
  124. package/src/orchestration/deep-research-orchestrator.ts +524 -773
  125. package/src/orchestration/deep-research-types.ts +47 -35
  126. package/src/orchestration/headless-observer.ts +114 -0
  127. package/src/orchestration/orchestration-types.ts +33 -0
  128. package/src/orchestration/quick-research-orchestrator.ts +463 -0
  129. package/src/orchestration/research-orchestration-service.ts +549 -0
  130. package/src/orchestration/research-session-service.ts +178 -0
  131. package/src/orchestration/research-synthesis-service.ts +348 -0
  132. package/src/orchestration/researcher-executor.ts +394 -0
  133. package/src/orchestration/researcher.ts +115 -42
  134. package/src/orchestration/service-initialization.ts +109 -0
  135. package/src/orchestration/session-context.ts +7 -3
  136. package/src/orchestration/session-state.ts +672 -0
  137. package/src/prompts/research-knowledge-relevance-triage.md +35 -0
  138. package/src/prompts/research-knowledge-search-extractor.md +41 -0
  139. package/src/prompts/research-tool-usage.md +63 -16
  140. package/src/prompts/researcher.md +59 -136
  141. package/src/prompts/system-coordinator.md +64 -13
  142. package/src/prompts/system-lead-evaluator.md +82 -189
  143. package/src/research-config.ts +872 -0
  144. package/src/sdk.ts +847 -0
  145. package/src/security/cisa-kev.ts +72 -9
  146. package/src/security/cvss.ts +92 -0
  147. package/src/security/ecosystem.ts +45 -0
  148. package/src/security/github-advisories.ts +168 -428
  149. package/src/security/github-advisory-types.ts +282 -0
  150. package/src/security/index.ts +63 -177
  151. package/src/security/nvd-client.ts +550 -0
  152. package/src/security/nvd-types.ts +179 -0
  153. package/src/security/osv-client.ts +246 -0
  154. package/src/security/osv-types.ts +285 -0
  155. package/src/security/types.ts +67 -53
  156. package/src/skill-install/skill-installer.ts +519 -0
  157. package/src/stackexchange/index.ts +81 -27
  158. package/src/stackexchange/output/compact.ts +7 -6
  159. package/src/stackexchange/output/table.ts +11 -7
  160. package/src/stackexchange/queries.ts +0 -10
  161. package/src/stackexchange/rest-client.ts +141 -66
  162. package/src/stackexchange/types.ts +0 -17
  163. package/src/tool.ts +15 -423
  164. package/src/tools/grep.ts +32 -310
  165. package/src/tools/health-tool-definition.ts +101 -0
  166. package/src/tools/index.ts +38 -9
  167. package/src/tools/research-knowledge-search.ts +974 -0
  168. package/src/tools/research-knowledge-types.ts +77 -0
  169. package/src/tools/research-tool-definition.ts +494 -0
  170. package/src/tools/scrape.ts +286 -388
  171. package/src/tools/search.ts +98 -153
  172. package/src/tools/security.ts +107 -80
  173. package/src/tools/stackexchange.ts +58 -35
  174. package/src/tools/youtube-transcript.ts +163 -0
  175. package/src/tui/knowledge-search-panel.ts +86 -0
  176. package/src/tui/pulse.ts +86 -0
  177. package/src/tui/research-health.ts +124 -0
  178. package/src/tui/research-panel-color-utils.ts +340 -0
  179. package/src/tui/research-panel-format.ts +54 -0
  180. package/src/tui/research-panel-state.ts +404 -0
  181. package/src/tui/research-panel-wave.ts +280 -0
  182. package/src/tui/research-panel.ts +339 -435
  183. package/src/tui/research-tui-manager.ts +233 -0
  184. package/src/tui/tui-controller.ts +137 -0
  185. package/src/types/extension-context.ts +18 -49
  186. package/src/types/index.ts +61 -0
  187. package/src/types/llm.ts +68 -29
  188. package/src/types/research-panel-types.ts +61 -0
  189. package/src/utils/circuit-breaker.ts +146 -0
  190. package/src/utils/citation-utils.ts +97 -0
  191. package/src/utils/disk-space-checker.ts +55 -0
  192. package/src/utils/error-tracker.ts +265 -0
  193. package/src/utils/host-config.ts +45 -0
  194. package/src/utils/input-validation.ts +8 -10
  195. package/src/utils/json-utils.ts +150 -16
  196. package/src/utils/llm-usage.ts +54 -0
  197. package/src/utils/log-rotation.ts +125 -0
  198. package/src/utils/log-utils.ts +159 -0
  199. package/src/utils/make-resource-loader.ts +3 -1
  200. package/src/utils/metrics-summary.ts +459 -0
  201. package/src/utils/metrics.ts +302 -0
  202. package/src/utils/research-export.ts +28 -12
  203. package/src/utils/safe-unref.ts +31 -0
  204. package/src/utils/shared-links.ts +195 -90
  205. package/src/utils/shutdown-manager.ts +65 -0
  206. package/src/utils/stdio-capture.ts +407 -0
  207. package/src/utils/text-utils.ts +258 -11
  208. package/src/utils/tool-usage-tracker.ts +83 -16
  209. package/src/utils/url-utils.ts +255 -0
  210. package/src/utils/user-agent.ts +28 -0
  211. package/src/web-research/browser-search.ts +179 -0
  212. package/src/web-research/retry-utils.ts +173 -77
  213. package/src/web-research/scraper-types.ts +72 -0
  214. package/src/web-research/scraper-utils.ts +434 -0
  215. package/src/web-research/search.ts +78 -218
  216. package/src/web-research/types.ts +9 -24
  217. package/src/web-research/utils.ts +2 -143
  218. package/src/web-research/web-scraper.ts +477 -0
  219. package/src/youtube/index.ts +154 -0
  220. package/src/youtube/potoken.ts +259 -0
  221. package/src/youtube/transcript-client.ts +390 -0
  222. package/src/youtube/video-id.ts +118 -0
  223. package/config/searxng/default-settings.yml +0 -189
  224. package/config/searxng/limiter.toml +0 -34
  225. package/config/tooling/eslint.config.js +0 -73
  226. package/config/tooling/vitest.config.integration.ts +0 -17
  227. package/config/tooling/vitest.config.ts +0 -40
  228. package/config/tooling/vitest.config.unit.ts +0 -12
  229. package/docs/assets/README-banner.jpg +0 -0
  230. package/scripts/setup.js +0 -212
  231. package/src/infrastructure/searxng-lifecycle.ts +0 -644
  232. package/src/infrastructure/searxng-manager.ts +0 -1183
  233. package/src/infrastructure/state-manager.ts +0 -918
  234. package/src/orchestration/deep-research-reducer.ts +0 -129
  235. package/src/orchestration/id-utils.ts +0 -63
  236. package/src/security/nvd.ts +0 -532
  237. package/src/security/osv.ts +0 -487
  238. package/src/stackexchange/cache.ts +0 -111
  239. package/src/stackexchange/output/index.ts +0 -7
  240. package/src/stackexchange/output/json.ts +0 -21
  241. package/src/tui/searxng-status.ts +0 -80
  242. package/src/utils/inject-date.ts +0 -29
  243. package/src/utils/research-error.ts +0 -205
  244. package/src/utils/searxng-config.ts +0 -94
  245. package/src/utils/session-state.ts +0 -295
  246. package/src/web-research/dependencies.ts +0 -20
  247. package/src/web-research/scrapers.ts +0 -935
  248. package/tsconfig.json +0 -40
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Knowledge Store Service Interfaces
3
+ */
4
+
5
+ import type { IService } from '../service-registry.ts';
6
+
7
+ /**
8
+ * Single document record in the knowledge store
9
+ */
10
+ export interface StoreDocument {
11
+ url: string;
12
+ text: string;
13
+ content?: string;
14
+ metadata: Record<string, any>;
15
+ timestamp: number;
16
+ workspace?: string;
17
+ is_global?: boolean;
18
+ ingestion_type?: string;
19
+ }
20
+
21
+ /**
22
+ * ONNX runtime environment
23
+ */
24
+ export interface ONNXRuntimeEnv {
25
+ logLevel?: 'verbose' | 'info' | 'warning' | 'error' | 'fatal';
26
+ debug?: boolean;
27
+ }
28
+
29
+ /**
30
+ * HuggingFace environment with ONNX support (Transformers.js v4)
31
+ */
32
+ export interface HFEnv {
33
+ cacheDir: string;
34
+ backends: {
35
+ onnx: ONNXRuntimeEnv;
36
+ };
37
+ }
38
+
39
+ /**
40
+ * Disposable pipeline interface
41
+ */
42
+ export interface DisposablePipeline {
43
+ dispose(): Promise<void>;
44
+ }
45
+
46
+ /**
47
+ * Embedder configuration options
48
+ */
49
+ export interface EmbedderOptions {
50
+ model: string;
51
+ pooling?: 'mean' | 'cls' | 'last_token';
52
+ queryPrefix?: string;
53
+ initializationTimeoutMs?: number;
54
+ device?: string;
55
+ maxTokens?: number;
56
+ batchSize?: number;
57
+ charsPerToken?: number;
58
+ documentPrefix?: string;
59
+ stateManager?: any; // To avoid circular dependency with IStateManager
60
+ useCache?: boolean;
61
+ }
62
+
63
+ /**
64
+ * Embedder state
65
+ */
66
+ export type EmbedderState = 'idle' | 'initializing' | 'ready' | 'failed' | 'disposing';
67
+
68
+ /**
69
+ * Item to be ingested into the knowledge store
70
+ */
71
+ export interface IngestionItem {
72
+ url: string;
73
+ markdown: string;
74
+ content?: string;
75
+ metadata?: Record<string, any>;
76
+ }
77
+
78
+ /**
79
+ * A URL entry returned from the knowledge store with its description
80
+ */
81
+ export interface StoreUrlEntry {
82
+ url: string;
83
+ description: string;
84
+ provenance?: string;
85
+ }
86
+
87
+ /**
88
+ * Embedder interface for text embedding operations
89
+ */
90
+ export interface IEmbedder {
91
+ getDevice(): string | null;
92
+ getOriginalDevice(): string | null;
93
+ getDimension(): number | null;
94
+ setDimension(dim: number): void;
95
+ isInitialized(): boolean;
96
+ embed(text: string): Promise<Float32Array | number[]>;
97
+ embedMany(texts: string[]): Promise<(Float32Array | number[])[]>;
98
+ dispose(): Promise<void>;
99
+ }
100
+
101
+ /**
102
+ * Core Knowledge Store interface for raw storage operations.
103
+ */
104
+ export interface IKnowledgeStore extends IService {
105
+ open(): Promise<void>;
106
+ close(): Promise<void>;
107
+ clear(filter?: string): Promise<void>;
108
+ /** Rebuild FTS indexes; returns true if a rebuild ran, false if skipped (empty/unchanged). */
109
+ rebuildFtsIndex(): Promise<boolean>;
110
+ /** Compact data fragments and prune stale versions/indices to reclaim disk. Returns true if it ran. */
111
+ optimize(options?: { cleanupOlderThan?: Date; deleteUnverified?: boolean }): Promise<boolean>;
112
+ count(): Promise<number>;
113
+ search(query: string, options?: { limit?: number }): Promise<StoreDocument[]>;
114
+ findRelevantUrls(query: string, options?: { limit?: number }): Promise<StoreUrlEntry[]>;
115
+ rebuildDocument(url: string): Promise<{ text: string; description: string | null; metadata: Record<string, any>; ageDays?: number } | null>;
116
+ findDocumentsByUrl(url: string): Promise<StoreDocument[]>;
117
+ findByUrl(url: string): Promise<StoreDocument[]>;
118
+ countScoped(workspace?: string): Promise<{ local: number; global: number; projects: number }>;
119
+
120
+ /** Extended operations */
121
+ addDocuments(docs: StoreDocument[]): Promise<void>;
122
+ deleteByUrl(url: string): Promise<void>;
123
+ deleteByUrlAndType(url: string, ingestionType: string): Promise<void>;
124
+ isStoreClosed?(): boolean;
125
+
126
+ /**
127
+ * Export the knowledge store entries (summaries and vectors) for use in a web application.
128
+ * @param outputPath - Path to save the exported JSON file
129
+ */
130
+ exportForWeb(outputPath: string): Promise<void>;
131
+ }
132
+
133
+ /**
134
+ * Higher-level service interface for Knowledge Store management.
135
+ */
136
+ export interface IKnowledgeStoreService extends IService {
137
+ isReady(): boolean;
138
+ /** The working directory this service initialized against (from ctx.cwd). */
139
+ getCwd(): string;
140
+ /**
141
+ * Why the store is DISABLED, if it is: 'native' (no ML/vector native stack on this
142
+ * platform — permanent), 'mode' (Knowledge Mode is/was `none` — revivable), or null
143
+ * (not disabled). Lets an observer report the accurate reason without forcing init.
144
+ */
145
+ getDisabledReason(): 'mode' | 'native' | null;
146
+ getDevice(): string | null;
147
+ getStore(): Promise<IKnowledgeStore | null>;
148
+ getEmbedder(): Promise<IEmbedder | null>;
149
+ getWriterQueue(): Promise<IWriterQueue | null>;
150
+ clear(): Promise<void>;
151
+ clearLocal(): Promise<void>;
152
+ clearGlobal(): Promise<void>;
153
+
154
+ /**
155
+ * Export the knowledge store for web use.
156
+ * @param outputPath - Path to save the exported JSON file
157
+ */
158
+ exportForWeb(outputPath: string): Promise<void>;
159
+ }
160
+
161
+ /**
162
+ * Writer queue interface for batching write operations
163
+ */
164
+ export interface IWriterQueue extends IService {
165
+ drain(): Promise<void>;
166
+ enqueue(item: IngestionItem): void;
167
+ }
168
+
169
+ /**
170
+ * Metrics snapshot interface
171
+ */
172
+ export interface IMetricsSnapshot {
173
+ counters: Record<string, number>;
174
+ gauges: Record<string, number>;
175
+ histograms: Record<string, IMetricHistogram>;
176
+ }
177
+
178
+ /**
179
+ * Metric histogram statistics interface
180
+ */
181
+ export interface IMetricHistogram {
182
+ count: number;
183
+ min: number;
184
+ max: number;
185
+ avg: number;
186
+ p50: number;
187
+ p90: number;
188
+ p95: number;
189
+ p99: number;
190
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Observer Interfaces
3
+ *
4
+ * Defines the ResearchObserver interface used by the planning service and
5
+ * orchestration layer to emit research lifecycle events. Lives in core/interfaces
6
+ * so both planning-interfaces.ts and the orchestration layer can import it
7
+ * without creating a circular dependency.
8
+ */
9
+
10
+ import type { ResearchPlan } from './research-plan-types.ts';
11
+ export interface HeadlessObserverOptions {
12
+ /** Callback for progress updates */
13
+ onProgress?: (event: string, data?: any) => void;
14
+ /** Whether to log events to the console/logger */
15
+ enableLogging?: boolean;
16
+ }
17
+
18
+ export interface ResearchObserver {
19
+ onStart?(query: string, complexity: number): void;
20
+
21
+ // Coordinator/Planning phase
22
+ onPlanningStart?(attempt: number): void;
23
+ onPlanningProgress?(status: string): void;
24
+ onPlanningTokens?(tokens: number, cost: number): void;
25
+ onPlanningSuccess?(plan: ResearchPlan): void;
26
+
27
+ // Research phase (rounds)
28
+ onRoundStart?(round: number): void;
29
+ onSearchStart?(queries: string[]): void;
30
+ onSearchProgress?(resultsCount: number): void;
31
+ onSearchComplete?(resultsCount: number): void;
32
+
33
+ // Individual researcher agents
34
+ onResearcherStart?(id: string, name: string, goal: string, roundNumber?: number): void;
35
+ onResearcherProgress?(id: string, status?: string, tokens?: number, cost?: number): void;
36
+ onResearcherTokensHint?(id: string, inputTokens: number): void;
37
+ onResearcherComplete?(id: string, report: string): void;
38
+ onResearcherFailure?(id: string, error: string): void;
39
+
40
+ /** Per-URL or per-tool-action result feedback (triggers TUI flash). */
41
+ onToolResult?(researcherId: string, success: boolean): void;
42
+
43
+ // Evaluation phase
44
+ onEvaluationStart?(round: number): void;
45
+ onEvaluationProgress?(status: string): void;
46
+ onEvaluationTokens?(tokens: number, cost: number): void;
47
+ onEvaluationDecision?(action: 'synthesize' | 'delegate', plan?: ResearchPlan, round?: number): void;
48
+
49
+ // Synthesis/Completion
50
+ /**
51
+ * Fired when the run enters FINAL synthesis / stops consuming steering:
52
+ * - deep mode: right before the forced (mustSynthesize) evaluator call, and
53
+ * on the evaluator-chose-synthesize path (idempotent there — the flag is
54
+ * already off via onEvaluationDecision('synthesize')).
55
+ * - quick mode: as soon as the researcher session settles, i.e. the point
56
+ * the 500ms steering-consume poller stops running.
57
+ * TUI consequence: steeringAcceptable flips false, so a late steer takes the
58
+ * fall-through path (forwarded to pi with an accurate toast) instead of being
59
+ * queued for a "next round" that will never happen.
60
+ */
61
+ onSynthesisStart?(): void;
62
+ onComplete?(result: string): void;
63
+ onError?(error: Error): void;
64
+
65
+ // Global token/cost tracking
66
+ onTokensConsumed?(tokens: number, cost: number): void;
67
+ }
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Orchestration Service Interfaces
3
+ */
4
+
5
+ import type { IService } from '../service-registry.ts';
6
+ import type { Config } from '../../config.ts';
7
+ import type { ResearchPlan, ResearcherConfig } from './planning-interfaces.ts';
8
+ import type { QueryResultWithError } from '../../web-research/types.ts';
9
+ import type { StoreUrlEntry } from './knowledge-interfaces.ts';
10
+
11
+ import type { Model } from '@earendil-works/pi-ai';
12
+ import type { ExtensionContext, AgentToolResult } from '@earendil-works/pi-coding-agent';
13
+ import type { ResearchObserver, HeadlessObserverOptions } from './observer-interfaces.ts';
14
+ import type { SteeringMessage } from './steering-interfaces.ts';
15
+
16
+ /**
17
+ * Options for running a research task
18
+ */
19
+ export interface ResearchOptions {
20
+ ctx: ExtensionContext;
21
+ query: string;
22
+ depth?: 0 | 1 | 2 | 3;
23
+ complexity?: 1 | 2 | 3;
24
+ model?: Model<any>;
25
+ observer?: ResearchObserver | HeadlessObserverOptions;
26
+ onUpdate?: (update: AgentToolResult<any>) => void;
27
+ sessionId: string;
28
+ researchId: string;
29
+ config?: Config;
30
+ excludeTools?: string[];
31
+ initialLinks?: string[];
32
+ signal?: AbortSignal;
33
+ }
34
+
35
+ /**
36
+ * Options for running researchers in parallel
37
+ */
38
+ export interface RunResearchersOptions {
39
+ plan: { researchers?: ResearcherConfig[] };
40
+ options: {
41
+ sessionId: string;
42
+ researchId: string;
43
+ query: string;
44
+ complexity: 1 | 2 | 3;
45
+ excludeTools?: string[];
46
+ ctx: ExtensionContext;
47
+ model: Model<any>;
48
+ config?: Config;
49
+ observer?: ResearchObserver;
50
+ initialLinks?: string[];
51
+ };
52
+ currentRound: number;
53
+ signal?: AbortSignal;
54
+ }
55
+
56
+ /**
57
+ * Research Synthesis Service Interface
58
+ */
59
+ export interface IResearchSynthesisService extends IService {
60
+ storeReport(researchId: string, researcherId: string, report: string): void;
61
+ getAllReports(researchId: string): Map<string, string>;
62
+ getReport(researchId: string, id: string): string | undefined;
63
+ getReportsForRound(researchId: string, round: number): Map<string, string>;
64
+ getReportCount(researchId: string): number;
65
+ hasReports(researchId: string): boolean;
66
+ clearReports(researchId?: string): void;
67
+ buildFallbackSynthesis(researchId: string, currentRound?: number): string;
68
+ ensureCitedLinks(researchId: string, result: string): string;
69
+ appendSteeringGuidance(result: string, steeringMessages: SteeringMessage[]): string;
70
+ appendMetadata(result: string, modelId: string): string;
71
+ }
72
+
73
+ /**
74
+ * Research Orchestration Service Interface
75
+ */
76
+ export interface IResearchOrchestration extends IService {
77
+ resolveResearchModel(options: ResearchOptions): Promise<Model<any>>;
78
+ runResearch(options: ResearchOptions, signal?: AbortSignal): Promise<string>;
79
+ cleanupResearchServices(sessionId?: string, researchId?: string, ctx?: any, config?: Config, opts?: { skipStoreMaintenance?: boolean }): Promise<void>;
80
+ distributeSearchResults(plan: ResearchPlan, results: QueryResultWithError[], ctx?: any): Promise<Map<string, string[]>>;
81
+ runResearchers(options: RunResearchersOptions, researcherLinks?: Map<string, string[]>, storeLinks?: Map<string, StoreUrlEntry[]>, ctx?: any): Promise<void>;
82
+ runSearchBurst(queries: string[], config: Config, signal?: AbortSignal, onProgress?: (links: number) => void, ctx?: any): Promise<QueryResultWithError[]>;
83
+ storeLinkDescriptions(sessionId: string, round: number, researchId: string, config: Config, ctx?: any): Promise<void>;
84
+ // Advisory only — logs infrastructure health; research never aborts on the result.
85
+ checkHealth(round: number, researchId?: string, ctx?: any): Promise<void>;
86
+ }
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Planning Service Interfaces
3
+ */
4
+
5
+ import type { IService } from '../service-registry.ts';
6
+ import type { Model } from '@earendil-works/pi-ai';
7
+ import type { ModelRegistry } from '@earendil-works/pi-coding-agent';
8
+ import type { ResearchObserver } from './observer-interfaces.ts';
9
+ import type { ResearchPlan, ResearcherConfig } from './research-plan-types.ts';
10
+ import type { Config } from '../../config.ts';
11
+
12
+ export type { ResearchPlan, ResearcherConfig };
13
+ export { ResearcherConfigSchema, ResearchPlanSchema } from './research-plan-types.ts';
14
+
15
+ /**
16
+ * Session context for planning operations
17
+ */
18
+ export interface SessionContext {
19
+ sessionId: string;
20
+ researchId: string;
21
+ }
22
+
23
+ /**
24
+ * Options for generating a research plan
25
+ */
26
+ export interface GeneratePlanOptions {
27
+ sessionId: string;
28
+ query: string;
29
+ complexity: 1 | 2 | 3;
30
+ model: Model<any>;
31
+ modelRegistry: ModelRegistry;
32
+ cwd: string;
33
+ signal?: AbortSignal;
34
+ observer?: ResearchObserver;
35
+ excludeTools?: string[];
36
+ steeringMessages?: string[];
37
+ /** Resolved config from the caller (SDK/orchestrator). Preferred over getConfig(cwd)
38
+ * so SDK code-config and ignoreGlobalConfig hermeticity reach the coordinator call. */
39
+ config?: Config;
40
+ }
41
+
42
+ /**
43
+ * Options for generating queries for a researcher
44
+ */
45
+ export interface GenerateQueriesOptions {
46
+ researcher: ResearcherConfig;
47
+ query: string;
48
+ complexity: 1 | 2 | 3;
49
+ model: Model<any>;
50
+ signal?: AbortSignal;
51
+ }
52
+
53
+ /**
54
+ * Options for updating plan for next round
55
+ */
56
+ export interface UpdatePlanOptions {
57
+ sessionId: string;
58
+ reports: Map<string, string>;
59
+ round: number;
60
+ query: string;
61
+ complexity: 1 | 2 | 3;
62
+ model: Model<any>;
63
+ modelRegistry: ModelRegistry;
64
+ cwd: string;
65
+ signal?: AbortSignal;
66
+ previousPlan: ResearchPlan | null;
67
+ totalResearchersPlanned: number;
68
+ mustSynthesize?: boolean;
69
+ observer?: ResearchObserver;
70
+ excludeTools?: string[];
71
+ steeringMessages?: string[];
72
+ /** Resolved config from the caller (SDK/orchestrator). Preferred over getConfig(cwd)
73
+ * so SDK code-config and ignoreGlobalConfig hermeticity reach the evaluator/synthesis call. */
74
+ config?: Config;
75
+ }
76
+
77
+ /**
78
+ * Planning service interface
79
+ */
80
+ export interface IPlanningService extends IService {
81
+ generatePlan(options: GeneratePlanOptions): Promise<ResearchPlan>;
82
+ generateResearchers(plan: ResearchPlan, query: string, complexity: 1 | 2 | 3): ResearcherConfig[];
83
+ generateQueries(options: GenerateQueriesOptions): Promise<string[]>;
84
+ updatePlanForRound(options: UpdatePlanOptions): Promise<ResearchPlan>;
85
+ getQueryHistory(sessionId: string): string[];
86
+ addToQueryHistory(sessionId: string, queries: string[]): void;
87
+ getCurrentPlan(sessionId: string): ResearchPlan | null;
88
+ getTotalResearchersPlanned(sessionId: string): number;
89
+ incrementTotalResearchersPlanned(sessionId: string, count: number): void;
90
+ getTeamSize(complexity: 1 | 2 | 3): number;
91
+ getQueryBudget(complexity: 1 | 2 | 3): number;
92
+ getComplexityGuidance(complexity: 1 | 2 | 3, maxTeamSize: number, queryBudget: number): string;
93
+ getEvaluatorComplexityGuidance(complexity: 1 | 2 | 3): string;
94
+ getRoundPhaseGuidance(currentRound: number, maxRounds: number, complexity: 1 | 2 | 3, maxTeamSize: number): string;
95
+ capResearcherQueries(plan: ResearchPlan, complexity: 1 | 2 | 3, serviceName: string): ResearchPlan;
96
+ parseJsonPlan(text: string): ResearchPlan;
97
+ buildFallbackCoordinatorPlan(rawText: string, query: string): ResearchPlan;
98
+ clearPlanningState(sessionId?: string): void;
99
+ isReady(): boolean;
100
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Process Service Interfaces
3
+ */
4
+
5
+ import type { IService } from '../service-registry.ts';
6
+
7
+ /**
8
+ * Process Lifecycle Service Interface
9
+ */
10
+ export interface IProcessLifecycle extends IService {
11
+ isProcessAlive(pid: number, expectedStartTime?: number | null): Promise<boolean>;
12
+ isProcessAliveSync(pid: number): boolean;
13
+ isPidAlive<TState>(
14
+ pid: number,
15
+ expectedSchedulerId?: string,
16
+ options?: {
17
+ getState?: (skipLock?: boolean) => Promise<TState>;
18
+ skipLock?: boolean;
19
+ getSchedulerIdFromState?: (state: TState) => string | undefined;
20
+ expectedStartTime?: number | null;
21
+ }
22
+ ): Promise<boolean>;
23
+ getCurrentPid(): number;
24
+ getProcessStartTime(pid: number): Promise<number | null>;
25
+ getCurrentProcessStartTime(): Promise<number | null>;
26
+ waitForProcessTermination(pid: number, timeoutMs?: number, checkIntervalMs?: number, expectedStartTime?: number | null): Promise<boolean>;
27
+ isCurrentProcess(pid: number): boolean;
28
+ getProcessInfo(pid: number): Promise<{ pid: number; alive: boolean; startTime?: number | null } | null>;
29
+ }
30
+
31
+ /**
32
+ * GPU Resource Service Interface
33
+ */
34
+ export interface IGPUResourceService extends IService {
35
+ acquireGpuLock(sessionId?: string, timeoutMs?: number, ctx?: any): Promise<boolean>;
36
+ releaseGpuLock(pid?: number, ctx?: any): Promise<void>;
37
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Research Plan Types
3
+ *
4
+ * Core data types for research plans and researcher configuration.
5
+ * Lives in a separate file so both planning-interfaces.ts and
6
+ * observer-interfaces.ts can import without creating a circular dependency.
7
+ */
8
+
9
+ import { Type, type Static } from 'typebox';
10
+
11
+ // ============================================================================
12
+ // TypeBox Schemas for Validation
13
+ // ============================================================================
14
+
15
+ /**
16
+ * Individual researcher configuration schema
17
+ */
18
+ export const ResearcherConfigSchema = Type.Object({
19
+ id: Type.Union([Type.String(), Type.Number()]),
20
+ name: Type.String(),
21
+ goal: Type.String(),
22
+ queries: Type.Array(Type.String()),
23
+ });
24
+
25
+ /**
26
+ * Individual researcher configuration type
27
+ */
28
+ export type ResearcherConfig = Static<typeof ResearcherConfigSchema>;
29
+
30
+ /**
31
+ * Research plan structure schema
32
+ */
33
+ export const ResearchPlanSchema = Type.Object({
34
+ action: Type.Optional(Type.Union([
35
+ Type.Literal('synthesize'),
36
+ Type.Literal('delegate'),
37
+ Type.Literal('wait')
38
+ ])),
39
+ // Optional at the schema level because a 'synthesize' response legitimately omits
40
+ // researchers (its contract is { action, content }). The delegate-requires-researchers
41
+ // invariant is enforced explicitly in parseJsonPlan() so that a valid synthesis is not
42
+ // misrouted into the agentic-repair path. See research-plan-types history / planning-utils.
43
+ researchers: Type.Optional(Type.Array(ResearcherConfigSchema)),
44
+ allQueries: Type.Optional(Type.Array(Type.String())),
45
+ content: Type.Optional(Type.String()),
46
+ title: Type.Optional(Type.String()),
47
+ });
48
+
49
+ /**
50
+ * Research plan structure type
51
+ */
52
+ export type ResearchPlan = Static<typeof ResearchPlanSchema>;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Scheduler Service Interfaces
3
+ */
4
+
5
+ import type { IService } from '../service-registry.ts';
6
+ import type { Config } from '../../config.ts';
7
+
8
+ /**
9
+ * Minimal scheduler instance interface — the raw scheduler object returned
10
+ * by the factory and stored inside SchedulerService.
11
+ */
12
+ export interface ISchedulerInstance {
13
+ shutdown(): Promise<void>;
14
+ schedulerId?: string;
15
+ }
16
+
17
+ /**
18
+ * Internal state management methods exposed by SchedulerService.
19
+ * Used by browser-lifecycle.ts and the infrastructure scheduler factory to manage
20
+ * scheduler instance state without creating a circular import on the SchedulerService class.
21
+ * Extends IService so it satisfies the tryGetService<T extends IService> constraint.
22
+ */
23
+ export interface ISchedulerInternals extends IService {
24
+ getSchedulerInstance(): ISchedulerInstance | null;
25
+ setSchedulerInstance(instance: ISchedulerInstance | null): void;
26
+ getSchedulerVersion(): string | null;
27
+ setSchedulerVersion(version: string | null): void;
28
+ getSchedulerInitializationPromise(): Promise<ISchedulerInstance> | null;
29
+ setSchedulerInitializationPromise(promise: Promise<ISchedulerInstance> | null): void;
30
+ getPendingShutdownPromise(): Promise<void> | null;
31
+ setPendingShutdownPromise(promise: Promise<void> | null): void;
32
+ isSchedulerRestartInProgress(): boolean;
33
+ setSchedulerRestartInProgress(inProgress: boolean): void;
34
+ }
35
+
36
+ /**
37
+ * Scheduler service interface
38
+ */
39
+ export interface ISchedulerService extends IService {
40
+ isReady(): boolean;
41
+ getScheduler(): IScheduler | null;
42
+ }
43
+
44
+ /**
45
+ * Scheduler search result — matches the shape returned by the browser
46
+ * infrastructure layer (BrowserTaskScheduler / BrowserClient).
47
+ */
48
+ export interface SearchResult {
49
+ title: string;
50
+ url: string;
51
+ content: string;
52
+ engine?: string;
53
+ score?: number;
54
+ }
55
+
56
+ /**
57
+ * Scheduler scrape result — matches the shape returned by the browser
58
+ * infrastructure layer (BrowserTaskScheduler / BrowserClient).
59
+ */
60
+ export interface ScrapeResult {
61
+ url: string;
62
+ success: boolean;
63
+ markdown: string;
64
+ error?: string;
65
+ source?: string;
66
+ layer?: string;
67
+ duration?: number;
68
+ }
69
+
70
+ /**
71
+ * Base scheduler interface
72
+ */
73
+ export interface IScheduler {
74
+ runSearch(query: string, config?: Config, signal?: AbortSignal): Promise<SearchResult[]>;
75
+ runScrape(url: string, config?: Config, signal?: AbortSignal): Promise<ScrapeResult>;
76
+ runHealthCheck(config?: Config, signal?: AbortSignal): Promise<{ success: boolean }>;
77
+ shutdown(): Promise<void>;
78
+ resetIdleTimerOnActivity?(): void;
79
+ schedulerId?: string;
80
+ }
81
+
82
+ /**
83
+ * Scheduler service metadata
84
+ */
85
+ export interface SchedulerMetadata {
86
+ schedulerId: string;
87
+ schedulerVersion: string;
88
+ port?: number;
89
+ pid: number;
90
+ isLeader: boolean;
91
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Service Names (Constants)
3
+ */
4
+
5
+ /**
6
+ * Standard service names used throughout the application
7
+ */
8
+ export const ServiceNames = {
9
+ SCHEDULER: 'scheduler',
10
+ SCHEDULER_FACTORY: 'scheduler-factory',
11
+ HEALTH_CHECK_CACHE: 'health-check-cache',
12
+ STATE_MANAGER: 'state-manager',
13
+ KNOWLEDGE_STORE: 'knowledge-store',
14
+ WRITER_QUEUE: 'writer-queue',
15
+ METRICS: 'metrics',
16
+ PLANNING: 'planning',
17
+ PROCESS_LIFECYCLE: 'process-lifecycle',
18
+ RESEARCH_ORCHESTRATION: 'research-orchestration',
19
+ STATE_PATH_CONFIGURATION: 'state-path-configuration',
20
+ // Helper services for state management
21
+ FILE_LOCK_SERVICE: 'file-lock-service',
22
+ GPU_RESOURCE_SERVICE: 'gpu-resource-service',
23
+ STATE_SESSION_MANAGER: 'state-session-manager',
24
+ STATE_BROWSER_MANAGER: 'state-browser-manager',
25
+ STATE_BACKUP_MANAGER: 'state-backup-manager',
26
+ STATE_METRICS_COLLECTOR: 'state-metrics-collector',
27
+ STATE_VALIDATOR: 'state-validator',
28
+ HEALTH_REGISTRY: 'health-registry',
29
+ // Browser infrastructure services
30
+ WORKER_POOL_MANAGER: 'worker-pool-manager',
31
+ // Research session services
32
+ RESEARCH_SESSION_SERVICE: 'research-session-service',
33
+ RESEARCH_SYNTHESIS_SERVICE: 'research-synthesis-service',
34
+ } as const;
35
+
36
+ /**
37
+ * Type of service names
38
+ */
39
+ export type ServiceName = typeof ServiceNames[keyof typeof ServiceNames];
@@ -0,0 +1,29 @@
1
+ /**
2
+ * State Manager Service Interface
3
+ */
4
+
5
+ import type { IService } from '../service-registry.ts';
6
+
7
+ /**
8
+ * State manager service interface
9
+ */
10
+ export interface IStateManager extends IService {
11
+ readState(): Promise<any>;
12
+ writeState(state: any): Promise<void>;
13
+ updateState(updater: (state: any) => any | Promise<any>): Promise<void>;
14
+ addSession(sessionId: string, param: number | string): Promise<void>;
15
+ removeSession(sessionId: string): Promise<void>;
16
+ updateHeartbeat(sessionId: string): Promise<void>;
17
+ cleanupStaleSessions(timeoutMs: number): Promise<number>;
18
+ getBrowserServer(): Promise<{ port: number; pid: number; schedulerId?: string; authSecret?: string } | null>;
19
+ setBrowserServer(port: number, pid: number, schedulerId?: string, authSecret?: string): Promise<void>;
20
+ clearBrowserServer(): Promise<void>;
21
+ getEmbeddingServer(): Promise<{ port: number; pid: number; startTime?: number; serverId: string; model?: string } | null>;
22
+ clearEmbeddingServer(): Promise<void>;
23
+ isPidAlive(pid: number, expectedSchedulerId?: string, skipLock?: boolean): Promise<boolean>;
24
+ acquireGpuLock(sessionId?: string, timeoutMs?: number): Promise<boolean>;
25
+ releaseGpuLock(pid?: number): Promise<void>;
26
+ getGpuOwner(): Promise<any | null>;
27
+ getMetrics(): Promise<any>;
28
+ cleanup(): Promise<void>;
29
+ }