@plurnk/plurnk-service 1.4.0 → 1.6.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/.env.defaults +37 -31
- package/INSTALL.md +16 -11
- package/README.md +1 -0
- package/SPEC.md +631 -397
- package/dist/Paths.d.ts.map +1 -1
- package/dist/Paths.js +2 -3
- package/dist/Paths.js.map +1 -1
- package/dist/build-info.json +1 -1
- package/dist/content/edit-collision.d.ts +5 -0
- package/dist/content/edit-collision.d.ts.map +1 -0
- package/dist/content/edit-collision.js +14 -0
- package/dist/content/edit-collision.js.map +1 -0
- package/dist/content/edit-receipt.d.ts +3 -2
- package/dist/content/edit-receipt.d.ts.map +1 -1
- package/dist/content/edit-receipt.js +58 -13
- package/dist/content/edit-receipt.js.map +1 -1
- package/dist/content/index.d.ts +5 -1
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +4 -1
- package/dist/content/index.js.map +1 -1
- package/dist/content/line-anchors.d.ts +41 -0
- package/dist/content/line-anchors.d.ts.map +1 -0
- package/dist/content/line-anchors.js +191 -0
- package/dist/content/line-anchors.js.map +1 -0
- package/dist/content/line-marker.d.ts +7 -3
- package/dist/content/line-marker.d.ts.map +1 -1
- package/dist/content/line-marker.js +2 -1
- package/dist/content/line-marker.js.map +1 -1
- package/dist/content/matcher.d.ts +1 -1
- package/dist/content/matcher.d.ts.map +1 -1
- package/dist/content/matcher.js +2 -2
- package/dist/content/matcher.js.map +1 -1
- package/dist/content/read-projector.d.ts +20 -0
- package/dist/content/read-projector.d.ts.map +1 -0
- package/dist/content/read-projector.js +122 -0
- package/dist/content/read-projector.js.map +1 -0
- package/dist/content/read-resolve.d.ts +2 -7
- package/dist/content/read-resolve.d.ts.map +1 -1
- package/dist/content/read-resolve.js +32 -107
- package/dist/content/read-resolve.js.map +1 -1
- package/dist/core/BranchReceipt.d.ts +0 -1
- package/dist/core/BranchReceipt.d.ts.map +1 -1
- package/dist/core/BranchReceipt.js +0 -3
- package/dist/core/BranchReceipt.js.map +1 -1
- package/dist/core/BudgetReadout.d.ts.map +1 -1
- package/dist/core/BudgetReadout.js +9 -2
- package/dist/core/BudgetReadout.js.map +1 -1
- package/dist/core/ChannelWrite.d.ts +3 -0
- package/dist/core/ChannelWrite.d.ts.map +1 -1
- package/dist/core/ChannelWrite.js +3 -3
- package/dist/core/ChannelWrite.js.map +1 -1
- package/dist/core/ChannelWrite.sql +4 -3
- package/dist/core/CoreSchemeServices.d.ts +10 -2
- package/dist/core/CoreSchemeServices.d.ts.map +1 -1
- package/dist/core/CoreSchemeServices.js.map +1 -1
- package/dist/core/Dispatcher.d.ts +14 -8
- package/dist/core/Dispatcher.d.ts.map +1 -1
- package/dist/core/Dispatcher.js +656 -312
- package/dist/core/Dispatcher.js.map +1 -1
- package/dist/core/DurableStatement.d.ts.map +1 -1
- package/dist/core/DurableStatement.js +2 -0
- package/dist/core/DurableStatement.js.map +1 -1
- package/dist/core/Engine.d.ts +24 -18
- package/dist/core/Engine.d.ts.map +1 -1
- package/dist/core/Engine.js +620 -392
- package/dist/core/Engine.js.map +1 -1
- package/dist/core/Engine.sql +188 -119
- package/dist/core/ExecutableTools.d.ts +10 -0
- package/dist/core/ExecutableTools.d.ts.map +1 -0
- package/dist/core/ExecutableTools.js +41 -0
- package/dist/core/ExecutableTools.js.map +1 -0
- package/dist/core/ExecutorRegistry.d.ts +3 -3
- package/dist/core/ExecutorRegistry.d.ts.map +1 -1
- package/dist/core/ExecutorRegistry.js +2 -2
- package/dist/core/ExecutorRegistry.js.map +1 -1
- package/dist/core/LogBody.d.ts +4 -1
- package/dist/core/LogBody.d.ts.map +1 -1
- package/dist/core/LogBody.js +46 -2
- package/dist/core/LogBody.js.map +1 -1
- package/dist/core/LogEntryProjection.d.ts +14 -0
- package/dist/core/LogEntryProjection.d.ts.map +1 -0
- package/dist/core/LogEntryProjection.js +38 -0
- package/dist/core/LogEntryProjection.js.map +1 -0
- package/dist/core/LoopLifecycle.d.ts +1 -2
- package/dist/core/LoopLifecycle.d.ts.map +1 -1
- package/dist/core/LoopLifecycle.js +1 -4
- package/dist/core/LoopLifecycle.js.map +1 -1
- package/dist/core/LoopLifecycle.sql +1 -4
- package/dist/core/ModelCall.d.ts +27 -0
- package/dist/core/ModelCall.d.ts.map +1 -0
- package/dist/core/ModelCall.js +125 -0
- package/dist/core/ModelCall.js.map +1 -0
- package/dist/core/PacketBuilder.d.ts +13 -12
- package/dist/core/PacketBuilder.d.ts.map +1 -1
- package/dist/core/PacketBuilder.js +146 -118
- package/dist/core/PacketBuilder.js.map +1 -1
- package/dist/core/ProblemLog.d.ts.map +1 -1
- package/dist/core/ProblemLog.js +1 -0
- package/dist/core/ProblemLog.js.map +1 -1
- package/dist/core/ProposalLifecycle.d.ts.map +1 -1
- package/dist/core/ProposalLifecycle.js +3 -4
- package/dist/core/ProposalLifecycle.js.map +1 -1
- package/dist/core/ProviderInstantiate.d.ts.map +1 -1
- package/dist/core/ProviderInstantiate.js +23 -6
- package/dist/core/ProviderInstantiate.js.map +1 -1
- package/dist/core/SchemeRegistry.js +7 -7
- package/dist/core/SchemeRegistry.js.map +1 -1
- package/dist/core/StrikeRail.d.ts +5 -2
- package/dist/core/StrikeRail.d.ts.map +1 -1
- package/dist/core/StrikeRail.js +10 -7
- package/dist/core/StrikeRail.js.map +1 -1
- package/dist/core/TerminalResult.d.ts +16 -0
- package/dist/core/TerminalResult.d.ts.map +1 -0
- package/dist/core/TerminalResult.js +49 -0
- package/dist/core/TerminalResult.js.map +1 -0
- package/dist/core/caps/CapsResolve.d.ts +5 -1
- package/dist/core/caps/CapsResolve.d.ts.map +1 -1
- package/dist/core/caps/CapsResolve.js +9 -5
- package/dist/core/caps/CapsResolve.js.map +1 -1
- package/dist/core/caps/DbChannelCaps.d.ts +1 -1
- package/dist/core/caps/DbChannelCaps.d.ts.map +1 -1
- package/dist/core/caps/DbChannelCaps.js +6 -4
- package/dist/core/caps/DbChannelCaps.js.map +1 -1
- package/dist/core/caps/DbEntryCaps.d.ts +2 -1
- package/dist/core/caps/DbEntryCaps.d.ts.map +1 -1
- package/dist/core/caps/DbEntryCaps.js +21 -8
- package/dist/core/caps/DbEntryCaps.js.map +1 -1
- package/dist/core/caps/DbNotifyCaps.d.ts +1 -1
- package/dist/core/caps/DbNotifyCaps.d.ts.map +1 -1
- package/dist/core/caps/DbNotifyCaps.js +6 -4
- package/dist/core/caps/DbNotifyCaps.js.map +1 -1
- package/dist/core/caps/DbProjectionCaps.d.ts +1 -0
- package/dist/core/caps/DbProjectionCaps.d.ts.map +1 -1
- package/dist/core/caps/DbProjectionCaps.js +29 -0
- package/dist/core/caps/DbProjectionCaps.js.map +1 -1
- package/dist/core/caps/DbSubscriptionCaps.d.ts +4 -6
- package/dist/core/caps/DbSubscriptionCaps.d.ts.map +1 -1
- package/dist/core/caps/DbSubscriptionCaps.js +27 -13
- package/dist/core/caps/DbSubscriptionCaps.js.map +1 -1
- package/dist/core/caps/SchemeCtxImpl.d.ts +11 -3
- package/dist/core/caps/SchemeCtxImpl.d.ts.map +1 -1
- package/dist/core/caps/SchemeCtxImpl.js +10 -8
- package/dist/core/caps/SchemeCtxImpl.js.map +1 -1
- package/dist/core/fork.d.ts.map +1 -1
- package/dist/core/fork.js +23 -7
- package/dist/core/fork.js.map +1 -1
- package/dist/core/fork.sql +35 -14
- package/dist/core/git-iso.d.ts +3 -2
- package/dist/core/git-iso.d.ts.map +1 -1
- package/dist/core/git-iso.js +27 -12
- package/dist/core/git-iso.js.map +1 -1
- package/dist/core/git-membership.d.ts +1 -0
- package/dist/core/git-membership.d.ts.map +1 -1
- package/dist/core/git-membership.js +87 -26
- package/dist/core/git-membership.js.map +1 -1
- package/dist/core/git-state.d.ts +8 -1
- package/dist/core/git-state.d.ts.map +1 -1
- package/dist/core/git-state.js +36 -17
- package/dist/core/git-state.js.map +1 -1
- package/dist/core/namespace.d.ts +1 -0
- package/dist/core/namespace.d.ts.map +1 -1
- package/dist/core/namespace.js +20 -0
- package/dist/core/namespace.js.map +1 -1
- package/dist/core/optimistic-settlement.d.ts +2 -0
- package/dist/core/optimistic-settlement.d.ts.map +1 -0
- package/dist/core/optimistic-settlement.js +14 -0
- package/dist/core/optimistic-settlement.js.map +1 -0
- package/dist/core/packet-wire.d.ts +5 -2
- package/dist/core/packet-wire.d.ts.map +1 -1
- package/dist/core/packet-wire.js +318 -114
- package/dist/core/packet-wire.js.map +1 -1
- package/dist/core/provider-accounting.d.ts +24 -0
- package/dist/core/provider-accounting.d.ts.map +1 -0
- package/dist/core/provider-accounting.js +76 -0
- package/dist/core/provider-accounting.js.map +1 -0
- package/dist/core/results.d.ts +4 -2
- package/dist/core/results.d.ts.map +1 -1
- package/dist/core/results.js +6 -0
- package/dist/core/results.js.map +1 -1
- package/dist/core/scheme-types.d.ts +0 -12
- package/dist/core/scheme-types.d.ts.map +1 -1
- package/dist/core/scheme-types.js.map +1 -1
- package/dist/core/search-gate.d.ts +2 -2
- package/dist/core/search-gate.d.ts.map +1 -1
- package/dist/core/search-gate.js +8 -8
- package/dist/core/search-gate.js.map +1 -1
- package/dist/core/token-ruler.js +1 -1
- package/dist/core/token-ruler.js.map +1 -1
- package/dist/core/turn-scheduler.js +1 -1
- package/dist/core/turn-scheduler.js.map +1 -1
- package/dist/core/worker-ops.sql +4 -4
- package/dist/core/workspace-settings.js +1 -1
- package/dist/core/workspace-settings.js.map +1 -1
- package/dist/digest/Digest.d.ts.map +1 -1
- package/dist/digest/Digest.js +349 -76
- package/dist/digest/Digest.js.map +1 -1
- package/dist/digest/digest.sql +42 -16
- package/dist/schemes/Exec.d.ts +4 -4
- package/dist/schemes/Exec.d.ts.map +1 -1
- package/dist/schemes/Exec.js +167 -134
- package/dist/schemes/Exec.js.map +1 -1
- package/dist/schemes/ExecOutputScheme.d.ts +4 -5
- package/dist/schemes/ExecOutputScheme.d.ts.map +1 -1
- package/dist/schemes/ExecOutputScheme.js +12 -20
- package/dist/schemes/ExecOutputScheme.js.map +1 -1
- package/dist/schemes/File.d.ts +5 -6
- package/dist/schemes/File.d.ts.map +1 -1
- package/dist/schemes/File.js +35 -41
- package/dist/schemes/File.js.map +1 -1
- package/dist/schemes/Log.d.ts +16 -5
- package/dist/schemes/Log.d.ts.map +1 -1
- package/dist/schemes/Log.js +229 -262
- package/dist/schemes/Log.js.map +1 -1
- package/dist/schemes/Log.sql +50 -27
- package/dist/schemes/Prompt.d.ts +3 -4
- package/dist/schemes/Prompt.d.ts.map +1 -1
- package/dist/schemes/Prompt.js +5 -5
- package/dist/schemes/Prompt.js.map +1 -1
- package/dist/schemes/Skill.d.ts +4 -5
- package/dist/schemes/Skill.d.ts.map +1 -1
- package/dist/schemes/Skill.js +3 -3
- package/dist/schemes/Skill.js.map +1 -1
- package/dist/schemes/Worker.d.ts +7 -7
- package/dist/schemes/Worker.d.ts.map +1 -1
- package/dist/schemes/Worker.js +99 -84
- package/dist/schemes/Worker.js.map +1 -1
- package/dist/schemes/_entry-crud.d.ts +2 -2
- package/dist/schemes/_entry-crud.d.ts.map +1 -1
- package/dist/schemes/_entry-crud.js +29 -10
- package/dist/schemes/_entry-crud.js.map +1 -1
- package/dist/schemes/_entry-crud.sql +11 -17
- package/dist/schemes/_entry-find.d.ts +41 -14
- package/dist/schemes/_entry-find.d.ts.map +1 -1
- package/dist/schemes/_entry-find.js +159 -166
- package/dist/schemes/_entry-find.js.map +1 -1
- package/dist/schemes/_entry-find.sql +2 -21
- package/dist/schemes/_entry-graph.sql +1 -1
- package/dist/schemes/_entry-manifest.d.ts +5 -17
- package/dist/schemes/_entry-manifest.d.ts.map +1 -1
- package/dist/schemes/_entry-manifest.js +28 -24
- package/dist/schemes/_entry-manifest.js.map +1 -1
- package/dist/schemes/_entry-ops.d.ts +13 -8
- package/dist/schemes/_entry-ops.d.ts.map +1 -1
- package/dist/schemes/_entry-ops.js +98 -119
- package/dist/schemes/_entry-ops.js.map +1 -1
- package/dist/schemes/_entry-ops.sql +31 -6
- package/dist/schemes/_entry-semantic.d.ts +5 -7
- package/dist/schemes/_entry-semantic.d.ts.map +1 -1
- package/dist/schemes/_entry-semantic.js +10 -31
- package/dist/schemes/_entry-semantic.js.map +1 -1
- package/dist/schemes/_entry-semantic.sql +2 -2
- package/dist/schemes/_entry-send.js +4 -4
- package/dist/schemes/_entry-send.js.map +1 -1
- package/dist/schemes/_search-index.d.ts.map +1 -1
- package/dist/schemes/_search-index.js +16 -6
- package/dist/schemes/_search-index.js.map +1 -1
- package/dist/schemes/exec-abort.js +2 -2
- package/dist/schemes/exec-abort.js.map +1 -1
- package/dist/server/BranchBatches.d.ts +1 -0
- package/dist/server/BranchBatches.d.ts.map +1 -1
- package/dist/server/BranchBatches.js +1 -0
- package/dist/server/BranchBatches.js.map +1 -1
- package/dist/server/Daemon.d.ts +6 -8
- package/dist/server/Daemon.d.ts.map +1 -1
- package/dist/server/Daemon.js +238 -68
- package/dist/server/Daemon.js.map +1 -1
- package/dist/server/DaemonModule.d.ts +3 -3
- package/dist/server/DaemonModule.d.ts.map +1 -1
- package/dist/server/branch-batch.sql +3 -1
- package/dist/server/client-input.d.ts +2 -1
- package/dist/server/client-input.d.ts.map +1 -1
- package/dist/server/client-input.js +7 -1
- package/dist/server/client-input.js.map +1 -1
- package/dist/server/drain.sql +8 -7
- package/dist/server/envelope.d.ts +0 -2
- package/dist/server/envelope.d.ts.map +1 -1
- package/dist/server/envelope.js +0 -1
- package/dist/server/envelope.js.map +1 -1
- package/dist/server/envelope.sql +3 -4
- package/dist/server/lifecycle-recovery.sql +44 -1
- package/dist/server/logEntry.d.ts +2 -1
- package/dist/server/logEntry.d.ts.map +1 -1
- package/dist/server/logEntry.js +15 -2
- package/dist/server/logEntry.js.map +1 -1
- package/dist/server/logEntry.sql +5 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +13 -1
- package/dist/service.js.map +1 -1
- package/migrations/001_schema.sql +730 -221
- package/package.json +53 -46
- package/dist/core/BudgetOverflow.d.ts +0 -23
- package/dist/core/BudgetOverflow.d.ts.map +0 -1
- package/dist/core/BudgetOverflow.js +0 -61
- package/dist/core/BudgetOverflow.js.map +0 -1
- package/dist/core/caps/DbTagCaps.d.ts +0 -10
- package/dist/core/caps/DbTagCaps.d.ts.map +0 -1
- package/dist/core/caps/DbTagCaps.js +0 -44
- package/dist/core/caps/DbTagCaps.js.map +0 -1
- package/dist/matrix/live-specimen.d.ts +0 -9
- package/dist/matrix/live-specimen.d.ts.map +0 -1
- package/dist/matrix/live-specimen.js +0 -37
- package/dist/matrix/live-specimen.js.map +0 -1
package/dist/schemes/Exec.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { parsePath } from "@plurnk/plurnk-contracts";
|
|
1
|
+
import { parsePath, TagSignal } from "@plurnk/plurnk-contracts";
|
|
2
2
|
import { Policy } from "@plurnk/plurnk-execs";
|
|
3
3
|
import { WebFetcher, WebMaterializationError, } from "@plurnk/plurnk-schemes-http";
|
|
4
4
|
import WorkspaceSettings from "../core/workspace-settings.js";
|
|
5
5
|
import EffectPolicy from "./EffectPolicy.js";
|
|
6
|
-
import EntryOps from "./_entry-ops.js";
|
|
7
6
|
import EntryCrud from "./_entry-crud.js";
|
|
8
7
|
import Owner from "../core/Owner.js";
|
|
9
8
|
import EntryFind from "./_entry-find.js";
|
|
@@ -13,7 +12,7 @@ import ExecAbort from "./exec-abort.js";
|
|
|
13
12
|
import { entryPathnameOf, renderAddress } from "../core/plurnk-uri.js";
|
|
14
13
|
import { writeFile, unlink, stat } from "node:fs/promises";
|
|
15
14
|
import { tmpdir } from "node:os";
|
|
16
|
-
import { join, resolve } from "node:path";
|
|
15
|
+
import { isAbsolute, join, resolve } from "node:path";
|
|
17
16
|
import { CoreSchemeAdapterBase } from "../core/CoreSchemeServices.js";
|
|
18
17
|
import ErrorDetail from "../core/ErrorDetail.js";
|
|
19
18
|
import Results, { OperationFailureError } from "../core/results.js";
|
|
@@ -21,11 +20,13 @@ import { InvalidOperationResultError, NetworkAddress } from "@plurnk/plurnk-sche
|
|
|
21
20
|
import DbProjectionCaps from "../core/caps/DbProjectionCaps.js";
|
|
22
21
|
import WorkerControlAddress from "../core/WorkerControlAddress.js";
|
|
23
22
|
import JournalTurn from "../core/JournalTurn.js";
|
|
23
|
+
import LogEntryProjection from "../core/LogEntryProjection.js";
|
|
24
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
24
25
|
// Executors are discovered + probed at boot into ExecutorRegistry and reach
|
|
25
26
|
// the scheme through ctx.executors ({§exec-registry-resolves}). Each runtime tag
|
|
26
27
|
// resolves to its sibling executor; the scheme itself stays runtime-agnostic.
|
|
27
28
|
// Extract the local arm of {§exec-target-routing}; non-file schemes are
|
|
28
|
-
// classified separately by
|
|
29
|
+
// classified separately by resourceSourceOf.
|
|
29
30
|
const localPathFromTarget = (target) => {
|
|
30
31
|
if (target === null)
|
|
31
32
|
return null;
|
|
@@ -39,21 +40,13 @@ const localPathFromTarget = (target) => {
|
|
|
39
40
|
// A non-file scheme target is distinct from the local path handled above. The
|
|
40
41
|
// consumer resolves its content at apply time; executors stay scheme-blind
|
|
41
42
|
// ({§executor-role}).
|
|
42
|
-
const
|
|
43
|
+
const resourceSourceOf = (target) => {
|
|
43
44
|
if (target === null || target.kind !== "url")
|
|
44
45
|
return null;
|
|
45
46
|
if (target.scheme === null || target.scheme === "file")
|
|
46
47
|
return null;
|
|
47
48
|
return target.raw;
|
|
48
49
|
};
|
|
49
|
-
// {§exec-target-routing} — effect classifies the invocation core is admitting,
|
|
50
|
-
// before a scheme-backed source can be materialized. A scheme target with no
|
|
51
|
-
// body becomes the command, so the executor has no target. With a body, the
|
|
52
|
-
// scheme content becomes a target at run time; its authored address is the
|
|
53
|
-
// stable, opaque target-present identity used only for the one effect call.
|
|
54
|
-
const effectTargetOf = (authoredTarget, routedTarget, schemeSource, command) => schemeSource !== null && command.length > 0
|
|
55
|
-
? authoredTarget?.raw ?? null
|
|
56
|
-
: routedTarget;
|
|
57
50
|
// EXEC's pathname is <runtime>/<loop_seq>/<turn_seq>/<sequence> (stamped by
|
|
58
51
|
// Dispatcher.#writeLog). Exec owns this convention, so it — not the client — turns
|
|
59
52
|
// the pathname into the entry's coordinate, mirrored onto stream payloads so
|
|
@@ -96,27 +89,22 @@ export default class Exec extends CoreSchemeAdapterBase {
|
|
|
96
89
|
writableBy: ["model", "client"],
|
|
97
90
|
volatile: true,
|
|
98
91
|
modelVisible: true,
|
|
99
|
-
|
|
100
|
-
documentation: "Runs a command in a runtime — `<<EXEC[runtime](target):command:EXEC` — output streams into the worker's `<runtime>:///<loop>/<turn>/<seq>` entry on the runtime's own channels (a subprocess → stdout/stderr; a computational runtime like sqlite/jq → a JSON `results` channel). A host-effecting command proposes for review before it runs; a read-only/pure one runs ungated. Either way you never fetch the output: the engine surfaces each turn's new stream bytes to you automatically — folded while the command runs, opened when it finishes.",
|
|
92
|
+
documentation: "Runs a registered executable tool — `## EXEC0 [executor] (target) <timeout,poll>\nbody` — using the tool's table-declared target and body contract. Output streams into the worker's `<executor>:///<loop>/<turn>/<seq>` entry on that tool's own channels. A host-effecting invocation proposes for review before it runs; a read-only or pure one runs ungated. Either way you never fetch the output: the engine surfaces each turn's new stream bytes automatically — folded while it runs, opened when it finishes.",
|
|
101
93
|
flags: {
|
|
102
94
|
excludedInAsk: true,
|
|
103
95
|
},
|
|
104
96
|
};
|
|
105
|
-
// The web-fetch the entry sink calls on content:null ({§exec-entry-sink}).
|
|
106
|
-
//
|
|
107
|
-
// fallback renders; injectable so tests substitute the network.
|
|
97
|
+
// The web-fetch the entry sink calls on content:null ({§exec-entry-sink}).
|
|
98
|
+
// Default = schemes-http's checked WebFetcher; injectable for tests.
|
|
108
99
|
#fetchWeb;
|
|
109
|
-
#closeWebFetcher;
|
|
110
100
|
constructor(fetchWeb) {
|
|
111
101
|
super();
|
|
112
|
-
const webFetcher = new WebFetcher();
|
|
113
102
|
if (fetchWeb === undefined) {
|
|
103
|
+
const webFetcher = new WebFetcher();
|
|
114
104
|
this.#fetchWeb = (url, opts) => webFetcher.fetch(url, opts);
|
|
115
|
-
this.#closeWebFetcher = () => webFetcher.close();
|
|
116
105
|
}
|
|
117
106
|
else {
|
|
118
107
|
this.#fetchWeb = fetchWeb;
|
|
119
|
-
this.#closeWebFetcher = async () => { };
|
|
120
108
|
}
|
|
121
109
|
}
|
|
122
110
|
#activeAborts = new Map();
|
|
@@ -124,11 +112,9 @@ export default class Exec extends CoreSchemeAdapterBase {
|
|
|
124
112
|
async idle() {
|
|
125
113
|
await Promise.allSettled([...this.#activeSpawns.values()]);
|
|
126
114
|
}
|
|
127
|
-
// {§handler-lifecycle} — idle is the streaming drain barrier
|
|
128
|
-
// hook owns release of its separate checked-fetch browser pool.
|
|
115
|
+
// {§handler-lifecycle} — idle is the streaming drain barrier.
|
|
129
116
|
async close() {
|
|
130
117
|
await this.idle();
|
|
131
|
-
await this.#closeWebFetcher();
|
|
132
118
|
}
|
|
133
119
|
// Whether the worker has an in-flight spawn (a background exec). The daemon
|
|
134
120
|
// reads this only for loop.cancel's cancelled=true/false answer — the
|
|
@@ -140,6 +126,29 @@ export default class Exec extends CoreSchemeAdapterBase {
|
|
|
140
126
|
return true;
|
|
141
127
|
return false;
|
|
142
128
|
}
|
|
129
|
+
// {§worker-optimistic-settlement} — wait on exactly the spawns initiated by
|
|
130
|
+
// this turn, ending immediately when all settle and never extending the
|
|
131
|
+
// opportunity to streams inherited from an earlier turn.
|
|
132
|
+
async settleTurnSpawns(workerId, turnId, timeoutMs, signal) {
|
|
133
|
+
signal?.throwIfAborted();
|
|
134
|
+
const pending = [...this.#activeAborts.entries()]
|
|
135
|
+
.filter(([, active]) => active.workerId === workerId && active.turnId === turnId)
|
|
136
|
+
.map(([subscriptionId]) => {
|
|
137
|
+
const spawn = this.#activeSpawns.get(subscriptionId);
|
|
138
|
+
if (spawn === undefined) {
|
|
139
|
+
throw new Error(`Active EXEC subscription ${subscriptionId} has no spawn settlement promise.`);
|
|
140
|
+
}
|
|
141
|
+
return spawn;
|
|
142
|
+
});
|
|
143
|
+
if (pending.length === 0)
|
|
144
|
+
return true;
|
|
145
|
+
if (timeoutMs === 0)
|
|
146
|
+
return false;
|
|
147
|
+
return await Promise.race([
|
|
148
|
+
Promise.allSettled(pending).then(() => true),
|
|
149
|
+
delay(timeoutMs, false, { signal, ref: false }),
|
|
150
|
+
]);
|
|
151
|
+
}
|
|
143
152
|
// {§exec-hold-until-concluded} — match active spawns against the
|
|
144
153
|
// operator's runtime or runtime:effect hold selectors.
|
|
145
154
|
hasActiveHoldSpawns(workerId, holdSet) {
|
|
@@ -185,51 +194,15 @@ export default class Exec extends CoreSchemeAdapterBase {
|
|
|
185
194
|
});
|
|
186
195
|
}
|
|
187
196
|
// EXEC op handler — the actual model-facing entry point per plurnk.md.
|
|
188
|
-
//
|
|
189
|
-
// signal=runtime, target=optional source/program/cwd, body=command.
|
|
197
|
+
// `## EXEC0 [runtime] (target)\nbody` → runtime-owned invocation buckets.
|
|
190
198
|
//
|
|
191
|
-
// Proposes (status=202) with attrs={runtime, cwd,
|
|
199
|
+
// Proposes (status=202) with attrs={runtime, cwd, body, pathname}.
|
|
192
200
|
// applyResolution spawns the subprocess; output streams into the
|
|
193
201
|
// coordinate-stamped <runtime>:///<pathname> entry's stdout/stderr channels
|
|
194
202
|
// (e.g. sh:///1/1/2, {§exec}). The model READs that entry on a subsequent turn.
|
|
195
203
|
async exec(statement, ctx) {
|
|
196
204
|
const core = this.coreContext(ctx);
|
|
197
|
-
|
|
198
|
-
// Non-file data sources resolve after acceptance. {§exec-target-routing}
|
|
199
|
-
const schemeSource = schemeSourceOf(statement.target);
|
|
200
|
-
// A local directory overrides cwd; every other local path remains the
|
|
201
|
-
// executor target. {§exec-target-routing}
|
|
202
|
-
const workspaceRow = await core.db.envelope_get_workspace.get({ id: core.workspaceId });
|
|
203
|
-
const projectRoot = workspaceRow?.project_root ?? null;
|
|
204
|
-
const localTarget = localPathFromTarget(statement.target);
|
|
205
|
-
let routedTarget = localTarget;
|
|
206
|
-
let cwd = projectRoot;
|
|
207
|
-
if (localTarget !== null) {
|
|
208
|
-
const abs = projectRoot !== null ? resolve(projectRoot, localTarget) : localTarget;
|
|
209
|
-
try {
|
|
210
|
-
if ((await stat(abs)).isDirectory()) {
|
|
211
|
-
cwd = abs;
|
|
212
|
-
routedTarget = null;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
catch (cause) {
|
|
216
|
-
if (cause?.code !== "ENOENT") {
|
|
217
|
-
console.error(`EXEC target classification failed for '${abs}':`, cause);
|
|
218
|
-
return Results.failure("scheme:exec", "target-classification-failed", 500, `EXEC target '${localTarget}' could not be inspected: ${ErrorDetail.preview(cause)}`, {}, {
|
|
219
|
-
target: localTarget,
|
|
220
|
-
stage: "target-classification",
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
// An empty body requires a file/program or scheme command source.
|
|
226
|
-
// {§exec-target-routing}
|
|
227
|
-
if (command.length === 0 && schemeSource === null && routedTarget === null) {
|
|
228
|
-
return Results.failure("scheme:exec", "command-required", 400, "EXEC requires a command body or an executable target.", {}, {
|
|
229
|
-
recovery: "Provide a command body or executable target.",
|
|
230
|
-
retryable: false,
|
|
231
|
-
});
|
|
232
|
-
}
|
|
205
|
+
const body = statement.body ?? "";
|
|
233
206
|
const requested = typeof statement.signal === "string" ? statement.signal : "";
|
|
234
207
|
const runtime = requested === "" ? "sh" : requested; // empty signal = default shell
|
|
235
208
|
if (core.executors === undefined)
|
|
@@ -276,14 +249,76 @@ export default class Exec extends CoreSchemeAdapterBase {
|
|
|
276
249
|
retryable: false,
|
|
277
250
|
});
|
|
278
251
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
252
|
+
const invocation = resolved.invocation;
|
|
253
|
+
const hasBody = body.length > 0;
|
|
254
|
+
const hasTarget = statement.target !== null;
|
|
255
|
+
const refuse = (code, detail, recovery, extensions = {}) => Results.failure("scheme:exec", code, 400, detail, {}, { runtime, recovery, retryable: false, ...extensions });
|
|
256
|
+
if (invocation.body.required && !hasBody) {
|
|
257
|
+
return refuse("body-required", `Executable tool '${runtime}' requires a ${invocation.body.role} body.`, `Provide the ${invocation.body.role} in the EXEC body.`);
|
|
258
|
+
}
|
|
259
|
+
if (invocation.target === undefined && hasTarget) {
|
|
260
|
+
return refuse("target-not-supported", `Executable tool '${runtime}' does not accept a target.`, `Remove the target and provide the ${invocation.body.role} in the body.`);
|
|
261
|
+
}
|
|
262
|
+
if (invocation.target?.required === true && !hasTarget) {
|
|
263
|
+
return refuse("target-required", `Executable tool '${runtime}' requires a ${invocation.target.role} target.`, `Provide the ${invocation.target.role} in (target).`);
|
|
264
|
+
}
|
|
265
|
+
if (!hasBody && !hasTarget) {
|
|
266
|
+
return refuse("input-required", `Executable tool '${runtime}' requires a body or target.`, `Provide ${invocation.target === undefined ? "a body" : "a body or target"}.`);
|
|
267
|
+
}
|
|
268
|
+
if (invocation.exclusive === true && hasBody && hasTarget) {
|
|
269
|
+
return refuse("input-conflict", `Executable tool '${runtime}' accepts its ${invocation.body.role} body and ${invocation.target?.role ?? "target"} target only as alternatives.`, "Provide either the body or target, not both.");
|
|
270
|
+
}
|
|
271
|
+
const workspaceRow = await core.db.envelope_get_workspace.get({ id: core.workspaceId });
|
|
272
|
+
const projectRoot = workspaceRow?.project_root ?? null;
|
|
273
|
+
let cwd = projectRoot;
|
|
274
|
+
let target = null;
|
|
275
|
+
let resourceSource = null;
|
|
276
|
+
const targetDecl = invocation.target;
|
|
277
|
+
if (statement.target !== null && targetDecl !== undefined) {
|
|
278
|
+
if (targetDecl.kind === "literal") {
|
|
279
|
+
target = statement.target.raw;
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
const localTarget = localPathFromTarget(statement.target);
|
|
283
|
+
if (localTarget !== null) {
|
|
284
|
+
target = localTarget;
|
|
285
|
+
}
|
|
286
|
+
else if (targetDecl.kind === "resource") {
|
|
287
|
+
resourceSource = resourceSourceOf(statement.target);
|
|
288
|
+
if (resourceSource === null) {
|
|
289
|
+
throw new Error(`EXEC '${runtime}' resource target could not be classified`);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
return refuse("target-kind-invalid", `Executable tool '${runtime}' accepts only a local or file:// ${targetDecl.role} target.`, `Use a local or file:// ${targetDecl.role} target.`, { target: statement.target.raw, targetKind: targetDecl.kind });
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (target !== null && targetDecl?.directory === "cwd") {
|
|
298
|
+
const inspected = isAbsolute(target)
|
|
299
|
+
? target
|
|
300
|
+
: projectRoot === null ? null : resolve(projectRoot, target);
|
|
301
|
+
if (inspected !== null) {
|
|
302
|
+
try {
|
|
303
|
+
if ((await stat(inspected)).isDirectory()) {
|
|
304
|
+
cwd = inspected;
|
|
305
|
+
target = null;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
catch (cause) {
|
|
309
|
+
if (cause?.code !== "ENOENT") {
|
|
310
|
+
console.error(`EXEC target classification failed for '${inspected}':`, cause);
|
|
311
|
+
return Results.failure("scheme:exec", "target-classification-failed", 500, `EXEC target '${target}' could not be inspected: ${ErrorDetail.preview(cause)}`, {}, { target, stage: "target-classification" });
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
if (!hasBody && target === null && resourceSource === null) {
|
|
317
|
+
return refuse("input-required", `Executable tool '${runtime}' has no executable body or realized target.`, `Provide a ${invocation.body.role} body or a non-directory target.`);
|
|
318
|
+
}
|
|
319
|
+
// One logical target derives one effect fact before policy consumes it.
|
|
320
|
+
// A non-file resource keeps its exact authored address until materialization.
|
|
321
|
+
const effectTarget = resourceSource ?? target;
|
|
287
322
|
const effect = resolved.executor.effect(effectTarget);
|
|
288
323
|
// cwd is the workspace project_root unless target routing selected a
|
|
289
324
|
// directory override. {§exec-target-routing}, {§executor-sinks}
|
|
@@ -300,21 +335,20 @@ export default class Exec extends CoreSchemeAdapterBase {
|
|
|
300
335
|
const turnScoped = typeof marks?.[0] === "number" && marks[0] === 0;
|
|
301
336
|
const pollSec = typeof marks?.[1] === "number" && marks[1] >= 0 ? Math.floor(marks[1]) : undefined;
|
|
302
337
|
const attrs = {
|
|
303
|
-
runtime, cwd,
|
|
304
|
-
...(
|
|
338
|
+
runtime, cwd, body, target, pathname: "", effect,
|
|
339
|
+
...(resourceSource !== null ? { resourceSource } : {}),
|
|
305
340
|
...(timeoutSec !== undefined ? { timeoutSec } : {}),
|
|
306
341
|
...(turnScoped ? { turnScoped: true } : {}),
|
|
307
342
|
...(pollSec !== undefined ? { pollSec } : {}),
|
|
308
343
|
};
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
const preview = runtime !== "" ? `[${runtime}] ${command}` : `$ ${command}`;
|
|
344
|
+
const previewInput = body !== "" ? body : statement.target?.raw ?? "";
|
|
345
|
+
const preview = runtime !== "" ? `[${runtime}] ${previewInput}` : `$ ${previewInput}`;
|
|
312
346
|
return { status: 202, body: preview, attrs }; // host runtime proposes with 202 — {§exec-host-proposes}
|
|
313
347
|
}
|
|
314
348
|
async applyResolution(args, ctx) {
|
|
315
349
|
const core = this.coreContext(ctx);
|
|
316
350
|
const attrs = args.attrs;
|
|
317
|
-
|
|
351
|
+
const body = typeof attrs.body === "string" ? attrs.body : "";
|
|
318
352
|
const pathname = attrs.pathname;
|
|
319
353
|
const runtime = (typeof attrs.runtime === "string" && attrs.runtime !== "") ? attrs.runtime : "sh";
|
|
320
354
|
const cwd = (typeof attrs.cwd === "string" && attrs.cwd.length > 0) ? attrs.cwd : null;
|
|
@@ -326,12 +360,11 @@ export default class Exec extends CoreSchemeAdapterBase {
|
|
|
326
360
|
if (!EffectPolicy.isEffect(effect)) {
|
|
327
361
|
throw new InvalidOperationResultError("The accepted EXEC proposal is missing its canonical effect fact.");
|
|
328
362
|
}
|
|
329
|
-
//
|
|
330
|
-
//
|
|
331
|
-
// {§exec-target-routing}
|
|
363
|
+
// Every non-file resource becomes a temporary executor target after
|
|
364
|
+
// acceptance; body presence never changes the target's role.
|
|
332
365
|
let tempPath = null;
|
|
333
|
-
if (attrs.
|
|
334
|
-
const sourceTarget = parsePath(attrs.
|
|
366
|
+
if (attrs.resourceSource !== undefined) {
|
|
367
|
+
const sourceTarget = parsePath(attrs.resourceSource);
|
|
335
368
|
if (sourceTarget?.kind !== "url" || sourceTarget.scheme === null || sourceTarget.scheme === "file") {
|
|
336
369
|
throw new InvalidOperationResultError("The accepted EXEC proposal has an invalid scheme source address.");
|
|
337
370
|
}
|
|
@@ -340,7 +373,7 @@ export default class Exec extends CoreSchemeAdapterBase {
|
|
|
340
373
|
suffix: "",
|
|
341
374
|
signal: null,
|
|
342
375
|
target: sourceTarget,
|
|
343
|
-
lineMarker:
|
|
376
|
+
lineMarker: { marks: [1, -1] },
|
|
344
377
|
body: null,
|
|
345
378
|
position: { line: 0, column: 0 },
|
|
346
379
|
}, core);
|
|
@@ -355,22 +388,12 @@ export default class Exec extends CoreSchemeAdapterBase {
|
|
|
355
388
|
retryable: false,
|
|
356
389
|
});
|
|
357
390
|
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
else {
|
|
362
|
-
tempPath = join(tmpdir(), `plurnk-exec-${core.workspaceId}-${pathname.replace(/[^a-zA-Z0-9]/g, "-")}`);
|
|
363
|
-
await writeFile(tempPath, content, "utf8");
|
|
364
|
-
target = tempPath;
|
|
365
|
-
}
|
|
391
|
+
tempPath = join(tmpdir(), `plurnk-exec-${core.workspaceId}-${pathname.replace(/[^a-zA-Z0-9]/g, "-")}`);
|
|
392
|
+
await writeFile(tempPath, content, "utf8");
|
|
393
|
+
target = tempPath;
|
|
366
394
|
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
if (command.length === 0 && target === null) {
|
|
370
|
-
if (attrs.schemeSource !== undefined) {
|
|
371
|
-
return Results.failure("scheme:exec", "source-command-empty", 422, "The EXEC source resolved to an empty command.", { outcome: "scheme_source_command_empty" }, { retryable: false });
|
|
372
|
-
}
|
|
373
|
-
throw new InvalidOperationResultError("The accepted EXEC proposal has neither a command nor a target.");
|
|
395
|
+
if (body.length === 0 && target === null) {
|
|
396
|
+
throw new InvalidOperationResultError("The accepted EXEC proposal has neither a body nor a realized target.");
|
|
374
397
|
}
|
|
375
398
|
// Resolve the runtime's executor from the boot registry, then seed
|
|
376
399
|
// channels from its declared topology ({§executor-channels}). Each executor declares its own
|
|
@@ -392,7 +415,7 @@ export default class Exec extends CoreSchemeAdapterBase {
|
|
|
392
415
|
state: decl.defaultState ?? "active",
|
|
393
416
|
};
|
|
394
417
|
}
|
|
395
|
-
const seed = { channels: seedChannels
|
|
418
|
+
const seed = { channels: seedChannels };
|
|
396
419
|
// {§exec} — the stream entry's scheme IS the runtime tag (sh/node), so it addresses by
|
|
397
420
|
// tag authority (sh:///l/t/s). The engine registers each runtime tag → this handler.
|
|
398
421
|
const { entryId } = await EntryCrud.writeEntry(pathname, seed, core, runtime, core.workerId);
|
|
@@ -407,7 +430,7 @@ export default class Exec extends CoreSchemeAdapterBase {
|
|
|
407
430
|
}
|
|
408
431
|
const subscriptionId = await ChannelWrite.openSubscription(core.db, {
|
|
409
432
|
workerId: core.workerId, entryId, scheme: runtime,
|
|
410
|
-
handle: runtime !== "" ? `${runtime}: ${
|
|
433
|
+
handle: runtime !== "" ? `${runtime}: ${body !== "" ? body : target ?? ""}` : body,
|
|
411
434
|
pollSeconds: typeof attrs.pollSec === "number" ? attrs.pollSec : null, // {§exec-poll} — hibernation wake cadence
|
|
412
435
|
turnScoped: attrs.turnScoped === true, // {§exec-poll} — `<0>` reaped at the next pre-turn
|
|
413
436
|
});
|
|
@@ -429,13 +452,13 @@ export default class Exec extends CoreSchemeAdapterBase {
|
|
|
429
452
|
if (parent.aborted)
|
|
430
453
|
controller.abort(ExecAbort.teardownReason());
|
|
431
454
|
}
|
|
432
|
-
this.#activeAborts.set(subscriptionId, { workerId: core.workerId, pathname, runtime, effect, controller, unlink });
|
|
455
|
+
this.#activeAborts.set(subscriptionId, { workerId: core.workerId, turnId: core.turnId, pathname, runtime, effect, controller, unlink });
|
|
433
456
|
this.liveSubscriptions().register(subscriptionId, {
|
|
434
457
|
cancel: () => controller.abort(ExecAbort.teardownReason()),
|
|
435
458
|
});
|
|
436
459
|
const tail = this.#runExecutor({
|
|
437
460
|
executor: resolved.executor,
|
|
438
|
-
runtime,
|
|
461
|
+
runtime, body, cwd, target, ctx: core, pathname,
|
|
439
462
|
entryId, subscriptionId, signal: controller.signal, controller, tempPath,
|
|
440
463
|
timeoutSec: typeof attrs.timeoutSec === "number" ? attrs.timeoutSec : null,
|
|
441
464
|
});
|
|
@@ -459,7 +482,7 @@ export default class Exec extends CoreSchemeAdapterBase {
|
|
|
459
482
|
// notify's reported state to "closed" before the chunk event fires
|
|
460
483
|
// as "active." Chain through a single promise queue to serialize.
|
|
461
484
|
async #runExecutor(opts) {
|
|
462
|
-
const { executor, runtime,
|
|
485
|
+
const { executor, runtime, body, cwd, target, ctx, pathname, entryId, subscriptionId, signal, controller, timeoutSec, tempPath } = opts;
|
|
463
486
|
const db = ctx.db;
|
|
464
487
|
const coordinate = coordinateFromPathname(pathname);
|
|
465
488
|
// grammar 0.74.20 EXEC `<T>` — kill the spawn after T seconds. unref'd so a pending timer never
|
|
@@ -520,7 +543,12 @@ export default class Exec extends CoreSchemeAdapterBase {
|
|
|
520
543
|
materialized = this.#fetchWeb(fetchAddress.url, { signal });
|
|
521
544
|
}
|
|
522
545
|
else {
|
|
523
|
-
materialized = Promise.resolve({
|
|
546
|
+
materialized = Promise.resolve({
|
|
547
|
+
url: fetchAddress?.url ?? "http://localhost",
|
|
548
|
+
body: content,
|
|
549
|
+
mimetype: opts.mimetype,
|
|
550
|
+
allowTavily: false,
|
|
551
|
+
});
|
|
524
552
|
}
|
|
525
553
|
const op = async () => {
|
|
526
554
|
const fetched = await materialized;
|
|
@@ -538,19 +566,21 @@ export default class Exec extends CoreSchemeAdapterBase {
|
|
|
538
566
|
}
|
|
539
567
|
if (web === null)
|
|
540
568
|
throw new Error(`entry(): '${path.slice(0, 80)}' has no readable projection`);
|
|
541
|
-
|
|
542
|
-
|
|
569
|
+
if (web.body === undefined) {
|
|
570
|
+
throw new Error(web.bodyOutcome.failure?.detail
|
|
571
|
+
?? `entry(): '${path.slice(0, 80)}' produced no readable body`);
|
|
572
|
+
}
|
|
573
|
+
const tags = TagSignal.applied(opts.tags.map((tag) => `+${tag}`)).add;
|
|
574
|
+
const tagSignal = tags.map((tag) => `+${tag}`);
|
|
543
575
|
// {§exec-entry-sink}/{§html-materialization} The shared
|
|
544
576
|
// materializer owns the decisive projection and its provenance.
|
|
545
|
-
const channels =
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
...(web.header === undefined ? {} : { header: { content: web.header, mimetype: "text/plain" } }),
|
|
549
|
-
};
|
|
577
|
+
const channels = WebFetcher.materializedChannels(web, content === null && fetchAddress !== null
|
|
578
|
+
? { url: fetchAddress.url, method: "GET" }
|
|
579
|
+
: undefined);
|
|
550
580
|
const decisive = web.body.content;
|
|
551
581
|
const source = web.html?.content ?? decisive;
|
|
552
582
|
const causalSource = await resolveCallerSource();
|
|
553
|
-
const written = Results.assert(await EntryCrud.writeEntry(pathname, { channels
|
|
583
|
+
const written = Results.assert(await EntryCrud.writeEntry(pathname, { channels }, ctx, scheme));
|
|
554
584
|
if (narration === null) {
|
|
555
585
|
const worker = await db.envelope_get_worker_by_name.get({ workspace_id: ctx.workspaceId, name: "plurnk" })
|
|
556
586
|
?? await db.envelope_insert_worker.get({ workspace_id: ctx.workspaceId, name: "plurnk", origin: "plurnk" });
|
|
@@ -570,21 +600,23 @@ export default class Exec extends CoreSchemeAdapterBase {
|
|
|
570
600
|
};
|
|
571
601
|
}
|
|
572
602
|
const sequence = narration.seq++;
|
|
603
|
+
const narrationAttrs = { kind: "entry_materialized" };
|
|
573
604
|
if (written.problem !== undefined) {
|
|
574
|
-
|
|
605
|
+
const coordinate = LogEntryProjection.coordinate(`${narration.loopSeq}/${narration.turnSeq}/${sequence}`, { origin: "plurnk", op: "EDIT", attrs: narrationAttrs });
|
|
606
|
+
Results.attachInstance(written, `log:///${coordinate}`);
|
|
575
607
|
}
|
|
576
|
-
await db.engine_insert_log_entry.get({
|
|
608
|
+
const logRow = await db.engine_insert_log_entry.get({
|
|
577
609
|
worker_id: narration.workerId, loop_id: narration.loopId, turn_id: narration.turnId, sequence,
|
|
578
|
-
// signal carries
|
|
610
|
+
// signal carries additive tag terms through the same slot a model's EDIT uses, so the
|
|
579
611
|
// ambient row renders its tags natively everywhere (packet meta line, digest).
|
|
580
|
-
origin: "plurnk", source: causalSource,
|
|
612
|
+
origin: "plurnk", source: causalSource, model_call_id: null,
|
|
613
|
+
op: "EDIT", suffix: "", signal: JSON.stringify(tagSignal),
|
|
581
614
|
scheme, username: null, password: null, hostname: null, port: null,
|
|
582
615
|
pathname, query: null, fragment: null, lineMarker: null,
|
|
583
616
|
tx: JSON.stringify({ op: "EDIT", body: source }), mimetype_tx: "application/json",
|
|
584
617
|
rx: JSON.stringify(written.problem === undefined
|
|
585
618
|
? {
|
|
586
619
|
...written,
|
|
587
|
-
tags,
|
|
588
620
|
span: decisive.split("\n").map((l, n) => `${n + 1}:${l}`).join("\n"),
|
|
589
621
|
}
|
|
590
622
|
: written),
|
|
@@ -592,8 +624,10 @@ export default class Exec extends CoreSchemeAdapterBase {
|
|
|
592
624
|
status_rx: written.status, tokens: ctx.tokenize?.(decisive) ?? 0, state: "resolved", outcome: null,
|
|
593
625
|
// Durable provenance for clients/forensics. This is machine
|
|
594
626
|
// ambience, not a human/model action waterfall item.
|
|
595
|
-
attrs: JSON.stringify(
|
|
627
|
+
attrs: JSON.stringify(narrationAttrs),
|
|
596
628
|
});
|
|
629
|
+
if (logRow === undefined)
|
|
630
|
+
throw new Error("entry(): log insert returned no row");
|
|
597
631
|
if (written.problem !== undefined)
|
|
598
632
|
throw new OperationFailureError(written);
|
|
599
633
|
return renderAddress(scheme, pathname);
|
|
@@ -605,11 +639,11 @@ export default class Exec extends CoreSchemeAdapterBase {
|
|
|
605
639
|
try {
|
|
606
640
|
try {
|
|
607
641
|
const reported = await executor.run({
|
|
608
|
-
runtime,
|
|
642
|
+
runtime, body, cwd, target, signal,
|
|
609
643
|
entry: entrySink,
|
|
610
644
|
env: ExecEnv.scoped(), // SPEC {§exec} {§exec-env-scoped} — never plurnk's own secrets
|
|
611
|
-
write: (channel, chunk) => enqueue(() => ChannelWrite.appendToChannel(db, {
|
|
612
|
-
entryId, channel, chunk, notify: ctx.streamEventNotify, coordinate,
|
|
645
|
+
write: (channel, chunk, mimetype) => enqueue(() => ChannelWrite.appendToChannel(db, {
|
|
646
|
+
entryId, channel, chunk, mimetype, notify: ctx.streamEventNotify, coordinate,
|
|
613
647
|
})),
|
|
614
648
|
setState: (channel, state) => enqueue(() => ChannelWrite.setChannelState(db, {
|
|
615
649
|
entryId, channel, state, notify: ctx.streamEventNotify, coordinate,
|
|
@@ -695,7 +729,7 @@ export default class Exec extends CoreSchemeAdapterBase {
|
|
|
695
729
|
if (ctx.wakeWorkerNotify !== undefined) {
|
|
696
730
|
ctx.wakeWorkerNotify({
|
|
697
731
|
workspaceId: ctx.workspaceId, workerId: ctx.workerId,
|
|
698
|
-
entryId, target: `${runtime}://${pathname}`, subscriptionId, result,
|
|
732
|
+
entryOwnerId: ctx.workerId, entryId, target: `${runtime}://${pathname}`, subscriptionId, result,
|
|
699
733
|
scheme: runtime,
|
|
700
734
|
summary: `${runtime}://${pathname} completed (${exitLabel}); stdout=${stdoutLength} bytes, stderr=${stderrLength} bytes`,
|
|
701
735
|
...coordinate,
|
|
@@ -704,25 +738,24 @@ export default class Exec extends CoreSchemeAdapterBase {
|
|
|
704
738
|
}
|
|
705
739
|
return result;
|
|
706
740
|
}
|
|
707
|
-
async
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
return EntryOps.readWorkspaceEntry(owner.statement, core, Exec.manifest, owner.ownerId);
|
|
741
|
+
async resolveEntryAddress(target, ctx) {
|
|
742
|
+
if (target.kind !== "url")
|
|
743
|
+
return null;
|
|
744
|
+
const ownerId = await Owner.resolveStreamOwner(target.hostname, this.coreContext(ctx));
|
|
745
|
+
return ownerId === null
|
|
746
|
+
? Results.failure("scheme:exec", "stream-not-found", 404, "No visible stream exists at the requested address.")
|
|
747
|
+
: { pathname: target.pathname, ownerId };
|
|
716
748
|
}
|
|
717
749
|
async find(statement, ctx) {
|
|
718
750
|
const core = this.coreContext(ctx);
|
|
719
751
|
const owner = await resolveStreamStatement(statement, core);
|
|
720
752
|
if (owner === null) {
|
|
721
753
|
return Results.failure("scheme:exec", "stream-not-found", 404, "No visible stream exists at the requested address.", {
|
|
722
|
-
content: null, mimetype: null, results: [], itemsTokenTotal: 0,
|
|
754
|
+
content: null, mimetype: null, results: [], itemsTokenTotal: 0, returnedItemsTokenTotal: 0,
|
|
755
|
+
matchingPathCount: 0, matchLocationCount: 0,
|
|
723
756
|
});
|
|
724
757
|
}
|
|
725
|
-
return EntryFind.findWorkspaceEntries(owner.statement, core, Exec.manifest, owner.ownerId);
|
|
758
|
+
return EntryFind.findWorkspaceEntries(owner.statement, core, Exec.manifest, { ownerId: owner.ownerId });
|
|
726
759
|
}
|
|
727
760
|
async readEntry(pathname, ctx) {
|
|
728
761
|
const core = this.coreContext(ctx);
|