@git.zone/tsdoc 2.0.5 → 2.1.0
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/.smartconfig.json +21 -2
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/aidocs_classes/commit.d.ts +3 -0
- package/dist_ts/aidocs_classes/commit.js +122 -115
- package/dist_ts/aidocs_classes/description.js +58 -14
- package/dist_ts/aidocs_classes/projectcontext.d.ts +2 -1
- package/dist_ts/aidocs_classes/projectcontext.js +24 -8
- package/dist_ts/aidocs_classes/readme.js +28 -20
- package/dist_ts/classes.aidoc.d.ts +20 -4
- package/dist_ts/classes.aidoc.js +96 -71
- package/dist_ts/classes.diffprocessor.d.ts +1 -0
- package/dist_ts/classes.diffprocessor.js +25 -16
- package/dist_ts/classes.typedoc.js +33 -11
- package/dist_ts/cli.js +57 -11
- package/dist_ts/helpers.agenttools.d.ts +2 -0
- package/dist_ts/helpers.agenttools.js +5 -0
- package/dist_ts/index.d.ts +1 -0
- package/dist_ts/index.js +2 -1
- package/dist_ts/plugins.d.ts +7 -3
- package/dist_ts/plugins.js +8 -4
- package/package.json +15 -15
- package/readme.md +39 -18
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/aidocs_classes/commit.ts +134 -134
- package/ts/aidocs_classes/description.ts +60 -17
- package/ts/aidocs_classes/projectcontext.ts +24 -24
- package/ts/aidocs_classes/readme.ts +28 -21
- package/ts/classes.aidoc.ts +124 -77
- package/ts/classes.diffprocessor.ts +23 -13
- package/ts/classes.typedoc.ts +35 -12
- package/ts/cli.ts +59 -10
- package/ts/helpers.agenttools.ts +5 -0
- package/ts/index.ts +1 -0
- package/ts/plugins.ts +8 -2
package/ts/classes.aidoc.ts
CHANGED
|
@@ -1,108 +1,155 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
|
|
3
3
|
import * as aiDocsClasses from './aidocs_classes/index.js';
|
|
4
|
+
import { logger } from './logging.js';
|
|
5
|
+
|
|
6
|
+
export type TAiDocAuthMode = plugins.tsagent.TTsAgentAuthMode;
|
|
7
|
+
|
|
8
|
+
export interface IAiDocConfig extends plugins.tsagent.ITsAgentConfig {}
|
|
9
|
+
|
|
10
|
+
export interface IAiDocResolvedConfig extends plugins.tsagent.ITsAgentResolvedConfig {}
|
|
11
|
+
|
|
12
|
+
export const defaultAiDocConfig: IAiDocResolvedConfig = {
|
|
13
|
+
...plugins.tsagent.defaultTsAgentConfig,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
type TAiDocRunAgentOptions = Parameters<plugins.tsagent.TsAgent['runAgent']>[0];
|
|
17
|
+
type TAiDocRunAgentResult = Awaited<ReturnType<plugins.tsagent.TsAgent['runAgent']>>;
|
|
18
|
+
|
|
19
|
+
const normalizeAuthMode = (value: unknown): TAiDocAuthMode | undefined => {
|
|
20
|
+
return value === 'auto' || value === 'chatgpt' || value === 'apiKey' ? value : undefined;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const normalizeProvider = (value: unknown): plugins.smartai.TProvider | undefined => {
|
|
24
|
+
return ['anthropic', 'openai', 'google', 'groq', 'mistral', 'xai', 'perplexity', 'ollama'].includes(String(value))
|
|
25
|
+
? value as plugins.smartai.TProvider
|
|
26
|
+
: undefined;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const normalizeChatGptSources = (value: unknown): plugins.smartaiOpenAiChatGptAuth.TOpenAiChatGptAuthSource[] | undefined => {
|
|
30
|
+
const input = typeof value === 'string' ? value.split(',').map(source => source.trim()) : value;
|
|
31
|
+
if (!Array.isArray(input)) return undefined;
|
|
32
|
+
const sources = input.filter((source): source is plugins.smartaiOpenAiChatGptAuth.TOpenAiChatGptAuthSource => {
|
|
33
|
+
return source === 'opencode' || source === 'codex' || source === 'smartai';
|
|
34
|
+
});
|
|
35
|
+
return sources.length > 0 ? sources : undefined;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const normalizeOpenAiReasoningEffort = (value: unknown): plugins.smartai.TOpenAiReasoningEffort | undefined => {
|
|
39
|
+
return ['none', 'minimal', 'low', 'medium', 'high', 'xhigh'].includes(String(value))
|
|
40
|
+
? value as plugins.smartai.TOpenAiReasoningEffort
|
|
41
|
+
: undefined;
|
|
42
|
+
};
|
|
4
43
|
|
|
5
44
|
export class AiDoc {
|
|
45
|
+
private tsAgent?: plugins.tsagent.TsAgent;
|
|
6
46
|
private openaiToken = '';
|
|
7
47
|
|
|
8
48
|
public smartconfigKV?: plugins.smartconfig.KeyValueStore<{ OPENAI_TOKEN: string }>;
|
|
9
|
-
public qenvInstance
|
|
10
|
-
public aidocInteract
|
|
11
|
-
public model!: plugins.
|
|
49
|
+
public qenvInstance?: plugins.qenv.Qenv;
|
|
50
|
+
public aidocInteract?: plugins.smartinteract.SmartInteract;
|
|
51
|
+
public model!: plugins.tsagent.TsAgent['model'];
|
|
52
|
+
public providerOptions?: IAiDocResolvedConfig['providerOptions'];
|
|
53
|
+
public config: IAiDocResolvedConfig = defaultAiDocConfig;
|
|
54
|
+
public selectedAuthSource: string = 'none';
|
|
12
55
|
|
|
13
|
-
argvArg: any;
|
|
56
|
+
public argvArg: any;
|
|
14
57
|
|
|
15
58
|
constructor(argvArg?: any) {
|
|
16
|
-
this.argvArg = argvArg;
|
|
59
|
+
this.argvArg = argvArg || {};
|
|
17
60
|
}
|
|
18
61
|
|
|
19
|
-
private
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (this.openaiToken.length > 6) {
|
|
23
|
-
// Extract the beginning and end parts of the token
|
|
24
|
-
const start = this.openaiToken.substring(0, 3);
|
|
25
|
-
const end = this.openaiToken.substring(this.openaiToken.length - 3);
|
|
26
|
-
printToken = `${start}...${end}`;
|
|
27
|
-
} else {
|
|
28
|
-
// If the token is not long enough, return it as is
|
|
29
|
-
printToken = this.openaiToken;
|
|
62
|
+
private get activeTsAgent(): plugins.tsagent.TsAgent {
|
|
63
|
+
if (!this.tsAgent) {
|
|
64
|
+
throw new Error('AiDoc.start() must be called before running AI tasks.');
|
|
30
65
|
}
|
|
31
|
-
|
|
66
|
+
return this.tsAgent;
|
|
32
67
|
}
|
|
33
68
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
await plugins.fsInstance.file(oldKvPath).exists() &&
|
|
49
|
-
!(await plugins.fsInstance.file(newKvPath).exists())
|
|
50
|
-
) {
|
|
51
|
-
console.log('Migrating tsdoc KeyValueStore to @git.zone/tsdoc...');
|
|
52
|
-
await plugins.fsInstance.directory(newKvDir).recursive().create();
|
|
53
|
-
await plugins.fsInstance.file(oldKvPath).copy(newKvPath);
|
|
54
|
-
await plugins.fsInstance.file(oldKvPath).delete();
|
|
55
|
-
console.log('Migration complete: tsdoc.json -> @git.zone/tsdoc.json');
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
this.smartconfigKV = new plugins.smartconfig.KeyValueStore({
|
|
59
|
-
typeArg: 'userHomeDir',
|
|
60
|
-
identityArg: '@git.zone/tsdoc',
|
|
61
|
-
mandatoryKeys: ['OPENAI_TOKEN'],
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
const missingKeys = await this.smartconfigKV.getMissingMandatoryKeys();
|
|
65
|
-
if (missingKeys.length > 0) {
|
|
66
|
-
// lets try argv
|
|
67
|
-
if (this.argvArg?.OPENAI_TOKEN) {
|
|
68
|
-
this.openaiToken = this.argvArg.OPENAI_TOKEN;
|
|
69
|
-
} else {
|
|
70
|
-
// lets try smartinteract
|
|
71
|
-
// wait for a second until OpenAI fixes punycode problem...
|
|
72
|
-
await plugins.smartdelay.delayFor(1000);
|
|
73
|
-
const answerObject = await this.aidocInteract.askQuestion({
|
|
74
|
-
type: 'input',
|
|
75
|
-
message: `Please provide your OpenAI token. This will be persisted in your home directory.`,
|
|
76
|
-
name: 'OPENAI_TOKEN',
|
|
77
|
-
default: '',
|
|
78
|
-
});
|
|
79
|
-
this.openaiToken = answerObject.value;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
this.printSanitizedToken();
|
|
83
|
-
await this.smartconfigKV.writeKey('OPENAI_TOKEN', this.openaiToken);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
if (!this.openaiToken && this.smartconfigKV) {
|
|
87
|
-
this.openaiToken = await this.smartconfigKV.readKey('OPENAI_TOKEN');
|
|
69
|
+
private async migrateKeyValueStore(): Promise<void> {
|
|
70
|
+
const homeDir = plugins.smartpath.get.home();
|
|
71
|
+
const oldKvPath = plugins.path.join(homeDir, '.smartconfig/kv/tsdoc.json');
|
|
72
|
+
const newKvDir = plugins.path.join(homeDir, '.smartconfig/kv/@git.zone');
|
|
73
|
+
const newKvPath = plugins.path.join(newKvDir, 'tsdoc.json');
|
|
74
|
+
if (
|
|
75
|
+
await plugins.fsInstance.file(oldKvPath).exists() &&
|
|
76
|
+
!(await plugins.fsInstance.file(newKvPath).exists())
|
|
77
|
+
) {
|
|
78
|
+
logger.log('info', 'Migrating tsdoc KeyValueStore to @git.zone/tsdoc...');
|
|
79
|
+
await plugins.fsInstance.directory(newKvDir).recursive().create();
|
|
80
|
+
await plugins.fsInstance.file(oldKvPath).copy(newKvPath);
|
|
81
|
+
await plugins.fsInstance.file(oldKvPath).delete();
|
|
82
|
+
logger.log('success', 'Migration complete: tsdoc.json -> @git.zone/tsdoc.json');
|
|
88
83
|
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private async resolveTsdocEnvConfig(): Promise<IAiDocConfig> {
|
|
87
|
+
this.qenvInstance = new plugins.qenv.Qenv();
|
|
88
|
+
const envProvider = normalizeProvider(await this.qenvInstance.getEnvVarOnDemand('TSDOC_AI_PROVIDER'));
|
|
89
|
+
const envModel = await this.qenvInstance.getEnvVarOnDemand('TSDOC_AI_MODEL');
|
|
90
|
+
const envAuthMode = normalizeAuthMode(await this.qenvInstance.getEnvVarOnDemand('TSDOC_AUTH_MODE'));
|
|
91
|
+
const envChatGptSources = normalizeChatGptSources(await this.qenvInstance.getEnvVarOnDemand('TSDOC_CHATGPT_AUTH_SOURCES'));
|
|
92
|
+
const envReasoningEffort = normalizeOpenAiReasoningEffort(await this.qenvInstance.getEnvVarOnDemand('TSDOC_OPENAI_REASONING_EFFORT'));
|
|
93
|
+
return {
|
|
94
|
+
provider: envProvider,
|
|
95
|
+
model: envModel || undefined,
|
|
96
|
+
authMode: envAuthMode,
|
|
97
|
+
chatGptAuthSources: envChatGptSources,
|
|
98
|
+
providerOptions: envReasoningEffort ? {
|
|
99
|
+
openai: {
|
|
100
|
+
reasoningEffort: envReasoningEffort,
|
|
101
|
+
},
|
|
102
|
+
} : undefined,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
89
105
|
|
|
90
|
-
|
|
91
|
-
this.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
106
|
+
public async start() {
|
|
107
|
+
await this.migrateKeyValueStore();
|
|
108
|
+
this.smartconfigKV = new plugins.smartconfig.KeyValueStore({
|
|
109
|
+
typeArg: 'userHomeDir',
|
|
110
|
+
identityArg: '@git.zone/tsdoc',
|
|
111
|
+
mandatoryKeys: ['OPENAI_TOKEN'],
|
|
95
112
|
});
|
|
113
|
+
|
|
114
|
+
this.tsAgent = new plugins.tsagent.TsAgent({
|
|
115
|
+
argvArg: this.argvArg,
|
|
116
|
+
projectDir: process.cwd(),
|
|
117
|
+
projectConfigKeys: ['@git.zone/tsagent', 'tsdoc', '@git.zone/tsdoc'],
|
|
118
|
+
legacyTokenStoreIdentities: ['@git.zone/tsdoc'],
|
|
119
|
+
config: await this.resolveTsdocEnvConfig(),
|
|
120
|
+
});
|
|
121
|
+
await this.tsAgent.start();
|
|
122
|
+
|
|
123
|
+
this.model = this.tsAgent.model;
|
|
124
|
+
this.providerOptions = this.tsAgent.providerOptions;
|
|
125
|
+
this.config = this.tsAgent.config as IAiDocResolvedConfig;
|
|
126
|
+
this.selectedAuthSource = this.tsAgent.selectedAuthSource;
|
|
127
|
+
this.openaiToken = this.tsAgent.getOpenaiToken();
|
|
128
|
+
if (this.selectedAuthSource !== 'none') {
|
|
129
|
+
logger.log('info', `Using AI auth from ${this.selectedAuthSource}.`);
|
|
130
|
+
}
|
|
96
131
|
}
|
|
97
132
|
|
|
98
133
|
public async stop() {
|
|
99
|
-
|
|
134
|
+
await this.tsAgent?.stop();
|
|
100
135
|
}
|
|
101
136
|
|
|
102
137
|
public getOpenaiToken(): string {
|
|
103
138
|
return this.openaiToken;
|
|
104
139
|
}
|
|
105
140
|
|
|
141
|
+
public async runAgent(options: TAiDocRunAgentOptions): Promise<TAiDocRunAgentResult> {
|
|
142
|
+
const result = await this.activeTsAgent.runAgent({
|
|
143
|
+
...options,
|
|
144
|
+
sessionId: options.sessionId ?? `tsdoc:${options.taskName}:${plugins.path.resolve(options.projectDir)}`,
|
|
145
|
+
});
|
|
146
|
+
logger.log(
|
|
147
|
+
'info',
|
|
148
|
+
`[${options.taskName}] tokens input=${result.usage.inputTokens} output=${result.usage.outputTokens} total=${result.usage.totalTokens} cacheRead=${result.usage.cacheReadTokens} cacheWrite=${result.usage.cacheWriteTokens}`,
|
|
149
|
+
);
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
|
|
106
153
|
public async buildReadme(projectDirArg: string) {
|
|
107
154
|
const readmeInstance = new aiDocsClasses.Readme(this, projectDirArg);
|
|
108
155
|
return await readmeInstance.build();
|
|
@@ -160,24 +160,18 @@ export class DiffProcessor {
|
|
|
160
160
|
|
|
161
161
|
const lines = diffString.split('\n');
|
|
162
162
|
let filepath = '';
|
|
163
|
+
let oldPath = '';
|
|
164
|
+
let newPath = '';
|
|
163
165
|
let status: 'added' | 'modified' | 'deleted' = 'modified';
|
|
164
166
|
let linesAdded = 0;
|
|
165
167
|
let linesRemoved = 0;
|
|
166
168
|
|
|
167
169
|
// Parse diff header to extract filepath and status
|
|
168
170
|
for (const line of lines) {
|
|
169
|
-
if (line.startsWith('---
|
|
170
|
-
|
|
171
|
-
} else if (line.startsWith('+++
|
|
172
|
-
|
|
173
|
-
if (newPath === '/dev/null') {
|
|
174
|
-
status = 'deleted';
|
|
175
|
-
} else if (filepath === '/dev/null') {
|
|
176
|
-
status = 'added';
|
|
177
|
-
filepath = newPath;
|
|
178
|
-
} else {
|
|
179
|
-
filepath = newPath;
|
|
180
|
-
}
|
|
171
|
+
if (line.startsWith('--- ')) {
|
|
172
|
+
oldPath = this.normalizeDiffPath(line.substring(4));
|
|
173
|
+
} else if (line.startsWith('+++ ')) {
|
|
174
|
+
newPath = this.normalizeDiffPath(line.substring(4));
|
|
181
175
|
} else if (line.startsWith('+') && !line.startsWith('+++')) {
|
|
182
176
|
linesAdded++;
|
|
183
177
|
} else if (line.startsWith('-') && !line.startsWith('---')) {
|
|
@@ -185,6 +179,16 @@ export class DiffProcessor {
|
|
|
185
179
|
}
|
|
186
180
|
}
|
|
187
181
|
|
|
182
|
+
if (oldPath === '/dev/null') {
|
|
183
|
+
status = 'added';
|
|
184
|
+
filepath = newPath;
|
|
185
|
+
} else if (newPath === '/dev/null') {
|
|
186
|
+
status = 'deleted';
|
|
187
|
+
filepath = oldPath;
|
|
188
|
+
} else {
|
|
189
|
+
filepath = newPath || oldPath;
|
|
190
|
+
}
|
|
191
|
+
|
|
188
192
|
const totalLines = linesAdded + linesRemoved;
|
|
189
193
|
const estimatedTokens = Math.ceil(diffString.length / 4);
|
|
190
194
|
|
|
@@ -199,6 +203,12 @@ export class DiffProcessor {
|
|
|
199
203
|
};
|
|
200
204
|
}
|
|
201
205
|
|
|
206
|
+
private normalizeDiffPath(pathArg: string): string {
|
|
207
|
+
const cleanPath = pathArg.trim().split('\t')[0].split(' ')[0];
|
|
208
|
+
if (cleanPath === '/dev/null') return cleanPath;
|
|
209
|
+
return cleanPath.replace(/^a\//, '').replace(/^b\//, '');
|
|
210
|
+
}
|
|
211
|
+
|
|
202
212
|
/**
|
|
203
213
|
* Prioritize files by importance (source files before build artifacts)
|
|
204
214
|
*/
|
|
@@ -215,7 +225,7 @@ export class DiffProcessor {
|
|
|
215
225
|
*/
|
|
216
226
|
private getFileImportanceScore(filepath: string): number {
|
|
217
227
|
// Source files - highest priority
|
|
218
|
-
if (filepath.match(/^(src|lib|app|components|pages|api)\//)) {
|
|
228
|
+
if (filepath.match(/^(ts|ts_web|src|lib|app|components|pages|api)\//)) {
|
|
219
229
|
return 100;
|
|
220
230
|
}
|
|
221
231
|
|
package/ts/classes.typedoc.ts
CHANGED
|
@@ -9,7 +9,8 @@ export class TypeDoc {
|
|
|
9
9
|
|
|
10
10
|
// Static
|
|
11
11
|
public static async isTypeDocDir(dirPathArg: string): Promise<boolean> {
|
|
12
|
-
return
|
|
12
|
+
return await plugins.fsInstance.file(plugins.path.join(dirPathArg, 'ts/index.ts')).exists()
|
|
13
|
+
|| await plugins.fsInstance.file(plugins.path.join(dirPathArg, 'ts_web/index.ts')).exists();
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
// Instance
|
|
@@ -32,26 +33,48 @@ export class TypeDoc {
|
|
|
32
33
|
include: [] as string[],
|
|
33
34
|
};
|
|
34
35
|
let startDirectory = '';
|
|
35
|
-
if (await plugins.fsInstance.directory(plugins.path.join(
|
|
36
|
-
data.include.push(plugins.path.join(
|
|
36
|
+
if (await plugins.fsInstance.directory(plugins.path.join(this.typedocDirectory, './ts')).exists()) {
|
|
37
|
+
data.include.push(plugins.path.join(this.typedocDirectory, './ts/**/*'));
|
|
37
38
|
startDirectory = 'ts';
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
if (await plugins.fsInstance.directory(plugins.path.join(
|
|
41
|
-
data.include.push(plugins.path.join(
|
|
41
|
+
if (await plugins.fsInstance.directory(plugins.path.join(this.typedocDirectory, './ts_web')).exists()) {
|
|
42
|
+
data.include.push(plugins.path.join(this.typedocDirectory, './ts_web/**/*'));
|
|
42
43
|
if (!startDirectory) {
|
|
43
44
|
startDirectory = 'ts_web';
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
if (!startDirectory) {
|
|
49
|
+
throw new Error(`No TypeDoc entrypoint found in ${this.typedocDirectory}`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const tempDir = plugins.path.join(this.typedocDirectory, '.nogit', 'tsdoc');
|
|
53
|
+
const tempTsconfigFile = plugins.path.join(tempDir, 'tsconfig.json');
|
|
54
|
+
await plugins.fsInstance.directory(tempDir).recursive().create();
|
|
55
|
+
await plugins.fsInstance.file(tempTsconfigFile).encoding('utf8').write(JSON.stringify(data));
|
|
56
|
+
const publicDir = plugins.path.join(this.typedocDirectory, 'public');
|
|
57
|
+
let targetDir = publicDir;
|
|
49
58
|
if (options?.publicSubdir) {
|
|
50
|
-
targetDir = plugins.path.join(targetDir, options.publicSubdir);
|
|
59
|
+
targetDir = plugins.path.resolve(plugins.path.join(targetDir, options.publicSubdir));
|
|
60
|
+
const resolvedPublicDir = plugins.path.resolve(publicDir);
|
|
61
|
+
if (!targetDir.startsWith(`${resolvedPublicDir}${plugins.path.sep}`) && targetDir !== resolvedPublicDir) {
|
|
62
|
+
throw new Error(`Invalid publicSubdir outside public directory: ${options.publicSubdir}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
const result = await this.smartshellInstance.exec(
|
|
67
|
+
`typedoc --tsconfig ${shellQuote(tempTsconfigFile)} --out ${shellQuote(targetDir)} ${shellQuote(plugins.path.join(this.typedocDirectory, startDirectory, 'index.ts'))}`,
|
|
68
|
+
);
|
|
69
|
+
if (result.exitCode !== 0) {
|
|
70
|
+
throw new Error('typedoc command failed.');
|
|
71
|
+
}
|
|
72
|
+
} finally {
|
|
73
|
+
if (await plugins.fsInstance.file(tempTsconfigFile).exists()) {
|
|
74
|
+
await plugins.fsInstance.file(tempTsconfigFile).delete();
|
|
75
|
+
}
|
|
51
76
|
}
|
|
52
|
-
await this.smartshellInstance.exec(
|
|
53
|
-
`typedoc --tsconfig ${paths.tsconfigFile} --out ${targetDir} ${startDirectory}/index.ts`,
|
|
54
|
-
);
|
|
55
|
-
await plugins.fsInstance.file(paths.tsconfigFile).delete();
|
|
56
77
|
}
|
|
57
78
|
}
|
|
79
|
+
|
|
80
|
+
const shellQuote = (value: string): string => `'${value.replaceAll("'", "'\\''")}'`;
|
package/ts/cli.ts
CHANGED
|
@@ -4,6 +4,41 @@ import { logger } from './logging.js';
|
|
|
4
4
|
|
|
5
5
|
import { TypeDoc } from './classes.typedoc.js';
|
|
6
6
|
import { AiDoc } from './classes.aidoc.js';
|
|
7
|
+
import { NoChangesError } from './aidocs_classes/commit.js';
|
|
8
|
+
|
|
9
|
+
const createAiDoc = async (argvArg: any): Promise<AiDoc> => {
|
|
10
|
+
const aidocInstance = new AiDoc(argvArg);
|
|
11
|
+
await aidocInstance.start();
|
|
12
|
+
return aidocInstance;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const getSmartcliArgv = (): string[] | undefined => {
|
|
16
|
+
if (process.argv.length === 0) return undefined;
|
|
17
|
+
if (process.argv[0] === process.execPath) return undefined;
|
|
18
|
+
return [process.execPath, 'tsdoc', ...process.argv];
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const handleAuthCommand = async (argvArg: any): Promise<void> => {
|
|
22
|
+
const subcommand = argvArg._?.[1] ?? 'status';
|
|
23
|
+
if (subcommand === 'login') {
|
|
24
|
+
await plugins.tsagent.loginChatGptAuth();
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const inspections = await plugins.tsagent.inspectChatGptAuthSources();
|
|
29
|
+
console.log('OpenAI ChatGPT auth sources:');
|
|
30
|
+
for (const inspection of inspections) {
|
|
31
|
+
const status = inspection.usable
|
|
32
|
+
? 'usable'
|
|
33
|
+
: inspection.exists
|
|
34
|
+
? inspection.expired
|
|
35
|
+
? 'expired'
|
|
36
|
+
: 'not usable'
|
|
37
|
+
: 'missing';
|
|
38
|
+
const account = inspection.email ? ` (${inspection.email})` : '';
|
|
39
|
+
console.log(` ${inspection.source}: ${status}${account} - ${inspection.filePath}`);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
7
42
|
|
|
8
43
|
export const run = async () => {
|
|
9
44
|
const tsdocCli = new plugins.smartcli.Smartcli();
|
|
@@ -28,8 +63,7 @@ export const run = async () => {
|
|
|
28
63
|
});
|
|
29
64
|
|
|
30
65
|
tsdocCli.addCommand('aidoc').subscribe(async (argvArg) => {
|
|
31
|
-
const aidocInstance =
|
|
32
|
-
await aidocInstance.start();
|
|
66
|
+
const aidocInstance = await createAiDoc(argvArg);
|
|
33
67
|
|
|
34
68
|
logger.log('info', `Generating new readme...`);
|
|
35
69
|
logger.log('info', `This may take some time...`);
|
|
@@ -39,9 +73,12 @@ export const run = async () => {
|
|
|
39
73
|
await aidocInstance.buildDescription(paths.cwd);
|
|
40
74
|
});
|
|
41
75
|
|
|
76
|
+
tsdocCli.addCommand('aidocs').subscribe(async (argvArg) => {
|
|
77
|
+
tsdocCli.triggerCommand('aidoc', argvArg);
|
|
78
|
+
});
|
|
79
|
+
|
|
42
80
|
tsdocCli.addCommand('readme').subscribe(async (argvArg) => {
|
|
43
|
-
const aidocInstance =
|
|
44
|
-
await aidocInstance.start();
|
|
81
|
+
const aidocInstance = await createAiDoc(argvArg);
|
|
45
82
|
|
|
46
83
|
logger.log('info', `Generating new readme...`);
|
|
47
84
|
logger.log('info', `This may take some time...`);
|
|
@@ -49,8 +86,7 @@ export const run = async () => {
|
|
|
49
86
|
});
|
|
50
87
|
|
|
51
88
|
tsdocCli.addCommand('description').subscribe(async (argvArg) => {
|
|
52
|
-
const aidocInstance =
|
|
53
|
-
await aidocInstance.start();
|
|
89
|
+
const aidocInstance = await createAiDoc(argvArg);
|
|
54
90
|
|
|
55
91
|
logger.log('info', `Generating new description and keywords...`);
|
|
56
92
|
logger.log('info', `This may take some time...`);
|
|
@@ -58,17 +94,30 @@ export const run = async () => {
|
|
|
58
94
|
});
|
|
59
95
|
|
|
60
96
|
tsdocCli.addCommand('commit').subscribe(async (argvArg) => {
|
|
61
|
-
const aidocInstance =
|
|
62
|
-
await aidocInstance.start();
|
|
97
|
+
const aidocInstance = await createAiDoc(argvArg);
|
|
63
98
|
|
|
64
99
|
logger.log('info', `Generating commit message...`);
|
|
65
100
|
logger.log('info', `This may take some time...`);
|
|
66
|
-
|
|
101
|
+
let commitObject: Awaited<ReturnType<AiDoc['buildNextCommitObject']>>;
|
|
102
|
+
try {
|
|
103
|
+
commitObject = await aidocInstance.buildNextCommitObject(paths.cwd);
|
|
104
|
+
} catch (error) {
|
|
105
|
+
if (error instanceof NoChangesError || (error as Error).name === 'NoChangesError') {
|
|
106
|
+
logger.log('info', 'No uncommitted changes found.');
|
|
107
|
+
console.log(JSON.stringify({ ok: true, noChanges: true }, null, 2));
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
67
112
|
|
|
68
113
|
logger.log('ok', `Commit message generated:`);
|
|
69
114
|
console.log(JSON.stringify(commitObject, null, 2));
|
|
70
115
|
});
|
|
71
116
|
|
|
117
|
+
tsdocCli.addCommand('auth').subscribe(async (argvArg) => {
|
|
118
|
+
await handleAuthCommand(argvArg);
|
|
119
|
+
});
|
|
120
|
+
|
|
72
121
|
tsdocCli.addCommand('test').subscribe((argvArg) => {
|
|
73
122
|
tsdocCli.triggerCommand('typedoc', argvArg);
|
|
74
123
|
process.on('exit', async () => {
|
|
@@ -76,5 +125,5 @@ export const run = async () => {
|
|
|
76
125
|
});
|
|
77
126
|
});
|
|
78
127
|
|
|
79
|
-
tsdocCli.startParse();
|
|
128
|
+
tsdocCli.startParse(getSmartcliArgv());
|
|
80
129
|
};
|
package/ts/index.ts
CHANGED
package/ts/plugins.ts
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
// node native
|
|
2
|
+
import * as fs from 'node:fs/promises';
|
|
2
3
|
import * as path from 'path';
|
|
3
4
|
|
|
4
|
-
export { path };
|
|
5
|
+
export { fs, path };
|
|
5
6
|
|
|
6
7
|
// pushrocks scope
|
|
7
8
|
import * as smartconfig from '@push.rocks/smartconfig';
|
|
8
9
|
import * as qenv from '@push.rocks/qenv';
|
|
9
10
|
import * as smartagent from '@push.rocks/smartagent';
|
|
11
|
+
import * as smartagentCompaction from '@push.rocks/smartagent/compaction';
|
|
10
12
|
import * as smartagentTools from '@push.rocks/smartagent/tools';
|
|
11
13
|
import * as smartai from '@push.rocks/smartai';
|
|
14
|
+
import * as smartaiOpenAiChatGptAuth from '@push.rocks/smartai/openai-chatgpt-auth';
|
|
12
15
|
import * as smartcli from '@push.rocks/smartcli';
|
|
13
16
|
import * as smartdelay from '@push.rocks/smartdelay';
|
|
14
17
|
import * as smartfile from '@push.rocks/smartfile';
|
|
@@ -25,8 +28,10 @@ export {
|
|
|
25
28
|
smartconfig,
|
|
26
29
|
qenv,
|
|
27
30
|
smartagent,
|
|
31
|
+
smartagentCompaction,
|
|
28
32
|
smartagentTools,
|
|
29
33
|
smartai,
|
|
34
|
+
smartaiOpenAiChatGptAuth,
|
|
30
35
|
smartcli,
|
|
31
36
|
smartdelay,
|
|
32
37
|
smartfile,
|
|
@@ -48,9 +53,10 @@ export const fsInstance = new smartfs.SmartFs(smartFsNodeProvider);
|
|
|
48
53
|
export const smartfileFactory = smartfile.SmartFileFactory.nodeFs();
|
|
49
54
|
|
|
50
55
|
// @git.zone scope
|
|
56
|
+
import * as tsagent from '@git.zone/tsagent';
|
|
51
57
|
import * as tspublish from '@git.zone/tspublish';
|
|
52
58
|
|
|
53
|
-
export { tspublish };
|
|
59
|
+
export { tsagent, tspublish };
|
|
54
60
|
|
|
55
61
|
// third party scope
|
|
56
62
|
import * as typedoc from 'typedoc';
|