@meistrari/tela-cli 0.7.0 → 0.7.5

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
@@ -0,0 +1,13 @@
1
+ import type { Writable } from 'node:stream';
2
+ export type CliIo = {
3
+ stdout: Pick<Writable, 'write'>;
4
+ stderr: Pick<Writable, 'write'>;
5
+ };
6
+ export type GlobalOptions = {
7
+ json: boolean;
8
+ verbose?: boolean;
9
+ };
10
+ export declare function writeJson(io: CliIo, value: unknown): void;
11
+ export declare function writeLine(io: CliIo, line?: string): void;
12
+ export declare function writeError(io: CliIo, message: string): void;
13
+ export declare function formatBool(value: boolean): string;
@@ -0,0 +1,2 @@
1
+ import type { CliIo } from './output';
2
+ export declare function runCli(argv: string[], io: CliIo): Promise<number>;
package/package.json CHANGED
@@ -1,34 +1,27 @@
1
1
  {
2
2
  "name": "@meistrari/tela-cli",
3
- "version": "0.7.0",
4
- "type": "module",
3
+ "version": "0.7.5",
4
+ "description": "Tela command line tools for local state and agent workflows.",
5
+ "license": "UNLICENSED",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/meistrari/tela-dock.git",
9
+ "directory": "apps/tela-cli"
10
+ },
11
+ "main": "dist/index.js",
12
+ "types": "dist/index.d.ts",
5
13
  "bin": {
6
- "tela": "cli.ts"
14
+ "tela": "dist/index.js"
7
15
  },
8
16
  "files": [
9
- "cli.ts",
10
- "postinstall.sh",
11
- "src/**/*"
17
+ "dist",
18
+ "scripts/install-skills.cjs",
19
+ "skills"
12
20
  ],
13
21
  "scripts": {
14
- "build": "bun build --compile ./cli.ts --outfile ./dist/tela",
15
- "postinstall": "bash ./postinstall.sh",
16
- "test": "bun test",
17
- "typecheck": "bunx tsc --noEmit"
18
- },
19
- "dependencies": {
20
- "@meistrari/auth-cli": "^1.0.1",
21
- "better-auth": "^1.6.3",
22
- "commander": "13.1.0",
23
- "ink": "6.2.3",
24
- "react": "19"
25
- },
26
- "devDependencies": {
27
- "@types/react": "19",
28
- "bun-types": "1.3.4",
29
- "ink-testing-library": "4.0.0"
22
+ "postinstall": "node scripts/install-skills.cjs --quiet"
30
23
  },
