@steerable/agent-harness 0.2.3 → 0.2.5
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/dist/generated/ActionSegmentPayload.d.ts +21 -0
- package/dist/generated/ActionSegmentPayload.js +1 -0
- package/dist/generated/AnalysisDocumentPayload.d.ts +19 -0
- package/dist/generated/AnalysisDocumentPayload.js +1 -0
- package/dist/generated/AskUserQuestionsPayload.d.ts +20 -0
- package/dist/generated/AskUserQuestionsPayload.js +1 -0
- package/dist/generated/CoverageReportPayload.d.ts +42 -0
- package/dist/generated/CoverageReportPayload.js +1 -0
- package/dist/generated/OrchestrationPlanPayload.d.ts +43 -0
- package/dist/generated/OrchestrationPlanPayload.js +1 -0
- package/dist/generated/PlanSelectorPayload.d.ts +37 -0
- package/dist/generated/PlanSelectorPayload.js +1 -0
- package/dist/generated/PlanStepsPayload.d.ts +7 -0
- package/dist/generated/PlanStepsPayload.js +1 -0
- package/dist/generated/QuizPayload.d.ts +28 -0
- package/dist/generated/QuizPayload.js +1 -0
- package/dist/generated/ResearchPlanPayload.d.ts +26 -0
- package/dist/generated/ResearchPlanPayload.js +1 -0
- package/dist/generated/SearchSourcesPayload.d.ts +14 -0
- package/dist/generated/SearchSourcesPayload.js +1 -0
- package/dist/generated/SuggestedRepliesPayload.d.ts +10 -0
- package/dist/generated/SuggestedRepliesPayload.js +1 -0
- package/dist/generated/SummaryMessagePayload.d.ts +16 -0
- package/dist/generated/SummaryMessagePayload.js +1 -0
- package/dist/generated/ThinkingProcessPayload.d.ts +11 -0
- package/dist/generated/ThinkingProcessPayload.js +1 -0
- package/dist/generated/ToolExecutionPayload.d.ts +28 -0
- package/dist/generated/ToolExecutionPayload.js +1 -0
- package/dist/safety-patterns.d.ts +39 -2
- package/dist/safety-patterns.js +155 -60
- package/package.json +3 -3
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payload of an action-segment card -- a strip of tool / action invocations the agent ran inline within an assistant message. Each segment carries a kind (the action type), a status, and arbitrary args/output payload that downstream renderers pretty-print.
|
|
3
|
+
*/
|
|
4
|
+
export interface ActionSegmentPayload {
|
|
5
|
+
segments: {
|
|
6
|
+
id: string;
|
|
7
|
+
/**
|
|
8
|
+
* Action / tool name, e.g. 'create_task' or 'search.web'.
|
|
9
|
+
*/
|
|
10
|
+
kind: string;
|
|
11
|
+
status: "pending" | "running" | "succeeded" | "failed" | "cancelled";
|
|
12
|
+
label?: string | null;
|
|
13
|
+
args?: any;
|
|
14
|
+
output?: any;
|
|
15
|
+
error?: string | null;
|
|
16
|
+
startedAt?: string | null;
|
|
17
|
+
finishedAt?: string | null;
|
|
18
|
+
[k: string]: any;
|
|
19
|
+
}[];
|
|
20
|
+
[k: string]: any;
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payload of an analysis-document card. Renders as a long-form markdown document (research write-up, design memo, etc.). The body string can include GFM markdown, mermaid blocks, and inline references. The optional metadata block carries model / timestamp info shown in the document header.
|
|
3
|
+
*/
|
|
4
|
+
export interface AnalysisDocumentPayload {
|
|
5
|
+
/**
|
|
6
|
+
* Optional document title; defaults to a generic 'Analysis' label client-side.
|
|
7
|
+
*/
|
|
8
|
+
title?: string | null;
|
|
9
|
+
/**
|
|
10
|
+
* Markdown body. May include mermaid code-fences.
|
|
11
|
+
*/
|
|
12
|
+
body: string;
|
|
13
|
+
createdAt?: string | null;
|
|
14
|
+
/**
|
|
15
|
+
* Display model badge id (resolved to model option client-side).
|
|
16
|
+
*/
|
|
17
|
+
modelId?: string | null;
|
|
18
|
+
[k: string]: any;
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payload of an ask-user-questions card. The agent has paused mid-run and needs structured input from the user before continuing. Each question is one of: option buttons (select), free-form text, or password. After the user answers, the backend re-emits the same card with answers filled in to switch the UI to read-only.
|
|
3
|
+
*/
|
|
4
|
+
export interface AskUserQuestionsPayload {
|
|
5
|
+
intro: string;
|
|
6
|
+
outro?: string | null;
|
|
7
|
+
answers?: {
|
|
8
|
+
[k: string]: string | string[];
|
|
9
|
+
} | null;
|
|
10
|
+
questions: {
|
|
11
|
+
id: string;
|
|
12
|
+
text: string;
|
|
13
|
+
type?: "select" | "text" | "password";
|
|
14
|
+
options?: string[];
|
|
15
|
+
placeholder?: string | null;
|
|
16
|
+
multiSelect?: boolean;
|
|
17
|
+
[k: string]: any;
|
|
18
|
+
}[];
|
|
19
|
+
[k: string]: any;
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payload of a coverage-report card. Summarises mastery of a knowledge graph: section-level coverage / mastery and a list of weak knowledge points the learner should remediate. The actions block tells the UI whether a 'practice weak points' button should be offered.
|
|
3
|
+
*/
|
|
4
|
+
export interface CoverageReportPayload {
|
|
5
|
+
reportId: string;
|
|
6
|
+
title: string;
|
|
7
|
+
/**
|
|
8
|
+
* 0..1 fraction of nodes covered.
|
|
9
|
+
*/
|
|
10
|
+
overallCoverage: number;
|
|
11
|
+
/**
|
|
12
|
+
* 0..1 fraction of nodes mastered.
|
|
13
|
+
*/
|
|
14
|
+
overallMastery: number;
|
|
15
|
+
summary?: string | null;
|
|
16
|
+
sections: {
|
|
17
|
+
id: string;
|
|
18
|
+
name: string;
|
|
19
|
+
coverage: number;
|
|
20
|
+
mastery: number;
|
|
21
|
+
totalCount: number;
|
|
22
|
+
learnedCount: number;
|
|
23
|
+
testedCount: number;
|
|
24
|
+
masteredCount: number;
|
|
25
|
+
weakKpIds: string[];
|
|
26
|
+
[k: string]: any;
|
|
27
|
+
}[];
|
|
28
|
+
weakPoints: {
|
|
29
|
+
id: string;
|
|
30
|
+
name: string;
|
|
31
|
+
sectionName?: string | null;
|
|
32
|
+
accuracy: number;
|
|
33
|
+
recommendation: string;
|
|
34
|
+
[k: string]: any;
|
|
35
|
+
}[];
|
|
36
|
+
actions: {
|
|
37
|
+
allowRemediateQuiz: boolean;
|
|
38
|
+
remediateActionLabel: string;
|
|
39
|
+
[k: string]: any;
|
|
40
|
+
};
|
|
41
|
+
[k: string]: any;
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payload of an orchestration-plan card emitted by the Coordinator agent. Lists every worker task (id + agent + prompt + dependencies). The UI renders one row per task with a live status dot driven by sibling assistant messages tagged with the same orchestrationGroupId + orchestrationTaskId.
|
|
3
|
+
*/
|
|
4
|
+
export interface OrchestrationPlanPayload {
|
|
5
|
+
/**
|
|
6
|
+
* Short prose explanation of why the coordinator picked this plan shape.
|
|
7
|
+
*/
|
|
8
|
+
rationale?: string;
|
|
9
|
+
/**
|
|
10
|
+
* How the workers run with respect to each other.
|
|
11
|
+
*/
|
|
12
|
+
mode?: "parallel" | "sequential" | "dag";
|
|
13
|
+
tasks: {
|
|
14
|
+
/**
|
|
15
|
+
* Stable id for this task within the orchestration group.
|
|
16
|
+
*/
|
|
17
|
+
id: string;
|
|
18
|
+
/**
|
|
19
|
+
* Which agent runs this task.
|
|
20
|
+
*/
|
|
21
|
+
agentId: string;
|
|
22
|
+
/**
|
|
23
|
+
* Per-task prompt the coordinator drafted.
|
|
24
|
+
*/
|
|
25
|
+
prompt?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Task ids that must finish before this one starts.
|
|
28
|
+
*/
|
|
29
|
+
dependsOn?: string[];
|
|
30
|
+
/**
|
|
31
|
+
* Task ids whose outputs this task is allowed to read.
|
|
32
|
+
*/
|
|
33
|
+
readOutputsFrom?: string[];
|
|
34
|
+
[k: string]: any;
|
|
35
|
+
}[];
|
|
36
|
+
coordinator?: {
|
|
37
|
+
agentId?: string;
|
|
38
|
+
name?: string;
|
|
39
|
+
avatar?: string;
|
|
40
|
+
[k: string]: any;
|
|
41
|
+
};
|
|
42
|
+
[k: string]: any;
|
|
43
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payload of a plan-selector card. The agent has drafted multiple candidate plans and is asking the user to pick one. Each plan carries effort / risk metrics and a pros/cons list. After selection the backend re-emits with selectedPlan filled in.
|
|
3
|
+
*/
|
|
4
|
+
export interface PlanSelectorPayload {
|
|
5
|
+
/**
|
|
6
|
+
* Short prose summarising how the candidate plans differ.
|
|
7
|
+
*/
|
|
8
|
+
comparison: string;
|
|
9
|
+
/**
|
|
10
|
+
* Id of the user-chosen plan once decided.
|
|
11
|
+
*/
|
|
12
|
+
selectedPlan?: string | null;
|
|
13
|
+
goalAttribution: {
|
|
14
|
+
type: "existing" | "new";
|
|
15
|
+
existingGoalId?: string | null;
|
|
16
|
+
existingGoalTitle?: string | null;
|
|
17
|
+
newGoalTitle?: string | null;
|
|
18
|
+
[k: string]: any;
|
|
19
|
+
};
|
|
20
|
+
plans: {
|
|
21
|
+
id: string;
|
|
22
|
+
name: string;
|
|
23
|
+
summary: string;
|
|
24
|
+
approach: string;
|
|
25
|
+
bestFor: string;
|
|
26
|
+
metrics: {
|
|
27
|
+
duration: string;
|
|
28
|
+
effortLevel: "low" | "medium" | "high";
|
|
29
|
+
riskLevel: "low" | "medium" | "high";
|
|
30
|
+
[k: string]: any;
|
|
31
|
+
};
|
|
32
|
+
pros: string[];
|
|
33
|
+
cons: string[];
|
|
34
|
+
[k: string]: any;
|
|
35
|
+
}[];
|
|
36
|
+
[k: string]: any;
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payload of a quiz card. Carries one or more questions (choice / fill / judge / short_answer) and a submit button label. After the learner submits, the backend re-emits the same quizId with submittedAnswers filled in to switch the UI to read-only review mode.
|
|
3
|
+
*/
|
|
4
|
+
export interface QuizPayload {
|
|
5
|
+
/**
|
|
6
|
+
* Stable id, used for resubmit and review continuity.
|
|
7
|
+
*/
|
|
8
|
+
quizId: string;
|
|
9
|
+
title: string;
|
|
10
|
+
description?: string | null;
|
|
11
|
+
submitActionLabel: string;
|
|
12
|
+
submittedAnswers?: {
|
|
13
|
+
[k: string]: string | string[];
|
|
14
|
+
} | null;
|
|
15
|
+
questions: {
|
|
16
|
+
id: string;
|
|
17
|
+
type: "choice" | "fill" | "judge" | "short_answer";
|
|
18
|
+
stem: string;
|
|
19
|
+
options?: string[] | null;
|
|
20
|
+
allowMultiple?: boolean | null;
|
|
21
|
+
placeholder?: string | null;
|
|
22
|
+
points?: number | null;
|
|
23
|
+
knowledgePointId?: string | null;
|
|
24
|
+
difficulty?: number | null;
|
|
25
|
+
[k: string]: any;
|
|
26
|
+
}[];
|
|
27
|
+
[k: string]: any;
|
|
28
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payload of a research-plan card. Snapshots a research agent's current sub-question tree and its decision for the next round. The UI shows each sub-question with kind / evidence-strength badges.
|
|
3
|
+
*/
|
|
4
|
+
export interface ResearchPlanPayload {
|
|
5
|
+
topic: string;
|
|
6
|
+
round: number;
|
|
7
|
+
/**
|
|
8
|
+
* True when the research loop is complete and this snapshot is the last one.
|
|
9
|
+
*/
|
|
10
|
+
final: boolean;
|
|
11
|
+
subQuestions: {
|
|
12
|
+
id: string;
|
|
13
|
+
question: string;
|
|
14
|
+
kind: "fact" | "compare" | "conclusion" | "risk";
|
|
15
|
+
status: "pending" | "searching" | "evidenced_strong" | "evidenced_medium" | "evidenced_weak" | "conflicted" | "exhausted";
|
|
16
|
+
evidenceCount: number;
|
|
17
|
+
note?: string | null;
|
|
18
|
+
[k: string]: any;
|
|
19
|
+
}[];
|
|
20
|
+
decision: {
|
|
21
|
+
next: "continue" | "expand" | "converge";
|
|
22
|
+
reason?: string | null;
|
|
23
|
+
[k: string]: any;
|
|
24
|
+
};
|
|
25
|
+
[k: string]: any;
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payload of a search-sources card. Lists the web pages that an agent consulted while answering. Rendered as a row of stacked favicons with an expandable detail list.
|
|
3
|
+
*/
|
|
4
|
+
export interface SearchSourcesPayload {
|
|
5
|
+
sources: {
|
|
6
|
+
url: string;
|
|
7
|
+
title?: string | null;
|
|
8
|
+
snippet?: string | null;
|
|
9
|
+
favicon?: string | null;
|
|
10
|
+
publishedAt?: string | null;
|
|
11
|
+
[k: string]: any;
|
|
12
|
+
}[];
|
|
13
|
+
[k: string]: any;
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payload of a suggested-replies card. A small set of single-shot quick-reply texts shown below the composer; clicking one sends that text as the next user message.
|
|
3
|
+
*/
|
|
4
|
+
export interface SuggestedRepliesPayload {
|
|
5
|
+
/**
|
|
6
|
+
* Quick-reply texts. Clients typically render the first ~6; backend should keep the list short.
|
|
7
|
+
*/
|
|
8
|
+
suggestions: string[];
|
|
9
|
+
[k: string]: any;
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payload of a summary-message card. Used when the chat history was condensed: the card shows a markdown summary along with a count of how many original messages it replaces. Collapsed by default.
|
|
3
|
+
*/
|
|
4
|
+
export interface SummaryMessagePayload {
|
|
5
|
+
/**
|
|
6
|
+
* Markdown summary text.
|
|
7
|
+
*/
|
|
8
|
+
body: string;
|
|
9
|
+
summarizedCount?: number | null;
|
|
10
|
+
status?: "pending" | "complete" | "failed" | null;
|
|
11
|
+
/**
|
|
12
|
+
* Free-form summary kind label (e.g. 'history_compaction').
|
|
13
|
+
*/
|
|
14
|
+
type?: string | null;
|
|
15
|
+
[k: string]: any;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payload of a thinking-process card. Renders the agent's chain-of-thought (markdown) in a collapsible panel. UI clients are responsible for redacting / disabling this card if the deployment policy forbids exposing raw reasoning to end users.
|
|
3
|
+
*/
|
|
4
|
+
export interface ThinkingProcessPayload {
|
|
5
|
+
/**
|
|
6
|
+
* Markdown chain-of-thought text.
|
|
7
|
+
*/
|
|
8
|
+
body: string;
|
|
9
|
+
defaultExpanded?: boolean;
|
|
10
|
+
[k: string]: any;
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payload of a tool-execution card. Unified representation of a single tool / MCP / local action invocation: name, status, args (input), output, and an optional human-readable summary. Both deeppath's ActionSegment and deeppath-agent's ExecutedActionsCard render off this same shape.
|
|
3
|
+
*/
|
|
4
|
+
export interface ToolExecutionPayload {
|
|
5
|
+
/**
|
|
6
|
+
* Stable id of this invocation.
|
|
7
|
+
*/
|
|
8
|
+
id: string;
|
|
9
|
+
/**
|
|
10
|
+
* Tool name as exposed to the agent.
|
|
11
|
+
*/
|
|
12
|
+
name: string;
|
|
13
|
+
status: "pending" | "running" | "succeeded" | "failed" | "cancelled";
|
|
14
|
+
/**
|
|
15
|
+
* One-line human summary for the row header.
|
|
16
|
+
*/
|
|
17
|
+
summary?: string | null;
|
|
18
|
+
args?: any;
|
|
19
|
+
output?: any;
|
|
20
|
+
error?: string | null;
|
|
21
|
+
durationMs?: number | null;
|
|
22
|
+
/**
|
|
23
|
+
* Optional icon hint (lucide name or url).
|
|
24
|
+
*/
|
|
25
|
+
icon?: string | null;
|
|
26
|
+
expandable?: boolean;
|
|
27
|
+
[k: string]: any;
|
|
28
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell command safety patterns — classify a command before it runs.
|
|
3
|
+
*
|
|
4
|
+
* Full 61-rule set reflowed from deeppath-agent's
|
|
5
|
+
* `src/harness/safety-patterns.ts`; the framework is now the source of truth
|
|
6
|
+
* (agent will import from here in A4). Kept in lockstep with the Python twin
|
|
7
|
+
* `packages/agent-harness/py/src/steerable_agent_harness/safety.py` via the
|
|
8
|
+
* conformance case `tests/conformance/cases/safety/classify_shell_command.yaml`.
|
|
9
|
+
*
|
|
10
|
+
* Rule order matters: `matchedRules` follows BUILTIN_PATTERNS order so both
|
|
11
|
+
* languages return identical lists.
|
|
12
|
+
*/
|
|
13
|
+
export interface CommandSafetyConfig {
|
|
14
|
+
disabledPatternIds?: string[];
|
|
15
|
+
hiddenPatternIds?: string[];
|
|
16
|
+
customPatterns?: Array<{
|
|
17
|
+
id: string;
|
|
18
|
+
label: string;
|
|
19
|
+
pattern: string;
|
|
20
|
+
category: string;
|
|
21
|
+
enabled: boolean;
|
|
22
|
+
}>;
|
|
23
|
+
}
|
|
1
24
|
export type PatternSeverity = "critical" | "warning";
|
|
2
25
|
export type PatternPlatform = "all" | "unix" | "windows";
|
|
3
26
|
export interface SafetyPatternDef {
|
|
@@ -9,8 +32,22 @@ export interface SafetyPatternDef {
|
|
|
9
32
|
severity: PatternSeverity;
|
|
10
33
|
platform: PatternPlatform;
|
|
11
34
|
}
|
|
35
|
+
export declare const SAFETY_CATEGORIES: Record<string, string>;
|
|
12
36
|
export declare const BUILTIN_PATTERNS: SafetyPatternDef[];
|
|
13
|
-
|
|
37
|
+
/**
|
|
38
|
+
* 根据用户配置计算当前生效的正则模式列表
|
|
39
|
+
*/
|
|
40
|
+
export declare function getActivePatterns(config?: CommandSafetyConfig | null): RegExp[];
|
|
41
|
+
/**
|
|
42
|
+
* 按分类分组返回内置模式
|
|
43
|
+
*/
|
|
44
|
+
export declare function getPatternsByCategory(): Record<string, SafetyPatternDef[]>;
|
|
45
|
+
/**
|
|
46
|
+
* 默认空配置(所有内置模式均启用,无自定义模式)
|
|
47
|
+
*/
|
|
48
|
+
export declare const DEFAULT_COMMAND_SAFETY_CONFIG: CommandSafetyConfig;
|
|
49
|
+
export interface ShellCommandClassification {
|
|
14
50
|
severity: "safe" | PatternSeverity;
|
|
15
51
|
matchedRules: string[];
|
|
16
|
-
}
|
|
52
|
+
}
|
|
53
|
+
export declare function classifyShellCommand(command: string, config?: CommandSafetyConfig | null): ShellCommandClassification;
|
package/dist/safety-patterns.js
CHANGED
|
@@ -1,71 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell command safety patterns — classify a command before it runs.
|
|
3
|
+
*
|
|
4
|
+
* Full 61-rule set reflowed from deeppath-agent's
|
|
5
|
+
* `src/harness/safety-patterns.ts`; the framework is now the source of truth
|
|
6
|
+
* (agent will import from here in A4). Kept in lockstep with the Python twin
|
|
7
|
+
* `packages/agent-harness/py/src/steerable_agent_harness/safety.py` via the
|
|
8
|
+
* conformance case `tests/conformance/cases/safety/classify_shell_command.yaml`.
|
|
9
|
+
*
|
|
10
|
+
* Rule order matters: `matchedRules` follows BUILTIN_PATTERNS order so both
|
|
11
|
+
* languages return identical lists.
|
|
12
|
+
*/
|
|
13
|
+
// ─── Categories ──────────────────────────────────────────────────────
|
|
14
|
+
export const SAFETY_CATEGORIES = {
|
|
15
|
+
file_ops: "文件操作",
|
|
16
|
+
system: "系统管理",
|
|
17
|
+
process: "进程管理",
|
|
18
|
+
network: "网络安全",
|
|
19
|
+
package: "包管理",
|
|
20
|
+
vcs: "版本控制",
|
|
21
|
+
container: "容器管理",
|
|
22
|
+
file_write: "文件写入",
|
|
23
|
+
windows: "Windows / PowerShell",
|
|
24
|
+
};
|
|
25
|
+
// ─── Built-in patterns ───────────────────────────────────────────────
|
|
26
|
+
// Merged from deeppath-agent local-actions.ts (web, severity=warning) and
|
|
27
|
+
// local-executor.ts (desktop, severity=critical). Keep aligned with the
|
|
28
|
+
// Python twin.
|
|
1
29
|
export const BUILTIN_PATTERNS = [
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
{
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
{
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
},
|
|
30
|
+
// ── file_ops ──
|
|
31
|
+
{ id: "rm", label: "rm 删除", description: "匹配 rm 命令", pattern: "\\brm\\s", category: "file_ops", severity: "warning", platform: "unix" },
|
|
32
|
+
{ id: "rm_end", label: "rm(行尾)", description: "匹配行尾的 rm", pattern: "\\brm$", category: "file_ops", severity: "warning", platform: "unix" },
|
|
33
|
+
{ id: "rm_rf_root", label: "rm -rf /", description: "递归删除根目录", pattern: "rm\\s+-rf\\s+\\/(?:\\s|$)", category: "file_ops", severity: "critical", platform: "unix" },
|
|
34
|
+
{ id: "rmdir", label: "rmdir 删除目录", description: "匹配 rmdir 命令", pattern: "\\brmdir\\s", category: "file_ops", severity: "warning", platform: "unix" },
|
|
35
|
+
{ id: "mv", label: "mv 移动/重命名", description: "匹配 mv 命令", pattern: "\\bmv\\s.*\\/", category: "file_ops", severity: "warning", platform: "unix" },
|
|
36
|
+
{ id: "shred", label: "shred 安全擦除", description: "不可恢复地擦除文件", pattern: "\\bshred\\b", category: "file_ops", severity: "warning", platform: "unix" },
|
|
37
|
+
{ id: "truncate", label: "truncate 截断文件", description: "截断文件内容", pattern: "\\btruncate\\b", category: "file_ops", severity: "warning", platform: "unix" },
|
|
38
|
+
// ── system ──
|
|
39
|
+
{ id: "sudo", label: "sudo 提权", description: "以超级用户权限执行", pattern: "\\bsudo\\s", category: "system", severity: "critical", platform: "unix" },
|
|
40
|
+
{ id: "mkfs", label: "mkfs 格式化磁盘", description: "创建文件系统(格式化)", pattern: "\\bmkfs\\b", category: "system", severity: "critical", platform: "unix" },
|
|
41
|
+
{ id: "dd", label: "dd 磁盘写入", description: "底层磁盘数据复制", pattern: "\\bdd\\s", category: "system", severity: "warning", platform: "unix" },
|
|
42
|
+
{ id: "dd_if", label: "dd if= 磁盘镜像", description: "使用 dd if= 读写磁盘", pattern: "\\bdd\\s+if=", category: "system", severity: "critical", platform: "unix" },
|
|
43
|
+
{ id: "format", label: "format 格式化", description: "格式化磁盘", pattern: "\\bformat\\b", category: "system", severity: "warning", platform: "all" },
|
|
44
|
+
{ id: "shutdown", label: "shutdown 关机", description: "关闭系统", pattern: "\\bshutdown\\b", category: "system", severity: "warning", platform: "all" },
|
|
45
|
+
{ id: "reboot", label: "reboot 重启", description: "重启系统", pattern: "\\breboot\\b", category: "system", severity: "warning", platform: "all" },
|
|
46
|
+
{ id: "chmod", label: "chmod 修改权限", description: "修改文件权限", pattern: "\\bchmod\\s", category: "system", severity: "warning", platform: "unix" },
|
|
47
|
+
{ id: "chmod_777_root", label: "chmod -R 777 /", description: "递归赋予根目录所有权限", pattern: "chmod\\s+-R\\s+777\\s+\\/(?:\\s|$)", category: "system", severity: "critical", platform: "unix" },
|
|
48
|
+
{ id: "chown", label: "chown 修改所有者", description: "修改文件所有者", pattern: "\\bchown\\s", category: "system", severity: "warning", platform: "unix" },
|
|
49
|
+
{ id: "fork_bomb", label: "Fork Bomb", description: ":(){ :|:& };: fork 炸弹", pattern: ":\\(\\)\\s*\\{\\s*:\\|:&\\s*\\};:", category: "system", severity: "critical", platform: "unix" },
|
|
50
|
+
// ── process ──
|
|
51
|
+
{ id: "kill", label: "kill 终止进程", description: "向进程发送信号", pattern: "\\bkill\\s", category: "process", severity: "warning", platform: "unix" },
|
|
52
|
+
{ id: "killall", label: "killall 终止所有", description: "按名称终止进程", pattern: "\\bkillall\\s", category: "process", severity: "warning", platform: "unix" },
|
|
53
|
+
// ── network ──
|
|
54
|
+
{ id: "curl_pipe_sh", label: "curl | sh", description: "从网络下载并直接执行脚本", pattern: "\\bcurl\\s.*\\|\\s*(sh|bash|zsh)", category: "network", severity: "warning", platform: "unix" },
|
|
55
|
+
{ id: "wget_pipe_sh", label: "wget | sh", description: "从网络下载并直接执行脚本", pattern: "\\bwget\\s.*\\|\\s*(sh|bash|zsh)", category: "network", severity: "warning", platform: "unix" },
|
|
56
|
+
{ id: "redirect_dev", label: "重定向到 /dev/", description: "向设备文件写入数据", pattern: ">\\s*\\/dev\\/", category: "network", severity: "warning", platform: "unix" },
|
|
57
|
+
// ── package ──
|
|
58
|
+
{ id: "npm_publish", label: "npm publish", description: "发布/取消发布 npm 包", pattern: "\\bnpm\\s+(publish|unpublish)", category: "package", severity: "warning", platform: "all" },
|
|
59
|
+
{ id: "pip_install", label: "pip install", description: "安装 Python 包", pattern: "\\bpip\\s+install\\b", category: "package", severity: "warning", platform: "all" },
|
|
60
|
+
{ id: "npm_install", label: "npm install", description: "安装 npm 包", pattern: "\\bnpm\\s+install\\b", category: "package", severity: "warning", platform: "all" },
|
|
61
|
+
{ id: "yarn_add", label: "yarn add", description: "添加 yarn 依赖", pattern: "\\byarn\\s+add\\b", category: "package", severity: "warning", platform: "all" },
|
|
62
|
+
{ id: "pnpm_add", label: "pnpm add", description: "添加 pnpm 依赖", pattern: "\\bpnpm\\s+add\\b", category: "package", severity: "warning", platform: "all" },
|
|
63
|
+
{ id: "uv_add", label: "uv add", description: "添加 uv 依赖", pattern: "\\buv\\s+add\\b", category: "package", severity: "warning", platform: "all" },
|
|
64
|
+
{ id: "apt_install", label: "apt install/remove", description: "系统包管理器操作", pattern: "\\bapt(-get)?\\s+(install|remove|purge)", category: "package", severity: "warning", platform: "unix" },
|
|
65
|
+
{ id: "brew_install", label: "brew install/uninstall", description: "Homebrew 包管理器操作", pattern: "\\bbrew\\s+(install|uninstall|remove)", category: "package", severity: "warning", platform: "unix" },
|
|
66
|
+
// ── vcs ──
|
|
67
|
+
{ id: "git_push", label: "git push / reset --hard", description: "Git 远程推送或硬重置", pattern: "\\bgit\\s+(push|reset\\s+--hard|clean\\s+-fd)", category: "vcs", severity: "warning", platform: "all" },
|
|
68
|
+
// ── container ──
|
|
69
|
+
{ id: "docker_rm", label: "docker rm/rmi/prune", description: "删除容器/镜像或清理系统", pattern: "\\bdocker\\s+(rm|rmi|system\\s+prune)", category: "container", severity: "warning", platform: "all" },
|
|
70
|
+
// ── file_write ──
|
|
71
|
+
{ id: "redirect_overwrite", label: "> / >> 重定向写入", description: "文件重定向覆盖或追加", pattern: "\\b(>\\s|>>)\\s*[^|]", category: "file_write", severity: "warning", platform: "all" },
|
|
72
|
+
{ id: "tee", label: "tee 写入文件", description: "将输出写入文件", pattern: "\\btee\\s", category: "file_write", severity: "warning", platform: "unix" },
|
|
73
|
+
{ id: "sed_inplace", label: "sed -i 原地修改", description: "直接修改文件内容", pattern: "\\bsed\\s+-i", category: "file_write", severity: "warning", platform: "unix" },
|
|
74
|
+
// ── windows ──
|
|
75
|
+
{ id: "win_del", label: "del 删除", description: "Windows 删除命令", pattern: "\\bdel\\s", category: "windows", severity: "warning", platform: "windows" },
|
|
76
|
+
{ id: "win_rd", label: "rd 删除目录", description: "Windows 删除目录", pattern: "\\brd\\s", category: "windows", severity: "warning", platform: "windows" },
|
|
77
|
+
{ id: "win_rd_end", label: "rd(行尾)", description: "匹配行尾的 rd", pattern: "\\brd$", category: "windows", severity: "warning", platform: "windows" },
|
|
78
|
+
{ id: "win_rdel", label: "rdel", description: "Windows rdel 命令", pattern: "\\brdel\\b", category: "windows", severity: "warning", platform: "windows" },
|
|
79
|
+
{ id: "win_del_force", label: "del /f /s /q 强制删除", description: "强制递归删除整个驱动器", pattern: "\\bdel\\s+\\/f\\s+\\/s\\s+\\/q\\s+[a-z]:\\\\", category: "windows", severity: "critical", platform: "windows" },
|
|
80
|
+
{ id: "win_rd_force", label: "rd /s /q 强制删除目录", description: "强制递归删除整个驱动器目录", pattern: "\\brd\\s+\\/s\\s+\\/q\\s+[a-z]:\\\\", category: "windows", severity: "critical", platform: "windows" },
|
|
81
|
+
{ id: "win_remove_item", label: "Remove-Item", description: "PowerShell 删除项", pattern: "\\bRemove-Item\\b", category: "windows", severity: "warning", platform: "windows" },
|
|
82
|
+
{ id: "win_stop_process", label: "Stop-Process", description: "PowerShell 终止进程", pattern: "\\bStop-Process\\b", category: "windows", severity: "warning", platform: "windows" },
|
|
83
|
+
{ id: "win_stop_computer", label: "Stop-Computer", description: "PowerShell 关机", pattern: "\\bStop-Computer\\b", category: "windows", severity: "warning", platform: "windows" },
|
|
84
|
+
{ id: "win_restart_computer", label: "Restart-Computer", description: "PowerShell 重启", pattern: "\\bRestart-Computer\\b", category: "windows", severity: "warning", platform: "windows" },
|
|
85
|
+
{ id: "win_set_execution_policy", label: "Set-ExecutionPolicy", description: "修改脚本执行策略", pattern: "\\bSet-ExecutionPolicy\\b", category: "windows", severity: "warning", platform: "windows" },
|
|
86
|
+
{ id: "win_format_volume", label: "Format-Volume", description: "PowerShell 格式化卷", pattern: "\\bFormat-Volume\\b", category: "windows", severity: "warning", platform: "windows" },
|
|
87
|
+
{ id: "win_clear_disk", label: "Clear-Disk", description: "PowerShell 清除磁盘", pattern: "\\bClear-Disk\\b", category: "windows", severity: "warning", platform: "windows" },
|
|
88
|
+
{ id: "win_wsl", label: "wsl 子系统", description: "调用 WSL 子系统", pattern: "\\bwsl\\s", category: "windows", severity: "warning", platform: "windows" },
|
|
89
|
+
{ id: "win_powershell_cmd", label: "powershell -Command", description: "通过 PowerShell 执行命令", pattern: "\\bpowershell\\s.*-[Cc]ommand", category: "windows", severity: "warning", platform: "windows" },
|
|
90
|
+
{ id: "win_pwsh", label: "pwsh", description: "PowerShell Core", pattern: "\\bpwsh\\s", category: "windows", severity: "warning", platform: "windows" },
|
|
91
|
+
{ id: "win_cmd_c", label: "cmd /c", description: "CMD 执行命令", pattern: "\\bcmd\\s*\\/c\\b", category: "windows", severity: "warning", platform: "windows" },
|
|
92
|
+
{ id: "win_reg", label: "reg delete/add", description: "注册表操作", pattern: "\\breg\\s+(delete|add)\\b", category: "windows", severity: "warning", platform: "windows" },
|
|
93
|
+
{ id: "win_net", label: "net user/stop/start", description: "网络和用户管理", pattern: "\\bnet\\s+(user|stop|start)\\b", category: "windows", severity: "warning", platform: "windows" },
|
|
94
|
+
{ id: "win_sc", label: "sc delete/stop/config", description: "服务管理", pattern: "\\bsc\\s+(delete|stop|config)\\b", category: "windows", severity: "warning", platform: "windows" },
|
|
95
|
+
{ id: "win_diskpart", label: "diskpart", description: "磁盘分区工具", pattern: "\\bdiskpart\\b", category: "windows", severity: "warning", platform: "windows" },
|
|
96
|
+
{ id: "win_bcdedit", label: "bcdedit", description: "启动配置编辑", pattern: "\\bbcdedit\\b", category: "windows", severity: "warning", platform: "windows" },
|
|
97
|
+
{ id: "win_sfc", label: "sfc", description: "系统文件检查器", pattern: "\\bsfc\\b", category: "windows", severity: "warning", platform: "windows" },
|
|
98
|
+
{ id: "win_dism", label: "dism", description: "部署映像服务和管理", pattern: "\\bdism\\b", category: "windows", severity: "warning", platform: "windows" },
|
|
99
|
+
// 只匹配 "format <盘符>:" 形式的磁盘格式化(含 format.com),避免误伤
|
|
100
|
+
// PowerShell 的 Format-List / Format-Table 等格式化输出 cmdlet
|
|
101
|
+
// (Format-Volume 由上面的 win_format_volume 单独覆盖)。
|
|
102
|
+
{ id: "win_format_cmd", label: "format(Windows)", description: "Windows 格式化磁盘命令", pattern: "\\bformat(\\.com)?\\s+[a-z]:", category: "windows", severity: "critical", platform: "windows" },
|
|
56
103
|
];
|
|
57
|
-
|
|
104
|
+
// ─── Helpers ─────────────────────────────────────────────────────────
|
|
105
|
+
/**
|
|
106
|
+
* 根据用户配置计算当前生效的正则模式列表
|
|
107
|
+
*/
|
|
108
|
+
export function getActivePatterns(config) {
|
|
109
|
+
const disabled = new Set(config?.disabledPatternIds ?? []);
|
|
110
|
+
const patterns = BUILTIN_PATTERNS.filter((p) => !disabled.has(p.id)).map((p) => {
|
|
111
|
+
const flags = p.platform === "windows" ? "i" : undefined;
|
|
112
|
+
return new RegExp(p.pattern, flags);
|
|
113
|
+
});
|
|
114
|
+
if (config?.customPatterns) {
|
|
115
|
+
for (const cp of config.customPatterns) {
|
|
116
|
+
if (!cp.enabled)
|
|
117
|
+
continue;
|
|
118
|
+
try {
|
|
119
|
+
patterns.push(new RegExp(cp.pattern));
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// skip invalid regex
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return patterns;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* 按分类分组返回内置模式
|
|
130
|
+
*/
|
|
131
|
+
export function getPatternsByCategory() {
|
|
132
|
+
const grouped = {};
|
|
133
|
+
for (const p of BUILTIN_PATTERNS) {
|
|
134
|
+
if (!grouped[p.category])
|
|
135
|
+
grouped[p.category] = [];
|
|
136
|
+
grouped[p.category].push(p);
|
|
137
|
+
}
|
|
138
|
+
return grouped;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* 默认空配置(所有内置模式均启用,无自定义模式)
|
|
142
|
+
*/
|
|
143
|
+
export const DEFAULT_COMMAND_SAFETY_CONFIG = {
|
|
144
|
+
disabledPatternIds: [],
|
|
145
|
+
hiddenPatternIds: [],
|
|
146
|
+
customPatterns: [],
|
|
147
|
+
};
|
|
148
|
+
export function classifyShellCommand(command, config) {
|
|
58
149
|
const normalized = command.trim();
|
|
59
|
-
if (!normalized)
|
|
150
|
+
if (!normalized) {
|
|
60
151
|
return { severity: "safe", matchedRules: [] };
|
|
61
|
-
|
|
152
|
+
}
|
|
153
|
+
const disabled = new Set(config?.disabledPatternIds ?? []);
|
|
154
|
+
const matches = BUILTIN_PATTERNS.filter((rule) => !disabled.has(rule.id)).filter((rule) => {
|
|
62
155
|
const flags = rule.platform === "windows" ? "i" : undefined;
|
|
63
156
|
return new RegExp(rule.pattern, flags).test(normalized);
|
|
64
157
|
});
|
|
65
|
-
if (!matches.length)
|
|
158
|
+
if (!matches.length) {
|
|
66
159
|
return { severity: "safe", matchedRules: [] };
|
|
160
|
+
}
|
|
161
|
+
const severity = matches.some((item) => item.severity === "critical") ? "critical" : "warning";
|
|
67
162
|
return {
|
|
68
|
-
severity
|
|
69
|
-
matchedRules: matches.map((
|
|
163
|
+
severity,
|
|
164
|
+
matchedRules: matches.map((item) => item.id),
|
|
70
165
|
};
|
|
71
166
|
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@steerable/agent-harness",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Steerable framework Tier 2 — TypeScript facade over the Python harness (policy, budget, retry, completion, tracing) used for cross-language conformance tests. Production code should depend on the Python harness.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
|
-
"homepage": "https://
|
|
6
|
+
"homepage": "https://steerableframework.com/",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "git+https://github.com/pathlyapp/steerable-framework.git",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"README.md"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@steerable/agent-protocol": "0.2.
|
|
32
|
+
"@steerable/agent-protocol": "0.2.5"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"typescript": "^5.8.3",
|