ai-summon 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/speckit.analyze.md +184 -0
- package/.claude/commands/speckit.checklist.md +294 -0
- package/.claude/commands/speckit.clarify.md +177 -0
- package/.claude/commands/speckit.constitution.md +78 -0
- package/.claude/commands/speckit.implement.md +121 -0
- package/.claude/commands/speckit.plan.md +81 -0
- package/.claude/commands/speckit.specify.md +204 -0
- package/.claude/commands/speckit.tasks.md +108 -0
- package/.claude/settings.local.json +23 -0
- package/.prettierignore +5 -0
- package/.prettierrc.json +10 -0
- package/.specify/memory/constitution.md +72 -0
- package/.specify/scripts/bash/check-prerequisites.sh +166 -0
- package/.specify/scripts/bash/common.sh +113 -0
- package/.specify/scripts/bash/create-new-feature.sh +97 -0
- package/.specify/scripts/bash/setup-plan.sh +60 -0
- package/.specify/scripts/bash/update-agent-context.sh +738 -0
- package/.specify/templates/agent-file-template.md +28 -0
- package/.specify/templates/checklist-template.md +40 -0
- package/.specify/templates/plan-template.md +111 -0
- package/.specify/templates/spec-template.md +115 -0
- package/.specify/templates/tasks-template.md +250 -0
- package/CLAUDE.md +199 -0
- package/PRD.md +268 -0
- package/README.md +171 -0
- package/dist/ai-summon.d.ts +2 -0
- package/dist/ai-summon.js +73 -0
- package/dist/commands/ide/index.d.ts +3 -0
- package/dist/commands/ide/index.js +253 -0
- package/dist/commands/init.d.ts +4 -0
- package/dist/commands/init.js +55 -0
- package/dist/commands/url.d.ts +4 -0
- package/dist/commands/url.js +223 -0
- package/dist/types/index.d.ts +40 -0
- package/dist/types/index.js +1 -0
- package/dist/util.d.ts +16 -0
- package/dist/util.js +109 -0
- package/eslint.config.js +47 -0
- package/package.json +47 -0
- package/specs/001-cloud-login-feature/contracts/cloud-command.ts +82 -0
- package/specs/001-cloud-login-feature/contracts/config-service.ts +170 -0
- package/specs/001-cloud-login-feature/data-model.md +269 -0
- package/specs/001-cloud-login-feature/plan.md +91 -0
- package/specs/001-cloud-login-feature/quickstart.md +366 -0
- package/specs/001-cloud-login-feature/research.md +290 -0
- package/specs/001-cloud-login-feature/spec.md +195 -0
- package/specs/001-cloud-login-feature/tasks.md +235 -0
- package/specs/001-cloud-scp-command/contracts/cloud-scp-api.ts +402 -0
- package/specs/001-cloud-scp-command/data-model.md +424 -0
- package/specs/001-cloud-scp-command/plan.md +124 -0
- package/specs/001-cloud-scp-command/quickstart.md +536 -0
- package/specs/001-cloud-scp-command/research.md +345 -0
- package/specs/001-cloud-scp-command/spec.md +248 -0
- package/specs/001-cloud-scp-command/tasks.md +434 -0
- package/src/ai-summon.ts +88 -0
- package/src/commands/ide/index.ts +322 -0
- package/src/commands/init.ts +64 -0
- package/src/commands/url.ts +262 -0
- package/src/types/index.ts +49 -0
- package/src/util.ts +146 -0
- package/tsconfig.json +21 -0
package/src/util.ts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { readFileSync, existsSync, readdirSync, mkdirSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join, basename } from 'path';
|
|
3
|
+
import { dirname } from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import { homedir } from 'os';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import { HshConfig } from './types/index.js';
|
|
8
|
+
|
|
9
|
+
export const getPackageJson = () => {
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = dirname(__filename);
|
|
12
|
+
const packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));
|
|
13
|
+
return packageJson;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const getConfigPath = (): string => {
|
|
17
|
+
const dir = join(homedir(), '.ai');
|
|
18
|
+
mkdirSync(dir, { recursive: true });
|
|
19
|
+
return join(dir, 'config.json');
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const readConfig = (): HshConfig => {
|
|
23
|
+
const configPath = getConfigPath();
|
|
24
|
+
|
|
25
|
+
if (!existsSync(configPath)) {
|
|
26
|
+
console.log(
|
|
27
|
+
chalk.yellow(
|
|
28
|
+
`Configuration file not found: ${configPath}\n` +
|
|
29
|
+
`Run "ai init" to create it and set your workingDirectory.`
|
|
30
|
+
)
|
|
31
|
+
);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const configContent = readFileSync(configPath, 'utf-8');
|
|
36
|
+
const config = JSON.parse(configContent);
|
|
37
|
+
|
|
38
|
+
// If workingDirectory is configured but repos/yiren are not, initialize them
|
|
39
|
+
if (config.workingDirectory && !config.repos) {
|
|
40
|
+
return {
|
|
41
|
+
workingDirectory: config.workingDirectory,
|
|
42
|
+
repos: {},
|
|
43
|
+
yiren: config.yiren || {},
|
|
44
|
+
urls: config.urls,
|
|
45
|
+
urlGroups: config.urlGroups,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return config as HshConfig;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Recursively scan directory for Git repositories
|
|
54
|
+
* Returns list of { name, path, topLevelFolder } objects
|
|
55
|
+
*/
|
|
56
|
+
export interface GitRepository {
|
|
57
|
+
name: string;
|
|
58
|
+
path: string;
|
|
59
|
+
topLevelFolder: string; // Top-level folder name relative to workingDirectory
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
interface IdeReposCacheFileV1 {
|
|
63
|
+
version: 1;
|
|
64
|
+
workingDirectory: string;
|
|
65
|
+
updatedAt: number;
|
|
66
|
+
repos: GitRepository[];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const ensureAiDir = (): string => {
|
|
70
|
+
const dir = join(homedir(), '.ai');
|
|
71
|
+
mkdirSync(dir, { recursive: true });
|
|
72
|
+
return dir;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const getIdeReposCachePath = (): string => {
|
|
76
|
+
const dir = ensureAiDir();
|
|
77
|
+
return join(dir, 'ide-repos-cache.json');
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export const readIdeReposCache = (workingDirectory: string): GitRepository[] | null => {
|
|
81
|
+
const cachePath = getIdeReposCachePath();
|
|
82
|
+
if (!existsSync(cachePath)) return null;
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
const raw = readFileSync(cachePath, 'utf-8');
|
|
86
|
+
const parsed = JSON.parse(raw) as Partial<IdeReposCacheFileV1>;
|
|
87
|
+
|
|
88
|
+
if (parsed.version !== 1) return null;
|
|
89
|
+
if (parsed.workingDirectory !== workingDirectory) return null;
|
|
90
|
+
if (!Array.isArray(parsed.repos)) return null;
|
|
91
|
+
|
|
92
|
+
return parsed.repos as GitRepository[];
|
|
93
|
+
} catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export const writeIdeReposCache = (workingDirectory: string, repos: GitRepository[]): void => {
|
|
99
|
+
const cachePath = getIdeReposCachePath();
|
|
100
|
+
const payload: IdeReposCacheFileV1 = {
|
|
101
|
+
version: 1,
|
|
102
|
+
workingDirectory,
|
|
103
|
+
updatedAt: Date.now(),
|
|
104
|
+
repos,
|
|
105
|
+
};
|
|
106
|
+
writeFileSync(cachePath, JSON.stringify(payload, null, 2), 'utf-8');
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export const findGitRepositories = (workingDirectory: string): GitRepository[] => {
|
|
110
|
+
const repositories: GitRepository[] = [];
|
|
111
|
+
|
|
112
|
+
const scanDirectory = (dir: string, topLevelFolder: string = '/'): void => {
|
|
113
|
+
try {
|
|
114
|
+
// Check if current directory contains .git folder
|
|
115
|
+
if (existsSync(join(dir, '.git'))) {
|
|
116
|
+
repositories.push({
|
|
117
|
+
name: basename(dir),
|
|
118
|
+
path: dir,
|
|
119
|
+
topLevelFolder,
|
|
120
|
+
});
|
|
121
|
+
return; // Stop recursing into this directory
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Continue scanning subdirectories
|
|
125
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
126
|
+
|
|
127
|
+
for (const entry of entries) {
|
|
128
|
+
if (entry.isDirectory()) {
|
|
129
|
+
const fullPath = join(dir, entry.name);
|
|
130
|
+
|
|
131
|
+
// Determine top-level folder for this entry
|
|
132
|
+
const isTopLevel = dir === workingDirectory;
|
|
133
|
+
const currentTopLevel = isTopLevel ? entry.name : topLevelFolder;
|
|
134
|
+
|
|
135
|
+
scanDirectory(fullPath, currentTopLevel);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
} catch {
|
|
139
|
+
// Silently skip directories with permission errors
|
|
140
|
+
// This will be enhanced in future iterations
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
scanDirectory(workingDirectory);
|
|
145
|
+
return repositories;
|
|
146
|
+
};
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"outDir": "dist",
|
|
8
|
+
"rootDir": "src",
|
|
9
|
+
"declaration": true,
|
|
10
|
+
"types": ["node"],
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"esModuleInterop": true,
|
|
14
|
+
"baseUrl": "./",
|
|
15
|
+
"paths": {
|
|
16
|
+
"*": ["*", "*.js"]
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"include": ["src/**/*"],
|
|
20
|
+
"exclude": ["node_modules", "dist"]
|
|
21
|
+
}
|