@nurama/sdk 0.0.0-stage → 1.4.0
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/LICENSE +202 -0
- package/NOTICE +5 -0
- package/README.md +1080 -2
- package/dist/BotClient.d.ts +66 -0
- package/dist/BotClient.d.ts.map +1 -0
- package/dist/BotClient.js +68 -0
- package/dist/BotClient.js.map +1 -0
- package/dist/NuramaClient.d.ts +448 -0
- package/dist/NuramaClient.d.ts.map +1 -0
- package/dist/NuramaClient.js +864 -0
- package/dist/NuramaClient.js.map +1 -0
- package/dist/browser/nurama-bot-sdk.js +11780 -0
- package/dist/browser/nurama-bot-sdk.min.js +1 -0
- package/dist/browser/nurama-sdk.js +11732 -0
- package/dist/browser/nurama-sdk.min.js +1 -0
- package/dist/routes/ai.d.ts +280 -0
- package/dist/routes/ai.d.ts.map +1 -0
- package/dist/routes/ai.js +173 -0
- package/dist/routes/ai.js.map +1 -0
- package/dist/routes/asset.d.ts +493 -0
- package/dist/routes/asset.d.ts.map +1 -0
- package/dist/routes/asset.js +848 -0
- package/dist/routes/asset.js.map +1 -0
- package/dist/routes/auth.d.ts +218 -0
- package/dist/routes/auth.d.ts.map +1 -0
- package/dist/routes/auth.js +454 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/routes/blogPosts.d.ts +17 -0
- package/dist/routes/blogPosts.d.ts.map +1 -0
- package/dist/routes/blogPosts.js +29 -0
- package/dist/routes/blogPosts.js.map +1 -0
- package/dist/routes/board.d.ts +187 -0
- package/dist/routes/board.d.ts.map +1 -0
- package/dist/routes/board.js +270 -0
- package/dist/routes/board.js.map +1 -0
- package/dist/routes/bot.d.ts +147 -0
- package/dist/routes/bot.d.ts.map +1 -0
- package/dist/routes/bot.js +157 -0
- package/dist/routes/bot.js.map +1 -0
- package/dist/routes/chat.d.ts +842 -0
- package/dist/routes/chat.d.ts.map +1 -0
- package/dist/routes/chat.js +863 -0
- package/dist/routes/chat.js.map +1 -0
- package/dist/routes/chatAi.d.ts +51 -0
- package/dist/routes/chatAi.d.ts.map +1 -0
- package/dist/routes/chatAi.js +109 -0
- package/dist/routes/chatAi.js.map +1 -0
- package/dist/routes/config.d.ts +11 -0
- package/dist/routes/config.d.ts.map +1 -0
- package/dist/routes/config.js +24 -0
- package/dist/routes/config.js.map +1 -0
- package/dist/routes/convo.d.ts +169 -0
- package/dist/routes/convo.d.ts.map +1 -0
- package/dist/routes/convo.js +284 -0
- package/dist/routes/convo.js.map +1 -0
- package/dist/routes/credits.d.ts +82 -0
- package/dist/routes/credits.d.ts.map +1 -0
- package/dist/routes/credits.js +49 -0
- package/dist/routes/credits.js.map +1 -0
- package/dist/routes/device.d.ts +74 -0
- package/dist/routes/device.d.ts.map +1 -0
- package/dist/routes/device.js +122 -0
- package/dist/routes/device.js.map +1 -0
- package/dist/routes/folder.d.ts +75 -0
- package/dist/routes/folder.d.ts.map +1 -0
- package/dist/routes/folder.js +99 -0
- package/dist/routes/folder.js.map +1 -0
- package/dist/routes/invite.d.ts +61 -0
- package/dist/routes/invite.d.ts.map +1 -0
- package/dist/routes/invite.js +86 -0
- package/dist/routes/invite.js.map +1 -0
- package/dist/routes/joinLink.d.ts +38 -0
- package/dist/routes/joinLink.d.ts.map +1 -0
- package/dist/routes/joinLink.js +81 -0
- package/dist/routes/joinLink.js.map +1 -0
- package/dist/routes/membership.d.ts +116 -0
- package/dist/routes/membership.d.ts.map +1 -0
- package/dist/routes/membership.js +183 -0
- package/dist/routes/membership.js.map +1 -0
- package/dist/routes/notification.d.ts +103 -0
- package/dist/routes/notification.d.ts.map +1 -0
- package/dist/routes/notification.js +89 -0
- package/dist/routes/notification.js.map +1 -0
- package/dist/routes/payment.d.ts +56 -0
- package/dist/routes/payment.d.ts.map +1 -0
- package/dist/routes/payment.js +78 -0
- package/dist/routes/payment.js.map +1 -0
- package/dist/routes/product.d.ts +43 -0
- package/dist/routes/product.d.ts.map +1 -0
- package/dist/routes/product.js +53 -0
- package/dist/routes/product.js.map +1 -0
- package/dist/routes/project.d.ts +821 -0
- package/dist/routes/project.d.ts.map +1 -0
- package/dist/routes/project.js +1153 -0
- package/dist/routes/project.js.map +1 -0
- package/dist/routes/public.d.ts +269 -0
- package/dist/routes/public.d.ts.map +1 -0
- package/dist/routes/public.js +412 -0
- package/dist/routes/public.js.map +1 -0
- package/dist/routes/scratch.d.ts +70 -0
- package/dist/routes/scratch.d.ts.map +1 -0
- package/dist/routes/scratch.js +67 -0
- package/dist/routes/scratch.js.map +1 -0
- package/dist/routes/settings.d.ts +102 -0
- package/dist/routes/settings.d.ts.map +1 -0
- package/dist/routes/settings.js +94 -0
- package/dist/routes/settings.js.map +1 -0
- package/dist/routes/shortlink.d.ts +79 -0
- package/dist/routes/shortlink.d.ts.map +1 -0
- package/dist/routes/shortlink.js +25 -0
- package/dist/routes/shortlink.js.map +1 -0
- package/dist/routes/socket.d.ts +108 -0
- package/dist/routes/socket.d.ts.map +1 -0
- package/dist/routes/socket.js +555 -0
- package/dist/routes/socket.js.map +1 -0
- package/dist/routes/storage.d.ts +44 -0
- package/dist/routes/storage.d.ts.map +1 -0
- package/dist/routes/storage.js +49 -0
- package/dist/routes/storage.js.map +1 -0
- package/dist/routes/subscription.d.ts +184 -0
- package/dist/routes/subscription.d.ts.map +1 -0
- package/dist/routes/subscription.js +219 -0
- package/dist/routes/subscription.js.map +1 -0
- package/dist/routes/supportChat.d.ts +40 -0
- package/dist/routes/supportChat.d.ts.map +1 -0
- package/dist/routes/supportChat.js +53 -0
- package/dist/routes/supportChat.js.map +1 -0
- package/dist/routes/supportTicket.d.ts +89 -0
- package/dist/routes/supportTicket.d.ts.map +1 -0
- package/dist/routes/supportTicket.js +54 -0
- package/dist/routes/supportTicket.js.map +1 -0
- package/dist/routes/tag.d.ts +72 -0
- package/dist/routes/tag.d.ts.map +1 -0
- package/dist/routes/tag.js +81 -0
- package/dist/routes/tag.js.map +1 -0
- package/dist/routes/task.d.ts +252 -0
- package/dist/routes/task.d.ts.map +1 -0
- package/dist/routes/task.js +284 -0
- package/dist/routes/task.js.map +1 -0
- package/dist/routes/taskRelation.d.ts +80 -0
- package/dist/routes/taskRelation.d.ts.map +1 -0
- package/dist/routes/taskRelation.js +71 -0
- package/dist/routes/taskRelation.js.map +1 -0
- package/dist/routes/token.d.ts +75 -0
- package/dist/routes/token.d.ts.map +1 -0
- package/dist/routes/token.js +51 -0
- package/dist/routes/token.js.map +1 -0
- package/dist/routes/user.d.ts +112 -0
- package/dist/routes/user.d.ts.map +1 -0
- package/dist/routes/user.js +151 -0
- package/dist/routes/user.js.map +1 -0
- package/dist/routes/version.d.ts +42 -0
- package/dist/routes/version.d.ts.map +1 -0
- package/dist/routes/version.js +38 -0
- package/dist/routes/version.js.map +1 -0
- package/dist/routes/webhook.d.ts +170 -0
- package/dist/routes/webhook.d.ts.map +1 -0
- package/dist/routes/webhook.js +173 -0
- package/dist/routes/webhook.js.map +1 -0
- package/dist/routes/workspace.d.ts +120 -0
- package/dist/routes/workspace.d.ts.map +1 -0
- package/dist/routes/workspace.js +199 -0
- package/dist/routes/workspace.js.map +1 -0
- package/dist/utils/uploadSessionManager.d.ts +133 -0
- package/dist/utils/uploadSessionManager.d.ts.map +1 -0
- package/dist/utils/uploadSessionManager.js +321 -0
- package/dist/utils/uploadSessionManager.js.map +1 -0
- package/dist/utils/urlParams.d.ts +35 -0
- package/dist/utils/urlParams.d.ts.map +1 -0
- package/dist/utils/urlParams.js +146 -0
- package/dist/utils/urlParams.js.map +1 -0
- package/dist/version.d.ts +15 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +12 -0
- package/dist/version.js.map +1 -0
- package/package.json +87 -3
- package/src/BotClient.ts +113 -0
- package/src/NuramaClient.ts +1193 -0
- package/src/bot-browser-entry.js +15 -0
- package/src/browser-entry.js +20 -0
- package/src/routes/ai.ts +378 -0
- package/src/routes/asset.ts +1104 -0
- package/src/routes/auth.ts +587 -0
- package/src/routes/blogPosts.ts +29 -0
- package/src/routes/board.ts +403 -0
- package/src/routes/bot.ts +257 -0
- package/src/routes/chat.ts +1292 -0
- package/src/routes/chatAi.ts +125 -0
- package/src/routes/config.ts +31 -0
- package/src/routes/convo.ts +321 -0
- package/src/routes/credits.ts +112 -0
- package/src/routes/device.ts +133 -0
- package/src/routes/folder.ts +154 -0
- package/src/routes/invite.ts +133 -0
- package/src/routes/joinLink.ts +100 -0
- package/src/routes/membership.ts +237 -0
- package/src/routes/notification.ts +166 -0
- package/src/routes/payment.ts +104 -0
- package/src/routes/product.ts +67 -0
- package/src/routes/project.ts +1528 -0
- package/src/routes/public.ts +496 -0
- package/src/routes/scratch.ts +94 -0
- package/src/routes/settings.ts +152 -0
- package/src/routes/shortlink.ts +90 -0
- package/src/routes/socket.ts +739 -0
- package/src/routes/storage.ts +83 -0
- package/src/routes/subscription.ts +307 -0
- package/src/routes/supportChat.ts +62 -0
- package/src/routes/supportTicket.ts +114 -0
- package/src/routes/tag.ts +131 -0
- package/src/routes/task.ts +431 -0
- package/src/routes/taskRelation.ts +125 -0
- package/src/routes/token.ts +113 -0
- package/src/routes/user.ts +214 -0
- package/src/routes/version.ts +62 -0
- package/src/routes/webhook.ts +295 -0
- package/src/routes/workspace.ts +223 -0
- package/src/utils/uploadSessionManager.ts +407 -0
- package/src/utils/urlParams.ts +181 -0
- package/src/version.ts +22 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import BotClient from './BotClient.js';
|
|
2
|
+
|
|
3
|
+
const OriginalBotClient = BotClient;
|
|
4
|
+
class BrowserBotClient extends OriginalBotClient {
|
|
5
|
+
constructor(apiKey, options = {}) {
|
|
6
|
+
super(apiKey, {
|
|
7
|
+
...options,
|
|
8
|
+
fetch: options.fetch || ((url, init) => window.fetch(url, init)),
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
window.NuramaBotClient = BrowserBotClient;
|
|
14
|
+
|
|
15
|
+
export default BrowserBotClient;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import NuramaClient from './NuramaClient.js';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
const OriginalNuramaClient = NuramaClient;
|
|
5
|
+
class BrowserNuramaClient extends OriginalNuramaClient {
|
|
6
|
+
constructor(baseURL, options = {}) {
|
|
7
|
+
// Ensure fetch is properly bound to window
|
|
8
|
+
const browserOptions = {
|
|
9
|
+
...options,
|
|
10
|
+
// Wrap fetch in a function that explicitly binds to window
|
|
11
|
+
fetch: (url, init) => window.fetch(url, init)
|
|
12
|
+
};
|
|
13
|
+
super(baseURL, browserOptions);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Explicitly assign the constructor to the global window object
|
|
18
|
+
window.NuramaClient = BrowserNuramaClient;
|
|
19
|
+
|
|
20
|
+
export default BrowserNuramaClient;
|
package/src/routes/ai.ts
ADDED
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import NuramaClient from '../NuramaClient.js';
|
|
2
|
+
|
|
3
|
+
/** One turn of the drafting conversation, as sent back on each request. */
|
|
4
|
+
export interface ComposeWithNuTurn {
|
|
5
|
+
role: 'user' | 'assistant';
|
|
6
|
+
text: string;
|
|
7
|
+
/**
|
|
8
|
+
* Wording this turn offered. Held per turn so an earlier draft stays
|
|
9
|
+
* takeable after the conversation has moved on — the user may prefer the
|
|
10
|
+
* version from three turns ago.
|
|
11
|
+
*/
|
|
12
|
+
proposal?: string | null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ComposeWithNuRequest {
|
|
16
|
+
workspaceId: string;
|
|
17
|
+
/** Chat being composed into. Read server-side for context and tone. */
|
|
18
|
+
chatId: string;
|
|
19
|
+
projectId?: string;
|
|
20
|
+
messages: ComposeWithNuTurn[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ComposeWithNuResponse {
|
|
24
|
+
/** What Nu said to the user. Never posted anywhere. */
|
|
25
|
+
text: string;
|
|
26
|
+
/** Wording the user may put in their composer, or null for a pure question. */
|
|
27
|
+
proposal: string | null;
|
|
28
|
+
billedCredits: number;
|
|
29
|
+
balanceAfter: number | null;
|
|
30
|
+
eventId: string | null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** One Nu Feedback submission. */
|
|
34
|
+
export interface SubmitAiFeedbackRequest {
|
|
35
|
+
rating: 'positive' | 'negative';
|
|
36
|
+
/** Which AI surface produced the reply — the two are tuned separately. */
|
|
37
|
+
surface: 'chat' | 'assist';
|
|
38
|
+
chatId: string;
|
|
39
|
+
messageId?: string;
|
|
40
|
+
/** The user's own words on what worked or didn't. Optional. */
|
|
41
|
+
notes?: string;
|
|
42
|
+
workspaceId?: string;
|
|
43
|
+
projectId?: string;
|
|
44
|
+
/** Extras the client already holds, folded into the stored snapshot. */
|
|
45
|
+
pageContext?: Record<string, unknown>;
|
|
46
|
+
contextItems?: Array<Record<string, unknown>>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface PolishRequest {
|
|
50
|
+
workspaceId: string;
|
|
51
|
+
text: string;
|
|
52
|
+
toneId: string;
|
|
53
|
+
projectId?: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface PolishResponse {
|
|
57
|
+
polishedText: string;
|
|
58
|
+
billedCredits: number;
|
|
59
|
+
balanceAfter: number;
|
|
60
|
+
eventId: string | null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface TaskGenerationContextMessage {
|
|
64
|
+
/** Display name of the message author. Optional but improves the prompt. */
|
|
65
|
+
authorName?: string;
|
|
66
|
+
content: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface GenerateTasksRequest {
|
|
70
|
+
workspaceId: string;
|
|
71
|
+
projectId: string;
|
|
72
|
+
messageText: string;
|
|
73
|
+
/** Optional source chat message id — reserved for future audit linking. */
|
|
74
|
+
messageId?: string;
|
|
75
|
+
/**
|
|
76
|
+
* Preceding chat messages (oldest first) to give the model conversational
|
|
77
|
+
* lead-in. Server caps at 10 messages and trims long content per-message;
|
|
78
|
+
* the focal `messageText` is the actual instruction.
|
|
79
|
+
*/
|
|
80
|
+
contextMessages?: TaskGenerationContextMessage[];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface GeneratedTask {
|
|
84
|
+
subject: string;
|
|
85
|
+
description: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface GenerateTasksResponse {
|
|
89
|
+
tasks: GeneratedTask[];
|
|
90
|
+
billedCredits: number;
|
|
91
|
+
balanceAfter: number;
|
|
92
|
+
eventId: string | null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface ToneEntry {
|
|
96
|
+
id: string;
|
|
97
|
+
label: string;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface ListTonesResponse {
|
|
101
|
+
tones: ToneEntry[];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Source for an image revision call. Exactly one of:
|
|
106
|
+
* - `url` — public media URL (typical for image assets).
|
|
107
|
+
* - `scratchId` — id of a Scratch row the FE uploaded via
|
|
108
|
+
* `createRevisionSourceUpload`. Preferred for
|
|
109
|
+
* captured video frames so bytes never transit the
|
|
110
|
+
* API node.
|
|
111
|
+
* - `dataUrl` — DEPRECATED legacy path: FE-captured video frame
|
|
112
|
+
* serialised as a base64 data URL inline in the
|
|
113
|
+
* request body. Kept here for back-compat during
|
|
114
|
+
* FE rollout; new code should always use the
|
|
115
|
+
* `scratchId` flow.
|
|
116
|
+
*/
|
|
117
|
+
export type ImageRevisionSource =
|
|
118
|
+
| { url: string }
|
|
119
|
+
| { scratchId: string }
|
|
120
|
+
| { dataUrl: string };
|
|
121
|
+
|
|
122
|
+
export interface GenerateImageRevisionRequest {
|
|
123
|
+
workspaceId: string;
|
|
124
|
+
projectId?: string;
|
|
125
|
+
/** Audit-only — the caller has already resolved the asset's media URL. */
|
|
126
|
+
assetId?: string;
|
|
127
|
+
source: ImageRevisionSource;
|
|
128
|
+
prompt: string;
|
|
129
|
+
/** Prior revisions to condition on (public URLs or data URLs). */
|
|
130
|
+
references?: string[];
|
|
131
|
+
/**
|
|
132
|
+
* Optional alpha-channel mask PNG (data URL) matching the source
|
|
133
|
+
* image's dimensions. Transparent pixels mark the edit region; opaque
|
|
134
|
+
* pixels are preserved. When supplied, the server forwards it as
|
|
135
|
+
* OpenAI's top-level `mask` field — NOT as another `references[]`
|
|
136
|
+
* entry — and auto-augments the prompt with a region directive.
|
|
137
|
+
*/
|
|
138
|
+
mask?: { dataUrl: string };
|
|
139
|
+
/** Groups all revisions from one modal session. */
|
|
140
|
+
jobId?: string;
|
|
141
|
+
/**
|
|
142
|
+
* Source image's aspect ratio (width / height). Two effects when set:
|
|
143
|
+
* 1. The server picks the closest OpenAI-supported generation
|
|
144
|
+
* size — landscape, portrait, or square — instead of always
|
|
145
|
+
* generating 1024×1024. Reduces the gap between the model's
|
|
146
|
+
* output aspect and the source aspect before any padding.
|
|
147
|
+
* 2. After generation, the server pads the result with black
|
|
148
|
+
* bars (letterbox/pillarbox) so the final bytes exactly
|
|
149
|
+
* match this aspect. The user gets an output image whose
|
|
150
|
+
* framing matches the input they started from, with the
|
|
151
|
+
* generated content centred and the unfilled edges padded.
|
|
152
|
+
*
|
|
153
|
+
* Omit (or pass `1.0`) for legacy square output.
|
|
154
|
+
*/
|
|
155
|
+
sourceAspect?: number;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export interface GenerateImageRevisionResponse {
|
|
159
|
+
/**
|
|
160
|
+
* Scratch id. The FE forwards this in one of two outcomes:
|
|
161
|
+
* - "Upload to project" → call `promoteRevision` (this SDK module)
|
|
162
|
+
* to materialise as a project-scoped Asset.
|
|
163
|
+
* - "Attach to chat" → pass `{ scratchId }` as a chat-message
|
|
164
|
+
* attachment item; the chat-send endpoint promotes it to a
|
|
165
|
+
* chat-scoped Asset at send time.
|
|
166
|
+
*/
|
|
167
|
+
revisionId: string;
|
|
168
|
+
/** Public URL the FE can render directly. */
|
|
169
|
+
revisionUrl: string | null;
|
|
170
|
+
model: string;
|
|
171
|
+
quality: string;
|
|
172
|
+
billedCredits: number;
|
|
173
|
+
balanceAfter: number | null;
|
|
174
|
+
eventId: string | null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Source-upload mint request. Returns a multipart upload bundle the
|
|
179
|
+
* FE drives like any other scratch / asset upload (PUT each `urls[i]`
|
|
180
|
+
* with the corresponding part, collect the ETags, call complete-
|
|
181
|
+
* upload). Server hardcodes mime to `image/jpeg` — the only producer
|
|
182
|
+
* is the captured video frame, which is always JPEG. Size cap
|
|
183
|
+
* (matches OpenAI's images/edits per-image limit): 25 MB.
|
|
184
|
+
*/
|
|
185
|
+
export interface CreateRevisionSourceUploadRequest {
|
|
186
|
+
workspaceId: string;
|
|
187
|
+
projectId?: string;
|
|
188
|
+
/** Audit-only lineage — the originating asset id. */
|
|
189
|
+
assetId?: string;
|
|
190
|
+
sizeInMB: number;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export interface CreateRevisionSourceUploadResponse {
|
|
194
|
+
/** Use as `source.scratchId` on the subsequent `generateRevision` call. */
|
|
195
|
+
scratchId: string;
|
|
196
|
+
/**
|
|
197
|
+
* Bucket-side keyPath. Pass to `nuramaClient.asset.multipartUpload`
|
|
198
|
+
* which threads it through into its session-progress + result shape.
|
|
199
|
+
*/
|
|
200
|
+
key: string;
|
|
201
|
+
/** Pass back to `POST /v1/scratch/:id/complete-upload` along with parts. */
|
|
202
|
+
uploadId: string;
|
|
203
|
+
/**
|
|
204
|
+
* One signed PUT URL per multipart part. Single-element array for
|
|
205
|
+
* sub-chunk-size payloads (1080p JPEG frames are well under).
|
|
206
|
+
*/
|
|
207
|
+
urls: string[];
|
|
208
|
+
/** ISO-string TTL — the row is reaped after this. */
|
|
209
|
+
expires: string;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Scratch promotion moved to the scratch namespace —
|
|
213
|
+
// `nuramaClient.scratch.promote(id, { fileName? })`. The AI module
|
|
214
|
+
// no longer carries a `promoteRevision`. Two reasons for the move:
|
|
215
|
+
// 1. Scratch is a generic primitive; promote applies to ALL scratch
|
|
216
|
+
// jobTypes, not just AI Revision.
|
|
217
|
+
// 2. Destination (workspace + project) is derived from the scratch
|
|
218
|
+
// row's own state on the server — keeps promote a single-arg
|
|
219
|
+
// operation from the FE's perspective ("promote this row") and
|
|
220
|
+
// removes the cross-workspace-promote attack surface.
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Methods for the Nu AI assistant integration points.
|
|
224
|
+
*
|
|
225
|
+
* Nu is the platform-native AI feature set. Each integration point is gated
|
|
226
|
+
* by workspace settings (`allowAiFeatures` master switch + per-feature toggle
|
|
227
|
+
* + role allowlist) and metered against the workspace's credit balance.
|
|
228
|
+
*
|
|
229
|
+
* MVP exposes a single integration point — Polish — used by the chat
|
|
230
|
+
* composer to rewrite a draft message in a selected tone.
|
|
231
|
+
*/
|
|
232
|
+
export default function createAiMethods(client: NuramaClient) {
|
|
233
|
+
return {
|
|
234
|
+
/**
|
|
235
|
+
* Rewrite a draft chat message in a selected tone. Charges the workspace's
|
|
236
|
+
* credit balance based on the underlying provider cost plus markup.
|
|
237
|
+
*
|
|
238
|
+
* @param data - Polish request payload.
|
|
239
|
+
* @returns The polished text plus billing telemetry.
|
|
240
|
+
*/
|
|
241
|
+
/**
|
|
242
|
+
* One turn of a Compose-with-Nu drafting conversation.
|
|
243
|
+
*
|
|
244
|
+
* Send only the drafting thread — the chat being written into is read
|
|
245
|
+
* server-side from `chatId`, under the caller's own permissions. The
|
|
246
|
+
* result is Nu's commentary plus, when it has one, a proposed message.
|
|
247
|
+
* Nothing is posted: the proposal is the user's to take or discard.
|
|
248
|
+
*/
|
|
249
|
+
async composeWithNu(data: ComposeWithNuRequest): Promise<ComposeWithNuResponse> {
|
|
250
|
+
if (!data?.workspaceId) throw new Error('workspaceId is required.');
|
|
251
|
+
if (!data?.chatId) throw new Error('chatId is required.');
|
|
252
|
+
if (!data?.messages?.length) throw new Error('messages is required.');
|
|
253
|
+
return client._request({
|
|
254
|
+
endpoint: '/v1/ai/compose',
|
|
255
|
+
method: 'POST',
|
|
256
|
+
body: data,
|
|
257
|
+
sendJWT: true,
|
|
258
|
+
});
|
|
259
|
+
},
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Record a thumbs-up / thumbs-down on one assistant reply.
|
|
263
|
+
*
|
|
264
|
+
* `chatId` is required because it is what the server authorises against —
|
|
265
|
+
* a user can only rate a reply in a chat they can already read — and it is
|
|
266
|
+
* what the stored transcript snapshot is built from.
|
|
267
|
+
*/
|
|
268
|
+
async submitFeedback(data: SubmitAiFeedbackRequest): Promise<{ id: string }> {
|
|
269
|
+
if (!data?.chatId) throw new Error('chatId is required.');
|
|
270
|
+
if (!data?.rating) throw new Error('rating is required.');
|
|
271
|
+
if (!data?.surface) throw new Error('surface is required.');
|
|
272
|
+
return client._request({
|
|
273
|
+
endpoint: '/v1/ai/feedback',
|
|
274
|
+
method: 'POST',
|
|
275
|
+
body: data,
|
|
276
|
+
sendJWT: true,
|
|
277
|
+
});
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
async polish(data: PolishRequest): Promise<PolishResponse> {
|
|
281
|
+
if (!data?.workspaceId) throw new Error('workspaceId is required.');
|
|
282
|
+
if (!data?.text) throw new Error('text is required.');
|
|
283
|
+
if (!data?.toneId) throw new Error('toneId is required.');
|
|
284
|
+
return client._request({
|
|
285
|
+
endpoint: '/v1/ai/polish',
|
|
286
|
+
method: 'POST',
|
|
287
|
+
body: data,
|
|
288
|
+
sendJWT: true,
|
|
289
|
+
});
|
|
290
|
+
},
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Convert a chat message into one or more board-task drafts. The
|
|
294
|
+
* frontend opens the EnhancedTaskCreatorModal in a loading state, calls
|
|
295
|
+
* this method, and seeds the modal's draft list from the response's
|
|
296
|
+
* `tasks` array. Requires both the AI add-on AND the Boards add-on on
|
|
297
|
+
* the workspace; the server returns `productNotActive` if either is
|
|
298
|
+
* missing.
|
|
299
|
+
*
|
|
300
|
+
* @param data - Task generation request payload.
|
|
301
|
+
* @returns Tasks plus billing telemetry.
|
|
302
|
+
*/
|
|
303
|
+
async generateTasks(data: GenerateTasksRequest): Promise<GenerateTasksResponse> {
|
|
304
|
+
if (!data?.workspaceId) throw new Error('workspaceId is required.');
|
|
305
|
+
if (!data?.projectId) throw new Error('projectId is required.');
|
|
306
|
+
if (!data?.messageText) throw new Error('messageText is required.');
|
|
307
|
+
return client._request({
|
|
308
|
+
endpoint: '/v1/ai/task-generation',
|
|
309
|
+
method: 'POST',
|
|
310
|
+
body: data,
|
|
311
|
+
sendJWT: true,
|
|
312
|
+
});
|
|
313
|
+
},
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Returns the catalogue of polish tones the platform supports. The FE
|
|
317
|
+
* uses this to populate the tone dropdown without hard-coding the IDs.
|
|
318
|
+
*/
|
|
319
|
+
async listTones(): Promise<ListTonesResponse> {
|
|
320
|
+
return client._request({
|
|
321
|
+
endpoint: '/v1/ai/tones',
|
|
322
|
+
method: 'GET',
|
|
323
|
+
sendJWT: true,
|
|
324
|
+
});
|
|
325
|
+
},
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Generate one image revision (prompt-driven variant of a source
|
|
329
|
+
* image or video frame). The result is staged on Scratch — the FE
|
|
330
|
+
* then chooses one of two outcomes:
|
|
331
|
+
* - "Add to project" → call `nuramaClient.scratch.promote(id)` to
|
|
332
|
+
* create a project-scoped Asset immediately.
|
|
333
|
+
* - "Attach to chat" → leave the scratch id in the chat
|
|
334
|
+
* composer's pending attachments; the chat-send endpoint
|
|
335
|
+
* accepts `{ scratchId, name? }` items in `attachments[]` and
|
|
336
|
+
* promotes each to a chat-scoped Asset at send time.
|
|
337
|
+
*/
|
|
338
|
+
async generateRevision(
|
|
339
|
+
data: GenerateImageRevisionRequest,
|
|
340
|
+
): Promise<GenerateImageRevisionResponse> {
|
|
341
|
+
if (!data?.workspaceId) throw new Error('workspaceId is required.');
|
|
342
|
+
if (!data?.source) throw new Error('source is required.');
|
|
343
|
+
if (!data?.prompt) throw new Error('prompt is required.');
|
|
344
|
+
return client._request({
|
|
345
|
+
endpoint: '/v1/ai/revisions',
|
|
346
|
+
method: 'POST',
|
|
347
|
+
body: data,
|
|
348
|
+
sendJWT: true,
|
|
349
|
+
});
|
|
350
|
+
},
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Mint a signed-URL bundle for uploading a source image (typically
|
|
354
|
+
* a captured video frame) into Scratch BEFORE calling
|
|
355
|
+
* `generateRevision`. Use the resulting `scratchId` as the
|
|
356
|
+
* `source.scratchId` on the generate call.
|
|
357
|
+
*
|
|
358
|
+
* Why this exists: video frames are captured client-side and need
|
|
359
|
+
* to reach OpenAI as a public media URL. Posting the bytes inline
|
|
360
|
+
* (as `dataUrl`) makes the API node a pass-through for multi-MB
|
|
361
|
+
* payloads; staging on Scratch first keeps the node out of the
|
|
362
|
+
* byte path entirely.
|
|
363
|
+
*/
|
|
364
|
+
async createRevisionSourceUpload(
|
|
365
|
+
data: CreateRevisionSourceUploadRequest,
|
|
366
|
+
): Promise<CreateRevisionSourceUploadResponse> {
|
|
367
|
+
if (!data?.workspaceId) throw new Error('workspaceId is required.');
|
|
368
|
+
if (!(data?.sizeInMB > 0)) throw new Error('sizeInMB must be a positive number.');
|
|
369
|
+
return client._request({
|
|
370
|
+
endpoint: '/v1/ai/revisions/source-upload',
|
|
371
|
+
method: 'POST',
|
|
372
|
+
body: data,
|
|
373
|
+
sendJWT: true,
|
|
374
|
+
});
|
|
375
|
+
},
|
|
376
|
+
|
|
377
|
+
};
|
|
378
|
+
}
|