@sixseven-ai/cli 0.1.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/README.md +143 -0
- package/USAGE.md +94 -0
- package/dist/api.js +181 -0
- package/dist/api.js.map +1 -0
- package/dist/bin.js +86 -0
- package/dist/bin.js.map +1 -0
- package/dist/commands/doctor.js +90 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/init.js +97 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/login.js +42 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/setup.js +185 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/status.js +36 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/config.js +125 -0
- package/dist/config.js.map +1 -0
- package/dist/mcp/server.js +561 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/source-reader.js +200 -0
- package/dist/source-reader.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import pc from 'picocolors';
|
|
4
|
+
import prompts from 'prompts';
|
|
5
|
+
import { SixSevenApi } from '../api.js';
|
|
6
|
+
import { DEFAULT_EXCLUDE, getToken, normalizeBaseUrl, projectConfigSchema, writeProjectConfig, } from '../config.js';
|
|
7
|
+
async function suggestCodeRoots(cwd) {
|
|
8
|
+
const candidates = ['src', 'app', 'apps', 'packages', 'lib', 'server'];
|
|
9
|
+
const found = [];
|
|
10
|
+
for (const c of candidates) {
|
|
11
|
+
try {
|
|
12
|
+
const stat = await fs.stat(path.join(cwd, c));
|
|
13
|
+
if (stat.isDirectory())
|
|
14
|
+
found.push(c);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// skip
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return found.length ? found : ['.'];
|
|
21
|
+
}
|
|
22
|
+
export async function initCommand(opts) {
|
|
23
|
+
const cwd = process.cwd();
|
|
24
|
+
let baseUrl = opts.baseUrl;
|
|
25
|
+
if (!baseUrl) {
|
|
26
|
+
if (opts.nonInteractive)
|
|
27
|
+
throw new Error('--base-url required');
|
|
28
|
+
const ans = await prompts({
|
|
29
|
+
type: 'text',
|
|
30
|
+
name: 'baseUrl',
|
|
31
|
+
message: 'SixSeven base URL',
|
|
32
|
+
initial: 'http://localhost:3067',
|
|
33
|
+
});
|
|
34
|
+
baseUrl = ans.baseUrl;
|
|
35
|
+
}
|
|
36
|
+
if (!baseUrl)
|
|
37
|
+
throw new Error('Aborted.');
|
|
38
|
+
const token = await getToken(baseUrl);
|
|
39
|
+
if (!token) {
|
|
40
|
+
throw new Error(`No saved token for ${normalizeBaseUrl(baseUrl)}. Run \`sixseven login\` first.`);
|
|
41
|
+
}
|
|
42
|
+
const api = new SixSevenApi({ baseUrl, token });
|
|
43
|
+
let projectId = opts.projectId;
|
|
44
|
+
if (!projectId) {
|
|
45
|
+
process.stdout.write(pc.dim('Fetching projects...\n'));
|
|
46
|
+
const projects = await api.listProjects();
|
|
47
|
+
if (!projects.length) {
|
|
48
|
+
throw new Error('No projects accessible with this token.');
|
|
49
|
+
}
|
|
50
|
+
if (opts.nonInteractive) {
|
|
51
|
+
throw new Error('--project-id required in non-interactive mode');
|
|
52
|
+
}
|
|
53
|
+
const ans = await prompts({
|
|
54
|
+
type: 'select',
|
|
55
|
+
name: 'projectId',
|
|
56
|
+
message: 'Select SixSeven project to bind this repo to',
|
|
57
|
+
choices: projects.map((p) => ({
|
|
58
|
+
title: p.name,
|
|
59
|
+
description: p.id,
|
|
60
|
+
value: p.id,
|
|
61
|
+
})),
|
|
62
|
+
});
|
|
63
|
+
projectId = ans.projectId;
|
|
64
|
+
}
|
|
65
|
+
if (!projectId)
|
|
66
|
+
throw new Error('Aborted.');
|
|
67
|
+
const codeRoots = await suggestCodeRoots(cwd);
|
|
68
|
+
const platformAns = opts.nonInteractive
|
|
69
|
+
? { platform: 'web' }
|
|
70
|
+
: await prompts({
|
|
71
|
+
type: 'select',
|
|
72
|
+
name: 'platform',
|
|
73
|
+
message: 'Default platform for testcases',
|
|
74
|
+
choices: [
|
|
75
|
+
{ title: 'web', value: 'web' },
|
|
76
|
+
{ title: 'android', value: 'android' },
|
|
77
|
+
{ title: 'ios', value: 'ios' },
|
|
78
|
+
],
|
|
79
|
+
initial: 0,
|
|
80
|
+
});
|
|
81
|
+
const cfg = projectConfigSchema.parse({
|
|
82
|
+
baseUrl: normalizeBaseUrl(baseUrl),
|
|
83
|
+
projectId,
|
|
84
|
+
defaultFeatureId: null,
|
|
85
|
+
codeRoots,
|
|
86
|
+
exclude: DEFAULT_EXCLUDE,
|
|
87
|
+
platform: platformAns.platform ?? 'web',
|
|
88
|
+
});
|
|
89
|
+
const written = await writeProjectConfig(cwd, cfg);
|
|
90
|
+
process.stdout.write(pc.green(`✓ Wrote ${path.relative(cwd, written)}\n`));
|
|
91
|
+
process.stdout.write(pc.dim(` baseUrl: ${cfg.baseUrl}\n`));
|
|
92
|
+
process.stdout.write(pc.dim(` projectId: ${cfg.projectId}\n`));
|
|
93
|
+
process.stdout.write(pc.dim(` codeRoots: ${cfg.codeRoots.join(', ')}\n`));
|
|
94
|
+
process.stdout.write(pc.dim(` platform: ${cfg.platform}\n`));
|
|
95
|
+
process.stdout.write(`\nNext: register the MCP server with Claude Code:\n${pc.cyan(' claude mcp add sixseven -- npx -y @sixseven/cli mcp\n')}`);
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import pc from 'picocolors';
|
|
2
|
+
import prompts from 'prompts';
|
|
3
|
+
import { SixSevenApi } from '../api.js';
|
|
4
|
+
import { normalizeBaseUrl, saveToken } from '../config.js';
|
|
5
|
+
export async function loginCommand(opts) {
|
|
6
|
+
let baseUrl = opts.baseUrl;
|
|
7
|
+
let token = opts.token;
|
|
8
|
+
if (!baseUrl) {
|
|
9
|
+
if (opts.nonInteractive)
|
|
10
|
+
throw new Error('--base-url required in non-interactive mode');
|
|
11
|
+
const ans = await prompts({
|
|
12
|
+
type: 'text',
|
|
13
|
+
name: 'baseUrl',
|
|
14
|
+
message: 'SixSeven base URL',
|
|
15
|
+
initial: 'http://localhost:3067',
|
|
16
|
+
validate: (v) => /^https?:\/\//.test(v) ? true : 'must start with http(s)://',
|
|
17
|
+
});
|
|
18
|
+
baseUrl = ans.baseUrl;
|
|
19
|
+
}
|
|
20
|
+
if (!baseUrl)
|
|
21
|
+
throw new Error('Aborted.');
|
|
22
|
+
if (!token) {
|
|
23
|
+
if (opts.nonInteractive)
|
|
24
|
+
throw new Error('--token required in non-interactive mode');
|
|
25
|
+
const ans = await prompts({
|
|
26
|
+
type: 'password',
|
|
27
|
+
name: 'token',
|
|
28
|
+
message: 'CI token (starts with 67ci_)',
|
|
29
|
+
validate: (v) => v.startsWith('67ci_') ? true : 'must start with 67ci_',
|
|
30
|
+
});
|
|
31
|
+
token = ans.token;
|
|
32
|
+
}
|
|
33
|
+
if (!token)
|
|
34
|
+
throw new Error('Aborted.');
|
|
35
|
+
process.stdout.write(pc.dim(`Verifying token against ${baseUrl}...\n`));
|
|
36
|
+
const api = new SixSevenApi({ baseUrl, token });
|
|
37
|
+
const user = await api.me();
|
|
38
|
+
process.stdout.write(pc.green(`✓ Logged in as ${user.email} (role: ${user.role})\n`));
|
|
39
|
+
await saveToken(baseUrl, token);
|
|
40
|
+
process.stdout.write(pc.dim(`Saved token for ${normalizeBaseUrl(baseUrl)} to ~/.sixseven/credentials\n`));
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAQ3D,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAkB;IACnD,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAC3B,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IAEvB,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,IAAI,IAAI,CAAC,cAAc;YACrB,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC;YACxB,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,mBAAmB;YAC5B,OAAO,EAAE,uBAAuB;YAChC,QAAQ,EAAE,CAAC,CAAS,EAAE,EAAE,CACtB,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,4BAA4B;SAC/D,CAAC,CAAC;QACH,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;IACxB,CAAC;IACD,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC;IAE1C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,IAAI,IAAI,CAAC,cAAc;YACrB,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC9D,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC;YACxB,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,8BAA8B;YACvC,QAAQ,EAAE,CAAC,CAAS,EAAE,EAAE,CACtB,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,uBAAuB;SACzD,CAAC,CAAC;QACH,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;IACpB,CAAC;IACD,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC;IAExC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,2BAA2B,OAAO,OAAO,CAAC,CAAC,CAAC;IACxE,MAAM,GAAG,GAAG,IAAI,WAAW,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,EAAE,EAAE,CAAC;IAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,EAAE,CAAC,KAAK,CAAC,kBAAkB,IAAI,CAAC,KAAK,WAAW,IAAI,CAAC,IAAI,KAAK,CAAC,CAChE,CAAC;IAEF,MAAM,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAChC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,EAAE,CAAC,GAAG,CACJ,mBAAmB,gBAAgB,CAAC,OAAO,CAAC,+BAA+B,CAC5E,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
2
|
+
import { promises as fs } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import pc from 'picocolors';
|
|
5
|
+
import prompts from 'prompts';
|
|
6
|
+
import { SixSevenApi } from '../api.js';
|
|
7
|
+
import { getToken, normalizeBaseUrl, readProjectConfig } from '../config.js';
|
|
8
|
+
import { initCommand } from './init.js';
|
|
9
|
+
import { loginCommand } from './login.js';
|
|
10
|
+
function hasBinaryOnPath(bin) {
|
|
11
|
+
const r = spawnSync(process.platform === 'win32' ? 'where' : 'which', [bin], {
|
|
12
|
+
stdio: 'ignore',
|
|
13
|
+
});
|
|
14
|
+
return r.status === 0;
|
|
15
|
+
}
|
|
16
|
+
function resolveMcpInvocation() {
|
|
17
|
+
if (hasBinaryOnPath('sixseven')) {
|
|
18
|
+
return { command: 'sixseven', args: ['mcp'], display: 'sixseven mcp' };
|
|
19
|
+
}
|
|
20
|
+
const entry = process.argv[1];
|
|
21
|
+
return {
|
|
22
|
+
command: process.execPath,
|
|
23
|
+
args: [entry, 'mcp'],
|
|
24
|
+
display: `node ${entry} mcp`,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
async function registerWithClaudeCode(invocation) {
|
|
28
|
+
if (!hasBinaryOnPath('claude')) {
|
|
29
|
+
process.stdout.write(pc.yellow('! `claude` CLI not found on PATH — skipping auto-registration.\n'));
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
return await new Promise((resolve) => {
|
|
33
|
+
const child = spawn('claude', ['mcp', 'add', 'sixseven', '--', invocation.command, ...invocation.args], { stdio: 'inherit' });
|
|
34
|
+
child.on('exit', (code) => resolve(code === 0));
|
|
35
|
+
child.on('error', () => resolve(false));
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function printManualSnippets(target, invocation) {
|
|
39
|
+
const argsJson = JSON.stringify(invocation.args);
|
|
40
|
+
if (target === 'cursor') {
|
|
41
|
+
process.stdout.write(`\n${pc.bold('Add to')} ${pc.cyan('.cursor/mcp.json')}:\n`);
|
|
42
|
+
process.stdout.write(`${pc.dim(JSON.stringify({
|
|
43
|
+
mcpServers: {
|
|
44
|
+
sixseven: { command: invocation.command, args: invocation.args },
|
|
45
|
+
},
|
|
46
|
+
}, null, 2))}\n`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (target === 'claude-desktop') {
|
|
50
|
+
process.stdout.write(`\n${pc.bold('Add to Claude Desktop config')} (${pc.cyan('~/Library/Application Support/Claude/claude_desktop_config.json')} on macOS):\n`);
|
|
51
|
+
process.stdout.write(`${pc.dim(JSON.stringify({
|
|
52
|
+
mcpServers: {
|
|
53
|
+
sixseven: { command: invocation.command, args: invocation.args },
|
|
54
|
+
},
|
|
55
|
+
}, null, 2))}\n`);
|
|
56
|
+
void argsJson;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export async function setupCommand(opts) {
|
|
60
|
+
const cwd = process.cwd();
|
|
61
|
+
process.stdout.write(pc.bold('SixSeven setup\n') +
|
|
62
|
+
pc.dim('Walks through: login → bind project → register MCP.\n\n'));
|
|
63
|
+
// 1. Login (skip if token already saved for this baseUrl)
|
|
64
|
+
let baseUrl = opts.baseUrl;
|
|
65
|
+
if (!baseUrl && !opts.nonInteractive) {
|
|
66
|
+
const ans = await prompts({
|
|
67
|
+
type: 'text',
|
|
68
|
+
name: 'baseUrl',
|
|
69
|
+
message: 'SixSeven base URL',
|
|
70
|
+
initial: 'http://localhost:3067',
|
|
71
|
+
validate: (v) => /^https?:\/\//.test(v) ? true : 'must start with http(s)://',
|
|
72
|
+
});
|
|
73
|
+
baseUrl = ans.baseUrl;
|
|
74
|
+
}
|
|
75
|
+
if (!baseUrl)
|
|
76
|
+
throw new Error('Aborted (no base URL).');
|
|
77
|
+
const existingToken = await getToken(baseUrl);
|
|
78
|
+
let tokenValid = false;
|
|
79
|
+
if (existingToken) {
|
|
80
|
+
try {
|
|
81
|
+
const api = new SixSevenApi({ baseUrl, token: existingToken });
|
|
82
|
+
const user = await api.me();
|
|
83
|
+
process.stdout.write(pc.green(`✓ Token already saved for ${normalizeBaseUrl(baseUrl)} (${user.email}). Skipping login.\n`));
|
|
84
|
+
tokenValid = true;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
process.stdout.write(pc.yellow(`! Saved token for ${normalizeBaseUrl(baseUrl)} is invalid — re-login required.\n`));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (!tokenValid) {
|
|
91
|
+
process.stdout.write(pc.bold('\n[1/3] Login\n'));
|
|
92
|
+
await loginCommand({
|
|
93
|
+
baseUrl,
|
|
94
|
+
token: opts.token,
|
|
95
|
+
nonInteractive: !!opts.nonInteractive,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
// 2. Init (skip / confirm if config already exists)
|
|
99
|
+
process.stdout.write(pc.bold('\n[2/3] Bind project\n'));
|
|
100
|
+
const existing = await readProjectConfig(cwd).catch(() => null);
|
|
101
|
+
let shouldInit = true;
|
|
102
|
+
if (existing) {
|
|
103
|
+
process.stdout.write(pc.dim(` Found existing .sixseven/config.json → projectId ${existing.projectId} on ${existing.baseUrl}\n`));
|
|
104
|
+
if (opts.nonInteractive) {
|
|
105
|
+
shouldInit = false;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
const ans = await prompts({
|
|
109
|
+
type: 'confirm',
|
|
110
|
+
name: 'rebind',
|
|
111
|
+
message: 'Re-bind this repo to a different project?',
|
|
112
|
+
initial: false,
|
|
113
|
+
});
|
|
114
|
+
shouldInit = !!ans.rebind;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (shouldInit) {
|
|
118
|
+
await initCommand({
|
|
119
|
+
baseUrl,
|
|
120
|
+
projectId: opts.projectId,
|
|
121
|
+
nonInteractive: !!opts.nonInteractive,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
process.stdout.write(pc.dim(' Keeping existing binding.\n'));
|
|
126
|
+
}
|
|
127
|
+
// 3. MCP registration
|
|
128
|
+
process.stdout.write(pc.bold('\n[3/3] Register MCP server\n'));
|
|
129
|
+
if (opts.skipMcp) {
|
|
130
|
+
process.stdout.write(pc.dim(' --skip-mcp set, skipping.\n'));
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const invocation = resolveMcpInvocation();
|
|
134
|
+
process.stdout.write(pc.dim(` MCP launch command: ${invocation.display}\n\n`));
|
|
135
|
+
let target;
|
|
136
|
+
if (opts.nonInteractive) {
|
|
137
|
+
target = 'claude-code';
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
const ans = await prompts({
|
|
141
|
+
type: 'select',
|
|
142
|
+
name: 'target',
|
|
143
|
+
message: 'Where do you want to register the MCP server?',
|
|
144
|
+
choices: [
|
|
145
|
+
{
|
|
146
|
+
title: 'Claude Code (auto via `claude mcp add`)',
|
|
147
|
+
value: 'claude-code',
|
|
148
|
+
},
|
|
149
|
+
{ title: 'Cursor (print .cursor/mcp.json snippet)', value: 'cursor' },
|
|
150
|
+
{
|
|
151
|
+
title: 'Claude Desktop (print config snippet)',
|
|
152
|
+
value: 'claude-desktop',
|
|
153
|
+
},
|
|
154
|
+
{ title: 'Skip — I will do it manually', value: 'skip' },
|
|
155
|
+
],
|
|
156
|
+
initial: 0,
|
|
157
|
+
});
|
|
158
|
+
target = ans.target ?? 'skip';
|
|
159
|
+
}
|
|
160
|
+
if (target === 'claude-code') {
|
|
161
|
+
const ok = await registerWithClaudeCode(invocation);
|
|
162
|
+
if (ok) {
|
|
163
|
+
process.stdout.write(pc.green('\n✓ Registered as MCP server "sixseven" with Claude Code.\n'));
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
process.stdout.write(pc.yellow('\n! Auto-registration failed. Run manually:\n') +
|
|
167
|
+
pc.cyan(` claude mcp add sixseven -- ${invocation.command} ${invocation.args.join(' ')}\n`));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
else if (target === 'skip') {
|
|
171
|
+
process.stdout.write(pc.dim(' Manual command:\n') +
|
|
172
|
+
pc.cyan(` claude mcp add sixseven -- ${invocation.command} ${invocation.args.join(' ')}\n`));
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
printManualSnippets(target, invocation);
|
|
176
|
+
}
|
|
177
|
+
// Final summary
|
|
178
|
+
const cfgPath = path.join(cwd, '.sixseven', 'config.json');
|
|
179
|
+
const cfgExists = await fs
|
|
180
|
+
.stat(cfgPath)
|
|
181
|
+
.then(() => true)
|
|
182
|
+
.catch(() => false);
|
|
183
|
+
process.stdout.write(`\n${pc.bold('Done.')} ${pc.dim('Next:')}\n${pc.dim(` • sixseven status — verify binding (${cfgExists ? 'config OK' : 'no config'})\n`)}${pc.dim(' • sixseven doctor — full diagnostics\n')}${pc.dim(' • Open Claude Code and ask: "list sixseven features"\n')}`);
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import pc from 'picocolors';
|
|
2
|
+
import { SixSevenApi } from '../api.js';
|
|
3
|
+
import { loadContext } from '../config.js';
|
|
4
|
+
export async function statusCommand() {
|
|
5
|
+
const ctx = await loadContext(process.cwd());
|
|
6
|
+
const api = new SixSevenApi({
|
|
7
|
+
baseUrl: ctx.config.baseUrl,
|
|
8
|
+
token: ctx.token,
|
|
9
|
+
});
|
|
10
|
+
process.stdout.write(pc.bold('SixSeven CLI status\n'));
|
|
11
|
+
process.stdout.write(` config: ${ctx.configPath}\n`);
|
|
12
|
+
process.stdout.write(` repoRoot: ${ctx.repoRoot}\n`);
|
|
13
|
+
process.stdout.write(` baseUrl: ${ctx.config.baseUrl}\n`);
|
|
14
|
+
process.stdout.write(` projectId: ${ctx.config.projectId}\n`);
|
|
15
|
+
process.stdout.write(` platform: ${ctx.config.platform}\n`);
|
|
16
|
+
process.stdout.write(` codeRoots: ${ctx.config.codeRoots.join(', ')}\n`);
|
|
17
|
+
try {
|
|
18
|
+
const user = await api.me();
|
|
19
|
+
process.stdout.write(pc.green(` token: ✓ valid (user: ${user.email}, role: ${user.role})\n`));
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
process.stdout.write(pc.red(` token: ✗ ${err.message}\n`));
|
|
23
|
+
process.exitCode = 1;
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const features = await api.listFeatures(ctx.config.projectId);
|
|
28
|
+
process.stdout.write(` features: ${features.length}\n`);
|
|
29
|
+
const tcs = await api.listTestCasesByProject(ctx.config.projectId);
|
|
30
|
+
process.stdout.write(` testcases: ${tcs.length}\n`);
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
process.stdout.write(pc.yellow(` warn: ${err.message}\n`));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,IAAI,WAAW,CAAC;QAC1B,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO;QAC3B,KAAK,EAAE,GAAG,CAAC,KAAK;KACjB,CAAC,CAAC;IAEH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC;IACvD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,GAAG,CAAC,UAAU,IAAI,CAAC,CAAC;IACzD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,GAAG,CAAC,QAAQ,IAAI,CAAC,CAAC;IACvD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;IAC7D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC;IAC/D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC;IAC9D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE1E,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,EAAE,EAAE,CAAC;QAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,EAAE,CAAC,KAAK,CACN,+BAA+B,IAAI,CAAC,KAAK,WAAW,IAAI,CAAC,IAAI,KAAK,CACnE,CACF,CAAC;IACJ,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,kBAAkB,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;QAChE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC9D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,sBAAsB,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACnE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;IACvD,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;IAC9D,CAAC;AACH,CAAC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
const DEFAULT_EXCLUDE = [
|
|
6
|
+
'node_modules',
|
|
7
|
+
'dist',
|
|
8
|
+
'build',
|
|
9
|
+
'.git',
|
|
10
|
+
'.next',
|
|
11
|
+
'.turbo',
|
|
12
|
+
'coverage',
|
|
13
|
+
'.cache',
|
|
14
|
+
];
|
|
15
|
+
export const PROJECT_CONFIG_FILENAME = '.sixseven/config.json';
|
|
16
|
+
/**
|
|
17
|
+
* Resolve credentials directory. Honors `SIXSEVEN_HOME` for sandboxed runs
|
|
18
|
+
* (CI, tests). Falls back to `~/.sixseven`.
|
|
19
|
+
*/
|
|
20
|
+
export function credentialsDir() {
|
|
21
|
+
return process.env.SIXSEVEN_HOME ?? path.join(homedir(), '.sixseven');
|
|
22
|
+
}
|
|
23
|
+
export function credentialsFile() {
|
|
24
|
+
return path.join(credentialsDir(), 'credentials');
|
|
25
|
+
}
|
|
26
|
+
export const projectConfigSchema = z.object({
|
|
27
|
+
baseUrl: z.string().url(),
|
|
28
|
+
projectId: z.string().min(1),
|
|
29
|
+
defaultFeatureId: z.string().nullish(),
|
|
30
|
+
codeRoots: z.array(z.string().min(1)).default(['.']),
|
|
31
|
+
exclude: z.array(z.string()).default(DEFAULT_EXCLUDE),
|
|
32
|
+
platform: z.enum(['web', 'android', 'ios']).default('web'),
|
|
33
|
+
});
|
|
34
|
+
export const credentialsSchema = z.object({
|
|
35
|
+
tokens: z.record(z.string()).default({}),
|
|
36
|
+
});
|
|
37
|
+
async function fileExists(p) {
|
|
38
|
+
try {
|
|
39
|
+
await fs.stat(p);
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export async function findRepoRoot(start) {
|
|
47
|
+
let cur = path.resolve(start);
|
|
48
|
+
// walk up looking for .sixseven/config.json
|
|
49
|
+
while (true) {
|
|
50
|
+
if (await fileExists(path.join(cur, PROJECT_CONFIG_FILENAME))) {
|
|
51
|
+
return cur;
|
|
52
|
+
}
|
|
53
|
+
const parent = path.dirname(cur);
|
|
54
|
+
if (parent === cur)
|
|
55
|
+
return null;
|
|
56
|
+
cur = parent;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export async function readProjectConfig(repoRoot) {
|
|
60
|
+
const p = path.join(repoRoot, PROJECT_CONFIG_FILENAME);
|
|
61
|
+
const raw = await fs.readFile(p, 'utf8');
|
|
62
|
+
const parsed = JSON.parse(raw);
|
|
63
|
+
return projectConfigSchema.parse(parsed);
|
|
64
|
+
}
|
|
65
|
+
export async function writeProjectConfig(repoRoot, cfg) {
|
|
66
|
+
const dir = path.join(repoRoot, '.sixseven');
|
|
67
|
+
await fs.mkdir(dir, { recursive: true });
|
|
68
|
+
const p = path.join(dir, 'config.json');
|
|
69
|
+
await fs.writeFile(p, `${JSON.stringify(cfg, null, 2)}\n`, 'utf8');
|
|
70
|
+
return p;
|
|
71
|
+
}
|
|
72
|
+
export async function readCredentials() {
|
|
73
|
+
const file = credentialsFile();
|
|
74
|
+
if (!(await fileExists(file))) {
|
|
75
|
+
return { tokens: {} };
|
|
76
|
+
}
|
|
77
|
+
const raw = await fs.readFile(file, 'utf8');
|
|
78
|
+
try {
|
|
79
|
+
return credentialsSchema.parse(JSON.parse(raw));
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return { tokens: {} };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export async function writeCredentials(creds) {
|
|
86
|
+
await fs.mkdir(credentialsDir(), { recursive: true, mode: 0o700 });
|
|
87
|
+
await fs.writeFile(credentialsFile(), `${JSON.stringify(creds, null, 2)}\n`, {
|
|
88
|
+
mode: 0o600,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
export async function saveToken(baseUrl, token) {
|
|
92
|
+
const creds = await readCredentials();
|
|
93
|
+
creds.tokens[normalizeBaseUrl(baseUrl)] = token;
|
|
94
|
+
await writeCredentials(creds);
|
|
95
|
+
}
|
|
96
|
+
export async function getToken(baseUrl) {
|
|
97
|
+
const creds = await readCredentials();
|
|
98
|
+
return creds.tokens[normalizeBaseUrl(baseUrl)] ?? null;
|
|
99
|
+
}
|
|
100
|
+
export function normalizeBaseUrl(u) {
|
|
101
|
+
return u.replace(/\/+$/, '');
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Resolve full runtime context: locate project config, load it, find matching
|
|
105
|
+
* token. Throws with an actionable message when anything is missing.
|
|
106
|
+
*/
|
|
107
|
+
export async function loadContext(cwd) {
|
|
108
|
+
const repoRoot = await findRepoRoot(cwd);
|
|
109
|
+
if (!repoRoot) {
|
|
110
|
+
throw new Error(`No ${PROJECT_CONFIG_FILENAME} found in this directory or any parent. Run \`sixseven init\` to create one.`);
|
|
111
|
+
}
|
|
112
|
+
const config = await readProjectConfig(repoRoot);
|
|
113
|
+
const token = await getToken(config.baseUrl);
|
|
114
|
+
if (!token) {
|
|
115
|
+
throw new Error(`No saved token for ${config.baseUrl}. Run \`sixseven login\` first.`);
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
config,
|
|
119
|
+
configPath: path.join(repoRoot, PROJECT_CONFIG_FILENAME),
|
|
120
|
+
repoRoot,
|
|
121
|
+
token,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
export { DEFAULT_EXCLUDE };
|
|
125
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|