@xopcai/xopc 0.0.161 → 0.0.162
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/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{activity-store-o7GRljfD.js → activity-store-hpcNv9MZ.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-9R3szLMc.js → agent-avatar-dicebear-Zf9UQEmQ.js} +1 -1
- package/dist/gateway/static/root/assets/agents-DfVkZlHc.js +2 -0
- package/dist/gateway/static/root/assets/{api-jSTqFMq9.js → api-Dnatri09.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-D81cyE76.js → app-management-settings-panel-BBTR9wJP.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-Ct6bZQCV.js → appearance-settings-C2zpLCHD.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-BMtAa4Ra.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-CfD7AZKn.js → archive-plugin-9eR_ODY1.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-CP_Gaxt3.js → attachment-load-DPuWYUeX.js} +1 -1
- package/dist/gateway/static/root/assets/{automation-suggestion-card-BGKM_NDZ.js → automation-suggestion-card-Dw49OJRl.js} +1 -1
- package/dist/gateway/static/root/assets/automations-page-BiSAMYTr.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-IPr2EVnS.js → binary-plugins-BdkJpDFm.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-B6aHEGA6.js → block-editor-CAi7SXYU.js} +47 -47
- package/dist/gateway/static/root/assets/browser-settings-page-DHmaEJS2.js +8 -0
- package/dist/gateway/static/root/assets/browser-workflow-inputs-Dx6wkGz1.js +1 -0
- package/dist/gateway/static/root/assets/browser-workflows-page-Skertc-A.js +3 -0
- package/dist/gateway/static/root/assets/capabilities-settings-panel-B5wSgf4f.js +2 -0
- package/dist/gateway/static/root/assets/{capability-presets-api-CCX9-LjU.js → capability-presets-api-CNFl7dM3.js} +1 -1
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-DyvFZwBj.js +2 -0
- package/dist/gateway/static/root/assets/{channel-recipient-api-MmLMLDWf.js → channel-recipient-api-DYQyGDw4.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-BBKEqDZn.js +1 -0
- package/dist/gateway/static/root/assets/channels-status-swr-Drk110ve.js +1 -0
- package/dist/gateway/static/root/assets/{connector-logo-BbjzIs87.js → connector-logo-Bng6kxYF.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-HpgaUDQ1.js +2 -0
- package/dist/gateway/static/root/assets/desktop-pet-Bpf6oegd.js +1 -0
- package/dist/gateway/static/root/assets/{desktop-pet-settings-DQLqGLc0.js → desktop-pet-settings-BVUyefSd.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-ClsiXhmz.js → directory-picker-path-field-DjSZAPz_.js} +1 -1
- package/dist/gateway/static/root/assets/{dreaming-settings-CjMPPdzg.js → dreaming-settings-CAZk2AM4.js} +3 -3
- package/dist/gateway/static/root/assets/{extension-debug-page-57eizjhB.js → extension-debug-page-C2F6vTTd.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-CsbSb3u1.js → extension-page-AnIt4bn4.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-DKA9-lyP.js → extension-settings-page-CLSc6682.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-DIPJuzBZ.js → gateway-config-api-DLFyZv33.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-CDLqAQY7.js → gateway-settings-DnQAA-qq.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-DrfSJtvT.js → gateway-startup-retry-DbzLyJ3R.js} +1 -1
- package/dist/gateway/static/root/assets/goal-create-dialog-DrnKFC6M.js +1 -0
- package/dist/gateway/static/root/assets/goal-detail-page-Cw1hpJkZ.js +4 -0
- package/dist/gateway/static/root/assets/{goals-config-api-lGC10UkU.js → goals-config-api-REmr3QCr.js} +1 -1
- package/dist/gateway/static/root/assets/goals-page-BDGkTVma.js +2 -0
- package/dist/gateway/static/root/assets/{goals-settings-BWq0pdrA.js → goals-settings-Dz0F3uRO.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-D4o8BJVv.js → heartbeat-settings-CQFY5gYs.js} +1 -1
- package/dist/gateway/static/root/assets/index-C8JkTS6d.js +199 -0
- package/dist/gateway/static/root/assets/index-hmrG55qg.css +1 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-6T2QYehS.js → keyboard-shortcuts-settings-BnOQXU5k.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-Bdef1b7F.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-DCjg2K9f.js → local-apps-page-KsOtWOyM.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-Dar-xqQr.js → locale-store-0lpYdNDr.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-CyYCBqym.js → logs-page-CwLPgrWh.js} +3 -3
- package/dist/gateway/static/root/assets/{markdown-split-rt1XO43g.js → markdown-split-D5GRg10r.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-Bwo8CJuh.js → media-plugins-C1ryULGs.js} +1 -1
- package/dist/gateway/static/root/assets/messages-BwQ3WssU.js +5 -0
- package/dist/gateway/static/root/assets/{notes-page-Dp-pkX7d.js → notes-page-CIeZ1_DT.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-Cf06q19x.js +4 -0
- package/dist/gateway/static/root/assets/{page-tabs-CzZ4iKOb.js → page-tabs-Caj1-E_X.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-3E_Qa-58.js → preview-open-alternatives-DKwEce-9.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-B2T48Sbt.js → product-open-page-B90ZskkN.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-SHTurM4t.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-BcC2qUAw.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-6vGefBHv.js +1 -0
- package/dist/gateway/static/root/assets/save-bar-controls-BDYt53uQ.js +1 -0
- package/dist/gateway/static/root/assets/{schedule-field-TkqUL3wm.js → schedule-field-Bcdni4Pj.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-DC-iU5IG.js → schema-form-D7oCARF7.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-C5014a53.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-CDY3ZI1K.js +1 -0
- package/dist/gateway/static/root/assets/{settings-collapsible-section-Dpqth3oA.js → settings-collapsible-section-6eNF8Jey.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-form-section-CNqF6IwY.js → settings-form-section-CARTHCxH.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-DkvwitK_.js → settings-loading-skeleton-DEwYqESe.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-B6vVdHeQ.js +1 -0
- package/dist/gateway/static/root/assets/{settings-page-layout-DWvNgISx.js → settings-page-layout-D3srt5Bi.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-z-rF0Hdg.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-DGpSPW-n.js → share-preview-page-Ck9SxiXw.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-CHZFXE_d.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-B7p2QNXt.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-ncw3tX9P.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-8TxxSbUw.js → system-settings-panel-DLBUQSk2.js} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-B5FzMWOx.js → theme-store-C1oaqeD2.js} +1 -1
- package/dist/gateway/static/root/assets/{typed-models-lib-DEGtSA5h.js → typed-models-lib-Divbg_C4.js} +1 -1
- package/dist/gateway/static/root/assets/{use-channel-catalog-BDU6FneG.js → use-channel-catalog-CP9a_rAf.js} +1 -1
- package/dist/gateway/static/root/assets/user-context-page-iYfeSLKI.js +1 -0
- package/dist/gateway/static/root/assets/voice-api-key-field-CrwkicvT.js +1 -0
- package/dist/gateway/static/root/assets/work-discovery-page-BQWxyPg8.js +1 -0
- package/dist/gateway/static/root/assets/work-item-detail-page-50ZzGay5.js +1 -0
- package/dist/gateway/static/root/assets/work-page-DPqEahx7.js +1 -0
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-Cwi8Pz7n.js → workflow-run-setup-panel-DbDPYQwB.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-C3eIC5HZ.js +11 -0
- package/dist/gateway/static/root/index.html +7 -7
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +1 -0
- package/dist/src/agent/agent-manager.js +1 -0
- package/dist/src/agent/client-error-format.js +3 -3
- package/dist/src/agent/outcomes/task-evaluation.d.ts +20 -0
- package/dist/src/agent/outcomes/task-evaluation.js +48 -0
- package/dist/src/agent/outcomes/task-verifier.d.ts +29 -0
- package/dist/src/agent/outcomes/task-verifier.js +71 -0
- package/dist/src/agent/prompt/memory/index.js +1 -1
- package/dist/src/agent/prompt/service-prompt-builder.js +32 -1
- package/dist/src/agent/service.js +1 -0
- package/dist/src/agent/service.types.d.ts +1 -0
- package/dist/src/agent/tools/browser/tool/browser-use-tool.d.ts +1 -7
- package/dist/src/agent/tools/browser/tool/browser-use-tool.js +2 -73
- package/dist/src/agent/tools/browser/tool/schemas.d.ts +1 -13
- package/dist/src/agent/tools/browser/tool/schemas.js +1 -9
- package/dist/src/agent/tools/browser-recipe-tool.d.ts +12 -0
- package/dist/src/agent/tools/browser-recipe-tool.js +113 -0
- package/dist/src/agent/tools/factory.d.ts +2 -0
- package/dist/src/agent/tools/factory.js +2 -0
- package/dist/src/agent/tools/index.d.ts +1 -0
- package/dist/src/agent/tools/index.js +2 -1
- package/dist/src/automations/domain/types.d.ts +13 -0
- package/dist/src/automations/domain/validation.d.ts +44 -24
- package/dist/src/automations/domain/validation.js +27 -18
- package/dist/src/automations/draft/automation-draft-validator.d.ts +6 -1
- package/dist/src/automations/draft/automation-draft-validator.js +1 -0
- package/dist/src/automations/service/action-executor.d.ts +1 -0
- package/dist/src/automations/service/action-executor.js +22 -0
- package/dist/src/browser/index.d.ts +0 -1
- package/dist/src/browser/index.js +1 -2
- package/dist/src/browser/pipeline/runner.d.ts +9 -2
- package/dist/src/browser/pipeline/runner.js +151 -105
- package/dist/src/browser/pipeline/schema.d.ts +21 -15
- package/dist/src/browser/pipeline/schema.js +93 -99
- package/dist/src/browser/recipes/index.d.ts +3 -0
- package/dist/src/browser/recipes/index.js +3 -0
- package/dist/src/browser/recipes/repository.d.ts +13 -0
- package/dist/src/browser/recipes/repository.js +81 -0
- package/dist/src/browser/recipes/runtime-service.d.ts +6 -0
- package/dist/src/browser/recipes/runtime-service.js +30 -0
- package/dist/src/browser/recipes/service.d.ts +36 -0
- package/dist/src/browser/recipes/service.js +186 -0
- package/dist/src/browser/recipes/types.d.ts +36 -0
- package/dist/src/browser/recipes/types.js +1 -0
- package/dist/src/cli/commands/browser-cli-helpers.js +6 -12
- package/dist/src/cli/commands/browser.js +4 -3
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/config/schema.d.ts +3 -3
- package/dist/src/config/schema.js +21 -21
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +1 -1
- package/dist/src/gateway/hono/routes/browser-workflows.d.ts +3 -0
- package/dist/src/gateway/hono/routes/browser-workflows.js +78 -0
- package/dist/src/gateway/hono/routes/home.js +1 -0
- package/dist/src/gateway/hono/routes/index.js +4 -0
- package/dist/src/gateway/hono/routes/interaction-state.d.ts +3 -0
- package/dist/src/gateway/hono/routes/interaction-state.js +45 -0
- package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
- package/dist/src/gateway/hono/routes/memory.js +33 -4
- package/dist/src/gateway/hono/routes/task-outcomes.d.ts +3 -0
- package/dist/src/gateway/hono/routes/task-outcomes.js +109 -0
- package/dist/src/gateway/hono/routes/you.d.ts +10 -2
- package/dist/src/gateway/hono/routes/you.js +184 -28
- package/dist/src/gateway/service/run-gateway-agent.js +84 -0
- package/dist/src/gateway/service.d.ts +3 -0
- package/dist/src/gateway/service.js +14 -0
- package/dist/src/proactive/insight-repository.d.ts +2 -0
- package/dist/src/proactive/insight-repository.js +5 -2
- package/dist/src/proactive/run-processor.js +22 -1
- package/dist/src/proactive/types.d.ts +2 -0
- package/dist/src/proactive/value-score.d.ts +13 -0
- package/dist/src/proactive/value-score.js +30 -0
- package/dist/src/share/share-types.js +5 -5
- package/dist/src/share/site-share-types.d.ts +1 -1
- package/dist/src/share/site-share-types.js +5 -5
- package/dist/src/storage/sqlite/index.d.ts +3 -0
- package/dist/src/storage/sqlite/index.js +4 -1
- package/dist/src/storage/sqlite/interaction-state-repository.d.ts +17 -0
- package/dist/src/storage/sqlite/interaction-state-repository.js +60 -0
- package/dist/src/storage/sqlite/memory-records-repository.js +1 -1
- package/dist/src/storage/sqlite/migrations/053_browser_recipes.sql +45 -0
- package/dist/src/storage/sqlite/migrations/054_task_outcomes.sql +24 -0
- package/dist/src/storage/sqlite/migrations/055_relationship_settings.sql +14 -0
- package/dist/src/storage/sqlite/migrations/056_task_verification.sql +6 -0
- package/dist/src/storage/sqlite/migrations/057_interaction_states.sql +11 -0
- package/dist/src/storage/sqlite/migrations/058_proactive_value.sql +3 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +3 -3
- package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
- package/dist/src/storage/sqlite/relationship-settings-repository.d.ts +17 -0
- package/dist/src/storage/sqlite/relationship-settings-repository.js +64 -0
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/storage/sqlite/schema.sql +46 -0
- package/dist/src/storage/sqlite/task-outcome-repository.d.ts +90 -0
- package/dist/src/storage/sqlite/task-outcome-repository.js +138 -0
- package/dist/src/user-context/interaction-state.d.ts +13 -0
- package/dist/src/user-context/interaction-state.js +69 -0
- package/dist/src/user-context/memory-use-audit.d.ts +10 -0
- package/dist/src/user-context/memory-use-audit.js +25 -0
- package/dist/src/user-context/personal-playbook.d.ts +11 -0
- package/dist/src/user-context/personal-playbook.js +41 -0
- package/dist/src/user-context/projection.d.ts +4 -0
- package/dist/src/user-context/projection.js +5 -1
- package/dist/src/user-context/relationship-continuity.d.ts +14 -0
- package/dist/src/user-context/relationship-continuity.js +51 -0
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/action-boundary-settings-panel-BIVBUiNT.js +0 -1
- package/dist/gateway/static/root/assets/agents-_qbUaYbs.js +0 -2
- package/dist/gateway/static/root/assets/apps-page-0sPqD0FK.js +0 -1
- package/dist/gateway/static/root/assets/automations-page-BxWBuBsE.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-C499b9AH.js +0 -8
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-Dva9SiPK.js +0 -2
- package/dist/gateway/static/root/assets/channels-settings-DNAU7u9o.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-CIOH7tgn.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-TwiBp8vY.js +0 -2
- package/dist/gateway/static/root/assets/desktop-pet-CYH5ZSXy.js +0 -1
- package/dist/gateway/static/root/assets/goal-create-dialog-Q3B0E-0s.js +0 -1
- package/dist/gateway/static/root/assets/goal-detail-page-C5VAK04G.js +0 -4
- package/dist/gateway/static/root/assets/goals-page-BJb-5IYw.js +0 -2
- package/dist/gateway/static/root/assets/index-CkUHH170.css +0 -1
- package/dist/gateway/static/root/assets/index-vq_cJZJC.js +0 -199
- package/dist/gateway/static/root/assets/local-app-workbench-page-euH17Kvb.js +0 -2
- package/dist/gateway/static/root/assets/messages-CxySDn9d.js +0 -5
- package/dist/gateway/static/root/assets/models-hub-panel-DObxxjc9.js +0 -2
- package/dist/gateway/static/root/assets/notes-workbench-CCb4RXcZ.js +0 -4
- package/dist/gateway/static/root/assets/project-detail-page-BvEcriRC.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-B_e79MRJ.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-DGcqnYfR.js +0 -1
- package/dist/gateway/static/root/assets/save-bar-controls-CkeKasGm.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-DQZhrDJ8.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-BkdeN99Y.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-qPG7I2zd.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-lwRAh9aw.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-BGj9IVUr.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-B2UBAs5U.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-DdjzFZ8I.js +0 -2
- package/dist/gateway/static/root/assets/user-context-page-BTTZpAGV.js +0 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-DuDQd-WU.js +0 -1
- package/dist/gateway/static/root/assets/work-discovery-page-BUVkVCsW.js +0 -1
- package/dist/gateway/static/root/assets/work-item-detail-page-DeEPPu4n.js +0 -1
- package/dist/gateway/static/root/assets/work-page-DQNUyTUq.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-BIy4wrzO.js +0 -11
- package/dist/src/browser/pipeline/source.d.ts +0 -9
- package/dist/src/browser/pipeline/source.js +0 -77
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { getSqliteDatabase, runSqliteWriteTransaction } from "../../storage/sqlite/transaction.js";
|
|
2
|
+
//#region src/browser/recipes/repository.ts
|
|
3
|
+
const RECIPE_SELECT = `SELECT recipe_id, revision, name, description, status, yaml_source, risk_level, domains_json, created_at_ms, updated_at_ms FROM browser_recipes`;
|
|
4
|
+
const RUN_SELECT = `SELECT run_id, recipe_id, recipe_revision, recipe_yaml, status, args_json, result_json, error, created_at_ms, started_at_ms, ended_at_ms, duration_ms FROM browser_recipe_runs`;
|
|
5
|
+
function recipeFromRow(row) {
|
|
6
|
+
return {
|
|
7
|
+
id: row.recipe_id,
|
|
8
|
+
revision: row.revision,
|
|
9
|
+
name: row.name,
|
|
10
|
+
description: row.description ?? void 0,
|
|
11
|
+
status: row.status,
|
|
12
|
+
yaml: row.yaml_source,
|
|
13
|
+
risk: row.risk_level,
|
|
14
|
+
domains: JSON.parse(row.domains_json),
|
|
15
|
+
createdAtMs: row.created_at_ms,
|
|
16
|
+
updatedAtMs: row.updated_at_ms
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function runFromRow(row) {
|
|
20
|
+
return {
|
|
21
|
+
id: row.run_id,
|
|
22
|
+
recipeId: row.recipe_id,
|
|
23
|
+
recipeRevision: row.recipe_revision,
|
|
24
|
+
recipeYaml: row.recipe_yaml,
|
|
25
|
+
status: row.status,
|
|
26
|
+
args: JSON.parse(row.args_json),
|
|
27
|
+
result: row.result_json ? JSON.parse(row.result_json) : void 0,
|
|
28
|
+
error: row.error ?? void 0,
|
|
29
|
+
createdAtMs: row.created_at_ms,
|
|
30
|
+
startedAtMs: row.started_at_ms ?? void 0,
|
|
31
|
+
endedAtMs: row.ended_at_ms ?? void 0,
|
|
32
|
+
durationMs: row.duration_ms ?? void 0
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function listBrowserRecipes() {
|
|
36
|
+
return getSqliteDatabase().prepare(`${RECIPE_SELECT} ORDER BY updated_at_ms DESC`).all().map(recipeFromRow);
|
|
37
|
+
}
|
|
38
|
+
function getBrowserRecipe(id) {
|
|
39
|
+
const row = getSqliteDatabase().prepare(`${RECIPE_SELECT} WHERE recipe_id = ?`).get(id);
|
|
40
|
+
return row ? recipeFromRow(row) : null;
|
|
41
|
+
}
|
|
42
|
+
function saveBrowserRecipe(recipe) {
|
|
43
|
+
runSqliteWriteTransaction((db) => db.prepare(`INSERT INTO browser_recipes (recipe_id, revision, name, description, status, yaml_source, risk_level, domains_json, created_at_ms, updated_at_ms) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(recipe_id) DO UPDATE SET revision=excluded.revision, name=excluded.name, description=excluded.description, status=excluded.status, yaml_source=excluded.yaml_source, risk_level=excluded.risk_level, domains_json=excluded.domains_json, updated_at_ms=excluded.updated_at_ms`).run(recipe.id, recipe.revision, recipe.name, recipe.description ?? null, recipe.status, recipe.yaml, recipe.risk, JSON.stringify(recipe.domains), recipe.createdAtMs, recipe.updatedAtMs));
|
|
44
|
+
}
|
|
45
|
+
function deleteBrowserRecipe(id) {
|
|
46
|
+
return runSqliteWriteTransaction((db) => db.prepare("DELETE FROM browser_recipes WHERE recipe_id = ?").run(id).changes > 0);
|
|
47
|
+
}
|
|
48
|
+
function saveBrowserRecipeRun(run) {
|
|
49
|
+
runSqliteWriteTransaction((db) => db.prepare(`INSERT INTO browser_recipe_runs (run_id, recipe_id, recipe_revision, recipe_yaml, status, args_json, result_json, error, created_at_ms, started_at_ms, ended_at_ms, duration_ms) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(run_id) DO UPDATE SET status=excluded.status, result_json=excluded.result_json, error=excluded.error, started_at_ms=excluded.started_at_ms, ended_at_ms=excluded.ended_at_ms, duration_ms=excluded.duration_ms`).run(run.id, run.recipeId, run.recipeRevision, run.recipeYaml, run.status, JSON.stringify(run.args), run.result === void 0 ? null : JSON.stringify(run.result), run.error ?? null, run.createdAtMs, run.startedAtMs ?? null, run.endedAtMs ?? null, run.durationMs ?? null));
|
|
50
|
+
}
|
|
51
|
+
function getBrowserRecipeRun(id) {
|
|
52
|
+
const row = getSqliteDatabase().prepare(`${RUN_SELECT} WHERE run_id = ?`).get(id);
|
|
53
|
+
return row ? runFromRow(row) : null;
|
|
54
|
+
}
|
|
55
|
+
function listBrowserRecipeRuns(recipeId) {
|
|
56
|
+
return (recipeId ? getSqliteDatabase().prepare(`${RUN_SELECT} WHERE recipe_id = ? ORDER BY created_at_ms DESC LIMIT 100`).all(recipeId) : getSqliteDatabase().prepare(`${RUN_SELECT} ORDER BY created_at_ms DESC LIMIT 100`).all()).map(runFromRow);
|
|
57
|
+
}
|
|
58
|
+
function hasActiveBrowserRecipeRuns(recipeId) {
|
|
59
|
+
return Boolean(getSqliteDatabase().prepare(`SELECT 1 FROM browser_recipe_runs WHERE recipe_id = ? AND status IN ('queued', 'running') LIMIT 1`).get(recipeId));
|
|
60
|
+
}
|
|
61
|
+
function listActiveBrowserRecipeRuns() {
|
|
62
|
+
return getSqliteDatabase().prepare(`${RUN_SELECT} WHERE status IN ('queued', 'running') ORDER BY created_at_ms ASC`).all().map(runFromRow);
|
|
63
|
+
}
|
|
64
|
+
function nextBrowserRecipeRunEventSeq(runId) {
|
|
65
|
+
return getSqliteDatabase().prepare("SELECT COALESCE(MAX(seq), 0) + 1 AS seq FROM browser_recipe_run_events WHERE run_id = ?").get(runId).seq;
|
|
66
|
+
}
|
|
67
|
+
function appendBrowserRecipeRunEvent(event) {
|
|
68
|
+
runSqliteWriteTransaction((db) => db.prepare("INSERT INTO browser_recipe_run_events (event_id, run_id, seq, type, data_json, created_at_ms) VALUES (?, ?, ?, ?, ?, ?)").run(event.id, event.runId, event.seq, event.type, event.data === void 0 ? null : JSON.stringify(event.data), event.createdAtMs));
|
|
69
|
+
}
|
|
70
|
+
function listBrowserRecipeRunEvents(runId) {
|
|
71
|
+
return getSqliteDatabase().prepare("SELECT event_id, run_id, seq, type, data_json, created_at_ms FROM browser_recipe_run_events WHERE run_id = ? ORDER BY seq ASC").all(runId).map((row) => ({
|
|
72
|
+
id: row.event_id,
|
|
73
|
+
runId: row.run_id,
|
|
74
|
+
seq: row.seq,
|
|
75
|
+
type: row.type,
|
|
76
|
+
data: row.data_json ? JSON.parse(row.data_json) : void 0,
|
|
77
|
+
createdAtMs: row.created_at_ms
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
export { appendBrowserRecipeRunEvent, deleteBrowserRecipe, getBrowserRecipe, getBrowserRecipeRun, hasActiveBrowserRecipeRuns, listActiveBrowserRecipeRuns, listBrowserRecipeRunEvents, listBrowserRecipeRuns, listBrowserRecipes, nextBrowserRecipeRunEventSeq, saveBrowserRecipe, saveBrowserRecipeRun };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Config } from '../../config/schema.js';
|
|
2
|
+
import { BrowserRecipeService } from './service.js';
|
|
3
|
+
export declare function createRuntimeBrowserRecipeService(deps: {
|
|
4
|
+
getConfig: () => Config;
|
|
5
|
+
emit?: (type: string, payload: unknown) => void;
|
|
6
|
+
}): BrowserRecipeService;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { BrowserManager } from "../manager.js";
|
|
2
|
+
import { resolveBrowserBackendFromConfig } from "../backend-from-config.js";
|
|
3
|
+
import { createBrowserActionRegistry } from "../actions/registry.js";
|
|
4
|
+
import { runBrowserPipeline } from "../pipeline/runner.js";
|
|
5
|
+
import { BrowserRecipeService } from "./service.js";
|
|
6
|
+
//#region src/browser/recipes/runtime-service.ts
|
|
7
|
+
function createRuntimeBrowserRecipeService(deps) {
|
|
8
|
+
const registry = createBrowserActionRegistry();
|
|
9
|
+
return new BrowserRecipeService(registry, async ({ yaml, args, signal, onStep }) => {
|
|
10
|
+
const manager = new BrowserManager({
|
|
11
|
+
getHeadless: () => false,
|
|
12
|
+
getBackend: () => resolveBrowserBackendFromConfig(deps.getConfig())
|
|
13
|
+
});
|
|
14
|
+
const taskId = `recipe-${Date.now()}`;
|
|
15
|
+
try {
|
|
16
|
+
await manager.ensureConnected();
|
|
17
|
+
return await runBrowserPipeline(yaml, args, {
|
|
18
|
+
page: manager.getExtensionProvider() ? null : await manager.getPage(taskId),
|
|
19
|
+
manager,
|
|
20
|
+
config: deps.getConfig(),
|
|
21
|
+
taskId,
|
|
22
|
+
signal
|
|
23
|
+
}, registry, { onStep });
|
|
24
|
+
} finally {
|
|
25
|
+
await manager.shutdown().catch(() => void 0);
|
|
26
|
+
}
|
|
27
|
+
}, deps.emit);
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { createRuntimeBrowserRecipeService };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type BrowserRecipeStepEvent } from '../pipeline/runner.js';
|
|
2
|
+
import type { BrowserActionRegistry, BrowserActionResult } from '../actions/types.js';
|
|
3
|
+
import type { BrowserRecipe, BrowserRecipeRun, BrowserRecipeStatus } from './types.js';
|
|
4
|
+
export type BrowserRecipeExecutor = (input: {
|
|
5
|
+
yaml: string;
|
|
6
|
+
args: Record<string, unknown>;
|
|
7
|
+
signal: AbortSignal;
|
|
8
|
+
onStep: (event: BrowserRecipeStepEvent) => void;
|
|
9
|
+
}) => Promise<BrowserActionResult>;
|
|
10
|
+
export declare class BrowserRecipeService {
|
|
11
|
+
private readonly registry;
|
|
12
|
+
private readonly executeRecipe;
|
|
13
|
+
private readonly emit?;
|
|
14
|
+
private activeRuns;
|
|
15
|
+
private executions;
|
|
16
|
+
private runWaiters;
|
|
17
|
+
constructor(registry: BrowserActionRegistry, executeRecipe: BrowserRecipeExecutor, emit?: (type: string, payload: unknown) => void);
|
|
18
|
+
list(): BrowserRecipe[];
|
|
19
|
+
get(id: string): BrowserRecipe;
|
|
20
|
+
listRuns(recipeId?: string): BrowserRecipeRun[];
|
|
21
|
+
getRun(id: string): BrowserRecipeRun;
|
|
22
|
+
listRunEvents(id: string): import("./types.js").BrowserRecipeRunEvent[];
|
|
23
|
+
validate(yaml: string): import("../pipeline/runner.js").ValidateResult;
|
|
24
|
+
save(input: {
|
|
25
|
+
yaml: string;
|
|
26
|
+
status?: BrowserRecipeStatus;
|
|
27
|
+
expectedId?: string;
|
|
28
|
+
}): BrowserRecipe;
|
|
29
|
+
remove(id: string): boolean;
|
|
30
|
+
startRun(recipeId: string, args: Record<string, unknown>): BrowserRecipeRun;
|
|
31
|
+
cancel(runId: string): boolean;
|
|
32
|
+
shutdown(): Promise<void>;
|
|
33
|
+
runAndWait(recipeId: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<BrowserRecipeRun>;
|
|
34
|
+
private addEvent;
|
|
35
|
+
private execute;
|
|
36
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { validateBrowserPipeline } from "../pipeline/runner.js";
|
|
2
|
+
import { appendBrowserRecipeRunEvent, deleteBrowserRecipe, getBrowserRecipe, getBrowserRecipeRun, hasActiveBrowserRecipeRuns, listActiveBrowserRecipeRuns, listBrowserRecipeRunEvents, listBrowserRecipeRuns, listBrowserRecipes, nextBrowserRecipeRunEventSeq, saveBrowserRecipe, saveBrowserRecipeRun } from "./repository.js";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
//#region src/browser/recipes/service.ts
|
|
5
|
+
var BrowserRecipeService = class {
|
|
6
|
+
activeRuns = /* @__PURE__ */ new Map();
|
|
7
|
+
executions = /* @__PURE__ */ new Map();
|
|
8
|
+
runWaiters = /* @__PURE__ */ new Map();
|
|
9
|
+
constructor(registry, executeRecipe, emit) {
|
|
10
|
+
this.registry = registry;
|
|
11
|
+
this.executeRecipe = executeRecipe;
|
|
12
|
+
this.emit = emit;
|
|
13
|
+
for (const run of listActiveBrowserRecipeRuns()) {
|
|
14
|
+
const endedAtMs = Date.now();
|
|
15
|
+
const recovered = {
|
|
16
|
+
...run,
|
|
17
|
+
status: "failed",
|
|
18
|
+
error: "Gateway stopped before the run completed",
|
|
19
|
+
endedAtMs,
|
|
20
|
+
durationMs: run.startedAtMs ? endedAtMs - run.startedAtMs : void 0
|
|
21
|
+
};
|
|
22
|
+
saveBrowserRecipeRun(recovered);
|
|
23
|
+
this.addEvent(run.id, "run.completed", {
|
|
24
|
+
status: recovered.status,
|
|
25
|
+
error: recovered.error
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
list() {
|
|
30
|
+
return listBrowserRecipes();
|
|
31
|
+
}
|
|
32
|
+
get(id) {
|
|
33
|
+
return getBrowserRecipe(id);
|
|
34
|
+
}
|
|
35
|
+
listRuns(recipeId) {
|
|
36
|
+
return listBrowserRecipeRuns(recipeId);
|
|
37
|
+
}
|
|
38
|
+
getRun(id) {
|
|
39
|
+
return getBrowserRecipeRun(id);
|
|
40
|
+
}
|
|
41
|
+
listRunEvents(id) {
|
|
42
|
+
return listBrowserRecipeRunEvents(id);
|
|
43
|
+
}
|
|
44
|
+
validate(yaml) {
|
|
45
|
+
return validateBrowserPipeline(yaml, this.registry);
|
|
46
|
+
}
|
|
47
|
+
save(input) {
|
|
48
|
+
const validation = this.validate(input.yaml);
|
|
49
|
+
if (!validation.ok || !validation.document) throw new Error(validation.errors.map((error) => `${error.path}: ${error.message}`).join("\n"));
|
|
50
|
+
const document = validation.document;
|
|
51
|
+
if (input.expectedId && document.id !== input.expectedId) throw new Error("Recipe id cannot change");
|
|
52
|
+
const existing = getBrowserRecipe(document.id);
|
|
53
|
+
const now = Date.now();
|
|
54
|
+
const recipe = {
|
|
55
|
+
id: document.id,
|
|
56
|
+
revision: (existing?.revision ?? 0) + 1,
|
|
57
|
+
name: document.name,
|
|
58
|
+
description: document.description,
|
|
59
|
+
status: input.status ?? existing?.status ?? "published",
|
|
60
|
+
yaml: input.yaml,
|
|
61
|
+
risk: document.risk,
|
|
62
|
+
domains: document.domains,
|
|
63
|
+
createdAtMs: existing?.createdAtMs ?? now,
|
|
64
|
+
updatedAtMs: now
|
|
65
|
+
};
|
|
66
|
+
saveBrowserRecipe(recipe);
|
|
67
|
+
return recipe;
|
|
68
|
+
}
|
|
69
|
+
remove(id) {
|
|
70
|
+
if (hasActiveBrowserRecipeRuns(id)) throw new Error("Cannot delete a browser automation while it is running");
|
|
71
|
+
return deleteBrowserRecipe(id);
|
|
72
|
+
}
|
|
73
|
+
startRun(recipeId, args) {
|
|
74
|
+
const recipe = getBrowserRecipe(recipeId);
|
|
75
|
+
if (!recipe) throw new Error("Browser automation not found");
|
|
76
|
+
if (recipe.status !== "published") throw new Error("Only enabled browser automations can run");
|
|
77
|
+
if (!this.validate(recipe.yaml).ok) throw new Error("Browser automation is invalid");
|
|
78
|
+
const run = {
|
|
79
|
+
id: randomUUID(),
|
|
80
|
+
recipeId,
|
|
81
|
+
recipeRevision: recipe.revision,
|
|
82
|
+
recipeYaml: recipe.yaml,
|
|
83
|
+
status: "queued",
|
|
84
|
+
args,
|
|
85
|
+
createdAtMs: Date.now()
|
|
86
|
+
};
|
|
87
|
+
saveBrowserRecipeRun(run);
|
|
88
|
+
this.addEvent(run.id, "run.queued", { recipeId });
|
|
89
|
+
const execution = this.execute(run);
|
|
90
|
+
this.executions.set(run.id, execution);
|
|
91
|
+
execution.finally(() => this.executions.delete(run.id)).catch(() => void 0);
|
|
92
|
+
return run;
|
|
93
|
+
}
|
|
94
|
+
cancel(runId) {
|
|
95
|
+
const controller = this.activeRuns.get(runId);
|
|
96
|
+
if (!controller) return false;
|
|
97
|
+
controller.abort();
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
async shutdown() {
|
|
101
|
+
for (const controller of this.activeRuns.values()) controller.abort();
|
|
102
|
+
await Promise.allSettled(this.executions.values());
|
|
103
|
+
}
|
|
104
|
+
async runAndWait(recipeId, args, signal) {
|
|
105
|
+
const run = this.startRun(recipeId, args);
|
|
106
|
+
return new Promise((resolve) => {
|
|
107
|
+
const onAbort = () => this.cancel(run.id);
|
|
108
|
+
const complete = (completed) => {
|
|
109
|
+
signal?.removeEventListener("abort", onAbort);
|
|
110
|
+
const active = this.runWaiters.get(run.id);
|
|
111
|
+
active?.delete(complete);
|
|
112
|
+
if (active?.size === 0) this.runWaiters.delete(run.id);
|
|
113
|
+
resolve(completed);
|
|
114
|
+
};
|
|
115
|
+
const waiters = this.runWaiters.get(run.id) ?? /* @__PURE__ */ new Set();
|
|
116
|
+
waiters.add(complete);
|
|
117
|
+
this.runWaiters.set(run.id, waiters);
|
|
118
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
119
|
+
if (signal?.aborted) onAbort();
|
|
120
|
+
const current = this.getRun(run.id);
|
|
121
|
+
if (current && current.status !== "queued" && current.status !== "running") complete(current);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
addEvent(runId, type, data) {
|
|
125
|
+
const seq = nextBrowserRecipeRunEventSeq(runId);
|
|
126
|
+
const event = {
|
|
127
|
+
id: randomUUID(),
|
|
128
|
+
runId,
|
|
129
|
+
seq,
|
|
130
|
+
type,
|
|
131
|
+
data,
|
|
132
|
+
createdAtMs: Date.now()
|
|
133
|
+
};
|
|
134
|
+
appendBrowserRecipeRunEvent(event);
|
|
135
|
+
this.emit?.(`browser.recipe.${type}`, event);
|
|
136
|
+
}
|
|
137
|
+
async execute(run) {
|
|
138
|
+
const controller = new AbortController();
|
|
139
|
+
this.activeRuns.set(run.id, controller);
|
|
140
|
+
const startedAtMs = Date.now();
|
|
141
|
+
let current = {
|
|
142
|
+
...run,
|
|
143
|
+
status: "running",
|
|
144
|
+
startedAtMs
|
|
145
|
+
};
|
|
146
|
+
saveBrowserRecipeRun(current);
|
|
147
|
+
this.addEvent(run.id, "run.started");
|
|
148
|
+
try {
|
|
149
|
+
const result = await this.executeRecipe({
|
|
150
|
+
yaml: run.recipeYaml,
|
|
151
|
+
args: run.args,
|
|
152
|
+
signal: controller.signal,
|
|
153
|
+
onStep: (event) => this.addEvent(run.id, `step.${event.status}`, event)
|
|
154
|
+
});
|
|
155
|
+
const endedAtMs = Date.now();
|
|
156
|
+
current = {
|
|
157
|
+
...current,
|
|
158
|
+
status: controller.signal.aborted ? "cancelled" : result.ok ? "succeeded" : "failed",
|
|
159
|
+
result: result.data,
|
|
160
|
+
error: result.error?.message,
|
|
161
|
+
endedAtMs,
|
|
162
|
+
durationMs: endedAtMs - startedAtMs
|
|
163
|
+
};
|
|
164
|
+
} catch (error) {
|
|
165
|
+
const endedAtMs = Date.now();
|
|
166
|
+
current = {
|
|
167
|
+
...current,
|
|
168
|
+
status: controller.signal.aborted ? "cancelled" : "failed",
|
|
169
|
+
error: error instanceof Error ? error.message : String(error),
|
|
170
|
+
endedAtMs,
|
|
171
|
+
durationMs: endedAtMs - startedAtMs
|
|
172
|
+
};
|
|
173
|
+
} finally {
|
|
174
|
+
saveBrowserRecipeRun(current);
|
|
175
|
+
this.addEvent(run.id, "run.completed", {
|
|
176
|
+
status: current.status,
|
|
177
|
+
error: current.error
|
|
178
|
+
});
|
|
179
|
+
this.activeRuns.delete(run.id);
|
|
180
|
+
for (const resolve of this.runWaiters.get(run.id) ?? []) resolve(current);
|
|
181
|
+
this.runWaiters.delete(run.id);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
//#endregion
|
|
186
|
+
export { BrowserRecipeService };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type BrowserRecipeStatus = 'published' | 'disabled';
|
|
2
|
+
export type BrowserRecipeRunStatus = 'queued' | 'running' | 'succeeded' | 'failed' | 'cancelled';
|
|
3
|
+
export interface BrowserRecipe {
|
|
4
|
+
id: string;
|
|
5
|
+
revision: number;
|
|
6
|
+
name: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
status: BrowserRecipeStatus;
|
|
9
|
+
yaml: string;
|
|
10
|
+
risk: 'read_only' | 'account_write' | 'sensitive';
|
|
11
|
+
domains: string[];
|
|
12
|
+
createdAtMs: number;
|
|
13
|
+
updatedAtMs: number;
|
|
14
|
+
}
|
|
15
|
+
export interface BrowserRecipeRun {
|
|
16
|
+
id: string;
|
|
17
|
+
recipeId: string;
|
|
18
|
+
recipeRevision: number;
|
|
19
|
+
recipeYaml: string;
|
|
20
|
+
status: BrowserRecipeRunStatus;
|
|
21
|
+
args: Record<string, unknown>;
|
|
22
|
+
result?: unknown;
|
|
23
|
+
error?: string;
|
|
24
|
+
createdAtMs: number;
|
|
25
|
+
startedAtMs?: number;
|
|
26
|
+
endedAtMs?: number;
|
|
27
|
+
durationMs?: number;
|
|
28
|
+
}
|
|
29
|
+
export interface BrowserRecipeRunEvent {
|
|
30
|
+
id: string;
|
|
31
|
+
runId: string;
|
|
32
|
+
seq: number;
|
|
33
|
+
type: string;
|
|
34
|
+
data?: unknown;
|
|
35
|
+
createdAtMs: number;
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -3,9 +3,9 @@ import { loadPlaywrightCoreModule } from "../../browser/providers/playwright-doc
|
|
|
3
3
|
import { BrowserManager } from "../../browser/manager.js";
|
|
4
4
|
import { resolveBrowserBackendFromConfig } from "../../browser/backend-from-config.js";
|
|
5
5
|
import { createBrowserActionRegistry } from "../../browser/actions/registry.js";
|
|
6
|
-
import {
|
|
7
|
-
import { runBrowserPipeline, validateBrowserPipelineSource } from "../../browser/pipeline/runner.js";
|
|
6
|
+
import { runBrowserPipeline, validateBrowserPipeline } from "../../browser/pipeline/runner.js";
|
|
8
7
|
import "../../browser/index.js";
|
|
8
|
+
import { readFile } from "node:fs/promises";
|
|
9
9
|
//#region src/cli/commands/browser-cli-helpers.ts
|
|
10
10
|
init_loader();
|
|
11
11
|
let _manager = null;
|
|
@@ -57,11 +57,8 @@ async function executeBrowserCliAction(action, args) {
|
|
|
57
57
|
}
|
|
58
58
|
async function validatePipelineCli(file) {
|
|
59
59
|
let yamlSource;
|
|
60
|
-
let sourceLocation;
|
|
61
60
|
try {
|
|
62
|
-
|
|
63
|
-
yamlSource = loaded.source;
|
|
64
|
-
sourceLocation = loaded.location;
|
|
61
|
+
yamlSource = await readFile(file, "utf8");
|
|
65
62
|
} catch (e) {
|
|
66
63
|
const msg = e instanceof Error ? e.message : String(e);
|
|
67
64
|
console.error(`Failed to read pipeline source: ${msg}`);
|
|
@@ -69,7 +66,7 @@ async function validatePipelineCli(file) {
|
|
|
69
66
|
return;
|
|
70
67
|
}
|
|
71
68
|
const registry = createBrowserActionRegistry();
|
|
72
|
-
const result =
|
|
69
|
+
const result = validateBrowserPipeline(yamlSource, registry);
|
|
73
70
|
if (result.ok) console.log(`✓ Pipeline "${result.document.name}" is valid (${result.document.pipeline.length} steps).`);
|
|
74
71
|
else {
|
|
75
72
|
console.error("✗ Pipeline validation failed:");
|
|
@@ -79,11 +76,8 @@ async function validatePipelineCli(file) {
|
|
|
79
76
|
}
|
|
80
77
|
async function runPipelineCli(file, args) {
|
|
81
78
|
let yamlSource;
|
|
82
|
-
let sourceLocation;
|
|
83
79
|
try {
|
|
84
|
-
|
|
85
|
-
yamlSource = loaded.source;
|
|
86
|
-
sourceLocation = loaded.location;
|
|
80
|
+
yamlSource = await readFile(file, "utf8");
|
|
87
81
|
} catch (e) {
|
|
88
82
|
const msg = e instanceof Error ? e.message : String(e);
|
|
89
83
|
console.error(`Failed to read pipeline source: ${msg}`);
|
|
@@ -92,7 +86,7 @@ async function runPipelineCli(file, args) {
|
|
|
92
86
|
}
|
|
93
87
|
const registry = createBrowserActionRegistry();
|
|
94
88
|
const ctx = await getActionContext();
|
|
95
|
-
const result = await runBrowserPipeline(yamlSource, args, ctx, registry
|
|
89
|
+
const result = await runBrowserPipeline(yamlSource, args, ctx, registry);
|
|
96
90
|
if (result.ok) {
|
|
97
91
|
if (result.text) console.log(result.text);
|
|
98
92
|
if (result.data && !result.text) console.log(JSON.stringify(result.data, null, 2));
|
|
@@ -38,16 +38,17 @@ function createBrowserCommand(_ctx) {
|
|
|
38
38
|
full_page: opts.fullPage
|
|
39
39
|
});
|
|
40
40
|
});
|
|
41
|
-
cmd.command("validate <file>").description("Validate a
|
|
41
|
+
cmd.command("validate <file>").description("Validate a Browser Recipe v1 YAML file without executing").action(async (file) => {
|
|
42
42
|
const { validatePipelineCli } = await import("./browser-cli-helpers.js");
|
|
43
43
|
await validatePipelineCli(file);
|
|
44
44
|
});
|
|
45
|
-
cmd.command("run <file>").description("Run a
|
|
45
|
+
cmd.command("run <file>").description("Run a Browser Recipe v1 YAML file").option("--arg <args...>", "Recipe args (key=<JSON value>)").action(async (file, opts) => {
|
|
46
46
|
const { runPipelineCli } = await import("./browser-cli-helpers.js");
|
|
47
47
|
const args = {};
|
|
48
48
|
if (opts.arg) for (const a of opts.arg) {
|
|
49
49
|
const eq = a.indexOf("=");
|
|
50
|
-
if (eq
|
|
50
|
+
if (eq <= 0) throw new Error(`Invalid --arg: ${a}`);
|
|
51
|
+
args[a.slice(0, eq)] = JSON.parse(a.slice(eq + 1));
|
|
51
52
|
}
|
|
52
53
|
await runPipelineCli(file, args);
|
|
53
54
|
});
|
|
@@ -52,7 +52,7 @@ async function checkDatabaseSchema(ctx) {
|
|
|
52
52
|
id: "database-schema",
|
|
53
53
|
label: "Database schema",
|
|
54
54
|
status: "pass",
|
|
55
|
-
message: `SQLite schema v${status.dbVersion} (current release
|
|
55
|
+
message: `SQLite schema v${status.dbVersion} (current release v58).`,
|
|
56
56
|
hints: []
|
|
57
57
|
};
|
|
58
58
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { init_agent_scope, normalizeAgentId, resolveAgentWorkspaceDir } from "../agent/agent-scope.js";
|
|
1
2
|
import { resolveEffectiveAgentManifest } from "../agent-manifest/resolver.js";
|
|
2
3
|
import "../agent-manifest/index.js";
|
|
3
|
-
import { init_agent_scope, normalizeAgentId, resolveAgentWorkspaceDir } from "../agent/agent-scope.js";
|
|
4
4
|
import { init_session_key, parseSessionKey } from "../routing/session-key.js";
|
|
5
5
|
import { agentExists, getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
|
|
6
6
|
//#region src/config/agent-profile.ts
|
|
@@ -782,16 +782,16 @@ export declare const WorkspaceConfigSchema: z.ZodOptional<z.ZodObject<{
|
|
|
782
782
|
}, z.core.$strip>>;
|
|
783
783
|
export type WorkspaceConfig = z.infer<typeof WorkspaceConfigSchema>;
|
|
784
784
|
export declare const GatewayBindModeSchema: z.ZodEnum<{
|
|
785
|
-
custom: "custom";
|
|
786
785
|
auto: "auto";
|
|
786
|
+
custom: "custom";
|
|
787
787
|
loopback: "loopback";
|
|
788
788
|
lan: "lan";
|
|
789
789
|
tailnet: "tailnet";
|
|
790
790
|
}>;
|
|
791
791
|
export declare const GatewayConfigSchema: z.ZodDefault<z.ZodObject<{
|
|
792
792
|
bind: z.ZodOptional<z.ZodEnum<{
|
|
793
|
-
custom: "custom";
|
|
794
793
|
auto: "auto";
|
|
794
|
+
custom: "custom";
|
|
795
795
|
loopback: "loopback";
|
|
796
796
|
lan: "lan";
|
|
797
797
|
tailnet: "tailnet";
|
|
@@ -1951,8 +1951,8 @@ export declare const ConfigSchema: z.ZodDefault<z.ZodObject<{
|
|
|
1951
1951
|
channels: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1952
1952
|
gateway: z.ZodDefault<z.ZodObject<{
|
|
1953
1953
|
bind: z.ZodOptional<z.ZodEnum<{
|
|
1954
|
-
custom: "custom";
|
|
1955
1954
|
auto: "auto";
|
|
1955
|
+
custom: "custom";
|
|
1956
1956
|
loopback: "loopback";
|
|
1957
1957
|
lan: "lan";
|
|
1958
1958
|
tailnet: "tailnet";
|
|
@@ -510,12 +510,12 @@ strict: z.boolean().optional() }).optional();
|
|
|
510
510
|
enabled: z.boolean().default(true),
|
|
511
511
|
/** Default TTL in ms (default 24h). */
|
|
512
512
|
defaultTtlMs: z.number().min(6e4).max(6048e5).default(864e5),
|
|
513
|
-
/** Maximum TTL in ms (default
|
|
514
|
-
maxTtlMs: z.number().min(6e4).max(2592e6).default(
|
|
515
|
-
/** Maximum concurrent active shares (default
|
|
516
|
-
maxActiveShares: z.number().min(1).max(1e4).default(
|
|
517
|
-
/** Maximum shareable file size in bytes (default
|
|
518
|
-
maxFileSize: z.number().min(1048576).max(10737418240).default(
|
|
513
|
+
/** Maximum TTL in ms (default 30 days). */
|
|
514
|
+
maxTtlMs: z.number().min(6e4).max(2592e6).default(2592e6),
|
|
515
|
+
/** Maximum concurrent active shares (default 500). */
|
|
516
|
+
maxActiveShares: z.number().min(1).max(1e4).default(500),
|
|
517
|
+
/** Maximum shareable file size in bytes (default 500 MB). */
|
|
518
|
+
maxFileSize: z.number().min(1048576).max(10737418240).default(524288e3),
|
|
519
519
|
/** MIME types allowed for inline preview (?inline=1). */
|
|
520
520
|
inlinePreviewMimes: z.array(z.string()).default([
|
|
521
521
|
"image/png",
|
|
@@ -532,10 +532,10 @@ strict: z.boolean().optional() }).optional();
|
|
|
532
532
|
/** Folder-sharing controls (browse + ZIP). */
|
|
533
533
|
directory: z.object({
|
|
534
534
|
enabled: z.boolean().default(true),
|
|
535
|
-
/** Maximum folder size in bytes at scan time (default
|
|
536
|
-
maxFolderSize: z.number().int().min(1048576).max(10737418240).default(
|
|
535
|
+
/** Maximum folder size in bytes at scan time (default 2 GB). */
|
|
536
|
+
maxFolderSize: z.number().int().min(1048576).max(10737418240).default(2147483648),
|
|
537
537
|
/** Maximum number of entries scanned for a single folder share. */
|
|
538
|
-
maxFileCount: z.number().int().min(1).max(1e5).default(
|
|
538
|
+
maxFileCount: z.number().int().min(1).max(1e5).default(1e4),
|
|
539
539
|
/** Traversal depth cap (defense against recursive symlinks). */
|
|
540
540
|
maxDepth: z.number().int().min(1).max(64).default(20),
|
|
541
541
|
/** In-memory directory listing cache TTL. */
|
|
@@ -544,8 +544,8 @@ strict: z.boolean().optional() }).optional();
|
|
|
544
544
|
zipConcurrency: z.number().int().min(1).max(8).default(1)
|
|
545
545
|
}).default({
|
|
546
546
|
enabled: true,
|
|
547
|
-
maxFolderSize:
|
|
548
|
-
maxFileCount:
|
|
547
|
+
maxFolderSize: 2147483648,
|
|
548
|
+
maxFileCount: 1e4,
|
|
549
549
|
maxDepth: 20,
|
|
550
550
|
listingCacheMs: 6e4,
|
|
551
551
|
zipConcurrency: 1
|
|
@@ -556,24 +556,24 @@ strict: z.boolean().optional() }).optional();
|
|
|
556
556
|
enabled: z.boolean().default(true),
|
|
557
557
|
/** Public host suffix that subdomain shares are served under. */
|
|
558
558
|
publicHostSuffix: z.string().min(1).default("share.xopc.ai"),
|
|
559
|
-
/** Default TTL in ms (default
|
|
560
|
-
defaultTtlMs: z.number().int().min(6e4).max(6048e5).default(
|
|
561
|
-
/** Maximum TTL in ms (default
|
|
562
|
-
maxTtlMs: z.number().int().min(6e4).max(2592e6).default(
|
|
563
|
-
/** Maximum concurrent active site shares. */
|
|
564
|
-
maxActiveSites: z.number().int().min(1).max(1e3).default(
|
|
559
|
+
/** Default TTL in ms (default 24h). */
|
|
560
|
+
defaultTtlMs: z.number().int().min(6e4).max(6048e5).default(864e5),
|
|
561
|
+
/** Maximum TTL in ms (default 30 days). */
|
|
562
|
+
maxTtlMs: z.number().int().min(6e4).max(2592e6).default(2592e6),
|
|
563
|
+
/** Maximum concurrent active site shares (default 50). */
|
|
564
|
+
maxActiveSites: z.number().int().min(1).max(1e3).default(50),
|
|
565
565
|
static: z.object({
|
|
566
566
|
enabled: z.boolean().default(true),
|
|
567
567
|
/** Maximum total bytes of files served per static site. */
|
|
568
|
-
maxRootDirSize: z.number().int().min(1048576).max(10737418240).default(
|
|
568
|
+
maxRootDirSize: z.number().int().min(1048576).max(10737418240).default(1073741824),
|
|
569
569
|
/** Maximum file count under root dir. */
|
|
570
|
-
maxFileCount: z.number().int().min(1).max(1e5).default(
|
|
570
|
+
maxFileCount: z.number().int().min(1).max(1e5).default(2e4),
|
|
571
571
|
/** Whether HTML/CSS rewrite of absolute paths is on by default. */
|
|
572
572
|
rewriteEnabledByDefault: z.boolean().default(false)
|
|
573
573
|
}).default({
|
|
574
574
|
enabled: true,
|
|
575
|
-
maxRootDirSize:
|
|
576
|
-
maxFileCount:
|
|
575
|
+
maxRootDirSize: 1073741824,
|
|
576
|
+
maxFileCount: 2e4,
|
|
577
577
|
rewriteEnabledByDefault: false
|
|
578
578
|
}),
|
|
579
579
|
proxy: z.object({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { resolveEffectiveAgentManifest } from "../agent-manifest/resolver.js";
|
|
2
1
|
import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentDir, resolveAgentProfileDir, resolveAgentWorkspaceDir, resolveDefaultAgentId, resolveUserPath, validateAgentIdForNewAgent } from "../agent/agent-scope.js";
|
|
2
|
+
import { resolveEffectiveAgentManifest } from "../agent-manifest/resolver.js";
|
|
3
3
|
import { resolveEffectiveAgentProfile } from "../config/agent-profile.js";
|
|
4
4
|
import { WORKSPACE_FILES, init_paths, resolveUserProfilePath } from "../config/paths.js";
|
|
5
5
|
import { AGENT_PROFILE_MARKDOWN_SYSTEM_FILES, REQUIRED_AGENT_PROFILE_MARKDOWN_FILE_SET } from "../agent/context/workspace.js";
|
|
@@ -209,7 +209,7 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
|
|
|
209
209
|
/** Masked `cfg.providers` for capability keys (image / STT / etc.). */
|
|
210
210
|
providersConfig: Record<string, import("./safe-providers-config.js").SafeProviderAuthEntry>;
|
|
211
211
|
gateway: {
|
|
212
|
-
bind: "
|
|
212
|
+
bind: "auto" | "custom" | "loopback" | "lan" | "tailnet";
|
|
213
213
|
customBindHost: string;
|
|
214
214
|
port: number;
|
|
215
215
|
corsOrigins: string[];
|