@meistrari/tela-cli 0.7.0 → 0.7.4

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.
Files changed (59) hide show
  1. package/README.md +56 -106
  2. package/dist/commands/auth.d.ts +2 -0
  3. package/dist/commands/context.d.ts +2 -0
  4. package/dist/commands/doctor-auth.d.ts +2 -0
  5. package/dist/commands/env.d.ts +2 -0
  6. package/dist/credentials.d.ts +2 -0
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.js +7027 -0
  9. package/dist/output.d.ts +13 -0
  10. package/dist/program.d.ts +2 -0
  11. package/package.json +17 -24
  12. package/scripts/install-skills.cjs +127 -0
  13. package/skills/tela-cli/SKILL.md +20 -0
  14. package/skills/tela-cli/references/agent.md +111 -0
  15. package/cli.ts +0 -25
  16. package/postinstall.sh +0 -19
  17. package/src/agent-api.ts +0 -300
  18. package/src/assets.d.ts +0 -4
  19. package/src/auth.ts +0 -432
  20. package/src/claude.ts +0 -101
  21. package/src/commands/doctor.ts +0 -35
  22. package/src/commands/feedback.ts +0 -701
  23. package/src/commands/metadata.ts +0 -242
  24. package/src/commands/push.ts +0 -208
  25. package/src/commands/run.ts +0 -1699
  26. package/src/commands/status.ts +0 -109
  27. package/src/commands/sync.ts +0 -245
  28. package/src/commit-message.ts +0 -69
  29. package/src/config.ts +0 -799
  30. package/src/diagnostics.ts +0 -813
  31. package/src/errors.ts +0 -122
  32. package/src/forgejo.ts +0 -233
  33. package/src/git.ts +0 -457
  34. package/src/ink/assets/160092__jorickhoofd__dog-bark-1.mp3 +0 -0
  35. package/src/ink/bark.tsx +0 -241
  36. package/src/ink/components.tsx +0 -178
  37. package/src/ink/runtime.tsx +0 -90
  38. package/src/ink/screens/feedback-screen.tsx +0 -395
  39. package/src/ink/screens/push-screen.tsx +0 -232
  40. package/src/ink/screens/run-screen.tsx +0 -292
  41. package/src/ink/screens/setup/breadcrumb.tsx +0 -24
  42. package/src/ink/screens/setup/setup-screen.tsx +0 -612
  43. package/src/ink/screens/setup/step-frame.tsx +0 -31
  44. package/src/ink/screens/setup/steps/done-step.tsx +0 -29
  45. package/src/ink/screens/setup/steps/environment-step.tsx +0 -23
  46. package/src/ink/screens/setup/steps/organization-step.tsx +0 -35
  47. package/src/ink/screens/setup/steps/review-step.tsx +0 -78
  48. package/src/ink/screens/setup/steps/running-step.tsx +0 -37
  49. package/src/ink/screens/setup/steps/ssh-key-step.tsx +0 -48
  50. package/src/ink/screens/setup/steps/text-field-step.tsx +0 -18
  51. package/src/ink/screens/setup/steps.ts +0 -156
  52. package/src/ink/screens/setup/types.ts +0 -65
  53. package/src/ink/screens/sync-screen.tsx +0 -283
  54. package/src/process.ts +0 -251
  55. package/src/program.ts +0 -2105
  56. package/src/runtime.ts +0 -147
  57. package/src/types.ts +0 -165
  58. package/src/ui.ts +0 -295
  59. package/src/version.ts +0 -3
