@productbrain/cli 0.1.0-beta.36 → 0.1.0-beta.38
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/dist/__tests__/experiment.test.d.ts +6 -0
- package/dist/__tests__/experiment.test.d.ts.map +1 -0
- package/dist/__tests__/experiment.test.js +69 -0
- package/dist/__tests__/experiment.test.js.map +1 -0
- package/dist/__tests__/onboarding-path-b.test.d.ts +2 -0
- package/dist/__tests__/onboarding-path-b.test.d.ts.map +1 -0
- package/dist/__tests__/onboarding-path-b.test.js +46 -0
- package/dist/__tests__/onboarding-path-b.test.js.map +1 -0
- package/dist/__tests__/onboarding.test.js +242 -89
- package/dist/__tests__/onboarding.test.js.map +1 -1
- package/dist/__tests__/setup.test.js +15 -6
- package/dist/__tests__/setup.test.js.map +1 -1
- package/dist/commands/connect-integration.test.d.ts +7 -0
- package/dist/commands/connect-integration.test.d.ts.map +1 -0
- package/dist/commands/connect-integration.test.js +148 -0
- package/dist/commands/connect-integration.test.js.map +1 -0
- package/dist/commands/connect.d.ts +17 -0
- package/dist/commands/connect.d.ts.map +1 -0
- package/dist/commands/connect.js +280 -0
- package/dist/commands/connect.js.map +1 -0
- package/dist/commands/connect.test.d.ts +6 -0
- package/dist/commands/connect.test.d.ts.map +1 -0
- package/dist/commands/connect.test.js +230 -0
- package/dist/commands/connect.test.js.map +1 -0
- package/dist/commands/handshake.d.ts +2 -0
- package/dist/commands/handshake.d.ts.map +1 -1
- package/dist/commands/handshake.js +20 -5
- package/dist/commands/handshake.js.map +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +29 -2
- package/dist/commands/setup.js.map +1 -1
- package/dist/generators/chain-classifier.d.ts +1 -1
- package/dist/generators/chain-classifier.d.ts.map +1 -1
- package/dist/generators/context-md.d.ts +1 -1
- package/dist/generators/context-md.d.ts.map +1 -1
- package/dist/generators/context-md.js +12 -1
- package/dist/generators/context-md.js.map +1 -1
- package/dist/index.js +14 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/config.d.ts +1 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +25 -1
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/conversation-engine.d.ts +22 -27
- package/dist/lib/conversation-engine.d.ts.map +1 -1
- package/dist/lib/conversation-engine.js +58 -80
- package/dist/lib/conversation-engine.js.map +1 -1
- package/dist/lib/conversation-phases.d.ts +22 -37
- package/dist/lib/conversation-phases.d.ts.map +1 -1
- package/dist/lib/conversation-phases.js +4 -4
- package/dist/lib/conversation-signals.d.ts +3 -0
- package/dist/lib/conversation-signals.d.ts.map +1 -1
- package/dist/lib/conversation-signals.js +14 -3
- package/dist/lib/conversation-signals.js.map +1 -1
- package/dist/lib/experiment.d.ts +18 -0
- package/dist/lib/experiment.d.ts.map +1 -0
- package/dist/lib/experiment.js +28 -0
- package/dist/lib/experiment.js.map +1 -0
- package/dist/lib/onboarding-path-b.d.ts +10 -0
- package/dist/lib/onboarding-path-b.d.ts.map +1 -0
- package/dist/lib/onboarding-path-b.js +214 -0
- package/dist/lib/onboarding-path-b.js.map +1 -0
- package/dist/lib/onboarding-phases.js +1 -1
- package/dist/lib/onboarding-shared.d.ts +81 -0
- package/dist/lib/onboarding-shared.d.ts.map +1 -0
- package/dist/lib/onboarding-shared.js +190 -0
- package/dist/lib/onboarding-shared.js.map +1 -0
- package/dist/lib/onboarding-topics.d.ts +27 -0
- package/dist/lib/onboarding-topics.d.ts.map +1 -0
- package/dist/lib/onboarding-topics.js +57 -0
- package/dist/lib/onboarding-topics.js.map +1 -0
- package/dist/lib/onboarding.d.ts +3 -3
- package/dist/lib/onboarding.d.ts.map +1 -1
- package/dist/lib/onboarding.js +109 -240
- package/dist/lib/onboarding.js.map +1 -1
- package/dist/lib/profiles.d.ts +5 -0
- package/dist/lib/profiles.d.ts.map +1 -1
- package/dist/lib/profiles.js +7 -0
- package/dist/lib/profiles.js.map +1 -1
- package/dist/lib/telemetry.d.ts +5 -5
- package/dist/lib/telemetry.d.ts.map +1 -1
- package/dist/lib/telemetry.js +34 -16
- package/dist/lib/telemetry.js.map +1 -1
- package/dist/lib/wizard-surfaces.d.ts +47 -0
- package/dist/lib/wizard-surfaces.d.ts.map +1 -0
- package/dist/lib/wizard-surfaces.js +176 -0
- package/dist/lib/wizard-surfaces.js.map +1 -0
- package/dist/lib/wizard-surfaces.test.d.ts +2 -0
- package/dist/lib/wizard-surfaces.test.d.ts.map +1 -0
- package/dist/lib/wizard-surfaces.test.js +127 -0
- package/dist/lib/wizard-surfaces.test.js.map +1 -0
- package/dist/lib/wizard-trust.d.ts +31 -0
- package/dist/lib/wizard-trust.d.ts.map +1 -0
- package/dist/lib/wizard-trust.js +66 -0
- package/dist/lib/wizard-trust.js.map +1 -0
- package/dist/lib/wizard-trust.test.d.ts +2 -0
- package/dist/lib/wizard-trust.test.d.ts.map +1 -0
- package/dist/lib/wizard-trust.test.js +32 -0
- package/dist/lib/wizard-trust.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -12,6 +12,7 @@ vi.mock('../lib/telemetry.js', () => ({
|
|
|
12
12
|
trackEvent: (event) => {
|
|
13
13
|
telemetryEvents.push(event);
|
|
14
14
|
},
|
|
15
|
+
initTelemetry: vi.fn(),
|
|
15
16
|
}));
|
|
16
17
|
const mcpCallMock = vi.fn();
|
|
17
18
|
const mcpCallWithSessionMock = vi.fn();
|
|
@@ -46,11 +47,19 @@ const runLoginMock = vi.fn();
|
|
|
46
47
|
vi.mock('../commands/login.js', () => ({
|
|
47
48
|
runLogin: () => runLoginMock(),
|
|
48
49
|
}));
|
|
49
|
-
// Mock
|
|
50
|
+
// Mock both onboarding paths — they have their own test files
|
|
50
51
|
const runOnboardingMock = vi.fn();
|
|
51
52
|
vi.mock('../lib/onboarding.js', () => ({
|
|
52
53
|
runOnboardingConversation: (...args) => runOnboardingMock(...args),
|
|
53
54
|
}));
|
|
55
|
+
const runOnboardingPathBMock = vi.fn();
|
|
56
|
+
vi.mock('../lib/onboarding-path-b.js', () => ({
|
|
57
|
+
runOnboardingPathB: (...args) => runOnboardingPathBMock(...args),
|
|
58
|
+
}));
|
|
59
|
+
vi.mock('../lib/experiment.js', () => ({
|
|
60
|
+
isExperimentActive: () => false,
|
|
61
|
+
assignOnboardingPath: () => 'B',
|
|
62
|
+
}));
|
|
54
63
|
let confirmAnswers = [];
|
|
55
64
|
let confirmIndex = 0;
|
|
56
65
|
vi.mock('../lib/prompts.js', () => ({
|
|
@@ -68,6 +77,7 @@ import { runSetup } from '../commands/setup.js';
|
|
|
68
77
|
describe('runSetup', () => {
|
|
69
78
|
beforeEach(() => {
|
|
70
79
|
vi.clearAllMocks();
|
|
80
|
+
runOnboardingPathBMock.mockReset();
|
|
71
81
|
telemetryEvents.length = 0;
|
|
72
82
|
confirmAnswers = [];
|
|
73
83
|
confirmIndex = 0;
|
|
@@ -84,8 +94,8 @@ describe('runSetup', () => {
|
|
|
84
94
|
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('pb_sk_'));
|
|
85
95
|
// Should show workspace name
|
|
86
96
|
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('Test Workspace'));
|
|
87
|
-
// Should call onboarding
|
|
88
|
-
expect(
|
|
97
|
+
// Should call onboarding path B (default path)
|
|
98
|
+
expect(runOnboardingPathBMock).toHaveBeenCalledWith('Test Workspace');
|
|
89
99
|
logSpy.mockRestore();
|
|
90
100
|
});
|
|
91
101
|
it('triggers login prompt when no valid config exists', async () => {
|
|
@@ -112,10 +122,9 @@ describe('runSetup', () => {
|
|
|
112
122
|
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
113
123
|
await runSetup();
|
|
114
124
|
expect(runLoginMock).toHaveBeenCalledOnce();
|
|
115
|
-
expect(telemetryEvents).toContain('setup_started');
|
|
116
125
|
expect(telemetryEvents).toContain('key_validated');
|
|
117
|
-
// Should call onboarding after login
|
|
118
|
-
expect(
|
|
126
|
+
// Should call onboarding path B after login (default path)
|
|
127
|
+
expect(runOnboardingPathBMock).toHaveBeenCalledWith('Test Workspace');
|
|
119
128
|
logSpy.mockRestore();
|
|
120
129
|
});
|
|
121
130
|
it('handles workspace verification failure gracefully', async () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.test.js","sourceRoot":"","sources":["../../src/__tests__/setup.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9D,iCAAiC;AACjC,MAAM,eAAe,GAAa,EAAE,CAAC;AAErC,EAAE,CAAC,IAAI,CAAC,qBAAqB,EAAE,GAAG,EAAE,CAAC,CAAC;IACpC,UAAU,EAAE,CAAC,KAAa,EAAE,EAAE;QAC5B,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;
|
|
1
|
+
{"version":3,"file":"setup.test.js","sourceRoot":"","sources":["../../src/__tests__/setup.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration tests for pb connect — full E2E flow (FEAT-958 S5).
|
|
3
|
+
* Covers: token validation -> redemption -> key save -> wizard -> handshake.
|
|
4
|
+
* All external deps (fs, fetch, wizard, handshake) are mocked.
|
|
5
|
+
*/
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=connect-integration.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect-integration.test.d.ts","sourceRoot":"","sources":["../../src/commands/connect-integration.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration tests for pb connect — full E2E flow (FEAT-958 S5).
|
|
3
|
+
* Covers: token validation -> redemption -> key save -> wizard -> handshake.
|
|
4
|
+
* All external deps (fs, fetch, wizard, handshake) are mocked.
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
7
|
+
// Mock modules BEFORE imports
|
|
8
|
+
const mockFetch = vi.fn();
|
|
9
|
+
global.fetch = mockFetch;
|
|
10
|
+
const mockCreateProfile = vi.fn();
|
|
11
|
+
const mockListProfiles = vi.fn(() => []);
|
|
12
|
+
vi.mock('fs', () => ({
|
|
13
|
+
mkdirSync: vi.fn(),
|
|
14
|
+
writeFileSync: vi.fn(),
|
|
15
|
+
existsSync: vi.fn(() => false),
|
|
16
|
+
readFileSync: vi.fn(() => {
|
|
17
|
+
throw new Error('ENOENT');
|
|
18
|
+
}),
|
|
19
|
+
}));
|
|
20
|
+
vi.mock('../lib/constants.js', () => ({
|
|
21
|
+
resolveAppUrl: () => 'https://test.convex.site',
|
|
22
|
+
}));
|
|
23
|
+
vi.mock('../lib/spinner.js', () => ({
|
|
24
|
+
withSpinner: async (_msg, fn) => fn(),
|
|
25
|
+
}));
|
|
26
|
+
let clackSelectCallCount = 0;
|
|
27
|
+
vi.mock('@clack/prompts', () => ({
|
|
28
|
+
select: vi.fn(async () => {
|
|
29
|
+
clackSelectCallCount++;
|
|
30
|
+
// First two calls are continue gates, third is "What's next?" menu
|
|
31
|
+
return clackSelectCallCount <= 2 ? 'continue' : 'start';
|
|
32
|
+
}),
|
|
33
|
+
isCancel: vi.fn(() => false),
|
|
34
|
+
}));
|
|
35
|
+
vi.mock('../lib/profiles.js', () => ({
|
|
36
|
+
createProfile: (...args) => mockCreateProfile(...args),
|
|
37
|
+
listProfiles: () => mockListProfiles(),
|
|
38
|
+
}));
|
|
39
|
+
vi.mock('./handshake.js', () => ({
|
|
40
|
+
runHandshake: vi.fn(async () => { }),
|
|
41
|
+
}));
|
|
42
|
+
// Import function under test and mocked modules
|
|
43
|
+
import { runConnect } from './connect.js';
|
|
44
|
+
import { writeFileSync } from 'fs';
|
|
45
|
+
import { runHandshake } from './handshake.js';
|
|
46
|
+
import { CLIError } from '../lib/errors.js';
|
|
47
|
+
import * as clack from '@clack/prompts';
|
|
48
|
+
// Suppress console output
|
|
49
|
+
const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
50
|
+
const stdoutSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
|
|
51
|
+
const originalEnv = { ...process.env };
|
|
52
|
+
describe('pb connect — integration', () => {
|
|
53
|
+
beforeEach(() => {
|
|
54
|
+
vi.clearAllMocks();
|
|
55
|
+
consoleSpy.mockClear();
|
|
56
|
+
stdoutSpy.mockClear();
|
|
57
|
+
clackSelectCallCount = 0;
|
|
58
|
+
process.env.CONVEX_SITE_URL = 'https://test.convex.site';
|
|
59
|
+
});
|
|
60
|
+
afterEach(() => {
|
|
61
|
+
process.env = { ...originalEnv };
|
|
62
|
+
});
|
|
63
|
+
it('happy path: full connect flow', async () => {
|
|
64
|
+
const token = 'pb_ct_' + 'a'.repeat(40);
|
|
65
|
+
mockFetch.mockResolvedValueOnce({
|
|
66
|
+
ok: true,
|
|
67
|
+
json: async () => ({
|
|
68
|
+
apiKey: 'pb_sk_test123',
|
|
69
|
+
workspaceId: 'ws1',
|
|
70
|
+
workspaceName: 'Test WS',
|
|
71
|
+
}),
|
|
72
|
+
});
|
|
73
|
+
await runConnect(token);
|
|
74
|
+
// fetch called with /auth/redeem-connect-token
|
|
75
|
+
expect(mockFetch).toHaveBeenCalledWith(expect.stringContaining('/auth/redeem-connect-token'), expect.objectContaining({
|
|
76
|
+
method: 'POST',
|
|
77
|
+
body: JSON.stringify({ token }),
|
|
78
|
+
}));
|
|
79
|
+
// Profile created with slugified workspace name
|
|
80
|
+
expect(mockCreateProfile).toHaveBeenCalledWith('test-ws', 'pb_sk_test123', expect.any(String));
|
|
81
|
+
// useProfile NOT called — connect doesn't hijack global profile
|
|
82
|
+
// Project config written
|
|
83
|
+
expect(writeFileSync).toHaveBeenCalled();
|
|
84
|
+
// Handshake called with no surface filtering (writes all)
|
|
85
|
+
expect(runHandshake).toHaveBeenCalledWith({
|
|
86
|
+
quiet: true,
|
|
87
|
+
});
|
|
88
|
+
// Interactive prompts were called (continue gates + what's next menu)
|
|
89
|
+
expect(clack.select).toHaveBeenCalled();
|
|
90
|
+
});
|
|
91
|
+
it('token rejection stops flow — wizard and handshake not called', async () => {
|
|
92
|
+
const token = 'pb_ct_' + 'a'.repeat(40);
|
|
93
|
+
mockFetch.mockResolvedValueOnce({
|
|
94
|
+
ok: false,
|
|
95
|
+
status: 400,
|
|
96
|
+
json: async () => ({
|
|
97
|
+
error: {
|
|
98
|
+
code: 'invalid_token',
|
|
99
|
+
message: 'Token expired',
|
|
100
|
+
},
|
|
101
|
+
}),
|
|
102
|
+
});
|
|
103
|
+
await expect(runConnect(token)).rejects.toThrow(CLIError);
|
|
104
|
+
// Handshake and prompts should NOT have been called
|
|
105
|
+
expect(runHandshake).not.toHaveBeenCalled();
|
|
106
|
+
expect(clack.select).not.toHaveBeenCalled();
|
|
107
|
+
});
|
|
108
|
+
it('invalid token format never hits server', async () => {
|
|
109
|
+
await expect(runConnect('bad_token')).rejects.toThrow(CLIError);
|
|
110
|
+
// fetch should NOT have been called
|
|
111
|
+
expect(mockFetch).not.toHaveBeenCalled();
|
|
112
|
+
});
|
|
113
|
+
it('handshake failure is non-fatal', async () => {
|
|
114
|
+
const token = 'pb_ct_' + 'a'.repeat(40);
|
|
115
|
+
mockFetch.mockResolvedValueOnce({
|
|
116
|
+
ok: true,
|
|
117
|
+
json: async () => ({
|
|
118
|
+
apiKey: 'pb_sk_test456',
|
|
119
|
+
workspaceId: 'ws2',
|
|
120
|
+
workspaceName: 'WS Two',
|
|
121
|
+
}),
|
|
122
|
+
});
|
|
123
|
+
// Make handshake throw
|
|
124
|
+
vi.mocked(runHandshake).mockRejectedValueOnce(new Error('Handshake network error'));
|
|
125
|
+
// runConnect should NOT throw despite handshake failure
|
|
126
|
+
await expect(runConnect(token)).resolves.toBeUndefined();
|
|
127
|
+
// Handshake was called (and failed gracefully)
|
|
128
|
+
expect(runHandshake).toHaveBeenCalledOnce();
|
|
129
|
+
});
|
|
130
|
+
it('clack cancel on continue gate exits with 130', async () => {
|
|
131
|
+
const token = 'pb_ct_' + 'a'.repeat(40);
|
|
132
|
+
mockFetch.mockResolvedValueOnce({
|
|
133
|
+
ok: true,
|
|
134
|
+
json: async () => ({
|
|
135
|
+
apiKey: 'pb_sk_cancel',
|
|
136
|
+
workspaceId: 'ws3',
|
|
137
|
+
workspaceName: 'Cancel WS',
|
|
138
|
+
}),
|
|
139
|
+
});
|
|
140
|
+
// Make isCancel return true on the first select call
|
|
141
|
+
vi.mocked(clack.isCancel).mockReturnValueOnce(true);
|
|
142
|
+
const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => { throw new Error('process.exit'); });
|
|
143
|
+
await expect(runConnect(token)).rejects.toThrow('process.exit');
|
|
144
|
+
expect(exitSpy).toHaveBeenCalledWith(130);
|
|
145
|
+
exitSpy.mockRestore();
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
//# sourceMappingURL=connect-integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect-integration.test.js","sourceRoot":"","sources":["../../src/commands/connect-integration.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pb connect — redeem a short-lived connect token to save an API key locally.
|
|
3
|
+
*
|
|
4
|
+
* Part of FEAT-958 Path C: Onboarding flow.
|
|
5
|
+
* Token is obtained from an onboarding link (e.g., email, QR code).
|
|
6
|
+
* S1 endpoint: POST /auth/redeem-connect-token
|
|
7
|
+
* S2 (this): CLI command to parse token, redeem, and save key locally.
|
|
8
|
+
* S3: Wizard flow (surface detection + trust level).
|
|
9
|
+
* S4: Final handshake (pb handshake).
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Main entrypoint for `pb connect <token>`.
|
|
13
|
+
* Validates token format, redeems it via /auth/redeem-connect-token,
|
|
14
|
+
* saves the key, and runs the wizard (S3).
|
|
15
|
+
*/
|
|
16
|
+
export declare function runConnect(token: string): Promise<void>;
|
|
17
|
+
//# sourceMappingURL=connect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAiNH;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoG7D"}
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pb connect — redeem a short-lived connect token to save an API key locally.
|
|
3
|
+
*
|
|
4
|
+
* Part of FEAT-958 Path C: Onboarding flow.
|
|
5
|
+
* Token is obtained from an onboarding link (e.g., email, QR code).
|
|
6
|
+
* S1 endpoint: POST /auth/redeem-connect-token
|
|
7
|
+
* S2 (this): CLI command to parse token, redeem, and save key locally.
|
|
8
|
+
* S3: Wizard flow (surface detection + trust level).
|
|
9
|
+
* S4: Final handshake (pb handshake).
|
|
10
|
+
*/
|
|
11
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
12
|
+
import { resolve } from 'path';
|
|
13
|
+
import { resolveAppUrl, resolveSiteUrl } from '../lib/constants.js';
|
|
14
|
+
import { CLIError, ErrorCode } from '../lib/errors.js';
|
|
15
|
+
import { createProfile, listProfiles, PROFILES_DIR } from '../lib/profiles.js';
|
|
16
|
+
import { withSpinner } from '../lib/spinner.js';
|
|
17
|
+
import * as clack from '@clack/prompts';
|
|
18
|
+
import { runHandshake } from './handshake.js';
|
|
19
|
+
const APP_URL = resolveAppUrl();
|
|
20
|
+
const TOKEN_PREFIX = 'pb_ct_';
|
|
21
|
+
/**
|
|
22
|
+
* Validate token format — must start with pb_ct_ and be >20 chars.
|
|
23
|
+
* @returns error message if invalid, undefined if valid.
|
|
24
|
+
*/
|
|
25
|
+
function validateTokenFormat(token) {
|
|
26
|
+
if (!token.startsWith(TOKEN_PREFIX)) {
|
|
27
|
+
return `Invalid token format. Token must start with '${TOKEN_PREFIX}'.`;
|
|
28
|
+
}
|
|
29
|
+
if (token.length < 30) {
|
|
30
|
+
return `Token is too short. Got ${token.length} chars, expected >30.`;
|
|
31
|
+
}
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* POST /auth/redeem-connect-token with the token.
|
|
36
|
+
* Returns the API key + workspace info, or throws CLIError on failure.
|
|
37
|
+
*/
|
|
38
|
+
async function redeemToken(token, siteUrl) {
|
|
39
|
+
return withSpinner('Redeeming token', async () => {
|
|
40
|
+
const controller = new AbortController();
|
|
41
|
+
const timer = setTimeout(() => controller.abort(), 5000);
|
|
42
|
+
try {
|
|
43
|
+
const res = await fetch(`${siteUrl}/auth/redeem-connect-token`, {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
headers: {
|
|
46
|
+
'Content-Type': 'application/json',
|
|
47
|
+
},
|
|
48
|
+
body: JSON.stringify({ token }),
|
|
49
|
+
signal: controller.signal,
|
|
50
|
+
});
|
|
51
|
+
clearTimeout(timer);
|
|
52
|
+
if (!res.ok) {
|
|
53
|
+
let errorCode = 'unknown_error';
|
|
54
|
+
let errorMessage = `Server returned ${res.status}`;
|
|
55
|
+
try {
|
|
56
|
+
const errorData = (await res.json());
|
|
57
|
+
if (errorData.error?.code) {
|
|
58
|
+
errorCode = errorData.error.code;
|
|
59
|
+
errorMessage = errorData.error.message ?? errorMessage;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Failed to parse error JSON — use default message
|
|
64
|
+
}
|
|
65
|
+
// Map error codes to user-friendly messages
|
|
66
|
+
if (errorCode === 'invalid_token' || res.status === 400) {
|
|
67
|
+
throw new CLIError('Token is invalid, expired, or already used. Get a new token from your onboarding link.', {
|
|
68
|
+
code: ErrorCode.AUTH_INVALID,
|
|
69
|
+
category: 'auth',
|
|
70
|
+
guidance: `Visit ${APP_URL} to get a new onboarding link, or contact support.`,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
if (errorCode === 'workspace_not_found' || res.status === 404) {
|
|
74
|
+
throw new CLIError('Workspace not found. The token may be from a deleted workspace.', {
|
|
75
|
+
code: ErrorCode.AUTH_DENIED,
|
|
76
|
+
category: 'auth',
|
|
77
|
+
guidance: 'Contact support for help.',
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
throw new CLIError(`Token redemption failed: ${errorMessage}`, {
|
|
81
|
+
code: ErrorCode.AUTH_INVALID,
|
|
82
|
+
category: 'auth',
|
|
83
|
+
guidance: `Visit ${APP_URL} to get a new onboarding link.`,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
const json = (await res.json());
|
|
87
|
+
// Check for error response (has error field)
|
|
88
|
+
if ('error' in json && json.error) {
|
|
89
|
+
const errorCode = json.error.code || 'unknown_error';
|
|
90
|
+
const errorMessage = json.error.message || 'Token redemption failed';
|
|
91
|
+
throw new CLIError(errorCode === 'invalid_token' ? 'Token is invalid, expired, or already used.' : errorMessage, {
|
|
92
|
+
code: ErrorCode.AUTH_INVALID,
|
|
93
|
+
category: 'auth',
|
|
94
|
+
guidance: `Visit ${APP_URL} to get a new onboarding link.`,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return json;
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
clearTimeout(timer);
|
|
101
|
+
// Re-throw CLIErrors (validation failures)
|
|
102
|
+
if (err instanceof CLIError)
|
|
103
|
+
throw err;
|
|
104
|
+
// Network/timeout error
|
|
105
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
106
|
+
if (msg === 'fetch failed' || msg.includes('ECONNREFUSED') || msg.includes('ENOTFOUND')) {
|
|
107
|
+
throw new CLIError('Could not reach ProductBrain. Check your internet connection.', {
|
|
108
|
+
code: ErrorCode.NETWORK_UNREACHABLE,
|
|
109
|
+
category: 'network',
|
|
110
|
+
guidance: 'Check your connection, then try again: pb connect <token>',
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
// Unknown error
|
|
114
|
+
throw new CLIError(`Network error: ${msg}`, {
|
|
115
|
+
code: ErrorCode.NETWORK_UNREACHABLE,
|
|
116
|
+
category: 'network',
|
|
117
|
+
guidance: 'Check your internet connection and try again.',
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Slugify workspace name for profile naming.
|
|
124
|
+
* Lowercase, replace spaces/special chars with hyphens, max 32 chars.
|
|
125
|
+
*/
|
|
126
|
+
function slugify(name) {
|
|
127
|
+
return name
|
|
128
|
+
.toLowerCase()
|
|
129
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
130
|
+
.replace(/^-|-$/g, '')
|
|
131
|
+
.slice(0, 32) || 'default';
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Save API key as a named profile. Creates or updates the profile.
|
|
135
|
+
* Does NOT activate the profile globally — project config (.productbrain/config.json)
|
|
136
|
+
* handles per-project resolution. User can switch manually with `pb use <profile>`.
|
|
137
|
+
* Sets process.env for the current process only (so handshake works).
|
|
138
|
+
*/
|
|
139
|
+
function saveKeyAsProfile(apiKey, siteUrl, profileName) {
|
|
140
|
+
const existing = listProfiles();
|
|
141
|
+
if (existing.includes(profileName)) {
|
|
142
|
+
// Overwrite existing profile with fresh credentials (re-connect scenario)
|
|
143
|
+
const lines = [
|
|
144
|
+
`# Product Brain CLI profile: ${profileName}`,
|
|
145
|
+
`PRODUCTBRAIN_API_KEY=${apiKey}`,
|
|
146
|
+
...(siteUrl ? [`CONVEX_SITE_URL=${siteUrl}`] : []),
|
|
147
|
+
'',
|
|
148
|
+
];
|
|
149
|
+
mkdirSync(PROFILES_DIR, { recursive: true });
|
|
150
|
+
writeFileSync(resolve(PROFILES_DIR, `${profileName}.env`), lines.join('\n'), { mode: 0o600 });
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
createProfile(profileName, apiKey, siteUrl);
|
|
154
|
+
}
|
|
155
|
+
// Don't call useProfile() — that hijacks the global active profile.
|
|
156
|
+
// Project config pins the workspace per-project instead.
|
|
157
|
+
process.env.PRODUCTBRAIN_API_KEY = apiKey;
|
|
158
|
+
process.env.CONVEX_SITE_URL = siteUrl;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Write .productbrain/config.json to pin this project to the workspace.
|
|
162
|
+
* Stores profile name + siteUrl. Does NOT include the API key (that stays in profiles, never committed).
|
|
163
|
+
*/
|
|
164
|
+
function saveProjectConfig(siteUrl, profileName) {
|
|
165
|
+
const configDir = resolve(process.cwd(), '.productbrain');
|
|
166
|
+
const configPath = resolve(configDir, 'config.json');
|
|
167
|
+
// Read existing config to preserve other fields
|
|
168
|
+
let existing = {};
|
|
169
|
+
if (existsSync(configPath)) {
|
|
170
|
+
try {
|
|
171
|
+
existing = JSON.parse(readFileSync(configPath, 'utf8'));
|
|
172
|
+
}
|
|
173
|
+
catch { /* ignore parse errors */ }
|
|
174
|
+
}
|
|
175
|
+
// Write profile + siteUrl (no API key — that stays in profiles, never committed)
|
|
176
|
+
const config = { ...existing, siteUrl, profile: profileName };
|
|
177
|
+
mkdirSync(configDir, { recursive: true });
|
|
178
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Main entrypoint for `pb connect <token>`.
|
|
182
|
+
* Validates token format, redeems it via /auth/redeem-connect-token,
|
|
183
|
+
* saves the key, and runs the wizard (S3).
|
|
184
|
+
*/
|
|
185
|
+
export async function runConnect(token) {
|
|
186
|
+
// 1. Validate token format
|
|
187
|
+
const formatError = validateTokenFormat(token);
|
|
188
|
+
if (formatError) {
|
|
189
|
+
throw new CLIError(formatError, {
|
|
190
|
+
code: ErrorCode.AUTH_INVALID,
|
|
191
|
+
category: 'auth',
|
|
192
|
+
guidance: `Usage: pb connect <token>\nToken must start with '${TOKEN_PREFIX}' and be at least 30 characters long.`,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
// 2. Determine site URL (shared constant — must match web UI endpoint)
|
|
196
|
+
const siteUrl = resolveSiteUrl().replace(/\/$/, '');
|
|
197
|
+
// 3. Redeem token
|
|
198
|
+
const result = await redeemToken(token, siteUrl);
|
|
199
|
+
// 4. Save API key as named profile + pin project config
|
|
200
|
+
const profileName = slugify(result.workspaceName);
|
|
201
|
+
saveKeyAsProfile(result.apiKey, siteUrl, profileName);
|
|
202
|
+
saveProjectConfig(siteUrl, profileName);
|
|
203
|
+
// 5. Print success
|
|
204
|
+
process.stdout.write('\n');
|
|
205
|
+
console.log(`✓ Connected to "${result.workspaceName}"`);
|
|
206
|
+
process.stdout.write('\n');
|
|
207
|
+
// 6. Run handshake — write ALL target files (no filtering)
|
|
208
|
+
console.log('Setting up your product context...\n');
|
|
209
|
+
try {
|
|
210
|
+
await runHandshake({ quiet: true });
|
|
211
|
+
console.log('✓ Context files synced to your AI tools:\n');
|
|
212
|
+
console.log(' .cursor/rules/ → Cursor');
|
|
213
|
+
console.log(' CLAUDE.md → Claude Code');
|
|
214
|
+
console.log(' .github/ → GitHub Copilot');
|
|
215
|
+
console.log(' AGENTS.md → Codex / CI');
|
|
216
|
+
console.log('');
|
|
217
|
+
console.log(' These update when you run `pb session start`.');
|
|
218
|
+
}
|
|
219
|
+
catch (err) {
|
|
220
|
+
// Handshake failure is non-fatal during connect
|
|
221
|
+
console.log('⚠ Context sync skipped (run `pb handshake` manually later)');
|
|
222
|
+
if (err instanceof Error)
|
|
223
|
+
console.log(` ${err.message}`);
|
|
224
|
+
}
|
|
225
|
+
process.stdout.write('\n');
|
|
226
|
+
// Screen 1 → Continue gate
|
|
227
|
+
const cont1 = await clack.select({
|
|
228
|
+
message: '',
|
|
229
|
+
options: [{ value: 'continue', label: 'Continue →' }],
|
|
230
|
+
});
|
|
231
|
+
if (clack.isCancel(cont1))
|
|
232
|
+
process.exit(130);
|
|
233
|
+
// 7. Profile & multi-workspace info
|
|
234
|
+
console.log(` Your API key is saved as profile "${profileName}".`);
|
|
235
|
+
console.log(' To connect another workspace, run `pb connect` with that token.');
|
|
236
|
+
console.log(' Switch between workspaces with `pb use <profile>`.\n');
|
|
237
|
+
console.log(' Context files were synced to this project.');
|
|
238
|
+
console.log(' For other repos, run `pb handshake` to set them up too.');
|
|
239
|
+
process.stdout.write('\n');
|
|
240
|
+
// Screen 2 → Continue gate
|
|
241
|
+
const cont2 = await clack.select({
|
|
242
|
+
message: '',
|
|
243
|
+
options: [{ value: 'continue', label: 'Continue →' }],
|
|
244
|
+
});
|
|
245
|
+
if (clack.isCancel(cont2))
|
|
246
|
+
process.exit(130);
|
|
247
|
+
// 8. Interactive "What's next?" menu
|
|
248
|
+
const next = await clack.select({
|
|
249
|
+
message: "What's next?",
|
|
250
|
+
options: [
|
|
251
|
+
{ value: 'start', label: 'Start coding', hint: 'Just one step' },
|
|
252
|
+
{ value: 'connect', label: 'Connect another workspace' },
|
|
253
|
+
{ value: 'docs', label: 'Learn more', hint: 'productbrain.io/docs' },
|
|
254
|
+
{ value: 'community', label: 'Join the community', hint: 'community.productbrain.io' },
|
|
255
|
+
],
|
|
256
|
+
});
|
|
257
|
+
if (clack.isCancel(next))
|
|
258
|
+
process.exit(130);
|
|
259
|
+
process.stdout.write('\n');
|
|
260
|
+
switch (next) {
|
|
261
|
+
case 'start':
|
|
262
|
+
console.log(' Next time you open your AI tool in this project, run:\n');
|
|
263
|
+
console.log(' pb session start\n');
|
|
264
|
+
console.log(' That refreshes your product context and starts a tracked session.');
|
|
265
|
+
console.log(' Then just code normally — your AI already has your context.');
|
|
266
|
+
break;
|
|
267
|
+
case 'connect':
|
|
268
|
+
console.log(' Run `pb connect <token>` with the token from your other workspace.');
|
|
269
|
+
console.log(' Each workspace gets its own profile. Switch with `pb use <profile>`.');
|
|
270
|
+
break;
|
|
271
|
+
case 'docs':
|
|
272
|
+
console.log(' → https://productbrain.io/docs');
|
|
273
|
+
break;
|
|
274
|
+
case 'community':
|
|
275
|
+
console.log(' → https://community.productbrain.io');
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
process.stdout.write('\n');
|
|
279
|
+
}
|
|
280
|
+
//# sourceMappingURL=connect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.test.d.ts","sourceRoot":"","sources":["../../src/commands/connect.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|