31
- "patchedDependencies": {
32
- "ink@6.2.3": "patches/ink@6.2.3.patch"
24
+ "publishConfig": {
25
+ "access": "public"
33
26
  }
34
27
  }
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('node:fs')
4
+ const os = require('node:os')
5
+ const path = require('node:path')
6
+
7
+ const skillName = 'tela-cli'
8
+ const metadataFile = '.tela-cli-skill.json'
9
+ const managedSource = '@meistrari/tela-cli'
10
+ const sourceDir = path.resolve(__dirname, '..', 'skills', skillName)
11
+ const quiet = process.argv.includes('--quiet')
12
+ const json = process.argv.includes('--json')
13
+
14
+ function homeDir() {
15
+ return process.env.HOME || os.homedir()
16
+ }
17
+
18
+ function targetRoots() {
19
+ return [
20
+ path.join(homeDir(), '.agents', 'skills'),
21
+ path.join(homeDir(), '.claude', 'skills'),
22
+ ]
23
+ }
24
+
25
+ function readJson(filePath) {
26
+ try {
27
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'))
28
+ } catch {
29
+ return null
30
+ }
31
+ }
32
+
33
+ function isManagedInstall(targetDir) {
34
+ const metadata = readJson(path.join(targetDir, metadataFile))
35
+ return metadata?.managedBy === managedSource && metadata?.skillName === skillName
36
+ }
37
+
38
+ function copySkill(targetDir) {
39
+ const parentDir = path.dirname(targetDir)
40
+ fs.mkdirSync(parentDir, { recursive: true })
41
+
42
+ const tempDir = fs.mkdtempSync(path.join(parentDir, `.${skillName}-tmp-`))
43
+ const backupDir = path.join(parentDir, `.${skillName}-backup-${process.pid}-${Date.now()}`)
44
+ let movedExisting = false
45
+
46
+ try {
47
+ fs.cpSync(sourceDir, tempDir, { recursive: true })
48
+ fs.writeFileSync(path.join(tempDir, metadataFile), `${JSON.stringify({
49
+ managedBy: managedSource,
50
+ skillName,
51
+ installedAt: new Date().toISOString(),
52
+ sourceDir,
53
+ }, null, 2)}\n`)
54
+
55
+ if (fs.existsSync(targetDir)) {
56
+ fs.renameSync(targetDir, backupDir)
57
+ movedExisting = true
58
+ }
59
+ fs.renameSync(tempDir, targetDir)
60
+ fs.rmSync(backupDir, { recursive: true, force: true })
61
+ } catch (error) {
62
+ fs.rmSync(tempDir, { recursive: true, force: true })
63
+ if (movedExisting && !fs.existsSync(targetDir) && fs.existsSync(backupDir)) {
64
+ fs.renameSync(backupDir, targetDir)
65
+ }
66
+ throw error
67
+ }
68
+ }
69
+
70
+ function install() {
71
+ if (process.env.TELA_CLI_SKIP_SKILL_INSTALL === '1') {
72
+ return {
73
+ ok: true,
74
+ skipped: true,
75
+ reason: 'TELA_CLI_SKIP_SKILL_INSTALL=1',
76
+ targets: [],
77
+ }
78
+ }
79
+
80
+ if (!fs.existsSync(path.join(sourceDir, 'SKILL.md'))) {
81
+ return {
82
+ ok: false,
83
+ error: `Bundled skill source is missing: ${sourceDir}`,
84
+ targets: [],
85
+ }
86
+ }
87
+
88
+ const targets = targetRoots().map((root) => {
89
+ const targetDir = path.join(root, skillName)
90
+ const exists = fs.existsSync(targetDir)
91
+
92
+ if (exists && !isManagedInstall(targetDir)) {
93
+ return {
94
+ targetDir,
95
+ status: 'skipped',
96
+ reason: 'existing unmanaged skill folder',
97
+ }
98
+ }
99
+
100
+ copySkill(targetDir)
101
+ return {
102
+ targetDir,
103
+ status: exists ? 'updated' : 'installed',
104
+ }
105
+ })
106
+
107
+ return {
108
+ ok: true,
109
+ skillName,
110
+ targets,
111
+ }
112
+ }
113
+
114
+ const result = install()
115
+
116
+ if (json) {
117
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`)
118
+ } else if (!quiet) {
119
+ for (const target of result.targets || []) {
120
+ process.stdout.write(`${target.status}: ${target.targetDir}${target.reason ? ` (${target.reason})` : ''}\n`)
121
+ }
122
+ }
123
+
124
+ if (!result.ok) {
125
+ if (!quiet && result.error) process.stderr.write(`${result.error}\n`)
126
+ process.exitCode = 1
127
+ }
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: tela-cli
3
+ description: Use when a coding agent needs to operate Tela Agent repositories through the local `tela` CLI with non-interactive, flag-driven commands and JSON output.
4
+ ---
5
+
6
+ # Tela CLI
7
+
8
+ Use the local `tela` binary for Tela Agent repository workflows. Prefer explicit
9
+ flags and `--json` so commands are safe in non-interactive agent sessions.
10
+
11
+ ## Subpaths
12
+
13
+ - Agent workflows: read `references/agent.md` before running `tela agent ...`.
14
+
15
+ ## Core Rules
16
+
17
+ - Use `tela agent ...` commands, not legacy top-level `sync`, `run`, `push`, or `feedback`.
18
+ - Prefer `--json` for machine-readable output and errors.
19
+ - Do not rely on prompts in coding-agent sessions; pass every required value by flag.
20
+ - Do not print token material. Use `tela auth token --json` for metadata and `--raw` only when a shell command explicitly needs the token.
@@ -0,0 +1,111 @@
1
+ # Tela Agent CLI
2
+
3
+ Use these commands from a repository checkout unless the command says otherwise.
4
+ Add `--json` whenever you need structured output.
5
+
6
+ ## Setup
7
+
8
+ Inspect valid setup choices:
9
+
10
+ ```bash
11
+ tela agent setup --list-options --context production/foundation --json
12
+ ```
13
+
14
+ Validate setup without provisioning or writing config:
15
+
16
+ ```bash
17
+ tela agent setup \
18
+ --context production/foundation \
19
+ --organization acme \
20
+ --clone-root "$HOME/tela-agents" \
21
+ --ssh-public-key "$HOME/.ssh/id_ed25519.pub" \
22
+ --ssh-private-key "$HOME/.ssh/id_ed25519" \
23
+ --dry-run \
24
+ --json
25
+ ```
26
+
27
+ Complete setup by removing `--dry-run`. This provisions the Forgejo user and
28
+ saves Agent setup metadata in the shared Tela local config.
29
+
30
+ ## Sync
31
+
32
+ Preview repository sync:
33
+
34
+ ```bash
35
+ tela agent sync agent-api --dry-run --json
36
+ tela agent sync --current --dry-run --json
37
+ tela agent sync --all --dry-run --json
38
+ ```
39
+
40
+ Run without `--dry-run` only after checking the plan. `--current` must be run
41
+ inside a git checkout. `--all` operates on the configured clone root.
42
+
43
+ ## Run
44
+
45
+ Run one-shot, non-interactively:
46
+
47
+ ```bash
48
+ tela agent run \
49
+ --mode one-shot \
50
+ --input caderno_teses=./brief.docx \
51
+ --input-conflict fail \
52
+ --json
53
+ ```
54
+
55
+ Input assignment format is `variable=path`, where `variable` is a first-level
56
+ folder under `input/`. Conflict modes:
57
+
58
+ - `fail`: default; exits before running Claude if the destination exists.
59
+ - `overwrite`: replaces the existing staged input.
60
+ - `rename`: uses the CLI suggested destination name.
61
+
62
+ Avoid `--mode chat` in coding-agent sessions because chat mode requires an
63
+ interactive terminal and cannot be combined with `--json`.
64
+
65
+ ## Push
66
+
67
+ Preview commit and push:
68
+
69
+ ```bash
70
+ tela agent push --message "feat: update agent behavior" --dry-run --json
71
+ ```
72
+
73
+ Push after checking the dry run:
74
+
75
+ ```bash
76
+ tela agent push --message "feat: update agent behavior" --json
77
+ ```
78
+
79
+ Use `--message` for agent sessions. `--claude` asks the local Claude CLI to
80
+ write a message, and `--manual` relies on fallback behavior.
81
+
82
+ ## Feedback
83
+
84
+ List feedback for the current commit:
85
+
86
+ ```bash
87
+ tela agent feedback --list --json
88
+ ```
89
+
90
+ Apply all actionable feedback:
91
+
92
+ ```bash
93
+ tela agent feedback --apply all --json
94
+ ```
95
+
96
+ Apply selected actionable feedback ids without prompts:
97
+
98
+ ```bash
99
+ tela agent feedback --apply select --feedback-id 1 --feedback-id 3 --json
100
+ ```
101
+
102
+ Only use ids where the `feedbacks[].actionable` value from `--list --json` is
103
+ `true`.
104
+
105
+ ## Guardrails
106
+
107
+ - Run `tela doctor auth --json` before agent workflows if credentials look stale.
108
+ - Use `tela context current --json` and `tela context list --json` to inspect the active context.
109
+ - Use `tela context use <context-id> --json` only when you intentionally want to mutate the active context.
110
+ - Treat non-JSON output as human display text; parse JSON only.
111
+ - Stop on `ok: false` or a non-zero exit code and inspect `error.code`, `error.summary`, and `error.fixes`.
package/cli.ts DELETED
@@ -1,25 +0,0 @@
1
- #!/usr/bin/env bun
2
-
3
- import { renderUserFacingError, serializeError, toUserFacingError } from './src/errors.ts'
4
- import { main } from './src/program.ts'
5
-
6
- function hasFlag(argv: string[], flag: string): boolean {
7
- return argv.includes(flag)
8
- }
9
-
10
- try {
11
- await main(process.argv)
12
- }
13
- catch (error) {
14
- if (hasFlag(process.argv, '--json')) {
15
- process.stderr.write(`${JSON.stringify(serializeError(error), null, 2)}\n`)
16
- }
17
- else {
18
- process.stderr.write(`${renderUserFacingError(error, {
19
- decorate: Boolean(process.stderr.isTTY),
20
- verbose: hasFlag(process.argv, '--verbose'),
21
- })}\n`)
22
- }
23
-
24
- process.exitCode = toUserFacingError(error).exitCode
25
- }
package/postinstall.sh DELETED
@@ -1,19 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -e
3
-
4
- ZSHRC="$HOME/.zshrc"
5
- PKG_DIR="$(cd "$(dirname "$0")" && pwd)"
6
- ALIAS_LINE="alias tela='bun run $PKG_DIR/cli.ts'"
7
- MARKER="# tela-cli"
8
-
9
- if [ ! -f "$ZSHRC" ]; then
10
- touch "$ZSHRC"
11
- fi
12
-
13
- # Remove any previous tela-cli entry
14
- sed -i '' "/$MARKER/d" "$ZSHRC" 2>/dev/null || sed -i "/$MARKER/d" "$ZSHRC" 2>/dev/null || true
15
-
16
- echo "$ALIAS_LINE $MARKER" >> "$ZSHRC"
17
-
18
- echo "tela command added to $ZSHRC"
19
- echo "Run 'source ~/.zshrc' or open a new terminal to use 'tela'"
package/src/agent-api.ts DELETED
@@ -1,300 +0,0 @@
1
- import { buildAgentApiHeaders, type FetchLike } from './auth.ts'
2
- import type {
3
- AgentRepoSummary,
4
- AvailableRepositorySummary,
5
- AgentFeedbackItem,
6
- AgentFeedbackListResponse,
7
- ForgejoUserCreateResponse,
8
- ForgejoUserSshKeyInput,
9
- OrganizationListResponse,
10
- OrganizationSummary,
11
- RepositoryListItemResponse,
12
- RepositoryListResponse,
13
- RepositoryLookupResponse,
14
- TelaCliConfig,
15
- TelaCliForgejoOrganization,
16
- } from './types.ts'
17
-
18
- const DEFAULT_TIMEOUT_MS = 10_000
19
-
20
- function joinUrl(baseUrl: string, path: string): string {
21
- return new URL(path, baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`).toString()
22
- }
23
-
24
- function parseJsonBody(responseText: string): unknown {
25
- try {
26
- return responseText ? JSON.parse(responseText) as unknown : null
27
- }
28
- catch {
29
- return null
30
- }
31
- }
32
-
33
- function isFeedbackItem(value: unknown): value is AgentFeedbackItem {
34
- if (!value || typeof value !== 'object') {
35
- return false
36
- }
37
-
38
- const candidate = value as Partial<AgentFeedbackItem>
39
- return (candidate.status === 'success' || candidate.status === 'failed')
40
- && typeof candidate.reason === 'string'
41
- && typeof candidate.suggestion === 'string'
42
- }
43
-
44
- function isForgejoOrganization(value: unknown): value is TelaCliForgejoOrganization {
45
- if (!value || typeof value !== 'object') {
46
- return false
47
- }
48
-
49
- const candidate = value as Partial<TelaCliForgejoOrganization>
50
- return typeof candidate.id === 'string' && typeof candidate.name === 'string'
51
- }
52
-
53
- function isOrganizationSummary(value: unknown): value is OrganizationSummary {
54
- if (!value || typeof value !== 'object') {
55
- return false
56
- }
57
-
58
- const candidate = value as Partial<OrganizationSummary>
59
- return typeof candidate.id === 'string'
60
- && typeof candidate.workspaceId === 'string'
61
- && typeof candidate.name === 'string'
62
- }
63
-
64
- function isAgentRepoSummary(value: unknown): value is AgentRepoSummary {
65
- if (!value || typeof value !== 'object') {
66
- return false
67
- }
68
-
69
- const candidate = value as Partial<AgentRepoSummary>
70
- return typeof candidate.id === 'string'
71
- && typeof candidate.workspaceId === 'string'
72
- && typeof candidate.organizationId === 'string'
73
- && typeof candidate.repository === 'string'
74
- }
75
-
76
- function isRepositoryListItemResponse(value: unknown): value is RepositoryListItemResponse {
77
- if (!value || typeof value !== 'object') {
78
- return false
79
- }
80
-
81
- const candidate = value as Partial<RepositoryListItemResponse>
82
- return isOrganizationSummary(candidate.organization)
83
- && isAgentRepoSummary(candidate.agentRepo)
84
- }
85
-
86
- export class AgentApiError extends Error {
87
- constructor(
88
- message: string,
89
- public readonly status: number,
90
- public readonly responseBody: string,
91
- ) {
92
- super(message)
93
- }
94
- }
95
-
96
- export async function fetchRepositoryLookup(
97
- repository: string,
98
- config: TelaCliConfig,
99
- fetchFn: FetchLike = fetch,
100
- ): Promise<Required<Pick<RepositoryLookupResponse, 'organization' | 'agentRepo' | 'forgejoRepository'>> & { success: true }> {
101
- const headers = await buildAgentApiHeaders(config, { fetchFn })
102
- const response = await fetchFn(
103
- joinUrl(config.agentApiUrl, `/v3/agents/repositories/${encodeURIComponent(repository)}`),
104
- {
105
- method: 'GET',
106
- headers,
107
- signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS),
108
- },
109
- )
110
-
111
- const responseText = await response.text()
112
- const payload = parseJsonBody(responseText) as RepositoryLookupResponse | null
113
-
114
- if (!response.ok) {
115
- throw new AgentApiError(
116
- payload?.error ?? `Agent API lookup failed with status ${response.status}`,
117
- response.status,
118
- responseText,
119
- )
120
- }
121
-
122
- if (!payload?.success || !payload.organization || !payload.agentRepo || !payload.forgejoRepository) {
123
- throw new AgentApiError('Agent API lookup returned an invalid payload', response.status, responseText)
124
- }
125
-
126
- return {
127
- success: true,
128
- organization: payload.organization,
129
- agentRepo: payload.agentRepo,
130
- forgejoRepository: payload.forgejoRepository,
131
- }
132
- }
133
-
134
- export async function fetchCommitFeedback(
135
- organizationName: string,
136
- repository: string,
137
- commitHash: string,
138
- config: TelaCliConfig,
139
- fetchFn: FetchLike = fetch,
140
- ): Promise<AgentFeedbackListResponse> {
141
- const headers = await buildAgentApiHeaders(config, { fetchFn })
142
- const response = await fetchFn(
143
- joinUrl(
144
- config.agentApiUrl,
145
- `/v3/agents/${encodeURIComponent(organizationName)}/${encodeURIComponent(repository)}/feedback?commitHash=${encodeURIComponent(commitHash)}`,
146
- ),
147
- {
148
- method: 'GET',
149
- headers,
150
- signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS),
151
- },
152
- )
153
-
154
- const responseText = await response.text()
155
- const payload = parseJsonBody(responseText) as Partial<AgentFeedbackListResponse> & { error?: string } | null
156
-
157
- if (!response.ok) {
158
- throw new AgentApiError(
159
- payload?.error ?? `Agent API feedback lookup failed with status ${response.status}`,
160
- response.status,
161
- responseText,
162
- )
163
- }
164
-
165
- if (!payload
166
- || typeof payload.commitHash !== 'string'
167
- || payload.commitHash !== commitHash
168
- || !Array.isArray(payload.feedbacks)
169
- || !payload.feedbacks.every(isFeedbackItem)) {
170
- throw new AgentApiError('Agent API feedback lookup returned an invalid payload', response.status, responseText)
171
- }
172
-
173
- return {
174
- commitHash: payload.commitHash,
175
- feedbacks: payload.feedbacks,
176
- }
177
- }
178
-
179
- export async function listOrganizations(
180
- config: TelaCliConfig,
181
- fetchFn: FetchLike = fetch,
182
- ): Promise<TelaCliForgejoOrganization[]> {
183
- const headers = await buildAgentApiHeaders(config, { fetchFn })
184
- const response = await fetchFn(
185
- joinUrl(config.agentApiUrl, '/v3/organizations'),
186
- {
187
- method: 'GET',
188
- headers,
189
- signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS),
190
- },
191
- )
192
-
193
- const responseText = await response.text()
194
- const payload = parseJsonBody(responseText) as OrganizationListResponse | null
195
-
196
- if (!response.ok) {
197
- throw new AgentApiError(
198
- payload?.error ?? `Agent API organization lookup failed with status ${response.status}`,
199
- response.status,
200
- responseText,
201
- )
202
- }
203
-
204
- if (!payload
205
- || payload.success !== true
206
- || !Array.isArray(payload.organizations)
207
- || !payload.organizations.every(isForgejoOrganization)) {
208
- throw new AgentApiError('Agent API organization lookup returned an invalid payload', response.status, responseText)
209
- }
210
-
211
- return payload.organizations
212
- }
213
-
214
- export async function listAvailableRepositories(
215
- config: TelaCliConfig,
216
- fetchFn: FetchLike = fetch,
217
- ): Promise<AvailableRepositorySummary[]> {
218
- const headers = await buildAgentApiHeaders(config, { fetchFn })
219
- const response = await fetchFn(
220
- joinUrl(config.agentApiUrl, '/v3/agents/repositories'),
221
- {
222
- method: 'GET',
223
- headers,
224
- signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS),
225
- },
226
- )
227
-
228
- const responseText = await response.text()
229
- const payload = parseJsonBody(responseText) as RepositoryListResponse | null
230
-
231
- if (!response.ok) {
232
- throw new AgentApiError(
233
- payload?.error ?? `Agent API repository listing failed with status ${response.status}`,
234
- response.status,
235
- responseText,
236
- )
237
- }
238
-
239
- if (!payload
240
- || payload.success !== true
241
- || !Array.isArray(payload.repositories)
242
- || !payload.repositories.every(isRepositoryListItemResponse)) {
243
- throw new AgentApiError('Agent API repository listing returned an invalid payload', response.status, responseText)
244
- }
245
-
246
- return payload.repositories.map(repository => ({
247
- ...repository,
248
- syncStatus: 'available' as const,
249
- }))
250
- }
251
-
252
- export async function provisionForgejoUser(
253
- input: {
254
- organizationName: string
255
- sshKey: ForgejoUserSshKeyInput
256
- },
257
- config: TelaCliConfig,
258
- fetchFn: FetchLike = fetch,
259
- ): Promise<ForgejoUserCreateResponse> {
260
- const headers = await buildAgentApiHeaders(config, { fetchFn })
261
- const response = await fetchFn(
262
- joinUrl(config.agentApiUrl, '/v3/forgejo/users'),
263
- {
264
- method: 'POST',
265
- headers: {
266
- ...headers,
267
- 'Content-Type': 'application/json',
268
- },
269
- body: JSON.stringify({
270
- organizationName: input.organizationName,
271
- sshKey: input.sshKey,
272
- }),
273
- signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS),
274
- },
275
- )
276
-
277
- const responseText = await response.text()
278
- const payload = parseJsonBody(responseText) as ForgejoUserCreateResponse | null
279
-
280
- if (!response.ok) {
281
- throw new AgentApiError(
282
- payload?.error ?? `Agent API Forgejo user provisioning failed with status ${response.status}`,
283
- response.status,
284
- responseText,
285
- )
286
- }
287
-
288
- if (!payload
289
- || payload.success !== true
290
- || typeof payload.username !== 'string'
291
- || typeof payload.organizationName !== 'string'
292
- || typeof payload.teamName !== 'string'
293
- || typeof payload.userCreated !== 'boolean'
294
- || typeof payload.teamCreated !== 'boolean'
295
- || typeof payload.sshKeyCreated !== 'boolean') {
296
- throw new AgentApiError('Agent API Forgejo user provisioning returned an invalid payload', response.status, responseText)
297
- }
298
-
299
- return payload
300
- }
package/src/assets.d.ts DELETED
@@ -1,4 +0,0 @@
1
- declare module '*.mp3' {
2
- const assetPath: string
3
- export default assetPath
4
- }