@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
package/node_modules/@clawdbot/lobster/node_modules/fast-uri/test/mailto-authority-security.test.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const test = require('tape')
|
|
4
|
+
const fastURI = require('..')
|
|
5
|
+
|
|
6
|
+
// GHSA-88VG-QFHM-JX5Q: `mailto://h/a` carries an authority (which RFC 6068 does
|
|
7
|
+
// not define for `mailto`) and a path. `mailtoParse` used to retain that
|
|
8
|
+
// authority and fold the path's leading "/" into the recipient local part; the
|
|
9
|
+
// generic serializer then reinserted a "/" separator on every pass, so
|
|
10
|
+
// serialize(parse(x)) was not a fixpoint and normalize() accreted one "%2F" per
|
|
11
|
+
// pass (unbounded growth for a renormalize-to-fixpoint consumer).
|
|
12
|
+
|
|
13
|
+
const authorityForms = [
|
|
14
|
+
['mailto://h/a', 'mailto:%2Fa@'],
|
|
15
|
+
['mailto://h/a@b', 'mailto:%2Fa@b'],
|
|
16
|
+
['mailto://h/', 'mailto:%2F@'],
|
|
17
|
+
['mailto://h/a,b', 'mailto:%2Fa@,b@'],
|
|
18
|
+
['mailto://user@h/a', 'mailto:%2Fa@'],
|
|
19
|
+
['mailto://h:8080/a', 'mailto:%2Fa@'],
|
|
20
|
+
['mailto://', 'mailto://'],
|
|
21
|
+
// recipients can come from a `to=` hfield even when the path is empty
|
|
22
|
+
['mailto://h?to=x@y', 'mailto:x@y'],
|
|
23
|
+
['mailto://h?to=x@y&to=a@b', 'mailto:x@y,a@b']
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
test('mailto with a retained authority and a path normalizes to a fixpoint', (t) => {
|
|
27
|
+
t.plan(authorityForms.length * 2)
|
|
28
|
+
|
|
29
|
+
for (const [input] of authorityForms) {
|
|
30
|
+
const once = fastURI.normalize(input)
|
|
31
|
+
const twice = fastURI.normalize(once)
|
|
32
|
+
|
|
33
|
+
t.equal(twice, once, input + ' normalize is idempotent')
|
|
34
|
+
t.equal(fastURI.equal(input, once), true, input + ' equals its normalized form')
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
test('mailto serialize(parse()) is a stable round trip for the authority form', (t) => {
|
|
39
|
+
t.plan(authorityForms.length)
|
|
40
|
+
|
|
41
|
+
for (const [input, expected] of authorityForms) {
|
|
42
|
+
t.equal(fastURI.serialize(fastURI.parse(input)), expected, input + ' round trips to a stable value')
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test('mailto authority form does not grow without bound under renormalization', (t) => {
|
|
47
|
+
// A renormalize-to-fixpoint loop must terminate instead of growing forever.
|
|
48
|
+
// A single normalize call already terminates, so this guards the fixpoint.
|
|
49
|
+
const inputs = ['mailto://h/a', 'mailto://h/a@b', 'mailto://h/a,b']
|
|
50
|
+
|
|
51
|
+
t.plan(inputs.length * 2)
|
|
52
|
+
|
|
53
|
+
for (const input of inputs) {
|
|
54
|
+
const first = fastURI.normalize(input)
|
|
55
|
+
let s = input
|
|
56
|
+
let iters = 0
|
|
57
|
+
let stable = false
|
|
58
|
+
while (iters < 1000) {
|
|
59
|
+
const next = fastURI.normalize(s)
|
|
60
|
+
if (next === s) {
|
|
61
|
+
stable = true
|
|
62
|
+
break
|
|
63
|
+
}
|
|
64
|
+
s = next
|
|
65
|
+
iters++
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
t.equal(stable, true, input + ' reaches a fixpoint')
|
|
69
|
+
t.equal(s.length, first.length, input + ' does not grow')
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test('mailto authority handling preserves host normalization for skip-normalize schemes', (t) => {
|
|
74
|
+
// Regression: a bare `mailto://host` with no path must keep its host and stay
|
|
75
|
+
// idempotent, so the generic host normalization path is unaffected.
|
|
76
|
+
const encodedHost = 'mailto://%41.com'
|
|
77
|
+
const literalHost = 'mailto://a.com'
|
|
78
|
+
|
|
79
|
+
t.equal(fastURI.parse(encodedHost).host, fastURI.parse(literalHost).host, 'parse results have consistent hosts')
|
|
80
|
+
t.equal(fastURI.normalize(encodedHost), fastURI.normalize(literalHost), 'normalize results are consistent')
|
|
81
|
+
t.equal(fastURI.equal(encodedHost, literalHost), true, 'encoded and literal hosts compare equal')
|
|
82
|
+
t.equal(fastURI.normalize(literalHost), literalHost, 'bare authority mailto is idempotent')
|
|
83
|
+
t.end()
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
test('mailto authority form is reported as malformed on the parsed component', (t) => {
|
|
87
|
+
t.equal(
|
|
88
|
+
fastURI.parse('mailto://h/a').error,
|
|
89
|
+
'URI mailto must not have an authority component.',
|
|
90
|
+
'the retained authority is surfaced as an error'
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
// A valid, authority-free mailto must not be flagged.
|
|
94
|
+
t.equal(fastURI.parse('mailto:user@host.com').error, undefined, 'well-formed mailto has no error')
|
|
95
|
+
t.end()
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
test('mailto serializer drops caller-supplied authority when recipients are present', (t) => {
|
|
99
|
+
t.equal(
|
|
100
|
+
fastURI.serialize({ scheme: 'mailto', host: 'h', to: ['a@b'] }),
|
|
101
|
+
'mailto:a@b',
|
|
102
|
+
'authority is dropped for direct recipients'
|
|
103
|
+
)
|
|
104
|
+
t.equal(
|
|
105
|
+
fastURI.serialize({ scheme: 'mailto', userinfo: 'u', host: 'h', port: 8080, to: ['a@b'] }),
|
|
106
|
+
'mailto:a@b',
|
|
107
|
+
'userinfo, host, and port are dropped for direct recipients'
|
|
108
|
+
)
|
|
109
|
+
t.equal(
|
|
110
|
+
fastURI.serialize({ scheme: 'mailto', host: 'h', headers: { to: 'a@b' } }),
|
|
111
|
+
'mailto:a@b',
|
|
112
|
+
'authority is dropped for recipients supplied through a to hfield'
|
|
113
|
+
)
|
|
114
|
+
t.equal(
|
|
115
|
+
fastURI.serialize({ scheme: 'mailto', host: 'h', to: ['a@b'], subject: 'hello' }),
|
|
116
|
+
'mailto:a@b?subject=hello',
|
|
117
|
+
'dropping authority preserves header fields'
|
|
118
|
+
)
|
|
119
|
+
t.equal(
|
|
120
|
+
fastURI.serialize({ scheme: 'mailto', host: 'h' }),
|
|
121
|
+
'mailto://h',
|
|
122
|
+
'bare authority without recipients remains idempotent'
|
|
123
|
+
)
|
|
124
|
+
t.end()
|
|
125
|
+
})
|
package/node_modules/@clawdbot/lobster/node_modules/fast-uri/test/mailto-field-name-security.test.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const test = require('tape')
|
|
4
|
+
const fastURI = require('..')
|
|
5
|
+
|
|
6
|
+
function encodeCharacter (value, index, lowercaseHex) {
|
|
7
|
+
let hex = value.charCodeAt(index).toString(16)
|
|
8
|
+
if (!lowercaseHex) hex = hex.toUpperCase()
|
|
9
|
+
return value.slice(0, index) + '%' + hex + value.slice(index + 1)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function mailtoState (component) {
|
|
13
|
+
return {
|
|
14
|
+
to: component.to,
|
|
15
|
+
subject: component.subject,
|
|
16
|
+
body: component.body,
|
|
17
|
+
headers: component.headers && { ...component.headers }
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
test('mailto parsing classifies decoded, case-insensitive reserved field names', (t) => {
|
|
22
|
+
const cases = [
|
|
23
|
+
{ name: 'to', value: 'attacker@evil.test', property: 'to' },
|
|
24
|
+
{ name: 'subject', value: 'injected subject', property: 'subject' },
|
|
25
|
+
{ name: 'body', value: 'injected body', property: 'body' }
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
for (const entry of cases) {
|
|
29
|
+
const variants = new Set([entry.name.toUpperCase()])
|
|
30
|
+
for (let i = 0; i < entry.name.length; i++) {
|
|
31
|
+
variants.add(encodeCharacter(entry.name, i, false))
|
|
32
|
+
variants.add(encodeCharacter(entry.name, i, true))
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
for (const name of variants) {
|
|
36
|
+
const parsed = fastURI.parse(`mailto:alice@example.test?${name}=${entry.value}`)
|
|
37
|
+
if (entry.property === 'to') {
|
|
38
|
+
t.deepEqual(parsed.to, ['alice@example.test', entry.value], name + ' is classified as a recipient')
|
|
39
|
+
} else {
|
|
40
|
+
t.equal(parsed[entry.property], entry.value, name + ' is classified as ' + entry.property)
|
|
41
|
+
}
|
|
42
|
+
t.equal(parsed.headers, undefined, name + ' is not exposed as a generic header')
|
|
43
|
+
|
|
44
|
+
const reparsed = fastURI.parse(fastURI.serialize(parsed))
|
|
45
|
+
t.deepEqual(mailtoState(reparsed), mailtoState(parsed), name + ' keeps its meaning after a roundtrip')
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
t.end()
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
test('mailto generic field names are decoded exactly once across roundtrips', (t) => {
|
|
53
|
+
const cases = [
|
|
54
|
+
['%2574o', '%74o'],
|
|
55
|
+
['%2573ubject', '%73ubject'],
|
|
56
|
+
['%2562ody', '%62ody'],
|
|
57
|
+
['x%2520y', 'x%20y'],
|
|
58
|
+
['%26to', '&to'],
|
|
59
|
+
['%25GGto', '%GGto']
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
for (const [encodedName, decodedName] of cases) {
|
|
63
|
+
let serialized = `mailto:alice@example.test?${encodedName}=value`
|
|
64
|
+
for (let round = 0; round < 3; round++) {
|
|
65
|
+
const parsed = fastURI.parse(serialized)
|
|
66
|
+
t.deepEqual({ ...parsed.headers }, { [decodedName]: 'value' }, encodedName + ' stays generic in round ' + round)
|
|
67
|
+
t.deepEqual(parsed.to, ['alice@example.test'], encodedName + ' does not add a recipient in round ' + round)
|
|
68
|
+
t.equal(parsed.subject, undefined, encodedName + ' does not set a subject in round ' + round)
|
|
69
|
+
t.equal(parsed.body, undefined, encodedName + ' does not set a body in round ' + round)
|
|
70
|
+
serialized = fastURI.serialize(parsed)
|
|
71
|
+
}
|
|
72
|
+
t.equal(serialized, `mailto:alice@example.test?${encodedName}=value`, encodedName + ' serializes idempotently')
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
t.equal(
|
|
76
|
+
fastURI.serialize({ scheme: 'mailto', to: ['alice@example.test'], headers: { '%74o': 'value' } }),
|
|
77
|
+
'mailto:alice@example.test?%2574o=value',
|
|
78
|
+
'a percent sequence in a decoded component key is encoded as data'
|
|
79
|
+
)
|
|
80
|
+
t.end()
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
test('mailto serialization canonicalizes reserved generic header names', (t) => {
|
|
84
|
+
const serialized = fastURI.serialize({
|
|
85
|
+
scheme: 'mailto',
|
|
86
|
+
to: ['alice@example.test'],
|
|
87
|
+
subject: 'safe subject',
|
|
88
|
+
body: 'safe body',
|
|
89
|
+
headers: {
|
|
90
|
+
TO: 'attacker@evil.test',
|
|
91
|
+
Subject: 'hidden subject',
|
|
92
|
+
BODY: 'hidden body',
|
|
93
|
+
cc: 'copy@example.test'
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
t.equal(
|
|
98
|
+
serialized,
|
|
99
|
+
'mailto:alice@example.test,attacker@evil.test?subject=safe%20subject&body=safe%20body&cc=copy@example.test',
|
|
100
|
+
'dedicated properties override header variants and all recipients are visible in the path'
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
const parsed = fastURI.parse(serialized)
|
|
104
|
+
t.deepEqual(parsed.to, ['alice@example.test', 'attacker@evil.test'], 'canonical recipients are classified consistently')
|
|
105
|
+
t.equal(parsed.subject, 'safe subject', 'the dedicated subject wins')
|
|
106
|
+
t.equal(parsed.body, 'safe body', 'the dedicated body wins')
|
|
107
|
+
t.deepEqual({ ...parsed.headers }, { cc: 'copy@example.test' }, 'only generic headers remain generic')
|
|
108
|
+
|
|
109
|
+
const empty = fastURI.serialize({
|
|
110
|
+
scheme: 'mailto',
|
|
111
|
+
to: ['alice@example.test'],
|
|
112
|
+
subject: '',
|
|
113
|
+
body: '',
|
|
114
|
+
headers: { Subject: 'hidden subject', BODY: 'hidden body' }
|
|
115
|
+
})
|
|
116
|
+
t.equal(empty, 'mailto:alice@example.test?subject=&body=', 'explicit empty properties override header variants')
|
|
117
|
+
const emptyParsed = fastURI.parse(empty)
|
|
118
|
+
t.equal(emptyParsed.subject, '', 'an empty subject round-trips')
|
|
119
|
+
t.equal(emptyParsed.body, '', 'an empty body round-trips')
|
|
120
|
+
t.end()
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
test('mailto duplicate reserved fields have deterministic parsing semantics', (t) => {
|
|
124
|
+
const parsed = fastURI.parse(
|
|
125
|
+
'mailto:alice@example.test?subject=first&%53UBJECT=last&body=first&%42ODY=last&to=one@example.test&%54O=two@example.test'
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
t.equal(parsed.subject, 'last', 'the last subject wins')
|
|
129
|
+
t.equal(parsed.body, 'last', 'the last body wins')
|
|
130
|
+
t.deepEqual(
|
|
131
|
+
parsed.to,
|
|
132
|
+
['alice@example.test', 'one@example.test', 'two@example.test'],
|
|
133
|
+
'all recipient fields are accumulated'
|
|
134
|
+
)
|
|
135
|
+
t.equal(parsed.headers, undefined, 'no reserved spelling remains generic')
|
|
136
|
+
t.end()
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
test('encoded reserved field names expose decoded control characters immediately', (t) => {
|
|
140
|
+
const input = 'mailto:alice@example.test?%73ubject=hello%0D%0Aworld'
|
|
141
|
+
const parsed = fastURI.parse(input)
|
|
142
|
+
|
|
143
|
+
t.equal(parsed.subject, 'hello\r\nworld', 'the first parse exposes CRLF in the dedicated property')
|
|
144
|
+
t.equal(parsed.headers, undefined, 'the subject is not hidden as a generic header')
|
|
145
|
+
t.equal(
|
|
146
|
+
fastURI.parse(fastURI.serialize(parsed)).subject,
|
|
147
|
+
parsed.subject,
|
|
148
|
+
'the decoded subject remains stable after a roundtrip'
|
|
149
|
+
)
|
|
150
|
+
t.end()
|
|
151
|
+
})
|
package/node_modules/@clawdbot/lobster/node_modules/fast-uri/test/security-normalization.test.js
CHANGED
|
@@ -126,6 +126,44 @@ test('hostname normalization decodes only current unreserved escapes', (t) => {
|
|
|
126
126
|
t.end()
|
|
127
127
|
})
|
|
128
128
|
|
|
129
|
+
test('scheme-relative hostname normalization folds decoded ASCII case', (t) => {
|
|
130
|
+
const encodedHost = '//%41.com'
|
|
131
|
+
const normalizedHost = fastURI.normalize(encodedHost)
|
|
132
|
+
const encodedMetadata = '//%4Detadata.internal/private'
|
|
133
|
+
const literalMetadata = '//metadata.internal/private'
|
|
134
|
+
|
|
135
|
+
t.equal(fastURI.parse(encodedHost).host, 'a.com', 'parse folds an encoded uppercase host letter')
|
|
136
|
+
t.equal(normalizedHost, '//a.com', 'normalize emits a lowercase host')
|
|
137
|
+
t.equal(fastURI.normalize(normalizedHost), normalizedHost, 'host normalization is idempotent')
|
|
138
|
+
t.equal(fastURI.equal(encodedHost, '//a.com'), true, 'encoded and literal host spellings compare equal')
|
|
139
|
+
t.equal(fastURI.equal(encodedMetadata, literalMetadata), true, 'encoded metadata host compares equal')
|
|
140
|
+
t.equal(
|
|
141
|
+
fastURI.resolve('x://trusted.example/', encodedMetadata),
|
|
142
|
+
fastURI.resolve('x://trusted.example/', literalMetadata),
|
|
143
|
+
'encoded and literal metadata hosts resolve identically'
|
|
144
|
+
)
|
|
145
|
+
t.equal(
|
|
146
|
+
fastURI.normalize('//example.com%2fpath'),
|
|
147
|
+
'//example.com%2Fpath',
|
|
148
|
+
'reserved host escapes remain encoded with uppercase hex'
|
|
149
|
+
)
|
|
150
|
+
t.equal(fastURI.normalize('//%2541.com'), '//%2541.com', 'nested host escapes are not decoded twice')
|
|
151
|
+
t.equal(fastURI.equal('//User@%41.com/path', '//user@a.com/path'), false, 'userinfo remains case-sensitive')
|
|
152
|
+
t.equal(fastURI.equal('//%41.com/Path', '//a.com/path'), false, 'path remains case-sensitive')
|
|
153
|
+
t.equal(fastURI.equal('//%41.com/?Token=Value', '//a.com/?token=value'), false, 'query remains case-sensitive')
|
|
154
|
+
t.end()
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
test('host normalization applies to schemes that skip path normalization', (t) => {
|
|
158
|
+
const encodedHost = 'mailto://%41.com'
|
|
159
|
+
const literalHost = 'mailto://a.com'
|
|
160
|
+
|
|
161
|
+
t.equal(fastURI.parse(encodedHost).host, fastURI.parse(literalHost).host, 'parse results have consistent hosts')
|
|
162
|
+
t.equal(fastURI.normalize(encodedHost), fastURI.normalize(literalHost), 'normalize results are consistent')
|
|
163
|
+
t.equal(fastURI.equal(encodedHost, literalHost), true, 'encoded and literal hosts compare equal')
|
|
164
|
+
t.end()
|
|
165
|
+
})
|
|
166
|
+
|
|
129
167
|
test('host conversion failures are not treated as comparable URLs', (t) => {
|
|
130
168
|
const malformedHost = 'http://trusted.test%2540evil.test/'
|
|
131
169
|
|
|
@@ -5,6 +5,22 @@ declare namespace fastUri {
|
|
|
5
5
|
scheme?: string;
|
|
6
6
|
userinfo?: string;
|
|
7
7
|
host?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Zone identifier of a zoned IPv6 host, e.g. `"eth0"` or `"25eth0"`. Set by
|
|
10
|
+
* `parse` for a bracketed IPv6 literal so `serialize`/`normalize` can
|
|
11
|
+
* reproduce the exact zone without re-deriving it from the ambiguous
|
|
12
|
+
* single-`%` form. It is validated on use, so a value that does not match
|
|
13
|
+
* `host` (for example after `host` is reassigned) is ignored.
|
|
14
|
+
*
|
|
15
|
+
* When building a component object by hand, set `ipv6Zone` to disambiguate
|
|
16
|
+
* a single-`%` host whose zone is ambiguous (a zone beginning with `25`
|
|
17
|
+
* is re-read as a `%25` separator). Without it, `serialize` falls back to
|
|
18
|
+
* a best-effort heuristic and may reinterpret such a zone, e.g. `{ host:
|
|
19
|
+
* "fe80::1%25eth0" }` serializes to `[fe80::1%25eth0]` (zone `eth0`), while
|
|
20
|
+
* `{ host: "fe80::1%25eth0", ipv6Zone: "25eth0" }` serializes to
|
|
21
|
+
* `[fe80::1%2525eth0]` (zone `25eth0`).
|
|
22
|
+
*/
|
|
23
|
+
ipv6Zone?: string;
|
|
8
24
|
port?: number | string;
|
|
9
25
|
path?: string;
|
|
10
26
|
query?: string;
|
package/node_modules/@clawdbot/lobster/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js
CHANGED
|
@@ -64,46 +64,47 @@ function plainValue(source, onError) {
|
|
|
64
64
|
}
|
|
65
65
|
if (badChar)
|
|
66
66
|
onError(0, 'BAD_SCALAR_START', `Plain value cannot start with ${badChar}`);
|
|
67
|
-
return
|
|
67
|
+
return unfoldLines(source);
|
|
68
68
|
}
|
|
69
69
|
function singleQuotedValue(source, onError) {
|
|
70
70
|
if (source[source.length - 1] !== "'" || source.length === 1)
|
|
71
71
|
onError(source.length, 'MISSING_CHAR', "Missing closing 'quote");
|
|
72
|
-
return
|
|
72
|
+
return unfoldLines(source.slice(1, -1)).replace(/''/g, "'");
|
|
73
73
|
}
|
|
74
|
-
function
|
|
74
|
+
function unfoldLines(source) {
|
|
75
|
+
const line = /(.*?)\r?\n/sy;
|
|
76
|
+
let match = line.exec(source);
|
|
77
|
+
if (!match)
|
|
78
|
+
return source;
|
|
75
79
|
/**
|
|
76
|
-
* The negative
|
|
80
|
+
* The negative lookbehinds in these RegExps are to
|
|
77
81
|
* prevent causing a polynomial search time in certain cases.
|
|
78
82
|
*
|
|
79
|
-
* The try-catch is for Safari
|
|
83
|
+
* The try-catch is for Safari < 16.4 and other old browsers:
|
|
80
84
|
* https://caniuse.com/js-regexp-lookbehind
|
|
81
85
|
*/
|
|
82
|
-
let
|
|
86
|
+
let trimEnd, trimBoth;
|
|
83
87
|
try {
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
trimEnd = new RegExp('(?<![ \t])[ \t]+$');
|
|
89
|
+
trimBoth = new RegExp('^[ \t]+|(?<![ \t])[ \t]+$', 'g');
|
|
86
90
|
}
|
|
87
91
|
catch {
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
trimEnd = /[ \t]+$/;
|
|
93
|
+
trimBoth = /^[ \t]+|[ \t]+$/g;
|
|
90
94
|
}
|
|
91
|
-
let
|
|
92
|
-
if (!match)
|
|
93
|
-
return source;
|
|
94
|
-
let res = match[1];
|
|
95
|
+
let res = match[1].replace(trimEnd, '');
|
|
95
96
|
let sep = ' ';
|
|
96
|
-
let pos =
|
|
97
|
-
line.lastIndex = pos;
|
|
97
|
+
let pos = line.lastIndex;
|
|
98
98
|
while ((match = line.exec(source))) {
|
|
99
|
-
|
|
99
|
+
const lm = match[1].replace(trimBoth, '');
|
|
100
|
+
if (lm === '') {
|
|
100
101
|
if (sep === '\n')
|
|
101
102
|
res += sep;
|
|
102
103
|
else
|
|
103
104
|
sep = '\n';
|
|
104
105
|
}
|
|
105
106
|
else {
|
|
106
|
-
res += sep +
|
|
107
|
+
res += sep + lm;
|
|
107
108
|
sep = ' ';
|
|
108
109
|
}
|
|
109
110
|
pos = line.lastIndex;
|
|
@@ -43,38 +43,40 @@ class Alias extends NodeBase {
|
|
|
43
43
|
if (node.anchor === this.source)
|
|
44
44
|
found = node;
|
|
45
45
|
}
|
|
46
|
+
if (found && ctx) {
|
|
47
|
+
const { anchors, doc, maxAliasCount } = ctx;
|
|
48
|
+
let data = anchors.get(found);
|
|
49
|
+
if (!data) {
|
|
50
|
+
// Resolve anchors for Node.prototype.toJS()
|
|
51
|
+
toJS(found, null, ctx);
|
|
52
|
+
data = anchors.get(found);
|
|
53
|
+
}
|
|
54
|
+
/* istanbul ignore if */
|
|
55
|
+
if (data?.res === undefined) {
|
|
56
|
+
const msg = 'This should not happen: Alias anchor was not resolved?';
|
|
57
|
+
throw new ReferenceError(msg);
|
|
58
|
+
}
|
|
59
|
+
if (maxAliasCount >= 0) {
|
|
60
|
+
data.count += 1;
|
|
61
|
+
if (data.aliasCount === 0)
|
|
62
|
+
data.aliasCount = getAliasCount(doc, found, anchors);
|
|
63
|
+
if (data.count * data.aliasCount > maxAliasCount) {
|
|
64
|
+
const msg = 'Excessive alias count indicates a resource exhaustion attack';
|
|
65
|
+
throw new ReferenceError(msg);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
46
69
|
return found;
|
|
47
70
|
}
|
|
48
71
|
toJSON(_arg, ctx) {
|
|
49
72
|
if (!ctx)
|
|
50
73
|
return { source: this.source };
|
|
51
|
-
const
|
|
52
|
-
const source = this.resolve(doc, ctx);
|
|
74
|
+
const source = this.resolve(ctx.doc, ctx);
|
|
53
75
|
if (!source) {
|
|
54
76
|
const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
|
|
55
77
|
throw new ReferenceError(msg);
|
|
56
78
|
}
|
|
57
|
-
|
|
58
|
-
if (!data) {
|
|
59
|
-
// Resolve anchors for Node.prototype.toJS()
|
|
60
|
-
toJS(source, null, ctx);
|
|
61
|
-
data = anchors.get(source);
|
|
62
|
-
}
|
|
63
|
-
/* istanbul ignore if */
|
|
64
|
-
if (data?.res === undefined) {
|
|
65
|
-
const msg = 'This should not happen: Alias anchor was not resolved?';
|
|
66
|
-
throw new ReferenceError(msg);
|
|
67
|
-
}
|
|
68
|
-
if (maxAliasCount >= 0) {
|
|
69
|
-
data.count += 1;
|
|
70
|
-
if (data.aliasCount === 0)
|
|
71
|
-
data.aliasCount = getAliasCount(doc, source, anchors);
|
|
72
|
-
if (data.count * data.aliasCount > maxAliasCount) {
|
|
73
|
-
const msg = 'Excessive alias count indicates a resource exhaustion attack';
|
|
74
|
-
throw new ReferenceError(msg);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return data.res;
|
|
79
|
+
return ctx.anchors.get(source).res;
|
|
78
80
|
}
|
|
79
81
|
toString(ctx, _onComment, _onChompKeep) {
|
|
80
82
|
const src = `*${this.source}`;
|
package/node_modules/@clawdbot/lobster/node_modules/yaml/dist/compose/resolve-flow-scalar.js
CHANGED
|
@@ -66,46 +66,47 @@ function plainValue(source, onError) {
|
|
|
66
66
|
}
|
|
67
67
|
if (badChar)
|
|
68
68
|
onError(0, 'BAD_SCALAR_START', `Plain value cannot start with ${badChar}`);
|
|
69
|
-
return
|
|
69
|
+
return unfoldLines(source);
|
|
70
70
|
}
|
|
71
71
|
function singleQuotedValue(source, onError) {
|
|
72
72
|
if (source[source.length - 1] !== "'" || source.length === 1)
|
|
73
73
|
onError(source.length, 'MISSING_CHAR', "Missing closing 'quote");
|
|
74
|
-
return
|
|
74
|
+
return unfoldLines(source.slice(1, -1)).replace(/''/g, "'");
|
|
75
75
|
}
|
|
76
|
-
function
|
|
76
|
+
function unfoldLines(source) {
|
|
77
|
+
const line = /(.*?)\r?\n/sy;
|
|
78
|
+
let match = line.exec(source);
|
|
79
|
+
if (!match)
|
|
80
|
+
return source;
|
|
77
81
|
/**
|
|
78
|
-
* The negative
|
|
82
|
+
* The negative lookbehinds in these RegExps are to
|
|
79
83
|
* prevent causing a polynomial search time in certain cases.
|
|
80
84
|
*
|
|
81
|
-
* The try-catch is for Safari
|
|
85
|
+
* The try-catch is for Safari < 16.4 and other old browsers:
|
|
82
86
|
* https://caniuse.com/js-regexp-lookbehind
|
|
83
87
|
*/
|
|
84
|
-
let
|
|
88
|
+
let trimEnd, trimBoth;
|
|
85
89
|
try {
|
|
86
|
-
|
|
87
|
-
|
|
90
|
+
trimEnd = new RegExp('(?<![ \t])[ \t]+$');
|
|
91
|
+
trimBoth = new RegExp('^[ \t]+|(?<![ \t])[ \t]+$', 'g');
|
|
88
92
|
}
|
|
89
93
|
catch {
|
|
90
|
-
|
|
91
|
-
|
|
94
|
+
trimEnd = /[ \t]+$/;
|
|
95
|
+
trimBoth = /^[ \t]+|[ \t]+$/g;
|
|
92
96
|
}
|
|
93
|
-
let
|
|
94
|
-
if (!match)
|
|
95
|
-
return source;
|
|
96
|
-
let res = match[1];
|
|
97
|
+
let res = match[1].replace(trimEnd, '');
|
|
97
98
|
let sep = ' ';
|
|
98
|
-
let pos =
|
|
99
|
-
line.lastIndex = pos;
|
|
99
|
+
let pos = line.lastIndex;
|
|
100
100
|
while ((match = line.exec(source))) {
|
|
101
|
-
|
|
101
|
+
const lm = match[1].replace(trimBoth, '');
|
|
102
|
+
if (lm === '') {
|
|
102
103
|
if (sep === '\n')
|
|
103
104
|
res += sep;
|
|
104
105
|
else
|
|
105
106
|
sep = '\n';
|
|
106
107
|
}
|
|
107
108
|
else {
|
|
108
|
-
res += sep +
|
|
109
|
+
res += sep + lm;
|
|
109
110
|
sep = ' ';
|
|
110
111
|
}
|
|
111
112
|
pos = line.lastIndex;
|
|
@@ -45,38 +45,40 @@ class Alias extends Node.NodeBase {
|
|
|
45
45
|
if (node.anchor === this.source)
|
|
46
46
|
found = node;
|
|
47
47
|
}
|
|
48
|
+
if (found && ctx) {
|
|
49
|
+
const { anchors, doc, maxAliasCount } = ctx;
|
|
50
|
+
let data = anchors.get(found);
|
|
51
|
+
if (!data) {
|
|
52
|
+
// Resolve anchors for Node.prototype.toJS()
|
|
53
|
+
toJS.toJS(found, null, ctx);
|
|
54
|
+
data = anchors.get(found);
|
|
55
|
+
}
|
|
56
|
+
/* istanbul ignore if */
|
|
57
|
+
if (data?.res === undefined) {
|
|
58
|
+
const msg = 'This should not happen: Alias anchor was not resolved?';
|
|
59
|
+
throw new ReferenceError(msg);
|
|
60
|
+
}
|
|
61
|
+
if (maxAliasCount >= 0) {
|
|
62
|
+
data.count += 1;
|
|
63
|
+
if (data.aliasCount === 0)
|
|
64
|
+
data.aliasCount = getAliasCount(doc, found, anchors);
|
|
65
|
+
if (data.count * data.aliasCount > maxAliasCount) {
|
|
66
|
+
const msg = 'Excessive alias count indicates a resource exhaustion attack';
|
|
67
|
+
throw new ReferenceError(msg);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
48
71
|
return found;
|
|
49
72
|
}
|
|
50
73
|
toJSON(_arg, ctx) {
|
|
51
74
|
if (!ctx)
|
|
52
75
|
return { source: this.source };
|
|
53
|
-
const
|
|
54
|
-
const source = this.resolve(doc, ctx);
|
|
76
|
+
const source = this.resolve(ctx.doc, ctx);
|
|
55
77
|
if (!source) {
|
|
56
78
|
const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
|
|
57
79
|
throw new ReferenceError(msg);
|
|
58
80
|
}
|
|
59
|
-
|
|
60
|
-
if (!data) {
|
|
61
|
-
// Resolve anchors for Node.prototype.toJS()
|
|
62
|
-
toJS.toJS(source, null, ctx);
|
|
63
|
-
data = anchors.get(source);
|
|
64
|
-
}
|
|
65
|
-
/* istanbul ignore if */
|
|
66
|
-
if (data?.res === undefined) {
|
|
67
|
-
const msg = 'This should not happen: Alias anchor was not resolved?';
|
|
68
|
-
throw new ReferenceError(msg);
|
|
69
|
-
}
|
|
70
|
-
if (maxAliasCount >= 0) {
|
|
71
|
-
data.count += 1;
|
|
72
|
-
if (data.aliasCount === 0)
|
|
73
|
-
data.aliasCount = getAliasCount(doc, source, anchors);
|
|
74
|
-
if (data.count * data.aliasCount > maxAliasCount) {
|
|
75
|
-
const msg = 'Excessive alias count indicates a resource exhaustion attack';
|
|
76
|
-
throw new ReferenceError(msg);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return data.res;
|
|
81
|
+
return ctx.anchors.get(source).res;
|
|
80
82
|
}
|
|
81
83
|
toString(ctx, _onComment, _onChompKeep) {
|
|
82
84
|
const src = `*${this.source}`;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clawdbot/lobster",
|
|
3
|
-
"version": "2026.9.
|
|
3
|
+
"version": "2026.9.13",
|
|
4
4
|
"description": "Workflow runtime for AI agents - deterministic pipelines with approval gates",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-agent",
|
|
@@ -62,15 +62,13 @@
|
|
|
62
62
|
"yaml": "^2.9.0"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
|
-
"@types/node": "^
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"oxlint-tsgolint": "^7.0.2001",
|
|
70
|
-
"typescript": "npm:@typescript/typescript6@^6.0.2"
|
|
65
|
+
"@types/node": "^22.20.2",
|
|
66
|
+
"oxfmt": "^0.67.0",
|
|
67
|
+
"oxlint": "^1.82.0",
|
|
68
|
+
"typescript": "^7.0.2"
|
|
71
69
|
},
|
|
72
70
|
"engines": {
|
|
73
71
|
"node": ">=22"
|
|
74
72
|
},
|
|
75
|
-
"packageManager": "pnpm@12.
|
|
73
|
+
"packageManager": "pnpm@12.4.1"
|
|
76
74
|
}
|
|
@@ -16,9 +16,8 @@ function Separator() {
|
|
|
16
16
|
function ImportSection(build) {
|
|
17
17
|
const context = build.UseUnevaluated() ? [`import { CheckContext } from "typebox/schema"`] : [];
|
|
18
18
|
const hashing = `import { Hashing } from "typebox/system"`;
|
|
19
|
-
const format = `import { Format } from "typebox/format"`;
|
|
20
19
|
const guard = `import { Guard } from "typebox/guard"`;
|
|
21
|
-
return [...context, hashing,
|
|
20
|
+
return [...context, hashing, guard];
|
|
22
21
|
}
|
|
23
22
|
// ------------------------------------------------------------------
|
|
24
23
|
// ExternalSection
|