ledgit-cli 0.4.2 → 0.4.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/index.js +300 -156
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -48242,16 +48242,6 @@ async function getValidAccessToken(cwd = process.cwd()) {
|
|
|
48242
48242
|
return null;
|
|
48243
48243
|
}
|
|
48244
48244
|
}
|
|
48245
|
-
function deleteAuth0Token(cwd = process.cwd()) {
|
|
48246
|
-
const localPath = getLocalTokenPath(cwd);
|
|
48247
|
-
const globalPath = getGlobalTokenPath();
|
|
48248
|
-
if (fs10.existsSync(localPath)) {
|
|
48249
|
-
fs10.unlinkSync(localPath);
|
|
48250
|
-
}
|
|
48251
|
-
if (fs10.existsSync(globalPath)) {
|
|
48252
|
-
fs10.unlinkSync(globalPath);
|
|
48253
|
-
}
|
|
48254
|
-
}
|
|
48255
48245
|
|
|
48256
48246
|
// src/lib/env.ts
|
|
48257
48247
|
async function loadConfig(cwd = process.cwd()) {
|
|
@@ -48287,7 +48277,10 @@ async function loadConfig(cwd = process.cwd()) {
|
|
|
48287
48277
|
if (!companyId) {
|
|
48288
48278
|
throw new Error("BOKIO_COMPANY_ID environment variable not set");
|
|
48289
48279
|
}
|
|
48290
|
-
|
|
48280
|
+
let inboxProvider = process.env.INBOX_PROVIDER;
|
|
48281
|
+
if (!inboxProvider && process.env.LEDGIT_API_TOKEN) {
|
|
48282
|
+
inboxProvider = "ledgit";
|
|
48283
|
+
}
|
|
48291
48284
|
const result = {
|
|
48292
48285
|
provider: "bokio",
|
|
48293
48286
|
bokio: { token, companyId }
|
|
@@ -48296,6 +48289,10 @@ async function loadConfig(cwd = process.cwd()) {
|
|
|
48296
48289
|
result.inboxProvider = "ledgit";
|
|
48297
48290
|
result.ledgit = {
|
|
48298
48291
|
getAccessToken: async () => {
|
|
48292
|
+
const apiToken = process.env.LEDGIT_API_TOKEN;
|
|
48293
|
+
if (apiToken) {
|
|
48294
|
+
return apiToken;
|
|
48295
|
+
}
|
|
48299
48296
|
const accessToken = await getValidAccessToken(cwd);
|
|
48300
48297
|
if (!accessToken) {
|
|
48301
48298
|
throw new Error("Ledgit authentication required for inbox. Run 'ledgit login' to authenticate.");
|
|
@@ -48310,6 +48307,10 @@ async function loadConfig(cwd = process.cwd()) {
|
|
|
48310
48307
|
provider: "ledgit",
|
|
48311
48308
|
ledgit: {
|
|
48312
48309
|
getAccessToken: async () => {
|
|
48310
|
+
const apiToken = process.env.LEDGIT_API_TOKEN;
|
|
48311
|
+
if (apiToken) {
|
|
48312
|
+
return apiToken;
|
|
48313
|
+
}
|
|
48313
48314
|
const token = await getValidAccessToken(cwd);
|
|
48314
48315
|
if (!token) {
|
|
48315
48316
|
throw new Error("Ledgit authentication required. Run 'ledgit login' to authenticate.");
|
|
@@ -56393,80 +56394,131 @@ async function loginCommand(options) {
|
|
|
56393
56394
|
}
|
|
56394
56395
|
|
|
56395
56396
|
// src/commands/token.ts
|
|
56396
|
-
|
|
56397
|
+
var API_BASE_URL = process.env.LEDGIT_API_URL || "https://api.ledgit.se";
|
|
56398
|
+
async function tokenCommand(action = "list", options = {}) {
|
|
56397
56399
|
const cwd = process.cwd();
|
|
56400
|
+
const accessToken = await getValidAccessToken(cwd);
|
|
56401
|
+
if (!accessToken) {
|
|
56402
|
+
console.error(`
|
|
56403
|
+
Not logged in. Run 'ledgit login' first.
|
|
56404
|
+
`);
|
|
56405
|
+
process.exit(1);
|
|
56406
|
+
}
|
|
56398
56407
|
switch (action) {
|
|
56399
|
-
case "
|
|
56400
|
-
const
|
|
56401
|
-
|
|
56402
|
-
|
|
56403
|
-
|
|
56404
|
-
|
|
56408
|
+
case "list": {
|
|
56409
|
+
const response = await fetch(`${API_BASE_URL}/api/tokens`, {
|
|
56410
|
+
headers: {
|
|
56411
|
+
Authorization: `Bearer ${accessToken}`
|
|
56412
|
+
}
|
|
56413
|
+
});
|
|
56414
|
+
if (!response.ok) {
|
|
56415
|
+
const error = await response.json().catch(() => ({}));
|
|
56416
|
+
console.error(`
|
|
56417
|
+
Failed to fetch tokens: ${error.error || response.statusText} (${response.status})
|
|
56405
56418
|
`);
|
|
56406
56419
|
process.exit(1);
|
|
56407
56420
|
}
|
|
56408
|
-
const
|
|
56409
|
-
const
|
|
56410
|
-
|
|
56411
|
-
|
|
56412
|
-
|
|
56413
|
-
|
|
56414
|
-
console.log(` Has Refresh Token: ${token.refresh_token ? "Yes" : "No"}`);
|
|
56415
|
-
console.log("");
|
|
56416
|
-
if (expired) {
|
|
56417
|
-
console.log(` Token is expired. Run 'ledgit token refresh' or 'ledgit login' to get a new token.
|
|
56421
|
+
const result = await response.json();
|
|
56422
|
+
const tokens = result.data;
|
|
56423
|
+
if (tokens.length === 0) {
|
|
56424
|
+
console.log(`
|
|
56425
|
+
No API tokens found.`);
|
|
56426
|
+
console.log(` Create one with: ledgit token create
|
|
56418
56427
|
`);
|
|
56428
|
+
return;
|
|
56419
56429
|
}
|
|
56420
|
-
|
|
56421
|
-
|
|
56422
|
-
|
|
56423
|
-
const
|
|
56424
|
-
|
|
56425
|
-
console.
|
|
56426
|
-
|
|
56430
|
+
console.log(`
|
|
56431
|
+
API Tokens:
|
|
56432
|
+
`);
|
|
56433
|
+
for (const token of tokens) {
|
|
56434
|
+
const lastUsed = token.lastUsedAt ? new Date(token.lastUsedAt).toLocaleDateString() : "Never";
|
|
56435
|
+
console.log(` ${token.name}`);
|
|
56436
|
+
console.log(` Token: ${token.tokenPrefix}...`);
|
|
56437
|
+
console.log(` Scopes: ${token.scopes.join(", ")}`);
|
|
56438
|
+
console.log(` Last used: ${lastUsed}`);
|
|
56439
|
+
console.log("");
|
|
56427
56440
|
}
|
|
56428
|
-
process.stdout.write(accessToken);
|
|
56429
56441
|
break;
|
|
56430
56442
|
}
|
|
56431
|
-
case "
|
|
56432
|
-
const
|
|
56433
|
-
|
|
56434
|
-
|
|
56435
|
-
|
|
56436
|
-
|
|
56443
|
+
case "create": {
|
|
56444
|
+
const name = await dist_default4({
|
|
56445
|
+
message: "Token name:",
|
|
56446
|
+
default: "GitHub Actions"
|
|
56447
|
+
});
|
|
56448
|
+
const scopes = ["read", "write"];
|
|
56449
|
+
console.log(`
|
|
56450
|
+
Creating API token...`);
|
|
56451
|
+
const response = await fetch(`${API_BASE_URL}/api/tokens`, {
|
|
56452
|
+
method: "POST",
|
|
56453
|
+
headers: {
|
|
56454
|
+
Authorization: `Bearer ${accessToken}`,
|
|
56455
|
+
"Content-Type": "application/json"
|
|
56456
|
+
},
|
|
56457
|
+
body: JSON.stringify({ name, scopes })
|
|
56458
|
+
});
|
|
56459
|
+
if (!response.ok) {
|
|
56460
|
+
const error = await response.json().catch(() => ({}));
|
|
56461
|
+
console.error(`
|
|
56462
|
+
Failed to create token: ${error.error || response.statusText}
|
|
56437
56463
|
`);
|
|
56438
56464
|
process.exit(1);
|
|
56439
56465
|
}
|
|
56440
|
-
|
|
56441
|
-
|
|
56442
|
-
|
|
56443
|
-
console.log(` Run 'ledgit login' to get a new token.
|
|
56466
|
+
const result = await response.json();
|
|
56467
|
+
console.log(`
|
|
56468
|
+
✓ API token created successfully!
|
|
56444
56469
|
`);
|
|
56445
|
-
|
|
56446
|
-
|
|
56447
|
-
|
|
56448
|
-
const accessToken = await getValidAccessToken(cwd);
|
|
56449
|
-
if (accessToken) {
|
|
56450
|
-
console.log(` Token refreshed successfully!
|
|
56470
|
+
console.log(" Token (copy now - it won't be shown again):");
|
|
56471
|
+
console.log(`
|
|
56472
|
+
${result.data.token}
|
|
56451
56473
|
`);
|
|
56452
|
-
|
|
56453
|
-
|
|
56474
|
+
console.log(" To use in GitHub Actions, add as a secret:");
|
|
56475
|
+
console.log(` gh secret set LEDGIT_API_TOKEN
|
|
56454
56476
|
`);
|
|
56455
|
-
process.exit(1);
|
|
56456
|
-
}
|
|
56457
56477
|
break;
|
|
56458
56478
|
}
|
|
56459
56479
|
case "revoke": {
|
|
56460
|
-
const
|
|
56461
|
-
|
|
56480
|
+
const listResponse = await fetch(`${API_BASE_URL}/api/tokens`, {
|
|
56481
|
+
headers: {
|
|
56482
|
+
Authorization: `Bearer ${accessToken}`
|
|
56483
|
+
}
|
|
56484
|
+
});
|
|
56485
|
+
if (!listResponse.ok) {
|
|
56486
|
+
const error = await listResponse.json().catch(() => ({}));
|
|
56487
|
+
console.error(`
|
|
56488
|
+
Failed to fetch tokens: ${error.error || listResponse.statusText} (${listResponse.status})
|
|
56489
|
+
`);
|
|
56490
|
+
process.exit(1);
|
|
56491
|
+
}
|
|
56492
|
+
const listResult = await listResponse.json();
|
|
56493
|
+
const tokens = listResult.data;
|
|
56494
|
+
if (tokens.length === 0) {
|
|
56462
56495
|
console.log(`
|
|
56463
|
-
No
|
|
56496
|
+
No API tokens to revoke.
|
|
56464
56497
|
`);
|
|
56465
56498
|
return;
|
|
56466
56499
|
}
|
|
56467
|
-
|
|
56500
|
+
const tokenId = await dist_default8({
|
|
56501
|
+
message: "Select token to revoke:",
|
|
56502
|
+
choices: tokens.map((t) => ({
|
|
56503
|
+
value: t.id,
|
|
56504
|
+
name: `${t.name} (${t.tokenPrefix}...)`
|
|
56505
|
+
}))
|
|
56506
|
+
});
|
|
56507
|
+
const response = await fetch(`${API_BASE_URL}/api/tokens/${tokenId}`, {
|
|
56508
|
+
method: "DELETE",
|
|
56509
|
+
headers: {
|
|
56510
|
+
Authorization: `Bearer ${accessToken}`
|
|
56511
|
+
}
|
|
56512
|
+
});
|
|
56513
|
+
if (!response.ok) {
|
|
56514
|
+
const error = await response.json().catch(() => ({}));
|
|
56515
|
+
console.error(`
|
|
56516
|
+
Failed to revoke token: ${error.error || response.statusText} (${response.status})
|
|
56517
|
+
`);
|
|
56518
|
+
process.exit(1);
|
|
56519
|
+
}
|
|
56468
56520
|
console.log(`
|
|
56469
|
-
|
|
56521
|
+
✓ Token revoked.
|
|
56470
56522
|
`);
|
|
56471
56523
|
break;
|
|
56472
56524
|
}
|
|
@@ -56474,10 +56526,9 @@ async function tokenCommand(action = "show", options = {}) {
|
|
|
56474
56526
|
console.error(`Unknown action: ${action}`);
|
|
56475
56527
|
console.log(`
|
|
56476
56528
|
Usage:`);
|
|
56477
|
-
console.log(" ledgit token
|
|
56478
|
-
console.log(" ledgit token
|
|
56479
|
-
console.log(" ledgit token
|
|
56480
|
-
console.log(" ledgit token revoke - Revoke/delete stored token");
|
|
56529
|
+
console.log(" ledgit token list - List all API tokens");
|
|
56530
|
+
console.log(" ledgit token create - Create a new API token");
|
|
56531
|
+
console.log(" ledgit token revoke - Revoke an API token");
|
|
56481
56532
|
process.exit(1);
|
|
56482
56533
|
}
|
|
56483
56534
|
}
|
|
@@ -56516,6 +56567,7 @@ jobs:
|
|
|
56516
56567
|
- name: Sync inbox
|
|
56517
56568
|
run: npx ledgit-cli sync-inbox
|
|
56518
56569
|
env:
|
|
56570
|
+
LEDGIT_API_TOKEN: \${{ secrets.LEDGIT_API_TOKEN }}
|
|
56519
56571
|
BOKIO_TOKEN: \${{ secrets.BOKIO_TOKEN }}
|
|
56520
56572
|
BOKIO_COMPANY_ID: \${{ secrets.BOKIO_COMPANY_ID }}
|
|
56521
56573
|
|
|
@@ -56591,40 +56643,6 @@ jobs:
|
|
|
56591
56643
|
--verbose \\
|
|
56592
56644
|
--output-format stream-json \\
|
|
56593
56645
|
2>&1 | tee /tmp/claude-output.json
|
|
56594
|
-
|
|
56595
|
-
- name: Write job summary
|
|
56596
|
-
if: always() && steps.check.outputs.has_new == 'true'
|
|
56597
|
-
run: |
|
|
56598
|
-
echo "## \uD83E\uDD16 Claude Bookkeeping Report" >> $GITHUB_STEP_SUMMARY
|
|
56599
|
-
echo "" >> $GITHUB_STEP_SUMMARY
|
|
56600
|
-
|
|
56601
|
-
# Show model from init
|
|
56602
|
-
jq -r 'select(.type == "system" and .subtype == "init") | "**Model:** \\(.model // "claude")"' /tmp/claude-output.json >> $GITHUB_STEP_SUMMARY 2>/dev/null || true
|
|
56603
|
-
echo "" >> $GITHUB_STEP_SUMMARY
|
|
56604
|
-
|
|
56605
|
-
# Count tool uses
|
|
56606
|
-
TOOL_COUNT=$(jq -s '[.[] | select(.type == "tool_use")] | length' /tmp/claude-output.json 2>/dev/null || echo "0")
|
|
56607
|
-
echo "**Tool calls:** $TOOL_COUNT" >> $GITHUB_STEP_SUMMARY
|
|
56608
|
-
echo "" >> $GITHUB_STEP_SUMMARY
|
|
56609
|
-
|
|
56610
|
-
# List unique tools used
|
|
56611
|
-
echo "### Tools Used" >> $GITHUB_STEP_SUMMARY
|
|
56612
|
-
jq -r 'select(.type == "tool_use") | .name' /tmp/claude-output.json 2>/dev/null | sort | uniq -c | while read count name; do
|
|
56613
|
-
echo "- $name ($count calls)" >> $GITHUB_STEP_SUMMARY
|
|
56614
|
-
done
|
|
56615
|
-
echo "" >> $GITHUB_STEP_SUMMARY
|
|
56616
|
-
|
|
56617
|
-
# Final result
|
|
56618
|
-
echo "### Result" >> $GITHUB_STEP_SUMMARY
|
|
56619
|
-
jq -r 'select(.type == "result") | "**Status:** \\(.subtype // "completed")\\n**Duration:** \\((.duration_ms // 0) / 1000 | floor)s\\n**Turns:** \\(.num_turns // "N/A")\\n**Cost:** $\\(.total_cost_usd // 0 | tostring | .[0:6])"' /tmp/claude-output.json >> $GITHUB_STEP_SUMMARY 2>/dev/null || true
|
|
56620
|
-
|
|
56621
|
-
- name: Upload Claude execution log
|
|
56622
|
-
if: always() && steps.check.outputs.has_new == 'true'
|
|
56623
|
-
uses: actions/upload-artifact@v4
|
|
56624
|
-
with:
|
|
56625
|
-
name: claude-execution-log
|
|
56626
|
-
path: /tmp/claude-output.json
|
|
56627
|
-
retention-days: 7
|
|
56628
56646
|
`;
|
|
56629
56647
|
var CLAUDE_BOOKKEEPING_WORKFLOW = `name: Claude Bookkeeping
|
|
56630
56648
|
on:
|
|
@@ -56719,40 +56737,6 @@ jobs:
|
|
|
56719
56737
|
--verbose \\
|
|
56720
56738
|
--output-format stream-json \\
|
|
56721
56739
|
2>&1 | tee /tmp/claude-output.json
|
|
56722
|
-
|
|
56723
|
-
- name: Write job summary
|
|
56724
|
-
if: always()
|
|
56725
|
-
run: |
|
|
56726
|
-
echo "## \uD83E\uDD16 Claude Response Report" >> $GITHUB_STEP_SUMMARY
|
|
56727
|
-
echo "" >> $GITHUB_STEP_SUMMARY
|
|
56728
|
-
|
|
56729
|
-
# Show model from init
|
|
56730
|
-
jq -r 'select(.type == "system" and .subtype == "init") | "**Model:** \\(.model // "claude")"' /tmp/claude-output.json >> $GITHUB_STEP_SUMMARY 2>/dev/null || true
|
|
56731
|
-
echo "" >> $GITHUB_STEP_SUMMARY
|
|
56732
|
-
|
|
56733
|
-
# Count tool uses
|
|
56734
|
-
TOOL_COUNT=$(jq -s '[.[] | select(.type == "tool_use")] | length' /tmp/claude-output.json 2>/dev/null || echo "0")
|
|
56735
|
-
echo "**Tool calls:** $TOOL_COUNT" >> $GITHUB_STEP_SUMMARY
|
|
56736
|
-
echo "" >> $GITHUB_STEP_SUMMARY
|
|
56737
|
-
|
|
56738
|
-
# List unique tools used
|
|
56739
|
-
echo "### Tools Used" >> $GITHUB_STEP_SUMMARY
|
|
56740
|
-
jq -r 'select(.type == "tool_use") | .name' /tmp/claude-output.json 2>/dev/null | sort | uniq -c | while read count name; do
|
|
56741
|
-
echo "- $name ($count calls)" >> $GITHUB_STEP_SUMMARY
|
|
56742
|
-
done
|
|
56743
|
-
echo "" >> $GITHUB_STEP_SUMMARY
|
|
56744
|
-
|
|
56745
|
-
# Final result
|
|
56746
|
-
echo "### Result" >> $GITHUB_STEP_SUMMARY
|
|
56747
|
-
jq -r 'select(.type == "result") | "**Status:** \\(.subtype // "completed")\\n**Duration:** \\((.duration_ms // 0) / 1000 | floor)s\\n**Turns:** \\(.num_turns // "N/A")\\n**Cost:** $\\(.total_cost_usd // 0 | tostring | .[0:6])"' /tmp/claude-output.json >> $GITHUB_STEP_SUMMARY 2>/dev/null || true
|
|
56748
|
-
|
|
56749
|
-
- name: Upload Claude execution log
|
|
56750
|
-
if: always()
|
|
56751
|
-
uses: actions/upload-artifact@v4
|
|
56752
|
-
with:
|
|
56753
|
-
name: claude-execution-log-pr-\${{ github.event.issue.number }}
|
|
56754
|
-
path: /tmp/claude-output.json
|
|
56755
|
-
retention-days: 7
|
|
56756
56740
|
`;
|
|
56757
56741
|
var SYNC_JOURNAL_WORKFLOW = `name: Sync Journal
|
|
56758
56742
|
on:
|
|
@@ -56778,6 +56762,7 @@ jobs:
|
|
|
56778
56762
|
- name: Sync to Bokio
|
|
56779
56763
|
run: npx ledgit-cli sync-journal
|
|
56780
56764
|
env:
|
|
56765
|
+
LEDGIT_API_TOKEN: \${{ secrets.LEDGIT_API_TOKEN }}
|
|
56781
56766
|
BOKIO_TOKEN: \${{ secrets.BOKIO_TOKEN }}
|
|
56782
56767
|
BOKIO_COMPANY_ID: \${{ secrets.BOKIO_COMPANY_ID }}
|
|
56783
56768
|
`;
|
|
@@ -57216,6 +57201,23 @@ async function authenticateClaude(options = {}) {
|
|
|
57216
57201
|
|
|
57217
57202
|
// src/lib/github.ts
|
|
57218
57203
|
var execAsync3 = promisify7(exec7);
|
|
57204
|
+
async function saveToEnv(cwd, key, value) {
|
|
57205
|
+
const envPath = path15.join(cwd, ".env");
|
|
57206
|
+
let content = "";
|
|
57207
|
+
try {
|
|
57208
|
+
content = await fs19.readFile(envPath, "utf-8");
|
|
57209
|
+
} catch {
|
|
57210
|
+
}
|
|
57211
|
+
const regex2 = new RegExp(`^${key}=.*$`, "m");
|
|
57212
|
+
if (regex2.test(content)) {
|
|
57213
|
+
content = content.replace(regex2, `${key}=${value}`);
|
|
57214
|
+
} else {
|
|
57215
|
+
content = content.trimEnd() + `
|
|
57216
|
+
${key}=${value}
|
|
57217
|
+
`;
|
|
57218
|
+
}
|
|
57219
|
+
await fs19.writeFile(envPath, content);
|
|
57220
|
+
}
|
|
57219
57221
|
async function checkGhInstalled() {
|
|
57220
57222
|
try {
|
|
57221
57223
|
await execAsync3("which gh");
|
|
@@ -57241,6 +57243,22 @@ async function checkGhWorkflowScope() {
|
|
|
57241
57243
|
return false;
|
|
57242
57244
|
}
|
|
57243
57245
|
}
|
|
57246
|
+
async function checkRepoAccess() {
|
|
57247
|
+
try {
|
|
57248
|
+
await execAsync3("gh repo view --json name");
|
|
57249
|
+
return true;
|
|
57250
|
+
} catch {
|
|
57251
|
+
return false;
|
|
57252
|
+
}
|
|
57253
|
+
}
|
|
57254
|
+
async function checkRepoSecretsAccess() {
|
|
57255
|
+
try {
|
|
57256
|
+
await execAsync3("gh api repos/{owner}/{repo}/actions/secrets/public-key");
|
|
57257
|
+
return true;
|
|
57258
|
+
} catch {
|
|
57259
|
+
return false;
|
|
57260
|
+
}
|
|
57261
|
+
}
|
|
57244
57262
|
async function hasGitRemote(cwd) {
|
|
57245
57263
|
try {
|
|
57246
57264
|
const cmd = cwd ? `git -C "${cwd}" remote -v` : "git remote -v";
|
|
@@ -57350,6 +57368,7 @@ needed to manage GitHub Actions and secrets.
|
|
|
57350
57368
|
To fix this, run:
|
|
57351
57369
|
gh auth refresh -h github.com -s repo,workflow`);
|
|
57352
57370
|
}
|
|
57371
|
+
const hasSecretsAccess = await checkRepoSecretsAccess();
|
|
57353
57372
|
let config3;
|
|
57354
57373
|
try {
|
|
57355
57374
|
config3 = await loadConfig(cwd);
|
|
@@ -57385,6 +57404,17 @@ Fortnox support requires OAuth token handling in CI, coming soon.`);
|
|
|
57385
57404
|
}
|
|
57386
57405
|
const secretName = authMethod === "api_key" ? "ANTHROPIC_API_KEY" : "CLAUDE_CODE_OAUTH_TOKEN";
|
|
57387
57406
|
let claudeToken = options.claudeToken;
|
|
57407
|
+
if (!claudeToken && authMethod === "oauth") {
|
|
57408
|
+
claudeToken = process.env.CLAUDE_CODE_OAUTH_TOKEN;
|
|
57409
|
+
if (claudeToken) {
|
|
57410
|
+
console.log(" Using existing CLAUDE_CODE_OAUTH_TOKEN from .env");
|
|
57411
|
+
}
|
|
57412
|
+
} else if (!claudeToken && authMethod === "api_key") {
|
|
57413
|
+
claudeToken = process.env.ANTHROPIC_API_KEY;
|
|
57414
|
+
if (claudeToken) {
|
|
57415
|
+
console.log(" Using existing ANTHROPIC_API_KEY from .env");
|
|
57416
|
+
}
|
|
57417
|
+
}
|
|
57388
57418
|
if (!claudeToken) {
|
|
57389
57419
|
if (authMethod === "api_key") {
|
|
57390
57420
|
claudeToken = await dist_default6({
|
|
@@ -57406,6 +57436,8 @@ Starting Claude OAuth authentication...`);
|
|
|
57406
57436
|
});
|
|
57407
57437
|
spinner.succeed("Claude authentication successful!");
|
|
57408
57438
|
claudeToken = result.token;
|
|
57439
|
+
await saveToEnv(cwd, "CLAUDE_CODE_OAUTH_TOKEN", claudeToken);
|
|
57440
|
+
console.log(" Saved token to .env");
|
|
57409
57441
|
} catch (error) {
|
|
57410
57442
|
spinner.fail("Claude authentication failed");
|
|
57411
57443
|
throw error;
|
|
@@ -57415,21 +57447,52 @@ Starting Claude OAuth authentication...`);
|
|
|
57415
57447
|
if (!claudeToken) {
|
|
57416
57448
|
throw new Error("Token is required.");
|
|
57417
57449
|
}
|
|
57418
|
-
|
|
57450
|
+
if (hasSecretsAccess) {
|
|
57451
|
+
console.log(`
|
|
57419
57452
|
Setting up GitHub secrets...`);
|
|
57420
|
-
|
|
57421
|
-
|
|
57422
|
-
|
|
57423
|
-
|
|
57424
|
-
|
|
57425
|
-
|
|
57426
|
-
|
|
57427
|
-
|
|
57428
|
-
|
|
57429
|
-
|
|
57430
|
-
|
|
57453
|
+
await setGhSecret(secretName, claudeToken);
|
|
57454
|
+
console.log(` Set ${secretName}`);
|
|
57455
|
+
await setGhSecret("BOKIO_TOKEN", config3.bokio.token);
|
|
57456
|
+
console.log(" Set BOKIO_TOKEN");
|
|
57457
|
+
await setGhSecret("BOKIO_COMPANY_ID", config3.bokio.companyId);
|
|
57458
|
+
console.log(" Set BOKIO_COMPANY_ID");
|
|
57459
|
+
if (options.ledgitApiToken) {
|
|
57460
|
+
await setGhSecret("LEDGIT_API_TOKEN", options.ledgitApiToken);
|
|
57461
|
+
console.log(" Set LEDGIT_API_TOKEN");
|
|
57462
|
+
}
|
|
57463
|
+
try {
|
|
57464
|
+
await enableActionsPrPermission();
|
|
57465
|
+
console.log(" Enabled Actions to create pull requests");
|
|
57466
|
+
} catch {
|
|
57467
|
+
console.error(`
|
|
57431
57468
|
Warning: Could not enable PR creation for Actions.`);
|
|
57432
|
-
|
|
57469
|
+
console.error("You may need to enable this manually in Settings > Actions > General");
|
|
57470
|
+
}
|
|
57471
|
+
} else {
|
|
57472
|
+
console.log(`
|
|
57473
|
+
⚠️ Unable to set secrets via GitHub CLI.`);
|
|
57474
|
+
console.log(` This can happen if you don't have admin access to this repository.
|
|
57475
|
+
`);
|
|
57476
|
+
console.log(" To fix gh access and retry, run:");
|
|
57477
|
+
console.log(` gh auth refresh -h github.com -s repo,workflow
|
|
57478
|
+
`);
|
|
57479
|
+
console.log(" Or add these secrets manually in GitHub:");
|
|
57480
|
+
console.log(` Go to: Settings > Secrets and variables > Actions > New repository secret
|
|
57481
|
+
`);
|
|
57482
|
+
console.log(` ${secretName}:`);
|
|
57483
|
+
console.log(` ${claudeToken}
|
|
57484
|
+
`);
|
|
57485
|
+
console.log(" BOKIO_TOKEN:");
|
|
57486
|
+
console.log(` ${config3.bokio.token}
|
|
57487
|
+
`);
|
|
57488
|
+
console.log(" BOKIO_COMPANY_ID:");
|
|
57489
|
+
console.log(` ${config3.bokio.companyId}
|
|
57490
|
+
`);
|
|
57491
|
+
if (options.ledgitApiToken) {
|
|
57492
|
+
console.log(" LEDGIT_API_TOKEN:");
|
|
57493
|
+
console.log(` ${options.ledgitApiToken}
|
|
57494
|
+
`);
|
|
57495
|
+
}
|
|
57433
57496
|
}
|
|
57434
57497
|
console.log(`
|
|
57435
57498
|
Creating workflow files...`);
|
|
@@ -57468,6 +57531,7 @@ Workflows created:`);
|
|
|
57468
57531
|
|
|
57469
57532
|
// src/commands/setup-github.ts
|
|
57470
57533
|
var execAsync4 = promisify8(exec8);
|
|
57534
|
+
var API_BASE_URL2 = process.env.LEDGIT_API_URL || "https://api.ledgit.se";
|
|
57471
57535
|
async function setupGithubCommand() {
|
|
57472
57536
|
const cwd = process.cwd();
|
|
57473
57537
|
console.log(`Setting up GitHub Actions for automated bookkeeping...
|
|
@@ -57482,7 +57546,73 @@ async function setupGithubCommand() {
|
|
|
57482
57546
|
console.log(` Using existing remote: ${repoUrl}
|
|
57483
57547
|
`);
|
|
57484
57548
|
}
|
|
57485
|
-
|
|
57549
|
+
let ghUser = "unknown";
|
|
57550
|
+
try {
|
|
57551
|
+
const { stdout } = await execAsync4("gh api user -q .login");
|
|
57552
|
+
ghUser = stdout.trim();
|
|
57553
|
+
} catch {
|
|
57554
|
+
}
|
|
57555
|
+
const hasRepoAccess = await checkRepoAccess();
|
|
57556
|
+
if (!hasRepoAccess) {
|
|
57557
|
+
throw new UserError(`Cannot access repository.
|
|
57558
|
+
|
|
57559
|
+
` + `You are logged in as '${ghUser}' but this account doesn't have access to the repository.
|
|
57560
|
+
|
|
57561
|
+
` + `To fix this:
|
|
57562
|
+
` + ` 1. Check your gh accounts: gh auth status
|
|
57563
|
+
` + ` 2. Switch account: gh auth switch -u <username>`);
|
|
57564
|
+
}
|
|
57565
|
+
const hasSecretsAccess = await checkRepoSecretsAccess();
|
|
57566
|
+
if (!hasSecretsAccess) {
|
|
57567
|
+
throw new UserError(`Cannot access repository secrets.
|
|
57568
|
+
|
|
57569
|
+
` + `You are logged in as '${ghUser}' but don't have admin/write access to manage secrets.
|
|
57570
|
+
|
|
57571
|
+
` + `To fix this:
|
|
57572
|
+
` + ` 1. Ensure you have admin access to this repository
|
|
57573
|
+
` + ` 2. Or refresh auth: gh auth refresh -h github.com -s repo,workflow`);
|
|
57574
|
+
}
|
|
57575
|
+
console.log(` Repository access verified (${ghUser})
|
|
57576
|
+
`);
|
|
57577
|
+
let ledgitApiToken;
|
|
57578
|
+
let config3;
|
|
57579
|
+
try {
|
|
57580
|
+
config3 = await loadConfig(cwd);
|
|
57581
|
+
} catch {
|
|
57582
|
+
}
|
|
57583
|
+
const needsLedgitToken = config3?.provider === "ledgit" || config3?.inboxProvider === "ledgit";
|
|
57584
|
+
if (needsLedgitToken) {
|
|
57585
|
+
const accessToken = await getValidAccessToken(cwd);
|
|
57586
|
+
if (accessToken) {
|
|
57587
|
+
console.log(" Creating Ledgit API token...");
|
|
57588
|
+
const response = await fetch(`${API_BASE_URL2}/api/tokens`, {
|
|
57589
|
+
method: "POST",
|
|
57590
|
+
headers: {
|
|
57591
|
+
Authorization: `Bearer ${accessToken}`,
|
|
57592
|
+
"Content-Type": "application/json"
|
|
57593
|
+
},
|
|
57594
|
+
body: JSON.stringify({
|
|
57595
|
+
name: "GitHub Actions",
|
|
57596
|
+
scopes: ["read", "write"]
|
|
57597
|
+
})
|
|
57598
|
+
});
|
|
57599
|
+
if (response.ok) {
|
|
57600
|
+
const result = await response.json();
|
|
57601
|
+
console.log(` ✓ Ledgit API token created
|
|
57602
|
+
`);
|
|
57603
|
+
ledgitApiToken = result.data.token;
|
|
57604
|
+
} else {
|
|
57605
|
+
console.log(" Could not create API token. You can create one later with:");
|
|
57606
|
+
console.log(` ledgit token create
|
|
57607
|
+
`);
|
|
57608
|
+
}
|
|
57609
|
+
} else {
|
|
57610
|
+
console.log(" Not logged in - skipping Ledgit API token creation.");
|
|
57611
|
+
console.log(` Run 'ledgit login' then 'ledgit token create' to create one.
|
|
57612
|
+
`);
|
|
57613
|
+
}
|
|
57614
|
+
}
|
|
57615
|
+
await setupClaudeWorkflow({ cwd, autoCommit: false, ledgitApiToken });
|
|
57486
57616
|
try {
|
|
57487
57617
|
await execAsync4("git add .github/workflows");
|
|
57488
57618
|
const { stdout: status } = await execAsync4("git status --porcelain .github/workflows");
|
|
@@ -58352,6 +58482,13 @@ initialize({
|
|
|
58352
58482
|
appName: "ledgit"
|
|
58353
58483
|
});
|
|
58354
58484
|
setVersion(pkg.version);
|
|
58485
|
+
|
|
58486
|
+
class UserError extends Error {
|
|
58487
|
+
constructor(message) {
|
|
58488
|
+
super(message);
|
|
58489
|
+
this.name = "UserError";
|
|
58490
|
+
}
|
|
58491
|
+
}
|
|
58355
58492
|
function withTelemetry(command, action) {
|
|
58356
58493
|
return async (...args) => {
|
|
58357
58494
|
const start = Date.now();
|
|
@@ -58375,6 +58512,13 @@ function withTelemetry(command, action) {
|
|
|
58375
58512
|
if (error instanceof Error) {
|
|
58376
58513
|
trackError("cli_command", error, { command });
|
|
58377
58514
|
}
|
|
58515
|
+
if (error instanceof UserError) {
|
|
58516
|
+
console.error(`
|
|
58517
|
+
Error: ${error.message}
|
|
58518
|
+
`);
|
|
58519
|
+
await shutdown();
|
|
58520
|
+
process.exit(1);
|
|
58521
|
+
}
|
|
58378
58522
|
throw error;
|
|
58379
58523
|
} finally {
|
|
58380
58524
|
await shutdown();
|
|
@@ -58393,19 +58537,16 @@ program.command("generate-lines").description("Append journal lines to an existi
|
|
|
58393
58537
|
program.command("list-tax-codes").description("List all available Swedish tax codes").action(withTelemetry("list-tax-codes", listTaxCodesCommand));
|
|
58394
58538
|
program.command("discard <inbox-directory>").description("Remove an inbox item and mark for deletion from provider").action(withTelemetry("discard", discardCommand));
|
|
58395
58539
|
program.command("login").description("Authenticate with Ledgit").option("-f, --force", "Overwrite existing token without prompting").action(withTelemetry("login", loginCommand));
|
|
58396
|
-
program.command("token [action]").description("Manage
|
|
58540
|
+
program.command("token [action]").description("Manage API tokens (PATs) for CI/CD").addHelpText("after", `
|
|
58397
58541
|
Actions:
|
|
58398
|
-
|
|
58399
|
-
|
|
58400
|
-
|
|
58401
|
-
revoke Revoke/delete stored token
|
|
58542
|
+
list List all API tokens (default)
|
|
58543
|
+
create Create a new API token
|
|
58544
|
+
revoke Revoke an API token
|
|
58402
58545
|
|
|
58403
58546
|
Examples:
|
|
58404
58547
|
$ ledgit token
|
|
58405
|
-
$ ledgit token
|
|
58406
|
-
$ ledgit token
|
|
58407
|
-
$ LEDGIT_TOKEN=$(ledgit token export)
|
|
58408
|
-
$ ledgit token refresh
|
|
58548
|
+
$ ledgit token list
|
|
58549
|
+
$ ledgit token create
|
|
58409
58550
|
$ ledgit token revoke
|
|
58410
58551
|
`).action(withTelemetry("token", tokenCommand));
|
|
58411
58552
|
program.command("update").description("Update AGENTS.md to the latest version").option("-f, --force", "Overwrite without prompting if modified").action(withTelemetry("update", updateCommand));
|
|
@@ -58442,3 +58583,6 @@ Examples:
|
|
|
58442
58583
|
`).action(withTelemetry("traktamente:create", traktamenteCommand));
|
|
58443
58584
|
traktamente.command("list").description("List available countries and traktamente rates").option("-y, --year <year>", "Year for rates (default: current year)").action(withTelemetry("traktamente:list", listCountriesCommand));
|
|
58444
58585
|
program.parse();
|
|
58586
|
+
export {
|
|
58587
|
+
UserError
|
|
58588
|
+
};
|