@hyperdrive.bot/gut 0.1.6 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/README.md +1 -1
  2. package/dist/base-command.d.ts +22 -0
  3. package/dist/base-command.js +99 -0
  4. package/dist/commands/add.d.ts +14 -0
  5. package/dist/commands/add.js +70 -0
  6. package/dist/commands/affected.d.ts +23 -0
  7. package/dist/commands/affected.js +323 -0
  8. package/dist/commands/audit.d.ts +33 -0
  9. package/dist/commands/audit.js +594 -0
  10. package/dist/commands/back.d.ts +6 -0
  11. package/dist/commands/back.js +29 -0
  12. package/dist/commands/checkout.d.ts +14 -0
  13. package/dist/commands/checkout.js +124 -0
  14. package/dist/commands/commit.d.ts +11 -0
  15. package/dist/commands/commit.js +107 -0
  16. package/dist/commands/context.d.ts +6 -0
  17. package/dist/commands/context.js +32 -0
  18. package/dist/commands/contexts.d.ts +7 -0
  19. package/dist/commands/contexts.js +88 -0
  20. package/dist/commands/deps.d.ts +10 -0
  21. package/dist/commands/deps.js +100 -0
  22. package/dist/commands/entity/add.d.ts +16 -0
  23. package/dist/commands/entity/add.js +103 -0
  24. package/dist/commands/entity/clone-all.d.ts +17 -0
  25. package/dist/commands/entity/clone-all.js +127 -0
  26. package/dist/commands/entity/clone.d.ts +15 -0
  27. package/dist/commands/entity/clone.js +106 -0
  28. package/dist/commands/entity/list.d.ts +11 -0
  29. package/dist/commands/entity/list.js +80 -0
  30. package/dist/commands/entity/remove.d.ts +12 -0
  31. package/dist/commands/entity/remove.js +54 -0
  32. package/dist/commands/extract.d.ts +35 -0
  33. package/dist/commands/extract.js +483 -0
  34. package/dist/commands/focus.d.ts +19 -0
  35. package/dist/commands/focus.js +137 -0
  36. package/dist/commands/graph.d.ts +18 -0
  37. package/dist/commands/graph.js +273 -0
  38. package/dist/commands/init.d.ts +11 -0
  39. package/dist/commands/init.js +75 -0
  40. package/dist/commands/insights.d.ts +21 -0
  41. package/dist/commands/insights.js +465 -0
  42. package/dist/commands/patterns.d.ts +40 -0
  43. package/dist/commands/patterns.js +405 -0
  44. package/dist/commands/pull.d.ts +11 -0
  45. package/dist/commands/pull.js +121 -0
  46. package/dist/commands/push.d.ts +11 -0
  47. package/dist/commands/push.js +97 -0
  48. package/dist/commands/quick-setup.d.ts +20 -0
  49. package/dist/commands/quick-setup.js +417 -0
  50. package/dist/commands/recent.d.ts +9 -0
  51. package/dist/commands/recent.js +51 -0
  52. package/dist/commands/related.d.ts +23 -0
  53. package/dist/commands/related.js +255 -0
  54. package/dist/commands/repos.d.ts +17 -0
  55. package/dist/commands/repos.js +184 -0
  56. package/dist/commands/stack.d.ts +10 -0
  57. package/dist/commands/stack.js +78 -0
  58. package/dist/commands/status.d.ts +13 -0
  59. package/dist/commands/status.js +193 -0
  60. package/dist/commands/sync.d.ts +11 -0
  61. package/dist/commands/sync.js +139 -0
  62. package/dist/commands/ticket/focus.d.ts +20 -0
  63. package/dist/commands/ticket/focus.js +217 -0
  64. package/dist/commands/ticket/get.d.ts +15 -0
  65. package/dist/commands/ticket/get.js +168 -0
  66. package/dist/commands/ticket/hint.d.ts +16 -0
  67. package/dist/commands/ticket/hint.js +147 -0
  68. package/dist/commands/ticket/index.d.ts +10 -0
  69. package/dist/commands/ticket/index.js +60 -0
  70. package/dist/commands/ticket/list.d.ts +13 -0
  71. package/dist/commands/ticket/list.js +120 -0
  72. package/dist/commands/ticket/sync.d.ts +14 -0
  73. package/dist/commands/ticket/sync.js +85 -0
  74. package/dist/commands/ticket/update.d.ts +17 -0
  75. package/dist/commands/ticket/update.js +142 -0
  76. package/dist/commands/unfocus.d.ts +6 -0
  77. package/dist/commands/unfocus.js +19 -0
  78. package/dist/commands/used-by.d.ts +13 -0
  79. package/dist/commands/used-by.js +110 -0
  80. package/dist/commands/workspace.d.ts +22 -0
  81. package/dist/commands/workspace.js +372 -0
  82. package/dist/index.d.ts +14 -0
  83. package/dist/index.js +16 -0
  84. package/dist/models/entity.model.d.ts +234 -0
  85. package/dist/models/entity.model.js +1 -0
  86. package/dist/models/ticket.model.d.ts +117 -0
  87. package/dist/models/ticket.model.js +43 -0
  88. package/dist/services/auth.service.d.ts +15 -0
  89. package/dist/services/auth.service.js +26 -0
  90. package/dist/services/config.service.d.ts +34 -0
  91. package/dist/services/config.service.js +234 -0
  92. package/dist/services/entity.service.d.ts +20 -0
  93. package/dist/services/entity.service.js +127 -0
  94. package/dist/services/focus.service.d.ts +71 -0
  95. package/dist/services/focus.service.js +614 -0
  96. package/dist/services/git.service.d.ts +39 -0
  97. package/dist/services/git.service.js +188 -0
  98. package/dist/services/gut-api.service.d.ts +53 -0
  99. package/dist/services/gut-api.service.js +99 -0
  100. package/dist/services/ticket.service.d.ts +84 -0
  101. package/dist/services/ticket.service.js +207 -0
  102. package/dist/utils/display.d.ts +26 -0
  103. package/dist/utils/display.js +145 -0
  104. package/dist/utils/filesystem.d.ts +32 -0
  105. package/dist/utils/filesystem.js +198 -0
  106. package/dist/utils/index.d.ts +13 -0
  107. package/dist/utils/index.js +14 -0
  108. package/dist/utils/validation.d.ts +22 -0
  109. package/dist/utils/validation.js +192 -0
  110. package/oclif.manifest.json +2008 -0
  111. package/package.json +11 -2
