@loopingai/core 0.8.2 → 0.8.3
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/round/turn.js +3 -2
- package/dist/subtasks/delegate.d.ts +29 -6
- package/dist/subtasks/delegate.js +26 -3
- package/package.json +1 -1
package/dist/round/turn.js
CHANGED
|
@@ -51,8 +51,9 @@ function byRound(branches) {
|
|
|
51
51
|
* than carried, from the durable rows that are the record of what happened.
|
|
52
52
|
*
|
|
53
53
|
* Failed and skipped branches are included so the model can disclose them rather
|
|
54
|
-
* than quietly answering as if the work had been done
|
|
55
|
-
*
|
|
54
|
+
* than quietly answering as if the work had been done — and, since a failed
|
|
55
|
+
* branch carries its reason in `output`, so it can tell a wall it should stop
|
|
56
|
+
* at from a hiccup worth retrying (see `delegateCallOutput`).
|
|
56
57
|
*/
|
|
57
58
|
function delegationPair(taskId, round, replyText, branches) {
|
|
58
59
|
const toolCallId = delegateToolCallId(taskId, round);
|
|
@@ -61,12 +61,29 @@ export declare function makeDelegateTool(types: SubtaskTypeRegistry, maxSubtasks
|
|
|
61
61
|
*/
|
|
62
62
|
export declare function delegateToolCallId(taskId: string, round: number): string;
|
|
63
63
|
/**
|
|
64
|
-
* One branch's outcome, as the tool result carries it. `output`
|
|
65
|
-
* branch
|
|
64
|
+
* One branch's outcome, as the tool result carries it. `output` carries the
|
|
65
|
+
* branch's report when it completed and its failure reason when it did not.
|
|
66
66
|
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
67
|
+
* **A failed branch says why, and that is a reversal worth explaining.** This
|
|
68
|
+
* used to be `null` for anything that did not complete, on the principle that
|
|
69
|
+
* internal diagnostics never reach the model. The principle was right about
|
|
70
|
+
* *diagnostics* and wrong about this field: what a facet writes into `error` is
|
|
71
|
+
* not a stack trace, it is a sentence addressed to the delegating model —
|
|
72
|
+
* "there is no checkout in this workspace yet… clone the repository before
|
|
73
|
+
* delegating", "every credential has reached its limit; send this request again
|
|
74
|
+
* after that". Withholding those left the parent with `status: "failed"` and
|
|
75
|
+
* nothing else, and a parent that cannot tell a transient failure from a
|
|
76
|
+
* permanent one retries. In the run that prompted this it retried twelve times
|
|
77
|
+
* over nine minutes, then apologised to the user for a wall it was never shown.
|
|
78
|
+
*
|
|
79
|
+
* What replaces the old rule is a constraint on the writer rather than a filter
|
|
80
|
+
* here: **an `error` is model-visible, so a facet must write it in words that
|
|
81
|
+
* are safe for one to read and act on.** Bounded by {@link MAX_OUTPUT_CHARS} on
|
|
82
|
+
* the way through, because a facet that ignores that is a context-window
|
|
83
|
+
* problem rather than a disclosure one.
|
|
84
|
+
*
|
|
85
|
+
* Still one field, not two. The model's question is "what came back from this
|
|
86
|
+
* branch", and `status` already says which kind of answer it is getting.
|
|
70
87
|
*
|
|
71
88
|
* A type alias, not an interface: this is serialized as the tool result's
|
|
72
89
|
* `JSONValue`, and only aliases get the implicit index signature that satisfies.
|
|
@@ -93,5 +110,11 @@ export type DelegateSubtaskOutcome = {
|
|
|
93
110
|
* and carries the durable `subtaskId`.
|
|
94
111
|
*/
|
|
95
112
|
export declare function delegateCallInput(reply: string, branches: CompositionBranch[]): DecompositionProposal;
|
|
96
|
-
/**
|
|
113
|
+
/**
|
|
114
|
+
* Rebuild one round's call result from its durable rows, in stable ordinal order.
|
|
115
|
+
*
|
|
116
|
+
* A completed branch reports its parts; any other branch reports its `error`, or
|
|
117
|
+
* `null` when it has none to give — a cancelled branch usually does not, and
|
|
118
|
+
* inventing a sentence for it would be worse than the absence.
|
|
119
|
+
*/
|
|
97
120
|
export declare function delegateCallOutput(branches: CompositionBranch[]): DelegateSubtaskOutcome[];
|
|
@@ -68,6 +68,21 @@ export function makeDelegateTool(types, maxSubtasks) {
|
|
|
68
68
|
export function delegateToolCallId(taskId, round) {
|
|
69
69
|
return `task_${taskId}_round_${round}_delegate`;
|
|
70
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Ceiling on one branch's `output`, applied to both halves of it.
|
|
73
|
+
*
|
|
74
|
+
* A round's history holds every branch of every earlier round, so this is
|
|
75
|
+
* multiplied by the whole delegation history rather than paid once. Generous
|
|
76
|
+
* enough for a report a subagent meant to be read, far short of a build log a
|
|
77
|
+
* failing one dumped into `error`.
|
|
78
|
+
*/
|
|
79
|
+
const MAX_OUTPUT_CHARS = 8_000;
|
|
80
|
+
function bounded(text) {
|
|
81
|
+
if (text.length <= MAX_OUTPUT_CHARS)
|
|
82
|
+
return text;
|
|
83
|
+
const suffix = "\n…[truncated]";
|
|
84
|
+
return `${text.slice(0, MAX_OUTPUT_CHARS - suffix.length)}${suffix}`;
|
|
85
|
+
}
|
|
71
86
|
/**
|
|
72
87
|
* Rebuild one round's call input from its durable rows, in stable ordinal order.
|
|
73
88
|
* Typed as {@link DecompositionProposal} — the same type the model's own calls
|
|
@@ -95,14 +110,22 @@ export function delegateCallInput(reply, branches) {
|
|
|
95
110
|
}))
|
|
96
111
|
};
|
|
97
112
|
}
|
|
98
|
-
/**
|
|
113
|
+
/**
|
|
114
|
+
* Rebuild one round's call result from its durable rows, in stable ordinal order.
|
|
115
|
+
*
|
|
116
|
+
* A completed branch reports its parts; any other branch reports its `error`, or
|
|
117
|
+
* `null` when it has none to give — a cancelled branch usually does not, and
|
|
118
|
+
* inventing a sentence for it would be worse than the absence.
|
|
119
|
+
*/
|
|
99
120
|
export function delegateCallOutput(branches) {
|
|
100
121
|
return branches.map((branch) => ({
|
|
101
122
|
subtaskId: branch.subtaskId,
|
|
102
123
|
type: branch.type,
|
|
103
124
|
status: branch.status,
|
|
104
125
|
output: branch.status === "completed"
|
|
105
|
-
? (branch.resultParts ?? []).map((part) => part.text).join("\n")
|
|
106
|
-
:
|
|
126
|
+
? bounded((branch.resultParts ?? []).map((part) => part.text).join("\n"))
|
|
127
|
+
: branch.error
|
|
128
|
+
? bounded(branch.error)
|
|
129
|
+
: null
|
|
107
130
|
}));
|
|
108
131
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loopingai/core",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.3",
|
|
4
4
|
"description": "Shared, mandatory foundation for Looping agents on Cloudflare Workers: zero-trust A2A, durable task lifecycle, delegation and subagent runtime, test harness.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"a2a",
|