dsh-ros2-common 0.1.0
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 +11 -0
- package/lib/index.js +8 -0
- package/lib/parse.js +110 -0
- package/lib/runner.js +168 -0
- package/lib/toolkit.js +212 -0
- package/lib/types/index.d.ts +8 -0
- package/lib/types/parse.d.ts +45 -0
- package/lib/types/runner.d.ts +53 -0
- package/lib/types/toolkit.d.ts +225 -0
- package/package.json +51 -0
- package/scripts/robot_profile.py +773 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { type JobHooks, type RunOptions, type RosResult } from './runner.js';
|
|
2
|
+
import { type JsonValue, parseJsonOrRaw } from './parse.js';
|
|
3
|
+
/** Execution seam injected by the plugin entry (real runner in prod, fake in tests). */
|
|
4
|
+
export type RunFn = (bin: string, args: string[], opts?: RunOptions) => Promise<RosResult>;
|
|
5
|
+
/** Minimal structural view of the DSH approval service (`ctx.approval.request`). */
|
|
6
|
+
export interface ApprovalRequest {
|
|
7
|
+
agent?: unknown;
|
|
8
|
+
toolName: string;
|
|
9
|
+
reason?: string;
|
|
10
|
+
signal?: AbortSignal;
|
|
11
|
+
}
|
|
12
|
+
/** Minimal structural view of the DSH jobs registry (`ctx.jobs`). */
|
|
13
|
+
export interface JobSnapshot {
|
|
14
|
+
id: string;
|
|
15
|
+
kind: string;
|
|
16
|
+
label: string;
|
|
17
|
+
status: string;
|
|
18
|
+
detail?: string;
|
|
19
|
+
startedAt?: number;
|
|
20
|
+
finishedAt?: number;
|
|
21
|
+
}
|
|
22
|
+
export interface JobSpec {
|
|
23
|
+
owner?: unknown;
|
|
24
|
+
kind: string;
|
|
25
|
+
label: string;
|
|
26
|
+
outputLimitBytes?: number;
|
|
27
|
+
run(): JobHooks;
|
|
28
|
+
}
|
|
29
|
+
export interface JobsApi {
|
|
30
|
+
start(spec: JobSpec): string;
|
|
31
|
+
list(caller?: unknown): JobSnapshot[];
|
|
32
|
+
get(id: string, caller?: unknown): JobSnapshot | undefined;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Pluggable vision contract (the vision package provides a concrete backend
|
|
36
|
+
* as an optional cordis service; core's ros2_gui_observe consumes it).
|
|
37
|
+
*/
|
|
38
|
+
export interface VisionConfig {
|
|
39
|
+
provider: string;
|
|
40
|
+
apiKey?: string;
|
|
41
|
+
model?: string;
|
|
42
|
+
baseUrl?: string;
|
|
43
|
+
}
|
|
44
|
+
export interface DescribeOptions {
|
|
45
|
+
signal?: AbortSignal;
|
|
46
|
+
}
|
|
47
|
+
export interface VisionProvider {
|
|
48
|
+
readonly name: string;
|
|
49
|
+
describe(imagePath: string, prompt: string, opts?: DescribeOptions): Promise<string>;
|
|
50
|
+
}
|
|
51
|
+
export interface ToolDeps {
|
|
52
|
+
run: RunFn;
|
|
53
|
+
/** Attach trailing stderr to successful results (default: drop noise). */
|
|
54
|
+
includeStderr?: boolean;
|
|
55
|
+
/** DSH approval service (L2 write tools fail closed without it). */
|
|
56
|
+
approval?: (req: ApprovalRequest) => Promise<string>;
|
|
57
|
+
/** DSH background jobs registry (needed by ros2_colcon_build). */
|
|
58
|
+
jobs?: JobsApi;
|
|
59
|
+
/** Workspace root used as fallback cwd / interface output root. */
|
|
60
|
+
workspaceRoot?: string;
|
|
61
|
+
/** L3 GUI lifecycle manager (ros2_gui_* / ros2_screenshot) — concrete type lives in dsh-ros2-core. */
|
|
62
|
+
gui?: unknown;
|
|
63
|
+
/** L3 pluggable multimodal vision (ros2_vision_describe / ros2_gui_observe). */
|
|
64
|
+
vision?: VisionProvider;
|
|
65
|
+
/**
|
|
66
|
+
* Tool-layer safety posture when the safety_monitor is unreachable:
|
|
67
|
+
* 'warn' (default, backward compatible) proceeds with a warning;
|
|
68
|
+
* 'reject' fails closed. A LOCKED /safety/state always rejects motion
|
|
69
|
+
* tools in both modes.
|
|
70
|
+
*/
|
|
71
|
+
safetyStrict?: 'warn' | 'reject';
|
|
72
|
+
}
|
|
73
|
+
/** Canonical result value shared by every tool (validated against `resultSchema`). */
|
|
74
|
+
export interface ToolResult {
|
|
75
|
+
ok: boolean;
|
|
76
|
+
tool: string;
|
|
77
|
+
command: string;
|
|
78
|
+
data: JsonValue;
|
|
79
|
+
warnings?: string[];
|
|
80
|
+
error?: {
|
|
81
|
+
code: string;
|
|
82
|
+
message: string;
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
export declare const resultSchema: {
|
|
86
|
+
readonly type: "object";
|
|
87
|
+
readonly additionalProperties: false;
|
|
88
|
+
readonly properties: {
|
|
89
|
+
readonly ok: {
|
|
90
|
+
readonly type: "boolean";
|
|
91
|
+
readonly required: true;
|
|
92
|
+
};
|
|
93
|
+
readonly tool: {
|
|
94
|
+
readonly type: "string";
|
|
95
|
+
readonly required: true;
|
|
96
|
+
};
|
|
97
|
+
readonly command: {
|
|
98
|
+
readonly type: "string";
|
|
99
|
+
readonly required: true;
|
|
100
|
+
};
|
|
101
|
+
readonly data: {
|
|
102
|
+
readonly type: "json";
|
|
103
|
+
readonly required: true;
|
|
104
|
+
};
|
|
105
|
+
readonly warnings: {
|
|
106
|
+
readonly type: "array";
|
|
107
|
+
readonly items: {
|
|
108
|
+
readonly type: "string";
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
readonly error: {
|
|
112
|
+
readonly type: "object";
|
|
113
|
+
readonly additionalProperties: false;
|
|
114
|
+
readonly properties: {
|
|
115
|
+
readonly code: {
|
|
116
|
+
readonly type: "string";
|
|
117
|
+
};
|
|
118
|
+
readonly message: {
|
|
119
|
+
readonly type: "string";
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
export declare const renderResult: (_args: unknown, value: JsonValue) => {
|
|
126
|
+
type: "text";
|
|
127
|
+
text: string;
|
|
128
|
+
}[];
|
|
129
|
+
export { type JsonValue, parseJsonOrRaw };
|
|
130
|
+
export { runCommand, spawnJob } from './runner.js';
|
|
131
|
+
export type { RosResult, RunOptions, JobHooks } from './runner.js';
|
|
132
|
+
export { foldGraph, parseLines, parseNodeInfo, parseTopicList, parseTransforms } from './parse.js';
|
|
133
|
+
/** Run-seam config (each domain package carries its own copy via Config). */
|
|
134
|
+
export interface RunConfig {
|
|
135
|
+
rosSetup: string;
|
|
136
|
+
timeoutMs: number;
|
|
137
|
+
rosLogDir: string;
|
|
138
|
+
workspaceRoot: string;
|
|
139
|
+
includeStderr: boolean;
|
|
140
|
+
}
|
|
141
|
+
/** Build the injected run seam from a package's config (mirrors legacy index.ts). */
|
|
142
|
+
export declare function makeRun(config: RunConfig): RunFn;
|
|
143
|
+
/** Path to a script shipped with dsh-ros2-common (e.g. robot_profile.py). */
|
|
144
|
+
export declare function commonScriptPath(name: string): string;
|
|
145
|
+
/** Optional value helpers (legacy ToolDeps params are loose). */
|
|
146
|
+
export declare function strOrUndefined(value: unknown): string | undefined;
|
|
147
|
+
export declare function numOrUndefined(value: unknown): number | undefined;
|
|
148
|
+
export declare function jsonOf(value: unknown): JsonValue;
|
|
149
|
+
export declare function tail(stderr: string): string[];
|
|
150
|
+
/**
|
|
151
|
+
* Gate a write operation behind DSH user approval. Fails closed: no approval
|
|
152
|
+
* service, no owning agent, an error, or any non-grant outcome all deny.
|
|
153
|
+
*/
|
|
154
|
+
export declare function requestApproval(deps: ToolDeps, exec: {
|
|
155
|
+
agent?: unknown;
|
|
156
|
+
signal?: AbortSignal;
|
|
157
|
+
}, toolName: string, reason: string): Promise<{
|
|
158
|
+
allowed: boolean;
|
|
159
|
+
outcome: string;
|
|
160
|
+
}>;
|
|
161
|
+
export declare function deniedResult(tool: string, command: string, outcome: string): ToolResult;
|
|
162
|
+
/** Safety-gate rejection with a distinct error code (SAFETY_LOCKED / SAFETY_MONITOR_DOWN). */
|
|
163
|
+
export declare function safetyDenied(tool: string, command: string, code: string, message: string): ToolResult;
|
|
164
|
+
export declare function toolError(tool: string, command: string, code: string, message: string): ToolResult;
|
|
165
|
+
export declare function okResult(tool: string, command: string, data: JsonValue): ToolResult;
|
|
166
|
+
export interface SafetyFields {
|
|
167
|
+
state?: string;
|
|
168
|
+
severity?: string;
|
|
169
|
+
cause?: string;
|
|
170
|
+
detail?: string;
|
|
171
|
+
}
|
|
172
|
+
/** Parse the flat `field: value` echo output of SafetyState.msg. */
|
|
173
|
+
export declare function parseSafetyEcho(stdout: string): SafetyFields;
|
|
174
|
+
/**
|
|
175
|
+
* Tool-layer safety gate for motion tools. A LOCKED /safety/state always
|
|
176
|
+
* rejects (with the trigger cause); an unreachable monitor rejects in
|
|
177
|
+
* 'reject' mode (fail-closed) or warns in 'warn' mode (backward compatible).
|
|
178
|
+
*/
|
|
179
|
+
export declare function enforceSafetyLock(deps: ToolDeps, tool: string, command: string, opts?: {
|
|
180
|
+
skip?: boolean;
|
|
181
|
+
}): Promise<{
|
|
182
|
+
denied?: ToolResult;
|
|
183
|
+
warning?: string;
|
|
184
|
+
}>;
|
|
185
|
+
/** Read the current latched /safety/state (monitor may be offline). */
|
|
186
|
+
export declare function readSafetyState(deps: ToolDeps): Promise<{
|
|
187
|
+
running: boolean;
|
|
188
|
+
fields: SafetyFields;
|
|
189
|
+
}>;
|
|
190
|
+
/** Locate a robot profile path (explicit path, or via robot_profile load). */
|
|
191
|
+
export declare function resolveProfilePath(deps: ToolDeps, robot: string, profile: string): Promise<string>;
|
|
192
|
+
/** Robot profile safety-view (the subset tools read for validation/gating). */
|
|
193
|
+
export interface ProfileSafetyView {
|
|
194
|
+
safety?: Record<string, unknown>;
|
|
195
|
+
joints?: Array<{
|
|
196
|
+
name: string;
|
|
197
|
+
limits?: Record<string, unknown>;
|
|
198
|
+
}>;
|
|
199
|
+
moveit?: {
|
|
200
|
+
groups?: Record<string, {
|
|
201
|
+
joints?: string[];
|
|
202
|
+
}>;
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
/** Load a registered robot profile (structured JSON, fast path). */
|
|
206
|
+
export declare function loadRobotProfile(deps: ToolDeps, robot: string): Promise<{
|
|
207
|
+
robot: ProfileSafetyView;
|
|
208
|
+
profile_path?: string;
|
|
209
|
+
} | null>;
|
|
210
|
+
export interface RosToolSpec {
|
|
211
|
+
name: string;
|
|
212
|
+
description: string;
|
|
213
|
+
bin?: string;
|
|
214
|
+
parameters?: Record<string, unknown>;
|
|
215
|
+
buildArgs: (params: Record<string, unknown>) => string[];
|
|
216
|
+
runOpts?: (params: Record<string, unknown>) => RunOptions;
|
|
217
|
+
parse: (res: RosResult, params: Record<string, unknown>) => JsonValue;
|
|
218
|
+
/** Interpret a non-zero exit as a finding instead of a failure. */
|
|
219
|
+
onNonZero?: (res: RosResult) => JsonValue;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Build an L1 read-only tool from a `ros2`-style command spec. Shared by
|
|
223
|
+
* dsh-ros2-core (diagnostics) and dsh-ros2-vision (image/VLM topics).
|
|
224
|
+
*/
|
|
225
|
+
export declare function ros2Tool(deps: ToolDeps, spec: RosToolSpec): import("@deepseek-ai/dsh-tools").ToolDefinition;
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-ros2-common",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Shared runtime for the dsh-ros2 plugin family: command runner, parsers, ToolDeps toolkit, and the robot-profile script (zero-copy across packages). Not a cordis bundle.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./lib/index.js",
|
|
7
|
+
"types": "./lib/types/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/types/index.d.ts",
|
|
11
|
+
"default": "./lib/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./package.json": "./package.json"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"lib",
|
|
17
|
+
"scripts",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": "^22.19.0 || >=24.0.0"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"dsh",
|
|
26
|
+
"dsh-plugin",
|
|
27
|
+
"deepseek-harness",
|
|
28
|
+
"ros2"
|
|
29
|
+
],
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/StvLi/dsh-ros2.git"
|
|
34
|
+
},
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@deepseek-ai/dsh-tools": "0.1.0-rc.6"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "^24.0.0",
|
|
43
|
+
"typescript": "^5.6.0",
|
|
44
|
+
"vitest": "^3.0.0"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"typecheck": "tsc --noEmit",
|
|
48
|
+
"test": "vitest run",
|
|
49
|
+
"build": "tsc -p tsconfig.build.json"
|
|
50
|
+
}
|
|
51
|
+
}
|