@@ -0,0 +1,234 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ export class ConfigService {
4
+ config = null;
5
+ configFile;
6
+ focus = null;
7
+ focusContextFile;
8
+ focusDir;
9
+ focusFile;
10
+ gutDir;
11
+ history = [];
12
+ historyFile;
13
+ workspaceRoot;
14
+ constructor(workspaceRoot) {
15
+ this.workspaceRoot = workspaceRoot || process.env.DS_WORKSPACE || process.cwd();
16
+ this.gutDir = path.join(this.workspaceRoot, '.gut');
17
+ this.focusDir = path.join(this.workspaceRoot, 'focus');
18
+ this.focusFile = path.join(this.gutDir, 'focus.json');
19
+ this.configFile = path.join(this.gutDir, 'config.json');
20
+ this.historyFile = path.join(this.gutDir, 'history.json');
21
+ this.focusContextFile = path.join(this.focusDir, 'context.yaml');
22
+ this.ensureDirectories();
23
+ this.loadAll();
24
+ }
25
+ addToHistory(focus) {
26
+ try {
27
+ if (!this.history)
28
+ this.history = [];
29
+ // Convert focus entities to string array for history
30
+ const entityNames = focus.entities ? focus.entities.map(e => e.name) : [focus.name];
31
+ // Don't add duplicate consecutive entries
32
+ const lastEntry = this.history.at(-1);
33
+ if (lastEntry
34
+ && lastEntry.entities.length === entityNames.length
35
+ && lastEntry.entities.every(e => entityNames.includes(e))) {
36
+ return;
37
+ }
38
+ // Add timestamp and limit history to 10 entries
39
+ const entry = {
40
+ entities: entityNames,
41
+ timestamp: Date.now(),
42
+ };
43
+ this.history.push(entry);
44
+ if (this.history.length > 10) {
45
+ this.history = this.history.slice(-10);
46
+ }
47
+ fs.writeFileSync(this.historyFile, JSON.stringify(this.history, null, 2));
48
+ }
49
+ catch (error) {
50
+ const message = error instanceof Error ? error.message : String(error);
51
+ console.warn('⚠️ Could not save history:', message);
52
+ }
53
+ }
54
+ clearHistory() {
55
+ this.history = [];
56
+ try {
57
+ if (fs.existsSync(this.historyFile)) {
58
+ fs.unlinkSync(this.historyFile);
59
+ }
60
+ }
61
+ catch (error) {
62
+ const message = error instanceof Error ? error.message : String(error);
63
+ console.warn('⚠️ Could not clear history:', message);
64
+ }
65
+ }
66
+ getConfig() {
67
+ if (!this.config) {
68
+ this.config = this.loadConfigSync();
69
+ }
70
+ return this.config || { entities: [], initialized: false };
71
+ }
72
+ getFocus() {
73
+ return this.focus;
74
+ }
75
+ getFocusDir() {
76
+ return this.focusDir;
77
+ }
78
+ getGutDir() {
79
+ return this.gutDir;
80
+ }
81
+ getHistory() {
82
+ return this.history;
83
+ }
84
+ getWorkspaceRoot() {
85
+ return this.workspaceRoot;
86
+ }
87
+ async initWorkspace(workspacePath) {
88
+ const config = {
89
+ entities: [],
90
+ initialized: true,
91
+ workspace: workspacePath,
92
+ };
93
+ this.saveConfig(config);
94
+ }
95
+ isInitialized() {
96
+ return this.config?.initialized || false;
97
+ }
98
+ async loadConfig() {
99
+ try {
100
+ if (fs.existsSync(this.configFile)) {
101
+ const content = fs.readFileSync(this.configFile, 'utf8');
102
+ return JSON.parse(content);
103
+ }
104
+ }
105
+ catch (error) {
106
+ const message = error instanceof Error ? error.message : String(error);
107
+ console.warn('⚠️ Could not load config:', message);
108
+ }
109
+ return { entities: [], initialized: false, workspace: this.workspaceRoot };
110
+ }
111
+ saveConfig(config) {
112
+ try {
113
+ fs.writeFileSync(this.configFile, JSON.stringify(config, null, 2));
114
+ this.config = config;
115
+ }
116
+ catch (error) {
117
+ const message = error instanceof Error ? error.message : String(error);
118
+ throw new Error(`Could not save config: ${message}`);
119
+ }
120
+ }
121
+ saveFocus(focus) {
122
+ try {
123
+ // Save to history before changing focus
124
+ if (this.focus && focus) {
125
+ this.addToHistory(this.focus);
126
+ }
127
+ if (focus) {
128
+ fs.writeFileSync(this.focusFile, JSON.stringify(focus, null, 2));
129
+ }
130
+ else if (fs.existsSync(this.focusFile)) {
131
+ fs.unlinkSync(this.focusFile);
132
+ }
133
+ this.focus = focus;
134
+ }
135
+ catch (error) {
136
+ const message = error instanceof Error ? error.message : String(error);
137
+ throw new Error(`Could not save focus state: ${message}`);
138
+ }
139
+ }
140
+ async saveFocusContext(context) {
141
+ try {
142
+ // Convert to YAML format (simplified - would use a YAML library in production)
143
+ const yamlContent = this.convertToYaml(context);
144
+ fs.writeFileSync(this.focusContextFile, yamlContent);
145
+ }
146
+ catch (error) {
147
+ const message = error instanceof Error ? error.message : String(error);
148
+ console.warn('⚠️ Could not save focus context:', message);
149
+ }
150
+ }
151
+ convertToYaml(obj, indent = 0) {
152
+ // Simple YAML converter - in production would use js-yaml library
153
+ const spaces = ' '.repeat(indent);
154
+ let yaml = '';
155
+ for (const [key, value] of Object.entries(obj)) {
156
+ if (value === null || value === undefined) {
157
+ continue;
158
+ }
159
+ if (typeof value === 'object' && !Array.isArray(value)) {
160
+ yaml += `${spaces}${key}:\n`;
161
+ yaml += this.convertToYaml(value, indent + 1);
162
+ }
163
+ else if (Array.isArray(value)) {
164
+ yaml += `${spaces}${key}:\n`;
165
+ for (const item of value) {
166
+ if (typeof item === 'object' && item !== null) {
167
+ yaml += `${spaces} -\n`;
168
+ yaml += this.convertToYaml(item, indent + 2);
169
+ }
170
+ else {
171
+ yaml += `${spaces} - ${String(item)}\n`;
172
+ }
173
+ }
174
+ }
175
+ else {
176
+ const valueStr = typeof value === 'string' ? `"${value}"` : String(value);
177
+ yaml += `${spaces}${key}: ${valueStr}\n`;
178
+ }
179
+ }
180
+ return yaml;
181
+ }
182
+ ensureDirectories() {
183
+ if (!fs.existsSync(this.gutDir)) {
184
+ fs.mkdirSync(this.gutDir, { recursive: true });
185
+ }
186
+ if (!fs.existsSync(this.focusDir)) {
187
+ fs.mkdirSync(this.focusDir, { recursive: true });
188
+ }
189
+ }
190
+ loadAll() {
191
+ this.config = this.loadConfigSync();
192
+ this.focus = this.loadFocus();
193
+ this.history = this.loadHistory();
194
+ }
195
+ loadConfigSync() {
196
+ try {
197
+ if (fs.existsSync(this.configFile)) {
198
+ const content = fs.readFileSync(this.configFile, 'utf8');
199
+ return JSON.parse(content);
200
+ }
201
+ }
202
+ catch (error) {
203
+ const message = error instanceof Error ? error.message : String(error);
204
+ console.warn('⚠️ Could not load config:', message);
205
+ }
206
+ return { entities: [], initialized: false };
207
+ }
208
+ loadFocus() {
209
+ try {
210
+ if (fs.existsSync(this.focusFile)) {
211
+ const content = fs.readFileSync(this.focusFile, 'utf8');
212
+ return JSON.parse(content);
213
+ }
214
+ }
215
+ catch (error) {
216
+ const message = error instanceof Error ? error.message : String(error);
217
+ console.warn('⚠️ Could not load focus state:', message);
218
+ }
219
+ return null;
220
+ }
221
+ loadHistory() {
222
+ try {
223
+ if (fs.existsSync(this.historyFile)) {
224
+ const content = fs.readFileSync(this.historyFile, 'utf8');
225
+ return JSON.parse(content);
226
+ }
227
+ }
228
+ catch (error) {
229
+ const message = error instanceof Error ? error.message : String(error);
230
+ console.warn('⚠️ Could not load history:', message);
231
+ }
232
+ return [];
233
+ }
234
+ }
@@ -0,0 +1,20 @@
1
+ import { Entity, EntityType } from '../models/entity.model.js';
2
+ import { ConfigService } from './config.service.js';
3
+ export declare class EntityService {
4
+ private configService;
5
+ constructor(configService: ConfigService);
6
+ addEntity(name: string, type: EntityType, entityPath: string, repository?: string): Promise<void>;
7
+ discoverEntities(): Entity[];
8
+ findEntity(name: string): Entity | undefined;
9
+ findEntityByTypeAndName(type: EntityType, name: string): Entity | undefined;
10
+ getAllEntities(): Entity[];
11
+ getEntitiesByType(type: EntityType): Entity[];
12
+ getEntity(name: string): Promise<Entity | null>;
13
+ getEntityByPath(searchPath: string): Entity | undefined;
14
+ listEntities(): Promise<Entity[]>;
15
+ removeEntity(name: string): void;
16
+ resolveEntityPath(entity: Entity): string;
17
+ updateEntity(name: string, updates: Partial<Entity>): Promise<void>;
18
+ validateEntityName(name: string): boolean;
19
+ private toAbsolutePath;
20
+ }
@@ -0,0 +1,127 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ const ENTITY_NAME_PATTERN = /^[a-zA-Z0-9-_]+$/;
4
+ export class EntityService {
5
+ configService;
6
+ constructor(configService) {
7
+ this.configService = configService;
8
+ }
9
+ async addEntity(name, type, entityPath, repository) {
10
+ const entity = {
11
+ name, path: entityPath, repository, type,
12
+ };
13
+ const config = this.configService.getConfig();
14
+ // Check if entity already exists
15
+ if (this.findEntity(entity.name)) {
16
+ throw new Error(`Entity '${entity.name}' already exists`);
17
+ }
18
+ const absolutePath = this.toAbsolutePath(entityPath);
19
+ if (!fs.existsSync(absolutePath)) {
20
+ // Create directory if it doesn't exist
21
+ fs.mkdirSync(absolutePath, { recursive: true });
22
+ }
23
+ // Add entity
24
+ config.entities = config.entities || [];
25
+ config.entities.push(entity);
26
+ this.configService.saveConfig(config);
27
+ }
28
+ discoverEntities() {
29
+ const discovered = [];
30
+ const workspaceRoot = this.configService.getWorkspaceRoot();
31
+ // Common patterns for entity discovery
32
+ const patterns = [
33
+ { dir: 'apps', type: 'delivery' },
34
+ { dir: 'packages', type: 'module' },
35
+ { dir: 'libs', type: 'module' },
36
+ { dir: 'services', type: 'service' },
37
+ { dir: 'tools', type: 'tool' },
38
+ ];
39
+ for (const pattern of patterns) {
40
+ const dirPath = path.join(workspaceRoot, pattern.dir);
41
+ if (fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory()) {
42
+ const subdirs = fs.readdirSync(dirPath)
43
+ .filter(item => {
44
+ const itemPath = path.join(dirPath, item);
45
+ return fs.statSync(itemPath).isDirectory() && !item.startsWith('.');
46
+ });
47
+ for (const subdir of subdirs) {
48
+ const entityPath = path.join(pattern.dir, subdir);
49
+ const fullPath = path.join(workspaceRoot, entityPath);
50
+ // Check if it's a git repository or has package.json
51
+ const hasGit = fs.existsSync(path.join(fullPath, '.git'));
52
+ const hasPackageJson = fs.existsSync(path.join(fullPath, 'package.json'));
53
+ if (hasGit || hasPackageJson) {
54
+ discovered.push({
55
+ name: subdir,
56
+ path: `./${entityPath}`,
57
+ type: pattern.type,
58
+ });
59
+ }
60
+ }
61
+ }
62
+ }
63
+ return discovered;
64
+ }
65
+ findEntity(name) {
66
+ const entities = this.getAllEntities();
67
+ return entities.find(e => e.name === name);
68
+ }
69
+ findEntityByTypeAndName(type, name) {
70
+ const entities = this.getAllEntities();
71
+ return entities.find(e => e.type === type && e.name === name);
72
+ }
73
+ getAllEntities() {
74
+ const config = this.configService.getConfig();
75
+ return config.entities || [];
76
+ }
77
+ getEntitiesByType(type) {
78
+ return this.getAllEntities().filter(e => e.type === type);
79
+ }
80
+ async getEntity(name) {
81
+ const entity = this.findEntity(name);
82
+ return entity || null;
83
+ }
84
+ getEntityByPath(searchPath) {
85
+ const entities = this.getAllEntities();
86
+ const absoluteSearchPath = path.resolve(searchPath);
87
+ return entities.find(entity => {
88
+ const entityPath = this.resolveEntityPath(entity);
89
+ return path.resolve(entityPath) === absoluteSearchPath;
90
+ });
91
+ }
92
+ async listEntities() {
93
+ return this.getAllEntities();
94
+ }
95
+ removeEntity(name) {
96
+ const config = this.configService.getConfig();
97
+ if (!this.findEntity(name)) {
98
+ throw new Error(`Entity '${name}' not found`);
99
+ }
100
+ config.entities = config.entities.filter(e => e.name !== name);
101
+ this.configService.saveConfig(config);
102
+ }
103
+ resolveEntityPath(entity) {
104
+ return this.toAbsolutePath(entity.path);
105
+ }
106
+ async updateEntity(name, updates) {
107
+ const config = this.configService.getConfig();
108
+ const entityIndex = config.entities.findIndex(e => e.name === name);
109
+ if (entityIndex === -1) {
110
+ throw new Error(`Entity '${name}' not found`);
111
+ }
112
+ config.entities[entityIndex] = {
113
+ ...config.entities[entityIndex],
114
+ ...updates,
115
+ };
116
+ this.configService.saveConfig(config);
117
+ }
118
+ validateEntityName(name) {
119
+ return ENTITY_NAME_PATTERN.test(name);
120
+ }
121
+ toAbsolutePath(relativePath) {
122
+ if (path.isAbsolute(relativePath)) {
123
+ return relativePath;
124
+ }
125
+ return path.join(this.configService.getWorkspaceRoot(), relativePath);
126
+ }
127
+ }
@@ -0,0 +1,71 @@
1
+ import { Entity, EntityType, Focus, FocusMode, HistoryEntry } from '../models/entity.model.js';
2
+ import { ConfigService } from './config.service.js';
3
+ export interface FocusOptions {
4
+ duration?: string;
5
+ entityType?: EntityType;
6
+ mode?: FocusMode;
7
+ }
8
+ export declare class FocusService {
9
+ private configService;
10
+ private entityService;
11
+ private focusStack;
12
+ constructor(configService: ConfigService);
13
+ addToFocus(entityNames: string[], options?: FocusOptions): Promise<void>;
14
+ clearFocus(): Promise<void>;
15
+ clearFocusStack(): number;
16
+ getCurrentFocus(): Promise<Focus | null>;
17
+ getFocusDescription(): Promise<string>;
18
+ getFocusedEntities(): Promise<Entity[]>;
19
+ getFocusStack(): Focus[];
20
+ getRecentFocus(limit?: number): HistoryEntry[];
21
+ isFocused(entityName: string): Promise<boolean>;
22
+ popFocusFromStack(): Promise<Focus | null>;
23
+ pushFocusToStack(): Promise<void>;
24
+ setFocus(entityNames: string[], options?: FocusOptions): Promise<void>;
25
+ switchToPrevious(): Promise<void>;
26
+ private assessComplexity;
27
+ private assessInterruptionRisk;
28
+ private assessSuccessProbability;
29
+ private determineContextType;
30
+ private estimateFocusDuration;
31
+ private generateAdaptiveSuggestions;
32
+ private generateAIContext;
33
+ private generateCollaborationContext;
34
+ private generateContextIntelligence;
35
+ private generateFocusContext;
36
+ private generateLearningInsights;
37
+ private generatePerformanceContext;
38
+ private getActiveTeamMembers;
39
+ private getAvailableDataForEntity;
40
+ private getBenchmarks;
41
+ private getBusinessContext;
42
+ private getCollaborationPatterns;
43
+ private getCommonPitfalls;
44
+ private getCommunicationPreferences;
45
+ private getContextSpecificTips;
46
+ private getCoordinationNeeds;
47
+ private getCurrentVelocity;
48
+ private getDayBasedSuggestions;
49
+ private getHistoricalPatterns;
50
+ private getKnowledgeScopeForMode;
51
+ private getLearningOpportunities;
52
+ private getOptimizationOpportunities;
53
+ private getPerformanceMetrics;
54
+ private getPerformanceTrends;
55
+ private getPersonaForMode;
56
+ private getProductivityOptimizations;
57
+ private getRecentActivity;
58
+ private getRecentPatterns;
59
+ private getRecommendedApproach;
60
+ private getRelatedEntities;
61
+ private getRestrictedKnowledgeForMode;
62
+ private getSharedResources;
63
+ private getSimilarEntityLessons;
64
+ private getSuccessFactors;
65
+ private getSuggestedActionsForMode;
66
+ private getTeamMembers;
67
+ private getTechnicalContext;
68
+ private getTimeBasedSuggestions;
69
+ private getWorkflowSuggestions;
70
+ private identifyBottlenecks;
71
+ }