@lionhummer/constellation 0.9.1 → 0.9.2
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 +19 -0
- package/dist/index.js +36 -0
- package/dist/types/client-core/src/index.d.ts +34 -0
- package/dist/types/sdk/src/index.d.ts +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -343,6 +343,24 @@ tools: {
|
|
|
343
343
|
|
|
344
344
|
The SDK records `client.processing` and one span per tool automatically. A response carries at most 512 spans, 128 logs and 1 MiB of telemetry; the SDK trims larger batches and records what it omitted. Do not put secrets or personal data in span names, attributes or log messages.
|
|
345
345
|
|
|
346
|
+
## Opening lines
|
|
347
|
+
|
|
348
|
+
Show a one-sentence opener while the real step is prepared. The operator configures its model and prompt in Constellation.
|
|
349
|
+
|
|
350
|
+
```ts
|
|
351
|
+
const opener = await client.openers.create({
|
|
352
|
+
idempotencyKey: `${turnId}`,
|
|
353
|
+
workspaceId, userId, externalId: threadId,
|
|
354
|
+
message,
|
|
355
|
+
history: recentTurns, // [{ role: "user" | "assistant", text }], oldest first
|
|
356
|
+
})
|
|
357
|
+
if (opener) void client.openers.sentence(opener.id).then((sentence) => {
|
|
358
|
+
if (sentence && !realOutputStarted) show(sentence)
|
|
359
|
+
})
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
Start the real request without waiting for the opener. `parseOpenerSentence(text)` applies the same checks to text you already have.
|
|
363
|
+
|
|
346
364
|
## Limits and timeouts
|
|
347
365
|
|
|
348
366
|
| Setting | Default | Notes |
|
|
@@ -367,6 +385,7 @@ A failed provider call falls back to the next provider only before any output ha
|
|
|
367
385
|
| `requests.submit(input)` | Start a request, continue it (`inReplyTo`), or stop it (`action: "observe"`). |
|
|
368
386
|
| `requests.preview(input)` | Validate a complete input and show routing, without calling a provider. |
|
|
369
387
|
| `requests.cancel(id)` | Cancel a request. |
|
|
388
|
+
| `openers.create(input)`, `openers.sentence(id)` | Start an opening line for a just-sent message (null when openers are turned off), then wait for its sentence (null when skipped or failed). |
|
|
370
389
|
| `requests.getState(id)` | Committed state: status, steps, attempt outcomes, usage and cost. |
|
|
371
390
|
| `requests.getSummary(id)`, `requests.get(id)` | Request detail, without or with spans and logs. |
|
|
372
391
|
| `requests.list(query)` | Page through requests, e.g. by `externalId` or `status`. |
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
// ../client-core/src/index.ts
|
|
2
|
+
function parseOpenerSentence(raw, maxWords = 25) {
|
|
3
|
+
const text = raw.trim();
|
|
4
|
+
if (!text || /^SKIP\b/i.test(text))
|
|
5
|
+
return null;
|
|
6
|
+
const sentence = (text.match(/^.+?[.!](?=\s|[A-Z]|$)/)?.[0] ?? text).trim();
|
|
7
|
+
if (sentence.includes("`") || sentence.includes(`
|
|
8
|
+
`) || sentence.split(/\s+/).length > maxWords)
|
|
9
|
+
return null;
|
|
10
|
+
return sentence;
|
|
11
|
+
}
|
|
12
|
+
|
|
2
13
|
class ConstellationError extends Error {
|
|
3
14
|
status;
|
|
4
15
|
code;
|
|
@@ -300,6 +311,30 @@ class RequestClient {
|
|
|
300
311
|
resolve: (input, signal) => this.#call("/v1/registry/resolve", "POST", input, signal)
|
|
301
312
|
};
|
|
302
313
|
}
|
|
314
|
+
get openers() {
|
|
315
|
+
return {
|
|
316
|
+
create: async (input, signal) => await this.#call("/v1/openers", "POST", input, signal) ?? null,
|
|
317
|
+
sentence: async (id, options = {}) => {
|
|
318
|
+
let text = "";
|
|
319
|
+
for await (const event of this.#events(id, { signal: options.signal })) {
|
|
320
|
+
if (event.type === "model.completed") {
|
|
321
|
+
const message = event.data.message;
|
|
322
|
+
text = message?.text ?? text;
|
|
323
|
+
break;
|
|
324
|
+
}
|
|
325
|
+
if (event.type === "model.failed" || event.type === "model.cancelled")
|
|
326
|
+
return null;
|
|
327
|
+
if (event.type === "model.delta") {
|
|
328
|
+
for (const entry of event.data.events ?? []) {
|
|
329
|
+
if (entry.event?.type === "text_delta")
|
|
330
|
+
text += entry.event.delta ?? "";
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return parseOpenerSentence(text, options.maxWords);
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
}
|
|
303
338
|
get requests() {
|
|
304
339
|
return {
|
|
305
340
|
submit: (input, signal) => this.#submit(input, signal),
|
|
@@ -770,6 +805,7 @@ export {
|
|
|
770
805
|
uuid7,
|
|
771
806
|
processEvent,
|
|
772
807
|
prepareResponse,
|
|
808
|
+
parseOpenerSentence,
|
|
773
809
|
normalizeTimestamp,
|
|
774
810
|
PermanentEventError,
|
|
775
811
|
PERMANENT_RESPONSE_CODES,
|
|
@@ -304,6 +304,24 @@ export type ModelDeltaEvent = {
|
|
|
304
304
|
};
|
|
305
305
|
};
|
|
306
306
|
export type RequestEvent = WebhookEvent | ModelDeltaEvent;
|
|
307
|
+
export type OpenerTurn = {
|
|
308
|
+
role: "user" | "assistant";
|
|
309
|
+
text: string;
|
|
310
|
+
};
|
|
311
|
+
export type OpenerInput = {
|
|
312
|
+
/** Stable per turn, so a retry never admits a second opener. */
|
|
313
|
+
idempotencyKey: string;
|
|
314
|
+
workspaceId: string;
|
|
315
|
+
userId?: string;
|
|
316
|
+
externalId?: string;
|
|
317
|
+
planId?: string;
|
|
318
|
+
/** The message the user just sent. */
|
|
319
|
+
message: string;
|
|
320
|
+
/** Earlier turns, oldest first; operator settings decide how many are used. */
|
|
321
|
+
history?: OpenerTurn[];
|
|
322
|
+
};
|
|
323
|
+
/** The opener line to show: one sentence, no code, within `maxWords`; null for SKIP or anything else. */
|
|
324
|
+
export declare function parseOpenerSentence(raw: string, maxWords?: number): string | null;
|
|
307
325
|
export type Page<T> = {
|
|
308
326
|
items: T[];
|
|
309
327
|
total: number;
|
|
@@ -503,6 +521,22 @@ export declare class RequestClient {
|
|
|
503
521
|
list: (scope: ModelScope, signal?: AbortSignal) => Promise<Json>;
|
|
504
522
|
resolve: (input: ModelResolution, signal?: AbortSignal) => Promise<Json>;
|
|
505
523
|
};
|
|
524
|
+
/**
|
|
525
|
+
* Opening lines: an operator-configured short model call, made when the user
|
|
526
|
+
* sends, naming what the assistant does first. create admits it as an
|
|
527
|
+
* ordinary request; sentence waits for it to end and returns the line to
|
|
528
|
+
* show, or null for SKIP, a failure, or an answer that breaks the format.
|
|
529
|
+
*/
|
|
530
|
+
get openers(): {
|
|
531
|
+
/** The opener request, or null when the operator has turned openers off. */
|
|
532
|
+
create: (input: OpenerInput, signal?: AbortSignal) => Promise<{
|
|
533
|
+
id: string;
|
|
534
|
+
} | null>;
|
|
535
|
+
sentence: (id: string, options?: {
|
|
536
|
+
signal?: AbortSignal;
|
|
537
|
+
maxWords?: number;
|
|
538
|
+
}) => Promise<string | null>;
|
|
539
|
+
};
|
|
506
540
|
/** Durable requests. create returns an ID; execution continues independently. */
|
|
507
541
|
get requests(): {
|
|
508
542
|
submit: (input: Admission, signal?: AbortSignal) => Promise<AdmissionReceipt>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** External server SDK. Operator APIs and cookie sessions are internal-only clients. */
|
|
2
2
|
import { RequestClient, type WebhookEvent, type Json, type Page, type PageQuery, type ModelResolution, type RequestRecord, type RequestEvent, type RecordTypes, type Timeline, type TimelineRow, type RequestListQuery, type RequestRecordsQuery, type RequestTimings, type TokenUsage } from "../../client-core/src/index";
|
|
3
|
-
export { ConstellationError, uuid7, normalizeTimestamp } from "../../client-core/src/index";
|
|
4
|
-
export type { InferenceParameters, Json, Tool, ToolCall, Message, RequestEventModes, RequestInput, Admission, AdmissionReceipt, ResponseOutcome, ObservationResponse, Observations, EventReference, ModelCompletedEvent, ModelDeltaEvent, ModelStreamFrame, RequestTimings, TimingInterval, TokenUsage, TokenPrice, CustomerPricing, BillingFacts, Status, RequestRecord, Step, Attempt, Span, TimelineRow, Timeline, Log, Inspection, RecordTypes, RequestEvent, Page, PageQuery, ModelScope, ModelResolution, WebhookEvent, RequestRecordsQuery, RequestListQuery } from "../../client-core/src/index";
|
|
3
|
+
export { ConstellationError, uuid7, normalizeTimestamp, parseOpenerSentence } from "../../client-core/src/index";
|
|
4
|
+
export type { InferenceParameters, Json, Tool, ToolCall, Message, RequestEventModes, RequestInput, Admission, AdmissionReceipt, ResponseOutcome, ObservationResponse, Observations, EventReference, ModelCompletedEvent, ModelDeltaEvent, ModelStreamFrame, RequestTimings, TimingInterval, TokenUsage, TokenPrice, CustomerPricing, BillingFacts, Status, RequestRecord, Step, Attempt, Span, TimelineRow, Timeline, Log, Inspection, RecordTypes, RequestEvent, Page, PageQuery, ModelScope, ModelResolution, WebhookEvent, RequestRecordsQuery, RequestListQuery, OpenerInput, OpenerTurn } from "../../client-core/src/index";
|
|
5
5
|
/** OpenAPI contract filtered to this key's permissions and scope. */
|
|
6
6
|
export type DiscoveryDocument = {
|
|
7
7
|
openapi: string;
|