@trkbt10/sier-llm-skills 0.2.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 +191 -0
- package/README.md +295 -0
- package/dist/browser-control/cdp/cdp-capture.d.ts +3 -0
- package/dist/browser-control/chrome-mcp/chrome-mcp-capture.d.ts +3 -0
- package/dist/browser-control/headless/headless-capture.d.ts +45 -0
- package/dist/browser-control/types.d.ts +37 -0
- package/dist/evidence-io/xlsx-image-patcher.d.ts +35 -0
- package/dist/evidence-io/xlsx-reader.d.ts +35 -0
- package/dist/evidence-io/xlsx-writer.d.ts +4 -0
- package/dist/evidence-schema/schema-validator.d.ts +3 -0
- package/dist/evidence-schema/types.d.ts +81 -0
- package/dist/evidence-server-B6i7fzMM.js +6813 -0
- package/dist/evidence-xlsx/image-to-drawing.d.ts +33 -0
- package/dist/evidence-xlsx/png.d.ts +17 -0
- package/dist/evidence-xlsx/schema-driven-sheets.d.ts +29 -0
- package/dist/evidence-xlsx/xlsx-builder.d.ts +10 -0
- package/dist/evidence-xlsx/xlsx-cells.d.ts +26 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +159 -0
- package/dist/mcp/evidence-server.d.ts +9 -0
- package/dist/mcp/serve.d.ts +8 -0
- package/dist/mcp-serve.js +17 -0
- package/dist/operation-capture/cdp-recorder.d.ts +18 -0
- package/dist/operation-capture/recording-session.d.ts +25 -0
- package/dist/operation-record/operation-io.d.ts +5 -0
- package/dist/operation-record/operation-types.d.ts +63 -0
- package/dist/operation-replay/history-to-evidence.d.ts +8 -0
- package/dist/operation-replay/replay.d.ts +4 -0
- package/package.json +73 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { XlsxDrawingAnchor } from 'aurochs/xlsx/domain';
|
|
2
|
+
import { MediaPart } from 'aurochs/xlsx/builder';
|
|
3
|
+
/** 画像配置の入力仕様。 */
|
|
4
|
+
export type ImageSpec = {
|
|
5
|
+
/** 画像データ。 */
|
|
6
|
+
readonly data: Uint8Array;
|
|
7
|
+
/** スクリーンショットフォーマット ("png" | "jpeg" | "webp")。 */
|
|
8
|
+
readonly format: string;
|
|
9
|
+
/** アンカー開始列 (1-based)。 */
|
|
10
|
+
readonly fromCol: number;
|
|
11
|
+
/** アンカー開始行 (1-based)。 */
|
|
12
|
+
readonly fromRow: number;
|
|
13
|
+
/** アンカー終了列 (1-based)。 */
|
|
14
|
+
readonly toCol: number;
|
|
15
|
+
/** アンカー終了行 (1-based)。 */
|
|
16
|
+
readonly toRow: number;
|
|
17
|
+
/** 表示名。 */
|
|
18
|
+
readonly name?: string;
|
|
19
|
+
};
|
|
20
|
+
/** Drawing ドメインオブジェクト変換結果。 */
|
|
21
|
+
export type DrawingResult = {
|
|
22
|
+
readonly anchors: readonly XlsxDrawingAnchor[];
|
|
23
|
+
readonly mediaMap: Map<string, MediaPart>;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* 画像配置仕様から XlsxDrawingAnchor + MediaPart を構築する。
|
|
27
|
+
*
|
|
28
|
+
* relId 生成、twoCellAnchor 構築、MediaPart 紐付けの SoT。
|
|
29
|
+
*
|
|
30
|
+
* @see ECMA-376 Part 4, Section 20.5.2.33 (twoCellAnchor)
|
|
31
|
+
* @see ECMA-376 Part 2, Section 9 (Relationships)
|
|
32
|
+
*/
|
|
33
|
+
export declare function buildDrawingFromImages(images: readonly ImageSpec[]): DrawingResult;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { XlsxExtent } from 'aurochs/xlsx/domain';
|
|
2
|
+
/**
|
|
3
|
+
* PNG ヘッダーから幅と高さを読み取る。
|
|
4
|
+
*
|
|
5
|
+
* PNG signature (8 bytes) + IHDR chunk: length(4) + "IHDR"(4) + width(4) + height(4)
|
|
6
|
+
*/
|
|
7
|
+
export declare function readPngDimensions(data: Uint8Array): {
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
} | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* 画像データから表示用 EMU extent を計算する。
|
|
13
|
+
* 指定幅に固定し、アスペクト比を維持する。
|
|
14
|
+
*/
|
|
15
|
+
export declare function computeImageExtent(imageData: Uint8Array, displayWidthEmu?: number): XlsxExtent;
|
|
16
|
+
/** スクリーンショット形式から MIME タイプを返す。 */
|
|
17
|
+
export declare function screenshotFormatToMime(format: string): string;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { XlsxWorksheet } from 'aurochs/xlsx/domain';
|
|
2
|
+
import { MediaPart } from 'aurochs/xlsx/builder';
|
|
3
|
+
import { EvidenceTestCase, EvidenceStep, EvidenceSheetSchema } from '../evidence-schema/types';
|
|
4
|
+
/** シート構築結果。 */
|
|
5
|
+
export type EvidenceSheetResult = {
|
|
6
|
+
readonly sheet: XlsxWorksheet;
|
|
7
|
+
readonly mediaMap: Map<string, MediaPart>;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* 既知のフィールド名からステップ/テストケースの値を解決する。
|
|
11
|
+
*
|
|
12
|
+
* 未知のフィールドは空文字列を返す (LLM が write_test_result で埋める想定)。
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveFieldValue(field: string, step: EvidenceStep, testCase: EvidenceTestCase): string;
|
|
15
|
+
/**
|
|
16
|
+
* スキーマ定義に基づいてエビデンスシートを構築する。
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildEvidenceSheetFromSchema(schemaEvidence: EvidenceSheetSchema["evidenceSheet"], testCases: readonly EvidenceTestCase[]): EvidenceSheetResult;
|
|
19
|
+
/**
|
|
20
|
+
* 表紙シートのフィールドからセル更新リストを返す。
|
|
21
|
+
*
|
|
22
|
+
* 実際の値は LLM が write_test_result で埋めるため、
|
|
23
|
+
* ここではフィールド定義から位置情報のみを抽出する。
|
|
24
|
+
*/
|
|
25
|
+
export declare function buildCoverSheetValues(schema: EvidenceSheetSchema["coverSheet"]): Array<{
|
|
26
|
+
col: string;
|
|
27
|
+
row: number;
|
|
28
|
+
value: string | number;
|
|
29
|
+
}>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { EvidenceReport, EvidenceSheetSchema } from '../evidence-schema/types';
|
|
2
|
+
/** buildEvidenceXlsx のオプション。 */
|
|
3
|
+
export type BuildEvidenceXlsxOptions = {
|
|
4
|
+
/** LLM が生成したマッピングスキーマ。省略時はデフォルトスキーマで構築する。 */
|
|
5
|
+
readonly schema?: EvidenceSheetSchema;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* EvidenceReport から XLSX ファイルを構築する。
|
|
9
|
+
*/
|
|
10
|
+
export declare function buildEvidenceXlsx(report: EvidenceReport, options?: BuildEvidenceXlsxOptions): Promise<Uint8Array>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { StyleId, Cell, CellValue, XlsxStyleSheet } from 'aurochs/xlsx/domain';
|
|
2
|
+
/** 指定位置にセルを作成する。 */
|
|
3
|
+
export declare function makeCell(col: number, row: number, value: CellValue, style?: StyleId): Cell;
|
|
4
|
+
/** 文字列セルを作成する。 */
|
|
5
|
+
export declare function strCell(col: number, row: number, text: string, style?: StyleId): Cell;
|
|
6
|
+
/** 数値セルを作成する。 */
|
|
7
|
+
export declare function numCell(col: number, row: number, num: number, style?: StyleId): Cell;
|
|
8
|
+
/** 空セルを作成する。 */
|
|
9
|
+
export declare function emptyCell(col: number, row: number, style?: StyleId): Cell;
|
|
10
|
+
/**
|
|
11
|
+
* エビデンス用スタイルシートを構築する。
|
|
12
|
+
*
|
|
13
|
+
* Style ID 対応:
|
|
14
|
+
* 0: デフォルト
|
|
15
|
+
* 1: ヘッダー (白太字 + 青背景 + 罫線)
|
|
16
|
+
* 2: 通常セル + 罫線
|
|
17
|
+
* 3: Pass ステータス (緑太字)
|
|
18
|
+
* 4: Fail ステータス (赤太字)
|
|
19
|
+
* 5: 日時セル
|
|
20
|
+
* 6: 偶数行セル (薄いグレー背景)
|
|
21
|
+
*/
|
|
22
|
+
export declare function buildEvidenceStyleSheet(): XlsxStyleSheet;
|
|
23
|
+
/** Date を "yyyy-mm-dd hh:mm:ss" 文字列に変換する。 */
|
|
24
|
+
export declare function formatDateTime(date: Date): string;
|
|
25
|
+
/** Excel シート名の制約 (31文字以下、特定文字禁止) に従いサニタイズする。 */
|
|
26
|
+
export declare function sanitizeSheetName(name: string): string;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Screenshot Evidence Builder for LLM.
|
|
3
|
+
*
|
|
4
|
+
* ブラウザー操作のスクリーンショットエビデンスを
|
|
5
|
+
* XLSX ファイルとして構築するライブラリ。
|
|
6
|
+
*
|
|
7
|
+
* 3つのキャプチャ戦略:
|
|
8
|
+
* - headless: Playwright ベースのヘッドレスブラウザー
|
|
9
|
+
* - cdp: Chrome DevTools Protocol 直接接続 (Electron 互換)
|
|
10
|
+
* - chrome-mcp: chrome-devtools-mcp (Google 公式 MCP) 経由
|
|
11
|
+
*/
|
|
12
|
+
export { createHeadlessCaptureStrategy } from './browser-control/headless/headless-capture';
|
|
13
|
+
export { createCdpCaptureStrategy } from './browser-control/cdp/cdp-capture';
|
|
14
|
+
export { createChromeMcpCaptureStrategy } from './browser-control/chrome-mcp/chrome-mcp-capture';
|
|
15
|
+
export type { CaptureStrategy, BrowserSession, LaunchOptions, Viewport, ScreenshotOptions, ClipRegion, } from './browser-control/types';
|
|
16
|
+
export { buildEvidenceXlsx } from './evidence-xlsx/xlsx-builder';
|
|
17
|
+
export type { BuildEvidenceXlsxOptions } from './evidence-xlsx/xlsx-builder';
|
|
18
|
+
export type { EvidenceStep, EvidenceTestCase, EvidenceReport, EvidenceSheetSchema, EvidenceColumnDef, ScreenshotPlacement, CoverSheetField, SummaryCells, CellPosition, } from './evidence-schema/types';
|
|
19
|
+
export { validateEvidenceSheetSchema } from './evidence-schema/schema-validator';
|
|
20
|
+
export { resolveFieldValue, buildEvidenceSheetFromSchema, buildCoverSheetValues } from './evidence-xlsx/schema-driven-sheets';
|
|
21
|
+
export type { EvidenceSheetResult } from './evidence-xlsx/schema-driven-sheets';
|
|
22
|
+
export type { BrowserOperation, OperationEntry, OperationHistory, StepDescription, } from './operation-record/operation-types';
|
|
23
|
+
export { serializeHistory, deserializeHistory } from './operation-record/operation-io';
|
|
24
|
+
export { createRecordingSession } from './operation-capture/recording-session';
|
|
25
|
+
export type { RecordingSession, RecordingSessionConfig } from './operation-capture/recording-session';
|
|
26
|
+
export { replayHistory } from './operation-replay/replay';
|
|
27
|
+
export { historyToEvidence } from './operation-replay/history-to-evidence';
|
|
28
|
+
export type { HistoryToEvidenceOptions } from './operation-replay/history-to-evidence';
|
|
29
|
+
export { createCdpRecorder } from './operation-capture/cdp-recorder';
|
|
30
|
+
export type { CdpRecorder, CdpRecorderConfig } from './operation-capture/cdp-recorder';
|
|
31
|
+
export { readXlsxAsText, formatXlsxForLlm, formatSheetForLlm } from './evidence-io/xlsx-reader';
|
|
32
|
+
export type { SheetText, SheetRow, SheetCell, XlsxReadResult } from './evidence-io/xlsx-reader';
|
|
33
|
+
export { updateXlsxCells } from './evidence-io/xlsx-writer';
|
|
34
|
+
export { patchXlsxWithImages } from './evidence-io/xlsx-image-patcher';
|
|
35
|
+
export type { ImageInsert, SheetImagePatch } from './evidence-io/xlsx-image-patcher';
|
|
36
|
+
export { createEvidenceServer } from './mcp/evidence-server';
|
|
37
|
+
export type { EvidenceServerConfig } from './mcp/evidence-server';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { _ as e, a as t, c as n, d as r, f as i, g as a, h as o, i as s, l as c, m as l, n as u, o as d, p as f, r as p, s as m, t as h, u as g, v as _ } from "./evidence-server-B6i7fzMM.js";
|
|
2
|
+
import { Client as v } from "@modelcontextprotocol/sdk/client/index.js";
|
|
3
|
+
import { StdioClientTransport as y } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
4
|
+
//#region src/browser-control/cdp/cdp-capture.ts
|
|
5
|
+
function b() {
|
|
6
|
+
return {
|
|
7
|
+
name: "cdp",
|
|
8
|
+
async launch(e) {
|
|
9
|
+
let t = e?.debugPort ?? 9222, n = e?.viewport ?? {
|
|
10
|
+
width: 1280,
|
|
11
|
+
height: 800
|
|
12
|
+
}, r = await (await import("chrome-remote-interface")).default({ port: t });
|
|
13
|
+
return await r.Page.enable(), await r.Runtime.enable(), await r.DOM.enable(), await r.Emulation.setDeviceMetricsOverride({
|
|
14
|
+
width: n.width,
|
|
15
|
+
height: n.height,
|
|
16
|
+
deviceScaleFactor: 1,
|
|
17
|
+
mobile: !1
|
|
18
|
+
}), {
|
|
19
|
+
async navigate(e) {
|
|
20
|
+
await r.Page.navigate({ url: e }), await r.Page.loadEventFired();
|
|
21
|
+
},
|
|
22
|
+
async screenshot(e) {
|
|
23
|
+
let t = e?.format ?? "png", n = {
|
|
24
|
+
format: t,
|
|
25
|
+
quality: t === "png" ? void 0 : e?.quality,
|
|
26
|
+
captureBeyondViewport: e?.fullPage ?? !1
|
|
27
|
+
};
|
|
28
|
+
e?.clip && (n.clip = {
|
|
29
|
+
x: e.clip.x,
|
|
30
|
+
y: e.clip.y,
|
|
31
|
+
width: e.clip.width,
|
|
32
|
+
height: e.clip.height,
|
|
33
|
+
scale: 1
|
|
34
|
+
});
|
|
35
|
+
let { data: i } = await r.Page.captureScreenshot(n);
|
|
36
|
+
return Uint8Array.from(atob(i), (e) => e.charCodeAt(0));
|
|
37
|
+
},
|
|
38
|
+
async click(e) {
|
|
39
|
+
let { root: t } = await r.DOM.getDocument(), { nodeId: n } = await r.DOM.querySelector({
|
|
40
|
+
nodeId: t.nodeId,
|
|
41
|
+
selector: e
|
|
42
|
+
});
|
|
43
|
+
if (n === 0) throw Error(`Element not found: ${e}`);
|
|
44
|
+
let { model: i } = await r.DOM.getBoxModel({ nodeId: n }), a = (i.content[0] + i.content[2]) / 2, o = (i.content[1] + i.content[5]) / 2;
|
|
45
|
+
await r.Input.dispatchMouseEvent({
|
|
46
|
+
type: "mousePressed",
|
|
47
|
+
x: a,
|
|
48
|
+
y: o,
|
|
49
|
+
button: "left",
|
|
50
|
+
clickCount: 1
|
|
51
|
+
}), await r.Input.dispatchMouseEvent({
|
|
52
|
+
type: "mouseReleased",
|
|
53
|
+
x: a,
|
|
54
|
+
y: o,
|
|
55
|
+
button: "left",
|
|
56
|
+
clickCount: 1
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
async type(e, t) {
|
|
60
|
+
let { root: n } = await r.DOM.getDocument(), { nodeId: i } = await r.DOM.querySelector({
|
|
61
|
+
nodeId: n.nodeId,
|
|
62
|
+
selector: e
|
|
63
|
+
});
|
|
64
|
+
if (i === 0) throw Error(`Element not found: ${e}`);
|
|
65
|
+
let { model: a } = await r.DOM.getBoxModel({ nodeId: i }), o = (a.content[0] + a.content[2]) / 2, s = (a.content[1] + a.content[5]) / 2;
|
|
66
|
+
await r.Input.dispatchMouseEvent({
|
|
67
|
+
type: "mousePressed",
|
|
68
|
+
x: o,
|
|
69
|
+
y: s,
|
|
70
|
+
button: "left",
|
|
71
|
+
clickCount: 1
|
|
72
|
+
}), await r.Input.dispatchMouseEvent({
|
|
73
|
+
type: "mouseReleased",
|
|
74
|
+
x: o,
|
|
75
|
+
y: s,
|
|
76
|
+
button: "left",
|
|
77
|
+
clickCount: 1
|
|
78
|
+
}), await r.Input.insertText({ text: t });
|
|
79
|
+
},
|
|
80
|
+
async evaluate(e) {
|
|
81
|
+
let { result: t } = await r.Runtime.evaluate({
|
|
82
|
+
expression: e,
|
|
83
|
+
returnByValue: !0,
|
|
84
|
+
awaitPromise: !0
|
|
85
|
+
});
|
|
86
|
+
return t.value;
|
|
87
|
+
},
|
|
88
|
+
async close() {
|
|
89
|
+
await r.close();
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/browser-control/chrome-mcp/chrome-mcp-capture.ts
|
|
97
|
+
function x() {
|
|
98
|
+
return {
|
|
99
|
+
name: "chrome-mcp",
|
|
100
|
+
async launch() {
|
|
101
|
+
let e = new y({
|
|
102
|
+
command: "npx",
|
|
103
|
+
args: ["chrome-devtools-mcp@latest"]
|
|
104
|
+
}), t = new v({
|
|
105
|
+
name: "screenshot-evidence",
|
|
106
|
+
version: "0.1.0"
|
|
107
|
+
});
|
|
108
|
+
return await t.connect(e), {
|
|
109
|
+
async navigate(e) {
|
|
110
|
+
await t.callTool({
|
|
111
|
+
name: "navigate_page",
|
|
112
|
+
arguments: { url: e }
|
|
113
|
+
});
|
|
114
|
+
},
|
|
115
|
+
async screenshot() {
|
|
116
|
+
let e = (await t.callTool({
|
|
117
|
+
name: "take_screenshot",
|
|
118
|
+
arguments: {}
|
|
119
|
+
})).content;
|
|
120
|
+
if (!Array.isArray(e)) throw Error("Unexpected MCP response format");
|
|
121
|
+
for (let t of e) if (typeof t == "object" && t && "type" in t && t.type === "image" && "data" in t && typeof t.data == "string") return Uint8Array.from(atob(t.data), (e) => e.charCodeAt(0));
|
|
122
|
+
for (let t of e) if (typeof t == "object" && t && "type" in t && t.type === "text" && "text" in t && typeof t.text == "string") {
|
|
123
|
+
let e = t.text.match(/data:image\/[^;]+;base64,([A-Za-z0-9+/=]+)/);
|
|
124
|
+
if (e) return Uint8Array.from(atob(e[1]), (e) => e.charCodeAt(0));
|
|
125
|
+
}
|
|
126
|
+
throw Error("No screenshot data found in MCP response");
|
|
127
|
+
},
|
|
128
|
+
async click(e) {
|
|
129
|
+
await t.callTool({
|
|
130
|
+
name: "click",
|
|
131
|
+
arguments: { selector: e }
|
|
132
|
+
});
|
|
133
|
+
},
|
|
134
|
+
async type(e, n) {
|
|
135
|
+
await t.callTool({
|
|
136
|
+
name: "fill",
|
|
137
|
+
arguments: {
|
|
138
|
+
selector: e,
|
|
139
|
+
value: n
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
},
|
|
143
|
+
async evaluate(e) {
|
|
144
|
+
let n = (await t.callTool({
|
|
145
|
+
name: "evaluate_script",
|
|
146
|
+
arguments: { script: e }
|
|
147
|
+
})).content;
|
|
148
|
+
if (Array.isArray(n) && n.length > 0 && typeof n[0] == "object" && n[0] !== null && "text" in n[0] && typeof n[0].text == "string") return JSON.parse(n[0].text);
|
|
149
|
+
throw Error("Unexpected evaluate response format");
|
|
150
|
+
},
|
|
151
|
+
async close() {
|
|
152
|
+
await t.close();
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
//#endregion
|
|
159
|
+
export { o as buildCoverSheetValues, a as buildEvidenceSheetFromSchema, l as buildEvidenceXlsx, b as createCdpCaptureStrategy, m as createCdpRecorder, x as createChromeMcpCaptureStrategy, h as createEvidenceServer, _ as createHeadlessCaptureStrategy, g as createRecordingSession, r as deserializeHistory, s as formatSheetForLlm, t as formatXlsxForLlm, n as historyToEvidence, u as patchXlsxWithImages, d as readXlsxAsText, c as replayHistory, e as resolveFieldValue, i as serializeHistory, p as updateXlsxCells, f as validateEvidenceSheetSchema };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import { CaptureStrategy, LaunchOptions } from '../browser-control/types';
|
|
3
|
+
export type EvidenceServerConfig = {
|
|
4
|
+
readonly strategy: CaptureStrategy;
|
|
5
|
+
readonly launchOptions?: LaunchOptions;
|
|
6
|
+
readonly outputDir: string;
|
|
7
|
+
};
|
|
8
|
+
/** 証跡エビデンス MCP サーバーを生成する。 */
|
|
9
|
+
export declare function createEvidenceServer(config: EvidenceServerConfig): Server;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { t as e, v as t } from "./evidence-server-B6i7fzMM.js";
|
|
3
|
+
import { StdioServerTransport as n } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
//#region src/mcp/serve.ts
|
|
5
|
+
var r = process.env.OUTPUT_DIR ?? "./output", i = e({
|
|
6
|
+
strategy: t(async (e) => (await import("playwright")).chromium.launch({ headless: e.headless })),
|
|
7
|
+
launchOptions: {
|
|
8
|
+
headless: !0,
|
|
9
|
+
viewport: {
|
|
10
|
+
width: 1280,
|
|
11
|
+
height: 800
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
outputDir: r
|
|
15
|
+
}), a = new n();
|
|
16
|
+
await i.connect(a);
|
|
17
|
+
//#endregion
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { OperationHistory } from '../operation-record/operation-types';
|
|
2
|
+
export type CdpRecorderConfig = {
|
|
3
|
+
readonly debugPort: number;
|
|
4
|
+
readonly viewport: {
|
|
5
|
+
readonly width: number;
|
|
6
|
+
readonly height: number;
|
|
7
|
+
};
|
|
8
|
+
readonly screenshotFormat?: "png" | "jpeg" | "webp";
|
|
9
|
+
};
|
|
10
|
+
/** CDP 傍受による手動操作レコーダー。 */
|
|
11
|
+
export type CdpRecorder = {
|
|
12
|
+
/** レコーディング開始。 */
|
|
13
|
+
start(): Promise<void>;
|
|
14
|
+
/** レコーディング停止、操作履歴を返す。 */
|
|
15
|
+
stop(title: string): Promise<OperationHistory>;
|
|
16
|
+
};
|
|
17
|
+
/** CdpRecorder を生成する。 */
|
|
18
|
+
export declare function createCdpRecorder(config: CdpRecorderConfig): CdpRecorder;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BrowserSession, ScreenshotOptions } from '../browser-control/types';
|
|
2
|
+
import { OperationEntry, OperationHistory, StepDescription } from '../operation-record/operation-types';
|
|
3
|
+
/** 操作を記録する BrowserSession 拡張。 */
|
|
4
|
+
export type RecordingSession = BrowserSession & {
|
|
5
|
+
/** 蓄積された操作履歴を確定して返す。 */
|
|
6
|
+
finalizeHistory(title: string): OperationHistory;
|
|
7
|
+
/** 現在の操作エントリ一覧。 */
|
|
8
|
+
readonly entries: readonly OperationEntry[];
|
|
9
|
+
/** テスト仕様書の操作手順・期待結果を付与して操作する。 */
|
|
10
|
+
navigateWithStep(url: string, step: StepDescription): Promise<void>;
|
|
11
|
+
clickWithStep(selector: string, step: StepDescription): Promise<void>;
|
|
12
|
+
typeWithStep(selector: string, text: string, step: StepDescription): Promise<void>;
|
|
13
|
+
evaluateWithStep<T>(expression: string, step: StepDescription): Promise<T>;
|
|
14
|
+
screenshotWithStep(step: StepDescription, options?: ScreenshotOptions): Promise<Uint8Array>;
|
|
15
|
+
};
|
|
16
|
+
export type RecordingSessionConfig = {
|
|
17
|
+
readonly inner: BrowserSession;
|
|
18
|
+
readonly viewport: {
|
|
19
|
+
readonly width: number;
|
|
20
|
+
readonly height: number;
|
|
21
|
+
};
|
|
22
|
+
readonly screenshotFormat?: "png" | "jpeg" | "webp";
|
|
23
|
+
};
|
|
24
|
+
/** RecordingSession を生成する。 */
|
|
25
|
+
export declare function createRecordingSession(config: RecordingSessionConfig): RecordingSession;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { OperationHistory } from './operation-types';
|
|
2
|
+
/** OperationHistory を JSON 文字列に変換する。 */
|
|
3
|
+
export declare function serializeHistory(history: OperationHistory): string;
|
|
4
|
+
/** JSON 文字列を OperationHistory に変換する。 */
|
|
5
|
+
export declare function deserializeHistory(json: string): OperationHistory;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { ScreenshotOptions } from '../browser-control/types';
|
|
2
|
+
/** ブラウザに対する個々の操作。 */
|
|
3
|
+
export type BrowserOperation = {
|
|
4
|
+
readonly kind: "navigate";
|
|
5
|
+
readonly url: string;
|
|
6
|
+
} | {
|
|
7
|
+
readonly kind: "click";
|
|
8
|
+
readonly selector: string;
|
|
9
|
+
} | {
|
|
10
|
+
readonly kind: "type";
|
|
11
|
+
readonly selector: string;
|
|
12
|
+
readonly text: string;
|
|
13
|
+
} | {
|
|
14
|
+
readonly kind: "evaluate";
|
|
15
|
+
readonly expression: string;
|
|
16
|
+
} | {
|
|
17
|
+
readonly kind: "screenshot";
|
|
18
|
+
readonly options?: ScreenshotOptions;
|
|
19
|
+
} | {
|
|
20
|
+
readonly kind: "wait";
|
|
21
|
+
readonly ms: number;
|
|
22
|
+
};
|
|
23
|
+
/** テスト仕様書における操作ステップの記述。 */
|
|
24
|
+
export type StepDescription = {
|
|
25
|
+
/** 操作手順 (例: "ログインボタンを押下する")。 */
|
|
26
|
+
readonly action: string;
|
|
27
|
+
/** 期待結果 (例: "ダッシュボード画面に遷移すること")。 */
|
|
28
|
+
readonly expected: string;
|
|
29
|
+
};
|
|
30
|
+
/** 操作実行後のエントリ (操作 + 実行結果メタデータ)。 */
|
|
31
|
+
export type OperationEntry = {
|
|
32
|
+
readonly operation: BrowserOperation;
|
|
33
|
+
/** テスト仕様書の操作手順・期待結果。省略時は operation から自動生成。 */
|
|
34
|
+
readonly step?: StepDescription;
|
|
35
|
+
/** 操作実行時刻 (ISO 8601)。 */
|
|
36
|
+
readonly timestamp: string;
|
|
37
|
+
/** 操作時点の URL。 */
|
|
38
|
+
readonly url: string;
|
|
39
|
+
/** 操作の実行時間 (ms)。 */
|
|
40
|
+
readonly durationMs: number;
|
|
41
|
+
/** 操作後のスクリーンショット。 */
|
|
42
|
+
readonly screenshot?: Uint8Array;
|
|
43
|
+
/** スクリーンショットのフォーマット。 */
|
|
44
|
+
readonly screenshotFormat?: "png" | "jpeg" | "webp";
|
|
45
|
+
/** evaluate の戻り値。 */
|
|
46
|
+
readonly evaluateResult?: unknown;
|
|
47
|
+
/** エラーメッセージ (操作失敗時)。 */
|
|
48
|
+
readonly error?: string;
|
|
49
|
+
};
|
|
50
|
+
/** 操作履歴全体。 */
|
|
51
|
+
export type OperationHistory = {
|
|
52
|
+
readonly version: 1;
|
|
53
|
+
readonly title: string;
|
|
54
|
+
/** セッション開始時刻 (ISO 8601)。 */
|
|
55
|
+
readonly startedAt: string;
|
|
56
|
+
/** セッション終了時刻 (ISO 8601)。 */
|
|
57
|
+
readonly finishedAt?: string;
|
|
58
|
+
readonly viewport: {
|
|
59
|
+
readonly width: number;
|
|
60
|
+
readonly height: number;
|
|
61
|
+
};
|
|
62
|
+
readonly entries: readonly OperationEntry[];
|
|
63
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { EvidenceReport } from '../evidence-schema/types';
|
|
2
|
+
import { OperationHistory } from '../operation-record/operation-types';
|
|
3
|
+
export type HistoryToEvidenceOptions = {
|
|
4
|
+
readonly testCaseName: string;
|
|
5
|
+
readonly testCaseUrl: string;
|
|
6
|
+
};
|
|
7
|
+
/** OperationHistory を EvidenceReport に変換する。 */
|
|
8
|
+
export declare function historyToEvidence(history: OperationHistory, options: HistoryToEvidenceOptions): EvidenceReport;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { BrowserSession } from '../browser-control/types';
|
|
2
|
+
import { OperationHistory } from '../operation-record/operation-types';
|
|
3
|
+
/** 操作履歴を BrowserSession 上で再生し、新たな操作履歴を返す。 */
|
|
4
|
+
export declare function replayHistory(session: BrowserSession, history: OperationHistory): Promise<OperationHistory>;
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@trkbt10/sier-llm-skills",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./mcp": {
|
|
13
|
+
"types": "./dist/mcp-serve.d.ts",
|
|
14
|
+
"import": "./dist/mcp-serve.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"lib",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"bin": {
|
|
23
|
+
"evidence-mcp": "./dist/mcp-serve.js"
|
|
24
|
+
},
|
|
25
|
+
"packageManager": "bun@1.3.11",
|
|
26
|
+
"sideEffects": false,
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "vite build",
|
|
29
|
+
"clean": "rimraf dist",
|
|
30
|
+
"lint": "eslint .",
|
|
31
|
+
"lint:fix": "eslint . --fix",
|
|
32
|
+
"format": "prettier --write .",
|
|
33
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
34
|
+
"test:cov": "vitest run --coverage",
|
|
35
|
+
"test": "vitest --run",
|
|
36
|
+
"serve:mcp": "bun run src/mcp/serve.ts"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@eslint-community/eslint-plugin-eslint-comments": "^4.7.1",
|
|
40
|
+
"@eslint/js": "^10.0.1",
|
|
41
|
+
"@types/node": "^25.5.0",
|
|
42
|
+
"@types/react": "^19.2.14",
|
|
43
|
+
"@typescript-eslint/eslint-plugin": "^8.57.1",
|
|
44
|
+
"@typescript-eslint/parser": "^8.57.1",
|
|
45
|
+
"@vitest/coverage-v8": "^4.1.0",
|
|
46
|
+
"ajv": "^8.18.0",
|
|
47
|
+
"eslint": "^10.0.3",
|
|
48
|
+
"eslint-config-prettier": "^10.1.8",
|
|
49
|
+
"eslint-plugin-import": "^2.32.0",
|
|
50
|
+
"eslint-plugin-jsdoc": "^62.8.0",
|
|
51
|
+
"prettier": "^3.8.1",
|
|
52
|
+
"rimraf": "^6.1.3",
|
|
53
|
+
"typescript": "^5.9.3",
|
|
54
|
+
"typescript-eslint": "^8.57.1",
|
|
55
|
+
"vite": "^8.0.0",
|
|
56
|
+
"vite-plugin-dts": "^4",
|
|
57
|
+
"vitest": "^4.1.0"
|
|
58
|
+
},
|
|
59
|
+
"dependencies": {
|
|
60
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
61
|
+
"aurochs": "0.9.0",
|
|
62
|
+
"chrome-remote-interface": "^0.34.0",
|
|
63
|
+
"fflate": "^0.8.2"
|
|
64
|
+
},
|
|
65
|
+
"peerDependencies": {
|
|
66
|
+
"playwright": ">=1.40.0"
|
|
67
|
+
},
|
|
68
|
+
"peerDependenciesMeta": {
|
|
69
|
+
"playwright": {
|
|
70
|
+
"optional": true
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|