@smthrs/flow 1.0.0-rc.13 → 1.0.0-rc.15
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/cjs/Interpreter.d.ts.map +1 -1
- package/dist/cjs/Interpreter.js +2 -1
- package/dist/cjs/Interpreter.js.map +2 -2
- package/dist/cjs/internal/RecordedPlan.d.ts +19 -0
- package/dist/cjs/internal/RecordedPlan.d.ts.map +1 -0
- package/dist/cjs/internal/RecordedPlan.js +55 -0
- package/dist/cjs/internal/RecordedPlan.js.map +7 -0
- package/dist/esm/Interpreter.d.ts.map +1 -1
- package/dist/esm/Interpreter.js +2 -1
- package/dist/esm/Interpreter.js.map +1 -1
- package/dist/esm/internal/RecordedPlan.d.ts +19 -0
- package/dist/esm/internal/RecordedPlan.d.ts.map +1 -0
- package/dist/esm/internal/RecordedPlan.js +45 -0
- package/dist/esm/internal/RecordedPlan.js.map +1 -0
- package/docs/guides/inspect-the-plan.md +1 -1
- package/package.json +6 -6
- package/src/Interpreter.ts +2 -1
- package/src/internal/RecordedPlan.ts +50 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resume compatibility is weaker than result reuse: unchanged callback source
|
|
3
|
+
* may rebuild a recorded plan, but an opaque closure still cannot earn a cache
|
|
4
|
+
* hit. Only the interpreter's PlanRecorded guard uses this projection. Approval
|
|
5
|
+
* digests and dispatch keys keep the original entropy-bearing material.
|
|
6
|
+
*
|
|
7
|
+
* @since 1.0.0
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
import { isRecord } from "@smthrs/canonical/Record";
|
|
11
|
+
import * as Graph from "../Graph.js";
|
|
12
|
+
/** Missing source metadata retains the old identity and fails closed. */
|
|
13
|
+
const callback = (value) => isRecord(value) && value._tag === "FunctionIdentity" && value.algorithm === "sha256-source-ephemeral/v4" &&
|
|
14
|
+
typeof value.sourceDigest === "string"
|
|
15
|
+
? { _tag: value._tag, algorithm: value.algorithm, digest: value.sourceDigest }
|
|
16
|
+
: value;
|
|
17
|
+
/** Project only callback slots, never identity-shaped application data. */
|
|
18
|
+
const body = (value) => {
|
|
19
|
+
if (!isRecord(value))
|
|
20
|
+
return value;
|
|
21
|
+
switch (value._tag) {
|
|
22
|
+
case "FlowCall":
|
|
23
|
+
return isRecord(value.declaration)
|
|
24
|
+
? { ...value, declaration: { ...value.declaration, body: callback(value.declaration.body) } }
|
|
25
|
+
: value;
|
|
26
|
+
case "Map":
|
|
27
|
+
return { ...value, mapper: callback(value.mapper) };
|
|
28
|
+
case "AndThen":
|
|
29
|
+
return { ...value, continuation: callback(value.continuation) };
|
|
30
|
+
case "Branch":
|
|
31
|
+
return { ...value, predicate: callback(value.predicate) };
|
|
32
|
+
case "Catch":
|
|
33
|
+
return { ...value, filterIdentity: callback(value.filterIdentity) };
|
|
34
|
+
default:
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* The same drafts, with only callback identities made restart-comparable.
|
|
40
|
+
*
|
|
41
|
+
* @since 1.0.0
|
|
42
|
+
* @private
|
|
43
|
+
*/
|
|
44
|
+
export const recordedPlanDrafts = (graph) => Graph.drafts(graph).map((draft) => ({ ...draft, material: { ...draft.material, body: body(draft.material.body) } }));
|
|
45
|
+
//# sourceMappingURL=RecordedPlan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RecordedPlan.js","sourceRoot":"","sources":["../../../src/internal/RecordedPlan.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAEnD,OAAO,KAAK,KAAK,MAAM,aAAa,CAAA;AAEpC,yEAAyE;AACzE,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAW,EAAE,CAC3C,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,kBAAkB,IAAI,KAAK,CAAC,SAAS,KAAK,4BAA4B;IACtG,OAAO,KAAK,CAAC,YAAY,KAAK,QAAQ;IACtC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,YAAY,EAAE;IAC9E,CAAC,CAAC,KAAK,CAAA;AAEX,2EAA2E;AAC3E,MAAM,IAAI,GAAG,CAAC,KAAc,EAAW,EAAE;IACvC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IAClC,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,UAAU;YACb,OAAO,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC;gBAChC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,WAAW,EAAE,EAAE,GAAG,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE;gBAC7F,CAAC,CAAC,KAAK,CAAA;QACX,KAAK,KAAK;YACR,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAA;QACrD,KAAK,SAAS;YACZ,OAAO,EAAE,GAAG,KAAK,EAAE,YAAY,EAAE,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAA;QACjE,KAAK,QAAQ;YACX,OAAO,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAA;QAC3D,KAAK,OAAO;YACV,OAAO,EAAE,GAAG,KAAK,EAAE,cAAc,EAAE,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAA;QACrE;YACE,OAAO,KAAK,CAAA;IAChB,CAAC;AACH,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAAkB,EAAiC,EAAE,CACtF,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA","sourcesContent":["/**\n * Resume compatibility is weaker than result reuse: unchanged callback source\n * may rebuild a recorded plan, but an opaque closure still cannot earn a cache\n * hit. Only the interpreter's PlanRecorded guard uses this projection. Approval\n * digests and dispatch keys keep the original entropy-bearing material.\n *\n * @since 1.0.0\n * @internal\n */\n\nimport { isRecord } from \"@smthrs/canonical/Record\"\nimport type * as Plan from \"@smthrs/plan/Plan\"\nimport * as Graph from \"../Graph.ts\"\n\n/** Missing source metadata retains the old identity and fails closed. */\nconst callback = (value: unknown): unknown =>\n isRecord(value) && value._tag === \"FunctionIdentity\" && value.algorithm === \"sha256-source-ephemeral/v4\" &&\n typeof value.sourceDigest === \"string\"\n ? { _tag: value._tag, algorithm: value.algorithm, digest: value.sourceDigest }\n : value\n\n/** Project only callback slots, never identity-shaped application data. */\nconst body = (value: unknown): unknown => {\n if (!isRecord(value)) return value\n switch (value._tag) {\n case \"FlowCall\":\n return isRecord(value.declaration)\n ? { ...value, declaration: { ...value.declaration, body: callback(value.declaration.body) } }\n : value\n case \"Map\":\n return { ...value, mapper: callback(value.mapper) }\n case \"AndThen\":\n return { ...value, continuation: callback(value.continuation) }\n case \"Branch\":\n return { ...value, predicate: callback(value.predicate) }\n case \"Catch\":\n return { ...value, filterIdentity: callback(value.filterIdentity) }\n default:\n return value\n }\n}\n\n/**\n * The same drafts, with only callback identities made restart-comparable.\n *\n * @since 1.0.0\n * @private\n */\nexport const recordedPlanDrafts = (graph: Graph.Graph): ReadonlyArray<Plan.NodeDraft> =>\n Graph.drafts(graph).map((draft) => ({ ...draft, material: { ...draft.material, body: body(draft.material.body) } }))\n"]}
|
|
@@ -19,7 +19,7 @@ engine, database, or jj: planning reads declarations only. They import
|
|
|
19
19
|
add both at the version of `@smthrs/flows` you have:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
npm install @smthrs/flow@1.0.0-rc.
|
|
22
|
+
npm install @smthrs/flow@1.0.0-rc.15 @smthrs/plan@1.0.0-rc.15
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
`@smthrs/flows` re-exports the same modules, so `import { Graph } from "@smthrs/flows"`
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smthrs/flow",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.0-rc.
|
|
4
|
+
"version": "1.0.0-rc.15",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"smthrs": {
|
|
7
7
|
"group": "engine"
|
|
@@ -289,11 +289,11 @@
|
|
|
289
289
|
"tag": "next"
|
|
290
290
|
},
|
|
291
291
|
"dependencies": {
|
|
292
|
-
"@smthrs/crypto": "1.0.0-rc.
|
|
293
|
-
"@smthrs/keys": "1.0.0-rc.
|
|
294
|
-
"@smthrs/plan": "1.0.0-rc.
|
|
295
|
-
"@smthrs/canonical": "1.0.0-rc.
|
|
296
|
-
"@smthrs/capability": "1.0.0-rc.
|
|
292
|
+
"@smthrs/crypto": "1.0.0-rc.15",
|
|
293
|
+
"@smthrs/keys": "1.0.0-rc.15",
|
|
294
|
+
"@smthrs/plan": "1.0.0-rc.15",
|
|
295
|
+
"@smthrs/canonical": "1.0.0-rc.15",
|
|
296
|
+
"@smthrs/capability": "1.0.0-rc.15"
|
|
297
297
|
},
|
|
298
298
|
"devDependencies": {
|
|
299
299
|
"@effect/language-service": "0.87.2",
|
package/src/Interpreter.ts
CHANGED
|
@@ -80,6 +80,7 @@ import * as HumanTask from "./HumanTask.ts"
|
|
|
80
80
|
import * as BoundedJson from "./internal/BoundedJson.ts"
|
|
81
81
|
import { ExecutionMiddleware } from "./internal/ExecutionMiddleware.ts"
|
|
82
82
|
import { OutcomeValueTypeId } from "./internal/OutcomeMarker.ts"
|
|
83
|
+
import { recordedPlanDrafts } from "./internal/RecordedPlan.ts"
|
|
83
84
|
import * as Sleep from "./Sleep.ts"
|
|
84
85
|
import * as WaitFor from "./WaitFor.ts"
|
|
85
86
|
|
|
@@ -272,7 +273,7 @@ const planPages = (
|
|
|
272
273
|
> =>
|
|
273
274
|
Effect.gen(function*() {
|
|
274
275
|
const identity = yield* StepKey.content({
|
|
275
|
-
body: { flow, nodes:
|
|
276
|
+
body: { flow, nodes: recordedPlanDrafts(graph), edges: Graph.edges(graph) },
|
|
276
277
|
inputs: {},
|
|
277
278
|
layers: [],
|
|
278
279
|
capabilities: {}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resume compatibility is weaker than result reuse: unchanged callback source
|
|
3
|
+
* may rebuild a recorded plan, but an opaque closure still cannot earn a cache
|
|
4
|
+
* hit. Only the interpreter's PlanRecorded guard uses this projection. Approval
|
|
5
|
+
* digests and dispatch keys keep the original entropy-bearing material.
|
|
6
|
+
*
|
|
7
|
+
* @since 1.0.0
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { isRecord } from "@smthrs/canonical/Record"
|
|
12
|
+
import type * as Plan from "@smthrs/plan/Plan"
|
|
13
|
+
import * as Graph from "../Graph.ts"
|
|
14
|
+
|
|
15
|
+
/** Missing source metadata retains the old identity and fails closed. */
|
|
16
|
+
const callback = (value: unknown): unknown =>
|
|
17
|
+
isRecord(value) && value._tag === "FunctionIdentity" && value.algorithm === "sha256-source-ephemeral/v4" &&
|
|
18
|
+
typeof value.sourceDigest === "string"
|
|
19
|
+
? { _tag: value._tag, algorithm: value.algorithm, digest: value.sourceDigest }
|
|
20
|
+
: value
|
|
21
|
+
|
|
22
|
+
/** Project only callback slots, never identity-shaped application data. */
|
|
23
|
+
const body = (value: unknown): unknown => {
|
|
24
|
+
if (!isRecord(value)) return value
|
|
25
|
+
switch (value._tag) {
|
|
26
|
+
case "FlowCall":
|
|
27
|
+
return isRecord(value.declaration)
|
|
28
|
+
? { ...value, declaration: { ...value.declaration, body: callback(value.declaration.body) } }
|
|
29
|
+
: value
|
|
30
|
+
case "Map":
|
|
31
|
+
return { ...value, mapper: callback(value.mapper) }
|
|
32
|
+
case "AndThen":
|
|
33
|
+
return { ...value, continuation: callback(value.continuation) }
|
|
34
|
+
case "Branch":
|
|
35
|
+
return { ...value, predicate: callback(value.predicate) }
|
|
36
|
+
case "Catch":
|
|
37
|
+
return { ...value, filterIdentity: callback(value.filterIdentity) }
|
|
38
|
+
default:
|
|
39
|
+
return value
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The same drafts, with only callback identities made restart-comparable.
|
|
45
|
+
*
|
|
46
|
+
* @since 1.0.0
|
|
47
|
+
* @private
|
|
48
|
+
*/
|
|
49
|
+
export const recordedPlanDrafts = (graph: Graph.Graph): ReadonlyArray<Plan.NodeDraft> =>
|
|
50
|
+
Graph.drafts(graph).map((draft) => ({ ...draft, material: { ...draft.material, body: body(draft.material.body) } }))
|