@plateforme-ai/lobster 2026.6.12
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/LICENSE +21 -0
- package/README.md +353 -0
- package/VISION.md +249 -0
- package/bin/clawd.invoke.js +18 -0
- package/bin/lobster.js +24 -0
- package/bin/openclaw.invoke.js +21 -0
- package/dist/src/cli.js +793 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/commands/commands_list.js +49 -0
- package/dist/src/commands/commands_list.js.map +1 -0
- package/dist/src/commands/registry.js +66 -0
- package/dist/src/commands/registry.js.map +1 -0
- package/dist/src/commands/stdlib/approve.js +77 -0
- package/dist/src/commands/stdlib/approve.js.map +1 -0
- package/dist/src/commands/stdlib/ask.js +171 -0
- package/dist/src/commands/stdlib/ask.js.map +1 -0
- package/dist/src/commands/stdlib/dedupe.js +55 -0
- package/dist/src/commands/stdlib/dedupe.js.map +1 -0
- package/dist/src/commands/stdlib/diff_last.js +35 -0
- package/dist/src/commands/stdlib/diff_last.js.map +1 -0
- package/dist/src/commands/stdlib/email_triage.js +279 -0
- package/dist/src/commands/stdlib/email_triage.js.map +1 -0
- package/dist/src/commands/stdlib/exec.js +130 -0
- package/dist/src/commands/stdlib/exec.js.map +1 -0
- package/dist/src/commands/stdlib/gog_gmail_search.js +94 -0
- package/dist/src/commands/stdlib/gog_gmail_search.js.map +1 -0
- package/dist/src/commands/stdlib/gog_gmail_send.js +104 -0
- package/dist/src/commands/stdlib/gog_gmail_send.js.map +1 -0
- package/dist/src/commands/stdlib/group_by.js +59 -0
- package/dist/src/commands/stdlib/group_by.js.map +1 -0
- package/dist/src/commands/stdlib/head.js +34 -0
- package/dist/src/commands/stdlib/head.js.map +1 -0
- package/dist/src/commands/stdlib/json.js +20 -0
- package/dist/src/commands/stdlib/json.js.map +1 -0
- package/dist/src/commands/stdlib/llm_invoke.js +758 -0
- package/dist/src/commands/stdlib/llm_invoke.js.map +1 -0
- package/dist/src/commands/stdlib/llm_task_invoke.js +2 -0
- package/dist/src/commands/stdlib/llm_task_invoke.js.map +1 -0
- package/dist/src/commands/stdlib/map.js +104 -0
- package/dist/src/commands/stdlib/map.js.map +1 -0
- package/dist/src/commands/stdlib/openclaw_invoke.js +136 -0
- package/dist/src/commands/stdlib/openclaw_invoke.js.map +1 -0
- package/dist/src/commands/stdlib/pick.js +45 -0
- package/dist/src/commands/stdlib/pick.js.map +1 -0
- package/dist/src/commands/stdlib/sort.js +86 -0
- package/dist/src/commands/stdlib/sort.js.map +1 -0
- package/dist/src/commands/stdlib/state.js +76 -0
- package/dist/src/commands/stdlib/state.js.map +1 -0
- package/dist/src/commands/stdlib/table.js +57 -0
- package/dist/src/commands/stdlib/table.js.map +1 -0
- package/dist/src/commands/stdlib/template.js +126 -0
- package/dist/src/commands/stdlib/template.js.map +1 -0
- package/dist/src/commands/stdlib/where.js +81 -0
- package/dist/src/commands/stdlib/where.js.map +1 -0
- package/dist/src/commands/types.js +2 -0
- package/dist/src/commands/types.js.map +1 -0
- package/dist/src/commands/workflows/workflows_list.js +24 -0
- package/dist/src/commands/workflows/workflows_list.js.map +1 -0
- package/dist/src/commands/workflows/workflows_run.js +74 -0
- package/dist/src/commands/workflows/workflows_run.js.map +1 -0
- package/dist/src/core/cost_tracker.js +119 -0
- package/dist/src/core/cost_tracker.js.map +1 -0
- package/dist/src/core/filters.js +102 -0
- package/dist/src/core/filters.js.map +1 -0
- package/dist/src/core/index.js +7 -0
- package/dist/src/core/index.js.map +1 -0
- package/dist/src/core/retry.js +89 -0
- package/dist/src/core/retry.js.map +1 -0
- package/dist/src/core/tool_runtime.js +289 -0
- package/dist/src/core/tool_runtime.js.map +1 -0
- package/dist/src/input_request.js +430 -0
- package/dist/src/input_request.js.map +1 -0
- package/dist/src/parser.js +145 -0
- package/dist/src/parser.js.map +1 -0
- package/dist/src/pipeline_resume_state.js +186 -0
- package/dist/src/pipeline_resume_state.js.map +1 -0
- package/dist/src/read_line.js +50 -0
- package/dist/src/read_line.js.map +1 -0
- package/dist/src/recipes/github/index.js +16 -0
- package/dist/src/recipes/github/index.js.map +1 -0
- package/dist/src/recipes/github/pr-monitor.js +248 -0
- package/dist/src/recipes/github/pr-monitor.js.map +1 -0
- package/dist/src/recipes/github/stages/pr-view.js +107 -0
- package/dist/src/recipes/github/stages/pr-view.js.map +1 -0
- package/dist/src/recipes/index.js +7 -0
- package/dist/src/recipes/index.js.map +1 -0
- package/dist/src/recipes/registry.js +30 -0
- package/dist/src/recipes/registry.js.map +1 -0
- package/dist/src/renderers/json.js +13 -0
- package/dist/src/renderers/json.js.map +1 -0
- package/dist/src/resume.js +179 -0
- package/dist/src/resume.js.map +1 -0
- package/dist/src/runtime.js +230 -0
- package/dist/src/runtime.js.map +1 -0
- package/dist/src/sdk/Lobster.js +402 -0
- package/dist/src/sdk/Lobster.js.map +1 -0
- package/dist/src/sdk/index.js +25 -0
- package/dist/src/sdk/index.js.map +1 -0
- package/dist/src/sdk/primitives/approve.js +47 -0
- package/dist/src/sdk/primitives/approve.js.map +1 -0
- package/dist/src/sdk/primitives/diff.js +156 -0
- package/dist/src/sdk/primitives/diff.js.map +1 -0
- package/dist/src/sdk/primitives/exec.js +167 -0
- package/dist/src/sdk/primitives/exec.js.map +1 -0
- package/dist/src/sdk/primitives/state.js +203 -0
- package/dist/src/sdk/primitives/state.js.map +1 -0
- package/dist/src/sdk/runtime.js +131 -0
- package/dist/src/sdk/runtime.js.map +1 -0
- package/dist/src/sdk/token.js +9 -0
- package/dist/src/sdk/token.js.map +1 -0
- package/dist/src/shell.js +39 -0
- package/dist/src/shell.js.map +1 -0
- package/dist/src/state/store.js +337 -0
- package/dist/src/state/store.js.map +1 -0
- package/dist/src/token.js +15 -0
- package/dist/src/token.js.map +1 -0
- package/dist/src/validation.js +38 -0
- package/dist/src/validation.js.map +1 -0
- package/dist/src/workflows/file.js +2405 -0
- package/dist/src/workflows/file.js.map +1 -0
- package/dist/src/workflows/github_pr_monitor.js +167 -0
- package/dist/src/workflows/github_pr_monitor.js.map +1 -0
- package/dist/src/workflows/graph.js +234 -0
- package/dist/src/workflows/graph.js.map +1 -0
- package/dist/src/workflows/registry.js +57 -0
- package/dist/src/workflows/registry.js.map +1 -0
- package/dist/test/approval_id.test.js +171 -0
- package/dist/test/approval_id.test.js.map +1 -0
- package/dist/test/approve_preview.test.js +38 -0
- package/dist/test/approve_preview.test.js.map +1 -0
- package/dist/test/clawd_invoke.test.js +124 -0
- package/dist/test/clawd_invoke.test.js.map +1 -0
- package/dist/test/clawd_invoke_legacy.test.js +63 -0
- package/dist/test/clawd_invoke_legacy.test.js.map +1 -0
- package/dist/test/cli_run_file_args_json.test.js +27 -0
- package/dist/test/cli_run_file_args_json.test.js.map +1 -0
- package/dist/test/commands_list.test.js +44 -0
- package/dist/test/commands_list.test.js.map +1 -0
- package/dist/test/condition_comparison.test.js +127 -0
- package/dist/test/condition_comparison.test.js.map +1 -0
- package/dist/test/core_tool_runtime.test.js +160 -0
- package/dist/test/core_tool_runtime.test.js.map +1 -0
- package/dist/test/cost_tracker.test.js +231 -0
- package/dist/test/cost_tracker.test.js.map +1 -0
- package/dist/test/dedupe.test.js +48 -0
- package/dist/test/dedupe.test.js.map +1 -0
- package/dist/test/diff_last.test.js +70 -0
- package/dist/test/diff_last.test.js.map +1 -0
- package/dist/test/doctor.test.js +19 -0
- package/dist/test/doctor.test.js.map +1 -0
- package/dist/test/dry_run.test.js +502 -0
- package/dist/test/dry_run.test.js.map +1 -0
- package/dist/test/email_triage.test.js +296 -0
- package/dist/test/email_triage.test.js.map +1 -0
- package/dist/test/exec_stdin.test.js +43 -0
- package/dist/test/exec_stdin.test.js.map +1 -0
- package/dist/test/for_each.test.js +228 -0
- package/dist/test/for_each.test.js.map +1 -0
- package/dist/test/github_pr_notify_format.test.js +19 -0
- package/dist/test/github_pr_notify_format.test.js.map +1 -0
- package/dist/test/github_pr_summary.test.js +41 -0
- package/dist/test/github_pr_summary.test.js.map +1 -0
- package/dist/test/group_by.test.js +43 -0
- package/dist/test/group_by.test.js.map +1 -0
- package/dist/test/llm_invoke.test.js +166 -0
- package/dist/test/llm_invoke.test.js.map +1 -0
- package/dist/test/llm_task_invoke.test.js +416 -0
- package/dist/test/llm_task_invoke.test.js.map +1 -0
- package/dist/test/map.test.js +41 -0
- package/dist/test/map.test.js.map +1 -0
- package/dist/test/multi_approval_resume.test.js +48 -0
- package/dist/test/multi_approval_resume.test.js.map +1 -0
- package/dist/test/on_error.test.js +151 -0
- package/dist/test/on_error.test.js.map +1 -0
- package/dist/test/openclaw_invoke_alias.test.js +13 -0
- package/dist/test/openclaw_invoke_alias.test.js.map +1 -0
- package/dist/test/parallel.test.js +184 -0
- package/dist/test/parallel.test.js.map +1 -0
- package/dist/test/parser.test.js +39 -0
- package/dist/test/parser.test.js.map +1 -0
- package/dist/test/read_line.test.js +25 -0
- package/dist/test/read_line.test.js.map +1 -0
- package/dist/test/request_input.test.js +946 -0
- package/dist/test/request_input.test.js.map +1 -0
- package/dist/test/resume.test.js +82 -0
- package/dist/test/resume.test.js.map +1 -0
- package/dist/test/sdk_lobster.test.js +177 -0
- package/dist/test/sdk_lobster.test.js.map +1 -0
- package/dist/test/shell.test.js +31 -0
- package/dist/test/shell.test.js.map +1 -0
- package/dist/test/sort.test.js +51 -0
- package/dist/test/sort.test.js.map +1 -0
- package/dist/test/state.test.js +336 -0
- package/dist/test/state.test.js.map +1 -0
- package/dist/test/step_retry.test.js +254 -0
- package/dist/test/step_retry.test.js.map +1 -0
- package/dist/test/step_timeout.test.js +154 -0
- package/dist/test/step_timeout.test.js.map +1 -0
- package/dist/test/template.test.js +46 -0
- package/dist/test/template.test.js.map +1 -0
- package/dist/test/template_filters.test.js +107 -0
- package/dist/test/template_filters.test.js.map +1 -0
- package/dist/test/tool_envelope_version.test.js +15 -0
- package/dist/test/tool_envelope_version.test.js.map +1 -0
- package/dist/test/tool_mode.test.js +83 -0
- package/dist/test/tool_mode.test.js.map +1 -0
- package/dist/test/validation.test.js +28 -0
- package/dist/test/validation.test.js.map +1 -0
- package/dist/test/workflow_args_env.test.js +41 -0
- package/dist/test/workflow_args_env.test.js.map +1 -0
- package/dist/test/workflow_composition.test.js +238 -0
- package/dist/test/workflow_composition.test.js.map +1 -0
- package/dist/test/workflow_file.test.js +1399 -0
- package/dist/test/workflow_file.test.js.map +1 -0
- package/dist/test/workflow_graph.test.js +97 -0
- package/dist/test/workflow_graph.test.js.map +1 -0
- package/dist/test/workflows.test.js +32 -0
- package/dist/test/workflows.test.js.map +1 -0
- package/package.json +75 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exec primitive - Execute shell commands and return JSON output
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* import { Lobster, exec } from 'lobster-sdk';
|
|
6
|
+
*
|
|
7
|
+
* new Lobster()
|
|
8
|
+
* .pipe(exec('gh pr view 123 --repo owner/repo --json title,url'))
|
|
9
|
+
* .pipe(items => items.filter(e => e.unread))
|
|
10
|
+
*/
|
|
11
|
+
import { spawn } from "node:child_process";
|
|
12
|
+
import { resolveInlineShellCommand } from "../../shell.js";
|
|
13
|
+
/**
|
|
14
|
+
* Run a process and capture output
|
|
15
|
+
* @param {string} command
|
|
16
|
+
* @param {string[]} argv
|
|
17
|
+
* @param {Object} options
|
|
18
|
+
* @returns {Promise<{stdout: string, stderr: string}>}
|
|
19
|
+
*/
|
|
20
|
+
function runProcess(command, argv, { env, cwd }) {
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
const child = spawn(command, argv, {
|
|
23
|
+
env,
|
|
24
|
+
cwd,
|
|
25
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
26
|
+
shell: false,
|
|
27
|
+
});
|
|
28
|
+
let stdout = "";
|
|
29
|
+
let stderr = "";
|
|
30
|
+
child.stdout.setEncoding("utf8");
|
|
31
|
+
child.stderr.setEncoding("utf8");
|
|
32
|
+
child.stdout.on("data", (d) => {
|
|
33
|
+
stdout += d;
|
|
34
|
+
});
|
|
35
|
+
child.stderr.on("data", (d) => {
|
|
36
|
+
stderr += d;
|
|
37
|
+
});
|
|
38
|
+
child.on("error", (err) => {
|
|
39
|
+
reject(new Error(`Failed to execute ${command}: ${err.message}`));
|
|
40
|
+
});
|
|
41
|
+
child.on("close", (code) => {
|
|
42
|
+
if (code === 0) {
|
|
43
|
+
resolve({ stdout, stderr });
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
reject(new Error(`${command} exited with code ${code}: ${stderr.trim() || stdout.trim()}`));
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Parse a shell command string into command and arguments
|
|
53
|
+
* Simple parsing - for complex cases, use options.shell
|
|
54
|
+
* @param {string} cmdString
|
|
55
|
+
* @returns {{command: string, args: string[]}}
|
|
56
|
+
*/
|
|
57
|
+
function parseCommand(cmdString) {
|
|
58
|
+
const tokens = [];
|
|
59
|
+
let current = "";
|
|
60
|
+
let quote = null;
|
|
61
|
+
for (let i = 0; i < cmdString.length; i++) {
|
|
62
|
+
const ch = cmdString[i];
|
|
63
|
+
if (quote) {
|
|
64
|
+
if (ch === "\\" && cmdString[i + 1]) {
|
|
65
|
+
current += cmdString[i + 1];
|
|
66
|
+
i++;
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (ch === quote) {
|
|
70
|
+
quote = null;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
current += ch;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (ch === '"' || ch === "'") {
|
|
77
|
+
quote = ch;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (ch === " " || ch === "\t") {
|
|
81
|
+
if (current.length > 0) {
|
|
82
|
+
tokens.push(current);
|
|
83
|
+
current = "";
|
|
84
|
+
}
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
current += ch;
|
|
88
|
+
}
|
|
89
|
+
if (current.length > 0) {
|
|
90
|
+
tokens.push(current);
|
|
91
|
+
}
|
|
92
|
+
const [command, ...args] = tokens;
|
|
93
|
+
return { command, args };
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Create an exec stage
|
|
97
|
+
*
|
|
98
|
+
* @param {string} cmdString - Command to execute
|
|
99
|
+
* @param {Object} [options]
|
|
100
|
+
* @param {boolean} [options.json=true] - Parse output as JSON
|
|
101
|
+
* @param {boolean} [options.shell=false] - Use shell execution
|
|
102
|
+
* @param {string} [options.cwd] - Working directory
|
|
103
|
+
* @returns {Object} Stage object with run method
|
|
104
|
+
*/
|
|
105
|
+
export function exec(cmdString, options = {}) {
|
|
106
|
+
const parseJson = options.json !== false;
|
|
107
|
+
const useShell = options.shell === true;
|
|
108
|
+
const cwd = options.cwd ?? process.cwd();
|
|
109
|
+
return {
|
|
110
|
+
type: "exec",
|
|
111
|
+
command: cmdString,
|
|
112
|
+
async run({ input, ctx }) {
|
|
113
|
+
// Drain input (exec doesn't use input stream)
|
|
114
|
+
for await (const _item of input) {
|
|
115
|
+
// no-op
|
|
116
|
+
}
|
|
117
|
+
const env = ctx.env ?? process.env;
|
|
118
|
+
let stdout;
|
|
119
|
+
if (useShell) {
|
|
120
|
+
// Shell execution
|
|
121
|
+
const shell = resolveInlineShellCommand({ command: cmdString, env });
|
|
122
|
+
const result = await runProcess(shell.command, shell.argv, { env, cwd });
|
|
123
|
+
stdout = result.stdout;
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
// Direct execution
|
|
127
|
+
const { command, args } = parseCommand(cmdString);
|
|
128
|
+
const result = await runProcess(command, args, { env, cwd });
|
|
129
|
+
stdout = result.stdout;
|
|
130
|
+
}
|
|
131
|
+
// Parse output
|
|
132
|
+
let output;
|
|
133
|
+
if (parseJson) {
|
|
134
|
+
try {
|
|
135
|
+
output = JSON.parse(stdout.trim() || "[]");
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
throw new Error(`exec output is not valid JSON: ${stdout.slice(0, 100)}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
output = stdout;
|
|
143
|
+
}
|
|
144
|
+
// Normalize to array
|
|
145
|
+
const items = Array.isArray(output) ? output : [output];
|
|
146
|
+
return {
|
|
147
|
+
output: (async function* () {
|
|
148
|
+
for (const item of items) {
|
|
149
|
+
yield item;
|
|
150
|
+
}
|
|
151
|
+
})(),
|
|
152
|
+
};
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Create an exec stage that runs in shell mode
|
|
158
|
+
* Convenience wrapper for exec(cmd, { shell: true })
|
|
159
|
+
*
|
|
160
|
+
* @param {string} cmdString
|
|
161
|
+
* @param {Object} [options]
|
|
162
|
+
* @returns {Object}
|
|
163
|
+
*/
|
|
164
|
+
export function shell(cmdString, options = {}) {
|
|
165
|
+
return exec(cmdString, { ...options, shell: true });
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=exec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../../../src/sdk/primitives/exec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State primitives - Persistent state management
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* import { Lobster, stateGet, stateSet } from 'lobster-sdk';
|
|
6
|
+
*
|
|
7
|
+
* // Read state
|
|
8
|
+
* new Lobster()
|
|
9
|
+
* .pipe(stateGet('my-key'))
|
|
10
|
+
* .pipe(value => console.log(value));
|
|
11
|
+
*
|
|
12
|
+
* // Write state
|
|
13
|
+
* new Lobster()
|
|
14
|
+
* .pipe(() => ({ count: 42 }))
|
|
15
|
+
* .pipe(stateSet('my-key'));
|
|
16
|
+
*/
|
|
17
|
+
import { randomBytes } from "node:crypto";
|
|
18
|
+
import { promises as fsp } from "node:fs";
|
|
19
|
+
import os from "node:os";
|
|
20
|
+
import path from "node:path";
|
|
21
|
+
/**
|
|
22
|
+
* Write a file atomically (stage to a sibling temp file, fsync, then rename).
|
|
23
|
+
* `rename(2)` is atomic on a single filesystem, so a concurrent reader or a
|
|
24
|
+
* crash never observes a truncated/partial file. Plain `fsp.writeFile`
|
|
25
|
+
* truncates the target up front, leaving a corruption window on SIGKILL/OOM/
|
|
26
|
+
* power loss. New state files are private by default; existing file modes are
|
|
27
|
+
* preserved across replacement. Kept local to keep the SDK self-contained.
|
|
28
|
+
* @param {string} filePath
|
|
29
|
+
* @param {string} data
|
|
30
|
+
*/
|
|
31
|
+
async function writeFileAtomic(filePath, data) {
|
|
32
|
+
const dir = path.dirname(filePath);
|
|
33
|
+
const tmpPath = path.join(dir, `.${path.basename(filePath)}.${randomBytes(6).toString("hex")}.tmp`);
|
|
34
|
+
let mode = 0o600;
|
|
35
|
+
let handle;
|
|
36
|
+
let cleanup = true;
|
|
37
|
+
try {
|
|
38
|
+
try {
|
|
39
|
+
mode = (await fsp.stat(filePath)).mode & 0o777;
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
if (err?.code !== "ENOENT")
|
|
43
|
+
throw err;
|
|
44
|
+
}
|
|
45
|
+
handle = await fsp.open(tmpPath, "wx", mode);
|
|
46
|
+
await handle.writeFile(data, "utf8");
|
|
47
|
+
await handle.sync();
|
|
48
|
+
await handle.close();
|
|
49
|
+
handle = undefined;
|
|
50
|
+
await fsp.chmod(tmpPath, mode);
|
|
51
|
+
await fsp.rename(tmpPath, filePath);
|
|
52
|
+
cleanup = false;
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
if (handle)
|
|
56
|
+
await handle.close().catch(() => { });
|
|
57
|
+
if (cleanup)
|
|
58
|
+
await fsp.rm(tmpPath, { force: true }).catch(() => { });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get the state directory
|
|
63
|
+
* @param {Object} ctx
|
|
64
|
+
* @returns {string}
|
|
65
|
+
*/
|
|
66
|
+
function getStateDir(ctx) {
|
|
67
|
+
return (ctx?.stateDir ||
|
|
68
|
+
(ctx?.env?.LOBSTER_STATE_DIR && String(ctx.env.LOBSTER_STATE_DIR).trim()) ||
|
|
69
|
+
path.join(os.homedir(), ".lobster", "state"));
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Convert a key to a safe file path
|
|
73
|
+
* @param {string} stateDir
|
|
74
|
+
* @param {string} key
|
|
75
|
+
* @returns {string}
|
|
76
|
+
*/
|
|
77
|
+
function keyToPath(stateDir, key) {
|
|
78
|
+
const safe = String(key)
|
|
79
|
+
.toLowerCase()
|
|
80
|
+
.replace(/[^a-z0-9._-]+/g, "_")
|
|
81
|
+
.replace(/_+/g, "_")
|
|
82
|
+
.replace(/^_+|_+$/g, "");
|
|
83
|
+
if (!safe)
|
|
84
|
+
throw new Error("state key is empty/invalid");
|
|
85
|
+
return path.join(stateDir, `${safe}.json`);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Create a state.get stage
|
|
89
|
+
*
|
|
90
|
+
* @param {string} key - State key to read
|
|
91
|
+
* @returns {Object} Stage object with run method
|
|
92
|
+
*/
|
|
93
|
+
export function stateGet(key) {
|
|
94
|
+
if (!key)
|
|
95
|
+
throw new Error("stateGet requires a key");
|
|
96
|
+
return {
|
|
97
|
+
type: "state.get",
|
|
98
|
+
key,
|
|
99
|
+
async run({ input, ctx }) {
|
|
100
|
+
// Drain input
|
|
101
|
+
for await (const _item of input) {
|
|
102
|
+
// no-op
|
|
103
|
+
}
|
|
104
|
+
const stateDir = getStateDir(ctx);
|
|
105
|
+
const filePath = keyToPath(stateDir, key);
|
|
106
|
+
let value = null;
|
|
107
|
+
try {
|
|
108
|
+
const text = await fsp.readFile(filePath, "utf8");
|
|
109
|
+
value = JSON.parse(text);
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
if (err?.code !== "ENOENT") {
|
|
113
|
+
throw err;
|
|
114
|
+
}
|
|
115
|
+
// File doesn't exist, return null
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
output: (async function* () {
|
|
119
|
+
yield value;
|
|
120
|
+
})(),
|
|
121
|
+
};
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Create a state.set stage
|
|
127
|
+
*
|
|
128
|
+
* @param {string} key - State key to write
|
|
129
|
+
* @returns {Object} Stage object with run method
|
|
130
|
+
*/
|
|
131
|
+
export function stateSet(key) {
|
|
132
|
+
if (!key)
|
|
133
|
+
throw new Error("stateSet requires a key");
|
|
134
|
+
return {
|
|
135
|
+
type: "state.set",
|
|
136
|
+
key,
|
|
137
|
+
async run({ input, ctx }) {
|
|
138
|
+
// Collect all input items
|
|
139
|
+
const items = [];
|
|
140
|
+
for await (const item of input) {
|
|
141
|
+
items.push(item);
|
|
142
|
+
}
|
|
143
|
+
const value = items.length === 1 ? items[0] : items;
|
|
144
|
+
const stateDir = getStateDir(ctx);
|
|
145
|
+
const filePath = keyToPath(stateDir, key);
|
|
146
|
+
await fsp.mkdir(stateDir, { recursive: true });
|
|
147
|
+
await writeFileAtomic(filePath, JSON.stringify(value, null, 2) + "\n");
|
|
148
|
+
// Pass through the value
|
|
149
|
+
return {
|
|
150
|
+
output: (async function* () {
|
|
151
|
+
yield value;
|
|
152
|
+
})(),
|
|
153
|
+
};
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* State namespace - provides get/set methods
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* import { state } from 'lobster-sdk';
|
|
162
|
+
*
|
|
163
|
+
* new Lobster()
|
|
164
|
+
* .pipe(state.get('my-key'))
|
|
165
|
+
* .pipe(state.set('my-key'));
|
|
166
|
+
*/
|
|
167
|
+
export const state = {
|
|
168
|
+
get: stateGet,
|
|
169
|
+
set: stateSet,
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* Read state directly (not as a pipeline stage)
|
|
173
|
+
* @param {string} key
|
|
174
|
+
* @param {Object} [ctx]
|
|
175
|
+
* @returns {Promise<any>}
|
|
176
|
+
*/
|
|
177
|
+
export async function readState(key, ctx = {}) {
|
|
178
|
+
const stateDir = getStateDir(ctx);
|
|
179
|
+
const filePath = keyToPath(stateDir, key);
|
|
180
|
+
try {
|
|
181
|
+
const text = await fsp.readFile(filePath, "utf8");
|
|
182
|
+
return JSON.parse(text);
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
if (err?.code === "ENOENT")
|
|
186
|
+
return null;
|
|
187
|
+
throw err;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Write state directly (not as a pipeline stage)
|
|
192
|
+
* @param {string} key
|
|
193
|
+
* @param {any} value
|
|
194
|
+
* @param {Object} [ctx]
|
|
195
|
+
* @returns {Promise<void>}
|
|
196
|
+
*/
|
|
197
|
+
export async function writeState(key, value, ctx = {}) {
|
|
198
|
+
const stateDir = getStateDir(ctx);
|
|
199
|
+
const filePath = keyToPath(stateDir, key);
|
|
200
|
+
await fsp.mkdir(stateDir, { recursive: true });
|
|
201
|
+
await writeFileAtomic(filePath, JSON.stringify(value, null, 2) + "\n");
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../../src/sdk/primitives/state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK Runtime - Executes Lobster pipelines
|
|
3
|
+
*
|
|
4
|
+
* This adapts SDK stages to the core runtime so command-level suspension rules
|
|
5
|
+
* stay identical across CLI, tool mode, and SDK entry points.
|
|
6
|
+
*/
|
|
7
|
+
import { runPipeline as runCorePipeline } from "../runtime.js";
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {Object} StageResult
|
|
10
|
+
* @property {AsyncIterable|any[]} [output] - Output items
|
|
11
|
+
* @property {boolean} [halt] - Whether to halt the pipeline
|
|
12
|
+
* @property {boolean} [rendered] - Whether output was rendered
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {Object} PipelineResult
|
|
16
|
+
* @property {any[]} items - Collected output items
|
|
17
|
+
* @property {boolean} halted - Whether pipeline halted
|
|
18
|
+
* @property {Object|null} haltedAt - Stage where halt occurred
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Collect async iterable to array
|
|
22
|
+
* @param {AsyncIterable} iterable
|
|
23
|
+
* @returns {Promise<any[]>}
|
|
24
|
+
*/
|
|
25
|
+
async function collectItems(iterable) {
|
|
26
|
+
const items = [];
|
|
27
|
+
for await (const item of iterable) {
|
|
28
|
+
items.push(item);
|
|
29
|
+
}
|
|
30
|
+
return items;
|
|
31
|
+
}
|
|
32
|
+
function normalizeSdkOutput(output) {
|
|
33
|
+
if (output === null || output === undefined)
|
|
34
|
+
return [];
|
|
35
|
+
if (Array.isArray(output))
|
|
36
|
+
return output;
|
|
37
|
+
if (typeof output?.[Symbol.asyncIterator] === "function" ||
|
|
38
|
+
typeof output?.[Symbol.iterator] === "function") {
|
|
39
|
+
return output;
|
|
40
|
+
}
|
|
41
|
+
return [output];
|
|
42
|
+
}
|
|
43
|
+
function createNullWritable() {
|
|
44
|
+
return {
|
|
45
|
+
write() {
|
|
46
|
+
return true;
|
|
47
|
+
},
|
|
48
|
+
end() {
|
|
49
|
+
return undefined;
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Run a pipeline of stages
|
|
55
|
+
*
|
|
56
|
+
* @param {Object} options
|
|
57
|
+
* @param {Array<Function|Object>} options.stages - Pipeline stages
|
|
58
|
+
* @param {Object} options.ctx - Execution context
|
|
59
|
+
* @param {any[]} [options.input] - Initial input items
|
|
60
|
+
* @returns {Promise<PipelineResult>}
|
|
61
|
+
*/
|
|
62
|
+
export async function runPipelineInternal({ stages, ctx, input = [], requestInputResume = undefined, }) {
|
|
63
|
+
const runtimeCtx = ctx ?? {};
|
|
64
|
+
const pipeline = stages.map((_stage, index) => ({
|
|
65
|
+
name: `sdk.stage.${index}`,
|
|
66
|
+
args: {},
|
|
67
|
+
raw: `sdk.stage.${index}`,
|
|
68
|
+
}));
|
|
69
|
+
const commands = new Map(stages.map((stage, index) => [
|
|
70
|
+
`sdk.stage.${index}`,
|
|
71
|
+
{
|
|
72
|
+
async run({ input, ctx }) {
|
|
73
|
+
const stageCtx = { ...runtimeCtx, ...ctx };
|
|
74
|
+
if (typeof stage === "function") {
|
|
75
|
+
const isGenerator = stage.constructor?.name === "AsyncGeneratorFunction" ||
|
|
76
|
+
stage.constructor?.name === "GeneratorFunction";
|
|
77
|
+
if (isGenerator) {
|
|
78
|
+
return { output: normalizeSdkOutput(stage(input, stageCtx)) };
|
|
79
|
+
}
|
|
80
|
+
const items = await collectItems(input);
|
|
81
|
+
return { output: normalizeSdkOutput(await stage(items, stageCtx)) };
|
|
82
|
+
}
|
|
83
|
+
if (typeof stage?.run === "function") {
|
|
84
|
+
const result = await stage.run({ input, ctx: stageCtx });
|
|
85
|
+
return result && "output" in result
|
|
86
|
+
? { ...result, output: normalizeSdkOutput(result.output) }
|
|
87
|
+
: result;
|
|
88
|
+
}
|
|
89
|
+
throw new Error(`Invalid stage at index ${index}: must be a function or have run() method`);
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
]));
|
|
93
|
+
const stdout = runtimeCtx.stdout ?? createNullWritable();
|
|
94
|
+
const stderr = runtimeCtx.stderr ?? createNullWritable();
|
|
95
|
+
return runCorePipeline({
|
|
96
|
+
pipeline,
|
|
97
|
+
registry: {
|
|
98
|
+
get(name) {
|
|
99
|
+
return commands.get(name);
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
stdin: runtimeCtx.stdin ?? { isTTY: false },
|
|
103
|
+
stdout,
|
|
104
|
+
stderr,
|
|
105
|
+
env: runtimeCtx.env ?? process.env,
|
|
106
|
+
mode: runtimeCtx.mode ?? "sdk",
|
|
107
|
+
cwd: runtimeCtx.cwd,
|
|
108
|
+
llmAdapters: runtimeCtx.llmAdapters,
|
|
109
|
+
signal: runtimeCtx.signal,
|
|
110
|
+
input: normalizeSdkOutput(input),
|
|
111
|
+
requestInputResume,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Re-export for compatibility with CLI runtime
|
|
116
|
+
*/
|
|
117
|
+
export async function runPipeline({ pipeline, registry, stdin, stdout, stderr, env, mode = "human", input, requestInputResume = undefined, requestInputEnabled = true, }) {
|
|
118
|
+
return runCorePipeline({
|
|
119
|
+
pipeline,
|
|
120
|
+
registry,
|
|
121
|
+
stdin,
|
|
122
|
+
stdout,
|
|
123
|
+
stderr,
|
|
124
|
+
env,
|
|
125
|
+
mode,
|
|
126
|
+
input,
|
|
127
|
+
requestInputResume,
|
|
128
|
+
requestInputEnabled,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/sdk/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token encoding/decoding for SDK resume functionality
|
|
3
|
+
*
|
|
4
|
+
* Re-exports from the main token module for consistency
|
|
5
|
+
*/
|
|
6
|
+
import { encodeToken as mainEncode, decodeToken as mainDecode } from "../token.js";
|
|
7
|
+
export const encodeToken = mainEncode;
|
|
8
|
+
export const decodeToken = mainDecode;
|
|
9
|
+
//# sourceMappingURL=token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../../src/sdk/token.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,IAAI,UAAU,EAAE,WAAW,IAAI,UAAU,EAAE,MAAM,aAAa,CAAC;AAEnF,MAAM,CAAC,MAAM,WAAW,GAAG,UAAU,CAAC;AACtC,MAAM,CAAC,MAAM,WAAW,GAAG,UAAU,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export function resolveInlineShellCommand({ command, env, platform = process.platform, }) {
|
|
2
|
+
const shellOverride = String(env?.LOBSTER_SHELL ?? "").trim();
|
|
3
|
+
const isWindows = platform === "win32";
|
|
4
|
+
if (shellOverride) {
|
|
5
|
+
return {
|
|
6
|
+
command: shellOverride,
|
|
7
|
+
argv: buildShellArgs({ shellCommand: shellOverride, command, isWindows }),
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
if (isWindows) {
|
|
11
|
+
const comspec = String(env?.ComSpec ?? env?.COMSPEC ?? "cmd.exe").trim() || "cmd.exe";
|
|
12
|
+
return {
|
|
13
|
+
command: comspec,
|
|
14
|
+
argv: ["/d", "/s", "/c", command],
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
// Keep default behavior deterministic and POSIX-compatible across environments.
|
|
18
|
+
const shell = "/bin/sh";
|
|
19
|
+
return {
|
|
20
|
+
command: shell,
|
|
21
|
+
argv: ["-lc", command],
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function buildShellArgs({ shellCommand, command, isWindows, }) {
|
|
25
|
+
const lowered = shellCommand.toLowerCase();
|
|
26
|
+
const looksLikeCmd = lowered.endsWith("cmd") || lowered.endsWith("cmd.exe");
|
|
27
|
+
const looksLikePowerShell = lowered.endsWith("powershell") ||
|
|
28
|
+
lowered.endsWith("powershell.exe") ||
|
|
29
|
+
lowered.endsWith("pwsh") ||
|
|
30
|
+
lowered.endsWith("pwsh.exe");
|
|
31
|
+
if (looksLikePowerShell) {
|
|
32
|
+
return ["-NoProfile", "-Command", command];
|
|
33
|
+
}
|
|
34
|
+
if (looksLikeCmd || isWindows) {
|
|
35
|
+
return ["/d", "/s", "/c", command];
|
|
36
|
+
}
|
|
37
|
+
return ["-lc", command];
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=shell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/shell.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,yBAAyB,CAAC,EACxC,OAAO,EACP,GAAG,EACH,QAAQ,GAAG,OAAO,CAAC,QAAQ,GAK5B;IACC,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,EAAE,aAAa,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9D,MAAM,SAAS,GAAG,QAAQ,KAAK,OAAO,CAAC;IAEvC,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO;YACL,OAAO,EAAE,aAAa;YACtB,IAAI,EAAE,cAAc,CAAC,EAAE,YAAY,EAAE,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;SAC1E,CAAC;IACJ,CAAC;IAED,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,EAAE,OAAO,IAAI,GAAG,EAAE,OAAO,IAAI,SAAS,CAAC,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC;QACtF,OAAO;YACL,OAAO,EAAE,OAAO;YAChB,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC;SAClC,CAAC;IACJ,CAAC;IAED,gFAAgF;IAChF,MAAM,KAAK,GAAG,SAAS,CAAC;IACxB,OAAO;QACL,OAAO,EAAE,KAAK;QACd,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC;KACvB,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,EACtB,YAAY,EACZ,OAAO,EACP,SAAS,GAKV;IACC,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC5E,MAAM,mBAAmB,GACvB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;QAC9B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;QACxB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAE/B,IAAI,mBAAmB,EAAE,CAAC;QACxB,OAAO,CAAC,YAAY,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,YAAY,IAAI,SAAS,EAAE,CAAC;QAC9B,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AAC1B,CAAC"}
|