@lnar/cli 0.0.1-dev.5da411d → 0.0.1-dev.632e82b

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.
Files changed (105) hide show
  1. package/README.md +16 -54
  2. package/dist/api-client.d.ts +19 -0
  3. package/dist/api-client.js +40 -0
  4. package/dist/api-client.js.map +1 -1
  5. package/dist/auth.d.ts +20 -0
  6. package/dist/auth.js +74 -0
  7. package/dist/auth.js.map +1 -0
  8. package/dist/browser.d.ts +1 -0
  9. package/dist/browser.js +68 -0
  10. package/dist/browser.js.map +1 -0
  11. package/dist/capture-client.d.ts +13 -0
  12. package/dist/capture-client.js +37 -0
  13. package/dist/capture-client.js.map +1 -0
  14. package/dist/capture-worker.d.ts +14 -0
  15. package/dist/capture-worker.js +105 -0
  16. package/dist/capture-worker.js.map +1 -0
  17. package/dist/cli.js +21 -0
  18. package/dist/cli.js.map +1 -1
  19. package/dist/commands/daemon.d.ts +2 -0
  20. package/dist/commands/daemon.js +114 -1
  21. package/dist/commands/daemon.js.map +1 -1
  22. package/dist/commands/login.d.ts +2 -0
  23. package/dist/commands/login.js +19 -9
  24. package/dist/commands/login.js.map +1 -1
  25. package/dist/commands/record.d.ts +7 -0
  26. package/dist/commands/record.js +117 -0
  27. package/dist/commands/record.js.map +1 -0
  28. package/dist/commands/scan.js +12 -0
  29. package/dist/commands/scan.js.map +1 -1
  30. package/dist/commands/sync.js +3 -0
  31. package/dist/commands/sync.js.map +1 -1
  32. package/dist/commands/up.js +19 -0
  33. package/dist/commands/up.js.map +1 -1
  34. package/dist/machine-id.d.ts +2 -0
  35. package/dist/machine-id.js +48 -0
  36. package/dist/machine-id.js.map +1 -0
  37. package/dist/pending-client.d.ts +1 -1
  38. package/dist/recording/bundle.d.ts +25 -0
  39. package/dist/recording/bundle.js +55 -0
  40. package/dist/recording/bundle.js.map +1 -0
  41. package/dist/recording/capture.d.ts +53 -0
  42. package/dist/recording/capture.js +163 -0
  43. package/dist/recording/capture.js.map +1 -0
  44. package/dist/recording/session.d.ts +30 -0
  45. package/dist/recording/session.js +47 -0
  46. package/dist/recording/session.js.map +1 -0
  47. package/dist/recording/types.d.ts +59 -0
  48. package/dist/recording/types.js +8 -0
  49. package/dist/recording/types.js.map +1 -0
  50. package/dist/run-client.d.ts +19 -0
  51. package/dist/run-client.js +44 -0
  52. package/dist/run-client.js.map +1 -0
  53. package/dist/run-worker.d.ts +25 -0
  54. package/dist/run-worker.js +85 -0
  55. package/dist/run-worker.js.map +1 -0
  56. package/dist/runtime/actions.d.ts +13 -0
  57. package/dist/runtime/actions.js +107 -0
  58. package/dist/runtime/actions.js.map +1 -0
  59. package/dist/runtime/client.d.ts +3 -0
  60. package/dist/runtime/client.js +85 -0
  61. package/dist/runtime/client.js.map +1 -0
  62. package/dist/runtime/login.d.ts +20 -0
  63. package/dist/runtime/login.js +34 -0
  64. package/dist/runtime/login.js.map +1 -0
  65. package/dist/runtime/loop.d.ts +28 -0
  66. package/dist/runtime/loop.js +68 -0
  67. package/dist/runtime/loop.js.map +1 -0
  68. package/dist/runtime/playbook.d.ts +49 -0
  69. package/dist/runtime/playbook.js +73 -0
  70. package/dist/runtime/playbook.js.map +1 -0
  71. package/dist/runtime/runner.d.ts +20 -0
  72. package/dist/runtime/runner.js +54 -0
  73. package/dist/runtime/runner.js.map +1 -0
  74. package/dist/runtime/types.d.ts +69 -0
  75. package/dist/runtime/types.js +10 -0
  76. package/dist/runtime/types.js.map +1 -0
  77. package/dist/scanners/claude-code-skills.d.ts +6 -0
  78. package/dist/scanners/claude-code-skills.js +201 -0
  79. package/dist/scanners/claude-code-skills.js.map +1 -0
  80. package/dist/scanners/claude-code.js +10 -3
  81. package/dist/scanners/claude-code.js.map +1 -1
  82. package/dist/scanners/index.js +3 -2
  83. package/dist/scanners/index.js.map +1 -1
  84. package/dist/service/files.d.ts +14 -2
  85. package/dist/service/files.js +16 -4
  86. package/dist/service/files.js.map +1 -1
  87. package/dist/service/install.js +83 -16
  88. package/dist/service/install.js.map +1 -1
  89. package/dist/sse-client.d.ts +72 -0
  90. package/dist/sse-client.js +174 -0
  91. package/dist/sse-client.js.map +1 -0
  92. package/dist/types.d.ts +43 -3
  93. package/dist/types.js +34 -2
  94. package/dist/types.js.map +1 -1
  95. package/dist/writers/claude-code.js +31 -10
  96. package/dist/writers/claude-code.js.map +1 -1
  97. package/dist/writers/registry.js +0 -4
  98. package/dist/writers/registry.js.map +1 -1
  99. package/package.json +11 -1
  100. package/dist/scanners/chatgpt.d.ts +0 -20
  101. package/dist/scanners/chatgpt.js +0 -49
  102. package/dist/scanners/chatgpt.js.map +0 -1
  103. package/dist/writers/chatgpt.d.ts +0 -8
  104. package/dist/writers/chatgpt.js +0 -12
  105. package/dist/writers/chatgpt.js.map +0 -1
