@orkestrel/agent 0.0.42 → 0.0.44
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/src/core/index.cjs +107 -13
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +73 -3
- package/dist/src/core/index.d.ts +73 -3
- package/dist/src/core/index.js +107 -15
- package/dist/src/core/index.js.map +1 -1
- package/package.json +10 -10
package/dist/src/core/index.cjs
CHANGED
|
@@ -5228,6 +5228,32 @@ function intersectFilters(parent, child) {
|
|
|
5228
5228
|
};
|
|
5229
5229
|
}
|
|
5230
5230
|
/**
|
|
5231
|
+
* Resolves the workspace a run renders and acts on: the one `selected` names, else the registry's
|
|
5232
|
+
* active one, kept only while `allowed` admits its id.
|
|
5233
|
+
*
|
|
5234
|
+
* @remarks
|
|
5235
|
+
* A selection the registry does not hold resolves to `undefined` and never falls back to the active
|
|
5236
|
+
* workspace. `allowed` is three-way, as {@link import('../helpers.js').filterAllowList} reads it.
|
|
5237
|
+
* `AgentContext.build`, the caller an agent run hands each tool call, and a ledger's calibration
|
|
5238
|
+
* resolve through it, so what a request renders and what a call receives come from one rule.
|
|
5239
|
+
*
|
|
5240
|
+
* @param workspaces - The workspace registry to read
|
|
5241
|
+
* @param selected - The id a `switch` call or the `workspace` option selected, or `undefined`
|
|
5242
|
+
* @param allowed - The ceiling's `workspaces` list (`undefined` ⇒ every id, `[]` ⇒ none)
|
|
5243
|
+
* @returns The workspace, or `undefined` when none resolves
|
|
5244
|
+
*
|
|
5245
|
+
* @example
|
|
5246
|
+
* ```ts
|
|
5247
|
+
* import { resolveWorkspace } from '@orkestrel/agent'
|
|
5248
|
+
*
|
|
5249
|
+
* resolveWorkspace(agent.context.workspaces, 'returns', ['returns']) // the registered returns workspace
|
|
5250
|
+
* ```
|
|
5251
|
+
*/
|
|
5252
|
+
function resolveWorkspace(workspaces, selected, allowed) {
|
|
5253
|
+
const workspace = selected === void 0 ? workspaces.active : workspaces.workspace(selected);
|
|
5254
|
+
return workspace !== void 0 && filterAllowList(allowed, [workspace.id], (id) => id).length > 0 ? workspace : void 0;
|
|
5255
|
+
}
|
|
5256
|
+
/**
|
|
5231
5257
|
* Renders one index line for a memo or a skill — `- name: description`, the built-in `render` of
|
|
5232
5258
|
* the memo and skill managers.
|
|
5233
5259
|
*
|
|
@@ -6283,10 +6309,8 @@ var AgentContext = class {
|
|
|
6283
6309
|
return skill === void 0 || skill.content.trim() === "" ? [] : [skill];
|
|
6284
6310
|
}), renderSkillBody, void 0);
|
|
6285
6311
|
if (bodies !== void 0) parts.push(bodies);
|
|
6286
|
-
const
|
|
6287
|
-
const
|
|
6288
|
-
const shown = filterAllowList(scope.workspaces, workspace === void 0 ? [] : [workspace], (one) => one.id);
|
|
6289
|
-
const files = filterAllowList(scope.files, shown.flatMap((one) => one.files()), (one) => one.path);
|
|
6312
|
+
const workspace = resolveWorkspace(this.#workspaces, options?.disclosure?.workspace, scope.workspaces);
|
|
6313
|
+
const files = filterAllowList(scope.files, workspace?.files() ?? [], (one) => one.path);
|
|
6290
6314
|
const documented = renderSection(WORKSPACE_SECTION_HEADER, files.flatMap((file) => (0, _orkestrel_workspace.isTextContent)(file.content) ? [{
|
|
6291
6315
|
path: file.path,
|
|
6292
6316
|
language: file.content.language,
|
|
@@ -7253,6 +7277,35 @@ function isAuthorityDecision(value) {
|
|
|
7253
7277
|
reason: _orkestrel_contract.isString
|
|
7254
7278
|
}, ["reason"])(value);
|
|
7255
7279
|
}
|
|
7280
|
+
/**
|
|
7281
|
+
* Checks whether a value is an agent caller: a plain record whose own keys are exactly `workspace`
|
|
7282
|
+
* and `files`, whose `workspace` is `undefined` or an object, and whose `files` is `undefined` or an
|
|
7283
|
+
* array of strings.
|
|
7284
|
+
*
|
|
7285
|
+
* @remarks
|
|
7286
|
+
* Total: each member is read once, and an omitted, inherited, or undeclared member, a throwing
|
|
7287
|
+
* accessor, and a revoked `Proxy` return false rather than throw. It checks the shape a caller
|
|
7288
|
+
* carries, never that `workspace` is a live workspace: a value that crossed a wire passes when it
|
|
7289
|
+
* holds that shape, so accept its `workspace` only as the very instance your own registry holds
|
|
7290
|
+
* under that id.
|
|
7291
|
+
*
|
|
7292
|
+
* @param value - The unknown caller candidate, such as `ToolContext.caller`
|
|
7293
|
+
* @returns True if the value satisfies the caller contract; false otherwise
|
|
7294
|
+
*
|
|
7295
|
+
* @example
|
|
7296
|
+
* ```ts
|
|
7297
|
+
* isAgentCaller({ workspace: undefined, files: undefined }) // true
|
|
7298
|
+
* isAgentCaller({ workspace: 'returns' }) // false
|
|
7299
|
+
* ```
|
|
7300
|
+
*/
|
|
7301
|
+
function isAgentCaller(value) {
|
|
7302
|
+
return (0, _orkestrel_contract.holds)(() => {
|
|
7303
|
+
if (!(0, _orkestrel_contract.isRecord)(value) || !(0, _orkestrel_contract.matchesExactKeys)(value, ["workspace", "files"])) return false;
|
|
7304
|
+
const workspace = value.workspace;
|
|
7305
|
+
const files = value.files;
|
|
7306
|
+
return (workspace === void 0 || (0, _orkestrel_contract.isObject)(workspace)) && (files === void 0 || (0, _orkestrel_contract.arrayOf)(_orkestrel_contract.isString)(files));
|
|
7307
|
+
});
|
|
7308
|
+
}
|
|
7256
7309
|
// src/core/agents/helpers.ts
|
|
7257
7310
|
/**
|
|
7258
7311
|
* Projects an unknown value onto a fresh, exact `JSONValue` representation of an
|
|
@@ -8617,6 +8670,7 @@ function collectDisclosure(conversation, builtins) {
|
|
|
8617
8670
|
* registers under a built-in's name is never read: `tool` and `execute` answer a built-in's name
|
|
8618
8671
|
* from the run's manager and every other name from the host's. Each handler reads the ceiling when
|
|
8619
8672
|
* it runs, the context scope intersected with the run scope at that moment, never a turn's copy.
|
|
8673
|
+
* The `caller` each call receives reads the ceiling the same way, as the call starts.
|
|
8620
8674
|
*/
|
|
8621
8675
|
var AgentRun = class {
|
|
8622
8676
|
#context;
|
|
@@ -8629,6 +8683,7 @@ var AgentRun = class {
|
|
|
8629
8683
|
#ceiling = {};
|
|
8630
8684
|
#shown = { skills: [] };
|
|
8631
8685
|
#ids = [];
|
|
8686
|
+
#files = [];
|
|
8632
8687
|
#advertised = [];
|
|
8633
8688
|
#snapshot;
|
|
8634
8689
|
#selection;
|
|
@@ -8712,6 +8767,31 @@ var AgentRun = class {
|
|
|
8712
8767
|
return this.#advertised.some((definition) => definition.name === "switch");
|
|
8713
8768
|
}
|
|
8714
8769
|
/**
|
|
8770
|
+
* Returns what a tool call receives as `ToolContext.caller`: the workspace instance the working
|
|
8771
|
+
* head rendered, kept only while the ceiling at this moment admits its id, and that ceiling's
|
|
8772
|
+
* `files` list.
|
|
8773
|
+
*
|
|
8774
|
+
* @remarks
|
|
8775
|
+
* The instance is the one the head's build resolved, never the registry's `active` pointer at the
|
|
8776
|
+
* call, so a host's `switch` made while the provider answers reaches the next turn's head and not
|
|
8777
|
+
* this call. Each read of this getter reads the `workspaces` and `files` lists of the context
|
|
8778
|
+
* scope and the run scope one time each, and no other list, so a call reads them as it starts, a
|
|
8779
|
+
* narrowing made after the turn's decision reaches that call, and a turn still reads its `tools`
|
|
8780
|
+
* list once.
|
|
8781
|
+
*
|
|
8782
|
+
* @returns A fresh caller
|
|
8783
|
+
*/
|
|
8784
|
+
get caller() {
|
|
8785
|
+
const outer = this.#context.scope;
|
|
8786
|
+
const inner = this.#scope;
|
|
8787
|
+
const rendered = this.#head?.rendered;
|
|
8788
|
+
const [workspace] = filterAllowList(intersectKeys(outer?.workspaces, inner?.workspaces), rendered === void 0 ? [] : [rendered], (one) => one.id);
|
|
8789
|
+
return {
|
|
8790
|
+
workspace,
|
|
8791
|
+
files: intersectKeys(outer?.files, inner?.files)
|
|
8792
|
+
};
|
|
8793
|
+
}
|
|
8794
|
+
/**
|
|
8715
8795
|
* Returns the selection the working head rendered.
|
|
8716
8796
|
*
|
|
8717
8797
|
* @returns The selection, or undefined before the first build
|
|
@@ -8735,8 +8815,10 @@ var AgentRun = class {
|
|
|
8735
8815
|
* `load`, `unload`, or `switch` is enabled, and only the records of an enabled built-in count.
|
|
8736
8816
|
* Registered skills hold their tools back only while `load` is enabled. The view compared with
|
|
8737
8817
|
* the working head's is the ceiling's `instructions`, `skills`, `memos`, `files`, and
|
|
8738
|
-
* `workspaces` lists, the shown skills by id, the shown workspace,
|
|
8739
|
-
*
|
|
8818
|
+
* `workspaces` lists, the shown skills by id, the shown workspace, the files that workspace
|
|
8819
|
+
* renders under the ceiling's `files` list, compared by identity, and whether `switch` is
|
|
8820
|
+
* advertised. An edit to a rendered file, by a tool or by the host, therefore makes the head
|
|
8821
|
+
* stale, and an edit to a file no build renders does not.
|
|
8740
8822
|
*
|
|
8741
8823
|
* @returns True if the working head was built with another view and must be rebuilt; false otherwise
|
|
8742
8824
|
*/
|
|
@@ -8751,13 +8833,19 @@ var AgentRun = class {
|
|
|
8751
8833
|
this.#ceiling = ceiling;
|
|
8752
8834
|
this.#shown = shown;
|
|
8753
8835
|
this.#ids = shown.skills.flatMap((name) => this.#context.skills.skill(name)?.id ?? []);
|
|
8836
|
+
this.#files = filterAllowList(ceiling.files, resolveWorkspace(this.#context.workspaces, shown.workspace, ceiling.workspaces)?.files() ?? [], (file) => file.path);
|
|
8754
8837
|
this.#advertised = filterAdvertisedTools(this.#candidates(ceiling), ceiling.tools, this.#builtins.has("load") ? this.#context.skills.skills() : [], shown.skills);
|
|
8755
8838
|
const head = this.#head;
|
|
8756
|
-
return head === void 0 || !matchesHeadLists(head.ceiling, ceiling) || head.ids.length !== this.#ids.length || head.ids.some((id, index) => id !== this.#ids[index]) || head.workspace !== shown.workspace || head.switchable !== this.switchable;
|
|
8839
|
+
return head === void 0 || !matchesHeadLists(head.ceiling, ceiling) || head.ids.length !== this.#ids.length || head.ids.some((id, index) => id !== this.#ids[index]) || head.workspace !== shown.workspace || head.switchable !== this.switchable || head.files.length !== this.#files.length || head.files.some((file, index) => file !== this.#files[index]);
|
|
8757
8840
|
}
|
|
8758
8841
|
/**
|
|
8759
|
-
* Records what the working head was built with: the selection, the built array's length,
|
|
8760
|
-
*
|
|
8842
|
+
* Records what the working head was built with: the selection, the built array's length, the
|
|
8843
|
+
* view the last `observe` resolved, and the workspace instance the build rendered.
|
|
8844
|
+
*
|
|
8845
|
+
* @remarks
|
|
8846
|
+
* Call it right after the build: it resolves the rendered workspace from the inputs the build
|
|
8847
|
+
* read, the shown workspace and the context scope's `workspaces` list intersected with the
|
|
8848
|
+
* snapshot's.
|
|
8761
8849
|
*
|
|
8762
8850
|
* @param selection - The selection the build rendered
|
|
8763
8851
|
* @param length - The length of the built array
|
|
@@ -8769,7 +8857,9 @@ var AgentRun = class {
|
|
|
8769
8857
|
ceiling: this.#ceiling,
|
|
8770
8858
|
ids: this.#ids,
|
|
8771
8859
|
workspace: this.#shown.workspace,
|
|
8772
|
-
switchable: this.switchable
|
|
8860
|
+
switchable: this.switchable,
|
|
8861
|
+
files: this.#files,
|
|
8862
|
+
rendered: resolveWorkspace(this.#context.workspaces, this.#shown.workspace, intersectKeys(this.#context.scope?.workspaces, this.#snapshot?.workspaces))
|
|
8773
8863
|
};
|
|
8774
8864
|
}
|
|
8775
8865
|
/**
|
|
@@ -9674,7 +9764,10 @@ var Agent = class {
|
|
|
9674
9764
|
const { allowed, denials } = authorization;
|
|
9675
9765
|
const entries = [...allowed].sort(([left], [right]) => left - right);
|
|
9676
9766
|
const started = entries.map(([, { call, tool }]) => {
|
|
9677
|
-
if (!this.#changed(run, call, tool, advertised)) return run.execute(call, {
|
|
9767
|
+
if (!this.#changed(run, call, tool, advertised)) return run.execute(call, {
|
|
9768
|
+
signal,
|
|
9769
|
+
caller: run.caller
|
|
9770
|
+
});
|
|
9678
9771
|
this.#emitter.emit("deny", call, `${call.name} changed after its decision`, void 0);
|
|
9679
9772
|
return denyCall(call, AUTHORITY_NOTES.denied);
|
|
9680
9773
|
});
|
|
@@ -13675,8 +13768,7 @@ var Ledger = class {
|
|
|
13675
13768
|
async #measureScale(head, bare, signal) {
|
|
13676
13769
|
const rate = bare / estimateMessages(head);
|
|
13677
13770
|
const workspace = this.#show(intersectFilters(this.#agent.context.scope, void 0)).workspace;
|
|
13678
|
-
const
|
|
13679
|
-
const files = ((workspace === void 0 ? workspaces.active : workspaces.workspace(workspace))?.files() ?? []).flatMap((file) => (0, _orkestrel_workspace.isTextContent)(file.content) ? [file.path] : []);
|
|
13771
|
+
const files = (resolveWorkspace(this.#agent.context.workspaces, workspace, void 0)?.files() ?? []).flatMap((file) => (0, _orkestrel_workspace.isTextContent)(file.content) ? [file.path] : []);
|
|
13680
13772
|
const shown = this.#agent.context.build({
|
|
13681
13773
|
selection: {
|
|
13682
13774
|
messages: [],
|
|
@@ -14960,6 +15052,7 @@ exports.instructionInputShape = instructionInputShape;
|
|
|
14960
15052
|
exports.intersectFilters = intersectFilters;
|
|
14961
15053
|
exports.intersectKeys = intersectKeys;
|
|
14962
15054
|
exports.isAgentBuiltin = isAgentBuiltin;
|
|
15055
|
+
exports.isAgentCaller = isAgentCaller;
|
|
14963
15056
|
exports.isAgentError = isAgentError;
|
|
14964
15057
|
exports.isAgentJobError = isAgentJobError;
|
|
14965
15058
|
exports.isAuthorityDecision = isAuthorityDecision;
|
|
@@ -15092,6 +15185,7 @@ exports.requireWorkspace = requireWorkspace;
|
|
|
15092
15185
|
exports.resolveDecision = resolveDecision;
|
|
15093
15186
|
exports.resolveDisclosure = resolveDisclosure;
|
|
15094
15187
|
exports.resolvePredict = resolvePredict;
|
|
15188
|
+
exports.resolveWorkspace = resolveWorkspace;
|
|
15095
15189
|
exports.sanitizeToken = sanitizeToken;
|
|
15096
15190
|
exports.sanitizeUsage = sanitizeUsage;
|
|
15097
15191
|
exports.scanAmendments = scanAmendments;
|