@markjaquith/agency 1.6.0 → 1.6.2
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/cli.ts +25 -1
- package/package.json +38 -38
- package/src/commands/task.ts +30 -8
- package/src/services/GitService.ts +74 -1
- package/src/utils/process.ts +8 -1
package/cli.ts
CHANGED
|
@@ -635,7 +635,31 @@ try {
|
|
|
635
635
|
await command.run(cmdPositionals, cmdValues, commandArgs)
|
|
636
636
|
} catch (error) {
|
|
637
637
|
if (error instanceof Error) {
|
|
638
|
-
|
|
638
|
+
let message = error.message
|
|
639
|
+
|
|
640
|
+
// Handle Effect FiberFailure errors that wrap tagged errors
|
|
641
|
+
// When the message is generic "An error has occurred", try to extract the actual error
|
|
642
|
+
if (message === "An error has occurred") {
|
|
643
|
+
// Try to extract the actual error from Effect's Cause structure
|
|
644
|
+
const causeSymbol = Object.getOwnPropertySymbols(error).find((s) =>
|
|
645
|
+
s.toString().includes("Cause"),
|
|
646
|
+
)
|
|
647
|
+
if (causeSymbol) {
|
|
648
|
+
const cause = (error as any)[causeSymbol]
|
|
649
|
+
if (cause && cause._tag === "Fail" && cause.failure) {
|
|
650
|
+
const failure = cause.failure
|
|
651
|
+
// Try common error message patterns
|
|
652
|
+
message =
|
|
653
|
+
failure.message ||
|
|
654
|
+
failure.stderr ||
|
|
655
|
+
(failure._tag
|
|
656
|
+
? `${failure._tag}: ${JSON.stringify(failure)}`
|
|
657
|
+
: JSON.stringify(failure))
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
console.error(`ⓘ ${message}`)
|
|
639
663
|
} else {
|
|
640
664
|
console.error("An unexpected error occurred:", error)
|
|
641
665
|
}
|
package/package.json
CHANGED
|
@@ -1,53 +1,65 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markjaquith/agency",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.2",
|
|
4
4
|
"description": "Manages personal agents files",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"agents",
|
|
7
|
+
"bun",
|
|
8
|
+
"personal-agents",
|
|
9
|
+
"typescript"
|
|
10
|
+
],
|
|
5
11
|
"license": "MIT",
|
|
6
12
|
"author": "Mark Jaquith",
|
|
7
13
|
"repository": {
|
|
8
14
|
"type": "git",
|
|
9
15
|
"url": "git+https://github.com/markjaquith/agency.git"
|
|
10
16
|
},
|
|
11
|
-
"module": "index.ts",
|
|
12
|
-
"type": "module",
|
|
13
17
|
"bin": {
|
|
14
18
|
"agency": "cli.ts"
|
|
15
19
|
},
|
|
20
|
+
"files": [
|
|
21
|
+
"index.ts",
|
|
22
|
+
"cli.ts",
|
|
23
|
+
"src",
|
|
24
|
+
"templates",
|
|
25
|
+
"README.md",
|
|
26
|
+
"LICENSE"
|
|
27
|
+
],
|
|
28
|
+
"type": "module",
|
|
29
|
+
"module": "index.ts",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./index.ts",
|
|
33
|
+
"import": "./index.ts"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public",
|
|
38
|
+
"provenance": true,
|
|
39
|
+
"registry": "https://registry.npmjs.org/",
|
|
40
|
+
"tag": "latest"
|
|
41
|
+
},
|
|
16
42
|
"scripts": {
|
|
17
43
|
"test": "find src -name '*.test.ts' ! -name '*.integration.test.ts' -print0 | xargs -0 -n 1 -P 4 bun test",
|
|
18
44
|
"test:integration": "find src -name '*.integration.test.ts' -print0 | xargs -0 -n 1 -P 4 bun test",
|
|
19
45
|
"test:all": "find src -name '*.test.ts' -print0 | xargs -0 -n 1 -P 4 bun test",
|
|
20
|
-
"format": "
|
|
21
|
-
"format:check": "
|
|
46
|
+
"format": "oxfmt",
|
|
47
|
+
"format:check": "oxfmt --check",
|
|
22
48
|
"knip": "knip --production",
|
|
23
49
|
"pushable": "./scripts/pushable",
|
|
24
50
|
"check-commit-msg": "./scripts/check-commit-msg",
|
|
25
51
|
"build": "bun build cli.ts --outdir dist --target node --minify"
|
|
26
52
|
},
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@effect/schema": "^0.75.5",
|
|
55
|
+
"effect": "^3.19.15",
|
|
56
|
+
"jsonc-parser": "^3.3.1",
|
|
57
|
+
"ora": "^8.2.0"
|
|
32
58
|
},
|
|
33
|
-
"files": [
|
|
34
|
-
"index.ts",
|
|
35
|
-
"cli.ts",
|
|
36
|
-
"src",
|
|
37
|
-
"templates",
|
|
38
|
-
"README.md",
|
|
39
|
-
"LICENSE"
|
|
40
|
-
],
|
|
41
|
-
"keywords": [
|
|
42
|
-
"agents",
|
|
43
|
-
"bun",
|
|
44
|
-
"typescript",
|
|
45
|
-
"personal-agents"
|
|
46
|
-
],
|
|
47
59
|
"devDependencies": {
|
|
48
60
|
"@types/bun": "^1.3.6",
|
|
49
61
|
"knip": "^5.82.1",
|
|
50
|
-
"
|
|
62
|
+
"oxfmt": "^0.27.0"
|
|
51
63
|
},
|
|
52
64
|
"peerDependencies": {
|
|
53
65
|
"typescript": "^5.9.3"
|
|
@@ -55,19 +67,7 @@
|
|
|
55
67
|
"engines": {
|
|
56
68
|
"bun": ">=1.0.0"
|
|
57
69
|
},
|
|
58
|
-
"dependencies": {
|
|
59
|
-
"@effect/schema": "^0.75.5",
|
|
60
|
-
"effect": "^3.19.15",
|
|
61
|
-
"jsonc-parser": "^3.3.1",
|
|
62
|
-
"ora": "^8.2.0"
|
|
63
|
-
},
|
|
64
70
|
"trustedDependencies": [
|
|
65
71
|
"@triggi/native-exec"
|
|
66
|
-
]
|
|
67
|
-
"publishConfig": {
|
|
68
|
-
"registry": "https://registry.npmjs.org/",
|
|
69
|
-
"tag": "latest",
|
|
70
|
-
"access": "public",
|
|
71
|
-
"provenance": true
|
|
72
|
-
}
|
|
72
|
+
]
|
|
73
73
|
}
|
package/src/commands/task.ts
CHANGED
|
@@ -422,14 +422,36 @@ export const task = (options: TaskOptions = {}) =>
|
|
|
422
422
|
(yield* git.findDefaultRemote(targetPath))
|
|
423
423
|
|
|
424
424
|
if (remote) {
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
yield* git.
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
425
|
+
// Get just the branch name (e.g., "main") to fetch only that branch
|
|
426
|
+
// This is much faster than fetching all branches in large repos
|
|
427
|
+
const mainBranchName = yield* git.getMainBranchName(targetPath)
|
|
428
|
+
|
|
429
|
+
if (mainBranchName) {
|
|
430
|
+
log(
|
|
431
|
+
info(
|
|
432
|
+
`Fetching latest from ${highlight.branch(`${remote}/${mainBranchName}`)}...`,
|
|
433
|
+
),
|
|
434
|
+
)
|
|
435
|
+
verboseLog(`Fetching ${mainBranchName} from remote: ${remote}`)
|
|
436
|
+
yield* git.fetch(targetPath, remote, mainBranchName).pipe(
|
|
437
|
+
Effect.catchAll((err) => {
|
|
438
|
+
verboseLog(
|
|
439
|
+
`Failed to fetch ${mainBranchName} from ${remote}: ${err}`,
|
|
440
|
+
)
|
|
441
|
+
return Effect.void
|
|
442
|
+
}),
|
|
443
|
+
)
|
|
444
|
+
} else {
|
|
445
|
+
// Fallback: fetch all branches if we can't determine the main branch
|
|
446
|
+
log(info(`Fetching latest from ${highlight.branch(remote)}...`))
|
|
447
|
+
verboseLog(`Fetching all branches from remote: ${remote}`)
|
|
448
|
+
yield* git.fetch(targetPath, remote).pipe(
|
|
449
|
+
Effect.catchAll((err) => {
|
|
450
|
+
verboseLog(`Failed to fetch from ${remote}: ${err}`)
|
|
451
|
+
return Effect.void
|
|
452
|
+
}),
|
|
453
|
+
)
|
|
454
|
+
}
|
|
433
455
|
}
|
|
434
456
|
|
|
435
457
|
// Now resolve the main branch (preferring remote)
|
|
@@ -22,7 +22,14 @@ export class GitCommandError extends Data.TaggedError("GitCommandError")<{
|
|
|
22
22
|
command: string
|
|
23
23
|
exitCode: number
|
|
24
24
|
stderr: string
|
|
25
|
-
}> {
|
|
25
|
+
}> {
|
|
26
|
+
override get message(): string {
|
|
27
|
+
return (
|
|
28
|
+
this.stderr ||
|
|
29
|
+
`Git command failed with exit code ${this.exitCode}: ${this.command}`
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
26
33
|
|
|
27
34
|
// Error mapper for git command failures
|
|
28
35
|
const mapToGitCommandError = createErrorMapper(GitCommandError)
|
|
@@ -515,6 +522,72 @@ export class GitService extends Effect.Service<GitService>()("GitService", {
|
|
|
515
522
|
),
|
|
516
523
|
),
|
|
517
524
|
|
|
525
|
+
/**
|
|
526
|
+
* Gets just the main branch name (e.g., "main" or "master") without any remote prefix.
|
|
527
|
+
*
|
|
528
|
+
* This is useful when you need to fetch a specific branch from a remote,
|
|
529
|
+
* as `git fetch origin main` requires just the branch name, not `origin/main`.
|
|
530
|
+
*/
|
|
531
|
+
getMainBranchName: (gitRoot: string) =>
|
|
532
|
+
Effect.gen(function* () {
|
|
533
|
+
// Get the configured main branch
|
|
534
|
+
const configuredBranch = yield* getGitConfigEffect(
|
|
535
|
+
"agency.mainBranch",
|
|
536
|
+
gitRoot,
|
|
537
|
+
).pipe(Effect.catchAll(() => Effect.succeed(null)))
|
|
538
|
+
|
|
539
|
+
// If configured, strip any remote prefix and return
|
|
540
|
+
if (configuredBranch) {
|
|
541
|
+
// Strip remote prefix if present (e.g., "origin/main" -> "main")
|
|
542
|
+
return (
|
|
543
|
+
configuredBranch.match(/^[^/]+\/(.+)$/)?.[1] || configuredBranch
|
|
544
|
+
)
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// Otherwise, find the main branch by checking what exists
|
|
548
|
+
// We need to check for common branch names that exist (local or remote)
|
|
549
|
+
const remotesResult = yield* runGitCommand(["git", "remote"], gitRoot)
|
|
550
|
+
const remotes =
|
|
551
|
+
remotesResult.exitCode === 0 && remotesResult.stdout.trim()
|
|
552
|
+
? remotesResult.stdout.trim().split("\n")
|
|
553
|
+
: []
|
|
554
|
+
|
|
555
|
+
// Determine the default remote
|
|
556
|
+
let defaultRemote: string | null = null
|
|
557
|
+
if (remotes.length > 0) {
|
|
558
|
+
if (remotes.includes("origin")) {
|
|
559
|
+
defaultRemote = "origin"
|
|
560
|
+
} else if (remotes.includes("upstream")) {
|
|
561
|
+
defaultRemote = "upstream"
|
|
562
|
+
} else {
|
|
563
|
+
defaultRemote = remotes[0] || null
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// Check for common branch names (either remote or local)
|
|
568
|
+
for (const branchName of ["main", "master"]) {
|
|
569
|
+
// Check remote version first
|
|
570
|
+
if (defaultRemote) {
|
|
571
|
+
const remoteBranch = `${defaultRemote}/${branchName}`
|
|
572
|
+
const exists = yield* branchExistsEffect(gitRoot, remoteBranch)
|
|
573
|
+
if (exists) {
|
|
574
|
+
return branchName
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
// Check local version
|
|
578
|
+
const localExists = yield* branchExistsEffect(gitRoot, branchName)
|
|
579
|
+
if (localExists) {
|
|
580
|
+
return branchName
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
return null
|
|
585
|
+
}).pipe(
|
|
586
|
+
Effect.mapError(
|
|
587
|
+
() => new GitError({ message: "Failed to get main branch name" }),
|
|
588
|
+
),
|
|
589
|
+
),
|
|
590
|
+
|
|
518
591
|
getDefaultBaseBranchConfig: (gitRoot: string) =>
|
|
519
592
|
pipe(
|
|
520
593
|
getGitConfigEffect("agency.baseBranch", gitRoot),
|
package/src/utils/process.ts
CHANGED
|
@@ -27,7 +27,14 @@ class ProcessError extends Data.TaggedError("ProcessError")<{
|
|
|
27
27
|
command: string
|
|
28
28
|
exitCode: number
|
|
29
29
|
stderr: string
|
|
30
|
-
}> {
|
|
30
|
+
}> {
|
|
31
|
+
override get message(): string {
|
|
32
|
+
return (
|
|
33
|
+
this.stderr ||
|
|
34
|
+
`Process failed with exit code ${this.exitCode}: ${this.command}`
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
31
38
|
|
|
32
39
|
/**
|
|
33
40
|
* Spawn a process with proper error handling and typed results.
|