jobarbiter 0.3.1 → 0.3.3
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/lib/config.d.ts +2 -0
- package/dist/lib/detect-tools.d.ts +46 -0
- package/dist/lib/detect-tools.js +473 -0
- package/dist/lib/observe.d.ts +6 -2
- package/dist/lib/observe.js +111 -129
- package/dist/lib/onboard.js +211 -127
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/lib/config.ts +2 -0
- package/src/lib/detect-tools.ts +526 -0
- package/src/lib/observe.ts +116 -131
- package/src/lib/onboard.ts +229 -143
package/dist/lib/onboard.js
CHANGED
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
import * as readline from "node:readline";
|
|
11
11
|
import { loadConfig, saveConfig, getConfigPath } from "./config.js";
|
|
12
12
|
import { apiUnauthenticated, api, ApiError } from "./api.js";
|
|
13
|
-
import {
|
|
13
|
+
import { installObservers } from "./observe.js";
|
|
14
|
+
import { detectAllTools, formatToolDisplay, } from "./detect-tools.js";
|
|
14
15
|
// ── ANSI Colors ────────────────────────────────────────────────────────
|
|
15
16
|
const colors = {
|
|
16
17
|
reset: "\x1b[0m",
|
|
@@ -91,13 +92,45 @@ class Prompt {
|
|
|
91
92
|
// ── Main Wizard ────────────────────────────────────────────────────────
|
|
92
93
|
export async function runOnboardWizard(opts) {
|
|
93
94
|
const baseUrl = opts.baseUrl || "https://jobarbiter-api-production.up.railway.app";
|
|
94
|
-
// Check for existing config
|
|
95
|
+
// Check for existing config — resume if onboarding incomplete
|
|
95
96
|
const existingConfig = loadConfig();
|
|
96
97
|
if (existingConfig && !opts.force) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
if (existingConfig.onboardingComplete) {
|
|
99
|
+
console.log(`\n${sym.check} ${c.success("You're already onboarded!")}`);
|
|
100
|
+
console.log(`\n Run ${c.highlight("jobarbiter status")} to check your account.`);
|
|
101
|
+
console.log(` Run ${c.highlight("jobarbiter onboard --force")} to start fresh.\n`);
|
|
102
|
+
process.exit(0);
|
|
103
|
+
}
|
|
104
|
+
// Onboarding incomplete — resume
|
|
105
|
+
const resumeStep = (existingConfig.onboardingStep ?? 1) + 1;
|
|
106
|
+
console.log(`\n${sym.rocket} ${c.bold("Resuming onboarding")} from step ${resumeStep}/6\n`);
|
|
107
|
+
console.log(c.dim(` Account: ${existingConfig.userType} | API key configured`));
|
|
108
|
+
console.log(c.dim(` Run ${c.highlight("jobarbiter onboard --force")} to start over.\n`));
|
|
109
|
+
const prompt = new Prompt();
|
|
110
|
+
const state = {
|
|
111
|
+
baseUrl,
|
|
112
|
+
apiKey: existingConfig.apiKey,
|
|
113
|
+
userType: existingConfig.userType,
|
|
114
|
+
userId: "",
|
|
115
|
+
email: "",
|
|
116
|
+
};
|
|
117
|
+
try {
|
|
118
|
+
if (existingConfig.userType === "worker" || existingConfig.userType === "seeker") {
|
|
119
|
+
await runWorkerFlow(prompt, state, resumeStep);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
await runEmployerFlow(prompt, state);
|
|
123
|
+
}
|
|
124
|
+
prompt.close();
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
prompt.close();
|
|
128
|
+
if (err instanceof Error) {
|
|
129
|
+
console.log(`\n${sym.cross} ${c.error(err.message)}`);
|
|
130
|
+
}
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
return;
|
|
101
134
|
}
|
|
102
135
|
const prompt = new Prompt();
|
|
103
136
|
const state = { baseUrl };
|
|
@@ -111,11 +144,13 @@ export async function runOnboardWizard(opts) {
|
|
|
111
144
|
state.email = email;
|
|
112
145
|
state.apiKey = apiKey;
|
|
113
146
|
state.userId = userId;
|
|
114
|
-
// Save config immediately after verification
|
|
147
|
+
// Save config immediately after verification (with step progress)
|
|
115
148
|
saveConfig({
|
|
116
149
|
apiKey,
|
|
117
150
|
baseUrl,
|
|
118
151
|
userType,
|
|
152
|
+
onboardingStep: 1,
|
|
153
|
+
onboardingComplete: false,
|
|
119
154
|
});
|
|
120
155
|
if (userType === "worker") {
|
|
121
156
|
await runWorkerFlow(prompt, state);
|
|
@@ -164,7 +199,9 @@ async function selectUserType(prompt) {
|
|
|
164
199
|
}
|
|
165
200
|
// ── Email & Verification ───────────────────────────────────────────────
|
|
166
201
|
async function handleEmailVerification(prompt, baseUrl, userType) {
|
|
167
|
-
|
|
202
|
+
// Workers: 1) Account, 2) Tool Detection, 3) Domains, 4) GitHub, 5) LinkedIn, 6) Done
|
|
203
|
+
// Employers: 1) Account, 2) (skip verification), 3) Company, 4) Domain, 5) What You Need, 6) Done
|
|
204
|
+
const totalSteps = 6;
|
|
168
205
|
console.log(`\n${sym.email} ${c.bold(`Step 1/${totalSteps} — Create Your Account`)}\n`);
|
|
169
206
|
// Get email
|
|
170
207
|
let email;
|
|
@@ -234,160 +271,207 @@ async function handleEmailVerification(prompt, baseUrl, userType) {
|
|
|
234
271
|
return { email, apiKey, userId };
|
|
235
272
|
}
|
|
236
273
|
// ── Worker Flow ────────────────────────────────────────────────────────
|
|
237
|
-
async function runWorkerFlow(prompt, state) {
|
|
274
|
+
async function runWorkerFlow(prompt, state, startStep = 2) {
|
|
238
275
|
const config = {
|
|
239
276
|
apiKey: state.apiKey,
|
|
240
277
|
baseUrl: state.baseUrl,
|
|
241
278
|
userType: "worker",
|
|
242
279
|
};
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
},
|
|
263
|
-
});
|
|
264
|
-
console.log(`${sym.check} Profile saved\n`);
|
|
265
|
-
}
|
|
266
|
-
catch (err) {
|
|
267
|
-
console.log(`${sym.warning} ${c.warning("Could not save profile details — you can update later with 'jobarbiter profile create'")}\n`);
|
|
268
|
-
}
|
|
269
|
-
// Step 3: Install Coding Agent Observers
|
|
270
|
-
await runObserverStep(prompt, state, 3, 6);
|
|
271
|
-
// Step 4: Connect GitHub (optional)
|
|
272
|
-
console.log(`${sym.link} ${c.bold("Step 4/6 — Connect GitHub")} ${c.dim("(optional)")}\n`);
|
|
273
|
-
console.log(`Connecting your GitHub lets us analyze your AI-assisted work patterns.`);
|
|
274
|
-
console.log(`This significantly boosts your proficiency score.\n`);
|
|
275
|
-
const githubUsername = await prompt.question(`GitHub username ${c.dim("(press Enter to skip)")}: `);
|
|
276
|
-
if (githubUsername) {
|
|
277
|
-
console.log(c.dim("\nConnecting GitHub..."));
|
|
280
|
+
const saveProgress = (step) => {
|
|
281
|
+
saveConfig({ ...config, onboardingStep: step });
|
|
282
|
+
};
|
|
283
|
+
// Step 2: Auto-detect AI Tools
|
|
284
|
+
if (startStep <= 2) {
|
|
285
|
+
const detectedToolsResult = await runToolDetectionStep(prompt, config);
|
|
286
|
+
state.tools = detectedToolsResult.tools;
|
|
287
|
+
saveProgress(2);
|
|
288
|
+
}
|
|
289
|
+
// Step 3: Domains
|
|
290
|
+
if (startStep <= 3) {
|
|
291
|
+
console.log(`${sym.target} ${c.bold("Step 3/6 — Your Domains")}\n`);
|
|
292
|
+
console.log(`What domains do you work in? ${c.dim("(comma-separated)")}`);
|
|
293
|
+
console.log(c.dim("Examples: full-stack dev, data engineering, trading, content creation\n"));
|
|
294
|
+
const domainsInput = await prompt.question(`${sym.arrow} `);
|
|
295
|
+
const domains = domainsInput.split(",").map(s => s.trim()).filter(Boolean);
|
|
296
|
+
state.domains = domains;
|
|
297
|
+
// Create/update profile
|
|
298
|
+
console.log(c.dim("\nSaving profile..."));
|
|
278
299
|
try {
|
|
279
|
-
await api(config, "POST", "/v1/
|
|
280
|
-
|
|
281
|
-
|
|
300
|
+
await api(config, "POST", "/v1/profile", {
|
|
301
|
+
domains,
|
|
302
|
+
tools: {
|
|
303
|
+
primary: state.tools,
|
|
304
|
+
},
|
|
282
305
|
});
|
|
283
|
-
console.log(`${sym.check}
|
|
284
|
-
state.githubUsername = githubUsername;
|
|
306
|
+
console.log(`${sym.check} Profile saved\n`);
|
|
285
307
|
}
|
|
286
308
|
catch (err) {
|
|
287
|
-
console.log(`${sym.warning} ${c.warning("Could not
|
|
309
|
+
console.log(`${sym.warning} ${c.warning("Could not save profile details — you can update later with 'jobarbiter profile create'")}\n`);
|
|
288
310
|
}
|
|
311
|
+
saveProgress(3);
|
|
289
312
|
}
|
|
290
|
-
|
|
291
|
-
|
|
313
|
+
// Step 4: Connect GitHub (optional)
|
|
314
|
+
if (startStep <= 4) {
|
|
315
|
+
console.log(`${sym.link} ${c.bold("Step 4/6 — Connect GitHub")} ${c.dim("(optional)")}\n`);
|
|
316
|
+
console.log(`Connecting your GitHub lets us analyze your AI-assisted work patterns.`);
|
|
317
|
+
console.log(`This significantly boosts your proficiency score.\n`);
|
|
318
|
+
const githubUsername = await prompt.question(`GitHub username ${c.dim("(press Enter to skip)")}: `);
|
|
319
|
+
if (githubUsername) {
|
|
320
|
+
console.log(c.dim("\nConnecting GitHub..."));
|
|
321
|
+
try {
|
|
322
|
+
await api(config, "POST", "/v1/attestations/git/connect", {
|
|
323
|
+
provider: "github",
|
|
324
|
+
username: githubUsername,
|
|
325
|
+
});
|
|
326
|
+
console.log(`${sym.check} GitHub connected: ${c.highlight(githubUsername)}\n`);
|
|
327
|
+
state.githubUsername = githubUsername;
|
|
328
|
+
}
|
|
329
|
+
catch (err) {
|
|
330
|
+
console.log(`${sym.warning} ${c.warning("Could not connect GitHub — you can try later with 'jobarbiter git connect'")}\n`);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
console.log(`${c.dim("Skipped — you can connect later with 'jobarbiter git connect'")}\n`);
|
|
335
|
+
}
|
|
336
|
+
saveProgress(4);
|
|
292
337
|
}
|
|
293
338
|
// Step 5: Connect LinkedIn (optional)
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
339
|
+
if (startStep <= 5) {
|
|
340
|
+
console.log(`${sym.link} ${c.bold("Step 5/6 — Connect LinkedIn")} ${c.dim("(optional)")}\n`);
|
|
341
|
+
console.log(`Your LinkedIn profile strengthens identity verification.`);
|
|
342
|
+
console.log(c.dim("We never post on your behalf or access your connections.\n"));
|
|
343
|
+
const linkedinUrl = await prompt.question(`LinkedIn URL ${c.dim("(press Enter to skip)")}: `);
|
|
344
|
+
if (linkedinUrl) {
|
|
345
|
+
console.log(c.dim("\nSubmitting for verification..."));
|
|
346
|
+
try {
|
|
347
|
+
await api(config, "POST", "/v1/verification/linkedin", {
|
|
348
|
+
linkedinUrl: linkedinUrl.trim(),
|
|
349
|
+
});
|
|
350
|
+
console.log(`${sym.check} LinkedIn submitted for verification\n`);
|
|
351
|
+
}
|
|
352
|
+
catch (err) {
|
|
353
|
+
console.log(`${sym.warning} ${c.warning("Could not submit LinkedIn — you can try later with 'jobarbiter identity linkedin <url>'")}\n`);
|
|
354
|
+
}
|
|
305
355
|
}
|
|
306
|
-
|
|
307
|
-
console.log(`${
|
|
356
|
+
else {
|
|
357
|
+
console.log(`${c.dim("Skipped — you can connect later with 'jobarbiter identity linkedin <url>'")}\n`);
|
|
308
358
|
}
|
|
309
|
-
|
|
310
|
-
else {
|
|
311
|
-
console.log(`${c.dim("Skipped — you can connect later with 'jobarbiter identity linkedin <url>'")}\n`);
|
|
359
|
+
saveProgress(5);
|
|
312
360
|
}
|
|
313
361
|
// Step 6: Done!
|
|
362
|
+
saveConfig({ ...config, onboardingComplete: true, onboardingStep: 6 });
|
|
314
363
|
showWorkerCompletion(state);
|
|
315
364
|
}
|
|
316
|
-
// ──
|
|
317
|
-
async function
|
|
318
|
-
console.log(`🔍 ${c.bold(
|
|
319
|
-
console.log(c.dim("Scanning
|
|
320
|
-
const
|
|
321
|
-
const
|
|
322
|
-
const
|
|
323
|
-
//
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
365
|
+
// ── Tool Detection Step ────────────────────────────────────────────────
|
|
366
|
+
async function runToolDetectionStep(prompt, config) {
|
|
367
|
+
console.log(`🔍 ${c.bold("Step 2/6 — Detecting AI Tools")}\n`);
|
|
368
|
+
console.log(c.dim(" Scanning your machine...\n"));
|
|
369
|
+
const allTools = detectAllTools();
|
|
370
|
+
const installed = allTools.filter((t) => t.installed);
|
|
371
|
+
const notInstalled = allTools.filter((t) => !t.installed && t.category === "coding-agent");
|
|
372
|
+
// Group by category
|
|
373
|
+
const codingAgents = installed.filter((t) => t.category === "coding-agent");
|
|
374
|
+
const chatTools = installed.filter((t) => t.category === "chat");
|
|
375
|
+
const orchestration = installed.filter((t) => t.category === "orchestration");
|
|
376
|
+
const apiProviders = installed.filter((t) => t.category === "api-provider");
|
|
377
|
+
// Display found tools
|
|
378
|
+
if (installed.length === 0) {
|
|
379
|
+
console.log(` ${c.dim("No AI tools detected on this system.")}\n`);
|
|
380
|
+
console.log(c.dim(" You can add tools later with 'jobarbiter observe install'.\n"));
|
|
381
|
+
return { tools: [] };
|
|
382
|
+
}
|
|
383
|
+
console.log(` ${c.bold("Found:")}`);
|
|
384
|
+
// Show coding agents with observer status
|
|
385
|
+
for (const tool of codingAgents) {
|
|
386
|
+
const display = formatToolDisplay(tool);
|
|
387
|
+
if (tool.observerAvailable) {
|
|
388
|
+
if (tool.observerActive) {
|
|
389
|
+
console.log(` ${sym.check} ${display} ${c.dim("(observer active)")}`);
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
console.log(` ${sym.check} ${display} ${c.success("(observer available)")}`);
|
|
393
|
+
}
|
|
333
394
|
}
|
|
334
395
|
else {
|
|
335
|
-
console.log(` ${c.
|
|
396
|
+
console.log(` ${sym.check} ${display} ${c.dim("(detected)")}`);
|
|
336
397
|
}
|
|
337
398
|
}
|
|
338
|
-
|
|
339
|
-
|
|
399
|
+
// Show other tools
|
|
400
|
+
for (const tool of chatTools) {
|
|
401
|
+
console.log(` ${sym.check} ${formatToolDisplay(tool)} ${c.dim("(detected)")}`);
|
|
340
402
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
if (needsInstall.length === 0) {
|
|
344
|
-
console.log(`\n ${c.dim("All detected agents already have observers installed.")}\n`);
|
|
345
|
-
return;
|
|
403
|
+
for (const tool of orchestration) {
|
|
404
|
+
console.log(` ${sym.check} ${formatToolDisplay(tool)} ${c.dim("(detected)")}`);
|
|
346
405
|
}
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
console.log(` only aggregate scores (tool usage, session counts, token volume).\n`);
|
|
350
|
-
console.log(c.dim(` Data stored locally: ~/.config/jobarbiter/observer/observations.json`));
|
|
351
|
-
console.log(c.dim(` Review anytime: jobarbiter observe status\n`));
|
|
352
|
-
const installAll = await prompt.confirm(` Install observers for all ${needsInstall.length} detected agent${needsInstall.length > 1 ? "s" : ""}?`);
|
|
353
|
-
let toInstall;
|
|
354
|
-
if (installAll) {
|
|
355
|
-
toInstall = needsInstall.map((a) => a.id);
|
|
406
|
+
for (const tool of apiProviders) {
|
|
407
|
+
console.log(` ${sym.check} ${tool.name} ${c.dim("configured")}`);
|
|
356
408
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
console.log(`\n
|
|
360
|
-
const
|
|
361
|
-
|
|
362
|
-
selections[agent.id] = await prompt.confirm(` ${agent.name}?`, true);
|
|
409
|
+
// Show not-detected coding agents
|
|
410
|
+
if (notInstalled.length > 0) {
|
|
411
|
+
console.log(`\n ${c.dim("Not detected (install to track):")}`);
|
|
412
|
+
for (const tool of notInstalled.slice(0, 5)) {
|
|
413
|
+
console.log(` ${c.dim("⬚")} ${tool.name}`);
|
|
363
414
|
}
|
|
364
|
-
|
|
365
|
-
.
|
|
366
|
-
.map(([k]) => k);
|
|
367
|
-
if (toInstall.length === 0) {
|
|
368
|
-
console.log(`\n ${c.dim("No observers installed. You can add them later with 'jobarbiter observe install'.")}\n`);
|
|
369
|
-
return;
|
|
415
|
+
if (notInstalled.length > 5) {
|
|
416
|
+
console.log(` ${c.dim(`... and ${notInstalled.length - 5} more`)}`);
|
|
370
417
|
}
|
|
371
418
|
}
|
|
372
|
-
//
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
console.log(`
|
|
419
|
+
// Collect tool names for profile
|
|
420
|
+
const toolNames = installed.map((t) => t.name);
|
|
421
|
+
// Observer installation for coding agents
|
|
422
|
+
const needsObserver = codingAgents.filter((t) => t.observerAvailable && !t.observerActive);
|
|
423
|
+
if (needsObserver.length > 0) {
|
|
424
|
+
console.log(`\n ${c.bold("Observers")}`);
|
|
425
|
+
console.log(` JobArbiter observes your coding sessions to build your`);
|
|
426
|
+
console.log(` proficiency profile. ${c.bold("No code or prompts leave your machine")} —`);
|
|
427
|
+
console.log(` only aggregate scores (tool usage, session counts, token volume).\n`);
|
|
428
|
+
console.log(c.dim(` Data stored locally: ~/.config/jobarbiter/observer/observations.json`));
|
|
429
|
+
console.log(c.dim(` Review anytime: jobarbiter observe status\n`));
|
|
430
|
+
const observerNames = needsObserver.map((t) => t.name).join(", ");
|
|
431
|
+
const installAll = await prompt.confirm(` Install observers for detected tools? (${observerNames})`);
|
|
432
|
+
if (installAll) {
|
|
433
|
+
const toInstall = needsObserver.map((t) => t.id);
|
|
434
|
+
console.log(c.dim("\n Installing observers..."));
|
|
435
|
+
const result = installObservers(toInstall);
|
|
436
|
+
for (const name of result.installed) {
|
|
437
|
+
console.log(` ${sym.check} ${name}`);
|
|
438
|
+
}
|
|
439
|
+
for (const name of result.skipped) {
|
|
440
|
+
console.log(` ${c.dim("—")} ${name} ${c.dim("(already installed)")}`);
|
|
441
|
+
}
|
|
442
|
+
for (const { agent, error: errMsg } of result.errors) {
|
|
443
|
+
console.log(` ${sym.cross} ${agent}: ${c.error(errMsg)}`);
|
|
444
|
+
}
|
|
445
|
+
if (result.installed.length > 0) {
|
|
446
|
+
console.log(`\n ${sym.check} ${c.success(`${result.installed.length} observer${result.installed.length > 1 ? "s" : ""} installed!`)}`);
|
|
447
|
+
console.log(c.dim(` Your proficiency profile will start building automatically.\n`));
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
else {
|
|
451
|
+
console.log(c.dim("\n Skipped — you can install observers later with 'jobarbiter observe install'.\n"));
|
|
452
|
+
}
|
|
380
453
|
}
|
|
381
|
-
|
|
382
|
-
|
|
454
|
+
else if (codingAgents.length > 0) {
|
|
455
|
+
const hasActiveObservers = codingAgents.some((t) => t.observerActive);
|
|
456
|
+
if (hasActiveObservers) {
|
|
457
|
+
console.log(`\n ${c.dim("All detected agents already have observers installed.")}\n`);
|
|
458
|
+
}
|
|
459
|
+
else {
|
|
460
|
+
console.log();
|
|
461
|
+
}
|
|
383
462
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
463
|
+
// "Did we miss anything?" prompt
|
|
464
|
+
console.log(` ${c.dim("Did we miss anything?")}`);
|
|
465
|
+
const additionalTools = await prompt.question(` Other AI tools you use ${c.dim("(comma-separated, or press Enter)")}: `);
|
|
466
|
+
if (additionalTools.trim()) {
|
|
467
|
+
const additional = additionalTools.split(",").map((s) => s.trim()).filter(Boolean);
|
|
468
|
+
toolNames.push(...additional);
|
|
469
|
+
console.log(` ${sym.check} Added: ${additional.join(", ")}\n`);
|
|
387
470
|
}
|
|
388
471
|
else {
|
|
389
472
|
console.log();
|
|
390
473
|
}
|
|
474
|
+
return { tools: toolNames };
|
|
391
475
|
}
|
|
392
476
|
function showWorkerCompletion(state) {
|
|
393
477
|
console.log(`${sym.done} ${c.bold("Step 6/6 — You're In!")}\n`);
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { api, apiUnauthenticated, ApiError } from "./lib/api.js";
|
|
|
6
6
|
import { output, outputList, success, error, setJsonMode } from "./lib/output.js";
|
|
7
7
|
import { runOnboardWizard } from "./lib/onboard.js";
|
|
8
8
|
import { detectAgents, installObservers, removeObservers, getObservationStatus } from "./lib/observe.js";
|
|
9
|
+
import { getObservableTools, formatToolDisplay } from "./lib/detect-tools.js";
|
|
9
10
|
|
|
10
11
|
const program = new Command();
|
|
11
12
|
|
package/src/lib/config.ts
CHANGED
|
@@ -6,6 +6,8 @@ export interface Config {
|
|
|
6
6
|
apiKey: string;
|
|
7
7
|
baseUrl: string;
|
|
8
8
|
userType: "worker" | "employer" | "seeker" | "poster";
|
|
9
|
+
onboardingComplete?: boolean;
|
|
10
|
+
onboardingStep?: number; // last completed step (1-6)
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
const CONFIG_DIR = join(homedir(), ".config", "jobarbiter");
|