toolnexus 0.19.0 → 0.20.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/dist/agents/home.js +4 -2
- package/dist/agents/runtime.d.ts +12 -3
- package/dist/agents/runtime.js +4 -3
- package/dist/builtin.d.ts +32 -2
- package/dist/builtin.js +324 -46
- package/dist/classifier.js +3 -1
- package/dist/client.d.ts +18 -4
- package/dist/client.js +68 -12
- package/package.json +2 -2
- package/src/agents/home.ts +4 -2
- package/src/agents/runtime.ts +12 -5
- package/src/builtin.ts +361 -46
- package/src/classifier.ts +3 -1
- package/src/client.ts +68 -12
package/src/client.ts
CHANGED
|
@@ -575,7 +575,7 @@ export class Client {
|
|
|
575
575
|
if (req.maxTokens) body.max_tokens = req.maxTokens
|
|
576
576
|
|
|
577
577
|
const signal = this.makeSignal(req.signal)
|
|
578
|
-
{
|
|
578
|
+
try {
|
|
579
579
|
const data = await this.llmCallJson(
|
|
580
580
|
`${this.opts.baseUrl.replace(/\/$/, "")}/chat/completions`,
|
|
581
581
|
{
|
|
@@ -603,6 +603,8 @@ export class Client {
|
|
|
603
603
|
model: this.opts.model,
|
|
604
604
|
raw: data,
|
|
605
605
|
}
|
|
606
|
+
} finally {
|
|
607
|
+
this.releaseSignal(signal)
|
|
606
608
|
}
|
|
607
609
|
}
|
|
608
610
|
|
|
@@ -637,7 +639,7 @@ export class Client {
|
|
|
637
639
|
if (tc) body.tool_choice = tc
|
|
638
640
|
|
|
639
641
|
const signal = this.makeSignal(req.signal)
|
|
640
|
-
{
|
|
642
|
+
try {
|
|
641
643
|
const data = await this.llmCallJson(
|
|
642
644
|
endpoint,
|
|
643
645
|
{
|
|
@@ -676,6 +678,8 @@ export class Client {
|
|
|
676
678
|
model: this.opts.model,
|
|
677
679
|
raw: data,
|
|
678
680
|
}
|
|
681
|
+
} finally {
|
|
682
|
+
this.releaseSignal(signal)
|
|
679
683
|
}
|
|
680
684
|
}
|
|
681
685
|
|
|
@@ -743,12 +747,30 @@ export class Client {
|
|
|
743
747
|
return [this.opts.systemPrompt ?? "", toolkit?.skillsPrompt() ?? ""].filter(Boolean).join("\n\n")
|
|
744
748
|
}
|
|
745
749
|
|
|
746
|
-
/**
|
|
750
|
+
/** Run-scoped timeout timers, cleared by `releaseSignal` when the run settles. */
|
|
751
|
+
private readonly runTimers = new WeakMap<AbortSignal, ReturnType<typeof setTimeout>>()
|
|
752
|
+
|
|
753
|
+
/** Drop a run's timeout timer. Idempotent, and safe on a signal that never had one. */
|
|
754
|
+
private releaseSignal(signal: AbortSignal): void {
|
|
755
|
+
const t = this.runTimers.get(signal)
|
|
756
|
+
if (t !== undefined) {
|
|
757
|
+
clearTimeout(t)
|
|
758
|
+
this.runTimers.delete(signal)
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
/** Build a run-scoped abort signal from the optional run-level timeout + an external signal.
|
|
763
|
+
*
|
|
764
|
+
* The timer is deliberately NOT `unref()`d. An unref'd timer cannot keep the event loop
|
|
765
|
+
* alive, so a run whose only pending work is a request that never settles — an injected
|
|
766
|
+
* `fetch`, an in-process transport, a stalled stream — drains the loop and the timeout never
|
|
767
|
+
* fires at all, which is the one case `timeoutMs` exists for. It is RELEASED instead: the
|
|
768
|
+
* caller clears it however the run leaves, so a finished run holds nothing open. */
|
|
747
769
|
private makeSignal(external?: AbortSignal): AbortSignal {
|
|
748
770
|
const ctrl = new AbortController()
|
|
749
771
|
if (this.opts.timeoutMs) {
|
|
750
772
|
const t = setTimeout(() => ctrl.abort(new Error(`run timeout after ${this.opts.timeoutMs}ms`)), this.opts.timeoutMs)
|
|
751
|
-
|
|
773
|
+
this.runTimers.set(ctrl.signal, t)
|
|
752
774
|
}
|
|
753
775
|
if (external) {
|
|
754
776
|
if (external.aborted) ctrl.abort(external.reason)
|
|
@@ -841,10 +863,47 @@ export class Client {
|
|
|
841
863
|
}
|
|
842
864
|
}
|
|
843
865
|
|
|
844
|
-
//
|
|
866
|
+
// The run-scoped timeout timer is owned by these four wrappers, so it is cleared however the
|
|
867
|
+
// run leaves: return, throw, or a consumer abandoning the stream half-way.
|
|
845
868
|
private async runOpenAI(prompt: PromptInput, toolkit: Toolkit | undefined, external?: AbortSignal, history?: any[]): Promise<RunResult> {
|
|
846
|
-
const key = resolveKey(this.opts)
|
|
847
869
|
const signal = this.makeSignal(external)
|
|
870
|
+
try {
|
|
871
|
+
return await this.runOpenAIWithSignal(signal, prompt, toolkit, history)
|
|
872
|
+
} finally {
|
|
873
|
+
this.releaseSignal(signal)
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
private async runAnthropic(prompt: PromptInput, toolkit: Toolkit | undefined, external?: AbortSignal, history?: any[]): Promise<RunResult> {
|
|
878
|
+
const signal = this.makeSignal(external)
|
|
879
|
+
try {
|
|
880
|
+
return await this.runAnthropicWithSignal(signal, prompt, toolkit, history)
|
|
881
|
+
} finally {
|
|
882
|
+
this.releaseSignal(signal)
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
private async *streamOpenAI(prompt: PromptInput, toolkit: Toolkit | undefined, external?: AbortSignal, history?: any[]): AsyncGenerator<StreamEvent, void, unknown> {
|
|
887
|
+
const signal = this.makeSignal(external)
|
|
888
|
+
try {
|
|
889
|
+
yield* this.streamOpenAIWithSignal(signal, prompt, toolkit, history)
|
|
890
|
+
} finally {
|
|
891
|
+
this.releaseSignal(signal)
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
private async *streamAnthropic(prompt: PromptInput, toolkit: Toolkit | undefined, external?: AbortSignal, history?: any[]): AsyncGenerator<StreamEvent, void, unknown> {
|
|
896
|
+
const signal = this.makeSignal(external)
|
|
897
|
+
try {
|
|
898
|
+
yield* this.streamAnthropicWithSignal(signal, prompt, toolkit, history)
|
|
899
|
+
} finally {
|
|
900
|
+
this.releaseSignal(signal)
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
// ---- OpenAI-style: POST {baseUrl}/chat/completions ----
|
|
905
|
+
private async runOpenAIWithSignal(signal: AbortSignal, prompt: PromptInput, toolkit: Toolkit | undefined, history?: any[]): Promise<RunResult> {
|
|
906
|
+
const key = resolveKey(this.opts)
|
|
848
907
|
const runStart = Date.now()
|
|
849
908
|
let messages: any[] = history && history.length ? [...history] : []
|
|
850
909
|
if (!messages.length) {
|
|
@@ -944,9 +1003,8 @@ export class Client {
|
|
|
944
1003
|
}
|
|
945
1004
|
|
|
946
1005
|
// ---- Anthropic-style: POST {baseUrl}/messages ----
|
|
947
|
-
private async
|
|
1006
|
+
private async runAnthropicWithSignal(signal: AbortSignal, prompt: PromptInput, toolkit: Toolkit | undefined, history?: any[]): Promise<RunResult> {
|
|
948
1007
|
const key = resolveKey(this.opts)
|
|
949
|
-
const signal = this.makeSignal(external)
|
|
950
1008
|
const base = this.opts.baseUrl.replace(/\/$/, "")
|
|
951
1009
|
const endpoint = base.endsWith("/v1") ? `${base}/messages` : `${base}/v1/messages`
|
|
952
1010
|
const system = this.system(toolkit)
|
|
@@ -1018,9 +1076,8 @@ export class Client {
|
|
|
1018
1076
|
}
|
|
1019
1077
|
|
|
1020
1078
|
// ---- Streaming: OpenAI-style ----
|
|
1021
|
-
private async *
|
|
1079
|
+
private async *streamOpenAIWithSignal(signal: AbortSignal, prompt: PromptInput, toolkit: Toolkit | undefined, history?: any[]): AsyncGenerator<StreamEvent, void, unknown> {
|
|
1022
1080
|
const key = resolveKey(this.opts)
|
|
1023
|
-
const signal = this.makeSignal(external)
|
|
1024
1081
|
const runStart = Date.now()
|
|
1025
1082
|
let messages: any[] = history && history.length ? [...history] : []
|
|
1026
1083
|
if (!messages.length) {
|
|
@@ -1114,9 +1171,8 @@ export class Client {
|
|
|
1114
1171
|
}
|
|
1115
1172
|
|
|
1116
1173
|
// ---- Streaming: Anthropic-style ----
|
|
1117
|
-
private async *
|
|
1174
|
+
private async *streamAnthropicWithSignal(signal: AbortSignal, prompt: PromptInput, toolkit: Toolkit | undefined, history?: any[]): AsyncGenerator<StreamEvent, void, unknown> {
|
|
1118
1175
|
const key = resolveKey(this.opts)
|
|
1119
|
-
const signal = this.makeSignal(external)
|
|
1120
1176
|
const runStart = Date.now()
|
|
1121
1177
|
const base = this.opts.baseUrl.replace(/\/$/, "")
|
|
1122
1178
|
const endpoint = base.endsWith("/v1") ? `${base}/messages` : `${base}/v1/messages`
|