@openclaw/lobster 2026.9.5 → 2026.9.7
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/assets/icon.png +0 -0
- package/dist/index.js +8 -294
- package/node_modules/@clawdbot/lobster/README.md +20 -133
- package/node_modules/@clawdbot/lobster/VISION.md +15 -238
- package/node_modules/@clawdbot/lobster/bin/clawd.invoke.js +2 -21
- package/node_modules/@clawdbot/lobster/bin/invoke.js +19 -0
- package/node_modules/@clawdbot/lobster/bin/lobster.js +2 -21
- package/node_modules/@clawdbot/lobster/bin/openclaw.invoke.js +2 -24
- package/node_modules/@clawdbot/lobster/dist/src/cli.js +32 -48
- package/node_modules/@clawdbot/lobster/dist/src/cli.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/command_tokens.js +81 -0
- package/node_modules/@clawdbot/lobster/dist/src/command_tokens.js.map +1 -0
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/dedupe.js +1 -12
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/dedupe.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/group_by.js +2 -14
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/group_by.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/llm_invoke.js +1 -337
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/llm_invoke.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/map.js +2 -13
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/map.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/sort.js +4 -21
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/sort.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/state.js +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/state.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/template.js +2 -13
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/template.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/commands/workflows/workflows_run.js +0 -18
- package/node_modules/@clawdbot/lobster/dist/src/commands/workflows/workflows_run.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/core/llm_accounting.js +304 -0
- package/node_modules/@clawdbot/lobster/dist/src/core/llm_accounting.js.map +1 -0
- package/node_modules/@clawdbot/lobster/dist/src/core/value_path.js +11 -0
- package/node_modules/@clawdbot/lobster/dist/src/core/value_path.js.map +1 -0
- package/node_modules/@clawdbot/lobster/dist/src/parser.js +2 -67
- package/node_modules/@clawdbot/lobster/dist/src/parser.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/recipes/github/index.js +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/recipes/github/pr-monitor.js +5 -64
- package/node_modules/@clawdbot/lobster/dist/src/recipes/github/pr-monitor.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/recipes/github/read_pr.js +45 -0
- package/node_modules/@clawdbot/lobster/dist/src/recipes/github/read_pr.js.map +1 -0
- package/node_modules/@clawdbot/lobster/dist/src/recipes/github/snapshot.js +45 -0
- package/node_modules/@clawdbot/lobster/dist/src/recipes/github/snapshot.js.map +1 -0
- package/node_modules/@clawdbot/lobster/dist/src/recipes/github/stages/pr-view.js +9 -47
- package/node_modules/@clawdbot/lobster/dist/src/recipes/github/stages/pr-view.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/sdk/Lobster.js +18 -135
- package/node_modules/@clawdbot/lobster/dist/src/sdk/Lobster.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/sdk/index.js +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/sdk/primitives/approve.js +1 -2
- package/node_modules/@clawdbot/lobster/dist/src/sdk/primitives/approve.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/sdk/primitives/diff.js +2 -8
- package/node_modules/@clawdbot/lobster/dist/src/sdk/primitives/diff.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/sdk/primitives/exec.js +15 -81
- package/node_modules/@clawdbot/lobster/dist/src/sdk/primitives/exec.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/sdk/primitives/state.js +3 -9
- package/node_modules/@clawdbot/lobster/dist/src/sdk/primitives/state.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/sdk/runtime.js +0 -12
- package/node_modules/@clawdbot/lobster/dist/src/sdk/runtime.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/sdk/state_env.js +6 -0
- package/node_modules/@clawdbot/lobster/dist/src/sdk/state_env.js.map +1 -0
- package/node_modules/@clawdbot/lobster/dist/src/state/atomic_file.js +192 -0
- package/node_modules/@clawdbot/lobster/dist/src/state/atomic_file.js.map +1 -0
- package/node_modules/@clawdbot/lobster/dist/src/state/store.js +2 -188
- package/node_modules/@clawdbot/lobster/dist/src/state/store.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/workflows/dry_run.js +262 -0
- package/node_modules/@clawdbot/lobster/dist/src/workflows/dry_run.js.map +1 -0
- package/node_modules/@clawdbot/lobster/dist/src/workflows/expressions.js +345 -0
- package/node_modules/@clawdbot/lobster/dist/src/workflows/expressions.js.map +1 -0
- package/node_modules/@clawdbot/lobster/dist/src/workflows/file.js +21 -1036
- package/node_modules/@clawdbot/lobster/dist/src/workflows/file.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/workflows/github_pr_monitor.js +8 -77
- package/node_modules/@clawdbot/lobster/dist/src/workflows/github_pr_monitor.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/workflows/graph.js +1 -7
- package/node_modules/@clawdbot/lobster/dist/src/workflows/graph.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/workflows/load.js +347 -0
- package/node_modules/@clawdbot/lobster/dist/src/workflows/load.js.map +1 -0
- package/node_modules/@clawdbot/lobster/dist/src/workflows/types.js +2 -0
- package/node_modules/@clawdbot/lobster/dist/src/workflows/types.js.map +1 -0
- package/node_modules/@clawdbot/lobster/dist/src/workflows/values.js +93 -0
- package/node_modules/@clawdbot/lobster/dist/src/workflows/values.js.map +1 -0
- package/node_modules/@clawdbot/lobster/dist/test/cancellation.test.js +1 -0
- package/node_modules/@clawdbot/lobster/dist/test/cancellation.test.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/test/cli_run_errors.test.js +53 -0
- package/node_modules/@clawdbot/lobster/dist/test/cli_run_errors.test.js.map +1 -0
- package/node_modules/@clawdbot/lobster/dist/test/command_arguments.test.js +82 -0
- package/node_modules/@clawdbot/lobster/dist/test/command_arguments.test.js.map +1 -0
- package/node_modules/@clawdbot/lobster/dist/test/cost_tracker.test.js +49 -19
- package/node_modules/@clawdbot/lobster/dist/test/cost_tracker.test.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/test/helpers/node_shell_fixture.js +17 -0
- package/node_modules/@clawdbot/lobster/dist/test/helpers/node_shell_fixture.js.map +1 -0
- package/node_modules/@clawdbot/lobster/dist/test/llm_invoke.test.js +2 -0
- package/node_modules/@clawdbot/lobster/dist/test/llm_invoke.test.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/test/pipeline_resume_state.test.js +65 -0
- package/node_modules/@clawdbot/lobster/dist/test/pipeline_resume_state.test.js.map +1 -0
- package/node_modules/@clawdbot/lobster/dist/test/process_output_limit.test.js +5 -3
- package/node_modules/@clawdbot/lobster/dist/test/process_output_limit.test.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/test/sdk_exec.test.js +72 -25
- package/node_modules/@clawdbot/lobster/dist/test/sdk_exec.test.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/test/workflow_graph.test.js +1 -1
- package/node_modules/@clawdbot/lobster/dist/test/workflow_graph.test.js.map +1 -1
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/README.md +1 -0
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/SECURITY.md +62 -13
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/index.js +40 -9
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/lib/schemes.js +76 -16
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/lib/utils.js +54 -10
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/package.json +1 -1
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/test/fixtures/uri-js-parse.json +1 -0
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/test/ipv6-validation.test.js +130 -0
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/test/mailto-authority-security.test.js +125 -0
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/test/mailto-field-name-security.test.js +151 -0
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/test/security-normalization.test.js +38 -0
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/types/index.d.ts +16 -0
- package/node_modules/@clawdbot/lobster/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +19 -18
- package/node_modules/@clawdbot/lobster/node_modules/yaml/browser/dist/nodes/Alias.js +25 -23
- package/node_modules/@clawdbot/lobster/node_modules/yaml/dist/compose/resolve-flow-scalar.js +19 -18
- package/node_modules/@clawdbot/lobster/node_modules/yaml/dist/nodes/Alias.js +25 -23
- package/node_modules/@clawdbot/lobster/node_modules/yaml/package.json +1 -1
- package/node_modules/@clawdbot/lobster/package.json +6 -8
- package/node_modules/typebox/build/compile/code.mjs +1 -2
- package/node_modules/typebox/build/compile/validator.mjs +5 -1
- package/node_modules/typebox/build/format/iri.mjs +16 -9
- package/node_modules/typebox/build/guard/emit.mjs +2 -2
- package/node_modules/typebox/build/guard/guard.d.mts +7 -5
- package/node_modules/typebox/build/guard/guard.mjs +14 -9
- package/node_modules/typebox/build/guard/index.mjs +6 -0
- package/node_modules/typebox/build/guard/unicode/unicode.d.mts +6 -0
- package/node_modules/typebox/build/guard/unicode/unicode.mjs +35 -0
- package/node_modules/typebox/build/guard/{string.mjs → unicode/unicode_segment.mjs} +16 -19
- package/node_modules/typebox/build/schema/build.mjs +2 -3
- package/node_modules/typebox/build/schema/engine/_pathing.d.mts +1 -0
- package/node_modules/typebox/build/schema/engine/_pathing.mjs +11 -0
- package/node_modules/typebox/build/schema/engine/_refine.mjs +13 -5
- package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/dependencies.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/dependentSchemas.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/dynamicRef.d.mts +1 -1
- package/node_modules/typebox/build/schema/engine/dynamicRef.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/format.mjs +9 -2
- package/node_modules/typebox/build/schema/engine/patternProperties.mjs +3 -2
- package/node_modules/typebox/build/schema/engine/properties.mjs +3 -2
- package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/recursiveRef.d.mts +1 -1
- package/node_modules/typebox/build/schema/engine/recursiveRef.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/ref.d.mts +1 -1
- package/node_modules/typebox/build/schema/engine/ref.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/schema.mjs +24 -24
- package/node_modules/typebox/build/schema/parse.mjs +3 -0
- package/node_modules/typebox/build/schema/pointer/pointer.d.mts +1 -6
- package/node_modules/typebox/build/schema/pointer/pointer.mjs +47 -64
- package/node_modules/typebox/build/system/settings/internal.d.mts +2 -0
- package/node_modules/typebox/build/system/settings/internal.mjs +20 -0
- package/node_modules/typebox/build/system/settings/settings.d.mts +11 -0
- package/node_modules/typebox/build/system/settings/settings.mjs +14 -0
- package/node_modules/typebox/build/type/extends/inference.d.mts +1 -1
- package/node_modules/typebox/build/type/extends/inference.mjs +15 -2
- package/node_modules/typebox/build/type/extends/tuple.d.mts +2 -1
- package/node_modules/typebox/build/type/extends/tuple.mjs +21 -1
- package/node_modules/typebox/build/value/parse/parse.mjs +10 -4
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +3 -1
- package/package.json +6 -6
- package/dist/runtime-api.js +0 -3
- package/node_modules/@clawdbot/lobster/dist/src/sdk/token.js +0 -9
- package/node_modules/@clawdbot/lobster/dist/src/sdk/token.js.map +0 -1
- /package/node_modules/typebox/build/guard/{string.d.mts → unicode/unicode_segment.d.mts} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../../../src/sdk/primitives/exec.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../../../src/sdk/primitives/exec.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { stateEnv } from "../state_env.js";
|
|
1
2
|
/**
|
|
2
3
|
* State primitives - Persistent state management
|
|
3
4
|
*
|
|
4
5
|
* @example
|
|
5
|
-
* import { Lobster, stateGet, stateSet } from 'lobster
|
|
6
|
+
* import { Lobster, stateGet, stateSet } from '@clawdbot/lobster';
|
|
6
7
|
*
|
|
7
8
|
* // Read state
|
|
8
9
|
* new Lobster()
|
|
@@ -15,11 +16,6 @@
|
|
|
15
16
|
* .pipe(stateSet('my-key'));
|
|
16
17
|
*/
|
|
17
18
|
import { readStateJsonWithLock, writeStateJson } from "../../state/store.js";
|
|
18
|
-
function stateEnv(ctx) {
|
|
19
|
-
return ctx?.stateDir
|
|
20
|
-
? { ...(ctx?.env ?? process.env), LOBSTER_STATE_DIR: ctx.stateDir }
|
|
21
|
-
: (ctx?.env ?? process.env);
|
|
22
|
-
}
|
|
23
19
|
/**
|
|
24
20
|
* Create a state.get stage
|
|
25
21
|
*
|
|
@@ -59,14 +55,12 @@ export function stateSet(key) {
|
|
|
59
55
|
type: "state.set",
|
|
60
56
|
key,
|
|
61
57
|
async run({ input, ctx }) {
|
|
62
|
-
// Collect all input items
|
|
63
58
|
const items = [];
|
|
64
59
|
for await (const item of input) {
|
|
65
60
|
items.push(item);
|
|
66
61
|
}
|
|
67
62
|
const value = items.length === 1 ? items[0] : items;
|
|
68
63
|
await writeStateJson({ env: stateEnv(ctx), key, value, signal: ctx?.signal });
|
|
69
|
-
// Pass through the value
|
|
70
64
|
return {
|
|
71
65
|
output: (async function* () {
|
|
72
66
|
yield value;
|
|
@@ -79,7 +73,7 @@ export function stateSet(key) {
|
|
|
79
73
|
* State namespace - provides get/set methods
|
|
80
74
|
*
|
|
81
75
|
* @example
|
|
82
|
-
* import { state } from 'lobster
|
|
76
|
+
* import { state } from '@clawdbot/lobster';
|
|
83
77
|
*
|
|
84
78
|
* new Lobster()
|
|
85
79
|
* .pipe(state.get('my-key'))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../../src/sdk/primitives/state.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../../src/sdk/primitives/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE7E;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAG;IAC3B,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAErD,OAAO;QACN,IAAI,EAAE,WAAW;QACjB,GAAG;QAEH,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;YACvB,cAAc;YACd,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;gBACjC,QAAQ;YACT,CAAC;YAED,MAAM,KAAK,GAAG,MAAM,qBAAqB,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;YAE5F,OAAO;gBACN,MAAM,EAAE,CAAC,KAAK,SAAS,CAAC;oBACvB,MAAM,KAAK,CAAC;gBACb,CAAC,CAAC,EAAE;aACJ,CAAC;QACH,CAAC;KACD,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAG;IAC3B,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAErD,OAAO;QACN,IAAI,EAAE,WAAW;QACjB,GAAG;QAEH,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;YACvB,MAAM,KAAK,GAAG,EAAE,CAAC;YACjB,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBAChC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClB,CAAC;YAED,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YAEpD,MAAM,cAAc,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;YAE9E,OAAO;gBACN,MAAM,EAAE,CAAC,KAAK,SAAS,CAAC;oBACvB,MAAM,KAAK,CAAC;gBACb,CAAC,CAAC,EAAE;aACJ,CAAC;QACH,CAAC;KACD,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG;IACpB,GAAG,EAAE,QAAQ;IACb,GAAG,EAAE,QAAQ;CACb,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAG,EAAE,GAAG,GAAQ,EAAE;IACjD,OAAO,qBAAqB,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;AAChF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,GAAQ,EAAE;IACzD,MAAM,cAAc,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;AAC/E,CAAC"}
|
|
@@ -5,18 +5,6 @@
|
|
|
5
5
|
* stay identical across CLI, tool mode, and SDK entry points.
|
|
6
6
|
*/
|
|
7
7
|
import { runPipeline as runCorePipeline } from "../runtime.js";
|
|
8
|
-
/**
|
|
9
|
-
* @typedef {Object} StageResult
|
|
10
|
-
* @property {AsyncIterable|any[]} [output] - Output items
|
|
11
|
-
* @property {boolean} [halt] - Whether to halt the pipeline
|
|
12
|
-
* @property {boolean} [rendered] - Whether output was rendered
|
|
13
|
-
*/
|
|
14
|
-
/**
|
|
15
|
-
* @typedef {Object} PipelineResult
|
|
16
|
-
* @property {any[]} items - Collected output items
|
|
17
|
-
* @property {boolean} halted - Whether pipeline halted
|
|
18
|
-
* @property {Object|null} haltedAt - Stage where halt occurred
|
|
19
|
-
*/
|
|
20
8
|
/**
|
|
21
9
|
* Collect async iterable to array
|
|
22
10
|
* @param {AsyncIterable} iterable
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/sdk/runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,eAAe,CAAC;AAE/D
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/sdk/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state_env.js","sourceRoot":"","sources":["../../../src/sdk/state_env.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,QAAQ,CAAC,GAA+D;IACvF,OAAO,GAAG,EAAE,QAAQ;QACnB,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,iBAAiB,EAAE,GAAG,CAAC,QAAQ,EAAE;QACnE,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { promises as fsp } from "node:fs";
|
|
3
|
+
import { randomBytes } from "node:crypto";
|
|
4
|
+
function markAtomicWritePublished(err) {
|
|
5
|
+
if (err && (typeof err === "object" || typeof err === "function")) {
|
|
6
|
+
Object.defineProperty(err, "atomicWritePublished", {
|
|
7
|
+
value: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
return err;
|
|
12
|
+
}
|
|
13
|
+
export function atomicWriteWasPublished(err) {
|
|
14
|
+
return Boolean(err?.atomicWritePublished);
|
|
15
|
+
}
|
|
16
|
+
function isDirectorySyncUnsupportedError(err) {
|
|
17
|
+
return [
|
|
18
|
+
"EACCES",
|
|
19
|
+
"EBADF",
|
|
20
|
+
"EINVAL",
|
|
21
|
+
"EISDIR",
|
|
22
|
+
"ENOSYS",
|
|
23
|
+
"ENOTSUP",
|
|
24
|
+
"EOPNOTSUPP",
|
|
25
|
+
"EPERM",
|
|
26
|
+
].includes(err?.code);
|
|
27
|
+
}
|
|
28
|
+
async function syncParentDir(filePath) {
|
|
29
|
+
await syncDirectory(path.dirname(filePath));
|
|
30
|
+
}
|
|
31
|
+
async function syncDirectory(dir) {
|
|
32
|
+
let handle;
|
|
33
|
+
try {
|
|
34
|
+
handle = await fsp.open(dir, "r");
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
if (isDirectorySyncUnsupportedError(err))
|
|
38
|
+
return;
|
|
39
|
+
throw err;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
await handle.sync();
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
if (!isDirectorySyncUnsupportedError(err))
|
|
46
|
+
throw err;
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
if (handle)
|
|
50
|
+
await handle.close().catch(() => { });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* On Windows, `fs.mkdir(..., { recursive: true })` reports the first created
|
|
55
|
+
* directory as an extended-length path (`\\?\C:\...`). `path.resolve` keeps
|
|
56
|
+
* that prefix, so such a path never compares equal to the plain drive path we
|
|
57
|
+
* walk toward and `path.relative` between the two yields an absolute path.
|
|
58
|
+
* Map the namespaces that have a plain equivalent back to it so both ends of the
|
|
59
|
+
* chain share one root form. The UNC marker is matched without regard to case,
|
|
60
|
+
* because Windows accepts a lowercase "unc" namespace component just as well.
|
|
61
|
+
*
|
|
62
|
+
* Device namespaces with no drive-letter or UNC equivalent, such as
|
|
63
|
+
* `\\?\Volume{GUID}\...`, are returned unchanged: stripping their prefix would
|
|
64
|
+
* leave a relative path and break an explicitly configured state directory.
|
|
65
|
+
*/
|
|
66
|
+
export function stripExtendedLengthPrefix(target) {
|
|
67
|
+
if (!target.startsWith("\\\\?\\"))
|
|
68
|
+
return target;
|
|
69
|
+
const rest = target.slice(4);
|
|
70
|
+
if (/^UNC\\/i.test(rest))
|
|
71
|
+
return `\\\\${rest.slice(4)}`;
|
|
72
|
+
if (/^[A-Za-z]:[\\/]/.test(rest))
|
|
73
|
+
return rest;
|
|
74
|
+
return target;
|
|
75
|
+
}
|
|
76
|
+
async function syncCreatedDirectoryChain(firstCreated, finalDir) {
|
|
77
|
+
const final = path.resolve(stripExtendedLengthPrefix(finalDir));
|
|
78
|
+
let current = path.resolve(stripExtendedLengthPrefix(firstCreated));
|
|
79
|
+
await syncDirectory(path.dirname(current));
|
|
80
|
+
while (current !== final) {
|
|
81
|
+
await syncDirectory(current);
|
|
82
|
+
const relative = path.relative(current, final);
|
|
83
|
+
const next = relative.split(path.sep)[0];
|
|
84
|
+
if (!next || next === "..")
|
|
85
|
+
break;
|
|
86
|
+
current = path.join(current, next);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export async function ensureDirectory(dir) {
|
|
90
|
+
const created = await fsp.mkdir(dir, { recursive: true });
|
|
91
|
+
if (created)
|
|
92
|
+
await syncCreatedDirectoryChain(created, dir);
|
|
93
|
+
}
|
|
94
|
+
function isLinkUnsupportedError(err) {
|
|
95
|
+
return ["ENOSYS", "ENOTSUP", "EOPNOTSUPP", "EPERM", "EXDEV"].includes(err?.code);
|
|
96
|
+
}
|
|
97
|
+
export function isAtomicExclusiveUnsupportedError(err) {
|
|
98
|
+
return err?.code === "ENOTSUP" && err?.cause && isLinkUnsupportedError(err.cause);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Write a file atomically: stage to a sibling temp file, fsync, then rename
|
|
102
|
+
* over the target. `rename(2)` is atomic on a single filesystem, so a reader
|
|
103
|
+
* (or a crash) never observes a truncated/partial file — it sees either the
|
|
104
|
+
* complete old content or the complete new content. Plain `fsp.writeFile`
|
|
105
|
+
* truncates the target up front, leaving a corruption window on SIGKILL/OOM/
|
|
106
|
+
* power loss. New state files are private by default; existing file modes are
|
|
107
|
+
* preserved across replacement. The temp file is removed on any failed path.
|
|
108
|
+
*/
|
|
109
|
+
export async function writeFileAtomic(filePath, data, options = {}) {
|
|
110
|
+
const renameFile = options.renameFile ?? fsp.rename;
|
|
111
|
+
const syncDir = options.syncParentDir ?? syncParentDir;
|
|
112
|
+
const dir = path.dirname(filePath);
|
|
113
|
+
const tmpPath = path.join(dir, `.${path.basename(filePath)}.${randomBytes(6).toString("hex")}.tmp`);
|
|
114
|
+
let mode = 0o600;
|
|
115
|
+
let handle;
|
|
116
|
+
let cleanup = true;
|
|
117
|
+
try {
|
|
118
|
+
try {
|
|
119
|
+
mode = (await fsp.stat(filePath)).mode & 0o777;
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
if (err?.code !== "ENOENT")
|
|
123
|
+
throw err;
|
|
124
|
+
}
|
|
125
|
+
handle = await fsp.open(tmpPath, "wx", mode);
|
|
126
|
+
await handle.writeFile(data, "utf8");
|
|
127
|
+
await handle.chmod(mode);
|
|
128
|
+
await handle.sync();
|
|
129
|
+
await handle.close();
|
|
130
|
+
handle = undefined;
|
|
131
|
+
options.signal?.throwIfAborted();
|
|
132
|
+
await renameFile(tmpPath, filePath);
|
|
133
|
+
cleanup = false;
|
|
134
|
+
// The rename is the irreversible publication point. Keep propagating a
|
|
135
|
+
// directory-sync failure, but mark it so a state transition can reconcile
|
|
136
|
+
// the visible replacement before deciding whether dispatch is safe.
|
|
137
|
+
try {
|
|
138
|
+
await syncDir(filePath);
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
throw markAtomicWritePublished(err);
|
|
142
|
+
}
|
|
143
|
+
return { signalAbortedAfterCommit: options.signal?.aborted === true };
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
if (handle)
|
|
147
|
+
await handle.close().catch(() => { });
|
|
148
|
+
if (cleanup)
|
|
149
|
+
await fsp.rm(tmpPath, { force: true }).catch(() => { });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
export async function writeFileAtomicExclusive(filePath, data, options = {}) {
|
|
153
|
+
const linkFile = options.linkFile ?? fsp.link;
|
|
154
|
+
const syncDir = options.syncParentDir ?? syncParentDir;
|
|
155
|
+
const dir = path.dirname(filePath);
|
|
156
|
+
const tmpPath = path.join(dir, `.${path.basename(filePath)}.${randomBytes(6).toString("hex")}.tmp`);
|
|
157
|
+
let handle;
|
|
158
|
+
try {
|
|
159
|
+
handle = await fsp.open(tmpPath, "wx", 0o600);
|
|
160
|
+
await handle.writeFile(data, "utf8");
|
|
161
|
+
await handle.chmod(0o600);
|
|
162
|
+
await handle.sync();
|
|
163
|
+
await handle.close();
|
|
164
|
+
handle = undefined;
|
|
165
|
+
try {
|
|
166
|
+
await linkFile(tmpPath, filePath);
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
if (!isLinkUnsupportedError(err))
|
|
170
|
+
throw err;
|
|
171
|
+
const unsupported = new Error("Atomic exclusive file creation requires hard-link support on this filesystem");
|
|
172
|
+
unsupported.code = "ENOTSUP";
|
|
173
|
+
unsupported.cause = err;
|
|
174
|
+
throw unsupported;
|
|
175
|
+
}
|
|
176
|
+
try {
|
|
177
|
+
await fsp.unlink(tmpPath);
|
|
178
|
+
await syncDir(filePath);
|
|
179
|
+
}
|
|
180
|
+
catch (err) {
|
|
181
|
+
await fsp.unlink(filePath).catch(() => { });
|
|
182
|
+
await syncDir(filePath).catch(() => { });
|
|
183
|
+
throw err;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
finally {
|
|
187
|
+
if (handle)
|
|
188
|
+
await handle.close().catch(() => { });
|
|
189
|
+
await fsp.rm(tmpPath, { force: true }).catch(() => { });
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=atomic_file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atomic_file.js","sourceRoot":"","sources":["../../../src/state/atomic_file.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { atomicWriteWasPublished, ensureDirectory, isAtomicExclusiveUnsupportedError, writeFileAtomic, writeFileAtomicExclusive, } from "./atomic_file.js";
|
|
2
|
+
export { atomicWriteWasPublished, ensureDirectory, isAtomicExclusiveUnsupportedError, writeFileAtomic, writeFileAtomicExclusive, stripExtendedLengthPrefix, } from "./atomic_file.js";
|
|
1
3
|
import os from "node:os";
|
|
2
4
|
import path from "node:path";
|
|
3
5
|
import { promises as fsp } from "node:fs";
|
|
@@ -35,100 +37,10 @@ export function stableStringify(value) {
|
|
|
35
37
|
return v;
|
|
36
38
|
});
|
|
37
39
|
}
|
|
38
|
-
function markAtomicWritePublished(err) {
|
|
39
|
-
if (err && (typeof err === "object" || typeof err === "function")) {
|
|
40
|
-
Object.defineProperty(err, "atomicWritePublished", {
|
|
41
|
-
value: true,
|
|
42
|
-
configurable: true,
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
return err;
|
|
46
|
-
}
|
|
47
|
-
export function atomicWriteWasPublished(err) {
|
|
48
|
-
return Boolean(err?.atomicWritePublished);
|
|
49
|
-
}
|
|
50
40
|
const STATE_LOCK_RETRY_MS = 10;
|
|
51
41
|
const STATE_LOCK_ORPHAN_MS = 30_000;
|
|
52
42
|
const STATE_LOCK_HEARTBEAT_MS = 250;
|
|
53
43
|
const TERMINAL_RESUME_CLEANUP_TIMEOUT_MS = STATE_LOCK_RETRY_MS * 10;
|
|
54
|
-
function isDirectorySyncUnsupportedError(err) {
|
|
55
|
-
return [
|
|
56
|
-
"EACCES",
|
|
57
|
-
"EBADF",
|
|
58
|
-
"EINVAL",
|
|
59
|
-
"EISDIR",
|
|
60
|
-
"ENOSYS",
|
|
61
|
-
"ENOTSUP",
|
|
62
|
-
"EOPNOTSUPP",
|
|
63
|
-
"EPERM",
|
|
64
|
-
].includes(err?.code);
|
|
65
|
-
}
|
|
66
|
-
async function syncParentDir(filePath) {
|
|
67
|
-
await syncDirectory(path.dirname(filePath));
|
|
68
|
-
}
|
|
69
|
-
async function syncDirectory(dir) {
|
|
70
|
-
let handle;
|
|
71
|
-
try {
|
|
72
|
-
handle = await fsp.open(dir, "r");
|
|
73
|
-
}
|
|
74
|
-
catch (err) {
|
|
75
|
-
if (isDirectorySyncUnsupportedError(err))
|
|
76
|
-
return;
|
|
77
|
-
throw err;
|
|
78
|
-
}
|
|
79
|
-
try {
|
|
80
|
-
await handle.sync();
|
|
81
|
-
}
|
|
82
|
-
catch (err) {
|
|
83
|
-
if (!isDirectorySyncUnsupportedError(err))
|
|
84
|
-
throw err;
|
|
85
|
-
}
|
|
86
|
-
finally {
|
|
87
|
-
if (handle)
|
|
88
|
-
await handle.close().catch(() => { });
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* On Windows, `fs.mkdir(..., { recursive: true })` reports the first created
|
|
93
|
-
* directory as an extended-length path (`\\?\C:\...`). `path.resolve` keeps
|
|
94
|
-
* that prefix, so such a path never compares equal to the plain drive path we
|
|
95
|
-
* walk toward and `path.relative` between the two yields an absolute path.
|
|
96
|
-
* Map the namespaces that have a plain equivalent back to it so both ends of the
|
|
97
|
-
* chain share one root form. The UNC marker is matched without regard to case,
|
|
98
|
-
* because Windows accepts a lowercase "unc" namespace component just as well.
|
|
99
|
-
*
|
|
100
|
-
* Device namespaces with no drive-letter or UNC equivalent, such as
|
|
101
|
-
* `\\?\Volume{GUID}\...`, are returned unchanged: stripping their prefix would
|
|
102
|
-
* leave a relative path and break an explicitly configured state directory.
|
|
103
|
-
*/
|
|
104
|
-
export function stripExtendedLengthPrefix(target) {
|
|
105
|
-
if (!target.startsWith("\\\\?\\"))
|
|
106
|
-
return target;
|
|
107
|
-
const rest = target.slice(4);
|
|
108
|
-
if (/^UNC\\/i.test(rest))
|
|
109
|
-
return `\\\\${rest.slice(4)}`;
|
|
110
|
-
if (/^[A-Za-z]:[\\/]/.test(rest))
|
|
111
|
-
return rest;
|
|
112
|
-
return target;
|
|
113
|
-
}
|
|
114
|
-
async function syncCreatedDirectoryChain(firstCreated, finalDir) {
|
|
115
|
-
const final = path.resolve(stripExtendedLengthPrefix(finalDir));
|
|
116
|
-
let current = path.resolve(stripExtendedLengthPrefix(firstCreated));
|
|
117
|
-
await syncDirectory(path.dirname(current));
|
|
118
|
-
while (current !== final) {
|
|
119
|
-
await syncDirectory(current);
|
|
120
|
-
const relative = path.relative(current, final);
|
|
121
|
-
const next = relative.split(path.sep)[0];
|
|
122
|
-
if (!next || next === "..")
|
|
123
|
-
break;
|
|
124
|
-
current = path.join(current, next);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
export async function ensureDirectory(dir) {
|
|
128
|
-
const created = await fsp.mkdir(dir, { recursive: true });
|
|
129
|
-
if (created)
|
|
130
|
-
await syncCreatedDirectoryChain(created, dir);
|
|
131
|
-
}
|
|
132
44
|
export function isJsonSyntaxError(err) {
|
|
133
45
|
return err instanceof SyntaxError;
|
|
134
46
|
}
|
|
@@ -401,108 +313,10 @@ export async function withFileLock({ filePath, signal, task, }) {
|
|
|
401
313
|
}
|
|
402
314
|
}
|
|
403
315
|
}
|
|
404
|
-
function isLinkUnsupportedError(err) {
|
|
405
|
-
return ["ENOSYS", "ENOTSUP", "EOPNOTSUPP", "EPERM", "EXDEV"].includes(err?.code);
|
|
406
|
-
}
|
|
407
|
-
export function isAtomicExclusiveUnsupportedError(err) {
|
|
408
|
-
return err?.code === "ENOTSUP" && err?.cause && isLinkUnsupportedError(err.cause);
|
|
409
|
-
}
|
|
410
316
|
function isOptionalApprovalIndexPersistenceError(err) {
|
|
411
317
|
return (isAtomicExclusiveUnsupportedError(err) ||
|
|
412
318
|
["EACCES", "EDQUOT", "EIO", "ENOSPC", "EPERM", "EROFS"].includes(err?.code));
|
|
413
319
|
}
|
|
414
|
-
/**
|
|
415
|
-
* Write a file atomically: stage to a sibling temp file, fsync, then rename
|
|
416
|
-
* over the target. `rename(2)` is atomic on a single filesystem, so a reader
|
|
417
|
-
* (or a crash) never observes a truncated/partial file — it sees either the
|
|
418
|
-
* complete old content or the complete new content. Plain `fsp.writeFile`
|
|
419
|
-
* truncates the target up front, leaving a corruption window on SIGKILL/OOM/
|
|
420
|
-
* power loss. New state files are private by default; existing file modes are
|
|
421
|
-
* preserved across replacement. The temp file is removed on any failed path.
|
|
422
|
-
*/
|
|
423
|
-
export async function writeFileAtomic(filePath, data, options = {}) {
|
|
424
|
-
const renameFile = options.renameFile ?? fsp.rename;
|
|
425
|
-
const syncDir = options.syncParentDir ?? syncParentDir;
|
|
426
|
-
const dir = path.dirname(filePath);
|
|
427
|
-
const tmpPath = path.join(dir, `.${path.basename(filePath)}.${randomBytes(6).toString("hex")}.tmp`);
|
|
428
|
-
let mode = 0o600;
|
|
429
|
-
let handle;
|
|
430
|
-
let cleanup = true;
|
|
431
|
-
try {
|
|
432
|
-
try {
|
|
433
|
-
mode = (await fsp.stat(filePath)).mode & 0o777;
|
|
434
|
-
}
|
|
435
|
-
catch (err) {
|
|
436
|
-
if (err?.code !== "ENOENT")
|
|
437
|
-
throw err;
|
|
438
|
-
}
|
|
439
|
-
handle = await fsp.open(tmpPath, "wx", mode);
|
|
440
|
-
await handle.writeFile(data, "utf8");
|
|
441
|
-
await handle.chmod(mode);
|
|
442
|
-
await handle.sync();
|
|
443
|
-
await handle.close();
|
|
444
|
-
handle = undefined;
|
|
445
|
-
options.signal?.throwIfAborted();
|
|
446
|
-
await renameFile(tmpPath, filePath);
|
|
447
|
-
cleanup = false;
|
|
448
|
-
// The rename is the irreversible publication point. Keep propagating a
|
|
449
|
-
// directory-sync failure, but mark it so a state transition can reconcile
|
|
450
|
-
// the visible replacement before deciding whether dispatch is safe.
|
|
451
|
-
try {
|
|
452
|
-
await syncDir(filePath);
|
|
453
|
-
}
|
|
454
|
-
catch (err) {
|
|
455
|
-
throw markAtomicWritePublished(err);
|
|
456
|
-
}
|
|
457
|
-
return { signalAbortedAfterCommit: options.signal?.aborted === true };
|
|
458
|
-
}
|
|
459
|
-
finally {
|
|
460
|
-
if (handle)
|
|
461
|
-
await handle.close().catch(() => { });
|
|
462
|
-
if (cleanup)
|
|
463
|
-
await fsp.rm(tmpPath, { force: true }).catch(() => { });
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
export async function writeFileAtomicExclusive(filePath, data, options = {}) {
|
|
467
|
-
const linkFile = options.linkFile ?? fsp.link;
|
|
468
|
-
const syncDir = options.syncParentDir ?? syncParentDir;
|
|
469
|
-
const dir = path.dirname(filePath);
|
|
470
|
-
const tmpPath = path.join(dir, `.${path.basename(filePath)}.${randomBytes(6).toString("hex")}.tmp`);
|
|
471
|
-
let handle;
|
|
472
|
-
try {
|
|
473
|
-
handle = await fsp.open(tmpPath, "wx", 0o600);
|
|
474
|
-
await handle.writeFile(data, "utf8");
|
|
475
|
-
await handle.chmod(0o600);
|
|
476
|
-
await handle.sync();
|
|
477
|
-
await handle.close();
|
|
478
|
-
handle = undefined;
|
|
479
|
-
try {
|
|
480
|
-
await linkFile(tmpPath, filePath);
|
|
481
|
-
}
|
|
482
|
-
catch (err) {
|
|
483
|
-
if (!isLinkUnsupportedError(err))
|
|
484
|
-
throw err;
|
|
485
|
-
const unsupported = new Error("Atomic exclusive file creation requires hard-link support on this filesystem");
|
|
486
|
-
unsupported.code = "ENOTSUP";
|
|
487
|
-
unsupported.cause = err;
|
|
488
|
-
throw unsupported;
|
|
489
|
-
}
|
|
490
|
-
try {
|
|
491
|
-
await fsp.unlink(tmpPath);
|
|
492
|
-
await syncDir(filePath);
|
|
493
|
-
}
|
|
494
|
-
catch (err) {
|
|
495
|
-
await fsp.unlink(filePath).catch(() => { });
|
|
496
|
-
await syncDir(filePath).catch(() => { });
|
|
497
|
-
throw err;
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
finally {
|
|
501
|
-
if (handle)
|
|
502
|
-
await handle.close().catch(() => { });
|
|
503
|
-
await fsp.rm(tmpPath, { force: true }).catch(() => { });
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
320
|
export async function readStateJson({ env, key, signal = undefined, }) {
|
|
507
321
|
signal?.throwIfAborted();
|
|
508
322
|
const stateDir = defaultStateDir(env);
|