@@ -0,0 +1,85 @@
1
+ /**
2
+ * 録画 run-job のローカル実行ワーカー (Demo-to-MCP / ハイブリッド R2)。
3
+ *
4
+ * daemon から呼ばれ、自分宛の pending run を順に
5
+ * claim → 鍵取得(K1) → playbook をローカルブラウザ実行 → 結果/失敗を報告
6
+ * する。computer use の Gemini 呼び出しはローカルから直接行われ、スクショは
7
+ * Lnar を経由しない。
8
+ *
9
+ * 依存 (API クライアント / 実行器) は注入可能にしてテストしやすくしている。
10
+ */
11
+ import { ApiError } from './api-client.js';
12
+ import { claimRun, getRunCredential, listPendingRuns, reportRunFailed, reportRunResult, } from './run-client.js';
13
+ import { parsePlaybook } from './runtime/playbook.js';
14
+ import { runPlaybook } from './runtime/runner.js';
15
+ const defaultDeps = () => ({
16
+ listPendingRuns,
17
+ claimRun,
18
+ getRunCredential,
19
+ reportRunResult,
20
+ reportRunFailed,
21
+ runPlaybook,
22
+ });
23
+ /** run.params (任意値) を文字列パラメータに正規化する。 */
24
+ function toStringParams(params) {
25
+ const out = {};
26
+ for (const [k, v] of Object.entries(params ?? {}))
27
+ out[k] = String(v);
28
+ return out;
29
+ }
30
+ function outcomeMessage(outcome) {
31
+ if (outcome.completed)
32
+ return outcome.finalText ?? 'タスクを完了しました。';
33
+ if (outcome.aborted)
34
+ return 'タスクは安全確認の拒否により中断されました。';
35
+ return `タスクは上限ターン数に達しました (${outcome.turns} turns)。`;
36
+ }
37
+ /** pending run を 1 件実行して結果を報告する。 */
38
+ export async function executeRun(baseUrl, token, hostname, run, deps) {
39
+ const log = deps.log ?? (() => { });
40
+ // claim は排他取得。競合 (409 = 別 daemon が先に取得) のときだけスキップする
41
+ // (走っている run を上書きしないため、failed 報告もしない)。それ以外 (認証切れ/
42
+ // ネットワーク/5xx 等) は握りつぶさず上位へ伝播し、daemon 側の try/catch で
43
+ // 可視化する (黙ってスキップすると run が pending のまま詰まり障害検知が遅れる)。
44
+ try {
45
+ await deps.claimRun(baseUrl, token, run.id, hostname);
46
+ }
47
+ catch (err) {
48
+ if (err instanceof ApiError && err.status === 409) {
49
+ log(`run ${run.id} claim skipped (409 conflict)`);
50
+ return;
51
+ }
52
+ throw err;
53
+ }
54
+ // claim 後の実行・報告。ここでの失敗は run を failed として報告する。
55
+ try {
56
+ const apiKey = await deps.getRunCredential(baseUrl, token);
57
+ const playbook = parsePlaybook(run.playbook);
58
+ const outcome = await deps.runPlaybook(playbook, toStringParams(run.params), {
59
+ apiKey,
60
+ logger: log,
61
+ startUrl: run.start_url ?? null,
62
+ purpose: run.purpose ?? null,
63
+ });
64
+ if (outcome.completed) {
65
+ await deps.reportRunResult(baseUrl, token, run.id, outcomeMessage(outcome));
66
+ }
67
+ else {
68
+ await deps.reportRunFailed(baseUrl, token, run.id, outcomeMessage(outcome));
69
+ }
70
+ }
71
+ catch (err) {
72
+ const message = err instanceof Error ? err.message : String(err);
73
+ log(`run ${run.id} failed: ${message}`);
74
+ await deps.reportRunFailed(baseUrl, token, run.id, message).catch(() => { });
75
+ }
76
+ }
77
+ /** 自分宛の pending run をすべて実行する。実行件数を返す。 */
78
+ export async function executePendingRuns(baseUrl, token, hostname, deps = defaultDeps()) {
79
+ const runs = await deps.listPendingRuns(baseUrl, token);
80
+ for (const run of runs) {
81
+ await executeRun(baseUrl, token, hostname, run, deps);
82
+ }
83
+ return runs.length;
84
+ }
85
+ //# sourceMappingURL=run-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-worker.js","sourceRoot":"","sources":["../src/run-worker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Gemini の function_call を Playwright 操作へ変換して実行する。
3
+ * 座標は正規化 (0-999) で来るため実ビューポートへスケールする。
4
+ */
5
+ import type { Page } from 'playwright';
6
+ import type { FunctionCallStep } from './types.js';
7
+ export interface ActionResult {
8
+ readonly name: string;
9
+ readonly callId: string;
10
+ readonly detail: Record<string, unknown>;
11
+ }
12
+ /** 1 つの function_call を実行する。未知のアクションは警告にとどめループを止めない。 */
13
+ export declare function executeAction(page: Page, step: FunctionCallStep): Promise<ActionResult>;
@@ -0,0 +1,107 @@
1
+ const NORM = 1000;
2
+ function toPixel(value, size) {
3
+ return Math.round(((value ?? 0) / NORM) * size);
4
+ }
5
+ function scaleScroll(magnitude, size) {
6
+ return magnitude ?? Math.round(size / 3);
7
+ }
8
+ async function applyScroll(page, args, vp) {
9
+ // スクロール原点が未指定なら (0,0) ではなくビューポート中央を使う。
10
+ const x = args.x === undefined ? Math.round(vp.width / 2) : toPixel(args.x, vp.width);
11
+ const y = args.y === undefined ? Math.round(vp.height / 2) : toPixel(args.y, vp.height);
12
+ const dir = args.direction ?? 'down';
13
+ const dx = dir === 'right'
14
+ ? scaleScroll(args.magnitude_in_pixels, vp.width)
15
+ : dir === 'left'
16
+ ? -scaleScroll(args.magnitude_in_pixels, vp.width)
17
+ : 0;
18
+ const dy = dir === 'down'
19
+ ? scaleScroll(args.magnitude_in_pixels, vp.height)
20
+ : dir === 'up'
21
+ ? -scaleScroll(args.magnitude_in_pixels, vp.height)
22
+ : 0;
23
+ await page.mouse.move(x, y);
24
+ await page.mouse.wheel(dx, dy);
25
+ }
26
+ /** 1 つの function_call を実行する。未知のアクションは警告にとどめループを止めない。 */
27
+ export async function executeAction(page, step) {
28
+ const args = step.arguments;
29
+ const vp = page.viewportSize() ?? { width: 1280, height: 800 };
30
+ const x = toPixel(args.x, vp.width);
31
+ const y = toPixel(args.y, vp.height);
32
+ // クリック系は座標必須。未指定で (0,0) を誤クリックしないよう no-op で返す。
33
+ const needsXY = step.name === 'click' || step.name === 'double_click' || step.name === 'right_click';
34
+ if (needsXY && (args.x === undefined || args.y === undefined)) {
35
+ console.error(`[actions] ${step.name}: 座標未指定のためスキップ`);
36
+ return {
37
+ name: step.name,
38
+ callId: step.id,
39
+ detail: { url: page.url(), skipped: 'missing coordinates' },
40
+ };
41
+ }
42
+ switch (step.name) {
43
+ case 'click':
44
+ await page.mouse.click(x, y);
45
+ break;
46
+ case 'double_click':
47
+ await page.mouse.dblclick(x, y);
48
+ break;
49
+ case 'right_click':
50
+ await page.mouse.click(x, y, { button: 'right' });
51
+ break;
52
+ case 'type':
53
+ if (args.text)
54
+ await page.keyboard.type(args.text);
55
+ if (args.press_enter)
56
+ await page.keyboard.press('Enter');
57
+ break;
58
+ case 'navigate':
59
+ if (args.url)
60
+ await page.goto(args.url, { waitUntil: 'domcontentloaded' });
61
+ break;
62
+ case 'scroll':
63
+ await applyScroll(page, args, vp);
64
+ break;
65
+ case 'press_key':
66
+ if (args.key)
67
+ await page.keyboard.press(args.key);
68
+ break;
69
+ case 'hotkey':
70
+ if (args.keys && args.keys.length > 0)
71
+ await page.keyboard.press(args.keys.join('+'));
72
+ break;
73
+ case 'drag_and_drop': {
74
+ if (args.start_x === undefined ||
75
+ args.start_y === undefined ||
76
+ args.end_x === undefined ||
77
+ args.end_y === undefined) {
78
+ console.error('[actions] drag_and_drop: 座標未指定のためスキップ');
79
+ return {
80
+ name: step.name,
81
+ callId: step.id,
82
+ detail: { url: page.url(), skipped: 'missing coordinates' },
83
+ };
84
+ }
85
+ await page.mouse.move(toPixel(args.start_x, vp.width), toPixel(args.start_y, vp.height));
86
+ await page.mouse.down();
87
+ await page.mouse.move(toPixel(args.end_x, vp.width), toPixel(args.end_y, vp.height));
88
+ await page.mouse.up();
89
+ break;
90
+ }
91
+ case 'go_back':
92
+ await page.goBack({ waitUntil: 'domcontentloaded' }).catch(() => { });
93
+ break;
94
+ case 'go_forward':
95
+ await page.goForward({ waitUntil: 'domcontentloaded' }).catch(() => { });
96
+ break;
97
+ case 'wait':
98
+ await page.waitForTimeout((args.seconds ?? 1) * 1000);
99
+ break;
100
+ case 'take_screenshot':
101
+ break; // 毎ターン loop が取得するため追加操作なし
102
+ default:
103
+ console.error(`[actions] 未対応のアクション: ${String(step.name)}`);
104
+ }
105
+ return { name: step.name, callId: step.id, detail: { url: page.url() } };
106
+ }
107
+ //# sourceMappingURL=actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/runtime/actions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ComputerUseClient } from './types.js';
2
+ /** GEMINI_API_KEY / GOOGLE_API_KEY から認証する computer use クライアントを生成する。 */
3
+ export declare function createGeminiClient(apiKey?: string): ComputerUseClient;
@@ -0,0 +1,85 @@
1
+ /**
2
+ * `@google/genai` (>= 2.0.0) の computer use interactions を ComputerUseClient に適合させる。
3
+ *
4
+ * 2.x は新 `steps` スキーマ。レスポンス:
5
+ * - function_call: { type:'function_call', id, name, arguments }
6
+ * - 最終テキスト : { type:'model_output', content:[{type:'text', text}] } (+ output_text)
7
+ * - thought ステップも混在 (無視)。完了は status==='completed'。
8
+ */
9
+ import { GoogleGenAI } from '@google/genai';
10
+ const MODEL = process.env.LNAR_COMPUTER_USE_MODEL ?? 'gemini-3.5-flash';
11
+ const TOOLS = [{ type: 'computer_use', environment: 'browser' }];
12
+ /** model_output / text ステップからテキストを取り出す。 */
13
+ function extractStepText(step) {
14
+ if (typeof step.text === 'string')
15
+ return step.text;
16
+ if (Array.isArray(step.content)) {
17
+ return step.content
18
+ .map((c) => {
19
+ const part = (c ?? {});
20
+ return typeof part.text === 'string' ? part.text : '';
21
+ })
22
+ .filter(Boolean)
23
+ .join('');
24
+ }
25
+ return '';
26
+ }
27
+ function normalize(raw) {
28
+ const obj = (raw ?? {});
29
+ const id = typeof obj.id === 'string' ? obj.id : '';
30
+ const rawSteps = Array.isArray(obj.steps)
31
+ ? obj.steps
32
+ : Array.isArray(obj.outputs)
33
+ ? obj.outputs
34
+ : [];
35
+ const steps = [];
36
+ for (const s of rawSteps) {
37
+ const step = (s ?? {});
38
+ if (step.type === 'function_call' && typeof step.name === 'string') {
39
+ steps.push({
40
+ type: 'function_call',
41
+ id: typeof step.id === 'string' ? step.id : '',
42
+ name: step.name,
43
+ arguments: (step.arguments ?? {}),
44
+ safety_decision: step.safety_decision,
45
+ });
46
+ }
47
+ else if (step.type === 'model_output' || step.type === 'text') {
48
+ const text = extractStepText(step);
49
+ if (text)
50
+ steps.push({ type: 'text', text });
51
+ }
52
+ }
53
+ if (!steps.some((s) => s.type === 'text') &&
54
+ typeof obj.output_text === 'string' &&
55
+ obj.output_text) {
56
+ steps.push({ type: 'text', text: obj.output_text });
57
+ }
58
+ if (!id) {
59
+ throw new Error('Gemini interactions API のレスポンスに id がありません。SDK バージョン/権限を確認してください。');
60
+ }
61
+ return { id, steps };
62
+ }
63
+ /** GEMINI_API_KEY / GOOGLE_API_KEY から認証する computer use クライアントを生成する。 */
64
+ export function createGeminiClient(apiKey) {
65
+ const key = apiKey ?? process.env.GEMINI_API_KEY ?? process.env.GOOGLE_API_KEY;
66
+ if (!key) {
67
+ throw new Error('GEMINI_API_KEY (または GOOGLE_API_KEY) が未設定です。');
68
+ }
69
+ const ai = new GoogleGenAI({ apiKey: key });
70
+ const interactions = ai.interactions;
71
+ return {
72
+ async createInitial(input) {
73
+ return normalize(await interactions.create({ model: MODEL, input, tools: TOOLS }));
74
+ },
75
+ async continueFrom(previousInteractionId, input) {
76
+ return normalize(await interactions.create({
77
+ model: MODEL,
78
+ previous_interaction_id: previousInteractionId,
79
+ input,
80
+ tools: TOOLS,
81
+ }));
82
+ },
83
+ };
84
+ }
85
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/runtime/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * オンデマンドのログイン受け渡し (Demo-to-MCP / Phase 4)。
3
+ *
4
+ * MCP サーバー文脈ではターミナル対話ができない (stdio は MCP プロトコル専有) ため、
5
+ * ローカルの可視ブラウザでユーザーがログインするのを **ポーリングで検知して自動再開**する。
6
+ * 認証情報はサーバー側に一切保存しない。
7
+ */
8
+ import type { Page } from 'playwright';
9
+ /** 現在ページがログイン待ちかを簡易判定する。 */
10
+ export declare function detectLoginWall(page: Page): Promise<boolean>;
11
+ export interface WaitForLoginOptions {
12
+ readonly timeoutMs?: number;
13
+ readonly pollMs?: number;
14
+ readonly log?: (message: string) => void;
15
+ }
16
+ /**
17
+ * ログイン壁が解消されるまで待つ。可視ブラウザでユーザーがログインを完了すると解消する。
18
+ * 解消したら true、タイムアウトしたら false。
19
+ */
20
+ export declare function waitForLoginToClear(page: Page, options?: WaitForLoginOptions): Promise<boolean>;
@@ -0,0 +1,34 @@
1
+ const LOGIN_URL_HINTS = ['login', 'signin', 'sign-in', 'auth', 'sso', 'oauth'];
2
+ /** 現在ページがログイン待ちかを簡易判定する。 */
3
+ export async function detectLoginWall(page) {
4
+ const url = page.url().toLowerCase();
5
+ if (LOGIN_URL_HINTS.some((h) => url.includes(h)))
6
+ return true;
7
+ try {
8
+ return (await page.locator('input[type="password"]:visible').count()) > 0;
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
14
+ /**
15
+ * ログイン壁が解消されるまで待つ。可視ブラウザでユーザーがログインを完了すると解消する。
16
+ * 解消したら true、タイムアウトしたら false。
17
+ */
18
+ export async function waitForLoginToClear(page, options = {}) {
19
+ const timeoutMs = options.timeoutMs ?? 5 * 60 * 1000;
20
+ const pollMs = options.pollMs ?? 1500;
21
+ const log = options.log ?? (() => { });
22
+ log(`🔐 ログインが必要です。ブラウザ画面でログインを完了してください: ${page.url()}`);
23
+ const start = Date.now();
24
+ while (Date.now() - start < timeoutMs) {
25
+ if (!(await detectLoginWall(page))) {
26
+ log('✅ ログインを検出しました。実行を再開します。');
27
+ return true;
28
+ }
29
+ await page.waitForTimeout(pollMs);
30
+ }
31
+ log('⏱️ ログイン待機がタイムアウトしました。');
32
+ return false;
33
+ }
34
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/runtime/login.ts"],"names":[],"mappings":"AASA,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;AAE/E,4BAA4B;AAC5B,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAU;IAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9D,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC;IAC5E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAQD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAU,EACV,UAA+B,EAAE;IAEjC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;IACrD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC;IACtC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAEtC,GAAG,CAAC,sCAAsC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACxD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,SAAS,EAAE,CAAC;QACtC,IAAI,CAAC,CAAC,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YACnC,GAAG,CAAC,yBAAyB,CAAC,CAAC;YAC/B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IACD,GAAG,CAAC,uBAAuB,CAAC,CAAC;IAC7B,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Gemini computer use エージェントループ (Demo-to-MCP / Phase 4)。
3
+ *
4
+ * スクショ+指示 → function_call → Playwright 実行 → 新スクショ → 次ターン。
5
+ * ログイン要求 / 安全確認はフック (LoopHooks) 経由で外部に委ねる (MCP/CLI で差し替え)。
6
+ */
7
+ import type { Page } from 'playwright';
8
+ import { type ComputerUseClient } from './types.js';
9
+ export interface LoopHooks {
10
+ /** 各ターンのアクション通知 (ログ用)。 */
11
+ onAction?(turn: number, name: string, intent: string | undefined): void;
12
+ /** ログイン壁検出時に呼ばれ、解消を待つ。resolve で続行。 */
13
+ onLoginRequired(page: Page): Promise<void>;
14
+ /** safety_decision の確認。true で承認 (safety_acknowledgement)、false で中断。 */
15
+ onSafetyDecision(explanation: string): Promise<boolean>;
16
+ }
17
+ export interface RunOptions {
18
+ readonly task: string;
19
+ readonly maxTurns: number;
20
+ }
21
+ export interface RunOutcome {
22
+ readonly completed: boolean;
23
+ readonly turns: number;
24
+ readonly finalText: string | null;
25
+ readonly aborted: boolean;
26
+ }
27
+ /** タスクを computer use ループで実行する。 */
28
+ export declare function runTask(client: ComputerUseClient, page: Page, options: RunOptions, hooks: LoopHooks): Promise<RunOutcome>;
@@ -0,0 +1,68 @@
1
+ import { executeAction } from './actions.js';
2
+ import { detectLoginWall } from './login.js';
3
+ import { isFunctionCall, } from './types.js';
4
+ async function screenshotBase64(page) {
5
+ return (await page.screenshot({ type: 'png' })).toString('base64');
6
+ }
7
+ function buildFunctionResult(result, screenshot, acknowledged) {
8
+ const detail = acknowledged ? { ...result.detail, safety_acknowledgement: true } : result.detail;
9
+ return {
10
+ type: 'function_result',
11
+ name: result.name,
12
+ call_id: result.callId,
13
+ result: [
14
+ { type: 'text', text: JSON.stringify(detail) },
15
+ { type: 'image', data: screenshot, mime_type: 'image/png' },
16
+ ],
17
+ };
18
+ }
19
+ function collectText(interaction) {
20
+ const texts = interaction.steps
21
+ .filter((s) => s.type === 'text')
22
+ .map((s) => (s.type === 'text' ? s.text : ''))
23
+ .filter(Boolean);
24
+ return texts.length > 0 ? texts.join('\n') : null;
25
+ }
26
+ /** タスクを computer use ループで実行する。 */
27
+ export async function runTask(client, page, options, hooks) {
28
+ const initialShot = await screenshotBase64(page);
29
+ let interaction = await client.createInitial([
30
+ { type: 'text', text: options.task },
31
+ { type: 'image', data: initialShot, mime_type: 'image/png' },
32
+ ]);
33
+ for (let turn = 1; turn <= options.maxTurns; turn++) {
34
+ const calls = interaction.steps.filter(isFunctionCall);
35
+ if (calls.length === 0) {
36
+ return {
37
+ completed: true,
38
+ turns: turn - 1,
39
+ finalText: collectText(interaction),
40
+ aborted: false,
41
+ };
42
+ }
43
+ const responses = [];
44
+ for (const call of calls) {
45
+ let acknowledged = false;
46
+ if (call.safety_decision?.decision === 'require_confirmation') {
47
+ acknowledged = await hooks.onSafetyDecision(call.safety_decision.explanation);
48
+ if (!acknowledged) {
49
+ return { completed: false, turns: turn, finalText: null, aborted: true };
50
+ }
51
+ }
52
+ hooks.onAction?.(turn, call.name, call.arguments.intent);
53
+ const result = await executeAction(page, call);
54
+ if (await detectLoginWall(page)) {
55
+ await hooks.onLoginRequired(page);
56
+ }
57
+ responses.push(buildFunctionResult(result, await screenshotBase64(page), acknowledged));
58
+ }
59
+ interaction = await client.continueFrom(interaction.id, responses);
60
+ }
61
+ return {
62
+ completed: false,
63
+ turns: options.maxTurns,
64
+ finalText: collectText(interaction),
65
+ aborted: false,
66
+ };
67
+ }
68
+ //# sourceMappingURL=loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/runtime/loop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * タスク手順書 (playbook) の型と、実行時プロンプトの組み立て (Demo-to-MCP / Phase 4)。
3
+ *
4
+ * バックエンド (api/src/services/recording_analysis.Playbook) と同じ構造。
5
+ * 解析で得た playbook を実行時パラメータと合成して computer use への指示文を作る。
6
+ */
7
+ import { z } from 'zod';
8
+ export declare const PlaybookStepSchema: z.ZodObject<{
9
+ order: z.ZodNumber;
10
+ action: z.ZodString;
11
+ target: z.ZodOptional<z.ZodNullable<z.ZodString>>;
12
+ intent: z.ZodString;
13
+ }, z.core.$strip>;
14
+ export declare const PlaybookParameterSchema: z.ZodObject<{
15
+ name: z.ZodString;
16
+ description: z.ZodString;
17
+ example: z.ZodOptional<z.ZodNullable<z.ZodString>>;
18
+ }, z.core.$strip>;
19
+ export declare const PlaybookAuthPointSchema: z.ZodObject<{
20
+ step_order: z.ZodNumber;
21
+ site: z.ZodOptional<z.ZodNullable<z.ZodString>>;
22
+ note: z.ZodString;
23
+ }, z.core.$strip>;
24
+ export declare const PlaybookSchema: z.ZodObject<{
25
+ summary: z.ZodString;
26
+ steps: z.ZodDefault<z.ZodArray<z.ZodObject<{
27
+ order: z.ZodNumber;
28
+ action: z.ZodString;
29
+ target: z.ZodOptional<z.ZodNullable<z.ZodString>>;
30
+ intent: z.ZodString;
31
+ }, z.core.$strip>>>;
32
+ parameters: z.ZodDefault<z.ZodArray<z.ZodObject<{
33
+ name: z.ZodString;
34
+ description: z.ZodString;
35
+ example: z.ZodOptional<z.ZodNullable<z.ZodString>>;
36
+ }, z.core.$strip>>>;
37
+ auth_points: z.ZodDefault<z.ZodArray<z.ZodObject<{
38
+ step_order: z.ZodNumber;
39
+ site: z.ZodOptional<z.ZodNullable<z.ZodString>>;
40
+ note: z.ZodString;
41
+ }, z.core.$strip>>>;
42
+ success_criteria: z.ZodDefault<z.ZodArray<z.ZodString>>;
43
+ }, z.core.$strip>;
44
+ export type Playbook = z.infer<typeof PlaybookSchema>;
45
+ export type PlaybookParameter = z.infer<typeof PlaybookParameterSchema>;
46
+ /** JSON (文字列 or オブジェクト) を検証して Playbook にする。 */
47
+ export declare function parsePlaybook(input: unknown): Playbook;
48
+ /** playbook + 実行時パラメータから computer use への指示文を組み立てる。 */
49
+ export declare function buildTaskPrompt(playbook: Playbook, params: Record<string, string>, purpose?: string | null): string;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * タスク手順書 (playbook) の型と、実行時プロンプトの組み立て (Demo-to-MCP / Phase 4)。
3
+ *
4
+ * バックエンド (api/src/services/recording_analysis.Playbook) と同じ構造。
5
+ * 解析で得た playbook を実行時パラメータと合成して computer use への指示文を作る。
6
+ */
7
+ import { z } from 'zod';
8
+ export const PlaybookStepSchema = z.object({
9
+ order: z.number(),
10
+ action: z.string(),
11
+ target: z.string().nullish(),
12
+ intent: z.string(),
13
+ });
14
+ export const PlaybookParameterSchema = z.object({
15
+ name: z.string(),
16
+ description: z.string(),
17
+ example: z.string().nullish(),
18
+ });
19
+ export const PlaybookAuthPointSchema = z.object({
20
+ step_order: z.number(),
21
+ site: z.string().nullish(),
22
+ note: z.string(),
23
+ });
24
+ export const PlaybookSchema = z.object({
25
+ summary: z.string(),
26
+ steps: z.array(PlaybookStepSchema).default([]),
27
+ parameters: z.array(PlaybookParameterSchema).default([]),
28
+ auth_points: z.array(PlaybookAuthPointSchema).default([]),
29
+ success_criteria: z.array(z.string()).default([]),
30
+ });
31
+ /** JSON (文字列 or オブジェクト) を検証して Playbook にする。 */
32
+ export function parsePlaybook(input) {
33
+ const obj = typeof input === 'string' ? JSON.parse(input) : input;
34
+ return PlaybookSchema.parse(obj);
35
+ }
36
+ /** playbook + 実行時パラメータから computer use への指示文を組み立てる。 */
37
+ export function buildTaskPrompt(playbook, params, purpose) {
38
+ const lines = [];
39
+ lines.push(`# タスク\n${playbook.summary}`);
40
+ const trimmedPurpose = purpose?.trim();
41
+ if (trimmedPurpose) {
42
+ lines.push(`\n# 目的\n${trimmedPurpose}`);
43
+ }
44
+ if (playbook.steps.length > 0) {
45
+ lines.push('\n# 手順');
46
+ for (const s of [...playbook.steps].sort((a, b) => a.order - b.order)) {
47
+ const target = s.target ? ` (${s.target})` : '';
48
+ lines.push(`${s.order}. [${s.action}] ${s.intent}${target}`);
49
+ }
50
+ }
51
+ if (playbook.parameters.length > 0) {
52
+ lines.push('\n# 入力パラメータ (この実行での値)');
53
+ for (const p of playbook.parameters) {
54
+ const value = params[p.name];
55
+ lines.push(`- ${p.name}: ${value ?? '(未指定)'} — ${p.description}`);
56
+ }
57
+ }
58
+ if (playbook.auth_points.length > 0) {
59
+ lines.push('\n# ログインが必要な箇所');
60
+ for (const a of playbook.auth_points) {
61
+ lines.push(`- 手順${a.step_order}${a.site ? ` (${a.site})` : ''}: ${a.note}`);
62
+ }
63
+ lines.push('ログイン画面が出たら、自分で資格情報を入力せずユーザーのログイン完了を待ってから続行してください。');
64
+ }
65
+ if (playbook.success_criteria.length > 0) {
66
+ lines.push('\n# 完了条件');
67
+ for (const c of playbook.success_criteria)
68
+ lines.push(`- ${c}`);
69
+ }
70
+ lines.push('\n上記の手順とパラメータに従ってタスクを実行し、完了したら結果を簡潔に報告してください。');
71
+ return lines.join('\n');
72
+ }
73
+ //# sourceMappingURL=playbook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playbook.js","sourceRoot":"","sources":["../../src/runtime/playbook.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { type RunOutcome } from './loop.js';
2
+ import { type Playbook } from './playbook.js';
3
+ import type { ComputerUseClient } from './types.js';
4
+ export type { RunOutcome } from './loop.js';
5
+ export interface RunPlaybookOptions {
6
+ readonly apiKey?: string;
7
+ readonly headless?: boolean;
8
+ readonly profileDir?: string;
9
+ readonly maxTurns?: number;
10
+ readonly startUrl?: string | null;
11
+ /** 作業の目的。指示文の先頭に含め、エージェントの意図理解を助ける。 */
12
+ readonly purpose?: string | null;
13
+ readonly logger?: (message: string) => void;
14
+ /** safety_decision を自動承認するか (既定 false=中断)。 */
15
+ readonly autoAcknowledgeSafety?: boolean;
16
+ /** テスト用にクライアントを差し替える。 */
17
+ readonly client?: ComputerUseClient;
18
+ }
19
+ /** playbook を実行し、結果を返す。 */
20
+ export declare function runPlaybook(playbook: Playbook, params: Record<string, string>, options?: RunPlaybookOptions): Promise<RunOutcome>;