feat: Add intelligent auto-router and enhanced integrations
- Add intelligent-router.sh hook for automatic agent routing - Add AUTO-TRIGGER-SUMMARY.md documentation - Add FINAL-INTEGRATION-SUMMARY.md documentation - Complete Prometheus integration (6 commands + 4 tools) - Complete Dexto integration (12 commands + 5 tools) - Enhanced Ralph with access to all agents - Fix /clawd command (removed disable-model-invocation) - Update hooks.json to v5 with intelligent routing - 291 total skills now available - All 21 commands with automatic routing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
232
dexto/packages/analytics/CHANGELOG.md
Normal file
232
dexto/packages/analytics/CHANGELOG.md
Normal file
@@ -0,0 +1,232 @@
|
||||
# @dexto/analytics
|
||||
|
||||
## 1.5.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 042f4f0: ### CLI Improvements
|
||||
- Add `/export` command to export conversations as Markdown or JSON
|
||||
- Add `Ctrl+T` toggle for task list visibility during processing
|
||||
- Improve task list UI with collapsible view near the processing message
|
||||
- Fix race condition causing duplicate rendering (mainly visible with explore tool)
|
||||
- Don't truncate `pattern` and `question` args in tool output display
|
||||
|
||||
### Bug Fixes
|
||||
- Fix build script to preserve `.dexto` storage (conversations, logs) during clean builds
|
||||
- Fix `@dexto/tools-todo` versioning - add to fixed version group in changeset config
|
||||
|
||||
### Configuration Changes
|
||||
- Remove approval timeout defaults - now waits indefinitely (better UX for CLI)
|
||||
- Add package versioning guidelines to AGENTS.md
|
||||
|
||||
- Updated dependencies [042f4f0]
|
||||
- @dexto/agent-management@1.5.6
|
||||
- @dexto/core@1.5.6
|
||||
|
||||
## 1.5.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [63fa083]
|
||||
- Updated dependencies [6df3ca9]
|
||||
- @dexto/core@1.5.5
|
||||
- @dexto/agent-management@1.5.5
|
||||
|
||||
## 1.5.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 499b890: Fix model override persistence after compaction and improve context token tracking
|
||||
|
||||
**Bug Fixes:**
|
||||
- Fix model override resetting to config model after compaction (now respects session overrides)
|
||||
|
||||
**Context Tracking Improvements:**
|
||||
- New algorithm uses actual `input_tokens` and `output_tokens` from LLM responses as source of truth
|
||||
- Self-correcting estimates: inaccuracies auto-correct when next LLM response arrives
|
||||
- Handles pruning automatically (next response's input_tokens reflects pruned state)
|
||||
- `/context` and compaction decisions now share common calculation logic
|
||||
- Removed `outputBuffer` concept in favor of single configurable threshold
|
||||
- Default compaction threshold lowered to 90%
|
||||
|
||||
**New `/context` Command:**
|
||||
- Interactive overlay with stacked token bar visualization
|
||||
- Breakdown by component: system prompt, tools, messages, free space, auto-compact buffer
|
||||
- Expandable per-tool token details
|
||||
- Shows pruned tool count and compaction history
|
||||
|
||||
**Observability:**
|
||||
- Comparison logging between estimated vs actual tokens for calibration
|
||||
- `dexto_llm_tokens_consumed` metric now includes estimated input tokens and accuracy metrics
|
||||
|
||||
- Updated dependencies [0016cd3]
|
||||
- Updated dependencies [499b890]
|
||||
- Updated dependencies [aa2c9a0]
|
||||
- @dexto/core@1.5.4
|
||||
- @dexto/agent-management@1.5.4
|
||||
|
||||
## 1.5.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [4f00295]
|
||||
- Updated dependencies [69c944c]
|
||||
- @dexto/agent-management@1.5.3
|
||||
- @dexto/core@1.5.3
|
||||
|
||||
## 1.5.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91acb03]
|
||||
- Updated dependencies [8a85ea4]
|
||||
- Updated dependencies [527f3f9]
|
||||
- @dexto/agent-management@1.5.2
|
||||
- @dexto/core@1.5.2
|
||||
|
||||
## 1.5.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a25d3ee]
|
||||
- Updated dependencies [bfcc7b1]
|
||||
- Updated dependencies [4aabdb7]
|
||||
- @dexto/agent-management@1.5.1
|
||||
- @dexto/core@1.5.1
|
||||
|
||||
## 1.5.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- e7722e5: Minor version bump for new release with bundler, custom tool pkgs, etc.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- abfe5ce: Update and standardize analytics for CLI and web UI
|
||||
- Updated dependencies [ee12727]
|
||||
- Updated dependencies [1e7e974]
|
||||
- Updated dependencies [4c05310]
|
||||
- Updated dependencies [5fa79fa]
|
||||
- Updated dependencies [ef40e60]
|
||||
- Updated dependencies [e714418]
|
||||
- Updated dependencies [e7722e5]
|
||||
- Updated dependencies [7d5ab19]
|
||||
- Updated dependencies [436a900]
|
||||
- @dexto/agent-management@1.5.0
|
||||
- @dexto/core@1.5.0
|
||||
|
||||
## 1.4.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [bd5c097]
|
||||
- Updated dependencies [7a64414]
|
||||
- Updated dependencies [3cdce89]
|
||||
- Updated dependencies [d640e40]
|
||||
- Updated dependencies [6f5627d]
|
||||
- Updated dependencies [6e6a3e7]
|
||||
- Updated dependencies [f73a519]
|
||||
- Updated dependencies [c54760f]
|
||||
- Updated dependencies [ab47df8]
|
||||
- Updated dependencies [3b4b919]
|
||||
- @dexto/core@1.4.0
|
||||
- @dexto/agent-management@1.4.0
|
||||
|
||||
## 1.3.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e2f770b]
|
||||
- Updated dependencies [f843b62]
|
||||
- Updated dependencies [eb266af]
|
||||
- @dexto/core@1.3.0
|
||||
- @dexto/agent-management@1.3.0
|
||||
|
||||
## 1.2.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [7feb030]
|
||||
- @dexto/core@1.2.6
|
||||
- @dexto/agent-management@1.2.6
|
||||
|
||||
## 1.2.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 5e27806: Add changeset for updated agentCard with protocol version 0.3.0
|
||||
- a35a256: Migrate from WebSocket to Server-Sent Events (SSE) for real-time streaming
|
||||
- Replace WebSocket with SSE for message streaming via new `/api/message-stream` endpoint
|
||||
- Refactor approval system from event-based providers to simpler handler pattern
|
||||
- Add new APIs for session approval
|
||||
- Move session title generation to a separate API
|
||||
- Add `ApprovalCoordinator` for multi-client SSE routing with sessionId mapping
|
||||
- Add stream and generate methods to DextoAgent and integ tests for itq=
|
||||
|
||||
- a154ae0: UI refactor with TanStack Query, new agent management package, and Hono as default server
|
||||
|
||||
**Server:**
|
||||
- Make Hono the default API server (use `DEXTO_USE_EXPRESS=true` env var to use Express)
|
||||
- Fix agentId propagation to Hono server for correct agent name display
|
||||
- Fix circular reference crashes in error logging by using structured logger context
|
||||
|
||||
**WebUI:**
|
||||
- Integrate TanStack Query for server state management with automatic caching and invalidation
|
||||
- Add centralized query key factory and API client with structured error handling
|
||||
- Replace manual data fetching with TanStack Query hooks across all components
|
||||
- Add Zustand for client-side persistent state (recent agents in localStorage)
|
||||
- Add keyboard shortcuts support with react-hotkeys-hook
|
||||
- Add optimistic updates for session management via WebSocket events
|
||||
- Fix Dialog auto-close bug in CreateMemoryModal
|
||||
- Add defensive null handling in MemoryPanel
|
||||
- Standardize Prettier formatting (single quotes, 4-space indentation)
|
||||
|
||||
**Agent Management:**
|
||||
- Add `@dexto/agent-management` package for centralized agent configuration management
|
||||
- Extract agent registry, preferences, and path utilities into dedicated package
|
||||
|
||||
**Internal:**
|
||||
- Improve build orchestration and fix dependency imports
|
||||
- Add `@dexto/agent-management` to global CLI installation
|
||||
|
||||
- ac649fd: Fix error handling and UI bugs, add gpt-5.1, gemini-3
|
||||
- Updated dependencies [c1e814f]
|
||||
- Updated dependencies [f9bca72]
|
||||
- Updated dependencies [c0a10cd]
|
||||
- Updated dependencies [81598b5]
|
||||
- Updated dependencies [4c90ffe]
|
||||
- Updated dependencies [1a20506]
|
||||
- Updated dependencies [8f373cc]
|
||||
- Updated dependencies [f28ad7e]
|
||||
- Updated dependencies [4dd4998]
|
||||
- Updated dependencies [5e27806]
|
||||
- Updated dependencies [a35a256]
|
||||
- Updated dependencies [0fa6ef5]
|
||||
- Updated dependencies [e2fb5f8]
|
||||
- Updated dependencies [a154ae0]
|
||||
- Updated dependencies [ac649fd]
|
||||
- @dexto/agent-management@1.2.5
|
||||
- @dexto/core@1.2.5
|
||||
|
||||
## 1.2.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- cd706e7: bump up version after fixing node-machine-id
|
||||
- Updated dependencies [cd706e7]
|
||||
- @dexto/core@1.2.4
|
||||
|
||||
## 1.2.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 5d6ae73: Bump up version to fix bugs
|
||||
- Updated dependencies [5d6ae73]
|
||||
- @dexto/core@1.2.3
|
||||
|
||||
## 1.2.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 8b96b63: Add posthog analytics package and add to web ui
|
||||
- @dexto/core@1.2.2
|
||||
27
dexto/packages/analytics/README.md
Normal file
27
dexto/packages/analytics/README.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# @dexto/analytics
|
||||
|
||||
Shared analytics utilities for Dexto CLI and WebUI.
|
||||
|
||||
## What's included
|
||||
|
||||
- **constants.ts**: PostHog configuration (keys, host, analytics disabled check)
|
||||
- **state.ts**: Analytics state management (distinct ID persistence)
|
||||
|
||||
## Usage
|
||||
|
||||
```typescript
|
||||
import { loadState, isAnalyticsDisabled, DEFAULT_POSTHOG_KEY } from '@dexto/analytics';
|
||||
|
||||
// Check if analytics is disabled
|
||||
if (isAnalyticsDisabled()) {
|
||||
// Skip analytics
|
||||
}
|
||||
|
||||
// Load analytics state (distinct ID)
|
||||
const state = await loadState();
|
||||
console.log(state.distinctId);
|
||||
```
|
||||
|
||||
## Note
|
||||
|
||||
This is an internal package used by `@dexto/cli` and `@dexto/webui`. It is marked as private and not published to npm.
|
||||
34
dexto/packages/analytics/package.json
Normal file
34
dexto/packages/analytics/package.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "@dexto/analytics",
|
||||
"version": "1.5.6",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.cjs"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dexto/agent-management": "workspace:*",
|
||||
"@dexto/core": "workspace:*",
|
||||
"node-machine-id": "^1.1.12"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "cross-env NODE_OPTIONS='--max-old-space-size=4096' tsup && cross-env NODE_OPTIONS='--max-old-space-size=4096' tsc -p tsconfig.json --emitDeclarationOnly",
|
||||
"dev": "tsup --watch",
|
||||
"typecheck": "tsc -p tsconfig.typecheck.json --noEmit",
|
||||
"lint": "eslint . --ext .ts"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"sideEffects": false
|
||||
}
|
||||
27
dexto/packages/analytics/src/constants.ts
Normal file
27
dexto/packages/analytics/src/constants.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
// packages/analytics/src/constants.ts
|
||||
|
||||
// Single source for PostHog configuration.
|
||||
// Embed your public key here (safe to publish). Host can stay default.
|
||||
export const DEFAULT_POSTHOG_KEY = 'phc_IJHITHjBKOjDyFiVeilfdumcGniXMuLeXeiLQhYvwDW';
|
||||
export const DEFAULT_POSTHOG_HOST = 'https://app.posthog.com';
|
||||
|
||||
/**
|
||||
* Single opt-out switch for analytics.
|
||||
*
|
||||
* Usage:
|
||||
* DEXTO_ANALYTICS_DISABLED=1 dexto ...
|
||||
*
|
||||
* When set to a truthy value ("1", "true", "yes"), analytics are fully disabled.
|
||||
*/
|
||||
export function isAnalyticsDisabled(): boolean {
|
||||
const v = process.env.DEXTO_ANALYTICS_DISABLED;
|
||||
return typeof v === 'string' && /^(1|true|yes)$/i.test(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic per-command timeout (in milliseconds) used by the analytics wrapper.
|
||||
*
|
||||
* This does NOT terminate the command. It emits a non-terminating timeout
|
||||
* event when the duration threshold is crossed to help diagnose long runs.
|
||||
*/
|
||||
export const COMMAND_TIMEOUT_MS = 120000; // 2 minutes (default for quick commands)
|
||||
175
dexto/packages/analytics/src/events.ts
Normal file
175
dexto/packages/analytics/src/events.ts
Normal file
@@ -0,0 +1,175 @@
|
||||
/**
|
||||
* Platform source for analytics events.
|
||||
* Used to distinguish which interface generated the event.
|
||||
*/
|
||||
export type AnalyticsSource = 'cli' | 'webui';
|
||||
|
||||
/**
|
||||
* LLM token consumption event.
|
||||
* Emitted after each LLM response with token usage data.
|
||||
*
|
||||
*/
|
||||
export interface LLMTokensConsumedEvent {
|
||||
source: AnalyticsSource;
|
||||
sessionId: string;
|
||||
provider?: string | undefined;
|
||||
model?: string | undefined;
|
||||
inputTokens?: number | undefined;
|
||||
outputTokens?: number | undefined;
|
||||
reasoningTokens?: number | undefined;
|
||||
totalTokens?: number | undefined;
|
||||
cacheReadTokens?: number | undefined;
|
||||
cacheWriteTokens?: number | undefined;
|
||||
/** Estimated input tokens (before LLM call, using length/4 heuristic) */
|
||||
estimatedInputTokens?: number | undefined;
|
||||
/** Accuracy of estimate vs actual: (estimated - actual) / actual * 100 */
|
||||
estimateAccuracyPercent?: number | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Message sent event.
|
||||
* Emitted when user sends a message to the agent.
|
||||
*/
|
||||
export interface MessageSentEvent {
|
||||
source: AnalyticsSource;
|
||||
sessionId: string;
|
||||
provider: string;
|
||||
model: string;
|
||||
hasImage: boolean;
|
||||
hasFile: boolean;
|
||||
messageLength: number;
|
||||
messageCount?: number | undefined;
|
||||
isQueued?: boolean | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tool called event.
|
||||
* Emitted when a tool is invoked by the LLM.
|
||||
*/
|
||||
export interface ToolCalledEvent {
|
||||
source: AnalyticsSource;
|
||||
sessionId: string;
|
||||
toolName: string;
|
||||
mcpServer?: string | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tool result event.
|
||||
* Emitted when a tool execution completes.
|
||||
*/
|
||||
export interface ToolResultEvent {
|
||||
source: AnalyticsSource;
|
||||
sessionId: string;
|
||||
toolName: string;
|
||||
success: boolean;
|
||||
approvalStatus?: 'approved' | 'rejected' | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Session created event.
|
||||
*/
|
||||
export interface SessionCreatedEvent {
|
||||
source: AnalyticsSource;
|
||||
sessionId: string;
|
||||
trigger: 'first_message' | 'manual' | 'resume';
|
||||
}
|
||||
|
||||
/**
|
||||
* Session reset event (conversation cleared).
|
||||
*/
|
||||
export interface SessionResetEvent {
|
||||
source: AnalyticsSource;
|
||||
sessionId: string;
|
||||
messageCount: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* LLM switched event.
|
||||
*/
|
||||
export interface LLMSwitchedEvent {
|
||||
source: AnalyticsSource;
|
||||
sessionId?: string | undefined;
|
||||
fromProvider: string;
|
||||
fromModel: string;
|
||||
toProvider: string;
|
||||
toModel: string;
|
||||
trigger: 'user_action' | 'config_change';
|
||||
}
|
||||
|
||||
/**
|
||||
* Session switched event.
|
||||
* Emitted when user switches to a different session.
|
||||
*/
|
||||
export interface SessionSwitchedEvent {
|
||||
source: AnalyticsSource;
|
||||
fromSessionId: string | null;
|
||||
toSessionId: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Agent switched event.
|
||||
* Emitted when user switches to a different agent.
|
||||
*/
|
||||
export interface AgentSwitchedEvent {
|
||||
source: AnalyticsSource;
|
||||
fromAgentId: string | null;
|
||||
toAgentId: string;
|
||||
toAgentName?: string | undefined;
|
||||
sessionId?: string | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* MCP server connected event.
|
||||
* Emitted when an MCP server connects successfully.
|
||||
*/
|
||||
export interface MCPServerConnectedEvent {
|
||||
source: AnalyticsSource;
|
||||
serverName: string;
|
||||
transportType: 'stdio' | 'http' | 'sse';
|
||||
toolCount?: number | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* File attached event.
|
||||
* Emitted when user attaches a file to a message.
|
||||
*/
|
||||
export interface FileAttachedEvent {
|
||||
source: AnalyticsSource;
|
||||
sessionId: string;
|
||||
fileType: string;
|
||||
fileSizeBytes?: number | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Image attached event.
|
||||
* Emitted when user attaches an image to a message.
|
||||
*/
|
||||
export interface ImageAttachedEvent {
|
||||
source: AnalyticsSource;
|
||||
sessionId: string;
|
||||
imageType: string;
|
||||
imageSizeBytes?: number | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shared analytics event map containing events supported by ALL platforms.
|
||||
* CLI and WebUI extend this map with platform-specific events.
|
||||
*
|
||||
* IMPORTANT: If an event is tracked by both CLI and WebUI, add it here.
|
||||
* Platform-specific events should be added to the respective platform's event map.
|
||||
*/
|
||||
export interface SharedAnalyticsEventMap {
|
||||
dexto_llm_tokens_consumed: LLMTokensConsumedEvent;
|
||||
dexto_message_sent: MessageSentEvent;
|
||||
dexto_tool_called: ToolCalledEvent;
|
||||
dexto_tool_result: ToolResultEvent;
|
||||
dexto_session_created: SessionCreatedEvent;
|
||||
dexto_session_reset: SessionResetEvent;
|
||||
dexto_llm_switched: LLMSwitchedEvent;
|
||||
dexto_session_switched: SessionSwitchedEvent;
|
||||
dexto_agent_switched: AgentSwitchedEvent;
|
||||
dexto_mcp_server_connected: MCPServerConnectedEvent;
|
||||
dexto_image_attached: ImageAttachedEvent;
|
||||
}
|
||||
|
||||
export type SharedAnalyticsEventName = keyof SharedAnalyticsEventMap;
|
||||
12
dexto/packages/analytics/src/index.ts
Normal file
12
dexto/packages/analytics/src/index.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
// packages/analytics/src/index.ts
|
||||
// Shared analytics utilities for Dexto CLI and WebUI
|
||||
|
||||
export {
|
||||
DEFAULT_POSTHOG_KEY,
|
||||
DEFAULT_POSTHOG_HOST,
|
||||
COMMAND_TIMEOUT_MS,
|
||||
isAnalyticsDisabled,
|
||||
} from './constants.js';
|
||||
export { loadState, saveState } from './state.js';
|
||||
export type { AnalyticsState } from './state.js';
|
||||
export * from './events.js';
|
||||
90
dexto/packages/analytics/src/state.ts
Normal file
90
dexto/packages/analytics/src/state.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
// packages/analytics/src/state.ts
|
||||
|
||||
import { promises as fs } from 'fs';
|
||||
import * as path from 'path';
|
||||
import os from 'os';
|
||||
import { randomUUID, createHash } from 'crypto';
|
||||
import { createRequire } from 'module';
|
||||
import { getDextoGlobalPath } from '@dexto/core';
|
||||
|
||||
/**
|
||||
* Shape of the persisted analytics state written to
|
||||
* ~/.dexto/telemetry/state.json.
|
||||
*
|
||||
* - distinctId: Anonymous ID (UUID) for grouping events by machine.
|
||||
* - createdAt: ISO timestamp when the state was first created.
|
||||
* - commandRunCounts: Local counters per command for coarse diagnostics.
|
||||
*/
|
||||
export interface AnalyticsState {
|
||||
distinctId: string;
|
||||
createdAt: string; // ISO string
|
||||
commandRunCounts?: Record<string, number>;
|
||||
}
|
||||
|
||||
const STATE_DIR = getDextoGlobalPath('telemetry');
|
||||
const STATE_FILE = path.join(STATE_DIR, 'state.json');
|
||||
|
||||
/**
|
||||
* Load the persisted analytics state, creating a new file if missing.
|
||||
* Returns a valid state object with defaults populated.
|
||||
*/
|
||||
export async function loadState(): Promise<AnalyticsState> {
|
||||
try {
|
||||
const content = await fs.readFile(STATE_FILE, 'utf8');
|
||||
const parsed = JSON.parse(content) as Partial<AnalyticsState>;
|
||||
// Validate minimal shape
|
||||
if (!parsed.distinctId) throw new Error('invalid state');
|
||||
return {
|
||||
distinctId: parsed.distinctId,
|
||||
createdAt: parsed.createdAt || new Date().toISOString(),
|
||||
commandRunCounts: parsed.commandRunCounts ?? {},
|
||||
};
|
||||
} catch {
|
||||
await fs.mkdir(STATE_DIR, { recursive: true });
|
||||
const state: AnalyticsState = {
|
||||
distinctId: computeDistinctId(),
|
||||
createdAt: new Date().toISOString(),
|
||||
commandRunCounts: {},
|
||||
};
|
||||
await saveState(state);
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist the analytics state to ~/.dexto/telemetry/state.json.
|
||||
*/
|
||||
export async function saveState(state: AnalyticsState): Promise<void> {
|
||||
await fs.mkdir(STATE_DIR, { recursive: true });
|
||||
await fs.writeFile(STATE_FILE, JSON.stringify(state, null, 2), 'utf8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute a stable, privacy‑safe machine identifier so identity
|
||||
* survives ~/.dexto deletion by default.
|
||||
*
|
||||
* Strategy:
|
||||
* - Prefer node-machine-id (hashed), which abstracts platform differences.
|
||||
* - Fallback to a salted/hashed hostname.
|
||||
* - As a last resort, generate a random UUID.
|
||||
*/
|
||||
function computeDistinctId(): string {
|
||||
try {
|
||||
// node-machine-id is CommonJS; require lazily to avoid import-time failures
|
||||
const requireCJS = createRequire(import.meta.url);
|
||||
const { machineIdSync } = requireCJS('node-machine-id') as {
|
||||
machineIdSync: (original?: boolean) => string;
|
||||
};
|
||||
// machineIdSync(true) returns a hashed, stable identifier
|
||||
const id = machineIdSync(true);
|
||||
if (typeof id === 'string' && id.length > 0) return `DEXTO-${id}`;
|
||||
} catch {
|
||||
// fall through to hostname hash
|
||||
}
|
||||
// Fallback: hash hostname to avoid exposing raw value
|
||||
const hostname = os.hostname() || 'unknown-host';
|
||||
const digest = createHash('sha256').update(hostname).digest('hex');
|
||||
if (digest) return `DEXTO-${digest.slice(0, 32)}`;
|
||||
// Last resort
|
||||
return `DEXTO-${randomUUID()}`;
|
||||
}
|
||||
14
dexto/packages/analytics/tsconfig.json
Normal file
14
dexto/packages/analytics/tsconfig.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"rootDir": "src",
|
||||
"outDir": "dist",
|
||||
"noEmit": false,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"emitDeclarationOnly": false
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["**/*.test.ts", "**/*.spec.ts", "**/*.integration.test.ts", "dist", "node_modules"]
|
||||
}
|
||||
4
dexto/packages/analytics/tsconfig.typecheck.json
Normal file
4
dexto/packages/analytics/tsconfig.typecheck.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": ["dist", "node_modules"]
|
||||
}
|
||||
18
dexto/packages/analytics/tsup.config.ts
Normal file
18
dexto/packages/analytics/tsup.config.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { defineConfig } from 'tsup';
|
||||
|
||||
export default defineConfig({
|
||||
entry: ['src/**/*.ts'],
|
||||
format: ['cjs', 'esm'],
|
||||
outDir: 'dist',
|
||||
dts: false, // Use tsc for declaration files
|
||||
platform: 'node',
|
||||
bundle: false,
|
||||
clean: true,
|
||||
tsconfig: './tsconfig.json',
|
||||
esbuildOptions(options) {
|
||||
options.logOverride = {
|
||||
...(options.logOverride ?? {}),
|
||||
'empty-import-meta': 'silent',
|
||||
};
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user