@ricsam/r5d-api 0.0.1 → 0.0.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/README.md CHANGED
@@ -1,45 +1,68 @@
1
1
  # @ricsam/r5d-api
2
2
 
3
- ## ⚠️ IMPORTANT NOTICE ⚠️
4
-
5
- **This package is created solely for the purpose of setting up OIDC (OpenID Connect) trusted publishing with npm.**
6
-
7
- This is **NOT** a functional package and contains **NO** code or functionality beyond the OIDC setup configuration.
8
-
9
- ## Purpose
10
-
11
- This package exists to:
12
- 1. Configure OIDC trusted publishing for the package name `@ricsam/r5d-api`
13
- 2. Enable secure, token-less publishing from CI/CD workflows
14
- 3. Establish provenance for packages published under this name
15
-
16
- ## What is OIDC Trusted Publishing?
17
-
18
- OIDC trusted publishing allows package maintainers to publish packages directly from their CI/CD workflows without needing to manage npm access tokens. Instead, it uses OpenID Connect to establish trust between the CI/CD provider (like GitHub Actions) and npm.
19
-
20
- ## Setup Instructions
21
-
22
- To properly configure OIDC trusted publishing for this package:
23
-
24
- 1. Go to [npmjs.com](https://www.npmjs.com/) and navigate to your package settings
25
- 2. Configure the trusted publisher (e.g., GitHub Actions)
26
- 3. Specify the repository and workflow that should be allowed to publish
27
- 4. Use the configured workflow to publish your actual package
28
-
29
- ## DO NOT USE THIS PACKAGE
30
-
31
- This package is a placeholder for OIDC configuration only. It:
32
- - Contains no executable code
33
- - Provides no functionality
34
- - Should not be installed as a dependency
35
- - Exists only for administrative purposes
36
-
37
- ## More Information
38
-
39
- For more details about npm's trusted publishing feature, see:
40
- - [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
41
- - [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
42
-
43
- ---
44
-
45
- **Maintained for OIDC setup purposes only**
3
+ Typed Node.js API client for the r5d.dev CLI backend surface.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @ricsam/r5d-api
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```ts
14
+ import { BinctlClient } from "@ricsam/r5d-api";
15
+
16
+ const client = new BinctlClient({
17
+ baseUrl: "https://r5d.dev",
18
+ token: process.env.BINCTL_TOKEN,
19
+ // or apiKey: process.env.BINCTL_API_KEY
20
+ });
21
+
22
+ const projects = await client.projects.list();
23
+ console.log(projects);
24
+ ```
25
+
26
+ ## Auth
27
+
28
+ `BinctlClient` supports:
29
+ - interactive token (`bin_tok_*`)
30
+ - API key (`bin_key_*`)
31
+
32
+ Set either `token` or `apiKey` in client options, or later via:
33
+ - `client.setToken(...)`
34
+ - `client.setApiKey(...)`
35
+
36
+ Trusted server-side callers that authenticate through custom headers, such as a session cookie, can pass `headers` with `authMode: "headers"`.
37
+
38
+ ## Main API Surface
39
+
40
+ - `auth.loginStart()`
41
+ - `auth.loginPoll(requestId, { pollCode })`
42
+ - `auth.status()`
43
+ - `auth.logout()`
44
+ - `auth.apiKeys.create/list/revoke`
45
+ - `projects.list()`
46
+ - `projects.create({ name?, orgId? })`
47
+ - `projects.describe(projectRef)`
48
+ - `projects.update(projectRef, { name?, mode? })`
49
+ - `projects.delete(projectRef)`
50
+ - `projects.branches.list/describe(projectRef, ...)`
51
+ - `projects.sessions.list(projectRef, { branch? })`
52
+ - `projects.sessions.create(projectRef, { branchName, name? })`
53
+ - `sessions.describe(sessionId)`
54
+ - `sessions.update(sessionId, { name })`
55
+ - `sessions.delete(sessionId)`
56
+ - `sessions.conversation(sessionId)`
57
+ - `sessions.prompt(sessionId, { message, mode, model })`
58
+ - `sessions.answerQuestions(sessionId, { answers })`
59
+ - `sessions.applyRequiredEnvs(sessionId, { envs })`
60
+
61
+ ## Errors
62
+
63
+ Non-2xx responses throw `BinctlApiError` with:
64
+ - `status`
65
+ - `path`
66
+ - `body`
67
+
68
+ Project responses expose `mode: "greenfield" | "prod"`, derived from the database-backed `projects.backwardsCompatible` flag.
@@ -0,0 +1,257 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var index_exports = {};
20
+ __export(index_exports, {
21
+ BinctlApiError: () => BinctlApiError,
22
+ BinctlClient: () => BinctlClient
23
+ });
24
+ module.exports = __toCommonJS(index_exports);
25
+ class BinctlApiError extends Error {
26
+ status;
27
+ path;
28
+ body;
29
+ constructor(message, input) {
30
+ super(message);
31
+ this.name = "BinctlApiError";
32
+ this.status = input.status;
33
+ this.path = input.path;
34
+ this.body = input.body;
35
+ }
36
+ }
37
+ function normalizeBaseUrl(url) {
38
+ return url.endsWith("/") ? url.slice(0, -1) : url;
39
+ }
40
+ function withQuery(path, query) {
41
+ if (!query) {
42
+ return path;
43
+ }
44
+ const params = new URLSearchParams();
45
+ for (const [key, value] of Object.entries(query)) {
46
+ if (value === void 0) continue;
47
+ params.set(key, value);
48
+ }
49
+ const queryString = params.toString();
50
+ return queryString.length > 0 ? `${path}?${queryString}` : path;
51
+ }
52
+ class BinctlClient {
53
+ fetchImpl;
54
+ baseUrl;
55
+ token;
56
+ apiKey;
57
+ extraHeaders;
58
+ authMode;
59
+ constructor(options = {}) {
60
+ this.fetchImpl = options.fetch ?? fetch;
61
+ this.baseUrl = normalizeBaseUrl(options.baseUrl ?? "https://r5d.dev");
62
+ this.token = options.token;
63
+ this.apiKey = options.apiKey;
64
+ this.extraHeaders = options.headers ?? {};
65
+ this.authMode = options.authMode ?? "bearer";
66
+ }
67
+ setBaseUrl(baseUrl) {
68
+ this.baseUrl = normalizeBaseUrl(baseUrl);
69
+ }
70
+ setToken(token) {
71
+ this.token = token;
72
+ }
73
+ setApiKey(apiKey) {
74
+ this.apiKey = apiKey;
75
+ }
76
+ resolveBearerToken() {
77
+ return this.token ?? this.apiKey;
78
+ }
79
+ async request(input) {
80
+ const authMode = input.auth ?? "auto";
81
+ const bearerToken = this.resolveBearerToken();
82
+ const headers = {
83
+ ...this.extraHeaders,
84
+ Accept: "application/json"
85
+ };
86
+ if (authMode === "auto") {
87
+ if (!bearerToken) {
88
+ if (this.authMode !== "headers") {
89
+ throw new BinctlApiError("Authentication required. Set token or apiKey in BinctlClient.", {
90
+ status: 401,
91
+ path: input.path,
92
+ body: { error: "Missing credentials" }
93
+ });
94
+ }
95
+ } else {
96
+ headers.Authorization = `Bearer ${bearerToken}`;
97
+ }
98
+ }
99
+ const hasBody = input.body !== void 0;
100
+ if (hasBody) {
101
+ headers["Content-Type"] = "application/json";
102
+ }
103
+ const pathWithQuery = withQuery(input.path, input.query);
104
+ const response = await this.fetchImpl(`${this.baseUrl}${pathWithQuery}`, {
105
+ method: input.method,
106
+ headers,
107
+ body: hasBody ? JSON.stringify(input.body) : void 0
108
+ });
109
+ const text = await response.text();
110
+ const payload = text.length > 0 ? safeJsonParse(text) : null;
111
+ if (!response.ok) {
112
+ const message = typeof payload === "object" && payload && "error" in payload && typeof payload.error === "string" ? payload.error : `Request failed (${response.status})`;
113
+ throw new BinctlApiError(message, {
114
+ status: response.status,
115
+ path: pathWithQuery,
116
+ body: payload
117
+ });
118
+ }
119
+ return payload;
120
+ }
121
+ auth = {
122
+ loginStart: (input) => this.request({
123
+ method: "POST",
124
+ path: "/api/binctl/auth/login/start",
125
+ auth: "none",
126
+ body: {
127
+ baseUrl: input?.baseUrl
128
+ }
129
+ }),
130
+ loginPoll: (requestId, input) => this.request({
131
+ method: "GET",
132
+ path: `/api/binctl/auth/login/poll/${encodeURIComponent(requestId)}`,
133
+ auth: "none",
134
+ query: {
135
+ pollCode: input.pollCode
136
+ }
137
+ }),
138
+ logout: () => this.request({
139
+ method: "POST",
140
+ path: "/api/binctl/auth/logout",
141
+ body: {}
142
+ }),
143
+ status: () => this.request({
144
+ method: "GET",
145
+ path: "/api/binctl/auth/status"
146
+ }),
147
+ apiKeys: {
148
+ create: (input) => this.request({
149
+ method: "POST",
150
+ path: "/api/binctl/auth/api-keys",
151
+ body: input
152
+ }),
153
+ list: () => this.request({
154
+ method: "GET",
155
+ path: "/api/binctl/auth/api-keys"
156
+ }),
157
+ revoke: (keyId) => this.request({
158
+ method: "DELETE",
159
+ path: `/api/binctl/auth/api-keys/${encodeURIComponent(keyId)}`
160
+ })
161
+ }
162
+ };
163
+ projects = {
164
+ list: () => this.request({
165
+ method: "GET",
166
+ path: "/api/binctl/projects"
167
+ }),
168
+ create: (input = {}) => this.request({
169
+ method: "POST",
170
+ path: "/api/binctl/projects",
171
+ body: input
172
+ }),
173
+ describe: (projectRef) => this.request({
174
+ method: "GET",
175
+ path: `/api/binctl/projects/${encodeURIComponent(projectRef)}`
176
+ }),
177
+ update: (projectRef, input) => this.request({
178
+ method: "PUT",
179
+ path: `/api/binctl/projects/${encodeURIComponent(projectRef)}`,
180
+ body: input
181
+ }),
182
+ delete: (projectRef) => this.request({
183
+ method: "DELETE",
184
+ path: `/api/binctl/projects/${encodeURIComponent(projectRef)}`
185
+ }),
186
+ branches: {
187
+ list: (projectRef) => this.request({
188
+ method: "GET",
189
+ path: `/api/binctl/projects/${encodeURIComponent(projectRef)}/branches`
190
+ }),
191
+ describe: (projectRef, branch) => this.request({
192
+ method: "GET",
193
+ path: `/api/binctl/projects/${encodeURIComponent(projectRef)}/branches/${encodeURIComponent(branch)}`
194
+ })
195
+ },
196
+ sessions: {
197
+ list: (projectRef, input) => this.request({
198
+ method: "GET",
199
+ path: `/api/binctl/projects/${encodeURIComponent(projectRef)}/sessions`,
200
+ query: {
201
+ branch: input?.branch
202
+ }
203
+ }),
204
+ create: (projectRef, input) => this.request({
205
+ method: "POST",
206
+ path: `/api/binctl/projects/${encodeURIComponent(projectRef)}/sessions`,
207
+ body: input
208
+ })
209
+ }
210
+ };
211
+ sessions = {
212
+ describe: (sessionId) => this.request({
213
+ method: "GET",
214
+ path: `/api/binctl/sessions/${encodeURIComponent(sessionId)}`
215
+ }),
216
+ update: (sessionId, input) => this.request({
217
+ method: "PUT",
218
+ path: `/api/binctl/sessions/${encodeURIComponent(sessionId)}`,
219
+ body: input
220
+ }),
221
+ delete: (sessionId) => this.request({
222
+ method: "DELETE",
223
+ path: `/api/binctl/sessions/${encodeURIComponent(sessionId)}`
224
+ }),
225
+ conversation: (sessionId) => this.request({
226
+ method: "GET",
227
+ path: `/api/binctl/sessions/${encodeURIComponent(sessionId)}/conversation`
228
+ }),
229
+ prompt: (sessionId, input) => this.request({
230
+ method: "POST",
231
+ path: `/api/binctl/sessions/${encodeURIComponent(sessionId)}/prompt`,
232
+ body: input
233
+ }),
234
+ answerQuestions: (sessionId, input) => this.request({
235
+ method: "POST",
236
+ path: `/api/binctl/sessions/${encodeURIComponent(sessionId)}/answer-questions`,
237
+ body: input
238
+ }),
239
+ applyRequiredEnvs: (sessionId, input) => this.request({
240
+ method: "POST",
241
+ path: `/api/binctl/sessions/${encodeURIComponent(sessionId)}/apply-required-envs`,
242
+ body: input
243
+ })
244
+ };
245
+ }
246
+ function safeJsonParse(text) {
247
+ try {
248
+ return JSON.parse(text);
249
+ } catch {
250
+ return { raw: text };
251
+ }
252
+ }
253
+ // Annotate the CommonJS export names for ESM import in node:
254
+ 0 && (module.exports = {
255
+ BinctlApiError,
256
+ BinctlClient
257
+ });
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "@ricsam/r5d-api",
3
+ "version": "0.0.3",
4
+ "type": "commonjs"
5
+ }
@@ -0,0 +1,232 @@
1
+ class BinctlApiError extends Error {
2
+ status;
3
+ path;
4
+ body;
5
+ constructor(message, input) {
6
+ super(message);
7
+ this.name = "BinctlApiError";
8
+ this.status = input.status;
9
+ this.path = input.path;
10
+ this.body = input.body;
11
+ }
12
+ }
13
+ function normalizeBaseUrl(url) {
14
+ return url.endsWith("/") ? url.slice(0, -1) : url;
15
+ }
16
+ function withQuery(path, query) {
17
+ if (!query) {
18
+ return path;
19
+ }
20
+ const params = new URLSearchParams();
21
+ for (const [key, value] of Object.entries(query)) {
22
+ if (value === void 0) continue;
23
+ params.set(key, value);
24
+ }
25
+ const queryString = params.toString();
26
+ return queryString.length > 0 ? `${path}?${queryString}` : path;
27
+ }
28
+ class BinctlClient {
29
+ fetchImpl;
30
+ baseUrl;
31
+ token;
32
+ apiKey;
33
+ extraHeaders;
34
+ authMode;
35
+ constructor(options = {}) {
36
+ this.fetchImpl = options.fetch ?? fetch;
37
+ this.baseUrl = normalizeBaseUrl(options.baseUrl ?? "https://r5d.dev");
38
+ this.token = options.token;
39
+ this.apiKey = options.apiKey;
40
+ this.extraHeaders = options.headers ?? {};
41
+ this.authMode = options.authMode ?? "bearer";
42
+ }
43
+ setBaseUrl(baseUrl) {
44
+ this.baseUrl = normalizeBaseUrl(baseUrl);
45
+ }
46
+ setToken(token) {
47
+ this.token = token;
48
+ }
49
+ setApiKey(apiKey) {
50
+ this.apiKey = apiKey;
51
+ }
52
+ resolveBearerToken() {
53
+ return this.token ?? this.apiKey;
54
+ }
55
+ async request(input) {
56
+ const authMode = input.auth ?? "auto";
57
+ const bearerToken = this.resolveBearerToken();
58
+ const headers = {
59
+ ...this.extraHeaders,
60
+ Accept: "application/json"
61
+ };
62
+ if (authMode === "auto") {
63
+ if (!bearerToken) {
64
+ if (this.authMode !== "headers") {
65
+ throw new BinctlApiError("Authentication required. Set token or apiKey in BinctlClient.", {
66
+ status: 401,
67
+ path: input.path,
68
+ body: { error: "Missing credentials" }
69
+ });
70
+ }
71
+ } else {
72
+ headers.Authorization = `Bearer ${bearerToken}`;
73
+ }
74
+ }
75
+ const hasBody = input.body !== void 0;
76
+ if (hasBody) {
77
+ headers["Content-Type"] = "application/json";
78
+ }
79
+ const pathWithQuery = withQuery(input.path, input.query);
80
+ const response = await this.fetchImpl(`${this.baseUrl}${pathWithQuery}`, {
81
+ method: input.method,
82
+ headers,
83
+ body: hasBody ? JSON.stringify(input.body) : void 0
84
+ });
85
+ const text = await response.text();
86
+ const payload = text.length > 0 ? safeJsonParse(text) : null;
87
+ if (!response.ok) {
88
+ const message = typeof payload === "object" && payload && "error" in payload && typeof payload.error === "string" ? payload.error : `Request failed (${response.status})`;
89
+ throw new BinctlApiError(message, {
90
+ status: response.status,
91
+ path: pathWithQuery,
92
+ body: payload
93
+ });
94
+ }
95
+ return payload;
96
+ }
97
+ auth = {
98
+ loginStart: (input) => this.request({
99
+ method: "POST",
100
+ path: "/api/binctl/auth/login/start",
101
+ auth: "none",
102
+ body: {
103
+ baseUrl: input?.baseUrl
104
+ }
105
+ }),
106
+ loginPoll: (requestId, input) => this.request({
107
+ method: "GET",
108
+ path: `/api/binctl/auth/login/poll/${encodeURIComponent(requestId)}`,
109
+ auth: "none",
110
+ query: {
111
+ pollCode: input.pollCode
112
+ }
113
+ }),
114
+ logout: () => this.request({
115
+ method: "POST",
116
+ path: "/api/binctl/auth/logout",
117
+ body: {}
118
+ }),
119
+ status: () => this.request({
120
+ method: "GET",
121
+ path: "/api/binctl/auth/status"
122
+ }),
123
+ apiKeys: {
124
+ create: (input) => this.request({
125
+ method: "POST",
126
+ path: "/api/binctl/auth/api-keys",
127
+ body: input
128
+ }),
129
+ list: () => this.request({
130
+ method: "GET",
131
+ path: "/api/binctl/auth/api-keys"
132
+ }),
133
+ revoke: (keyId) => this.request({
134
+ method: "DELETE",
135
+ path: `/api/binctl/auth/api-keys/${encodeURIComponent(keyId)}`
136
+ })
137
+ }
138
+ };
139
+ projects = {
140
+ list: () => this.request({
141
+ method: "GET",
142
+ path: "/api/binctl/projects"
143
+ }),
144
+ create: (input = {}) => this.request({
145
+ method: "POST",
146
+ path: "/api/binctl/projects",
147
+ body: input
148
+ }),
149
+ describe: (projectRef) => this.request({
150
+ method: "GET",
151
+ path: `/api/binctl/projects/${encodeURIComponent(projectRef)}`
152
+ }),
153
+ update: (projectRef, input) => this.request({
154
+ method: "PUT",
155
+ path: `/api/binctl/projects/${encodeURIComponent(projectRef)}`,
156
+ body: input
157
+ }),
158
+ delete: (projectRef) => this.request({
159
+ method: "DELETE",
160
+ path: `/api/binctl/projects/${encodeURIComponent(projectRef)}`
161
+ }),
162
+ branches: {
163
+ list: (projectRef) => this.request({
164
+ method: "GET",
165
+ path: `/api/binctl/projects/${encodeURIComponent(projectRef)}/branches`
166
+ }),
167
+ describe: (projectRef, branch) => this.request({
168
+ method: "GET",
169
+ path: `/api/binctl/projects/${encodeURIComponent(projectRef)}/branches/${encodeURIComponent(branch)}`
170
+ })
171
+ },
172
+ sessions: {
173
+ list: (projectRef, input) => this.request({
174
+ method: "GET",
175
+ path: `/api/binctl/projects/${encodeURIComponent(projectRef)}/sessions`,
176
+ query: {
177
+ branch: input?.branch
178
+ }
179
+ }),
180
+ create: (projectRef, input) => this.request({
181
+ method: "POST",
182
+ path: `/api/binctl/projects/${encodeURIComponent(projectRef)}/sessions`,
183
+ body: input
184
+ })
185
+ }
186
+ };
187
+ sessions = {
188
+ describe: (sessionId) => this.request({
189
+ method: "GET",
190
+ path: `/api/binctl/sessions/${encodeURIComponent(sessionId)}`
191
+ }),
192
+ update: (sessionId, input) => this.request({
193
+ method: "PUT",
194
+ path: `/api/binctl/sessions/${encodeURIComponent(sessionId)}`,
195
+ body: input
196
+ }),
197
+ delete: (sessionId) => this.request({
198
+ method: "DELETE",
199
+ path: `/api/binctl/sessions/${encodeURIComponent(sessionId)}`
200
+ }),
201
+ conversation: (sessionId) => this.request({
202
+ method: "GET",
203
+ path: `/api/binctl/sessions/${encodeURIComponent(sessionId)}/conversation`
204
+ }),
205
+ prompt: (sessionId, input) => this.request({
206
+ method: "POST",
207
+ path: `/api/binctl/sessions/${encodeURIComponent(sessionId)}/prompt`,
208
+ body: input
209
+ }),
210
+ answerQuestions: (sessionId, input) => this.request({
211
+ method: "POST",
212
+ path: `/api/binctl/sessions/${encodeURIComponent(sessionId)}/answer-questions`,
213
+ body: input
214
+ }),
215
+ applyRequiredEnvs: (sessionId, input) => this.request({
216
+ method: "POST",
217
+ path: `/api/binctl/sessions/${encodeURIComponent(sessionId)}/apply-required-envs`,
218
+ body: input
219
+ })
220
+ };
221
+ }
222
+ function safeJsonParse(text) {
223
+ try {
224
+ return JSON.parse(text);
225
+ } catch {
226
+ return { raw: text };
227
+ }
228
+ }
229
+ export {
230
+ BinctlApiError,
231
+ BinctlClient
232
+ };
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "@ricsam/r5d-api",
3
+ "version": "0.0.3",
4
+ "type": "module"
5
+ }
@@ -0,0 +1,211 @@
1
+ export type ChatMode = "ask" | "plan" | "build" | "agent" | "explore" | "review" | "test" | "research";
2
+ export type ModelTier = "low" | "medium" | "high" | "max";
3
+ export type BinctlProject = {
4
+ id: string;
5
+ slug: string | null;
6
+ name: string | null;
7
+ mode: "greenfield" | "prod";
8
+ createdAt: string;
9
+ updatedAt: string;
10
+ };
11
+ export type BinctlProjectDescription = BinctlProject & {
12
+ orgId: string | null;
13
+ };
14
+ export type BinctlBranch = {
15
+ branchName: string;
16
+ sessionCount: number;
17
+ lastSessionAt: string | null;
18
+ };
19
+ export type BinctlSessionSummary = {
20
+ id: string;
21
+ name: string | null;
22
+ branchName: string;
23
+ createdAt: string;
24
+ updatedAt: string;
25
+ };
26
+ export type BinctlSessionDescription = {
27
+ id: string;
28
+ projectId: string;
29
+ projectSlug: string | null;
30
+ projectName: string | null;
31
+ branchName: string;
32
+ name: string | null;
33
+ fixedMode?: ChatMode | null;
34
+ fixedTier?: ModelTier | null;
35
+ createdAt: string;
36
+ updatedAt: string;
37
+ };
38
+ export type BinctlPendingQuestionOption = {
39
+ id: string;
40
+ label: string;
41
+ description?: string;
42
+ };
43
+ export type BinctlPendingQuestion = {
44
+ id: string;
45
+ question: string;
46
+ allowMultiple?: boolean;
47
+ options: BinctlPendingQuestionOption[];
48
+ };
49
+ export type BinctlRequiredEnv = {
50
+ target: "backend" | "frontend";
51
+ name: string;
52
+ optional: boolean;
53
+ generateScript?: string;
54
+ description: string;
55
+ };
56
+ export type BinctlConversationResponse = {
57
+ session: BinctlSessionDescription;
58
+ conversation: unknown;
59
+ thread: unknown[];
60
+ pendingQuestions: BinctlPendingQuestion[];
61
+ requiredEnvs: BinctlRequiredEnv[];
62
+ };
63
+ export type BinctlLoginStartResponse = {
64
+ requestId: string;
65
+ pollCode: string;
66
+ loginUrl: string;
67
+ expiresAt: string;
68
+ intervalMs: number;
69
+ };
70
+ export type BinctlLoginPollResponse = {
71
+ status: "pending";
72
+ expiresAt: string;
73
+ intervalMs: number;
74
+ } | {
75
+ status: "approved";
76
+ token: string;
77
+ credentialId: string;
78
+ } | {
79
+ status: "expired" | "consumed";
80
+ };
81
+ export type BinctlAuthStatusResponse = {
82
+ authenticated: true;
83
+ source: "session" | "binctl";
84
+ user: {
85
+ id: string;
86
+ email: string;
87
+ name: string | null;
88
+ };
89
+ };
90
+ export type BinctlApiKey = {
91
+ id: string;
92
+ name: string;
93
+ createdAt: string;
94
+ lastUsedAt: string | null;
95
+ };
96
+ export type BinctlProjectCreateInput = {
97
+ name?: string;
98
+ orgId?: string;
99
+ };
100
+ export type BinctlProjectUpdateInput = {
101
+ name?: string;
102
+ mode?: "greenfield" | "prod";
103
+ };
104
+ export type BinctlSessionCreateInput = {
105
+ name?: string;
106
+ branchName: string;
107
+ };
108
+ export type BinctlSessionUpdateInput = {
109
+ name: string | null;
110
+ };
111
+ export type BinctlClientOptions = {
112
+ baseUrl?: string;
113
+ token?: string;
114
+ apiKey?: string;
115
+ fetch?: typeof fetch;
116
+ headers?: Record<string, string>;
117
+ authMode?: "bearer" | "headers";
118
+ };
119
+ export declare class BinctlApiError extends Error {
120
+ readonly status: number;
121
+ readonly path: string;
122
+ readonly body: unknown;
123
+ constructor(message: string, input: {
124
+ status: number;
125
+ path: string;
126
+ body: unknown;
127
+ });
128
+ }
129
+ export declare class BinctlClient {
130
+ private readonly fetchImpl;
131
+ private baseUrl;
132
+ private token?;
133
+ private apiKey?;
134
+ private readonly extraHeaders;
135
+ private readonly authMode;
136
+ constructor(options?: BinctlClientOptions);
137
+ setBaseUrl(baseUrl: string): void;
138
+ setToken(token?: string): void;
139
+ setApiKey(apiKey?: string): void;
140
+ private resolveBearerToken;
141
+ private request;
142
+ readonly auth: {
143
+ loginStart: (input?: {
144
+ baseUrl?: string;
145
+ }) => Promise<BinctlLoginStartResponse>;
146
+ loginPoll: (requestId: string, input: {
147
+ pollCode: string;
148
+ }) => Promise<BinctlLoginPollResponse>;
149
+ logout: () => Promise<{
150
+ success: boolean;
151
+ revokedCredential: boolean;
152
+ }>;
153
+ status: () => Promise<BinctlAuthStatusResponse>;
154
+ apiKeys: {
155
+ create: (input: {
156
+ name: string;
157
+ }) => Promise<{
158
+ id: string;
159
+ apiKey: string;
160
+ name: string;
161
+ createdAt: string;
162
+ }>;
163
+ list: () => Promise<BinctlApiKey[]>;
164
+ revoke: (keyId: string) => Promise<{
165
+ success: boolean;
166
+ }>;
167
+ };
168
+ };
169
+ readonly projects: {
170
+ list: () => Promise<BinctlProject[]>;
171
+ create: (input?: BinctlProjectCreateInput) => Promise<BinctlProjectDescription>;
172
+ describe: (projectRef: string) => Promise<BinctlProjectDescription>;
173
+ update: (projectRef: string, input: BinctlProjectUpdateInput) => Promise<BinctlProjectDescription>;
174
+ delete: (projectRef: string) => Promise<{
175
+ success: boolean;
176
+ }>;
177
+ branches: {
178
+ list: (projectRef: string) => Promise<BinctlBranch[]>;
179
+ describe: (projectRef: string, branch: string) => Promise<{
180
+ project: BinctlProject;
181
+ branchName: string;
182
+ sessions: BinctlSessionSummary[];
183
+ }>;
184
+ };
185
+ sessions: {
186
+ list: (projectRef: string, input?: {
187
+ branch?: string;
188
+ }) => Promise<BinctlSessionSummary[]>;
189
+ create: (projectRef: string, input: BinctlSessionCreateInput) => Promise<BinctlSessionDescription>;
190
+ };
191
+ };
192
+ readonly sessions: {
193
+ describe: (sessionId: string) => Promise<BinctlSessionDescription>;
194
+ update: (sessionId: string, input: BinctlSessionUpdateInput) => Promise<BinctlSessionDescription>;
195
+ delete: (sessionId: string) => Promise<{
196
+ success: boolean;
197
+ }>;
198
+ conversation: (sessionId: string) => Promise<BinctlConversationResponse>;
199
+ prompt: (sessionId: string, input: {
200
+ message: string;
201
+ mode: ChatMode;
202
+ model: ModelTier;
203
+ }) => Promise<BinctlConversationResponse>;
204
+ answerQuestions: (sessionId: string, input: {
205
+ answers: string[];
206
+ }) => Promise<BinctlConversationResponse>;
207
+ applyRequiredEnvs: (sessionId: string, input: {
208
+ envs: string[];
209
+ }) => Promise<BinctlConversationResponse>;
210
+ };
211
+ }
package/package.json CHANGED
@@ -1,10 +1,31 @@
1
1
  {
2
2
  "name": "@ricsam/r5d-api",
3
- "version": "0.0.1",
4
- "description": "OIDC trusted publishing setup package for @ricsam/r5d-api",
5
- "keywords": [
6
- "oidc",
7
- "trusted-publishing",
8
- "setup"
9
- ]
3
+ "version": "0.0.3",
4
+ "type": "module",
5
+ "main": "./dist/cjs/index.cjs",
6
+ "module": "./dist/mjs/index.mjs",
7
+ "types": "./dist/types/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/types/index.d.ts",
11
+ "import": "./dist/mjs/index.mjs",
12
+ "require": "./dist/cjs/index.cjs"
13
+ }
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/ricsam/r5d-dev.git",
18
+ "directory": "binctl-packages/binctl-api"
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "README.md"
23
+ ],
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "engines": {
28
+ "node": ">=18"
29
+ },
30
+ "sideEffects": false
10
31
  }