@michengai/dsh-automation 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -4
- package/README.zh-CN.md +16 -4
- package/lib/client.js +80 -32
- package/lib/client.js.map +3 -3
- package/lib/index.js +68 -8
- package/lib/types/client/AutomationView.d.ts +1 -1
- package/lib/types/client/contracts.d.ts +3 -1
- package/lib/types/client/create-modal-logic.d.ts +3 -0
- package/lib/types/client/create-modal.d.ts +6 -1
- package/lib/types/client/helpers.d.ts +2 -2
- package/lib/types/client/locales.d.ts +0 -8
- package/lib/types/client/permissions.d.ts +4 -0
- package/lib/types/client/protocol.d.ts +8 -1
- package/lib/types/executor.d.ts +3 -0
- package/lib/types/index.d.ts +2 -6
- package/lib/types/permission-presets.d.ts +14 -0
- package/lib/types/service.d.ts +10 -0
- package/lib/types/types.d.ts +2 -1
- package/package.json +3 -4
package/lib/index.js
CHANGED
|
@@ -123,6 +123,8 @@ async function snapshotValue(service, payload, signal) {
|
|
|
123
123
|
models: snapshot.models,
|
|
124
124
|
defaultModel: snapshot.defaultModel,
|
|
125
125
|
skills: snapshot.skills,
|
|
126
|
+
permissions: snapshot.permissions,
|
|
127
|
+
defaultPermission: snapshot.defaultPermission,
|
|
126
128
|
automations: snapshot.definitions.map((definition) => ({
|
|
127
129
|
id: definition.id,
|
|
128
130
|
revision: definition.revision,
|
|
@@ -21570,7 +21572,7 @@ var automationScheduleSchema = external_exports.discriminatedUnion("kind", [
|
|
|
21570
21572
|
timeZone
|
|
21571
21573
|
})
|
|
21572
21574
|
]);
|
|
21573
|
-
var permissionPreset =
|
|
21575
|
+
var permissionPreset = nonBlank;
|
|
21574
21576
|
var creator = external_exports.object({ kind: external_exports.enum(["agent", "web"]), sessionId: nonBlank });
|
|
21575
21577
|
var targetSnapshot = external_exports.object({
|
|
21576
21578
|
workspaceId: nonBlank,
|
|
@@ -21756,7 +21758,6 @@ function positiveInteger(value, field) {
|
|
|
21756
21758
|
// src/executor.ts
|
|
21757
21759
|
import { installModelSelection } from "@deepseek-ai/dsh-agent";
|
|
21758
21760
|
import { createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
21759
|
-
import { setSandboxMode } from "@deepseek-ai/dsh-sandbox-policy";
|
|
21760
21761
|
import { SessionId } from "@deepseek-ai/dsh-session";
|
|
21761
21762
|
import { setApprovalPolicy } from "@deepseek-ai/dsh-user-approval";
|
|
21762
21763
|
import { WorkspaceId } from "@deepseek-ai/dsh-workspace";
|
|
@@ -21801,6 +21802,10 @@ function unattendedToolGuardReason(name2, args) {
|
|
|
21801
21802
|
}
|
|
21802
21803
|
return UNATTENDED_TOOL_ALLOWLIST.has(name2) ? void 0 : `\u5DE5\u5177 '${name2}' \u4E0D\u5728\u65E0\u4EBA\u503C\u5B88\u81EA\u52A8\u5316\u5141\u8BB8\u5217\u8868\u4E2D\u3002`;
|
|
21803
21804
|
}
|
|
21805
|
+
function applyUnattendedPermission(presets, session, permission) {
|
|
21806
|
+
presets.set(session, permission);
|
|
21807
|
+
setApprovalPolicy(session, "never");
|
|
21808
|
+
}
|
|
21804
21809
|
function summarizeRun(events, firstSeq) {
|
|
21805
21810
|
let started = false;
|
|
21806
21811
|
let text = "";
|
|
@@ -21870,8 +21875,7 @@ async function executeAutomationRun(ctx, definition, run, config2) {
|
|
|
21870
21875
|
installModelSelection(agentCtx, { current: selection, assembled: void 0 });
|
|
21871
21876
|
const agent = agentCtx.agent;
|
|
21872
21877
|
if (agent === void 0) throw new Error("automation setup has no scoped Agent");
|
|
21873
|
-
|
|
21874
|
-
setApprovalPolicy(agent.session, "never");
|
|
21878
|
+
applyUnattendedPermission(ctx.permissionPresets, agent.session, target.permissionPreset);
|
|
21875
21879
|
agentCtx.tools.guard((exec) => unattendedToolGuardReason(exec.name, exec.arguments));
|
|
21876
21880
|
}
|
|
21877
21881
|
}));
|
|
@@ -21971,6 +21975,15 @@ function pinAutomationSessionTitle(ctx, session, title) {
|
|
|
21971
21975
|
}
|
|
21972
21976
|
}
|
|
21973
21977
|
|
|
21978
|
+
// src/permission-presets.ts
|
|
21979
|
+
function normalizePermissionPreset(input, names) {
|
|
21980
|
+
if (typeof input !== "string") return void 0;
|
|
21981
|
+
const raw = input.trim();
|
|
21982
|
+
if (raw === "") return void 0;
|
|
21983
|
+
const value = raw === "full-access" ? "danger-full-access" : raw;
|
|
21984
|
+
return names.includes(value) ? value : void 0;
|
|
21985
|
+
}
|
|
21986
|
+
|
|
21974
21987
|
// src/service.ts
|
|
21975
21988
|
var MAX_TIMER_DELAY_MS = 2147483647;
|
|
21976
21989
|
var AUTOMATION_SESSION_PREFIX = "dsh-automation-session-";
|
|
@@ -22007,6 +22020,7 @@ var AutomationService = class _AutomationService {
|
|
|
22007
22020
|
const service = new _AutomationService(ctx, domain2, config2);
|
|
22008
22021
|
service.definitions = domain2.table("definitions");
|
|
22009
22022
|
service.runs = domain2.table("runs");
|
|
22023
|
+
await service.migratePermissionPresets();
|
|
22010
22024
|
await service.recoverInterruptedRuns();
|
|
22011
22025
|
await service.reconcileMissingSessions();
|
|
22012
22026
|
await service.pruneAllHistory();
|
|
@@ -22031,6 +22045,19 @@ var AutomationService = class _AutomationService {
|
|
|
22031
22045
|
return typeof source === "object" && source !== null && source.kind === "automation";
|
|
22032
22046
|
});
|
|
22033
22047
|
}
|
|
22048
|
+
permissionNames() {
|
|
22049
|
+
return this.permissionPresets().names;
|
|
22050
|
+
}
|
|
22051
|
+
permissionOptions() {
|
|
22052
|
+
const presets = this.permissionPresets();
|
|
22053
|
+
return presets.names.map((name2) => presets.optionOf(name2));
|
|
22054
|
+
}
|
|
22055
|
+
defaultPermission() {
|
|
22056
|
+
const presets = this.permissionPresets();
|
|
22057
|
+
const value = normalizePermissionPreset(presets.defaultPreset, presets.names);
|
|
22058
|
+
if (value === void 0) throw new Error("Host \u7684\u9ED8\u8BA4\u6743\u9650\u9884\u8BBE\u4E0D\u5728\u5B98\u65B9\u6743\u9650\u5217\u8868\u4E2D\u3002");
|
|
22059
|
+
return value;
|
|
22060
|
+
}
|
|
22034
22061
|
async dispose() {
|
|
22035
22062
|
this.stopping = true;
|
|
22036
22063
|
this.clearTimer();
|
|
@@ -22058,6 +22085,8 @@ var AutomationService = class _AutomationService {
|
|
|
22058
22085
|
models: options.models,
|
|
22059
22086
|
defaultModel: options.defaultModel,
|
|
22060
22087
|
skills: options.skills,
|
|
22088
|
+
permissions: this.permissionOptions(),
|
|
22089
|
+
defaultPermission: this.defaultPermission(),
|
|
22061
22090
|
definitions: definitions.map((definition) => ({
|
|
22062
22091
|
...definition,
|
|
22063
22092
|
nextRunAt: definition.status === "active" ? nextOccurrence(definition.schedule, now2) : null,
|
|
@@ -22086,7 +22115,7 @@ var AutomationService = class _AutomationService {
|
|
|
22086
22115
|
provider: target.provider,
|
|
22087
22116
|
model: target.model,
|
|
22088
22117
|
...request.reasoningEffort === void 0 ? {} : { reasoningEffort: request.reasoningEffort },
|
|
22089
|
-
permissionPreset: request.permissionPreset
|
|
22118
|
+
permissionPreset: this.requirePermission(request.permissionPreset),
|
|
22090
22119
|
createdBy: { kind: scope.creatorKind, sessionId: scope.sessionId },
|
|
22091
22120
|
now: now2
|
|
22092
22121
|
});
|
|
@@ -22102,11 +22131,12 @@ var AutomationService = class _AutomationService {
|
|
|
22102
22131
|
throwIfCancelled(signal);
|
|
22103
22132
|
const now2 = toIso();
|
|
22104
22133
|
const { status, ...fields } = input;
|
|
22134
|
+
const normalizedFields = fields.permissionPreset === void 0 ? fields : { ...fields, permissionPreset: this.requirePermission(fields.permissionPreset) };
|
|
22105
22135
|
if (fields.schedule?.kind === "once" && nextOccurrence(fields.schedule, now2) === null) {
|
|
22106
22136
|
throw new Error("\u4E00\u6B21\u6027\u81EA\u52A8\u5316\u5FC5\u987B\u5B89\u6392\u5728\u672A\u6765\u65F6\u95F4\u3002");
|
|
22107
22137
|
}
|
|
22108
22138
|
const statusChanged = status !== void 0 && status !== current.status;
|
|
22109
|
-
const value = Object.keys(
|
|
22139
|
+
const value = Object.keys(normalizedFields).length === 0 && !statusChanged ? current : updateDefinition(current, { ...normalizedFields, ...status === void 0 ? {} : { status }, now: now2 });
|
|
22110
22140
|
if (value !== current) await this.definitions.put(id, value);
|
|
22111
22141
|
return value;
|
|
22112
22142
|
}, signal);
|
|
@@ -22463,6 +22493,34 @@ var AutomationService = class _AutomationService {
|
|
|
22463
22493
|
});
|
|
22464
22494
|
return result;
|
|
22465
22495
|
}
|
|
22496
|
+
permissionPresets() {
|
|
22497
|
+
return this.ctx.permissionPresets;
|
|
22498
|
+
}
|
|
22499
|
+
requirePermission(input) {
|
|
22500
|
+
const presets = this.permissionPresets();
|
|
22501
|
+
if (input === void 0) return this.defaultPermission();
|
|
22502
|
+
const value = normalizePermissionPreset(input, presets.names);
|
|
22503
|
+
if (value === void 0) throw new Error(`unknown permission preset '${input}'`);
|
|
22504
|
+
return value;
|
|
22505
|
+
}
|
|
22506
|
+
/** 把旧版 full-access 及已移除的预设收敛到 Host 当前可用列表。 */
|
|
22507
|
+
async migratePermissionPresets() {
|
|
22508
|
+
const presets = this.permissionPresets();
|
|
22509
|
+
const fallback = this.defaultPermission();
|
|
22510
|
+
for (const [id, definition] of this.definitions.entries()) {
|
|
22511
|
+
const permissionPreset2 = normalizePermissionPreset(definition.permissionPreset, presets.names) ?? fallback;
|
|
22512
|
+
if (permissionPreset2 === definition.permissionPreset) continue;
|
|
22513
|
+
await this.definitions.put(id, { ...definition, permissionPreset: permissionPreset2 });
|
|
22514
|
+
}
|
|
22515
|
+
for (const [id, run] of this.runs.entries()) {
|
|
22516
|
+
const permissionPreset2 = normalizePermissionPreset(run.targetSnapshot.permissionPreset, presets.names) ?? fallback;
|
|
22517
|
+
if (permissionPreset2 === run.targetSnapshot.permissionPreset) continue;
|
|
22518
|
+
await this.runs.put(id, {
|
|
22519
|
+
...run,
|
|
22520
|
+
targetSnapshot: { ...run.targetSnapshot, permissionPreset: permissionPreset2 }
|
|
22521
|
+
});
|
|
22522
|
+
}
|
|
22523
|
+
}
|
|
22466
22524
|
async recoverInterruptedRuns() {
|
|
22467
22525
|
const finishedAt = toIso();
|
|
22468
22526
|
for (const [id, run] of this.runs.entries()) {
|
|
@@ -22630,6 +22688,7 @@ function scheduleFromArgs(args, now2) {
|
|
|
22630
22688
|
}
|
|
22631
22689
|
function registerAutomationTools(service, agent) {
|
|
22632
22690
|
const scope = { sessionId: agent.id, creatorKind: "agent" };
|
|
22691
|
+
const permissionNames = [...service.permissionNames()];
|
|
22633
22692
|
const disposers = [];
|
|
22634
22693
|
const register = (definition) => {
|
|
22635
22694
|
disposers.push(agent.ctx.tools.register(definition));
|
|
@@ -22647,7 +22706,7 @@ function registerAutomationTools(service, agent) {
|
|
|
22647
22706
|
every_minutes: { type: "integer", description: "\u95F4\u9694\u8BA1\u5212\u7684\u5206\u949F\u6570\uFF0C\u6700\u5C0F 5\u3002" },
|
|
22648
22707
|
time: { type: "string", description: "\u6BCF\u5929\u6216\u6BCF\u5468\u8BA1\u5212\u7684\u672C\u5730 HH:mm\u3002" },
|
|
22649
22708
|
weekdays: { type: "array", items: { type: "string", enum: WEEKDAYS2 } },
|
|
22650
|
-
permission: { type: "string", enum:
|
|
22709
|
+
permission: { type: "string", enum: permissionNames }
|
|
22651
22710
|
},
|
|
22652
22711
|
output: JSON_OUTPUT,
|
|
22653
22712
|
async execute(args, exec) {
|
|
@@ -22703,7 +22762,7 @@ function registerAutomationTools(service, agent) {
|
|
|
22703
22762
|
every_minutes: { type: "integer" },
|
|
22704
22763
|
time: { type: "string" },
|
|
22705
22764
|
weekdays: { type: "array", items: { type: "string", enum: WEEKDAYS2 } },
|
|
22706
|
-
permission: { type: "string", enum:
|
|
22765
|
+
permission: { type: "string", enum: permissionNames }
|
|
22707
22766
|
},
|
|
22708
22767
|
output: JSON_OUTPUT,
|
|
22709
22768
|
async execute(args, exec) {
|
|
@@ -22793,6 +22852,7 @@ var inject = [
|
|
|
22793
22852
|
"workspaceRegistry",
|
|
22794
22853
|
"agentDefaultModel",
|
|
22795
22854
|
"agentPresets",
|
|
22855
|
+
"permissionPresets",
|
|
22796
22856
|
"tools",
|
|
22797
22857
|
"connection",
|
|
22798
22858
|
"llm"
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { AutomationViewProps } from './contracts.js';
|
|
2
|
-
export declare function AutomationView({ t, runtime, closeSettings, pickWorkspaceDirectory }: AutomationViewProps): JSX.Element;
|
|
2
|
+
export declare function AutomationView({ t, permissionT, runtime, closeSettings, pickWorkspaceDirectory }: AutomationViewProps): JSX.Element;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { ComponentType, ReactNode } from 'react';
|
|
2
2
|
import type { AutomationLocaleKey } from './locales.js';
|
|
3
3
|
import type { AutomationRuntime } from './runtime.js';
|
|
4
|
+
import type { PermissionTranslate } from './permissions.js';
|
|
4
5
|
export type Translate = (key: AutomationLocaleKey, params?: Record<string, unknown>) => string;
|
|
5
6
|
export interface AutomationViewProps {
|
|
6
7
|
readonly t: Translate;
|
|
8
|
+
readonly permissionT: PermissionTranslate;
|
|
7
9
|
readonly runtime: AutomationRuntime;
|
|
8
10
|
readonly closeSettings?: () => void;
|
|
9
11
|
readonly pickWorkspaceDirectory?: () => Promise<string | null>;
|
|
@@ -49,7 +51,7 @@ export interface ClientContext {
|
|
|
49
51
|
readonly zh: Record<string, string>;
|
|
50
52
|
readonly en: Record<string, string>;
|
|
51
53
|
}): () => void;
|
|
52
|
-
bind(namespace: string):
|
|
54
|
+
bind(namespace: string): (key: string, params?: Record<string, unknown>) => string;
|
|
53
55
|
};
|
|
54
56
|
slots: {
|
|
55
57
|
inject(name: string, register: () => void | (() => void)): void;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import type { AutomationPermission } from './protocol.js';
|
|
1
2
|
/** 新建/编辑弹窗只允许取消或 ESC 关闭,点旁边不能关。 */
|
|
2
3
|
export declare function shouldCloseCreateModal(reason: 'backdrop' | 'escape' | 'cancel'): boolean;
|
|
4
|
+
/** 只有从非完全访问切换到完全访问时才需要风险确认。 */
|
|
5
|
+
export declare function shouldConfirmFullAccess(current: AutomationPermission, next: AutomationPermission): boolean;
|
|
3
6
|
/** 和 Chat 一样:先选目录,取消则不登记;没有手输路径这条路。 */
|
|
4
7
|
export declare function adoptPickedWorkspace(input: {
|
|
5
8
|
readonly pick: () => Promise<string | null>;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { Translate } from './contracts.js';
|
|
2
|
+
import type { PermissionOption } from './protocol.js';
|
|
3
|
+
import { type PermissionTranslate } from './permissions.js';
|
|
2
4
|
import { type AutomationFormState } from './helpers.js';
|
|
3
|
-
export declare function CreateModal({ t, busy, workspaces, models, defaultModel, skills, draft, editing, onClose, onSubmit, onAddWorkspace, pickWorkspaceDirectory, }: {
|
|
5
|
+
export declare function CreateModal({ t, permissionT, busy, workspaces, models, defaultModel, skills, permissions, defaultPermission, draft, editing, onClose, onSubmit, onAddWorkspace, pickWorkspaceDirectory, }: {
|
|
4
6
|
readonly t: Translate;
|
|
7
|
+
readonly permissionT: PermissionTranslate;
|
|
5
8
|
readonly busy: boolean;
|
|
6
9
|
readonly workspaces: readonly {
|
|
7
10
|
id: string;
|
|
@@ -22,6 +25,8 @@ export declare function CreateModal({ t, busy, workspaces, models, defaultModel,
|
|
|
22
25
|
id: string;
|
|
23
26
|
name: string;
|
|
24
27
|
}[];
|
|
28
|
+
readonly permissions: readonly PermissionOption[];
|
|
29
|
+
readonly defaultPermission: string;
|
|
25
30
|
readonly draft?: Partial<AutomationFormState>;
|
|
26
31
|
readonly editing?: boolean;
|
|
27
32
|
readonly onClose: () => void;
|
|
@@ -35,7 +35,7 @@ export declare function insertSkillGesture(prompt: string, token: string, caret:
|
|
|
35
35
|
readonly caret: number;
|
|
36
36
|
};
|
|
37
37
|
export declare function localDateTimeValue(date?: Date): string;
|
|
38
|
-
export declare function defaultFormState(now?: Date, workspaces?: readonly WorkspaceOption[], defaultModel?: ModelOption | null): AutomationFormState;
|
|
38
|
+
export declare function defaultFormState(now?: Date, workspaces?: readonly WorkspaceOption[], defaultModel?: ModelOption | null, defaultPermission?: string): AutomationFormState;
|
|
39
39
|
export declare function buildCreateInput(form: AutomationFormState, workspaces: readonly WorkspaceOption[], models: readonly ModelOption[], now?: Date, options?: {
|
|
40
40
|
readonly allowPastOnce?: boolean;
|
|
41
41
|
}): CreateAutomationInput;
|
|
@@ -63,5 +63,5 @@ export interface HistoryGroup {
|
|
|
63
63
|
readonly items: readonly import('./protocol.js').AutomationRunViewModel[];
|
|
64
64
|
}
|
|
65
65
|
export declare function groupHistory(runs: readonly import('./protocol.js').AutomationRunViewModel[], range: HistoryRange, now: Date, t: Translate): HistoryGroup[];
|
|
66
|
-
export declare function formFromAutomation(item: import('./protocol.js').AutomationViewModel, workspaces?: readonly WorkspaceOption[], defaultModel?: ModelOption | null): AutomationFormState;
|
|
66
|
+
export declare function formFromAutomation(item: import('./protocol.js').AutomationViewModel, workspaces?: readonly WorkspaceOption[], defaultModel?: ModelOption | null, defaultPermission?: string): AutomationFormState;
|
|
67
67
|
export declare function prettyModelName(model: string): string;
|
|
@@ -134,11 +134,6 @@ export declare const en: {
|
|
|
134
134
|
readonly 'form.days': "Weekdays";
|
|
135
135
|
readonly 'form.timeZone': "Time zone";
|
|
136
136
|
readonly 'form.permission': "Permission boundary";
|
|
137
|
-
readonly 'form.readOnly': "Read Only";
|
|
138
|
-
readonly 'form.readOnlyHint': "Inspect the workspace without changing files.";
|
|
139
|
-
readonly 'form.workspaceWrite': "Workspace Write";
|
|
140
|
-
readonly 'form.fullAccess': "Full access";
|
|
141
|
-
readonly 'form.workspaceWriteHint': "May change files in this workspace; past approvals are not reused.";
|
|
142
137
|
readonly 'form.cancel': "Cancel";
|
|
143
138
|
readonly 'form.submit': "Create automation";
|
|
144
139
|
readonly 'form.submitting': "Creating…";
|
|
@@ -166,9 +161,6 @@ export declare const en: {
|
|
|
166
161
|
readonly 'card.nextRun': "Next";
|
|
167
162
|
readonly 'card.lastRun': "Last";
|
|
168
163
|
readonly 'card.never': "Not yet run";
|
|
169
|
-
readonly 'card.permission.read-only': "Read-only";
|
|
170
|
-
readonly 'card.permission.workspace-write': "Workspace write";
|
|
171
|
-
readonly 'card.permission.full-access': "Full access";
|
|
172
164
|
readonly 'schedule.onceAt': "Once · {time}";
|
|
173
165
|
readonly 'schedule.everyMinutes': "Every {count} minutes";
|
|
174
166
|
readonly 'schedule.dailyAt': "Daily · {time}";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { PermissionOption } from './protocol.js';
|
|
2
|
+
export type PermissionTranslate = (key: string, params?: Record<string, unknown>) => string;
|
|
3
|
+
/** 与 Chat 一致:只本地化官方内置原名,自定义预设保留 Host 提供的名称。 */
|
|
4
|
+
export declare function permissionLabel(option: PermissionOption, t: PermissionTranslate): string;
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
/** Web 客户端与 Host RPC 共享的 JSON 契约。 */
|
|
2
2
|
export type AutomationStatus = 'active' | 'paused';
|
|
3
3
|
export type AutomationRunStatus = 'queued' | 'running' | 'succeeded' | 'failed' | 'skipped' | 'cancelled' | 'interrupted';
|
|
4
|
-
export type AutomationPermission =
|
|
4
|
+
export type AutomationPermission = string;
|
|
5
|
+
export interface PermissionOption {
|
|
6
|
+
readonly value: string;
|
|
7
|
+
readonly name: string;
|
|
8
|
+
readonly description?: string;
|
|
9
|
+
}
|
|
5
10
|
export type AutomationSchedule = {
|
|
6
11
|
readonly kind: 'once';
|
|
7
12
|
readonly at: string;
|
|
@@ -93,6 +98,8 @@ export interface AutomationSnapshot {
|
|
|
93
98
|
readonly id: string;
|
|
94
99
|
readonly name: string;
|
|
95
100
|
}[];
|
|
101
|
+
readonly permissions: readonly PermissionOption[];
|
|
102
|
+
readonly defaultPermission: string;
|
|
96
103
|
readonly automations: readonly AutomationViewModel[];
|
|
97
104
|
readonly runs: readonly AutomationRunViewModel[];
|
|
98
105
|
readonly serverNow: string;
|
package/lib/types/executor.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** 已认领 run 的独立 Agent 执行边界。 */
|
|
2
2
|
import type { Context } from '@deepseek-ai/cordis';
|
|
3
|
+
import type { PermissionPresetService } from './permission-presets.ts';
|
|
3
4
|
import type { AutomationDefinition, AutomationRun } from './types.ts';
|
|
4
5
|
interface SessionEventLike {
|
|
5
6
|
readonly seq: number;
|
|
@@ -21,6 +22,8 @@ export interface ExecutorConfig {
|
|
|
21
22
|
readonly sessionId: string;
|
|
22
23
|
readonly signal?: AbortSignal;
|
|
23
24
|
}
|
|
25
|
+
/** 先应用官方预设的完整语义,再让无人值守审批 fail-closed。 */
|
|
26
|
+
export declare function applyUnattendedPermission(presets: PermissionPresetService, session: unknown, permission: AutomationDefinition['permissionPreset']): void;
|
|
24
27
|
export declare function summarizeRun(events: readonly SessionEventLike[], firstSeq: number): {
|
|
25
28
|
readonly text: string;
|
|
26
29
|
readonly reason?: Record<string, any>;
|
package/lib/types/index.d.ts
CHANGED
|
@@ -16,14 +16,10 @@ export interface ApprovalPolicyReader {
|
|
|
16
16
|
};
|
|
17
17
|
overrideOf?(session: unknown): SessionApprovalPolicy | undefined;
|
|
18
18
|
}
|
|
19
|
-
/**
|
|
20
|
-
* 读会话审批策略。官方三档对应:
|
|
21
|
-
* Read Only / Workspace Write → ask
|
|
22
|
-
* Full access → never
|
|
23
|
-
*/
|
|
19
|
+
/** 读取当前会话实际审批策略;自定义权限预设也以 Host 投影结果为准。 */
|
|
24
20
|
export declare function sessionApprovalPolicy(approval: ApprovalPolicyReader | undefined, session: unknown): SessionApprovalPolicy | undefined;
|
|
25
21
|
/**
|
|
26
|
-
*
|
|
22
|
+
* 只在实际 ask 策略下二次确认。never 策略再 ask,
|
|
27
23
|
* 会被映射成 “the user rejected tool”,且不会弹窗。
|
|
28
24
|
*/
|
|
29
25
|
export declare function needsHumanApproval(exec: {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Host 官方权限预设服务的最小结构契约。 */
|
|
2
|
+
export interface PermissionOption {
|
|
3
|
+
readonly value: string;
|
|
4
|
+
readonly name: string;
|
|
5
|
+
readonly description?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface PermissionPresetService {
|
|
8
|
+
readonly names: readonly string[];
|
|
9
|
+
readonly defaultPreset: string;
|
|
10
|
+
optionOf(name: string): PermissionOption;
|
|
11
|
+
set(session: unknown, name: string): void;
|
|
12
|
+
}
|
|
13
|
+
/** 兼容旧版插件曾保存的 full-access 名称,其余值必须来自 Host 当前列表。 */
|
|
14
|
+
export declare function normalizePermissionPreset(input: unknown, names: readonly string[]): string | undefined;
|
package/lib/types/service.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** 持久化定义、occurrence 认领、时钟与执行调度。 */
|
|
2
2
|
import type { Context } from '@deepseek-ai/cordis';
|
|
3
|
+
import { type PermissionOption } from './permission-presets.ts';
|
|
3
4
|
import type { AutomationDefinition, AutomationRun, AutomationSchedule, PermissionPreset, UpdateAutomationInput } from './types.ts';
|
|
4
5
|
export declare const AUTOMATION_SESSION_PREFIX = "dsh-automation-session-";
|
|
5
6
|
export interface AutomationConfig {
|
|
@@ -45,6 +46,8 @@ export interface AutomationSnapshot {
|
|
|
45
46
|
readonly id: string;
|
|
46
47
|
readonly name: string;
|
|
47
48
|
}[];
|
|
49
|
+
readonly permissions: readonly PermissionOption[];
|
|
50
|
+
readonly defaultPermission: string;
|
|
48
51
|
readonly definitions: readonly AutomationDefinitionView[];
|
|
49
52
|
readonly runs: readonly AutomationRun[];
|
|
50
53
|
}
|
|
@@ -73,6 +76,9 @@ export declare class AutomationService {
|
|
|
73
76
|
static open(ctx: Context, config: AutomationConfig): Promise<AutomationService>;
|
|
74
77
|
start(): void;
|
|
75
78
|
ownsSession(sessionId: string, events?: readonly SessionEventLike[]): boolean;
|
|
79
|
+
permissionNames(): readonly string[];
|
|
80
|
+
permissionOptions(): readonly PermissionOption[];
|
|
81
|
+
defaultPermission(): string;
|
|
76
82
|
dispose(): Promise<void>;
|
|
77
83
|
snapshot(scope: AutomationScope, signal?: AbortSignal): Promise<AutomationSnapshot>;
|
|
78
84
|
create(scope: AutomationScope, request: CreateRequest, signal?: AbortSignal): Promise<AutomationDefinition>;
|
|
@@ -105,6 +111,10 @@ export declare class AutomationService {
|
|
|
105
111
|
private armRetryTimer;
|
|
106
112
|
private clearTimer;
|
|
107
113
|
private serialize;
|
|
114
|
+
private permissionPresets;
|
|
115
|
+
private requirePermission;
|
|
116
|
+
/** 把旧版 full-access 及已移除的预设收敛到 Host 当前可用列表。 */
|
|
117
|
+
private migratePermissionPresets;
|
|
108
118
|
private recoverInterruptedRuns;
|
|
109
119
|
private pruneWorkspaceHistory;
|
|
110
120
|
private pruneAllHistory;
|
package/lib/types/types.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export type AutomationStatus = 'active' | 'paused';
|
|
2
2
|
export type AutomationRunStatus = 'queued' | 'running' | 'succeeded' | 'failed' | 'skipped' | 'cancelled';
|
|
3
3
|
export type Weekday = 'MO' | 'TU' | 'WE' | 'TH' | 'FR' | 'SA' | 'SU';
|
|
4
|
-
|
|
4
|
+
/** 权限预设名称由 Host 的 permissionPresets 服务动态提供。 */
|
|
5
|
+
export type PermissionPreset = string;
|
|
5
6
|
export interface OnceSchedule {
|
|
6
7
|
readonly kind: 'once';
|
|
7
8
|
readonly at: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@michengai/dsh-automation",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "在独立 DSH Session 中按计划执行编码任务,支持 Web 设置页与 Agent 双入口管理。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
},
|
|
19
19
|
"files": [
|
|
20
20
|
"lib",
|
|
21
|
-
"assets",
|
|
21
|
+
"assets",
|
|
22
22
|
"docs",
|
|
23
23
|
"cordis.patch.yml",
|
|
24
24
|
"README.md",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"@deepseek-ai/dsh-client-ui-conversation": ">=0.1.0-rc.5 <0.2.0",
|
|
75
75
|
"@deepseek-ai/dsh-client-ui-settings": ">=0.1.0-rc.5 <0.2.0",
|
|
76
76
|
"@deepseek-ai/dsh-llm": ">=0.1.0-rc.5 <0.2.0",
|
|
77
|
-
"@deepseek-ai/dsh-
|
|
77
|
+
"@deepseek-ai/dsh-permission-presets": ">=0.1.0-rc.5 <0.2.0",
|
|
78
78
|
"@deepseek-ai/dsh-session": ">=0.1.0-rc.5 <0.2.0",
|
|
79
79
|
"@deepseek-ai/dsh-storage-domain": ">=0.1.0-rc.5 <0.2.0",
|
|
80
80
|
"@deepseek-ai/dsh-tools": ">=0.1.0-rc.5 <0.2.0",
|
|
@@ -110,4 +110,3 @@
|
|
|
110
110
|
"registry": "https://registry.npmjs.org/"
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
|
-
|