lalph 0.3.104 → 0.3.106
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/cli.mjs +1127 -1047
- package/package.json +9 -9
- package/src/Github/TokenManager.ts +20 -6
- package/src/IssueSource.ts +43 -7
- package/src/Prd.ts +1 -0
- package/src/domain/GithubComment.ts +3 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lalph",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.106",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -37,24 +37,24 @@
|
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@changesets/changelog-github": "^0.6.0",
|
|
39
39
|
"@changesets/cli": "^2.30.0",
|
|
40
|
-
"@effect/ai-openai": "4.0.0-beta.
|
|
41
|
-
"@effect/ai-openai-compat": "4.0.0-beta.
|
|
42
|
-
"@effect/language-service": "^0.
|
|
43
|
-
"@effect/platform-node": "4.0.0-beta.
|
|
40
|
+
"@effect/ai-openai": "4.0.0-beta.38",
|
|
41
|
+
"@effect/ai-openai-compat": "4.0.0-beta.38",
|
|
42
|
+
"@effect/language-service": "^0.82.0",
|
|
43
|
+
"@effect/platform-node": "4.0.0-beta.38",
|
|
44
44
|
"@linear/sdk": "^78.0.0",
|
|
45
45
|
"@octokit/plugin-rest-endpoint-methods": "^17.0.0",
|
|
46
46
|
"@octokit/types": "^16.0.0",
|
|
47
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
48
|
-
"clanka": "^0.2.
|
|
47
|
+
"@typescript/native-preview": "7.0.0-dev.20260323.1",
|
|
48
|
+
"clanka": "^0.2.34",
|
|
49
49
|
"concurrently": "^9.2.1",
|
|
50
|
-
"effect": "4.0.0-beta.
|
|
50
|
+
"effect": "4.0.0-beta.38",
|
|
51
51
|
"husky": "^9.1.7",
|
|
52
52
|
"lint-staged": "^16.4.0",
|
|
53
53
|
"octokit": "^5.0.5",
|
|
54
54
|
"oxlint": "^1.56.0",
|
|
55
55
|
"prettier": "^3.8.1",
|
|
56
56
|
"tsdown": "^0.21.4",
|
|
57
|
-
"typescript": "^
|
|
57
|
+
"typescript": "^6.0.2",
|
|
58
58
|
"yaml": "^2.8.3"
|
|
59
59
|
},
|
|
60
60
|
"lint-staged": {
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
Effect,
|
|
4
4
|
Layer,
|
|
5
5
|
Option,
|
|
6
|
+
Redacted,
|
|
6
7
|
Schedule,
|
|
7
8
|
Schema,
|
|
8
9
|
Semaphore,
|
|
@@ -16,7 +17,9 @@ import {
|
|
|
16
17
|
HttpClientResponse,
|
|
17
18
|
} from "effect/unstable/http"
|
|
18
19
|
import { KeyValueStore } from "effect/unstable/persistence"
|
|
20
|
+
import { Prompt } from "effect/unstable/cli"
|
|
19
21
|
import { layerKvs } from "../Kvs.ts"
|
|
22
|
+
import type { QuitError } from "effect/Terminal"
|
|
20
23
|
|
|
21
24
|
const clientId = "Ov23liJMtg6leTI1Vu6m"
|
|
22
25
|
|
|
@@ -24,6 +27,7 @@ export class TokenManager extends ServiceMap.Service<TokenManager>()(
|
|
|
24
27
|
"lalph/Github/TokenManager",
|
|
25
28
|
{
|
|
26
29
|
make: Effect.gen(function* () {
|
|
30
|
+
const promptEnv = yield* Effect.services<Prompt.Environment>()
|
|
27
31
|
const kvs = KeyValueStore.prefix(
|
|
28
32
|
yield* KeyValueStore.KeyValueStore,
|
|
29
33
|
"github.accessToken",
|
|
@@ -54,16 +58,26 @@ export class TokenManager extends ServiceMap.Service<TokenManager>()(
|
|
|
54
58
|
),
|
|
55
59
|
})
|
|
56
60
|
|
|
61
|
+
const promptPat = Effect.gen(function* () {
|
|
62
|
+
return yield* Prompt.password({
|
|
63
|
+
message:
|
|
64
|
+
"GitHub PAT with repo, read:user, read:project scopes (leave empty for OAuth)",
|
|
65
|
+
validate: (value) => Effect.succeed(value.trim()),
|
|
66
|
+
})
|
|
67
|
+
}).pipe(Effect.provideServices(promptEnv))
|
|
68
|
+
|
|
57
69
|
const getNoLock: Effect.Effect<
|
|
58
70
|
AccessToken,
|
|
59
|
-
HttpClientError.HttpClientError | Schema.SchemaError
|
|
71
|
+
HttpClientError.HttpClientError | QuitError | Schema.SchemaError
|
|
60
72
|
> = Effect.gen(function* () {
|
|
61
|
-
if (Option.
|
|
62
|
-
|
|
63
|
-
yield* set(Option.some(newToken))
|
|
64
|
-
return newToken
|
|
73
|
+
if (Option.isSome(currentToken)) {
|
|
74
|
+
return currentToken.value
|
|
65
75
|
}
|
|
66
|
-
|
|
76
|
+
const token = Redacted.value(yield* promptPat)
|
|
77
|
+
const accessToken =
|
|
78
|
+
token.length > 0 ? new AccessToken({ token }) : yield* deviceCode
|
|
79
|
+
yield* set(Option.some(accessToken))
|
|
80
|
+
return accessToken
|
|
67
81
|
})
|
|
68
82
|
const get = Semaphore.makeUnsafe(1).withPermit(getNoLock)
|
|
69
83
|
|
package/src/IssueSource.ts
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
SubscriptionRef,
|
|
12
12
|
pipe,
|
|
13
13
|
} from "effect"
|
|
14
|
-
import
|
|
14
|
+
import { PrdIssue } from "./domain/PrdIssue.ts"
|
|
15
15
|
import type { ProjectId } from "./domain/Project.ts"
|
|
16
16
|
import type { CurrentProjectId, Settings } from "./Settings.ts"
|
|
17
17
|
import type { CliAgentPreset } from "./domain/CliAgentPreset.ts"
|
|
@@ -127,16 +127,20 @@ export class IssueSource extends ServiceMap.Service<
|
|
|
127
127
|
|
|
128
128
|
const update = Effect.fnUntraced(function* (
|
|
129
129
|
projectId: ProjectId,
|
|
130
|
-
|
|
130
|
+
f: (_: ReadonlyArray<PrdIssue>) => ReadonlyArray<PrdIssue>,
|
|
131
131
|
) {
|
|
132
132
|
const ref = yield* ScopedCache.get(refs, projectId)
|
|
133
|
-
yield* SubscriptionRef.
|
|
133
|
+
yield* SubscriptionRef.update(ref, (change) =>
|
|
134
|
+
IssuesChange.Internal({
|
|
135
|
+
issues: f(change.issues),
|
|
136
|
+
}),
|
|
137
|
+
)
|
|
134
138
|
})
|
|
135
139
|
|
|
136
140
|
const updateIssues = (projectId: ProjectId) =>
|
|
137
141
|
pipe(
|
|
138
142
|
impl.issues(projectId),
|
|
139
|
-
Effect.tap((issues) => update(projectId, issues)),
|
|
143
|
+
Effect.tap((issues) => update(projectId, () => issues)),
|
|
140
144
|
)
|
|
141
145
|
|
|
142
146
|
return IssueSource.of({
|
|
@@ -151,17 +155,49 @@ export class IssueSource extends ServiceMap.Service<
|
|
|
151
155
|
createIssue: (projectId, issue) =>
|
|
152
156
|
pipe(
|
|
153
157
|
impl.createIssue(projectId, issue),
|
|
154
|
-
Effect.tap(
|
|
158
|
+
Effect.tap((createdIssue) =>
|
|
159
|
+
update(projectId, (issues) => {
|
|
160
|
+
const nextIssue = issue.update({ id: createdIssue.id })
|
|
161
|
+
const index = issues.findIndex(
|
|
162
|
+
(current) => current.id === createdIssue.id,
|
|
163
|
+
)
|
|
164
|
+
if (index === -1) {
|
|
165
|
+
return [...issues, nextIssue]
|
|
166
|
+
}
|
|
167
|
+
return issues.map((current, i) =>
|
|
168
|
+
i === index ? nextIssue : current,
|
|
169
|
+
)
|
|
170
|
+
}),
|
|
171
|
+
),
|
|
155
172
|
),
|
|
156
173
|
updateIssue: (options) =>
|
|
157
174
|
pipe(
|
|
158
175
|
impl.updateIssue(options),
|
|
159
|
-
Effect.tap(
|
|
176
|
+
Effect.tap(() =>
|
|
177
|
+
update(options.projectId, (issues) =>
|
|
178
|
+
issues.map((issue) =>
|
|
179
|
+
issue.id === options.issueId
|
|
180
|
+
? new PrdIssue({
|
|
181
|
+
...issue,
|
|
182
|
+
title: options.title ?? issue.title,
|
|
183
|
+
description: options.description ?? issue.description,
|
|
184
|
+
state: options.state ?? issue.state,
|
|
185
|
+
blockedBy: options.blockedBy ?? issue.blockedBy,
|
|
186
|
+
autoMerge: options.autoMerge ?? issue.autoMerge,
|
|
187
|
+
})
|
|
188
|
+
: issue,
|
|
189
|
+
),
|
|
190
|
+
),
|
|
191
|
+
),
|
|
160
192
|
),
|
|
161
193
|
cancelIssue: (projectId, issueId) =>
|
|
162
194
|
pipe(
|
|
163
195
|
impl.cancelIssue(projectId, issueId),
|
|
164
|
-
Effect.tap(
|
|
196
|
+
Effect.tap(() =>
|
|
197
|
+
update(projectId, (issues) =>
|
|
198
|
+
issues.filter((issue) => issue.id !== issueId),
|
|
199
|
+
),
|
|
200
|
+
),
|
|
165
201
|
),
|
|
166
202
|
})
|
|
167
203
|
})
|
package/src/Prd.ts
CHANGED
|
@@ -36,7 +36,9 @@ export class PullRequestComments extends S.Class<PullRequestComments>(
|
|
|
36
36
|
|
|
37
37
|
export class PullRequest extends S.Class<PullRequest>("PullRequest")({
|
|
38
38
|
url: S.String,
|
|
39
|
-
reviewDecision: S.
|
|
39
|
+
reviewDecision: S.NullOr(
|
|
40
|
+
S.Literals(["APPROVED", "CHANGES_REQUESTED", "REVIEW_REQUIRED"]),
|
|
41
|
+
),
|
|
40
42
|
reviews: S.suspend(() => Reviews),
|
|
41
43
|
reviewThreads: S.suspend(() => ReviewThreads),
|
|
42
44
|
comments: PullRequestComments,
|