@stackmemoryai/stackmemory 0.3.5 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/verifiers/base-verifier.js.map +2 -2
- package/dist/agents/verifiers/formatter-verifier.js.map +2 -2
- package/dist/agents/verifiers/llm-judge.js.map +2 -2
- package/dist/cli/claude-sm.js +24 -13
- package/dist/cli/claude-sm.js.map +2 -2
- package/dist/cli/codex-sm.js +24 -13
- package/dist/cli/codex-sm.js.map +2 -2
- package/dist/cli/commands/agent.js.map +2 -2
- package/dist/cli/commands/chromadb.js +217 -32
- package/dist/cli/commands/chromadb.js.map +2 -2
- package/dist/cli/commands/clear.js +12 -1
- package/dist/cli/commands/clear.js.map +2 -2
- package/dist/cli/commands/context.js +13 -2
- package/dist/cli/commands/context.js.map +2 -2
- package/dist/cli/commands/dashboard.js.map +2 -2
- package/dist/cli/commands/gc.js +202 -0
- package/dist/cli/commands/gc.js.map +7 -0
- package/dist/cli/commands/handoff.js +12 -1
- package/dist/cli/commands/handoff.js.map +2 -2
- package/dist/cli/commands/infinite-storage.js +251 -0
- package/dist/cli/commands/infinite-storage.js.map +7 -0
- package/dist/cli/commands/linear-create.js +13 -2
- package/dist/cli/commands/linear-create.js.map +2 -2
- package/dist/cli/commands/linear-list.js +12 -1
- package/dist/cli/commands/linear-list.js.map +2 -2
- package/dist/cli/commands/linear-migrate.js +12 -1
- package/dist/cli/commands/linear-migrate.js.map +2 -2
- package/dist/cli/commands/linear-test.js +12 -1
- package/dist/cli/commands/linear-test.js.map +2 -2
- package/dist/cli/commands/linear-unified.js +262 -0
- package/dist/cli/commands/linear-unified.js.map +7 -0
- package/dist/cli/commands/linear.js +17 -6
- package/dist/cli/commands/linear.js.map +2 -2
- package/dist/cli/commands/monitor.js.map +2 -2
- package/dist/cli/commands/onboard.js.map +2 -2
- package/dist/cli/commands/quality.js.map +2 -2
- package/dist/cli/commands/search.js.map +2 -2
- package/dist/cli/commands/session.js.map +2 -2
- package/dist/cli/commands/skills.js +12 -1
- package/dist/cli/commands/skills.js.map +2 -2
- package/dist/cli/commands/storage.js +18 -7
- package/dist/cli/commands/storage.js.map +2 -2
- package/dist/cli/commands/tasks.js.map +2 -2
- package/dist/cli/commands/tui.js +13 -2
- package/dist/cli/commands/tui.js.map +2 -2
- package/dist/cli/commands/webhook.js +14 -3
- package/dist/cli/commands/webhook.js.map +2 -2
- package/dist/cli/commands/workflow.js +14 -3
- package/dist/cli/commands/workflow.js.map +2 -2
- package/dist/cli/commands/worktree.js.map +2 -2
- package/dist/cli/index.js +20 -5
- package/dist/cli/index.js.map +2 -2
- package/dist/core/config/config-manager.js.map +2 -2
- package/dist/core/context/auto-context.js.map +2 -2
- package/dist/core/context/compaction-handler.js.map +2 -2
- package/dist/core/context/context-bridge.js.map +2 -2
- package/dist/core/context/dual-stack-manager.js.map +2 -2
- package/dist/core/context/frame-database.js.map +2 -2
- package/dist/core/context/frame-digest.js.map +2 -2
- package/dist/core/context/frame-handoff-manager.js.map +2 -2
- package/dist/core/context/frame-manager.js +12 -1
- package/dist/core/context/frame-manager.js.map +2 -2
- package/dist/core/context/frame-stack.js.map +2 -2
- package/dist/core/context/incremental-gc.js +279 -0
- package/dist/core/context/incremental-gc.js.map +7 -0
- package/dist/core/context/permission-manager.js +12 -1
- package/dist/core/context/permission-manager.js.map +2 -2
- package/dist/core/context/refactored-frame-manager.js.map +2 -2
- package/dist/core/context/shared-context-layer.js +12 -1
- package/dist/core/context/shared-context-layer.js.map +2 -2
- package/dist/core/context/stack-merge-resolver.js.map +2 -2
- package/dist/core/context/validation.js.map +2 -2
- package/dist/core/database/batch-operations.js.map +2 -2
- package/dist/core/database/connection-pool.js.map +2 -2
- package/dist/core/database/migration-manager.js.map +2 -2
- package/dist/core/database/paradedb-adapter.js.map +2 -2
- package/dist/core/database/query-cache.js.map +2 -2
- package/dist/core/database/query-router.js.map +2 -2
- package/dist/core/database/sqlite-adapter.js.map +2 -2
- package/dist/core/digest/enhanced-hybrid-digest.js.map +2 -2
- package/dist/core/errors/recovery.js.map +2 -2
- package/dist/core/merge/resolution-engine.js.map +2 -2
- package/dist/core/monitoring/error-handler.js.map +2 -2
- package/dist/core/monitoring/logger.js +14 -3
- package/dist/core/monitoring/logger.js.map +2 -2
- package/dist/core/monitoring/metrics.js +13 -2
- package/dist/core/monitoring/metrics.js.map +2 -2
- package/dist/core/monitoring/progress-tracker.js +12 -1
- package/dist/core/monitoring/progress-tracker.js.map +2 -2
- package/dist/core/monitoring/session-monitor.js.map +2 -2
- package/dist/core/performance/context-cache.js.map +2 -2
- package/dist/core/performance/lazy-context-loader.js.map +2 -2
- package/dist/core/performance/monitor.js.map +2 -2
- package/dist/core/performance/optimized-frame-context.js.map +2 -2
- package/dist/core/performance/performance-benchmark.js.map +2 -2
- package/dist/core/performance/performance-profiler.js +12 -1
- package/dist/core/performance/performance-profiler.js.map +2 -2
- package/dist/core/performance/streaming-jsonl-parser.js.map +2 -2
- package/dist/core/persistence/postgres-adapter.js.map +2 -2
- package/dist/core/projects/project-manager.js.map +2 -2
- package/dist/core/retrieval/context-retriever.js.map +2 -2
- package/dist/core/retrieval/graph-retrieval.js.map +2 -2
- package/dist/core/retrieval/llm-context-retrieval.js.map +2 -2
- package/dist/core/retrieval/retrieval-benchmarks.js.map +2 -2
- package/dist/core/retrieval/summary-generator.js.map +2 -2
- package/dist/core/session/clear-survival.js.map +2 -2
- package/dist/core/session/handoff-generator.js.map +2 -2
- package/dist/core/session/session-manager.js +16 -5
- package/dist/core/session/session-manager.js.map +2 -2
- package/dist/core/skills/skill-storage.js +13 -2
- package/dist/core/skills/skill-storage.js.map +2 -2
- package/dist/core/storage/chromadb-adapter.js.map +2 -2
- package/dist/core/storage/chromadb-simple.js +160 -0
- package/dist/core/storage/chromadb-simple.js.map +7 -0
- package/dist/core/storage/infinite-storage.js +443 -0
- package/dist/core/storage/infinite-storage.js.map +7 -0
- package/dist/core/storage/railway-optimized-storage.js +19 -8
- package/dist/core/storage/railway-optimized-storage.js.map +2 -2
- package/dist/core/storage/remote-storage.js +12 -1
- package/dist/core/storage/remote-storage.js.map +2 -2
- package/dist/core/trace/cli-trace-wrapper.js +16 -5
- package/dist/core/trace/cli-trace-wrapper.js.map +2 -2
- package/dist/core/trace/db-trace-wrapper.js.map +2 -2
- package/dist/core/trace/debug-trace.js +21 -10
- package/dist/core/trace/debug-trace.js.map +2 -2
- package/dist/core/trace/index.js +46 -35
- package/dist/core/trace/index.js.map +2 -2
- package/dist/core/trace/trace-demo.js +12 -1
- package/dist/core/trace/trace-demo.js.map +2 -2
- package/dist/core/trace/trace-detector.js.map +2 -2
- package/dist/core/trace/trace-store.js.map +2 -2
- package/dist/core/utils/compression.js +79 -0
- package/dist/core/utils/compression.js.map +7 -0
- package/dist/core/utils/update-checker.js.map +2 -2
- package/dist/core/worktree/worktree-manager.js.map +2 -2
- package/dist/features/analytics/api/analytics-api.js.map +2 -2
- package/dist/features/analytics/core/analytics-service.js +12 -1
- package/dist/features/analytics/core/analytics-service.js.map +2 -2
- package/dist/features/analytics/queries/metrics-queries.js.map +2 -2
- package/dist/features/tasks/pebbles-task-store.js.map +2 -2
- package/dist/features/tui/components/analytics-panel.js.map +2 -2
- package/dist/features/tui/components/pr-tracker.js.map +2 -2
- package/dist/features/tui/components/session-monitor.js.map +2 -2
- package/dist/features/tui/components/subagent-fleet.js.map +2 -2
- package/dist/features/tui/components/task-board.js +650 -2
- package/dist/features/tui/components/task-board.js.map +2 -2
- package/dist/features/tui/index.js +16 -5
- package/dist/features/tui/index.js.map +2 -2
- package/dist/features/tui/services/data-service.js +35 -52
- package/dist/features/tui/services/data-service.js.map +2 -2
- package/dist/features/tui/services/linear-task-reader.js +100 -0
- package/dist/features/tui/services/linear-task-reader.js.map +7 -0
- package/dist/features/tui/services/websocket-client.js +13 -2
- package/dist/features/tui/services/websocket-client.js.map +2 -2
- package/dist/features/tui/terminal-compat.js +27 -16
- package/dist/features/tui/terminal-compat.js.map +2 -2
- package/dist/features/web/client/stores/task-store.js +22 -0
- package/dist/features/web/client/stores/task-store.js.map +7 -0
- package/dist/features/web/server/index.js +182 -0
- package/dist/features/web/server/index.js.map +7 -0
- package/dist/integrations/claude-code/enhanced-pre-clear-hooks.js.map +2 -2
- package/dist/integrations/claude-code/lifecycle-hooks.js.map +2 -2
- package/dist/integrations/claude-code/post-task-hooks.js.map +2 -2
- package/dist/integrations/linear/auth.js +17 -6
- package/dist/integrations/linear/auth.js.map +2 -2
- package/dist/integrations/linear/auto-sync.js.map +2 -2
- package/dist/integrations/linear/client.js.map +2 -2
- package/dist/integrations/linear/config.js.map +2 -2
- package/dist/integrations/linear/migration.js.map +2 -2
- package/dist/integrations/linear/oauth-server.js +13 -2
- package/dist/integrations/linear/oauth-server.js.map +2 -2
- package/dist/integrations/linear/rest-client.js.map +2 -2
- package/dist/integrations/linear/sync-enhanced.js +202 -0
- package/dist/integrations/linear/sync-enhanced.js.map +7 -0
- package/dist/integrations/linear/sync-manager.js.map +2 -2
- package/dist/integrations/linear/sync-service.js +12 -1
- package/dist/integrations/linear/sync-service.js.map +2 -2
- package/dist/integrations/linear/sync.js +34 -3
- package/dist/integrations/linear/sync.js.map +2 -2
- package/dist/integrations/linear/unified-sync.js +560 -0
- package/dist/integrations/linear/unified-sync.js.map +7 -0
- package/dist/integrations/linear/webhook-handler.js +12 -1
- package/dist/integrations/linear/webhook-handler.js.map +2 -2
- package/dist/integrations/linear/webhook-server.js +14 -3
- package/dist/integrations/linear/webhook-server.js.map +2 -2
- package/dist/integrations/linear/webhook.js +12 -1
- package/dist/integrations/linear/webhook.js.map +2 -2
- package/dist/integrations/mcp/handlers/context-handlers.js.map +2 -2
- package/dist/integrations/mcp/handlers/linear-handlers.js.map +2 -2
- package/dist/integrations/mcp/handlers/skill-handlers.js +13 -2
- package/dist/integrations/mcp/handlers/skill-handlers.js.map +2 -2
- package/dist/integrations/mcp/handlers/task-handlers.js.map +2 -2
- package/dist/integrations/mcp/handlers/trace-handlers.js.map +2 -2
- package/dist/integrations/mcp/middleware/tool-scoring.js.map +2 -2
- package/dist/integrations/mcp/refactored-server.js +15 -4
- package/dist/integrations/mcp/refactored-server.js.map +2 -2
- package/dist/integrations/mcp/server.js +12 -1
- package/dist/integrations/mcp/server.js.map +2 -2
- package/dist/integrations/mcp/tool-definitions.js.map +2 -2
- package/dist/integrations/pg-aiguide/embedding-provider.js +13 -2
- package/dist/integrations/pg-aiguide/embedding-provider.js.map +2 -2
- package/dist/integrations/pg-aiguide/semantic-search.js.map +2 -2
- package/dist/mcp/stackmemory-mcp-server.js +12 -1
- package/dist/mcp/stackmemory-mcp-server.js.map +2 -2
- package/dist/middleware/exponential-rate-limiter.js.map +2 -2
- package/dist/servers/production/auth-middleware.js +13 -2
- package/dist/servers/production/auth-middleware.js.map +2 -2
- package/dist/servers/railway/index.js +22 -11
- package/dist/servers/railway/index.js.map +2 -2
- package/dist/services/config-service.js.map +2 -2
- package/dist/services/context-service.js.map +2 -2
- package/dist/skills/claude-skills.js +150 -1
- package/dist/skills/claude-skills.js.map +2 -2
- package/dist/skills/dashboard-launcher.js +212 -0
- package/dist/skills/dashboard-launcher.js.map +7 -0
- package/dist/skills/repo-ingestion-skill.js +561 -0
- package/dist/skills/repo-ingestion-skill.js.map +7 -0
- package/dist/utils/logger.js +12 -1
- package/dist/utils/logger.js.map +2 -2
- package/package.json +7 -1
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
+
function getEnv(key, defaultValue) {
|
|
3
|
+
const value = process.env[key];
|
|
4
|
+
if (value === void 0) {
|
|
5
|
+
if (defaultValue !== void 0) return defaultValue;
|
|
6
|
+
throw new Error(`Environment variable ${key} is required`);
|
|
7
|
+
}
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
function getOptionalEnv(key) {
|
|
11
|
+
return process.env[key];
|
|
12
|
+
}
|
|
2
13
|
function registerLinearTestCommand(parent) {
|
|
3
14
|
parent.command("linear:test").description("Test Linear API connection").option("--api-key <key>", "Linear API key").action(async (options) => {
|
|
4
15
|
try {
|
|
5
|
-
const apiKey = options.apiKey || process.env
|
|
16
|
+
const apiKey = options.apiKey || process.env["LINEAR_API_KEY"];
|
|
6
17
|
if (!apiKey) {
|
|
7
18
|
console.log(chalk.red("\u274C No API key provided"));
|
|
8
19
|
console.log("Use --api-key or set LINEAR_API_KEY environment variable");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/cli/commands/linear-test.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Simple Linear sync test command\n */\n\nimport chalk from 'chalk';\nimport { Command } from 'commander';\n\nexport function registerLinearTestCommand(parent: Command) {\n parent\n .command('linear:test')\n .description('Test Linear API connection')\n .option('--api-key <key>', 'Linear API key')\n .action(async (options) => {\n try {\n const apiKey = options.apiKey || process.env
|
|
5
|
-
"mappings": "AAIA,OAAO,WAAW;
|
|
4
|
+
"sourcesContent": ["/**\n * Simple Linear sync test command\n */\n\nimport chalk from 'chalk';\nimport { Command } from 'commander';\n// Type-safe environment variable access\nfunction getEnv(key: string, defaultValue?: string): string {\n const value = process.env[key];\n if (value === undefined) {\n if (defaultValue !== undefined) return defaultValue;\n throw new Error(`Environment variable ${key} is required`);\n }\n return value;\n}\n\nfunction getOptionalEnv(key: string): string | undefined {\n return process.env[key];\n}\n\n\nexport function registerLinearTestCommand(parent: Command) {\n parent\n .command('linear:test')\n .description('Test Linear API connection')\n .option('--api-key <key>', 'Linear API key')\n .action(async (options) => {\n try {\n const apiKey = options.apiKey || process.env['LINEAR_API_KEY'];\n \n if (!apiKey) {\n console.log(chalk.red('\u274C No API key provided'));\n console.log('Use --api-key or set LINEAR_API_KEY environment variable');\n return;\n }\n \n console.log(chalk.yellow('\uD83D\uDD04 Testing Linear connection...'));\n \n // Simple GraphQL query to test connection\n const response = await fetch('https://api.linear.app/graphql', {\n method: 'POST',\n headers: {\n 'Authorization': apiKey,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n query: `\n query Me {\n viewer {\n id\n name\n email\n }\n teams {\n nodes {\n id\n key\n name\n }\n }\n }\n `\n }),\n });\n \n if (!response.ok) {\n console.log(chalk.red(`\u274C API Error: ${response.status} ${response.statusText}`));\n return;\n }\n \n const result: any = await response.json();\n \n if (result.errors) {\n console.log(chalk.red('\u274C GraphQL Errors:'));\n result.errors.forEach((err: any) => console.log(` - ${err.message}`));\n return;\n }\n \n if (result.data?.viewer) {\n console.log(chalk.green('\u2705 Connected to Linear!'));\n console.log(chalk.cyan('\\n\uD83D\uDC64 User:'));\n console.log(` Name: ${result.data.viewer.name}`);\n console.log(` Email: ${result.data.viewer.email}`);\n }\n \n if (result.data?.teams?.nodes?.length > 0) {\n console.log(chalk.cyan('\\n\uD83C\uDFE2 Teams:'));\n result.data.teams.nodes.forEach((team: any) => {\n console.log(` - ${team.name} (${team.key})`);\n });\n }\n \n // Test creating a sample issue (optional)\n console.log(chalk.yellow('\\n\uD83D\uDD04 Testing issue creation...'));\n \n if (result.data?.teams?.nodes?.length > 0) {\n const teamId = result.data.teams.nodes[0].id;\n \n const createResponse = await fetch('https://api.linear.app/graphql', {\n method: 'POST',\n headers: {\n 'Authorization': apiKey,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n query: `\n mutation CreateIssue($input: IssueCreateInput!) {\n issueCreate(input: $input) {\n success\n issue {\n id\n identifier\n title\n url\n }\n }\n }\n `,\n variables: {\n input: {\n teamId: teamId,\n title: '[TEST] StackMemory Integration Test',\n description: 'This is a test issue created by StackMemory to verify Linear integration.',\n priority: 4, // Low priority\n }\n }\n }),\n });\n \n const createResult: any = await createResponse.json();\n \n if (createResult.data?.issueCreate?.success) {\n const issue = createResult.data.issueCreate.issue;\n console.log(chalk.green('\u2705 Test issue created successfully!'));\n console.log(` ID: ${issue.identifier}`);\n console.log(` Title: ${issue.title}`);\n console.log(` URL: ${issue.url}`);\n \n // Optional: Delete the test issue\n console.log(chalk.gray('\\n(You can delete this test issue from Linear)'));\n } else {\n console.log(chalk.yellow('\u26A0 Could not create test issue'));\n }\n }\n \n console.log(chalk.green('\\n\u2705 Linear integration test completed!'));\n \n } catch (error: unknown) {\n console.error(chalk.red('\u274C Test failed:'), (error as Error).message);\n process.exit(1);\n }\n });\n}"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { UnifiedLinearSync } from "../../integrations/linear/unified-sync.js";
|
|
3
|
+
import { LinearAuthManager } from "../../integrations/linear/auth.js";
|
|
4
|
+
import { LinearClient } from "../../integrations/linear/client.js";
|
|
5
|
+
import { PebblesTaskStore } from "../../features/tasks/pebbles-task-store.js";
|
|
6
|
+
import Database from "better-sqlite3";
|
|
7
|
+
import { join } from "path";
|
|
8
|
+
import { existsSync, readFileSync } from "fs";
|
|
9
|
+
import Table from "cli-table3";
|
|
10
|
+
import ora from "ora";
|
|
11
|
+
function registerUnifiedLinearCommands(parent) {
|
|
12
|
+
const linear = parent.command("linear").description("Unified Linear integration with duplicate detection and task planning");
|
|
13
|
+
linear.command("sync").description("Intelligent sync with Linear (duplicate detection, bidirectional, task planning)").option("-d, --direction <dir>", "Sync direction: bidirectional, to_linear, from_linear", "bidirectional").option("-t, --team <id>", "Linear team ID").option("--no-duplicates", "Disable duplicate detection").option("--merge-strategy <strategy>", "Duplicate handling: merge_content, skip, create_anyway", "merge_content").option("--conflict <resolution>", "Conflict resolution: newest_wins, linear_wins, local_wins", "newest_wins").option("--task-plan", "Enable task planning integration").option("--dry-run", "Preview changes without syncing").option("--daemon", "Run as background daemon").option("-i, --interval <minutes>", "Auto-sync interval", "15").option("--verbose", "Show detailed sync progress").action(async (options) => {
|
|
14
|
+
const spinner = ora("Initializing Linear sync...").start();
|
|
15
|
+
try {
|
|
16
|
+
const projectRoot = process.cwd();
|
|
17
|
+
const dbPath = join(projectRoot, ".stackmemory", "context.db");
|
|
18
|
+
if (!existsSync(dbPath)) {
|
|
19
|
+
spinner.fail("StackMemory not initialized");
|
|
20
|
+
console.log(chalk.yellow('Run "stackmemory init" first'));
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const db = new Database(dbPath);
|
|
24
|
+
const taskStore = new PebblesTaskStore(projectRoot, db);
|
|
25
|
+
const authManager = new LinearAuthManager(projectRoot);
|
|
26
|
+
const config = {
|
|
27
|
+
direction: options.direction,
|
|
28
|
+
defaultTeamId: options.team,
|
|
29
|
+
duplicateDetection: options.duplicates !== false,
|
|
30
|
+
mergeStrategy: options.mergeStrategy,
|
|
31
|
+
conflictResolution: options.conflict,
|
|
32
|
+
taskPlanningEnabled: options.taskPlan || false
|
|
33
|
+
};
|
|
34
|
+
const unifiedSync = new UnifiedLinearSync(taskStore, authManager, projectRoot, config);
|
|
35
|
+
if (options.verbose) {
|
|
36
|
+
unifiedSync.on("sync:started", ({ config: config2 }) => {
|
|
37
|
+
spinner.text = `Syncing (${config2.direction})...`;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
spinner.text = "Authenticating with Linear...";
|
|
41
|
+
await unifiedSync.initialize();
|
|
42
|
+
if (options.dryRun) {
|
|
43
|
+
spinner.info("Dry run mode - no changes will be made");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (options.daemon) {
|
|
47
|
+
spinner.succeed("Starting sync daemon");
|
|
48
|
+
console.log(chalk.cyan(`Sync interval: ${options.interval} minutes`));
|
|
49
|
+
console.log(chalk.gray("Press Ctrl+C to stop\n"));
|
|
50
|
+
const stats = await unifiedSync.sync();
|
|
51
|
+
displaySyncStats(stats);
|
|
52
|
+
const interval = setInterval(async () => {
|
|
53
|
+
console.log(chalk.yellow(`
|
|
54
|
+
[${(/* @__PURE__ */ new Date()).toLocaleTimeString()}] Running scheduled sync...`));
|
|
55
|
+
try {
|
|
56
|
+
const stats2 = await unifiedSync.sync();
|
|
57
|
+
displaySyncStats(stats2);
|
|
58
|
+
} catch (error) {
|
|
59
|
+
console.error(chalk.red("Sync failed:"), error.message);
|
|
60
|
+
}
|
|
61
|
+
}, parseInt(options.interval) * 60 * 1e3);
|
|
62
|
+
process.on("SIGINT", () => {
|
|
63
|
+
console.log(chalk.yellow("\nStopping sync daemon..."));
|
|
64
|
+
clearInterval(interval);
|
|
65
|
+
db.close();
|
|
66
|
+
process.exit(0);
|
|
67
|
+
});
|
|
68
|
+
process.stdin.resume();
|
|
69
|
+
} else {
|
|
70
|
+
spinner.text = "Syncing tasks...";
|
|
71
|
+
const stats = await unifiedSync.sync();
|
|
72
|
+
spinner.succeed("Sync completed");
|
|
73
|
+
displaySyncStats(stats);
|
|
74
|
+
if (options.taskPlan) {
|
|
75
|
+
displayTaskPlan(projectRoot);
|
|
76
|
+
}
|
|
77
|
+
db.close();
|
|
78
|
+
}
|
|
79
|
+
} catch (error) {
|
|
80
|
+
spinner.fail("Sync failed");
|
|
81
|
+
console.error(chalk.red("Error:"), error.message);
|
|
82
|
+
if (options.verbose) {
|
|
83
|
+
console.error(error);
|
|
84
|
+
}
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
linear.command("status").description("Show Linear connection status and sync statistics").action(async () => {
|
|
89
|
+
try {
|
|
90
|
+
const authManager = new LinearAuthManager(process.cwd());
|
|
91
|
+
const hasAuth = authManager.isConfigured();
|
|
92
|
+
if (!hasAuth && !process.env.LINEAR_API_KEY) {
|
|
93
|
+
console.log(chalk.yellow("\u26A0 Not connected to Linear"));
|
|
94
|
+
console.log('Run "stackmemory linear auth" to connect');
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
console.log(chalk.green("\u2713 Linear connection configured"));
|
|
98
|
+
const statsFile = join(process.cwd(), ".stackmemory", "sync-stats.json");
|
|
99
|
+
if (existsSync(statsFile)) {
|
|
100
|
+
const stats = JSON.parse(readFileSync(statsFile, "utf8"));
|
|
101
|
+
console.log(chalk.cyan("\nLast sync:"));
|
|
102
|
+
console.log(` Time: ${new Date(stats.timestamp).toLocaleString()}`);
|
|
103
|
+
console.log(` Duration: ${stats.duration}ms`);
|
|
104
|
+
console.log(` To Linear: ${stats.toLinear.created} created, ${stats.toLinear.updated} updated`);
|
|
105
|
+
console.log(` From Linear: ${stats.fromLinear.created} created, ${stats.fromLinear.updated} updated`);
|
|
106
|
+
if (stats.toLinear.duplicatesMerged > 0) {
|
|
107
|
+
console.log(chalk.green(` Duplicates prevented: ${stats.toLinear.duplicatesMerged}`));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const planFile = join(process.cwd(), ".stackmemory", "task-plan.md");
|
|
111
|
+
if (existsSync(planFile)) {
|
|
112
|
+
console.log(chalk.cyan("\n\u2713 Task planning enabled"));
|
|
113
|
+
const reportFile = join(process.cwd(), ".stackmemory", "task-report.md");
|
|
114
|
+
if (existsSync(reportFile)) {
|
|
115
|
+
console.log(` Report: ${reportFile}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
} catch (error) {
|
|
119
|
+
console.error(chalk.red("Status check failed:"), error.message);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
linear.command("plan").description("View and manage task planning").option("--generate", "Generate task plan from current tasks").option("--report", "Show task report").action(async (options) => {
|
|
123
|
+
try {
|
|
124
|
+
const projectRoot = process.cwd();
|
|
125
|
+
if (options.generate) {
|
|
126
|
+
console.log(chalk.yellow("Generating task plan..."));
|
|
127
|
+
const dbPath = join(projectRoot, ".stackmemory", "context.db");
|
|
128
|
+
const db = new Database(dbPath);
|
|
129
|
+
const taskStore = new PebblesTaskStore(projectRoot, db);
|
|
130
|
+
const authManager = new LinearAuthManager(projectRoot);
|
|
131
|
+
const unifiedSync = new UnifiedLinearSync(taskStore, authManager, projectRoot, {
|
|
132
|
+
taskPlanningEnabled: true,
|
|
133
|
+
autoCreateTaskPlan: true
|
|
134
|
+
});
|
|
135
|
+
await unifiedSync.initialize();
|
|
136
|
+
await unifiedSync.sync();
|
|
137
|
+
console.log(chalk.green("\u2713 Task plan generated"));
|
|
138
|
+
db.close();
|
|
139
|
+
}
|
|
140
|
+
displayTaskPlan(projectRoot, options.report);
|
|
141
|
+
} catch (error) {
|
|
142
|
+
console.error(chalk.red("Plan generation failed:"), error.message);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
linear.command("duplicates").description("Check for and manage duplicate Linear issues").option("--check <title>", "Check if a title would create a duplicate").option("--merge", "Merge detected duplicates").option("--list", "List potential duplicates").action(async (options) => {
|
|
146
|
+
try {
|
|
147
|
+
const authManager = new LinearAuthManager(process.cwd());
|
|
148
|
+
const token = await authManager.getValidToken();
|
|
149
|
+
if (!token) {
|
|
150
|
+
console.log(chalk.red("Not authenticated with Linear"));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const client = new LinearClient({
|
|
154
|
+
apiKey: token,
|
|
155
|
+
useBearer: authManager.isOAuth()
|
|
156
|
+
});
|
|
157
|
+
if (options.check) {
|
|
158
|
+
const { LinearDuplicateDetector } = await import("../../integrations/linear/sync-enhanced.js");
|
|
159
|
+
const detector = new LinearDuplicateDetector(client);
|
|
160
|
+
console.log(chalk.yellow(`Checking for duplicates of: "${options.check}"`));
|
|
161
|
+
const result = await detector.checkForDuplicate(options.check);
|
|
162
|
+
if (result.isDuplicate && result.existingIssue) {
|
|
163
|
+
console.log(chalk.red("\u26A0 Duplicate detected!"));
|
|
164
|
+
console.log(` Issue: ${result.existingIssue.identifier} - ${result.existingIssue.title}`);
|
|
165
|
+
console.log(` Similarity: ${Math.round((result.similarity || 0) * 100)}%`);
|
|
166
|
+
console.log(` URL: ${result.existingIssue.url}`);
|
|
167
|
+
} else {
|
|
168
|
+
console.log(chalk.green("\u2713 No duplicates found"));
|
|
169
|
+
}
|
|
170
|
+
} else if (options.list) {
|
|
171
|
+
console.log(chalk.yellow("Scanning for potential duplicates..."));
|
|
172
|
+
console.log("Feature coming soon");
|
|
173
|
+
} else {
|
|
174
|
+
console.log("Specify --check, --merge, or --list");
|
|
175
|
+
}
|
|
176
|
+
} catch (error) {
|
|
177
|
+
console.error(chalk.red("Duplicate check failed:"), error.message);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
linear.command("auth").description("Authenticate with Linear").option("--api-key <key>", "Use API key").option("--oauth", "Use OAuth flow").action(async (options) => {
|
|
181
|
+
try {
|
|
182
|
+
const authManager = new LinearAuthManager(process.cwd());
|
|
183
|
+
if (options.apiKey) {
|
|
184
|
+
process.env.LINEAR_API_KEY = options.apiKey;
|
|
185
|
+
console.log(chalk.green("\u2713 API key configured"));
|
|
186
|
+
const client = new LinearClient({ apiKey: options.apiKey });
|
|
187
|
+
const user = await client.getViewer();
|
|
188
|
+
console.log(chalk.cyan(`Connected as: ${user.name} (${user.email})`));
|
|
189
|
+
} else {
|
|
190
|
+
console.log(chalk.cyan("Linear Authentication"));
|
|
191
|
+
console.log("\nOption 1: API Key (Recommended for automation)");
|
|
192
|
+
console.log(" 1. Go to: https://linear.app/settings/api");
|
|
193
|
+
console.log(" 2. Create a personal API key");
|
|
194
|
+
console.log(" 3. Run: stackmemory linear auth --api-key YOUR_KEY");
|
|
195
|
+
console.log("\nOption 2: OAuth (For user-facing apps)");
|
|
196
|
+
console.log(" Configure OAuth app and use linear-oauth-server");
|
|
197
|
+
}
|
|
198
|
+
} catch (error) {
|
|
199
|
+
console.error(chalk.red("Authentication failed:"), error.message);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
function displaySyncStats(stats) {
|
|
204
|
+
const table = new Table({
|
|
205
|
+
head: ["Direction", "Created", "Updated", "Merged", "Skipped"],
|
|
206
|
+
style: { head: ["cyan"] }
|
|
207
|
+
});
|
|
208
|
+
table.push(
|
|
209
|
+
["\u2192 Linear", stats.toLinear.created, stats.toLinear.updated, stats.toLinear.duplicatesMerged, stats.toLinear.skipped],
|
|
210
|
+
["\u2190 Linear", stats.fromLinear.created, stats.fromLinear.updated, "-", stats.fromLinear.skipped]
|
|
211
|
+
);
|
|
212
|
+
console.log("\n" + table.toString());
|
|
213
|
+
if (stats.conflicts.length > 0) {
|
|
214
|
+
console.log(chalk.yellow(`
|
|
215
|
+
\u26A0 Conflicts: ${stats.conflicts.length}`));
|
|
216
|
+
stats.conflicts.slice(0, 5).forEach((c) => {
|
|
217
|
+
console.log(` - ${c.reason}`);
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
if (stats.errors.length > 0) {
|
|
221
|
+
console.log(chalk.red(`
|
|
222
|
+
\u274C Errors: ${stats.errors.length}`));
|
|
223
|
+
stats.errors.slice(0, 5).forEach((e) => {
|
|
224
|
+
console.log(` - ${e.substring(0, 100)}`);
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
console.log(chalk.gray(`
|
|
228
|
+
Completed in ${stats.duration}ms`));
|
|
229
|
+
}
|
|
230
|
+
function displayTaskPlan(projectRoot, showReport = false) {
|
|
231
|
+
const reportFile = join(projectRoot, ".stackmemory", "task-report.md");
|
|
232
|
+
const planFile = join(projectRoot, ".stackmemory", "task-plan.json");
|
|
233
|
+
if (showReport && existsSync(reportFile)) {
|
|
234
|
+
const report = readFileSync(reportFile, "utf8");
|
|
235
|
+
console.log("\n" + report);
|
|
236
|
+
} else if (existsSync(planFile)) {
|
|
237
|
+
const plan = JSON.parse(readFileSync(planFile, "utf8"));
|
|
238
|
+
console.log(chalk.cyan("\n\u{1F4CB} Task Plan Overview"));
|
|
239
|
+
console.log(`Last updated: ${new Date(plan.lastUpdated).toLocaleString()}
|
|
240
|
+
`);
|
|
241
|
+
plan.phases.forEach((phase) => {
|
|
242
|
+
console.log(chalk.yellow(`${phase.name} (${phase.tasks.length})`));
|
|
243
|
+
console.log(chalk.gray(` ${phase.description}`));
|
|
244
|
+
if (phase.tasks.length > 0) {
|
|
245
|
+
phase.tasks.slice(0, 5).forEach((task) => {
|
|
246
|
+
const status = task.linearId ? "\u{1F517}" : " ";
|
|
247
|
+
console.log(` ${status} ${task.title}`);
|
|
248
|
+
});
|
|
249
|
+
if (phase.tasks.length > 5) {
|
|
250
|
+
console.log(chalk.gray(` ...and ${phase.tasks.length - 5} more`));
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
console.log();
|
|
254
|
+
});
|
|
255
|
+
} else {
|
|
256
|
+
console.log(chalk.yellow("No task plan found. Run sync with --task-plan to generate."));
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
export {
|
|
260
|
+
registerUnifiedLinearCommands
|
|
261
|
+
};
|
|
262
|
+
//# sourceMappingURL=linear-unified.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/cli/commands/linear-unified.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Unified Linear CLI Commands\n * Consolidates all Linear operations into a single, coherent interface\n */\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport { UnifiedLinearSync, UnifiedSyncConfig, SyncStats, DEFAULT_UNIFIED_CONFIG } from '../../integrations/linear/unified-sync.js';\nimport { LinearAuthManager } from '../../integrations/linear/auth.js';\nimport { LinearClient } from '../../integrations/linear/client.js';\nimport { PebblesTaskStore } from '../../features/tasks/pebbles-task-store.js';\nimport Database from 'better-sqlite3';\nimport { join } from 'path';\nimport { existsSync, readFileSync } from 'fs';\nimport { logger } from '../../core/monitoring/logger.js';\nimport Table from 'cli-table3';\nimport ora from 'ora';\n\nexport function registerUnifiedLinearCommands(parent: Command) {\n const linear = parent\n .command('linear')\n .description('Unified Linear integration with duplicate detection and task planning');\n\n // Main sync command with all features\n linear\n .command('sync')\n .description('Intelligent sync with Linear (duplicate detection, bidirectional, task planning)')\n .option('-d, --direction <dir>', 'Sync direction: bidirectional, to_linear, from_linear', 'bidirectional')\n .option('-t, --team <id>', 'Linear team ID')\n .option('--no-duplicates', 'Disable duplicate detection')\n .option('--merge-strategy <strategy>', 'Duplicate handling: merge_content, skip, create_anyway', 'merge_content')\n .option('--conflict <resolution>', 'Conflict resolution: newest_wins, linear_wins, local_wins', 'newest_wins')\n .option('--task-plan', 'Enable task planning integration')\n .option('--dry-run', 'Preview changes without syncing')\n .option('--daemon', 'Run as background daemon')\n .option('-i, --interval <minutes>', 'Auto-sync interval', '15')\n .option('--verbose', 'Show detailed sync progress')\n .action(async (options) => {\n const spinner = ora('Initializing Linear sync...').start();\n \n try {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n spinner.fail('StackMemory not initialized');\n console.log(chalk.yellow('Run \"stackmemory init\" first'));\n return;\n }\n\n // Initialize components\n const db = new Database(dbPath);\n const taskStore = new PebblesTaskStore(projectRoot, db);\n const authManager = new LinearAuthManager(projectRoot);\n\n // Build config from options\n const config: Partial<UnifiedSyncConfig> = {\n direction: options.direction,\n defaultTeamId: options.team,\n duplicateDetection: options.duplicates !== false,\n mergeStrategy: options.mergeStrategy,\n conflictResolution: options.conflict,\n taskPlanningEnabled: options.taskPlan || false,\n };\n\n // Create unified sync instance\n const unifiedSync = new UnifiedLinearSync(taskStore, authManager, projectRoot, config);\n\n // Listen to events for progress\n if (options.verbose) {\n unifiedSync.on('sync:started', ({ config }) => {\n spinner.text = `Syncing (${config.direction})...`;\n });\n }\n\n // Initialize\n spinner.text = 'Authenticating with Linear...';\n await unifiedSync.initialize();\n\n if (options.dryRun) {\n spinner.info('Dry run mode - no changes will be made');\n // TODO: Implement dry run preview\n return;\n }\n\n if (options.daemon) {\n // Daemon mode\n spinner.succeed('Starting sync daemon');\n console.log(chalk.cyan(`Sync interval: ${options.interval} minutes`));\n console.log(chalk.gray('Press Ctrl+C to stop\\n'));\n\n // Initial sync\n const stats = await unifiedSync.sync();\n displaySyncStats(stats);\n\n // Schedule periodic syncs\n const interval = setInterval(async () => {\n console.log(chalk.yellow(`\\n[${new Date().toLocaleTimeString()}] Running scheduled sync...`));\n try {\n const stats = await unifiedSync.sync();\n displaySyncStats(stats);\n } catch (error: unknown) {\n console.error(chalk.red('Sync failed:'), (error as Error).message);\n }\n }, parseInt(options.interval) * 60 * 1000);\n\n // Handle graceful shutdown\n process.on('SIGINT', () => {\n console.log(chalk.yellow('\\nStopping sync daemon...'));\n clearInterval(interval);\n db.close();\n process.exit(0);\n });\n\n // Keep process alive\n process.stdin.resume();\n } else {\n // Single sync\n spinner.text = 'Syncing tasks...';\n const stats = await unifiedSync.sync();\n \n spinner.succeed('Sync completed');\n displaySyncStats(stats);\n\n // Show task plan if enabled\n if (options.taskPlan) {\n displayTaskPlan(projectRoot);\n }\n\n db.close();\n }\n } catch (error: unknown) {\n spinner.fail('Sync failed');\n console.error(chalk.red('Error:'), (error as Error).message);\n if (options.verbose) {\n console.error(error);\n }\n process.exit(1);\n }\n });\n\n // Quick status command\n linear\n .command('status')\n .description('Show Linear connection status and sync statistics')\n .action(async () => {\n try {\n const authManager = new LinearAuthManager(process.cwd());\n const hasAuth = authManager.isConfigured();\n\n if (!hasAuth && !process.env.LINEAR_API_KEY) {\n console.log(chalk.yellow('\u26A0 Not connected to Linear'));\n console.log('Run \"stackmemory linear auth\" to connect');\n return;\n }\n\n console.log(chalk.green('\u2713 Linear connection configured'));\n\n // Show last sync stats if available\n const statsFile = join(process.cwd(), '.stackmemory', 'sync-stats.json');\n if (existsSync(statsFile)) {\n const stats = JSON.parse(readFileSync(statsFile, 'utf8'));\n console.log(chalk.cyan('\\nLast sync:'));\n console.log(` Time: ${new Date(stats.timestamp).toLocaleString()}`);\n console.log(` Duration: ${stats.duration}ms`);\n console.log(` To Linear: ${stats.toLinear.created} created, ${stats.toLinear.updated} updated`);\n console.log(` From Linear: ${stats.fromLinear.created} created, ${stats.fromLinear.updated} updated`);\n \n if (stats.toLinear.duplicatesMerged > 0) {\n console.log(chalk.green(` Duplicates prevented: ${stats.toLinear.duplicatesMerged}`));\n }\n }\n\n // Show task plan status\n const planFile = join(process.cwd(), '.stackmemory', 'task-plan.md');\n if (existsSync(planFile)) {\n console.log(chalk.cyan('\\n\u2713 Task planning enabled'));\n const reportFile = join(process.cwd(), '.stackmemory', 'task-report.md');\n if (existsSync(reportFile)) {\n console.log(` Report: ${reportFile}`);\n }\n }\n } catch (error: unknown) {\n console.error(chalk.red('Status check failed:'), (error as Error).message);\n }\n });\n\n // Task planning command\n linear\n .command('plan')\n .description('View and manage task planning')\n .option('--generate', 'Generate task plan from current tasks')\n .option('--report', 'Show task report')\n .action(async (options) => {\n try {\n const projectRoot = process.cwd();\n \n if (options.generate) {\n console.log(chalk.yellow('Generating task plan...'));\n // Run sync with task planning enabled\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n const db = new Database(dbPath);\n const taskStore = new PebblesTaskStore(projectRoot, db);\n const authManager = new LinearAuthManager(projectRoot);\n \n const unifiedSync = new UnifiedLinearSync(taskStore, authManager, projectRoot, {\n taskPlanningEnabled: true,\n autoCreateTaskPlan: true,\n });\n \n await unifiedSync.initialize();\n await unifiedSync.sync();\n \n console.log(chalk.green('\u2713 Task plan generated'));\n db.close();\n }\n \n displayTaskPlan(projectRoot, options.report);\n } catch (error: unknown) {\n console.error(chalk.red('Plan generation failed:'), (error as Error).message);\n }\n });\n\n // Duplicate detection command\n linear\n .command('duplicates')\n .description('Check for and manage duplicate Linear issues')\n .option('--check <title>', 'Check if a title would create a duplicate')\n .option('--merge', 'Merge detected duplicates')\n .option('--list', 'List potential duplicates')\n .action(async (options) => {\n try {\n const authManager = new LinearAuthManager(process.cwd());\n const token = await authManager.getValidToken();\n \n if (!token) {\n console.log(chalk.red('Not authenticated with Linear'));\n return;\n }\n\n const client = new LinearClient({\n apiKey: token,\n useBearer: authManager.isOAuth(),\n });\n\n if (options.check) {\n // Import dynamically to avoid circular dependency\n const { LinearDuplicateDetector } = await import('../../integrations/linear/sync-enhanced.js');\n const detector = new LinearDuplicateDetector(client);\n \n console.log(chalk.yellow(`Checking for duplicates of: \"${options.check}\"`));\n const result = await detector.checkForDuplicate(options.check);\n \n if (result.isDuplicate && result.existingIssue) {\n console.log(chalk.red('\u26A0 Duplicate detected!'));\n console.log(` Issue: ${result.existingIssue.identifier} - ${result.existingIssue.title}`);\n console.log(` Similarity: ${Math.round((result.similarity || 0) * 100)}%`);\n console.log(` URL: ${result.existingIssue.url}`);\n } else {\n console.log(chalk.green('\u2713 No duplicates found'));\n }\n } else if (options.list) {\n console.log(chalk.yellow('Scanning for potential duplicates...'));\n // TODO: Implement duplicate scanning\n console.log('Feature coming soon');\n } else {\n console.log('Specify --check, --merge, or --list');\n }\n } catch (error: unknown) {\n console.error(chalk.red('Duplicate check failed:'), (error as Error).message);\n }\n });\n\n // Auth command (simplified)\n linear\n .command('auth')\n .description('Authenticate with Linear')\n .option('--api-key <key>', 'Use API key')\n .option('--oauth', 'Use OAuth flow')\n .action(async (options) => {\n try {\n const authManager = new LinearAuthManager(process.cwd());\n\n if (options.apiKey) {\n // Simple API key setup\n process.env.LINEAR_API_KEY = options.apiKey;\n console.log(chalk.green('\u2713 API key configured'));\n \n // Test connection\n const client = new LinearClient({ apiKey: options.apiKey });\n const user = await client.getViewer();\n console.log(chalk.cyan(`Connected as: ${user.name} (${user.email})`));\n } else {\n console.log(chalk.cyan('Linear Authentication'));\n console.log('\\nOption 1: API Key (Recommended for automation)');\n console.log(' 1. Go to: https://linear.app/settings/api');\n console.log(' 2. Create a personal API key');\n console.log(' 3. Run: stackmemory linear auth --api-key YOUR_KEY');\n console.log('\\nOption 2: OAuth (For user-facing apps)');\n console.log(' Configure OAuth app and use linear-oauth-server');\n }\n } catch (error: unknown) {\n console.error(chalk.red('Authentication failed:'), (error as Error).message);\n }\n });\n}\n\n/**\n * Display sync statistics\n */\nfunction displaySyncStats(stats: SyncStats): void {\n const table = new Table({\n head: ['Direction', 'Created', 'Updated', 'Merged', 'Skipped'],\n style: { head: ['cyan'] },\n });\n\n table.push(\n ['\u2192 Linear', stats.toLinear.created, stats.toLinear.updated, stats.toLinear.duplicatesMerged, stats.toLinear.skipped],\n ['\u2190 Linear', stats.fromLinear.created, stats.fromLinear.updated, '-', stats.fromLinear.skipped]\n );\n\n console.log('\\n' + table.toString());\n\n if (stats.conflicts.length > 0) {\n console.log(chalk.yellow(`\\n\u26A0 Conflicts: ${stats.conflicts.length}`));\n stats.conflicts.slice(0, 5).forEach((c) => {\n console.log(` - ${c.reason}`);\n });\n }\n\n if (stats.errors.length > 0) {\n console.log(chalk.red(`\\n\u274C Errors: ${stats.errors.length}`));\n stats.errors.slice(0, 5).forEach((e: string) => {\n console.log(` - ${e.substring(0, 100)}`);\n });\n }\n\n console.log(chalk.gray(`\\nCompleted in ${stats.duration}ms`));\n}\n\n/**\n * Display task plan\n */\nfunction displayTaskPlan(projectRoot: string, showReport = false): void {\n const reportFile = join(projectRoot, '.stackmemory', 'task-report.md');\n const planFile = join(projectRoot, '.stackmemory', 'task-plan.json');\n\n if (showReport && existsSync(reportFile)) {\n const report = readFileSync(reportFile, 'utf8');\n console.log('\\n' + report);\n } else if (existsSync(planFile)) {\n const plan = JSON.parse(readFileSync(planFile, 'utf8'));\n \n console.log(chalk.cyan('\\n\uD83D\uDCCB Task Plan Overview'));\n console.log(`Last updated: ${new Date(plan.lastUpdated).toLocaleString()}\\n`);\n\n plan.phases.forEach((phase) => {\n console.log(chalk.yellow(`${phase.name} (${phase.tasks.length})`));\n console.log(chalk.gray(` ${phase.description}`));\n \n if (phase.tasks.length > 0) {\n phase.tasks.slice(0, 5).forEach((task) => {\n const status = task.linearId ? '\uD83D\uDD17' : ' ';\n console.log(` ${status} ${task.title}`);\n });\n \n if (phase.tasks.length > 5) {\n console.log(chalk.gray(` ...and ${phase.tasks.length - 5} more`));\n }\n }\n console.log();\n });\n } else {\n console.log(chalk.yellow('No task plan found. Run sync with --task-plan to generate.'));\n }\n}"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["config", "stats"]
|
|
7
|
+
}
|
|
@@ -20,6 +20,17 @@ import { join } from "path";
|
|
|
20
20
|
import { existsSync } from "fs";
|
|
21
21
|
import { logger } from "../../core/monitoring/logger.js";
|
|
22
22
|
import Table from "cli-table3";
|
|
23
|
+
function getEnv(key, defaultValue) {
|
|
24
|
+
const value = process.env[key];
|
|
25
|
+
if (value === void 0) {
|
|
26
|
+
if (defaultValue !== void 0) return defaultValue;
|
|
27
|
+
throw new Error(`Environment variable ${key} is required`);
|
|
28
|
+
}
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
function getOptionalEnv(key) {
|
|
32
|
+
return process.env[key];
|
|
33
|
+
}
|
|
23
34
|
function displaySyncResult(result) {
|
|
24
35
|
if (result.success) {
|
|
25
36
|
console.log(chalk.green("\u2713 Sync completed successfully"));
|
|
@@ -64,7 +75,7 @@ function registerLinearCommands(parent) {
|
|
|
64
75
|
"Filter by status (backlog, started, completed, etc.)"
|
|
65
76
|
).option("--my", "Show only tasks assigned to me").option("--cache", "Show cache stats only").option("--refresh", "Force refresh cache").option("--count", "Show count by status only").action(async (options) => {
|
|
66
77
|
try {
|
|
67
|
-
const apiKey = process.env
|
|
78
|
+
const apiKey = process.env["LINEAR_API_KEY"];
|
|
68
79
|
if (!apiKey) {
|
|
69
80
|
console.log(
|
|
70
81
|
chalk.yellow("\u26A0 Set LINEAR_API_KEY environment variable")
|
|
@@ -138,7 +149,7 @@ ${displayTasks.length} shown, ${tasks.length} total tasks`
|
|
|
138
149
|
linear.command("auth").description("Authenticate with Linear").option("--api-key <key>", "Use API key instead of OAuth").option("--no-browser", "Do not open browser automatically").action(async (options) => {
|
|
139
150
|
try {
|
|
140
151
|
if (options.apiKey) {
|
|
141
|
-
process.env
|
|
152
|
+
process.env["LINEAR_API_KEY"] = options.apiKey;
|
|
142
153
|
console.log(chalk.green("\u2713 Linear API key set"));
|
|
143
154
|
const client = new LinearClient({ apiKey: options.apiKey });
|
|
144
155
|
const user = await client.getViewer();
|
|
@@ -149,8 +160,8 @@ ${displayTasks.length} shown, ${tasks.length} total tasks`
|
|
|
149
160
|
}
|
|
150
161
|
} else {
|
|
151
162
|
const authManager = new LinearAuthManager(process.cwd());
|
|
152
|
-
const clientId = process.env
|
|
153
|
-
const clientSecret = process.env
|
|
163
|
+
const clientId = process.env["LINEAR_CLIENT_ID"];
|
|
164
|
+
const clientSecret = process.env["LINEAR_CLIENT_SECRET"];
|
|
154
165
|
if (!clientId || !clientSecret) {
|
|
155
166
|
console.log(chalk.yellow("\n\u26A0 Linear OAuth app not configured"));
|
|
156
167
|
console.log(chalk.cyan("\n\u{1F4DD} Setup Instructions:"));
|
|
@@ -305,7 +316,7 @@ ${displayTasks.length} shown, ${tasks.length} total tasks`
|
|
|
305
316
|
try {
|
|
306
317
|
const authManager = new LinearAuthManager(process.cwd());
|
|
307
318
|
const tokens = authManager.loadTokens();
|
|
308
|
-
const apiKey = process.env
|
|
319
|
+
const apiKey = process.env["LINEAR_API_KEY"];
|
|
309
320
|
if (!tokens && !apiKey) {
|
|
310
321
|
console.log(chalk.yellow("\u26A0 Not authenticated with Linear"));
|
|
311
322
|
console.log('Run "stackmemory linear auth" to connect');
|
|
@@ -345,7 +356,7 @@ ${displayTasks.length} shown, ${tasks.length} total tasks`
|
|
|
345
356
|
"Filter by status (backlog, started, completed, etc.)"
|
|
346
357
|
).option("--my", "Show only tasks assigned to me").option("--cache", "Show cache stats").option("--refresh", "Force refresh cache").action(async (options) => {
|
|
347
358
|
try {
|
|
348
|
-
const apiKey = process.env
|
|
359
|
+
const apiKey = process.env["LINEAR_API_KEY"];
|
|
349
360
|
if (!apiKey) {
|
|
350
361
|
console.log(
|
|
351
362
|
chalk.yellow("\u26A0 Set LINEAR_API_KEY environment variable")
|