@gitset-dev/cli 2.1.0 → 2.2.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/index.js +8 -0
- package/lib/ai/providers/gemini.js +2 -0
- package/lib/prompts/context.js +8 -1
- package/lib/prompts/index.js +2 -2
- package/package.json +1 -1
- package/src/commands/feedback.js +98 -0
package/index.js
CHANGED
|
@@ -17,6 +17,8 @@ function showHelp() {
|
|
|
17
17
|
|
|
18
18
|
${theme.bold('First time?')} Run ${theme.accent('gitset config')} — an interactive wizard sets up your AI provider in under a minute.
|
|
19
19
|
|
|
20
|
+
${theme.bold('Found a bug or have a suggestion?')} Run ${theme.accent('gitset feedback')} anytime.
|
|
21
|
+
|
|
20
22
|
${theme.bold('AI commands')} (use your own provider key):
|
|
21
23
|
commit Generate a commit message from staged changes
|
|
22
24
|
pr Generate a pull-request description from the branch diff
|
|
@@ -35,6 +37,7 @@ ${theme.bold('Local tools')} (no AI):
|
|
|
35
37
|
status Show git + provider status
|
|
36
38
|
template Manage local templates (~/.gitset/templates), edit <tool> to customize
|
|
37
39
|
init Scaffold local templates
|
|
40
|
+
feedback Report a bug, suggest a feature, or share feedback
|
|
38
41
|
|
|
39
42
|
${theme.bold('Setup')}:
|
|
40
43
|
config interactive setup wizard
|
|
@@ -125,6 +128,9 @@ Manage local templates in ~/.gitset/templates.
|
|
|
125
128
|
path print the templates directory`,
|
|
126
129
|
init: `Usage: gitset init
|
|
127
130
|
Scaffold the local template directory.`,
|
|
131
|
+
feedback: `Usage: gitset feedback
|
|
132
|
+
Interactively submit a bug report, feature suggestion, or general feedback.
|
|
133
|
+
Filed as a GitHub issue in gitset-dev/gitset via your own \`gh\` auth.`,
|
|
128
134
|
config: `Usage: gitset config [set|list|remove|theme|path]
|
|
129
135
|
(no args) interactive setup wizard
|
|
130
136
|
set interactive wizard, or: set <provider> --key <key> [--model m] [--base-url u] [--default]
|
|
@@ -200,6 +206,8 @@ async function main() {
|
|
|
200
206
|
code = await require('./src/commands/labelspack').runLabelspackCommand(rest); break;
|
|
201
207
|
case 'dependabot':
|
|
202
208
|
code = (await require('./src/commands/dependabot-resolver')(null, rest)) || 0; break;
|
|
209
|
+
case 'feedback':
|
|
210
|
+
code = (await require('./src/commands/feedback')()) || 0; break;
|
|
203
211
|
|
|
204
212
|
case 'auth': case 'verify': case 'logout':
|
|
205
213
|
code = deprecatedAuth(command); break;
|
|
@@ -21,6 +21,8 @@ function create({ apiKey, model, timeoutMs = 60_000 }) {
|
|
|
21
21
|
temperature: req.temperature ?? 0.7,
|
|
22
22
|
...(req.maxTokens ? { maxOutputTokens: req.maxTokens } : {}),
|
|
23
23
|
...(req.system ? { systemInstruction: req.system } : {}),
|
|
24
|
+
|
|
25
|
+
thinkingConfig: { thinkingBudget: req.thinkingBudget ?? 0 },
|
|
24
26
|
};
|
|
25
27
|
const ac = req.signal ? { abortSignal: req.signal } : {};
|
|
26
28
|
return { config: cfg, http: { ...ac, timeout: timeoutMs } };
|
package/lib/prompts/context.js
CHANGED
|
@@ -14,4 +14,11 @@ function dateAwarenessNote() {
|
|
|
14
14
|
'content specifically and verifiably describes a past event.';
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
function constraintAdherenceNote() {
|
|
18
|
+
return 'If the input below contains explicit constraints or exclusions (e.g. "do not ' +
|
|
19
|
+
'mention X", "do not name Y", a required format, a forbidden word), treat them as hard ' +
|
|
20
|
+
'requirements — re-check your output against each one before finishing, not just your ' +
|
|
21
|
+
'first draft.';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = { currentDateLine, dateAwarenessNote, constraintAdherenceNote };
|
package/lib/prompts/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
const defaults = require('./defaults');
|
|
5
|
-
const { dateAwarenessNote } = require('./context');
|
|
5
|
+
const { dateAwarenessNote, constraintAdherenceNote } = require('./context');
|
|
6
6
|
|
|
7
7
|
let _cache = null;
|
|
8
8
|
|
|
@@ -63,7 +63,7 @@ function getPrompt(key, ctx = {}) {
|
|
|
63
63
|
throw new Error(`Prompt "${key}" must return { system: string, user: string }`);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
return { ...out, system: `${out.system}\n\n${dateAwarenessNote()}` };
|
|
66
|
+
return { ...out, system: `${out.system}\n\n${dateAwarenessNote()}\n\n${constraintAdherenceNote()}` };
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
function toAIRequest(key, ctx = {}, extra = {}) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gitset-dev/cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Gitset CLI — drafts commits, PRs, issues, READMEs and release notes with your own AI key. Fully local: your code and keys never touch a Gitset server. Draft. Refine. Ship.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"bin": {
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const { execFileSync } = require('child_process');
|
|
2
|
+
const os = require('os');
|
|
3
|
+
const { log, askQuestion, selectOption } = require('../utils/ui');
|
|
4
|
+
|
|
5
|
+
const REPO = 'gitset-dev/gitset';
|
|
6
|
+
|
|
7
|
+
const TYPE_LABELS = {
|
|
8
|
+
bug: ['user-feedback', 'bug'],
|
|
9
|
+
suggestion: ['user-feedback', 'feature-request'],
|
|
10
|
+
qos: ['user-feedback'],
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const TYPE_TITLES = {
|
|
14
|
+
bug: 'Bug Report',
|
|
15
|
+
suggestion: 'Feature Suggestion',
|
|
16
|
+
qos: 'Quality of Service Feedback',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
function ghAvailable() {
|
|
20
|
+
try { execFileSync('gh', ['--version'], { stdio: 'ignore' }); return true; }
|
|
21
|
+
catch { return false; }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function ensureLabel(name, color, description) {
|
|
25
|
+
try {
|
|
26
|
+
execFileSync('gh', ['label', 'create', name, '--repo', REPO, '--color', color, '--description', description], { stdio: 'ignore' });
|
|
27
|
+
} catch { }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function buildBody(message, tool, version, includeSystemInfo) {
|
|
31
|
+
const lines = [message.trim(), ''];
|
|
32
|
+
if (includeSystemInfo) {
|
|
33
|
+
lines.push(
|
|
34
|
+
'<details>',
|
|
35
|
+
'<summary>Metadata</summary>',
|
|
36
|
+
'',
|
|
37
|
+
'- Source: cli',
|
|
38
|
+
tool ? `- Tool/command: ${tool}` : null,
|
|
39
|
+
`- Version: ${version}`,
|
|
40
|
+
`- OS: ${os.platform()}-${os.arch()}`,
|
|
41
|
+
'',
|
|
42
|
+
'</details>',
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
return lines.filter((l) => l !== null).join('\n');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = async function commandFeedback() {
|
|
49
|
+
console.log('\n=== Gitset Feedback ===\n');
|
|
50
|
+
|
|
51
|
+
if (!ghAvailable()) {
|
|
52
|
+
log('The `gh` CLI is required to submit feedback (https://cli.github.com).', 'red');
|
|
53
|
+
return 1;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const type = await selectOption('What kind of feedback would you like to share?', [
|
|
57
|
+
{ label: 'Bug Report', value: 'bug' },
|
|
58
|
+
{ label: 'Feature Suggestion', value: 'suggestion' },
|
|
59
|
+
{ label: 'Quality of Service / General Feedback', value: 'qos' },
|
|
60
|
+
]);
|
|
61
|
+
|
|
62
|
+
let title = '';
|
|
63
|
+
while (!title) {
|
|
64
|
+
title = (await askQuestion('Short title for your feedback: ')).slice(0, 120);
|
|
65
|
+
if (!title) log('A title is required.', 'red');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const tool = await askQuestion('Which tool or command does this relate to? (optional): ');
|
|
69
|
+
|
|
70
|
+
let message = '';
|
|
71
|
+
while (!message) {
|
|
72
|
+
message = await askQuestion('Please describe your feedback: ');
|
|
73
|
+
if (!message) log('A description is required.', 'red');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const version = require('../../package.json').version;
|
|
77
|
+
const consent = await askQuestion(`May we include your CLI version (${version}) and OS automatically? (Y/n): `);
|
|
78
|
+
const includeSystemInfo = consent.trim().toLowerCase() !== 'n';
|
|
79
|
+
|
|
80
|
+
ensureLabel('user-feedback', 'D4A5A5', 'Submitted via the in-app/CLI feedback tool (issue #20).');
|
|
81
|
+
|
|
82
|
+
const issueTitle = `[${TYPE_TITLES[type]}] ${title}`;
|
|
83
|
+
const body = buildBody(message, tool, version, includeSystemInfo);
|
|
84
|
+
const labels = TYPE_LABELS[type];
|
|
85
|
+
|
|
86
|
+
const args = ['issue', 'create', '--repo', REPO, '--title', issueTitle, '--body', body];
|
|
87
|
+
for (const l of labels) args.push('--label', l);
|
|
88
|
+
|
|
89
|
+
log('\nSubmitting feedback...', 'dim');
|
|
90
|
+
try {
|
|
91
|
+
const url = execFileSync('gh', args, { encoding: 'utf8' }).trim();
|
|
92
|
+
log(`\n✔ Feedback successfully submitted! View your issue here: ${url}`, 'green');
|
|
93
|
+
return 0;
|
|
94
|
+
} catch (e) {
|
|
95
|
+
log('Failed to submit feedback (is `gh` authenticated?).', 'red');
|
|
96
|
+
return 1;
|
|
97
|
+
}
|
|
98
|
+
};
|