@bastani/atomic 0.9.0-alpha.1 → 0.9.0-alpha.2
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/CHANGELOG.md +23 -0
- package/dist/builtin/cursor/CHANGELOG.md +6 -0
- package/dist/builtin/cursor/package.json +2 -2
- package/dist/builtin/intercom/CHANGELOG.md +6 -0
- package/dist/builtin/intercom/package.json +2 -2
- package/dist/builtin/mcp/CHANGELOG.md +6 -0
- package/dist/builtin/mcp/package.json +3 -3
- package/dist/builtin/subagents/CHANGELOG.md +6 -0
- package/dist/builtin/subagents/package.json +4 -4
- package/dist/builtin/web-access/CHANGELOG.md +6 -0
- package/dist/builtin/web-access/package.json +2 -2
- package/dist/builtin/workflows/CHANGELOG.md +12 -0
- package/dist/builtin/workflows/README.md +189 -122
- package/dist/builtin/workflows/builtin/deep-research-codebase.ts +30 -27
- package/dist/builtin/workflows/builtin/goal-runner.ts +10 -17
- package/dist/builtin/workflows/builtin/goal.ts +39 -44
- package/dist/builtin/workflows/builtin/index.d.ts +1 -0
- package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +16 -17
- package/dist/builtin/workflows/builtin/open-claude-design.d.ts +1 -0
- package/dist/builtin/workflows/builtin/open-claude-design.ts +42 -50
- package/dist/builtin/workflows/builtin/ralph.ts +44 -41
- package/dist/builtin/workflows/package.json +2 -2
- package/dist/builtin/workflows/src/authoring/typebox-defaults.d.ts +41 -0
- package/dist/builtin/workflows/src/authoring/typebox-defaults.ts +217 -0
- package/dist/builtin/workflows/src/authoring/workflow.ts +184 -0
- package/dist/builtin/workflows/src/authoring.d.ts +14 -66
- package/dist/builtin/workflows/src/engine/graph-inference.ts +100 -0
- package/dist/builtin/workflows/src/engine/options.ts +40 -0
- package/dist/builtin/workflows/src/engine/primitives/chain.ts +29 -0
- package/dist/builtin/workflows/src/engine/primitives/exit.ts +2 -0
- package/dist/builtin/workflows/src/engine/primitives/parallel.ts +47 -0
- package/dist/builtin/workflows/src/engine/primitives/task.ts +108 -0
- package/dist/builtin/workflows/src/engine/primitives/ui.ts +41 -0
- package/dist/builtin/workflows/src/engine/primitives/workflow.ts +159 -0
- package/dist/builtin/workflows/src/engine/replay.ts +8 -0
- package/dist/builtin/workflows/src/engine/run.ts +356 -0
- package/dist/builtin/workflows/src/engine/runtime.ts +160 -0
- package/dist/builtin/workflows/src/extension/workflow-module-loader.ts +9 -3
- package/dist/builtin/workflows/src/extension/workflow-schema.ts +0 -18
- package/dist/builtin/workflows/src/index.ts +0 -2
- package/dist/builtin/workflows/src/runs/background/runner.ts +6 -3
- package/dist/builtin/workflows/src/runs/foreground/executor-child-boundary.ts +3 -3
- package/dist/builtin/workflows/src/runs/foreground/executor-child-helpers.ts +4 -4
- package/dist/builtin/workflows/src/runs/foreground/executor-child-workflow.ts +1 -158
- package/dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts +1 -1
- package/dist/builtin/workflows/src/runs/foreground/executor-outputs.ts +2 -2
- package/dist/builtin/workflows/src/runs/foreground/executor-prompt-nodes.ts +1 -1
- package/dist/builtin/workflows/src/runs/foreground/executor-run.ts +1 -359
- package/dist/builtin/workflows/src/runs/foreground/executor-scheduler.ts +1 -1
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-call.ts +2 -5
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-factory.ts +12 -4
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-replay.ts +4 -3
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-types.ts +9 -2
- package/dist/builtin/workflows/src/runs/foreground/executor-task-context.ts +2 -132
- package/dist/builtin/workflows/src/runs/foreground/executor-types.ts +2 -2
- package/dist/builtin/workflows/src/runs/shared/graph-inference.ts +2 -100
- package/dist/builtin/workflows/src/sdk-surface.ts +6 -9
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +9 -3
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.ts +17 -3
- package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +3 -33
- package/dist/builtin/workflows/src/shared/authoring-contract-ui.ts +9 -81
- package/dist/builtin/workflows/src/shared/types.ts +25 -8
- package/dist/builtin/workflows/src/shared/workflow-authoring-types.d.ts +49 -0
- package/dist/builtin/workflows/src/shared/workflow-authoring-types.ts +84 -0
- package/dist/builtin/workflows/src/workflows/registry.ts +7 -3
- package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-auto-compaction.js +6 -1
- package/dist/core/agent-session-auto-compaction.js.map +1 -1
- package/dist/core/agent-session-bash.d.ts.map +1 -1
- package/dist/core/agent-session-bash.js +0 -5
- package/dist/core/agent-session-bash.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +0 -2
- package/dist/core/agent-session-methods.d.ts.map +1 -1
- package/dist/core/agent-session-methods.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +0 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +0 -1
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
- package/dist/core/agent-session-tool-registry.js +0 -2
- package/dist/core/agent-session-tool-registry.js.map +1 -1
- package/dist/core/agent-session-types.d.ts +0 -2
- package/dist/core/agent-session-types.d.ts.map +1 -1
- package/dist/core/agent-session-types.js.map +1 -1
- package/dist/core/agent-session.d.ts +0 -2
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +0 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/atomic-guide-command.d.ts.map +1 -1
- package/dist/core/atomic-guide-command.js +1 -1
- package/dist/core/atomic-guide-command.js.map +1 -1
- package/dist/core/extensions/loader-core.d.ts +1 -3
- package/dist/core/extensions/loader-core.d.ts.map +1 -1
- package/dist/core/extensions/loader-core.js +13 -6
- package/dist/core/extensions/loader-core.js.map +1 -1
- package/dist/core/extensions/loader-virtual-modules.d.ts +7 -1
- package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
- package/dist/core/extensions/loader-virtual-modules.js +34 -2
- package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +2 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +2 -1
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/index.d.ts +0 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +0 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/model-registry-builtins.d.ts.map +1 -1
- package/dist/core/model-registry-builtins.js +6 -0
- package/dist/core/model-registry-builtins.js.map +1 -1
- package/dist/core/model-registry-schemas.d.ts +65 -13
- package/dist/core/model-registry-schemas.d.ts.map +1 -1
- package/dist/core/model-registry-schemas.js +10 -0
- package/dist/core/model-registry-schemas.js.map +1 -1
- package/dist/core/resource-loader-core.d.ts +1 -0
- package/dist/core/resource-loader-core.d.ts.map +1 -1
- package/dist/core/resource-loader-core.js +2 -0
- package/dist/core/resource-loader-core.js.map +1 -1
- package/dist/core/resource-loader-extensions.d.ts.map +1 -1
- package/dist/core/resource-loader-extensions.js +3 -3
- package/dist/core/resource-loader-extensions.js.map +1 -1
- package/dist/core/resource-loader-internals.d.ts +1 -0
- package/dist/core/resource-loader-internals.d.ts.map +1 -1
- package/dist/core/resource-loader-internals.js.map +1 -1
- package/dist/core/resource-loader-reload.d.ts.map +1 -1
- package/dist/core/resource-loader-reload.js +6 -2
- package/dist/core/resource-loader-reload.js.map +1 -1
- package/dist/core/sdk-exports.d.ts +1 -1
- package/dist/core/sdk-exports.d.ts.map +1 -1
- package/dist/core/sdk-exports.js.map +1 -1
- package/dist/core/sdk-types.d.ts +0 -3
- package/dist/core/sdk-types.d.ts.map +1 -1
- package/dist/core/sdk-types.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +0 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager-history.d.ts.map +1 -1
- package/dist/core/session-manager-history.js +2 -1
- package/dist/core/session-manager-history.js.map +1 -1
- package/dist/core/tools/bash.d.ts +0 -5
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +10 -11
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff-preserve.d.ts +18 -0
- package/dist/core/tools/edit-diff-preserve.d.ts.map +1 -0
- package/dist/core/tools/edit-diff-preserve.js +85 -0
- package/dist/core/tools/edit-diff-preserve.js.map +1 -0
- package/dist/core/tools/edit-diff.d.ts +3 -2
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +15 -18
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/index.d.ts +0 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +0 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +2 -2
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/model-search.d.ts +5 -0
- package/dist/modes/interactive/model-search.d.ts.map +1 -1
- package/dist/modes/interactive/model-search.js +9 -0
- package/dist/modes/interactive/model-search.js.map +1 -1
- package/dist/utils/shell.d.ts +1 -0
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +12 -5
- package/dist/utils/shell.js.map +1 -1
- package/docs/custom-provider.md +4 -3
- package/docs/models.md +3 -2
- package/docs/packages.md +2 -2
- package/docs/quickstart.md +1 -1
- package/docs/sdk.md +2 -40
- package/docs/security.md +1 -1
- package/docs/workflows.md +238 -173
- package/package.json +5 -5
- package/dist/builtin/workflows/src/workflows/define-workflow.ts +0 -277
- package/dist/core/tools/bash-policy-compile.d.ts +0 -5
- package/dist/core/tools/bash-policy-compile.d.ts.map +0 -1
- package/dist/core/tools/bash-policy-compile.js +0 -241
- package/dist/core/tools/bash-policy-compile.js.map +0 -1
- package/dist/core/tools/bash-policy-evaluate.d.ts +0 -3
- package/dist/core/tools/bash-policy-evaluate.d.ts.map +0 -1
- package/dist/core/tools/bash-policy-evaluate.js +0 -92
- package/dist/core/tools/bash-policy-evaluate.js.map +0 -1
- package/dist/core/tools/bash-policy-format.d.ts +0 -5
- package/dist/core/tools/bash-policy-format.d.ts.map +0 -1
- package/dist/core/tools/bash-policy-format.js +0 -49
- package/dist/core/tools/bash-policy-format.js.map +0 -1
- package/dist/core/tools/bash-policy-parser.d.ts +0 -4
- package/dist/core/tools/bash-policy-parser.d.ts.map +0 -1
- package/dist/core/tools/bash-policy-parser.js +0 -155
- package/dist/core/tools/bash-policy-parser.js.map +0 -1
- package/dist/core/tools/bash-policy-segment.d.ts +0 -3
- package/dist/core/tools/bash-policy-segment.d.ts.map +0 -1
- package/dist/core/tools/bash-policy-segment.js +0 -275
- package/dist/core/tools/bash-policy-segment.js.map +0 -1
- package/dist/core/tools/bash-policy-shell.d.ts +0 -11
- package/dist/core/tools/bash-policy-shell.d.ts.map +0 -1
- package/dist/core/tools/bash-policy-shell.js +0 -267
- package/dist/core/tools/bash-policy-shell.js.map +0 -1
- package/dist/core/tools/bash-policy-types.d.ts +0 -146
- package/dist/core/tools/bash-policy-types.d.ts.map +0 -1
- package/dist/core/tools/bash-policy-types.js +0 -2
- package/dist/core/tools/bash-policy-types.js.map +0 -1
- package/dist/core/tools/bash-policy.d.ts +0 -6
- package/dist/core/tools/bash-policy.d.ts.map +0 -1
- package/dist/core/tools/bash-policy.js +0 -5
- package/dist/core/tools/bash-policy.js.map +0 -1
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { compilePolicy, invalidPolicyMode } from "./bash-policy-compile.js";
|
|
2
|
-
import { parseBashCommandSegments, wholeCommandTarget } from "./bash-policy-parser.js";
|
|
3
|
-
function ruleMatches(rule, target) {
|
|
4
|
-
switch (rule.kind) {
|
|
5
|
-
case "exact":
|
|
6
|
-
return target === rule.value;
|
|
7
|
-
case "prefix":
|
|
8
|
-
return target.startsWith(rule.value);
|
|
9
|
-
case "glob":
|
|
10
|
-
return rule.value.test(target);
|
|
11
|
-
case "regex":
|
|
12
|
-
return rule.value.test(target);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
function firstMatchingRule(rules, target) {
|
|
16
|
-
for (const rule of rules) {
|
|
17
|
-
if (ruleMatches(rule, target))
|
|
18
|
-
return rule.source;
|
|
19
|
-
}
|
|
20
|
-
return undefined;
|
|
21
|
-
}
|
|
22
|
-
function isNoRuleDefaultAllowPolicy(policy) {
|
|
23
|
-
return policy.defaultDecision === "allow" && policy.allow.length === 0 && policy.deny.length === 0;
|
|
24
|
-
}
|
|
25
|
-
export function evaluateBashCommandPolicy(command, policy) {
|
|
26
|
-
if (policy === undefined) {
|
|
27
|
-
return { allowed: true, mode: "segments", targets: [] };
|
|
28
|
-
}
|
|
29
|
-
const compiled = compilePolicy(policy);
|
|
30
|
-
if (!compiled.ok) {
|
|
31
|
-
return {
|
|
32
|
-
allowed: false,
|
|
33
|
-
mode: invalidPolicyMode(policy),
|
|
34
|
-
targets: [],
|
|
35
|
-
rejection: {
|
|
36
|
-
reason: "invalid-policy",
|
|
37
|
-
message: compiled.message,
|
|
38
|
-
},
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
const activePolicy = compiled.policy;
|
|
42
|
-
if (isNoRuleDefaultAllowPolicy(activePolicy)) {
|
|
43
|
-
return { allowed: true, mode: activePolicy.match, targets: [] };
|
|
44
|
-
}
|
|
45
|
-
const targetsResult = activePolicy.match === "whole"
|
|
46
|
-
? { ok: true, segments: [wholeCommandTarget(command)] }
|
|
47
|
-
: parseBashCommandSegments(command);
|
|
48
|
-
if (!targetsResult.ok) {
|
|
49
|
-
return {
|
|
50
|
-
allowed: false,
|
|
51
|
-
mode: activePolicy.match,
|
|
52
|
-
targets: [],
|
|
53
|
-
rejection: {
|
|
54
|
-
reason: "unsupported-shell-syntax",
|
|
55
|
-
message: targetsResult.error.reason,
|
|
56
|
-
parseError: targetsResult.error,
|
|
57
|
-
},
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
for (const target of targetsResult.segments) {
|
|
61
|
-
const denyRule = firstMatchingRule(activePolicy.deny, target.target);
|
|
62
|
-
if (denyRule !== undefined) {
|
|
63
|
-
return {
|
|
64
|
-
allowed: false,
|
|
65
|
-
mode: activePolicy.match,
|
|
66
|
-
targets: targetsResult.segments,
|
|
67
|
-
rejection: {
|
|
68
|
-
reason: "matched-deny",
|
|
69
|
-
message: `command ${JSON.stringify(target.head)} matched a deny rule`,
|
|
70
|
-
target,
|
|
71
|
-
matchedRule: denyRule,
|
|
72
|
-
},
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
const allowRule = firstMatchingRule(activePolicy.allow, target.target);
|
|
76
|
-
if (allowRule !== undefined || activePolicy.defaultDecision === "allow") {
|
|
77
|
-
continue;
|
|
78
|
-
}
|
|
79
|
-
return {
|
|
80
|
-
allowed: false,
|
|
81
|
-
mode: activePolicy.match,
|
|
82
|
-
targets: targetsResult.segments,
|
|
83
|
-
rejection: {
|
|
84
|
-
reason: "default-deny",
|
|
85
|
-
message: `command ${JSON.stringify(target.head)} is not permitted by default-deny bash policy`,
|
|
86
|
-
target,
|
|
87
|
-
},
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
return { allowed: true, mode: activePolicy.match, targets: targetsResult.segments };
|
|
91
|
-
}
|
|
92
|
-
//# sourceMappingURL=bash-policy-evaluate.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bash-policy-evaluate.js","sourceRoot":"","sources":["../../../src/core/tools/bash-policy-evaluate.ts"],"names":[],"mappings":"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","sourcesContent":["import { compilePolicy, invalidPolicyMode } from \"./bash-policy-compile.ts\";\nimport { parseBashCommandSegments, wholeCommandTarget } from \"./bash-policy-parser.ts\";\nimport type {\n\tBashCommandParseResult,\n\tBashCommandPolicy,\n\tBashCommandPolicyDecision,\n\tBashCommandRule,\n\tCompiledBashCommandPolicy,\n\tCompiledRule,\n} from \"./bash-policy-types.ts\";\n\nfunction ruleMatches(rule: CompiledRule, target: string): boolean {\n\tswitch (rule.kind) {\n\t\tcase \"exact\":\n\t\t\treturn target === rule.value;\n\t\tcase \"prefix\":\n\t\t\treturn target.startsWith(rule.value);\n\t\tcase \"glob\":\n\t\t\treturn rule.value.test(target);\n\t\tcase \"regex\":\n\t\t\treturn rule.value.test(target);\n\t}\n}\n\nfunction firstMatchingRule(rules: readonly CompiledRule[], target: string): BashCommandRule | undefined {\n\tfor (const rule of rules) {\n\t\tif (ruleMatches(rule, target)) return rule.source;\n\t}\n\treturn undefined;\n}\n\nfunction isNoRuleDefaultAllowPolicy(policy: CompiledBashCommandPolicy): boolean {\n\treturn policy.defaultDecision === \"allow\" && policy.allow.length === 0 && policy.deny.length === 0;\n}\n\nexport function evaluateBashCommandPolicy(\n\tcommand: string,\n\tpolicy: BashCommandPolicy | undefined,\n): BashCommandPolicyDecision {\n\tif (policy === undefined) {\n\t\treturn { allowed: true, mode: \"segments\", targets: [] };\n\t}\n\n\tconst compiled = compilePolicy(policy);\n\tif (!compiled.ok) {\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\tmode: invalidPolicyMode(policy),\n\t\t\ttargets: [],\n\t\t\trejection: {\n\t\t\t\treason: \"invalid-policy\",\n\t\t\t\tmessage: compiled.message,\n\t\t\t},\n\t\t};\n\t}\n\n\tconst activePolicy = compiled.policy;\n\tif (isNoRuleDefaultAllowPolicy(activePolicy)) {\n\t\treturn { allowed: true, mode: activePolicy.match, targets: [] };\n\t}\n\n\tconst targetsResult: BashCommandParseResult = activePolicy.match === \"whole\"\n\t\t? { ok: true, segments: [wholeCommandTarget(command)] }\n\t\t: parseBashCommandSegments(command);\n\n\tif (!targetsResult.ok) {\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\tmode: activePolicy.match,\n\t\t\ttargets: [],\n\t\t\trejection: {\n\t\t\t\treason: \"unsupported-shell-syntax\",\n\t\t\t\tmessage: targetsResult.error.reason,\n\t\t\t\tparseError: targetsResult.error,\n\t\t\t},\n\t\t};\n\t}\n\n\tfor (const target of targetsResult.segments) {\n\t\tconst denyRule = firstMatchingRule(activePolicy.deny, target.target);\n\t\tif (denyRule !== undefined) {\n\t\t\treturn {\n\t\t\t\tallowed: false,\n\t\t\t\tmode: activePolicy.match,\n\t\t\t\ttargets: targetsResult.segments,\n\t\t\t\trejection: {\n\t\t\t\t\treason: \"matched-deny\",\n\t\t\t\t\tmessage: `command ${JSON.stringify(target.head)} matched a deny rule`,\n\t\t\t\t\ttarget,\n\t\t\t\t\tmatchedRule: denyRule,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst allowRule = firstMatchingRule(activePolicy.allow, target.target);\n\t\tif (allowRule !== undefined || activePolicy.defaultDecision === \"allow\") {\n\t\t\tcontinue;\n\t\t}\n\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\tmode: activePolicy.match,\n\t\t\ttargets: targetsResult.segments,\n\t\t\trejection: {\n\t\t\t\treason: \"default-deny\",\n\t\t\t\tmessage: `command ${JSON.stringify(target.head)} is not permitted by default-deny bash policy`,\n\t\t\t\ttarget,\n\t\t\t},\n\t\t};\n\t}\n\n\treturn { allowed: true, mode: activePolicy.match, targets: targetsResult.segments };\n}\n"]}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { BashCommandPolicyDecision } from "./bash-policy-types.ts";
|
|
2
|
-
export declare function formatBashCommandPolicyRejection(decision: Extract<BashCommandPolicyDecision, {
|
|
3
|
-
readonly allowed: false;
|
|
4
|
-
}>, policyLabel?: string): string;
|
|
5
|
-
//# sourceMappingURL=bash-policy-format.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bash-policy-format.d.ts","sourceRoot":"","sources":["../../../src/core/tools/bash-policy-format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAmB,MAAM,wBAAwB,CAAC;AAkBzF,wBAAgB,gCAAgC,CAC/C,QAAQ,EAAE,OAAO,CAAC,yBAAyB,EAAE;IAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,EACzE,WAAW,SAAwB,GACjC,MAAM,CAsCR","sourcesContent":["import type { BashCommandPolicyDecision, BashCommandRule } from \"./bash-policy-types.ts\";\n\nconst DIAGNOSTIC_TEXT_LIMIT = 220;\n\nfunction truncateDiagnostic(text: string): string {\n\tif (text.length <= DIAGNOSTIC_TEXT_LIMIT) return text;\n\treturn `${text.slice(0, DIAGNOSTIC_TEXT_LIMIT - 1)}…`;\n}\n\nfunction formatRule(rule: BashCommandRule): string {\n\tif (typeof rule === \"string\") return JSON.stringify(rule);\n\tif (\"prefix\" in rule) return `{ prefix: ${JSON.stringify(rule.prefix)} }`;\n\tif (\"glob\" in rule) return `{ glob: ${JSON.stringify(rule.glob)} }`;\n\treturn rule.flags === undefined\n\t\t? `{ regex: ${JSON.stringify(rule.regex)} }`\n\t\t: `{ regex: ${JSON.stringify(rule.regex)}, flags: ${JSON.stringify(rule.flags)} }`;\n}\n\nexport function formatBashCommandPolicyRejection(\n\tdecision: Extract<BashCommandPolicyDecision, { readonly allowed: false }>,\n\tpolicyLabel = \"bash command policy\",\n): string {\n\tconst lines = [`Bash command blocked by ${policyLabel}.`, \"\"];\n\tconst rejection = decision.rejection;\n\n\tif (rejection.reason === \"unsupported-shell-syntax\") {\n\t\tlines.push(\n\t\t\t\"The command uses shell syntax that Atomic cannot safely parse in `segments` mode.\",\n\t\t\t`Reason: ${rejection.message}.`,\n\t\t);\n\t\tif (rejection.parseError) {\n\t\t\tlines.push(`Parser source: ${rejection.parseError.source} at offset ${rejection.parseError.offset}.`);\n\t\t}\n\t\tlines.push(\n\t\t\t\"Use match: \\\"whole\\\" only if the caller intentionally accepts raw-command matching semantics.\",\n\t\t);\n\t} else if (rejection.reason === \"invalid-policy\") {\n\t\tlines.push(\"The configured bash command policy is invalid.\", `Reason: ${rejection.message}.`);\n\t} else {\n\t\tconst target = rejection.target;\n\t\tif (target) {\n\t\t\tlines.push(\n\t\t\t\t`Command head: \\`${truncateDiagnostic(target.head)}\\``,\n\t\t\t\t`Rejected ${decision.mode === \"whole\" ? \"command\" : \"segment\"}: \\`${truncateDiagnostic(target.target)}\\``,\n\t\t\t\t`Segment source: ${target.source}`,\n\t\t\t);\n\t\t}\n\t\tif (rejection.reason === \"matched-deny\") {\n\t\t\tlines.push(\"Reason: matched a deny rule; deny rules take precedence over allow rules.\");\n\t\t\tif (rejection.matchedRule !== undefined) {\n\t\t\t\tlines.push(`Matched deny rule: ${formatRule(rejection.matchedRule)}`);\n\t\t\t}\n\t\t} else {\n\t\t\tlines.push(\"Reason: no allow rule matched and the policy default is deny.\");\n\t\t}\n\t}\n\n\tlines.push(`Policy mode: ${decision.mode}.`, \"\", \"No shell process was started.\");\n\treturn lines.join(\"\\n\");\n}\n"]}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
const DIAGNOSTIC_TEXT_LIMIT = 220;
|
|
2
|
-
function truncateDiagnostic(text) {
|
|
3
|
-
if (text.length <= DIAGNOSTIC_TEXT_LIMIT)
|
|
4
|
-
return text;
|
|
5
|
-
return `${text.slice(0, DIAGNOSTIC_TEXT_LIMIT - 1)}…`;
|
|
6
|
-
}
|
|
7
|
-
function formatRule(rule) {
|
|
8
|
-
if (typeof rule === "string")
|
|
9
|
-
return JSON.stringify(rule);
|
|
10
|
-
if ("prefix" in rule)
|
|
11
|
-
return `{ prefix: ${JSON.stringify(rule.prefix)} }`;
|
|
12
|
-
if ("glob" in rule)
|
|
13
|
-
return `{ glob: ${JSON.stringify(rule.glob)} }`;
|
|
14
|
-
return rule.flags === undefined
|
|
15
|
-
? `{ regex: ${JSON.stringify(rule.regex)} }`
|
|
16
|
-
: `{ regex: ${JSON.stringify(rule.regex)}, flags: ${JSON.stringify(rule.flags)} }`;
|
|
17
|
-
}
|
|
18
|
-
export function formatBashCommandPolicyRejection(decision, policyLabel = "bash command policy") {
|
|
19
|
-
const lines = [`Bash command blocked by ${policyLabel}.`, ""];
|
|
20
|
-
const rejection = decision.rejection;
|
|
21
|
-
if (rejection.reason === "unsupported-shell-syntax") {
|
|
22
|
-
lines.push("The command uses shell syntax that Atomic cannot safely parse in `segments` mode.", `Reason: ${rejection.message}.`);
|
|
23
|
-
if (rejection.parseError) {
|
|
24
|
-
lines.push(`Parser source: ${rejection.parseError.source} at offset ${rejection.parseError.offset}.`);
|
|
25
|
-
}
|
|
26
|
-
lines.push("Use match: \"whole\" only if the caller intentionally accepts raw-command matching semantics.");
|
|
27
|
-
}
|
|
28
|
-
else if (rejection.reason === "invalid-policy") {
|
|
29
|
-
lines.push("The configured bash command policy is invalid.", `Reason: ${rejection.message}.`);
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
const target = rejection.target;
|
|
33
|
-
if (target) {
|
|
34
|
-
lines.push(`Command head: \`${truncateDiagnostic(target.head)}\``, `Rejected ${decision.mode === "whole" ? "command" : "segment"}: \`${truncateDiagnostic(target.target)}\``, `Segment source: ${target.source}`);
|
|
35
|
-
}
|
|
36
|
-
if (rejection.reason === "matched-deny") {
|
|
37
|
-
lines.push("Reason: matched a deny rule; deny rules take precedence over allow rules.");
|
|
38
|
-
if (rejection.matchedRule !== undefined) {
|
|
39
|
-
lines.push(`Matched deny rule: ${formatRule(rejection.matchedRule)}`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
lines.push("Reason: no allow rule matched and the policy default is deny.");
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
lines.push(`Policy mode: ${decision.mode}.`, "", "No shell process was started.");
|
|
47
|
-
return lines.join("\n");
|
|
48
|
-
}
|
|
49
|
-
//# sourceMappingURL=bash-policy-format.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bash-policy-format.js","sourceRoot":"","sources":["../../../src/core/tools/bash-policy-format.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BashCommandPolicyDecision, BashCommandRule } from \"./bash-policy-types.ts\";\n\nconst DIAGNOSTIC_TEXT_LIMIT = 220;\n\nfunction truncateDiagnostic(text: string): string {\n\tif (text.length <= DIAGNOSTIC_TEXT_LIMIT) return text;\n\treturn `${text.slice(0, DIAGNOSTIC_TEXT_LIMIT - 1)}…`;\n}\n\nfunction formatRule(rule: BashCommandRule): string {\n\tif (typeof rule === \"string\") return JSON.stringify(rule);\n\tif (\"prefix\" in rule) return `{ prefix: ${JSON.stringify(rule.prefix)} }`;\n\tif (\"glob\" in rule) return `{ glob: ${JSON.stringify(rule.glob)} }`;\n\treturn rule.flags === undefined\n\t\t? `{ regex: ${JSON.stringify(rule.regex)} }`\n\t\t: `{ regex: ${JSON.stringify(rule.regex)}, flags: ${JSON.stringify(rule.flags)} }`;\n}\n\nexport function formatBashCommandPolicyRejection(\n\tdecision: Extract<BashCommandPolicyDecision, { readonly allowed: false }>,\n\tpolicyLabel = \"bash command policy\",\n): string {\n\tconst lines = [`Bash command blocked by ${policyLabel}.`, \"\"];\n\tconst rejection = decision.rejection;\n\n\tif (rejection.reason === \"unsupported-shell-syntax\") {\n\t\tlines.push(\n\t\t\t\"The command uses shell syntax that Atomic cannot safely parse in `segments` mode.\",\n\t\t\t`Reason: ${rejection.message}.`,\n\t\t);\n\t\tif (rejection.parseError) {\n\t\t\tlines.push(`Parser source: ${rejection.parseError.source} at offset ${rejection.parseError.offset}.`);\n\t\t}\n\t\tlines.push(\n\t\t\t\"Use match: \\\"whole\\\" only if the caller intentionally accepts raw-command matching semantics.\",\n\t\t);\n\t} else if (rejection.reason === \"invalid-policy\") {\n\t\tlines.push(\"The configured bash command policy is invalid.\", `Reason: ${rejection.message}.`);\n\t} else {\n\t\tconst target = rejection.target;\n\t\tif (target) {\n\t\t\tlines.push(\n\t\t\t\t`Command head: \\`${truncateDiagnostic(target.head)}\\``,\n\t\t\t\t`Rejected ${decision.mode === \"whole\" ? \"command\" : \"segment\"}: \\`${truncateDiagnostic(target.target)}\\``,\n\t\t\t\t`Segment source: ${target.source}`,\n\t\t\t);\n\t\t}\n\t\tif (rejection.reason === \"matched-deny\") {\n\t\t\tlines.push(\"Reason: matched a deny rule; deny rules take precedence over allow rules.\");\n\t\t\tif (rejection.matchedRule !== undefined) {\n\t\t\t\tlines.push(`Matched deny rule: ${formatRule(rejection.matchedRule)}`);\n\t\t\t}\n\t\t} else {\n\t\t\tlines.push(\"Reason: no allow rule matched and the policy default is deny.\");\n\t\t}\n\t}\n\n\tlines.push(`Policy mode: ${decision.mode}.`, \"\", \"No shell process was started.\");\n\treturn lines.join(\"\\n\");\n}\n"]}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { BashCommandParseResult, BashCommandSegment } from "./bash-policy-types.ts";
|
|
2
|
-
export declare function parseBashCommandSegments(command: string): BashCommandParseResult;
|
|
3
|
-
export declare function wholeCommandTarget(command: string): BashCommandSegment;
|
|
4
|
-
//# sourceMappingURL=bash-policy-parser.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bash-policy-parser.d.ts","sourceRoot":"","sources":["../../../src/core/tools/bash-policy-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,sBAAsB,EACtB,kBAAkB,EAGlB,MAAM,wBAAwB,CAAC;AA+IhC,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,sBAAsB,CAEhF;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,kBAAkB,CActE","sourcesContent":["import type {\n\tBashCommandParseResult,\n\tBashCommandSegment,\n\tBashCommandSegmentSource,\n\tShellQuoteState,\n} from \"./bash-policy-types.ts\";\nimport { buildSegment } from \"./bash-policy-segment.ts\";\nimport {\n\tfindClosingBacktick,\n\tfindClosingParen,\n\tisCommandSubstitutionAt,\n\tisHereDocumentAt,\n\tisProcessSubstitutionAt,\n\tlineTerminatorLengthAt,\n\toperatorLengthAt,\n} from \"./bash-policy-shell.ts\";\n\nfunction shellError(reason: string, offset: number, source: BashCommandSegmentSource): BashCommandParseResult {\n\treturn { ok: false, error: { reason, offset, source } };\n}\n\nfunction parseSegmentsInSource(\n\tinput: string,\n\tbaseOffset: number,\n\tsource: BashCommandSegmentSource,\n): BashCommandParseResult {\n\tconst segments: BashCommandSegment[] = [];\n\tlet quote: ShellQuoteState = \"none\";\n\tlet segmentStart = 0;\n\tlet nestedForCurrentSegment: BashCommandSegment[] = [];\n\n\tconst commitSegment = (end: number): BashCommandParseResult | undefined => {\n\t\tconst built = buildSegment(input.slice(segmentStart, end), baseOffset + segmentStart, baseOffset + end, source);\n\t\tif (!built.ok) return { ok: false, error: built.error };\n\t\tif (built.segment) segments.push(built.segment);\n\t\tsegments.push(...nestedForCurrentSegment);\n\t\tnestedForCurrentSegment = [];\n\t\treturn undefined;\n\t};\n\n\tfor (let i = 0; i < input.length; i += 1) {\n\t\tconst char = input[i]!;\n\n\t\tif (quote === \"single\") {\n\t\t\tif (char === \"'\") quote = \"none\";\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"\\\\\") {\n\t\t\tif (i + 1 >= input.length) {\n\t\t\t\treturn shellError(\"trailing escape\", baseOffset + i, source);\n\t\t\t}\n\t\t\ti += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (quote === \"double\") {\n\t\t\tif (char === \"\\\"\") {\n\t\t\t\tquote = \"none\";\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (isCommandSubstitutionAt(input, i)) {\n\t\t\t\tconst close = findClosingParen(input, i + 1, \"command substitution `$(`\");\n\t\t\t\tif (!close.ok) return shellError(close.reason, baseOffset + close.offset, source);\n\t\t\t\tconst nested = parseSegmentsInSource(input.slice(i + 2, close.closeIndex), baseOffset + i + 2, \"command-substitution\");\n\t\t\t\tif (!nested.ok) return nested;\n\t\t\t\tnestedForCurrentSegment.push(...nested.segments);\n\t\t\t\ti = close.closeIndex;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (char === \"`\") {\n\t\t\t\tconst close = findClosingBacktick(input, i);\n\t\t\t\tif (!close.ok) return shellError(close.reason, baseOffset + close.offset, source);\n\t\t\t\tconst nested = parseSegmentsInSource(input.slice(i + 1, close.closeIndex), baseOffset + i + 1, \"backtick\");\n\t\t\t\tif (!nested.ok) return nested;\n\t\t\t\tnestedForCurrentSegment.push(...nested.segments);\n\t\t\t\ti = close.closeIndex;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"'\") {\n\t\t\tquote = \"single\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"\\\"\") {\n\t\t\tquote = \"double\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (isHereDocumentAt(input, i)) {\n\t\t\treturn shellError(\"here-documents are not supported by bash policy segments mode\", baseOffset + i, source);\n\t\t}\n\t\tif (isCommandSubstitutionAt(input, i)) {\n\t\t\tconst close = findClosingParen(input, i + 1, \"command substitution `$(`\");\n\t\t\tif (!close.ok) return shellError(close.reason, baseOffset + close.offset, source);\n\t\t\tconst nested = parseSegmentsInSource(input.slice(i + 2, close.closeIndex), baseOffset + i + 2, \"command-substitution\");\n\t\t\tif (!nested.ok) return nested;\n\t\t\tnestedForCurrentSegment.push(...nested.segments);\n\t\t\ti = close.closeIndex;\n\t\t\tcontinue;\n\t\t}\n\t\tif (isProcessSubstitutionAt(input, i)) {\n\t\t\tconst close = findClosingParen(input, i + 1, \"process substitution\");\n\t\t\tif (!close.ok) return shellError(close.reason, baseOffset + close.offset, source);\n\t\t\tconst nested = parseSegmentsInSource(input.slice(i + 2, close.closeIndex), baseOffset + i + 2, \"process-substitution\");\n\t\t\tif (!nested.ok) return nested;\n\t\t\tnestedForCurrentSegment.push(...nested.segments);\n\t\t\ti = close.closeIndex;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"`\") {\n\t\t\tconst close = findClosingBacktick(input, i);\n\t\t\tif (!close.ok) return shellError(close.reason, baseOffset + close.offset, source);\n\t\t\tconst nested = parseSegmentsInSource(input.slice(i + 1, close.closeIndex), baseOffset + i + 1, \"backtick\");\n\t\t\tif (!nested.ok) return nested;\n\t\t\tnestedForCurrentSegment.push(...nested.segments);\n\t\t\ti = close.closeIndex;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"(\" || char === \")\") {\n\t\t\treturn shellError(\"unsupported shell grouping parentheses\", baseOffset + i, source);\n\t\t}\n\n\t\tconst lineTerminatorLength = lineTerminatorLengthAt(input, i);\n\t\tif (lineTerminatorLength > 0) {\n\t\t\tconst committed = commitSegment(i);\n\t\t\tif (committed) return committed;\n\t\t\ti += lineTerminatorLength - 1;\n\t\t\tsegmentStart = i + 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst operatorLength = operatorLengthAt(input, i);\n\t\tif (operatorLength > 0) {\n\t\t\tconst committed = commitSegment(i);\n\t\t\tif (committed) return committed;\n\t\t\ti += operatorLength - 1;\n\t\t\tsegmentStart = i + 1;\n\t\t}\n\t}\n\n\tif (quote === \"single\") return shellError(\"unclosed single quote\", baseOffset + input.length, source);\n\tif (quote === \"double\") return shellError(\"unclosed double quote\", baseOffset + input.length, source);\n\tconst committed = commitSegment(input.length);\n\tif (committed) return committed;\n\treturn { ok: true, segments };\n}\n\nexport function parseBashCommandSegments(command: string): BashCommandParseResult {\n\treturn parseSegmentsInSource(command, 0, \"top-level\");\n}\n\nexport function wholeCommandTarget(command: string): BashCommandSegment {\n\tconst target = command;\n\tconst trimmed = command.trimStart();\n\tconst leading = command.length - trimmed.length;\n\tconst firstSpace = trimmed.search(/\\s/);\n\tconst head = firstSpace === -1 ? trimmed : trimmed.slice(0, firstSpace);\n\treturn {\n\t\traw: command,\n\t\ttarget,\n\t\thead,\n\t\tstart: leading,\n\t\tend: command.length,\n\t\tsource: \"top-level\",\n\t};\n}\n"]}
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import { buildSegment } from "./bash-policy-segment.js";
|
|
2
|
-
import { findClosingBacktick, findClosingParen, isCommandSubstitutionAt, isHereDocumentAt, isProcessSubstitutionAt, lineTerminatorLengthAt, operatorLengthAt, } from "./bash-policy-shell.js";
|
|
3
|
-
function shellError(reason, offset, source) {
|
|
4
|
-
return { ok: false, error: { reason, offset, source } };
|
|
5
|
-
}
|
|
6
|
-
function parseSegmentsInSource(input, baseOffset, source) {
|
|
7
|
-
const segments = [];
|
|
8
|
-
let quote = "none";
|
|
9
|
-
let segmentStart = 0;
|
|
10
|
-
let nestedForCurrentSegment = [];
|
|
11
|
-
const commitSegment = (end) => {
|
|
12
|
-
const built = buildSegment(input.slice(segmentStart, end), baseOffset + segmentStart, baseOffset + end, source);
|
|
13
|
-
if (!built.ok)
|
|
14
|
-
return { ok: false, error: built.error };
|
|
15
|
-
if (built.segment)
|
|
16
|
-
segments.push(built.segment);
|
|
17
|
-
segments.push(...nestedForCurrentSegment);
|
|
18
|
-
nestedForCurrentSegment = [];
|
|
19
|
-
return undefined;
|
|
20
|
-
};
|
|
21
|
-
for (let i = 0; i < input.length; i += 1) {
|
|
22
|
-
const char = input[i];
|
|
23
|
-
if (quote === "single") {
|
|
24
|
-
if (char === "'")
|
|
25
|
-
quote = "none";
|
|
26
|
-
continue;
|
|
27
|
-
}
|
|
28
|
-
if (char === "\\") {
|
|
29
|
-
if (i + 1 >= input.length) {
|
|
30
|
-
return shellError("trailing escape", baseOffset + i, source);
|
|
31
|
-
}
|
|
32
|
-
i += 1;
|
|
33
|
-
continue;
|
|
34
|
-
}
|
|
35
|
-
if (quote === "double") {
|
|
36
|
-
if (char === "\"") {
|
|
37
|
-
quote = "none";
|
|
38
|
-
continue;
|
|
39
|
-
}
|
|
40
|
-
if (isCommandSubstitutionAt(input, i)) {
|
|
41
|
-
const close = findClosingParen(input, i + 1, "command substitution `$(`");
|
|
42
|
-
if (!close.ok)
|
|
43
|
-
return shellError(close.reason, baseOffset + close.offset, source);
|
|
44
|
-
const nested = parseSegmentsInSource(input.slice(i + 2, close.closeIndex), baseOffset + i + 2, "command-substitution");
|
|
45
|
-
if (!nested.ok)
|
|
46
|
-
return nested;
|
|
47
|
-
nestedForCurrentSegment.push(...nested.segments);
|
|
48
|
-
i = close.closeIndex;
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
if (char === "`") {
|
|
52
|
-
const close = findClosingBacktick(input, i);
|
|
53
|
-
if (!close.ok)
|
|
54
|
-
return shellError(close.reason, baseOffset + close.offset, source);
|
|
55
|
-
const nested = parseSegmentsInSource(input.slice(i + 1, close.closeIndex), baseOffset + i + 1, "backtick");
|
|
56
|
-
if (!nested.ok)
|
|
57
|
-
return nested;
|
|
58
|
-
nestedForCurrentSegment.push(...nested.segments);
|
|
59
|
-
i = close.closeIndex;
|
|
60
|
-
}
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
if (char === "'") {
|
|
64
|
-
quote = "single";
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
if (char === "\"") {
|
|
68
|
-
quote = "double";
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
if (isHereDocumentAt(input, i)) {
|
|
72
|
-
return shellError("here-documents are not supported by bash policy segments mode", baseOffset + i, source);
|
|
73
|
-
}
|
|
74
|
-
if (isCommandSubstitutionAt(input, i)) {
|
|
75
|
-
const close = findClosingParen(input, i + 1, "command substitution `$(`");
|
|
76
|
-
if (!close.ok)
|
|
77
|
-
return shellError(close.reason, baseOffset + close.offset, source);
|
|
78
|
-
const nested = parseSegmentsInSource(input.slice(i + 2, close.closeIndex), baseOffset + i + 2, "command-substitution");
|
|
79
|
-
if (!nested.ok)
|
|
80
|
-
return nested;
|
|
81
|
-
nestedForCurrentSegment.push(...nested.segments);
|
|
82
|
-
i = close.closeIndex;
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
if (isProcessSubstitutionAt(input, i)) {
|
|
86
|
-
const close = findClosingParen(input, i + 1, "process substitution");
|
|
87
|
-
if (!close.ok)
|
|
88
|
-
return shellError(close.reason, baseOffset + close.offset, source);
|
|
89
|
-
const nested = parseSegmentsInSource(input.slice(i + 2, close.closeIndex), baseOffset + i + 2, "process-substitution");
|
|
90
|
-
if (!nested.ok)
|
|
91
|
-
return nested;
|
|
92
|
-
nestedForCurrentSegment.push(...nested.segments);
|
|
93
|
-
i = close.closeIndex;
|
|
94
|
-
continue;
|
|
95
|
-
}
|
|
96
|
-
if (char === "`") {
|
|
97
|
-
const close = findClosingBacktick(input, i);
|
|
98
|
-
if (!close.ok)
|
|
99
|
-
return shellError(close.reason, baseOffset + close.offset, source);
|
|
100
|
-
const nested = parseSegmentsInSource(input.slice(i + 1, close.closeIndex), baseOffset + i + 1, "backtick");
|
|
101
|
-
if (!nested.ok)
|
|
102
|
-
return nested;
|
|
103
|
-
nestedForCurrentSegment.push(...nested.segments);
|
|
104
|
-
i = close.closeIndex;
|
|
105
|
-
continue;
|
|
106
|
-
}
|
|
107
|
-
if (char === "(" || char === ")") {
|
|
108
|
-
return shellError("unsupported shell grouping parentheses", baseOffset + i, source);
|
|
109
|
-
}
|
|
110
|
-
const lineTerminatorLength = lineTerminatorLengthAt(input, i);
|
|
111
|
-
if (lineTerminatorLength > 0) {
|
|
112
|
-
const committed = commitSegment(i);
|
|
113
|
-
if (committed)
|
|
114
|
-
return committed;
|
|
115
|
-
i += lineTerminatorLength - 1;
|
|
116
|
-
segmentStart = i + 1;
|
|
117
|
-
continue;
|
|
118
|
-
}
|
|
119
|
-
const operatorLength = operatorLengthAt(input, i);
|
|
120
|
-
if (operatorLength > 0) {
|
|
121
|
-
const committed = commitSegment(i);
|
|
122
|
-
if (committed)
|
|
123
|
-
return committed;
|
|
124
|
-
i += operatorLength - 1;
|
|
125
|
-
segmentStart = i + 1;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
if (quote === "single")
|
|
129
|
-
return shellError("unclosed single quote", baseOffset + input.length, source);
|
|
130
|
-
if (quote === "double")
|
|
131
|
-
return shellError("unclosed double quote", baseOffset + input.length, source);
|
|
132
|
-
const committed = commitSegment(input.length);
|
|
133
|
-
if (committed)
|
|
134
|
-
return committed;
|
|
135
|
-
return { ok: true, segments };
|
|
136
|
-
}
|
|
137
|
-
export function parseBashCommandSegments(command) {
|
|
138
|
-
return parseSegmentsInSource(command, 0, "top-level");
|
|
139
|
-
}
|
|
140
|
-
export function wholeCommandTarget(command) {
|
|
141
|
-
const target = command;
|
|
142
|
-
const trimmed = command.trimStart();
|
|
143
|
-
const leading = command.length - trimmed.length;
|
|
144
|
-
const firstSpace = trimmed.search(/\s/);
|
|
145
|
-
const head = firstSpace === -1 ? trimmed : trimmed.slice(0, firstSpace);
|
|
146
|
-
return {
|
|
147
|
-
raw: command,
|
|
148
|
-
target,
|
|
149
|
-
head,
|
|
150
|
-
start: leading,
|
|
151
|
-
end: command.length,
|
|
152
|
-
source: "top-level",
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
//# sourceMappingURL=bash-policy-parser.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bash-policy-parser.js","sourceRoot":"","sources":["../../../src/core/tools/bash-policy-parser.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tBashCommandParseResult,\n\tBashCommandSegment,\n\tBashCommandSegmentSource,\n\tShellQuoteState,\n} from \"./bash-policy-types.ts\";\nimport { buildSegment } from \"./bash-policy-segment.ts\";\nimport {\n\tfindClosingBacktick,\n\tfindClosingParen,\n\tisCommandSubstitutionAt,\n\tisHereDocumentAt,\n\tisProcessSubstitutionAt,\n\tlineTerminatorLengthAt,\n\toperatorLengthAt,\n} from \"./bash-policy-shell.ts\";\n\nfunction shellError(reason: string, offset: number, source: BashCommandSegmentSource): BashCommandParseResult {\n\treturn { ok: false, error: { reason, offset, source } };\n}\n\nfunction parseSegmentsInSource(\n\tinput: string,\n\tbaseOffset: number,\n\tsource: BashCommandSegmentSource,\n): BashCommandParseResult {\n\tconst segments: BashCommandSegment[] = [];\n\tlet quote: ShellQuoteState = \"none\";\n\tlet segmentStart = 0;\n\tlet nestedForCurrentSegment: BashCommandSegment[] = [];\n\n\tconst commitSegment = (end: number): BashCommandParseResult | undefined => {\n\t\tconst built = buildSegment(input.slice(segmentStart, end), baseOffset + segmentStart, baseOffset + end, source);\n\t\tif (!built.ok) return { ok: false, error: built.error };\n\t\tif (built.segment) segments.push(built.segment);\n\t\tsegments.push(...nestedForCurrentSegment);\n\t\tnestedForCurrentSegment = [];\n\t\treturn undefined;\n\t};\n\n\tfor (let i = 0; i < input.length; i += 1) {\n\t\tconst char = input[i]!;\n\n\t\tif (quote === \"single\") {\n\t\t\tif (char === \"'\") quote = \"none\";\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"\\\\\") {\n\t\t\tif (i + 1 >= input.length) {\n\t\t\t\treturn shellError(\"trailing escape\", baseOffset + i, source);\n\t\t\t}\n\t\t\ti += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (quote === \"double\") {\n\t\t\tif (char === \"\\\"\") {\n\t\t\t\tquote = \"none\";\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (isCommandSubstitutionAt(input, i)) {\n\t\t\t\tconst close = findClosingParen(input, i + 1, \"command substitution `$(`\");\n\t\t\t\tif (!close.ok) return shellError(close.reason, baseOffset + close.offset, source);\n\t\t\t\tconst nested = parseSegmentsInSource(input.slice(i + 2, close.closeIndex), baseOffset + i + 2, \"command-substitution\");\n\t\t\t\tif (!nested.ok) return nested;\n\t\t\t\tnestedForCurrentSegment.push(...nested.segments);\n\t\t\t\ti = close.closeIndex;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (char === \"`\") {\n\t\t\t\tconst close = findClosingBacktick(input, i);\n\t\t\t\tif (!close.ok) return shellError(close.reason, baseOffset + close.offset, source);\n\t\t\t\tconst nested = parseSegmentsInSource(input.slice(i + 1, close.closeIndex), baseOffset + i + 1, \"backtick\");\n\t\t\t\tif (!nested.ok) return nested;\n\t\t\t\tnestedForCurrentSegment.push(...nested.segments);\n\t\t\t\ti = close.closeIndex;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"'\") {\n\t\t\tquote = \"single\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"\\\"\") {\n\t\t\tquote = \"double\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (isHereDocumentAt(input, i)) {\n\t\t\treturn shellError(\"here-documents are not supported by bash policy segments mode\", baseOffset + i, source);\n\t\t}\n\t\tif (isCommandSubstitutionAt(input, i)) {\n\t\t\tconst close = findClosingParen(input, i + 1, \"command substitution `$(`\");\n\t\t\tif (!close.ok) return shellError(close.reason, baseOffset + close.offset, source);\n\t\t\tconst nested = parseSegmentsInSource(input.slice(i + 2, close.closeIndex), baseOffset + i + 2, \"command-substitution\");\n\t\t\tif (!nested.ok) return nested;\n\t\t\tnestedForCurrentSegment.push(...nested.segments);\n\t\t\ti = close.closeIndex;\n\t\t\tcontinue;\n\t\t}\n\t\tif (isProcessSubstitutionAt(input, i)) {\n\t\t\tconst close = findClosingParen(input, i + 1, \"process substitution\");\n\t\t\tif (!close.ok) return shellError(close.reason, baseOffset + close.offset, source);\n\t\t\tconst nested = parseSegmentsInSource(input.slice(i + 2, close.closeIndex), baseOffset + i + 2, \"process-substitution\");\n\t\t\tif (!nested.ok) return nested;\n\t\t\tnestedForCurrentSegment.push(...nested.segments);\n\t\t\ti = close.closeIndex;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"`\") {\n\t\t\tconst close = findClosingBacktick(input, i);\n\t\t\tif (!close.ok) return shellError(close.reason, baseOffset + close.offset, source);\n\t\t\tconst nested = parseSegmentsInSource(input.slice(i + 1, close.closeIndex), baseOffset + i + 1, \"backtick\");\n\t\t\tif (!nested.ok) return nested;\n\t\t\tnestedForCurrentSegment.push(...nested.segments);\n\t\t\ti = close.closeIndex;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"(\" || char === \")\") {\n\t\t\treturn shellError(\"unsupported shell grouping parentheses\", baseOffset + i, source);\n\t\t}\n\n\t\tconst lineTerminatorLength = lineTerminatorLengthAt(input, i);\n\t\tif (lineTerminatorLength > 0) {\n\t\t\tconst committed = commitSegment(i);\n\t\t\tif (committed) return committed;\n\t\t\ti += lineTerminatorLength - 1;\n\t\t\tsegmentStart = i + 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst operatorLength = operatorLengthAt(input, i);\n\t\tif (operatorLength > 0) {\n\t\t\tconst committed = commitSegment(i);\n\t\t\tif (committed) return committed;\n\t\t\ti += operatorLength - 1;\n\t\t\tsegmentStart = i + 1;\n\t\t}\n\t}\n\n\tif (quote === \"single\") return shellError(\"unclosed single quote\", baseOffset + input.length, source);\n\tif (quote === \"double\") return shellError(\"unclosed double quote\", baseOffset + input.length, source);\n\tconst committed = commitSegment(input.length);\n\tif (committed) return committed;\n\treturn { ok: true, segments };\n}\n\nexport function parseBashCommandSegments(command: string): BashCommandParseResult {\n\treturn parseSegmentsInSource(command, 0, \"top-level\");\n}\n\nexport function wholeCommandTarget(command: string): BashCommandSegment {\n\tconst target = command;\n\tconst trimmed = command.trimStart();\n\tconst leading = command.length - trimmed.length;\n\tconst firstSpace = trimmed.search(/\\s/);\n\tconst head = firstSpace === -1 ? trimmed : trimmed.slice(0, firstSpace);\n\treturn {\n\t\traw: command,\n\t\ttarget,\n\t\thead,\n\t\tstart: leading,\n\t\tend: command.length,\n\t\tsource: \"top-level\",\n\t};\n}\n"]}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import type { SegmentBuildResult } from "./bash-policy-types.ts";
|
|
2
|
-
export declare function buildSegment(rawSegment: string, absoluteStart: number, absoluteEnd: number, source: "top-level" | "command-substitution" | "process-substitution" | "backtick"): SegmentBuildResult;
|
|
3
|
-
//# sourceMappingURL=bash-policy-segment.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bash-policy-segment.d.ts","sourceRoot":"","sources":["../../../src/core/tools/bash-policy-segment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAsC,MAAM,wBAAwB,CAAC;AAyMrG,wBAAgB,YAAY,CAC3B,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,WAAW,GAAG,sBAAsB,GAAG,sBAAsB,GAAG,UAAU,GAChF,kBAAkB,CA0FpB","sourcesContent":["import type { SegmentBuildResult, ShellQuoteState, ShellWordMetadata } from \"./bash-policy-types.ts\";\nimport {\n\tfindClosingBacktick,\n\tfindClosingParen,\n\tisCommandSubstitutionAt,\n\tisProcessSubstitutionAt,\n\tisWhitespace,\n\treadShellWord,\n} from \"./bash-policy-shell.ts\";\n\nconst UNSUPPORTED_CONTROL_HEADS = new Set([\n\t\"!\",\n\t\"[[\",\n\t\"]]\",\n\t\"case\",\n\t\"coproc\",\n\t\"do\",\n\t\"done\",\n\t\"elif\",\n\t\"else\",\n\t\"esac\",\n\t\"fi\",\n\t\"for\",\n\t\"function\",\n\t\"if\",\n\t\"in\",\n\t\"select\",\n\t\"then\",\n\t\"time\",\n\t\"until\",\n\t\"while\",\n\t\"{\",\n\t\"}\",\n]);\n\ntype LiteralCommandHeadValidation =\n\t| { readonly ok: true }\n\t| { readonly ok: false; readonly reason: string };\n\ninterface AttachedRedirectionToken {\n\treadonly token: string;\n\treadonly offset: number;\n}\n\nfunction isAsciiDigit(char: string | undefined): boolean {\n\treturn char !== undefined && char >= \"0\" && char <= \"9\";\n}\n\nfunction leadingRedirectionTokenAt(input: string, index: number): string | undefined {\n\tlet operatorStart = index;\n\twhile (isAsciiDigit(input[operatorStart])) operatorStart += 1;\n\n\tconst hasDescriptorPrefix = operatorStart > index;\n\tconst char = input[operatorStart];\n\tconst next = input[operatorStart + 1];\n\tconst afterNext = input[operatorStart + 2];\n\n\tif (char === undefined) return undefined;\n\tif (hasDescriptorPrefix && char !== \"<\" && char !== \">\") return undefined;\n\n\tif (!hasDescriptorPrefix && (char === \"<\" || char === \">\") && next === \"(\") {\n\t\treturn undefined;\n\t}\n\n\tlet operator: string | undefined;\n\tif (char === \"&\" && next === \">\") {\n\t\toperator = afterNext === \">\" ? \"&>>\" : \"&>\";\n\t} else if (char === \"<\") {\n\t\tif (next === \"<\") operator = \"<<\";\n\t\telse if (next === \"&\") operator = \"<&\";\n\t\telse if (next === \">\") operator = \"<>\";\n\t\telse operator = \"<\";\n\t} else if (char === \">\") {\n\t\tif (next === \">\") operator = \">>\";\n\t\telse if (next === \"|\") operator = \">|\";\n\t\telse if (next === \"&\") operator = \">&\";\n\t\telse operator = \">\";\n\t}\n\n\treturn operator === undefined ? undefined : `${input.slice(index, operatorStart)}${operator}`;\n}\n\nfunction isEnvAssignmentWord(word: string): boolean {\n\treturn /^[A-Za-z_][A-Za-z0-9_]*(?:\\+)?=/.test(word);\n}\n\nfunction attachedRedirectionOperatorAt(input: string, index: number): string | undefined {\n\tconst char = input[index];\n\tconst next = input[index + 1];\n\tconst afterNext = input[index + 2];\n\n\tif ((char === \"<\" || char === \">\") && next === \"(\") {\n\t\treturn undefined;\n\t}\n\tif (char === \"&\" && next === \">\") {\n\t\treturn afterNext === \">\" ? \"&>>\" : \"&>\";\n\t}\n\tif (char === \"<\") {\n\t\tif (next === \"<\") return \"<<\";\n\t\tif (next === \"&\") return \"<&\";\n\t\tif (next === \">\") return \"<>\";\n\t\treturn \"<\";\n\t}\n\tif (char === \">\") {\n\t\tif (next === \">\") return \">>\";\n\t\tif (next === \"|\") return \">|\";\n\t\tif (next === \"&\") return \">&\";\n\t\treturn \">\";\n\t}\n\treturn undefined;\n}\n\nfunction attachedCommandHeadRedirection(\n\tinput: string,\n\tstart: number,\n\tend: number,\n): AttachedRedirectionToken | undefined {\n\tlet quote: ShellQuoteState = \"none\";\n\n\tfor (let i = start; i < end; i += 1) {\n\t\tconst char = input[i]!;\n\t\tif (quote === \"single\") {\n\t\t\tif (char === \"'\") quote = \"none\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"\\\\\") {\n\t\t\ti += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (quote === \"double\") {\n\t\t\tif (char === \"\\\"\") {\n\t\t\t\tquote = \"none\";\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (isCommandSubstitutionAt(input, i) || isProcessSubstitutionAt(input, i)) {\n\t\t\t\tconst close = findClosingParen(input, i + 1, isCommandSubstitutionAt(input, i) ? \"command substitution `$(`\" : \"process substitution\");\n\t\t\t\tif (close.ok) i = close.closeIndex;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (char === \"`\") {\n\t\t\t\tconst close = findClosingBacktick(input, i);\n\t\t\t\tif (close.ok) i = close.closeIndex;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"'\") {\n\t\t\tquote = \"single\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"\\\"\") {\n\t\t\tquote = \"double\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (isCommandSubstitutionAt(input, i) || isProcessSubstitutionAt(input, i)) {\n\t\t\tconst close = findClosingParen(input, i + 1, isCommandSubstitutionAt(input, i) ? \"command substitution `$(`\" : \"process substitution\");\n\t\t\tif (close.ok) i = close.closeIndex;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"`\") {\n\t\t\tconst close = findClosingBacktick(input, i);\n\t\t\tif (close.ok) i = close.closeIndex;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst operator = attachedRedirectionOperatorAt(input, i);\n\t\tif (operator !== undefined && i > start) {\n\t\t\treturn { token: operator, offset: i };\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\nfunction validateLiteralCommandHead(head: string, metadata: ShellWordMetadata): LiteralCommandHeadValidation {\n\tif (head.length === 0) {\n\t\treturn { ok: false, reason: \"empty command heads are not supported by bash policy segments mode\" };\n\t}\n\tif (metadata.sawSingleQuote || metadata.sawDoubleQuote) {\n\t\treturn { ok: false, reason: \"quoted or quote-constructed command heads are not supported by bash policy segments mode\" };\n\t}\n\tif (metadata.sawEscape) {\n\t\treturn { ok: false, reason: \"escape-constructed command heads are not supported by bash policy segments mode\" };\n\t}\n\tif (metadata.sawCommandSubstitution || metadata.sawProcessSubstitution || metadata.sawBacktick) {\n\t\treturn { ok: false, reason: \"command, process, and backtick substitutions are not supported in command heads by bash policy segments mode\" };\n\t}\n\tif (metadata.sawParameterExpansion) {\n\t\treturn { ok: false, reason: \"parameter-expanded command heads are not supported by bash policy segments mode\" };\n\t}\n\tif (metadata.sawTildePrefix) {\n\t\treturn { ok: false, reason: \"tilde-expanded command heads are not supported by bash policy segments mode\" };\n\t}\n\tif (metadata.sawGlobPattern) {\n\t\treturn { ok: false, reason: \"glob-expanded command heads are not supported by bash policy segments mode\" };\n\t}\n\tif (metadata.sawBraceExpansion) {\n\t\treturn { ok: false, reason: \"brace-expanded command heads are not supported by bash policy segments mode\" };\n\t}\n\treturn { ok: true };\n}\n\nexport function buildSegment(\n\trawSegment: string,\n\tabsoluteStart: number,\n\tabsoluteEnd: number,\n\tsource: \"top-level\" | \"command-substitution\" | \"process-substitution\" | \"backtick\",\n): SegmentBuildResult {\n\tlet cursor = 0;\n\twhile (cursor < rawSegment.length && isWhitespace(rawSegment[cursor]!)) cursor += 1;\n\tif (cursor >= rawSegment.length) return { ok: true };\n\n\twhile (cursor < rawSegment.length) {\n\t\twhile (cursor < rawSegment.length && isWhitespace(rawSegment[cursor]!)) cursor += 1;\n\t\tif (cursor >= rawSegment.length) return { ok: true };\n\n\t\tconst leadingRedirection = leadingRedirectionTokenAt(rawSegment, cursor);\n\t\tif (leadingRedirection !== undefined) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: {\n\t\t\t\t\treason: `leading shell redirection ${JSON.stringify(leadingRedirection)} is not supported by bash policy segments mode`,\n\t\t\t\t\toffset: absoluteStart + cursor,\n\t\t\t\t\tsource,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst word = readShellWord(rawSegment, cursor);\n\t\tif (!word.ok) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: { reason: word.reason, offset: absoluteStart + word.offset, source },\n\t\t\t};\n\t\t}\n\n\t\tconst attachedRedirection = attachedCommandHeadRedirection(rawSegment, cursor, word.end);\n\t\tif (attachedRedirection !== undefined) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: {\n\t\t\t\t\treason: `attached shell redirection ${JSON.stringify(attachedRedirection.token)} in the command head is not supported by bash policy segments mode`,\n\t\t\t\t\toffset: absoluteStart + attachedRedirection.offset,\n\t\t\t\t\tsource,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tif (isEnvAssignmentWord(word.word)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: {\n\t\t\t\t\treason: \"environment assignment words are not supported by bash policy segments mode\",\n\t\t\t\t\toffset: absoluteStart + cursor,\n\t\t\t\t\tsource,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst target = rawSegment.slice(cursor).trim();\n\t\tconst head = word.word;\n\t\tif (UNSUPPORTED_CONTROL_HEADS.has(head)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: {\n\t\t\t\t\treason: `unsupported shell reserved or compound syntax starting with ${JSON.stringify(head)}`,\n\t\t\t\t\toffset: absoluteStart + cursor,\n\t\t\t\t\tsource,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tconst literalHead = validateLiteralCommandHead(head, word.metadata);\n\t\tif (!literalHead.ok) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: {\n\t\t\t\t\treason: literalHead.reason,\n\t\t\t\t\toffset: absoluteStart + cursor,\n\t\t\t\t\tsource,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tok: true,\n\t\t\tsegment: {\n\t\t\t\traw: rawSegment.trim(),\n\t\t\t\ttarget,\n\t\t\t\thead,\n\t\t\t\tstart: absoluteStart + cursor,\n\t\t\t\tend: absoluteEnd,\n\t\t\t\tsource,\n\t\t\t},\n\t\t};\n\t}\n\n\treturn { ok: true };\n}\n"]}
|