@astralform/js 9.3.0 → 9.4.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.cjs +90 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +94 -3
- package/dist/index.d.ts +94 -3
- package/dist/index.js +90 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -500,6 +500,79 @@ var AstralformClient = class {
|
|
|
500
500
|
`/v1/code/projects/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`
|
|
501
501
|
);
|
|
502
502
|
}
|
|
503
|
+
},
|
|
504
|
+
/**
|
|
505
|
+
* Code groups: a user-named container under one repository, for a feature
|
|
506
|
+
* whose work outlives a single session. Its sessions share one plan and one
|
|
507
|
+
* set of notes, so what one writes the others read.
|
|
508
|
+
*
|
|
509
|
+
* A group is a LABEL, not a binding — unlike a task's project, which is
|
|
510
|
+
* written once on the first turn. A task may join, move between, or leave
|
|
511
|
+
* groups at any time, and a deleted group's sessions survive as ungrouped.
|
|
512
|
+
*
|
|
513
|
+
* The server enforces three things worth knowing before you render a
|
|
514
|
+
* failure: a group that is not this user's answers `404` (never `403`, so a
|
|
515
|
+
* group id cannot be probed); filing a task into a group under a DIFFERENT
|
|
516
|
+
* repository than the task's answers `409`; and the group's plan and notes
|
|
517
|
+
* are deleted with the group, while each session keeps its own.
|
|
518
|
+
*/
|
|
519
|
+
groups: {
|
|
520
|
+
/**
|
|
521
|
+
* This user's groups, oldest first. Pass a repository to narrow to one
|
|
522
|
+
* repository's — the composer's picker does; the sidebar asks once and
|
|
523
|
+
* nests them itself.
|
|
524
|
+
*/
|
|
525
|
+
list: async (repository) => {
|
|
526
|
+
const query = repository ? `?repository=${encodeURIComponent(repository)}` : "";
|
|
527
|
+
const raw = await this.get(`/v1/code/groups${query}`);
|
|
528
|
+
return raw.map((g) => camelizeKeys(g));
|
|
529
|
+
},
|
|
530
|
+
/**
|
|
531
|
+
* Create a group under a repository. The repository goes through the same
|
|
532
|
+
* normaliser the Projects surface uses, so a pasted GitHub URL is accepted
|
|
533
|
+
* and anything that is not `owner/repo` is refused.
|
|
534
|
+
*/
|
|
535
|
+
create: async (repository, title) => {
|
|
536
|
+
const raw = await this.post("/v1/code/groups", { repository, title });
|
|
537
|
+
return camelizeKeys(raw);
|
|
538
|
+
},
|
|
539
|
+
/** Rename a group. A group that is not this user's answers `404`. */
|
|
540
|
+
rename: async (groupId, title) => {
|
|
541
|
+
const raw = await this.patch(`/v1/code/groups/${encodeURIComponent(groupId)}`, { title });
|
|
542
|
+
return camelizeKeys(raw);
|
|
543
|
+
},
|
|
544
|
+
/**
|
|
545
|
+
* Delete a group. Its tasks survive and become ungrouped, each keeping its
|
|
546
|
+
* own plan and notes; the group's SHARED documents are deleted with it.
|
|
547
|
+
*/
|
|
548
|
+
remove: async (groupId) => {
|
|
549
|
+
await this.del(`/v1/code/groups/${encodeURIComponent(groupId)}`);
|
|
550
|
+
},
|
|
551
|
+
/**
|
|
552
|
+
* File a task into a group. Idempotent — filing an already-filed task
|
|
553
|
+
* again is the same state, not an error. Refused with `409` when the task
|
|
554
|
+
* belongs to a different repository than the group, because it would
|
|
555
|
+
* render nowhere in the sidebar.
|
|
556
|
+
*/
|
|
557
|
+
assign: async (groupId, conversationId) => {
|
|
558
|
+
const raw = await this.post(
|
|
559
|
+
`/v1/code/groups/${encodeURIComponent(groupId)}/tasks/${encodeURIComponent(conversationId)}`,
|
|
560
|
+
void 0
|
|
561
|
+
);
|
|
562
|
+
return camelizeKeys(raw);
|
|
563
|
+
},
|
|
564
|
+
/**
|
|
565
|
+
* Take a task out of its group. The task and its documents are untouched.
|
|
566
|
+
*
|
|
567
|
+
* Deliberately not strict about WHICH group the task is in: a task that is
|
|
568
|
+
* in a different one (or in none) already satisfies "this task should not
|
|
569
|
+
* be grouped", so the call clears it rather than refusing.
|
|
570
|
+
*/
|
|
571
|
+
unassign: async (groupId, conversationId) => {
|
|
572
|
+
await this.del(
|
|
573
|
+
`/v1/code/groups/${encodeURIComponent(groupId)}/tasks/${encodeURIComponent(conversationId)}`
|
|
574
|
+
);
|
|
575
|
+
}
|
|
503
576
|
}
|
|
504
577
|
};
|
|
505
578
|
if (isApiKeyConfig(config)) {
|
|
@@ -1061,7 +1134,11 @@ var AstralformClient = class {
|
|
|
1061
1134
|
// A mode this SDK does not know must not reach a `switch` typed as
|
|
1062
1135
|
// `VoicePolishMode`; `structured` is the server's own default.
|
|
1063
1136
|
defaultMode: isVoicePolishMode(raw.default_mode) ? raw.default_mode : "structured",
|
|
1064
|
-
|
|
1137
|
+
// Deliberately not read from the wire. The field was retired from the
|
|
1138
|
+
// platform (2026-10-09): no shipped client implements pause detection
|
|
1139
|
+
// and the server no longer sends it, so an older server's stored value
|
|
1140
|
+
// must not resurrect it.
|
|
1141
|
+
silenceAutoStopSeconds: 2,
|
|
1065
1142
|
// Deliberately not read from the wire. Auto-send was removed from the
|
|
1066
1143
|
// platform (2026-09-14) and the server pins `auto_send` to false; an
|
|
1067
1144
|
// older server still sending `true` must not make a client auto-send, so
|
|
@@ -1718,22 +1795,24 @@ function translateWireEvent(wire) {
|
|
|
1718
1795
|
status: wire.status,
|
|
1719
1796
|
final: wire.final
|
|
1720
1797
|
};
|
|
1721
|
-
case "message_stop":
|
|
1798
|
+
case "message_stop": {
|
|
1799
|
+
const usage = wire.usage ?? {};
|
|
1722
1800
|
return {
|
|
1723
1801
|
type: "message_stop",
|
|
1724
1802
|
turnId: wire.turn_id,
|
|
1725
1803
|
jobId: wire.job_id,
|
|
1726
1804
|
stopReason: wire.stop_reason,
|
|
1727
1805
|
usage: {
|
|
1728
|
-
inputTokens:
|
|
1729
|
-
outputTokens:
|
|
1730
|
-
cachedTokens:
|
|
1731
|
-
cacheCreationTokens:
|
|
1806
|
+
inputTokens: usage.input_tokens ?? 0,
|
|
1807
|
+
outputTokens: usage.output_tokens ?? 0,
|
|
1808
|
+
cachedTokens: usage.cached_tokens ?? 0,
|
|
1809
|
+
cacheCreationTokens: usage.cache_creation_tokens ?? 0
|
|
1732
1810
|
},
|
|
1733
1811
|
ttfbMs: wire.ttfb_ms,
|
|
1734
1812
|
totalMs: wire.total_ms,
|
|
1735
1813
|
stallCount: wire.stall_count
|
|
1736
1814
|
};
|
|
1815
|
+
}
|
|
1737
1816
|
case "stall":
|
|
1738
1817
|
return {
|
|
1739
1818
|
type: "stall",
|
|
@@ -2085,7 +2164,7 @@ var ChatSession = class {
|
|
|
2085
2164
|
if (!(err instanceof DOMException && err.name === "AbortError")) {
|
|
2086
2165
|
this.emit({
|
|
2087
2166
|
type: "error",
|
|
2088
|
-
code: "connection_error",
|
|
2167
|
+
code: err instanceof AstralformError ? err.code : "connection_error",
|
|
2089
2168
|
message: err instanceof Error ? err.message : String(err),
|
|
2090
2169
|
blockPath: null
|
|
2091
2170
|
});
|
|
@@ -2237,6 +2316,9 @@ var ChatSession = class {
|
|
|
2237
2316
|
if (typeof data?.seq === "number") {
|
|
2238
2317
|
this.lastSeq = data.seq;
|
|
2239
2318
|
}
|
|
2319
|
+
if (typeof data === "object" && data !== null && "data" in data && data.data === "[DONE]") {
|
|
2320
|
+
sawTerminal = true;
|
|
2321
|
+
}
|
|
2240
2322
|
continue;
|
|
2241
2323
|
}
|
|
2242
2324
|
parsed = data;
|
|
@@ -2366,7 +2448,7 @@ var ChatSession = class {
|
|
|
2366
2448
|
}
|
|
2367
2449
|
return;
|
|
2368
2450
|
case "block_delta":
|
|
2369
|
-
if (ownsTurnState && wire.delta
|
|
2451
|
+
if (ownsTurnState && wire.delta?.channel === "text" && this.currentTextPath !== null && pathEquals(this.currentTextPath, wire.path)) {
|
|
2370
2452
|
this.accumulatedText += wire.delta.text;
|
|
2371
2453
|
}
|
|
2372
2454
|
return;
|