package/src/errors.ts DELETED
@@ -1,122 +0,0 @@
1
- import { CommandError } from './process.ts'
2
- import { errorCard, type RenderOptions } from './ui.ts'
3
-
4
- export interface UserFacingErrorInput {
5
- code: string
6
- summary: string
7
- details?: string
8
- fixes?: string[]
9
- evidence?: string[]
10
- exitCode?: number
11
- cause?: unknown
12
- }
13
-
14
- export class UserFacingError extends Error {
15
- public readonly code: string
16
- public readonly summary: string
17
- public readonly details?: string
18
- public readonly fixes: string[]
19
- public readonly evidence: string[]
20
- public readonly exitCode: number
21
- public readonly cause?: unknown
22
-
23
- constructor(input: UserFacingErrorInput) {
24
- super(input.summary)
25
- this.name = 'UserFacingError'
26
- this.code = input.code
27
- this.summary = input.summary
28
- this.details = input.details
29
- this.fixes = input.fixes ?? []
30
- this.evidence = input.evidence ?? []
31
- this.exitCode = input.exitCode ?? 1
32
- this.cause = input.cause
33
- }
34
- }
35
-
36
- export function createUserFacingError(input: UserFacingErrorInput): UserFacingError {
37
- return new UserFacingError(input)
38
- }
39
-
40
- export function isUserFacingError(error: unknown): error is UserFacingError {
41
- return error instanceof UserFacingError
42
- }
43
-
44
- export function toUserFacingError(error: unknown): UserFacingError {
45
- if (isUserFacingError(error)) {
46
- return error
47
- }
48
-
49
- if (error instanceof CommandError) {
50
- const stdout = error.result.stdout.trim()
51
- const stderr = error.result.stderr.trim()
52
- const evidence = [
53
- `Command: ${error.result.command.join(' ')}`,
54
- stdout ? `stdout: ${stdout}` : '',
55
- stderr ? `stderr: ${stderr}` : '',
56
- ].filter(Boolean)
57
-
58
- return new UserFacingError({
59
- code: 'command_failed',
60
- summary: 'A local command failed.',
61
- details: error.message,
62
- evidence,
63
- exitCode: 1,
64
- cause: error,
65
- })
66
- }
67
-
68
- if (error instanceof Error) {
69
- return new UserFacingError({
70
- code: 'unexpected_error',
71
- summary: error.message,
72
- exitCode: 1,
73
- cause: error,
74
- })
75
- }
76
-
77
- return new UserFacingError({
78
- code: 'unexpected_error',
79
- summary: String(error),
80
- exitCode: 1,
81
- cause: error,
82
- })
83
- }
84
-
85
- export function renderUserFacingError(
86
- error: unknown,
87
- options: RenderOptions & { verbose?: boolean } = {},
88
- ): string {
89
- const userError = toUserFacingError(error)
90
- const evidence = options.verbose ? userError.evidence : []
91
-
92
- return errorCard({
93
- summary: userError.summary,
94
- details: userError.details,
95
- fixes: userError.fixes,
96
- evidence,
97
- }, options)
98
- }
99
-
100
- export function serializeError(error: unknown): {
101
- ok: false
102
- error: {
103
- code: string
104
- summary: string
105
- details?: string
106
- fixes: string[]
107
- evidence: string[]
108
- }
109
- } {
110
- const userError = toUserFacingError(error)
111
-
112
- return {
113
- ok: false,
114
- error: {
115
- code: userError.code,
116
- summary: userError.summary,
117
- details: userError.details,
118
- fixes: userError.fixes,
119
- evidence: userError.evidence,
120
- },
121
- }
122
- }
package/src/forgejo.ts DELETED
@@ -1,233 +0,0 @@
1
- import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs'
2
- import { homedir } from 'node:os'
3
- import { basename, extname, join } from 'node:path'
4
- import { provisionForgejoUser, type AgentApiError } from './agent-api.ts'
5
- import type { FetchLike } from './auth.ts'
6
- import { createUserFacingError } from './errors.ts'
7
- import type {
8
- ForgejoUserCreateResponse,
9
- ForgejoUserSshKeyInput,
10
- TelaCliConfig,
11
- TelaCliGitSshKey,
12
- TelaCliForgejoOrganization,
13
- } from './types.ts'
14
-
15
- export interface SelectedSshPublicKey extends ForgejoUserSshKeyInput {
16
- path: string
17
- }
18
-
19
- export interface EnsureForgejoUserAccessOptions {
20
- config: TelaCliConfig
21
- organization: TelaCliForgejoOrganization
22
- sshKey: SelectedSshPublicKey
23
- fetchFn?: FetchLike
24
- onProgress?: (message: string, title?: string) => void
25
- provisionFn?: typeof provisionForgejoUser
26
- saveConfig: (config: TelaCliConfig) => void
27
- }
28
-
29
- export interface ForgejoAccessResult {
30
- config: TelaCliConfig
31
- detail: string
32
- response: ForgejoUserCreateResponse
33
- }
34
-
35
- function getHomeDir(): string {
36
- return process.env.HOME || homedir()
37
- }
38
-
39
- function expandHome(input: string): string {
40
- if (input === '~') {
41
- return getHomeDir()
42
- }
43
-
44
- if (input.startsWith('~/')) {
45
- return join(getHomeDir(), input.slice(2))
46
- }
47
-
48
- return input
49
- }
50
-
51
- function getSshDirectory(): string {
52
- return join(getHomeDir(), '.ssh')
53
- }
54
-
55
- function sshKeyTitleFromPath(filePath: string): string {
56
- const base = basename(filePath)
57
- return extname(base) === '.pub'
58
- ? base.slice(0, -4)
59
- : base
60
- }
61
-
62
- export function loadSshPublicKey(filePath: string): SelectedSshPublicKey {
63
- const expandedPath = expandHome(filePath.trim())
64
- if (!expandedPath) {
65
- throw new Error('SSH public key path is required')
66
- }
67
-
68
- if (!existsSync(expandedPath)) {
69
- throw new Error(`SSH public key file does not exist: ${expandedPath}`)
70
- }
71
-
72
- const stats = statSync(expandedPath)
73
- if (!stats.isFile()) {
74
- throw new Error(`SSH public key path is not a file: ${expandedPath}`)
75
- }
76
-
77
- const key = readFileSync(expandedPath, 'utf-8').trim()
78
- if (!key) {
79
- throw new Error(`SSH public key file is empty: ${expandedPath}`)
80
- }
81
-
82
- return {
83
- path: expandedPath,
84
- title: sshKeyTitleFromPath(expandedPath),
85
- key,
86
- }
87
- }
88
-
89
- export function validateSshPublicKeyPath(value: string): string | undefined {
90
- try {
91
- loadSshPublicKey(value)
92
- return undefined
93
- }
94
- catch (error) {
95
- return error instanceof Error ? error.message : 'SSH public key path is invalid'
96
- }
97
- }
98
-
99
- export function inferSshPrivateKeyPath(publicKeyPath: string): string {
100
- const expandedPath = expandHome(publicKeyPath.trim())
101
- return expandedPath.endsWith('.pub')
102
- ? expandedPath.slice(0, -4)
103
- : expandedPath
104
- }
105
-
106
- export function resolveSshPrivateKeyPath(filePath: string): string {
107
- const expandedPath = expandHome(filePath.trim())
108
- if (!expandedPath) {
109
- throw new Error('SSH private key path is required')
110
- }
111
-
112
- if (!existsSync(expandedPath)) {
113
- throw new Error(`SSH private key file does not exist: ${expandedPath}`)
114
- }
115
-
116
- const stats = statSync(expandedPath)
117
- if (!stats.isFile()) {
118
- throw new Error(`SSH private key path is not a file: ${expandedPath}`)
119
- }
120
-
121
- return expandedPath
122
- }
123
-
124
- export function validateSshPrivateKeyPath(value: string): string | undefined {
125
- try {
126
- resolveSshPrivateKeyPath(value)
127
- return undefined
128
- }
129
- catch (error) {
130
- return error instanceof Error ? error.message : 'SSH private key path is invalid'
131
- }
132
- }
133
-
134
- export function createGitSshKey(sshKey: SelectedSshPublicKey, privateKeyPath: string): TelaCliGitSshKey {
135
- return {
136
- title: sshKey.title,
137
- publicKeyPath: sshKey.path,
138
- privateKeyPath: resolveSshPrivateKeyPath(privateKeyPath),
139
- }
140
- }
141
-
142
- export function listDiscoveredSshPublicKeys(): SelectedSshPublicKey[] {
143
- const sshDirectory = getSshDirectory()
144
- if (!existsSync(sshDirectory)) {
145
- return []
146
- }
147
-
148
- return readdirSync(sshDirectory, { withFileTypes: true })
149
- .filter(entry => entry.isFile() && entry.name.endsWith('.pub'))
150
- .map(entry => loadSshPublicKey(join(sshDirectory, entry.name)))
151
- .sort((left, right) => left.title.localeCompare(right.title) || left.path.localeCompare(right.path))
152
- }
153
-
154
- function buildProvisioningDetail(result: ForgejoUserCreateResponse, sshKey: SelectedSshPublicKey): string {
155
- const userState = result.userCreated ? 'user created' : 'user already existed'
156
- const keyState = result.sshKeyCreated ? 'SSH key added' : 'SSH key already present'
157
- const teamState = result.teamCreated ? 'team created' : 'team ensured'
158
- const username = result.username ?? '<unknown>'
159
- const teamName = result.teamName ?? '<unknown>'
160
-
161
- return `${username} in ${teamName}; ${userState}, ${teamState}, ${keyState} (${sshKey.title})`
162
- }
163
-
164
- function toProvisioningError(error: unknown): never {
165
- const agentApiError = error as AgentApiError
166
- if (agentApiError && typeof agentApiError.status === 'number' && typeof agentApiError.responseBody === 'string') {
167
- throw createUserFacingError({
168
- code: 'forgejo_user_provision_failed',
169
- summary: 'Forgejo user provisioning failed.',
170
- details: agentApiError.message,
171
- fixes: [
172
- 'Run `tela setup` again to refresh the Tela session and retry SSH-key provisioning.',
173
- 'Use `--verbose` if you need the full Agent API response details.',
174
- ],
175
- evidence: [
176
- `Agent API status: ${agentApiError.status}`,
177
- agentApiError.responseBody ? `Response body: ${agentApiError.responseBody}` : '',
178
- ].filter(Boolean),
179
- cause: error,
180
- })
181
- }
182
-
183
- throw createUserFacingError({
184
- code: 'forgejo_user_provision_failed',
185
- summary: 'Forgejo user provisioning failed.',
186
- details: error instanceof Error ? error.message : String(error),
187
- fixes: [
188
- 'Run `tela setup` again to refresh the Tela session and retry SSH-key provisioning.',
189
- ],
190
- cause: error,
191
- })
192
- }
193
-
194
- export async function ensureForgejoUserAccess(options: EnsureForgejoUserAccessOptions): Promise<ForgejoAccessResult> {
195
- const provisionFn = options.provisionFn ?? provisionForgejoUser
196
- const baseConfig: TelaCliConfig = {
197
- ...options.config,
198
- forgejoOrganization: options.organization,
199
- forgejoUserRegistered: false,
200
- }
201
-
202
- options.saveConfig(baseConfig)
203
- options.onProgress?.(
204
- `Provisioning Forgejo access for ${options.organization.name} with ${options.sshKey.title}.`,
205
- 'Forgejo',
206
- )
207
-
208
- let response: ForgejoUserCreateResponse
209
- try {
210
- response = await provisionFn({
211
- organizationName: options.organization.name,
212
- sshKey: options.sshKey,
213
- }, baseConfig, options.fetchFn)
214
- }
215
- catch (error) {
216
- toProvisioningError(error)
217
- }
218
-
219
- const finalConfig: TelaCliConfig = {
220
- ...baseConfig,
221
- forgejoUserRegistered: true,
222
- }
223
- options.saveConfig(finalConfig)
224
-
225
- const detail = buildProvisioningDetail(response, options.sshKey)
226
- options.onProgress?.(`Forgejo access ready: ${detail}`, 'Forgejo')
227
-
228
- return {
229
- config: finalConfig,
230
- detail,
231
- response,
232
- }
233
- }