@betterlu/agentlu 1.1.1 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -40,7 +40,17 @@ export interface ClientDefaults {
40
40
  export interface RunOptions {
41
41
  agent?: string;
42
42
  model?: string;
43
- input: string;
43
+ input?: string;
44
+ /**
45
+ * Image attachments previously uploaded via `upload()`. Prepended to the
46
+ * user turn as `input_image` parts; `input` becomes the accompanying text.
47
+ */
48
+ fileIds?: string[];
49
+ /** Structured input messages (OpenAI shape) - overrides `input`. */
50
+ inputMessages?: Array<{
51
+ role: string;
52
+ content: string | Array<Record<string, unknown>>;
53
+ }>;
44
54
  instructions?: string;
45
55
  tools?: Array<string | {
46
56
  type: string;
@@ -106,11 +116,22 @@ export declare class AgentLu {
106
116
  person?: string | null;
107
117
  defaults?: ClientDefaults;
108
118
  }): UseCaseRunner;
109
- /** Register a use-case client and resolve to its api key. */
119
+ /**
120
+ * Register a use-case client and resolve to its api key. The key is cached
121
+ * on this instance (same semantics as `register`), so a following
122
+ * `responses.create` is authorized.
123
+ */
110
124
  useCaseClient(name: string, opts?: {
111
125
  person?: string | null;
112
126
  defaults?: ClientDefaults;
113
127
  }): Promise<string>;
128
+ /**
129
+ * Upload an image (or document) for use with `run({ fileIds })` /
130
+ * `input_image`. Returns the `file_id` to reference.
131
+ */
132
+ upload(data: Uint8Array | Blob, filename: string, mime?: string): Promise<{
133
+ id: string;
134
+ }>;
114
135
  me(): Promise<unknown>;
115
136
  /**
116
137
  * One-shot helper. When `schema` is given, returns the validated object as
package/dist/index.js CHANGED
@@ -55,13 +55,29 @@ export class AgentLu {
55
55
  useCase(name, opts) {
56
56
  return new UseCaseRunner(this, name, opts);
57
57
  }
58
- /** Register a use-case client and resolve to its api key. */
58
+ /**
59
+ * Register a use-case client and resolve to its api key. The key is cached
60
+ * on this instance (same semantics as `register`), so a following
61
+ * `responses.create` is authorized.
62
+ */
59
63
  async useCaseClient(name, opts) {
60
64
  const res = await this.request("POST", "/clients", { name, ...opts }, { auth: false });
61
65
  if (!res.api_key)
62
66
  throw new AgentLuError(500, "internal_error", "register returned no key", true);
67
+ this.apiKey = res.api_key;
63
68
  return res.api_key;
64
69
  }
70
+ /**
71
+ * Upload an image (or document) for use with `run({ fileIds })` /
72
+ * `input_image`. Returns the `file_id` to reference.
73
+ */
74
+ async upload(data, filename, mime) {
75
+ const form = new FormData();
76
+ const blob = data instanceof Blob ? data : new Blob([new Uint8Array(data)], { type: mime ?? "application/octet-stream" });
77
+ form.append("file", blob, filename);
78
+ const res = await this.raw("POST", "/files", form);
79
+ return (await res.json());
80
+ }
65
81
  async me() {
66
82
  return this.request("GET", "/me");
67
83
  }
@@ -71,8 +87,20 @@ export class AgentLu {
71
87
  * could not produce matching JSON.
72
88
  */
73
89
  async run(opts) {
90
+ let input = opts.inputMessages ?? opts.input;
91
+ if (opts.fileIds?.length) {
92
+ input = [
93
+ {
94
+ role: "user",
95
+ content: [
96
+ ...opts.fileIds.map((file_id) => ({ type: "input_image", file_id })),
97
+ { type: "input_text", text: opts.input ?? "" },
98
+ ],
99
+ },
100
+ ];
101
+ }
74
102
  const body = {
75
- input: opts.input,
103
+ input,
76
104
  agent: opts.agent,
77
105
  model: opts.model,
78
106
  instructions: opts.instructions,
@@ -201,14 +229,16 @@ export class AgentLu {
201
229
  }
202
230
  async raw(method, path, body, opts) {
203
231
  const headers = {};
204
- if (body !== undefined)
232
+ const isForm = typeof FormData !== "undefined" && body instanceof FormData;
233
+ if (body !== undefined && !isForm) {
205
234
  headers["Content-Type"] = "application/json";
235
+ }
206
236
  if (opts?.auth !== false && this.apiKey)
207
237
  headers.Authorization = `Bearer ${this.apiKey}`;
208
238
  const res = await this.fetchImpl(`${this.baseUrl}${path}`, {
209
239
  method,
210
240
  headers,
211
- body: body === undefined ? undefined : JSON.stringify(body),
241
+ body: body === undefined ? undefined : isForm ? body : JSON.stringify(body),
212
242
  });
213
243
  if (!res.ok) {
214
244
  let code = `http_${res.status}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@betterlu/agentlu",
3
- "version": "1.1.1",
3
+ "version": "1.2.1",
4
4
  "description": "Client for the agentlu service API (/v1). Or just use the openai SDK pointed at http://localhost:8912/v1.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",