@bradygaster/squad-sdk 0.7.0 → 0.8.2
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/README.md +296 -296
- package/dist/adapter/client.d.ts +243 -0
- package/dist/adapter/client.d.ts.map +1 -0
- package/dist/adapter/client.js +567 -0
- package/dist/adapter/client.js.map +1 -0
- package/dist/adapter/errors.d.ts +260 -0
- package/dist/adapter/errors.d.ts.map +1 -0
- package/dist/adapter/errors.js +362 -0
- package/dist/adapter/errors.js.map +1 -0
- package/dist/adapter/types.d.ts +779 -0
- package/dist/adapter/types.d.ts.map +1 -0
- package/dist/adapter/types.js +11 -0
- package/dist/adapter/types.js.map +1 -0
- package/dist/agents/charter-compiler.d.ts +102 -0
- package/dist/agents/charter-compiler.d.ts.map +1 -0
- package/dist/agents/charter-compiler.js +157 -0
- package/dist/agents/charter-compiler.js.map +1 -0
- package/dist/agents/history-shadow.d.ts +80 -0
- package/dist/agents/history-shadow.d.ts.map +1 -0
- package/dist/agents/history-shadow.js +239 -0
- package/dist/agents/history-shadow.js.map +1 -0
- package/dist/agents/index.d.ts +71 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +183 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/lifecycle.d.ts +138 -0
- package/dist/agents/lifecycle.d.ts.map +1 -0
- package/dist/agents/lifecycle.js +284 -0
- package/dist/agents/lifecycle.js.map +1 -0
- package/dist/agents/model-selector.d.ts +80 -0
- package/dist/agents/model-selector.d.ts.map +1 -0
- package/dist/agents/model-selector.js +171 -0
- package/dist/agents/model-selector.js.map +1 -0
- package/dist/agents/onboarding.d.ts +65 -0
- package/dist/agents/onboarding.d.ts.map +1 -0
- package/dist/agents/onboarding.js +373 -0
- package/dist/agents/onboarding.js.map +1 -0
- package/dist/build/bundle.d.ts +32 -0
- package/dist/build/bundle.d.ts.map +1 -0
- package/dist/build/bundle.js +97 -0
- package/dist/build/bundle.js.map +1 -0
- package/dist/build/ci-pipeline.d.ts +51 -0
- package/dist/build/ci-pipeline.d.ts.map +1 -0
- package/dist/build/ci-pipeline.js +180 -0
- package/dist/build/ci-pipeline.js.map +1 -0
- package/dist/build/github-dist.d.ts +37 -0
- package/dist/build/github-dist.d.ts.map +1 -0
- package/dist/build/github-dist.js +117 -0
- package/dist/build/github-dist.js.map +1 -0
- package/dist/build/index.d.ts +11 -0
- package/dist/build/index.d.ts.map +1 -0
- package/dist/build/index.js +11 -0
- package/dist/build/index.js.map +1 -0
- package/dist/build/install-migration.d.ts +28 -0
- package/dist/build/install-migration.d.ts.map +1 -0
- package/dist/build/install-migration.js +103 -0
- package/dist/build/install-migration.js.map +1 -0
- package/dist/build/npm-package.d.ts +54 -0
- package/dist/build/npm-package.d.ts.map +1 -0
- package/dist/build/npm-package.js +128 -0
- package/dist/build/npm-package.js.map +1 -0
- package/dist/build/release.d.ts +108 -0
- package/dist/build/release.d.ts.map +1 -0
- package/dist/build/release.js +295 -0
- package/dist/build/release.js.map +1 -0
- package/dist/build/versioning.d.ts +38 -0
- package/dist/build/versioning.d.ts.map +1 -0
- package/dist/build/versioning.js +113 -0
- package/dist/build/versioning.js.map +1 -0
- package/dist/casting/casting-engine.d.ts +60 -0
- package/dist/casting/casting-engine.d.ts.map +1 -0
- package/dist/casting/casting-engine.js +223 -0
- package/dist/casting/casting-engine.js.map +1 -0
- package/dist/casting/casting-history.d.ts +54 -0
- package/dist/casting/casting-history.d.ts.map +1 -0
- package/dist/casting/casting-history.js +63 -0
- package/dist/casting/casting-history.js.map +1 -0
- package/dist/casting/index.d.ts +46 -0
- package/dist/casting/index.d.ts.map +1 -0
- package/dist/casting/index.js +45 -0
- package/dist/casting/index.js.map +1 -0
- package/dist/client/event-bus.d.ts +29 -0
- package/dist/client/event-bus.d.ts.map +1 -0
- package/dist/client/event-bus.js +52 -0
- package/dist/client/event-bus.js.map +1 -0
- package/dist/client/index.d.ts +100 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +170 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/session-pool.d.ts +66 -0
- package/dist/client/session-pool.d.ts.map +1 -0
- package/dist/client/session-pool.js +145 -0
- package/dist/client/session-pool.js.map +1 -0
- package/dist/config/agent-doc.d.ts +43 -0
- package/dist/config/agent-doc.d.ts.map +1 -0
- package/dist/config/agent-doc.js +158 -0
- package/dist/config/agent-doc.js.map +1 -0
- package/dist/config/agent-source.d.ts +95 -0
- package/dist/config/agent-source.d.ts.map +1 -0
- package/dist/config/agent-source.js +274 -0
- package/dist/config/agent-source.js.map +1 -0
- package/dist/config/doc-sync.d.ts +66 -0
- package/dist/config/doc-sync.d.ts.map +1 -0
- package/dist/config/doc-sync.js +270 -0
- package/dist/config/doc-sync.js.map +1 -0
- package/dist/config/feature-audit.d.ts +49 -0
- package/dist/config/feature-audit.d.ts.map +1 -0
- package/dist/config/feature-audit.js +148 -0
- package/dist/config/feature-audit.js.map +1 -0
- package/dist/config/index.d.ts +15 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +15 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/init.d.ts +61 -0
- package/dist/config/init.d.ts.map +1 -0
- package/dist/config/init.js +376 -0
- package/dist/config/init.js.map +1 -0
- package/dist/config/legacy-fallback.d.ts +83 -0
- package/dist/config/legacy-fallback.d.ts.map +1 -0
- package/dist/config/legacy-fallback.js +212 -0
- package/dist/config/legacy-fallback.js.map +1 -0
- package/dist/config/markdown-migration.d.ts +157 -0
- package/dist/config/markdown-migration.d.ts.map +1 -0
- package/dist/config/markdown-migration.js +434 -0
- package/dist/config/markdown-migration.js.map +1 -0
- package/dist/config/migration.d.ts +123 -0
- package/dist/config/migration.d.ts.map +1 -0
- package/dist/config/migration.js +273 -0
- package/dist/config/migration.js.map +1 -0
- package/dist/config/migrations/index.d.ts +36 -0
- package/dist/config/migrations/index.d.ts.map +1 -0
- package/dist/config/migrations/index.js +216 -0
- package/dist/config/migrations/index.js.map +1 -0
- package/dist/config/models.d.ts +134 -0
- package/dist/config/models.d.ts.map +1 -0
- package/dist/config/models.js +354 -0
- package/dist/config/models.js.map +1 -0
- package/dist/config/routing.d.ts +118 -0
- package/dist/config/routing.d.ts.map +1 -0
- package/dist/config/routing.js +247 -0
- package/dist/config/routing.js.map +1 -0
- package/dist/config/schema.d.ts +72 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +63 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/coordinator/coordinator.d.ts +82 -0
- package/dist/coordinator/coordinator.d.ts.map +1 -0
- package/dist/coordinator/coordinator.js +192 -0
- package/dist/coordinator/coordinator.js.map +1 -0
- package/dist/coordinator/direct-response.d.ts +83 -0
- package/dist/coordinator/direct-response.d.ts.map +1 -0
- package/dist/coordinator/direct-response.js +187 -0
- package/dist/coordinator/direct-response.js.map +1 -0
- package/dist/coordinator/fan-out.d.ts +83 -0
- package/dist/coordinator/fan-out.d.ts.map +1 -0
- package/dist/coordinator/fan-out.js +161 -0
- package/dist/coordinator/fan-out.js.map +1 -0
- package/dist/coordinator/index.d.ts +62 -0
- package/dist/coordinator/index.d.ts.map +1 -0
- package/dist/coordinator/index.js +171 -0
- package/dist/coordinator/index.js.map +1 -0
- package/dist/coordinator/response-tiers.d.ts +49 -0
- package/dist/coordinator/response-tiers.d.ts.map +1 -0
- package/dist/coordinator/response-tiers.js +149 -0
- package/dist/coordinator/response-tiers.js.map +1 -0
- package/dist/hooks/index.d.ts +103 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +279 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/index.d.ts +33 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +33 -3
- package/dist/index.js.map +1 -1
- package/dist/marketplace/backend.d.ts +35 -0
- package/dist/marketplace/backend.d.ts.map +1 -0
- package/dist/marketplace/backend.js +99 -0
- package/dist/marketplace/backend.js.map +1 -0
- package/dist/marketplace/browser.d.ts +33 -0
- package/dist/marketplace/browser.d.ts.map +1 -0
- package/dist/marketplace/browser.js +97 -0
- package/dist/marketplace/browser.js.map +1 -0
- package/dist/marketplace/extension-adapter.d.ts +51 -0
- package/dist/marketplace/extension-adapter.d.ts.map +1 -0
- package/dist/marketplace/extension-adapter.js +81 -0
- package/dist/marketplace/extension-adapter.js.map +1 -0
- package/dist/marketplace/index.d.ts +51 -0
- package/dist/marketplace/index.d.ts.map +1 -0
- package/dist/marketplace/index.js +108 -0
- package/dist/marketplace/index.js.map +1 -0
- package/dist/marketplace/packaging.d.ts +25 -0
- package/dist/marketplace/packaging.d.ts.map +1 -0
- package/dist/marketplace/packaging.js +117 -0
- package/dist/marketplace/packaging.js.map +1 -0
- package/dist/marketplace/schema.d.ts +50 -0
- package/dist/marketplace/schema.d.ts.map +1 -0
- package/dist/marketplace/schema.js +120 -0
- package/dist/marketplace/schema.js.map +1 -0
- package/dist/marketplace/security.d.ts +26 -0
- package/dist/marketplace/security.d.ts.map +1 -0
- package/dist/marketplace/security.js +199 -0
- package/dist/marketplace/security.js.map +1 -0
- package/dist/parsers.d.ts +15 -0
- package/dist/parsers.d.ts.map +1 -0
- package/dist/parsers.js +15 -0
- package/dist/parsers.js.map +1 -0
- package/dist/ralph/index.d.ts +58 -0
- package/dist/ralph/index.d.ts.map +1 -0
- package/dist/ralph/index.js +128 -0
- package/dist/ralph/index.js.map +1 -0
- package/dist/resolution.d.ts +47 -0
- package/dist/resolution.d.ts.map +1 -0
- package/dist/resolution.js +106 -0
- package/dist/resolution.js.map +1 -0
- package/dist/runtime/benchmarks.d.ts +121 -0
- package/dist/runtime/benchmarks.d.ts.map +1 -0
- package/dist/runtime/benchmarks.js +251 -0
- package/dist/runtime/benchmarks.js.map +1 -0
- package/dist/runtime/config.d.ts +314 -0
- package/dist/runtime/config.d.ts.map +1 -0
- package/dist/runtime/config.js +467 -0
- package/dist/runtime/config.js.map +1 -0
- package/dist/runtime/constants.d.ts +35 -0
- package/dist/runtime/constants.d.ts.map +1 -0
- package/dist/runtime/constants.js +58 -0
- package/dist/runtime/constants.js.map +1 -0
- package/dist/runtime/cost-tracker.d.ts +73 -0
- package/dist/runtime/cost-tracker.d.ts.map +1 -0
- package/dist/runtime/cost-tracker.js +157 -0
- package/dist/runtime/cost-tracker.js.map +1 -0
- package/dist/runtime/event-bus-otel-bridge.d.ts +19 -0
- package/dist/runtime/event-bus-otel-bridge.d.ts.map +1 -0
- package/dist/runtime/event-bus-otel-bridge.js +61 -0
- package/dist/runtime/event-bus-otel-bridge.js.map +1 -0
- package/dist/runtime/event-bus-ws-bridge.d.ts +35 -0
- package/dist/runtime/event-bus-ws-bridge.d.ts.map +1 -0
- package/dist/runtime/event-bus-ws-bridge.js +55 -0
- package/dist/runtime/event-bus-ws-bridge.js.map +1 -0
- package/dist/runtime/event-bus.d.ts +190 -0
- package/dist/runtime/event-bus.d.ts.map +1 -0
- package/dist/runtime/event-bus.js +218 -0
- package/dist/runtime/event-bus.js.map +1 -0
- package/dist/runtime/event-payloads.d.ts +108 -0
- package/dist/runtime/event-payloads.d.ts.map +1 -0
- package/dist/runtime/event-payloads.js +28 -0
- package/dist/runtime/event-payloads.js.map +1 -0
- package/dist/runtime/health.d.ts +66 -0
- package/dist/runtime/health.d.ts.map +1 -0
- package/dist/runtime/health.js +112 -0
- package/dist/runtime/health.js.map +1 -0
- package/dist/runtime/i18n.d.ts +54 -0
- package/dist/runtime/i18n.d.ts.map +1 -0
- package/dist/runtime/i18n.js +126 -0
- package/dist/runtime/i18n.js.map +1 -0
- package/dist/runtime/offline.d.ts +64 -0
- package/dist/runtime/offline.d.ts.map +1 -0
- package/dist/runtime/offline.js +108 -0
- package/dist/runtime/offline.js.map +1 -0
- package/dist/runtime/otel-bridge.d.ts +52 -0
- package/dist/runtime/otel-bridge.d.ts.map +1 -0
- package/dist/runtime/otel-bridge.js +132 -0
- package/dist/runtime/otel-bridge.js.map +1 -0
- package/dist/runtime/otel-init.d.ts +72 -0
- package/dist/runtime/otel-init.d.ts.map +1 -0
- package/dist/runtime/otel-init.js +68 -0
- package/dist/runtime/otel-init.js.map +1 -0
- package/dist/runtime/otel-metrics.d.ts +42 -0
- package/dist/runtime/otel-metrics.d.ts.map +1 -0
- package/dist/runtime/otel-metrics.js +196 -0
- package/dist/runtime/otel-metrics.js.map +1 -0
- package/dist/runtime/otel.d.ts +53 -0
- package/dist/runtime/otel.d.ts.map +1 -0
- package/dist/runtime/otel.js +127 -0
- package/dist/runtime/otel.js.map +1 -0
- package/dist/runtime/squad-observer.d.ts +75 -0
- package/dist/runtime/squad-observer.d.ts.map +1 -0
- package/dist/runtime/squad-observer.js +190 -0
- package/dist/runtime/squad-observer.js.map +1 -0
- package/dist/runtime/streaming.d.ts +106 -0
- package/dist/runtime/streaming.d.ts.map +1 -0
- package/dist/runtime/streaming.js +192 -0
- package/dist/runtime/streaming.js.map +1 -0
- package/dist/runtime/telemetry.d.ts +82 -0
- package/dist/runtime/telemetry.d.ts.map +1 -0
- package/dist/runtime/telemetry.js +120 -0
- package/dist/runtime/telemetry.js.map +1 -0
- package/dist/sharing/agent-repo.d.ts +33 -0
- package/dist/sharing/agent-repo.d.ts.map +1 -0
- package/dist/sharing/agent-repo.js +79 -0
- package/dist/sharing/agent-repo.js.map +1 -0
- package/dist/sharing/cache.d.ts +36 -0
- package/dist/sharing/cache.d.ts.map +1 -0
- package/dist/sharing/cache.js +85 -0
- package/dist/sharing/cache.js.map +1 -0
- package/dist/sharing/conflicts.d.ts +32 -0
- package/dist/sharing/conflicts.d.ts.map +1 -0
- package/dist/sharing/conflicts.js +121 -0
- package/dist/sharing/conflicts.js.map +1 -0
- package/dist/sharing/export.d.ts +50 -0
- package/dist/sharing/export.d.ts.map +1 -0
- package/dist/sharing/export.js +156 -0
- package/dist/sharing/export.js.map +1 -0
- package/dist/sharing/history-split.d.ts +34 -0
- package/dist/sharing/history-split.d.ts.map +1 -0
- package/dist/sharing/history-split.js +101 -0
- package/dist/sharing/history-split.js.map +1 -0
- package/dist/sharing/import.d.ts +37 -0
- package/dist/sharing/import.d.ts.map +1 -0
- package/dist/sharing/import.js +138 -0
- package/dist/sharing/import.js.map +1 -0
- package/dist/sharing/index.d.ts +11 -0
- package/dist/sharing/index.d.ts.map +1 -0
- package/dist/sharing/index.js +11 -0
- package/dist/sharing/index.js.map +1 -0
- package/dist/sharing/versioning.d.ts +32 -0
- package/dist/sharing/versioning.d.ts.map +1 -0
- package/dist/sharing/versioning.js +64 -0
- package/dist/sharing/versioning.js.map +1 -0
- package/dist/skills/index.d.ts +49 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +85 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/skill-loader.d.ts +56 -0
- package/dist/skills/skill-loader.d.ts.map +1 -0
- package/dist/skills/skill-loader.js +106 -0
- package/dist/skills/skill-loader.js.map +1 -0
- package/dist/skills/skill-source.d.ts +63 -0
- package/dist/skills/skill-source.d.ts.map +1 -0
- package/dist/skills/skill-source.js +199 -0
- package/dist/skills/skill-source.js.map +1 -0
- package/dist/tools/index.d.ts +95 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +475 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/types.d.ts +43 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/upstream/index.d.ts +8 -0
- package/dist/upstream/index.d.ts.map +1 -0
- package/dist/upstream/index.js +7 -0
- package/dist/upstream/index.js.map +1 -0
- package/dist/upstream/resolver.d.ts +37 -0
- package/dist/upstream/resolver.d.ts.map +1 -0
- package/dist/upstream/resolver.js +234 -0
- package/dist/upstream/resolver.js.map +1 -0
- package/dist/upstream/types.d.ts +55 -0
- package/dist/upstream/types.d.ts.map +1 -0
- package/dist/upstream/types.js +11 -0
- package/dist/upstream/types.js.map +1 -0
- package/dist/utils/normalize-eol.d.ts +6 -0
- package/dist/utils/normalize-eol.d.ts.map +1 -0
- package/dist/utils/normalize-eol.js +8 -0
- package/dist/utils/normalize-eol.js.map +1 -0
- package/package.json +197 -63
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Squad Observer — File watcher for .squad/ directory changes (Issue #268)
|
|
3
|
+
*
|
|
4
|
+
* Monitors the .squad/ directory for file changes and emits OTel spans
|
|
5
|
+
* and EventBus events for real-time observability of squad state changes.
|
|
6
|
+
* Ported from paulyuk/squad#1.
|
|
7
|
+
*
|
|
8
|
+
* @module runtime/squad-observer
|
|
9
|
+
*/
|
|
10
|
+
import fs from 'node:fs';
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
import { SpanStatusCode } from '@opentelemetry/api';
|
|
13
|
+
import { getTracer } from './otel.js';
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// Category classification
|
|
16
|
+
// ============================================================================
|
|
17
|
+
/**
|
|
18
|
+
* Classify a file path within .squad/ into a category.
|
|
19
|
+
*/
|
|
20
|
+
export function classifyFile(relativePath) {
|
|
21
|
+
const normalized = relativePath.replace(/\\/g, '/');
|
|
22
|
+
if (normalized.startsWith('agents/'))
|
|
23
|
+
return 'agent';
|
|
24
|
+
if (normalized.startsWith('casting/'))
|
|
25
|
+
return 'casting';
|
|
26
|
+
if (normalized.startsWith('skills/'))
|
|
27
|
+
return 'skill';
|
|
28
|
+
if (normalized.startsWith('decisions/') || normalized === 'decisions.md')
|
|
29
|
+
return 'decision';
|
|
30
|
+
if (normalized === 'config.json' || normalized === 'team.md' || normalized.startsWith('config/'))
|
|
31
|
+
return 'config';
|
|
32
|
+
return 'unknown';
|
|
33
|
+
}
|
|
34
|
+
// ============================================================================
|
|
35
|
+
// Observer implementation
|
|
36
|
+
// ============================================================================
|
|
37
|
+
/**
|
|
38
|
+
* File watcher that monitors .squad/ directory and emits OTel events.
|
|
39
|
+
*
|
|
40
|
+
* Usage:
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const observer = new SquadObserver({
|
|
43
|
+
* squadDir: '/path/to/.squad',
|
|
44
|
+
* eventBus: myEventBus,
|
|
45
|
+
* });
|
|
46
|
+
* observer.start();
|
|
47
|
+
* // ... later
|
|
48
|
+
* observer.stop();
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export class SquadObserver {
|
|
52
|
+
config;
|
|
53
|
+
watcher;
|
|
54
|
+
debounceTimers = new Map();
|
|
55
|
+
running = false;
|
|
56
|
+
constructor(config) {
|
|
57
|
+
this.config = {
|
|
58
|
+
squadDir: config.squadDir,
|
|
59
|
+
eventBus: config.eventBus,
|
|
60
|
+
debounceMs: config.debounceMs ?? 200,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Start watching the .squad/ directory for changes.
|
|
65
|
+
* Emits OTel spans and EventBus events for each detected change.
|
|
66
|
+
*/
|
|
67
|
+
start() {
|
|
68
|
+
if (this.running)
|
|
69
|
+
return;
|
|
70
|
+
if (!fs.existsSync(this.config.squadDir)) {
|
|
71
|
+
throw new Error(`Squad directory not found: ${this.config.squadDir}`);
|
|
72
|
+
}
|
|
73
|
+
const tracer = getTracer('squad-observer');
|
|
74
|
+
const span = tracer.startSpan('squad.observer.start', {
|
|
75
|
+
attributes: {
|
|
76
|
+
'squad.dir': this.config.squadDir,
|
|
77
|
+
'debounce_ms': this.config.debounceMs,
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
try {
|
|
81
|
+
this.watcher = fs.watch(this.config.squadDir, { recursive: true }, (eventType, filename) => {
|
|
82
|
+
if (!filename)
|
|
83
|
+
return;
|
|
84
|
+
this.handleChange(eventType, filename);
|
|
85
|
+
});
|
|
86
|
+
this.watcher.on('error', (err) => {
|
|
87
|
+
const errSpan = tracer.startSpan('squad.observer.error', {
|
|
88
|
+
attributes: { 'error.message': err.message },
|
|
89
|
+
});
|
|
90
|
+
errSpan.setStatus({ code: SpanStatusCode.ERROR, message: err.message });
|
|
91
|
+
errSpan.recordException(err);
|
|
92
|
+
errSpan.end();
|
|
93
|
+
});
|
|
94
|
+
this.running = true;
|
|
95
|
+
span.end();
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
99
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
100
|
+
span.recordException(error);
|
|
101
|
+
span.end();
|
|
102
|
+
throw err;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Stop watching and clean up.
|
|
107
|
+
*/
|
|
108
|
+
stop() {
|
|
109
|
+
if (!this.running)
|
|
110
|
+
return;
|
|
111
|
+
const tracer = getTracer('squad-observer');
|
|
112
|
+
const span = tracer.startSpan('squad.observer.stop');
|
|
113
|
+
// Clear all pending debounce timers
|
|
114
|
+
for (const timer of this.debounceTimers.values()) {
|
|
115
|
+
clearTimeout(timer);
|
|
116
|
+
}
|
|
117
|
+
this.debounceTimers.clear();
|
|
118
|
+
this.watcher?.close();
|
|
119
|
+
this.watcher = undefined;
|
|
120
|
+
this.running = false;
|
|
121
|
+
span.end();
|
|
122
|
+
}
|
|
123
|
+
/** Whether the observer is currently running. */
|
|
124
|
+
get isRunning() {
|
|
125
|
+
return this.running;
|
|
126
|
+
}
|
|
127
|
+
// --------------------------------------------------------------------------
|
|
128
|
+
// Internal
|
|
129
|
+
// --------------------------------------------------------------------------
|
|
130
|
+
handleChange(eventType, filename) {
|
|
131
|
+
// Debounce rapid changes to the same file
|
|
132
|
+
const existing = this.debounceTimers.get(filename);
|
|
133
|
+
if (existing)
|
|
134
|
+
clearTimeout(existing);
|
|
135
|
+
this.debounceTimers.set(filename, setTimeout(() => {
|
|
136
|
+
this.debounceTimers.delete(filename);
|
|
137
|
+
this.processChange(filename);
|
|
138
|
+
}, this.config.debounceMs));
|
|
139
|
+
}
|
|
140
|
+
processChange(filename) {
|
|
141
|
+
const absolutePath = path.join(this.config.squadDir, filename);
|
|
142
|
+
const category = classifyFile(filename);
|
|
143
|
+
const exists = fs.existsSync(absolutePath);
|
|
144
|
+
// Determine change type — basic heuristic since fs.watch doesn't tell us
|
|
145
|
+
const changeType = exists ? 'modified' : 'deleted';
|
|
146
|
+
const change = {
|
|
147
|
+
relativePath: filename,
|
|
148
|
+
absolutePath,
|
|
149
|
+
changeType,
|
|
150
|
+
category,
|
|
151
|
+
timestamp: new Date(),
|
|
152
|
+
};
|
|
153
|
+
// Emit OTel span
|
|
154
|
+
this.emitSpan(change);
|
|
155
|
+
// Emit EventBus event
|
|
156
|
+
if (this.config.eventBus) {
|
|
157
|
+
this.emitEvent(change);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
emitSpan(change) {
|
|
161
|
+
const tracer = getTracer('squad-observer');
|
|
162
|
+
const span = tracer.startSpan('squad.observer.file_change', {
|
|
163
|
+
attributes: {
|
|
164
|
+
'file.path': change.relativePath,
|
|
165
|
+
'file.category': change.category,
|
|
166
|
+
'change.type': change.changeType,
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
span.end();
|
|
170
|
+
}
|
|
171
|
+
emitEvent(change) {
|
|
172
|
+
if (!this.config.eventBus)
|
|
173
|
+
return;
|
|
174
|
+
// Map file categories to appropriate event types
|
|
175
|
+
const event = {
|
|
176
|
+
type: 'agent:milestone',
|
|
177
|
+
agentName: change.category === 'agent' ? path.basename(path.dirname(change.relativePath)) : undefined,
|
|
178
|
+
payload: {
|
|
179
|
+
action: 'file_change',
|
|
180
|
+
file: change.relativePath,
|
|
181
|
+
category: change.category,
|
|
182
|
+
changeType: change.changeType,
|
|
183
|
+
},
|
|
184
|
+
timestamp: change.timestamp,
|
|
185
|
+
};
|
|
186
|
+
// Fire and forget — errors handled by EventBus
|
|
187
|
+
void this.config.eventBus.emit(event);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=squad-observer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"squad-observer.js","sourceRoot":"","sources":["../../src/runtime/squad-observer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Streaming Event Pipeline
|
|
3
|
+
*
|
|
4
|
+
* Processes streaming events from Copilot SDK sessions including message deltas,
|
|
5
|
+
* reasoning deltas, and usage/cost tracking.
|
|
6
|
+
*
|
|
7
|
+
* @module runtime/streaming
|
|
8
|
+
*/
|
|
9
|
+
/** A chunk of assistant message content. */
|
|
10
|
+
export interface StreamDelta {
|
|
11
|
+
type: 'message_delta';
|
|
12
|
+
sessionId: string;
|
|
13
|
+
agentName?: string;
|
|
14
|
+
content: string;
|
|
15
|
+
/** Monotonically increasing index within the message. */
|
|
16
|
+
index: number;
|
|
17
|
+
timestamp: Date;
|
|
18
|
+
}
|
|
19
|
+
/** Token usage and cost data for a completed turn. */
|
|
20
|
+
export interface UsageEvent {
|
|
21
|
+
type: 'usage';
|
|
22
|
+
sessionId: string;
|
|
23
|
+
agentName?: string;
|
|
24
|
+
model: string;
|
|
25
|
+
inputTokens: number;
|
|
26
|
+
outputTokens: number;
|
|
27
|
+
/** Estimated cost in USD (may be 0 if pricing unavailable). */
|
|
28
|
+
estimatedCost: number;
|
|
29
|
+
timestamp: Date;
|
|
30
|
+
}
|
|
31
|
+
/** A chunk of model reasoning/thinking content. */
|
|
32
|
+
export interface ReasoningDelta {
|
|
33
|
+
type: 'reasoning_delta';
|
|
34
|
+
sessionId: string;
|
|
35
|
+
agentName?: string;
|
|
36
|
+
content: string;
|
|
37
|
+
index: number;
|
|
38
|
+
timestamp: Date;
|
|
39
|
+
}
|
|
40
|
+
/** Union of all streaming event types. */
|
|
41
|
+
export type StreamingEvent = StreamDelta | UsageEvent | ReasoningDelta;
|
|
42
|
+
export type DeltaHandler = (event: StreamDelta) => void | Promise<void>;
|
|
43
|
+
export type UsageHandler = (event: UsageEvent) => void | Promise<void>;
|
|
44
|
+
export type ReasoningHandler = (event: ReasoningDelta) => void | Promise<void>;
|
|
45
|
+
export interface UsageSummary {
|
|
46
|
+
totalInputTokens: number;
|
|
47
|
+
totalOutputTokens: number;
|
|
48
|
+
estimatedCost: number;
|
|
49
|
+
byAgent: Map<string, AgentUsage>;
|
|
50
|
+
}
|
|
51
|
+
export interface AgentUsage {
|
|
52
|
+
inputTokens: number;
|
|
53
|
+
outputTokens: number;
|
|
54
|
+
estimatedCost: number;
|
|
55
|
+
model: string;
|
|
56
|
+
turnCount: number;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Processes streaming events from SDK sessions.
|
|
60
|
+
*
|
|
61
|
+
* Allows registration of handlers for message deltas, reasoning deltas,
|
|
62
|
+
* and usage events. Aggregates token counts across all active sessions.
|
|
63
|
+
*/
|
|
64
|
+
export declare class StreamingPipeline {
|
|
65
|
+
private deltaHandlers;
|
|
66
|
+
private usageHandlers;
|
|
67
|
+
private reasoningHandlers;
|
|
68
|
+
private attachedSessions;
|
|
69
|
+
private usageData;
|
|
70
|
+
/** Per-session message start timestamps for latency tracking. */
|
|
71
|
+
private messageStartTimes;
|
|
72
|
+
/** Per-session flag tracking whether first token has been recorded. */
|
|
73
|
+
private firstTokenRecorded;
|
|
74
|
+
/** Register a handler for message deltas. */
|
|
75
|
+
onDelta(handler: DeltaHandler): () => void;
|
|
76
|
+
/** Register a handler for token usage/cost data. */
|
|
77
|
+
onUsage(handler: UsageHandler): () => void;
|
|
78
|
+
/** Register a handler for reasoning deltas. */
|
|
79
|
+
onReasoning(handler: ReasoningHandler): () => void;
|
|
80
|
+
/**
|
|
81
|
+
* Mark the start of a new message for a session.
|
|
82
|
+
* Call this before sending a message to enable TTFT and duration tracking.
|
|
83
|
+
*/
|
|
84
|
+
markMessageStart(sessionId: string): void;
|
|
85
|
+
/** Wire up handlers to a session's event stream. */
|
|
86
|
+
attachToSession(sessionId: string): void;
|
|
87
|
+
/** Clean up handlers for a session. */
|
|
88
|
+
detachFromSession(sessionId: string): void;
|
|
89
|
+
/** Check whether a session is currently attached. */
|
|
90
|
+
isAttached(sessionId: string): boolean;
|
|
91
|
+
/** Returns all currently attached session IDs. */
|
|
92
|
+
getAttachedSessions(): ReadonlySet<string>;
|
|
93
|
+
/**
|
|
94
|
+
* Process an incoming streaming event.
|
|
95
|
+
* Dispatches to the correct set of handlers based on event type.
|
|
96
|
+
*/
|
|
97
|
+
processEvent(event: StreamingEvent): Promise<void>;
|
|
98
|
+
/** Aggregate token counts and cost across all sessions. */
|
|
99
|
+
getUsageSummary(): UsageSummary;
|
|
100
|
+
/** Remove all handlers and detach all sessions. */
|
|
101
|
+
clear(): void;
|
|
102
|
+
private dispatchDelta;
|
|
103
|
+
private dispatchUsage;
|
|
104
|
+
private dispatchReasoning;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=streaming.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["../../src/runtime/streaming.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Streaming Event Pipeline
|
|
3
|
+
*
|
|
4
|
+
* Processes streaming events from Copilot SDK sessions including message deltas,
|
|
5
|
+
* reasoning deltas, and usage/cost tracking.
|
|
6
|
+
*
|
|
7
|
+
* @module runtime/streaming
|
|
8
|
+
*/
|
|
9
|
+
import { recordTokenUsage, recordTimeToFirstToken, recordResponseDuration, recordTokensPerSecond, } from './otel-metrics.js';
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// StreamingPipeline
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* Processes streaming events from SDK sessions.
|
|
15
|
+
*
|
|
16
|
+
* Allows registration of handlers for message deltas, reasoning deltas,
|
|
17
|
+
* and usage events. Aggregates token counts across all active sessions.
|
|
18
|
+
*/
|
|
19
|
+
export class StreamingPipeline {
|
|
20
|
+
deltaHandlers = new Set();
|
|
21
|
+
usageHandlers = new Set();
|
|
22
|
+
reasoningHandlers = new Set();
|
|
23
|
+
attachedSessions = new Set();
|
|
24
|
+
usageData = [];
|
|
25
|
+
/** Per-session message start timestamps for latency tracking. */
|
|
26
|
+
messageStartTimes = new Map();
|
|
27
|
+
/** Per-session flag tracking whether first token has been recorded. */
|
|
28
|
+
firstTokenRecorded = new Map();
|
|
29
|
+
/** Register a handler for message deltas. */
|
|
30
|
+
onDelta(handler) {
|
|
31
|
+
this.deltaHandlers.add(handler);
|
|
32
|
+
return () => this.deltaHandlers.delete(handler);
|
|
33
|
+
}
|
|
34
|
+
/** Register a handler for token usage/cost data. */
|
|
35
|
+
onUsage(handler) {
|
|
36
|
+
this.usageHandlers.add(handler);
|
|
37
|
+
return () => this.usageHandlers.delete(handler);
|
|
38
|
+
}
|
|
39
|
+
/** Register a handler for reasoning deltas. */
|
|
40
|
+
onReasoning(handler) {
|
|
41
|
+
this.reasoningHandlers.add(handler);
|
|
42
|
+
return () => this.reasoningHandlers.delete(handler);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Mark the start of a new message for a session.
|
|
46
|
+
* Call this before sending a message to enable TTFT and duration tracking.
|
|
47
|
+
*/
|
|
48
|
+
markMessageStart(sessionId) {
|
|
49
|
+
this.messageStartTimes.set(sessionId, Date.now());
|
|
50
|
+
this.firstTokenRecorded.set(sessionId, false);
|
|
51
|
+
}
|
|
52
|
+
/** Wire up handlers to a session's event stream. */
|
|
53
|
+
attachToSession(sessionId) {
|
|
54
|
+
if (this.attachedSessions.has(sessionId)) {
|
|
55
|
+
throw new Error(`Session ${sessionId} is already attached`);
|
|
56
|
+
}
|
|
57
|
+
this.attachedSessions.add(sessionId);
|
|
58
|
+
}
|
|
59
|
+
/** Clean up handlers for a session. */
|
|
60
|
+
detachFromSession(sessionId) {
|
|
61
|
+
this.attachedSessions.delete(sessionId);
|
|
62
|
+
}
|
|
63
|
+
/** Check whether a session is currently attached. */
|
|
64
|
+
isAttached(sessionId) {
|
|
65
|
+
return this.attachedSessions.has(sessionId);
|
|
66
|
+
}
|
|
67
|
+
/** Returns all currently attached session IDs. */
|
|
68
|
+
getAttachedSessions() {
|
|
69
|
+
return this.attachedSessions;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Process an incoming streaming event.
|
|
73
|
+
* Dispatches to the correct set of handlers based on event type.
|
|
74
|
+
*/
|
|
75
|
+
async processEvent(event) {
|
|
76
|
+
if (!this.attachedSessions.has(event.sessionId)) {
|
|
77
|
+
return; // Ignore events from unattached sessions
|
|
78
|
+
}
|
|
79
|
+
switch (event.type) {
|
|
80
|
+
case 'message_delta':
|
|
81
|
+
// Record TTFT on first delta (index === 0) for this message
|
|
82
|
+
if (event.index === 0 && !this.firstTokenRecorded.get(event.sessionId)) {
|
|
83
|
+
this.firstTokenRecorded.set(event.sessionId, true);
|
|
84
|
+
const startTime = this.messageStartTimes.get(event.sessionId);
|
|
85
|
+
if (startTime !== undefined) {
|
|
86
|
+
recordTimeToFirstToken(Date.now() - startTime);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
await this.dispatchDelta(event);
|
|
90
|
+
break;
|
|
91
|
+
case 'usage': {
|
|
92
|
+
this.usageData.push(event);
|
|
93
|
+
await this.dispatchUsage(event);
|
|
94
|
+
recordTokenUsage(event);
|
|
95
|
+
// Record response duration and tokens/sec when usage arrives
|
|
96
|
+
const msgStart = this.messageStartTimes.get(event.sessionId);
|
|
97
|
+
if (msgStart !== undefined) {
|
|
98
|
+
const durationMs = Date.now() - msgStart;
|
|
99
|
+
recordResponseDuration(durationMs);
|
|
100
|
+
if (durationMs > 0 && event.outputTokens > 0) {
|
|
101
|
+
recordTokensPerSecond((event.outputTokens / durationMs) * 1000);
|
|
102
|
+
}
|
|
103
|
+
this.messageStartTimes.delete(event.sessionId);
|
|
104
|
+
this.firstTokenRecorded.delete(event.sessionId);
|
|
105
|
+
}
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
case 'reasoning_delta':
|
|
109
|
+
await this.dispatchReasoning(event);
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/** Aggregate token counts and cost across all sessions. */
|
|
114
|
+
getUsageSummary() {
|
|
115
|
+
const byAgent = new Map();
|
|
116
|
+
let totalInputTokens = 0;
|
|
117
|
+
let totalOutputTokens = 0;
|
|
118
|
+
let estimatedCost = 0;
|
|
119
|
+
for (const event of this.usageData) {
|
|
120
|
+
totalInputTokens += event.inputTokens;
|
|
121
|
+
totalOutputTokens += event.outputTokens;
|
|
122
|
+
estimatedCost += event.estimatedCost;
|
|
123
|
+
const agentKey = event.agentName ?? 'unknown';
|
|
124
|
+
const existing = byAgent.get(agentKey);
|
|
125
|
+
if (existing) {
|
|
126
|
+
existing.inputTokens += event.inputTokens;
|
|
127
|
+
existing.outputTokens += event.outputTokens;
|
|
128
|
+
existing.estimatedCost += event.estimatedCost;
|
|
129
|
+
existing.turnCount += 1;
|
|
130
|
+
existing.model = event.model; // keep latest model
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
byAgent.set(agentKey, {
|
|
134
|
+
inputTokens: event.inputTokens,
|
|
135
|
+
outputTokens: event.outputTokens,
|
|
136
|
+
estimatedCost: event.estimatedCost,
|
|
137
|
+
model: event.model,
|
|
138
|
+
turnCount: 1,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return { totalInputTokens, totalOutputTokens, estimatedCost, byAgent };
|
|
143
|
+
}
|
|
144
|
+
/** Remove all handlers and detach all sessions. */
|
|
145
|
+
clear() {
|
|
146
|
+
this.deltaHandlers.clear();
|
|
147
|
+
this.usageHandlers.clear();
|
|
148
|
+
this.reasoningHandlers.clear();
|
|
149
|
+
this.attachedSessions.clear();
|
|
150
|
+
this.usageData = [];
|
|
151
|
+
this.messageStartTimes.clear();
|
|
152
|
+
this.firstTokenRecorded.clear();
|
|
153
|
+
}
|
|
154
|
+
// ---------- Private ----------
|
|
155
|
+
async dispatchDelta(event) {
|
|
156
|
+
for (const handler of this.deltaHandlers) {
|
|
157
|
+
try {
|
|
158
|
+
const result = handler(event);
|
|
159
|
+
if (result instanceof Promise)
|
|
160
|
+
await result;
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
// Isolate handler errors
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
async dispatchUsage(event) {
|
|
168
|
+
for (const handler of this.usageHandlers) {
|
|
169
|
+
try {
|
|
170
|
+
const result = handler(event);
|
|
171
|
+
if (result instanceof Promise)
|
|
172
|
+
await result;
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
// Isolate handler errors
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
async dispatchReasoning(event) {
|
|
180
|
+
for (const handler of this.reasoningHandlers) {
|
|
181
|
+
try {
|
|
182
|
+
const result = handler(event);
|
|
183
|
+
if (result instanceof Promise)
|
|
184
|
+
await result;
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
// Isolate handler errors
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=streaming.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streaming.js","sourceRoot":"","sources":["../../src/runtime/streaming.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telemetry & Update Notifications (M4-7, Issue #108)
|
|
3
|
+
*
|
|
4
|
+
* Privacy-first, opt-in telemetry collection for Squad.
|
|
5
|
+
* No PII, no code content — only aggregate usage metrics.
|
|
6
|
+
*
|
|
7
|
+
* @module runtime/telemetry
|
|
8
|
+
*/
|
|
9
|
+
/** Recognised telemetry event names. */
|
|
10
|
+
export type TelemetryEventName = 'squad.init' | 'squad.run' | 'squad.agent.spawn' | 'squad.error' | 'squad.upgrade';
|
|
11
|
+
/** A single telemetry event. */
|
|
12
|
+
export interface TelemetryEvent {
|
|
13
|
+
/** Event name */
|
|
14
|
+
name: TelemetryEventName;
|
|
15
|
+
/** Arbitrary metadata (must not contain PII or code) */
|
|
16
|
+
properties?: Record<string, string | number | boolean>;
|
|
17
|
+
/** Timestamp (defaults to Date.now()) */
|
|
18
|
+
timestamp?: number;
|
|
19
|
+
}
|
|
20
|
+
/** Configuration for telemetry. */
|
|
21
|
+
export interface TelemetryConfig {
|
|
22
|
+
/** Master switch — disabled by default */
|
|
23
|
+
enabled: boolean;
|
|
24
|
+
/** HTTP endpoint for flushing events */
|
|
25
|
+
endpoint?: string;
|
|
26
|
+
/** Whether to strip identifying data even from properties */
|
|
27
|
+
anonymize?: boolean;
|
|
28
|
+
/** Event names to exclude from collection */
|
|
29
|
+
excludeEvents?: TelemetryEventName[];
|
|
30
|
+
}
|
|
31
|
+
/** Pluggable transport — how events are actually sent. */
|
|
32
|
+
export type TelemetryTransport = (events: TelemetryEvent[], endpoint: string) => Promise<void>;
|
|
33
|
+
/** Register a custom transport for flushing events. */
|
|
34
|
+
export declare function setTelemetryTransport(fn: TelemetryTransport): void;
|
|
35
|
+
/**
|
|
36
|
+
* Opt-in, privacy-respecting telemetry collector.
|
|
37
|
+
*
|
|
38
|
+
* Events are queued in memory and only sent when `flush()` is called.
|
|
39
|
+
* The collector respects the consent flag and never transmits when disabled.
|
|
40
|
+
*
|
|
41
|
+
* ```ts
|
|
42
|
+
* const telemetry = new TelemetryCollector({ enabled: false });
|
|
43
|
+
* telemetry.setConsent(true);
|
|
44
|
+
* telemetry.collectEvent({ name: 'squad.init' });
|
|
45
|
+
* await telemetry.flush();
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare class TelemetryCollector {
|
|
49
|
+
private queue;
|
|
50
|
+
private config;
|
|
51
|
+
constructor(config?: Partial<TelemetryConfig>);
|
|
52
|
+
/** Returns the current consent (enabled) status. */
|
|
53
|
+
getConsentStatus(): boolean;
|
|
54
|
+
/** Set consent status. When false, collectEvent becomes a no-op. */
|
|
55
|
+
setConsent(enabled: boolean): void;
|
|
56
|
+
/**
|
|
57
|
+
* Queue a telemetry event.
|
|
58
|
+
*
|
|
59
|
+
* Does nothing when consent is not given or the event name is excluded.
|
|
60
|
+
*/
|
|
61
|
+
collectEvent(event: TelemetryEvent): void;
|
|
62
|
+
/**
|
|
63
|
+
* Send all queued events via the configured transport, then clear the queue.
|
|
64
|
+
* Returns the number of events flushed.
|
|
65
|
+
*/
|
|
66
|
+
flush(): Promise<number>;
|
|
67
|
+
/** Return the number of queued (unflushed) events. */
|
|
68
|
+
get pendingCount(): number;
|
|
69
|
+
/** Discard all queued events without sending. */
|
|
70
|
+
drain(): void;
|
|
71
|
+
/** Return a copy of the current config. */
|
|
72
|
+
getConfig(): Readonly<TelemetryConfig>;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Decide whether the user should be notified about available updates.
|
|
76
|
+
*
|
|
77
|
+
* @param lastCheck - Timestamp of the last update check
|
|
78
|
+
* @param intervalMs - Minimum milliseconds between notifications
|
|
79
|
+
* @returns true if enough time has elapsed since the last check
|
|
80
|
+
*/
|
|
81
|
+
export declare function shouldNotifyUpdate(lastCheck: Date, intervalMs: number): boolean;
|
|
82
|
+
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/runtime/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,wCAAwC;AACxC,MAAM,MAAM,kBAAkB,GAC1B,YAAY,GACZ,WAAW,GACX,mBAAmB,GACnB,aAAa,GACb,eAAe,CAAC;AAEpB,gCAAgC;AAChC,MAAM,WAAW,cAAc;IAC7B,iBAAiB;IACjB,IAAI,EAAE,kBAAkB,CAAC;IACzB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IACvD,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,mCAAmC;AACnC,MAAM,WAAW,eAAe;IAC9B,0CAA0C;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,6CAA6C;IAC7C,aAAa,CAAC,EAAE,kBAAkB,EAAE,CAAC;CACtC;AAED,0DAA0D;AAC1D,MAAM,MAAM,kBAAkB,GAAG,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAU/F,uDAAuD;AACvD,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,kBAAkB,GAAG,IAAI,CAElE;AAMD;;;;;;;;;;;;GAYG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,KAAK,CAAwB;IACrC,OAAO,CAAC,MAAM,CAAkB;gBAEpB,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC;IAc7C,oDAAoD;IACpD,gBAAgB,IAAI,OAAO;IAI3B,oEAAoE;IACpE,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAQlC;;;;OAIG;IACH,YAAY,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI;IAgBzC;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAW9B,sDAAsD;IACtD,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,iDAAiD;IACjD,KAAK,IAAI,IAAI;IAIb,2CAA2C;IAC3C,SAAS,IAAI,QAAQ,CAAC,eAAe,CAAC;CAGvC;AAMD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAG/E"}
|