create-workframe 0.1.0 → 0.1.2
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 +201 -201
- package/NOTICE +12 -12
- package/README.md +8 -92
- package/SECURITY.md +38 -40
- package/bin/workframe.js +329 -329
- package/docs/workspace-instructions/WORKFRAME_ONBOARDING.md +1 -1
- package/docs/workspace-instructions/WORKFRAME_ROUTING.md +8 -8
- package/package.json +3 -6
- package/profiles/architect/AGENTS.md +29 -29
- package/profiles/architect/SOUL.md +2 -2
- package/profiles/architect/skills/devops/kanban-worker/SKILL.md +27 -27
- package/profiles/designer/AGENTS.md +26 -26
- package/profiles/designer/skills/devops/kanban-worker/SKILL.md +27 -27
- package/profiles/dev/AGENTS.md +28 -28
- package/profiles/dev/skills/devops/kanban-worker/SKILL.md +27 -27
- package/profiles/docs/AGENTS.md +27 -27
- package/profiles/docs/skills/devops/kanban-worker/SKILL.md +27 -27
- package/profiles/research/AGENTS.md +26 -26
- package/profiles/research/skills/devops/kanban-worker/SKILL.md +27 -27
- package/profiles/visionary/AGENTS.md +25 -25
- package/profiles/visionary/skills/devops/kanban-worker/SKILL.md +27 -27
- package/profiles/workframe-agent/AGENTS.md +37 -37
- package/profiles/workframe-agent/skills/devops/botfather/SKILL.md +85 -85
- package/profiles/workframe-agent/skills/devops/kanban-handoff-pattern/SKILL.md +58 -58
- package/profiles/workframe-agent/skills/devops/workframe-cohort/SKILL.md +54 -54
- package/rules/workspace-README.md +5 -5
- package/scripts/bundle-workframe-ui.mjs +3 -3
- package/scripts/ensure-compose-host-paths.mjs +51 -51
- package/scripts/lib/install-identity.mjs +212 -212
- package/scripts/set-compose-public-url.mjs +92 -92
- package/scripts/sync-canonical-to-package.mjs +27 -9
- package/shared/WORKFRAME_AGENT_LIBRARY.md +17 -17
- package/shared/WORKFRAME_AGENT_OPERATIONS.md +15 -15
- package/shared/WORKFRAME_AGENT_PACKS.json +18 -18
- package/shared/WORKFRAME_AGENT_PACKS.yaml +8 -8
- package/shared/WORKFRAME_SKILL_CURATION.md +4 -4
- package/workframe-api/README.md +26 -28
- package/workframe-api/action_proxy.py +131 -131
- package/workframe-api/auth_rate_limit.py +49 -49
- package/workframe-api/credential_vault.py +445 -445
- package/workframe-api/data/avatar-catalog.json +41 -41
- package/workframe-api/email_sender.py +220 -220
- package/workframe-api/google_auth.py +90 -90
- package/workframe-api/install_api.py +359 -359
- package/workframe-api/internal_proxy_auth.py +150 -150
- package/workframe-api/llm_proxy.py +277 -277
- package/workframe-api/oidc_jwt.py +108 -108
- package/workframe-api/package.json +12 -13
- package/workframe-api/public/assets/index-DPXu_lGn.css +1 -1
- package/workframe-api/public/assets/index-DYnLrCZZ.js +8 -8
- package/workframe-api/requirements.txt +2 -2
- package/workframe-api/site_meta.py +271 -271
- package/workframe-api/stack_config.py +427 -427
- package/workframe-api/time-bind-chat.py +99 -99
- package/workframe-api/turn_credentials.py +226 -226
- package/workframe-api/updates.py +417 -417
- package/workframe-api/vault_kek.py +159 -159
- package/workframe-api/zk_auth.py +633 -633
- package/workframe-supervisor/Dockerfile +11 -11
- package/workframe-supervisor/server.py +787 -787
- package/workframe-ui/docker/nginx.conf +85 -85
- package/workframe-ui/public/assets/{arc-CBDYvkAF.js → arc-COAT3laO.js} +1 -1
- package/workframe-ui/public/assets/architecture-7EHR7CIX-DUyH3hWG.js +1 -0
- package/workframe-ui/public/assets/{architectureDiagram-3BPJPVTR-XnBRKeW0.js → architectureDiagram-3BPJPVTR-BFjWV24l.js} +1 -1
- package/workframe-ui/public/assets/{blockDiagram-GPEHLZMM-VYHUfVhd.js → blockDiagram-GPEHLZMM-DSQLPfrj.js} +1 -1
- package/workframe-ui/public/assets/{c4Diagram-AAUBKEIU-BTjUcJpm.js → c4Diagram-AAUBKEIU-DKEHv1t2.js} +1 -1
- package/workframe-ui/public/assets/channel-g7r_RGaY.js +1 -0
- package/workframe-ui/public/assets/{chunk-2J33WTMH-w7uu7R-b.js → chunk-2J33WTMH-DHZg-DUi.js} +1 -1
- package/workframe-ui/public/assets/{chunk-3OPIFGDE-Cb9LtnDX.js → chunk-3OPIFGDE-BB-OYTfp.js} +1 -1
- package/workframe-ui/public/assets/{chunk-4BX2VUAB-DiQ-qCwH.js → chunk-4BX2VUAB-C93q0YIm.js} +1 -1
- package/workframe-ui/public/assets/{chunk-55IACEB6-C-mLFr7z.js → chunk-55IACEB6-MAYniqik.js} +1 -1
- package/workframe-ui/public/assets/{chunk-5ZQYHXKU-DOesfiCI.js → chunk-5ZQYHXKU-ChgN6YJs.js} +1 -1
- package/workframe-ui/public/assets/{chunk-727SXJPM-BJ3oBZuz.js → chunk-727SXJPM-B_FYwdAv.js} +1 -1
- package/workframe-ui/public/assets/{chunk-AQP2D5EJ-CCA6xpGs.js → chunk-AQP2D5EJ-1_Hw_h1A.js} +1 -1
- package/workframe-ui/public/assets/{chunk-BSJP7CBP-a0cMNFb2.js → chunk-BSJP7CBP-CFiDQ1Rv.js} +1 -1
- package/workframe-ui/public/assets/{chunk-CSCIHK7Q-kuqN8EIY.js → chunk-CSCIHK7Q-DZ9UMTlB.js} +1 -1
- package/workframe-ui/public/assets/{chunk-FMBD7UC4-DyPgYHCg.js → chunk-FMBD7UC4-DlMlyFgw.js} +1 -1
- package/workframe-ui/public/assets/{chunk-KSCS5N6A-CdUuvR0V.js → chunk-KSCS5N6A-DHXtQ_Hf.js} +1 -1
- package/workframe-ui/public/assets/{chunk-L5ZTLDWV-Dq9NoWmK.js → chunk-L5ZTLDWV-CuQzg-QG.js} +1 -1
- package/workframe-ui/public/assets/{chunk-LZXEDZCA-p74rddlO.js → chunk-LZXEDZCA-BHzjzCGg.js} +2 -2
- package/workframe-ui/public/assets/{chunk-ND2GUHAM-DBD2u1Gz.js → chunk-ND2GUHAM-DHXx05n2.js} +1 -1
- package/workframe-ui/public/assets/{chunk-NZK2D7GU-BeIeYFnd.js → chunk-NZK2D7GU-CV5pmDM_.js} +1 -1
- package/workframe-ui/public/assets/{chunk-O5CBEL6O-ClHc56ib.js → chunk-O5CBEL6O-6tkCHxsV.js} +1 -1
- package/workframe-ui/public/assets/chunk-QZHKN3VN-C5UQehWY.js +1 -0
- package/workframe-ui/public/assets/chunk-WU5MYG2G-DhWllrI8.js +1 -0
- package/workframe-ui/public/assets/{chunk-XPW4576I-EFr8R_1p.js → chunk-XPW4576I-BClwIiCp.js} +1 -1
- package/workframe-ui/public/assets/classDiagram-4FO5ZUOK-BBM_8T8E.js +1 -0
- package/workframe-ui/public/assets/classDiagram-v2-Q7XG4LA2-BBM_8T8E.js +1 -0
- package/workframe-ui/public/assets/{cose-bilkent-S5V4N54A-C7aPBODd.js → cose-bilkent-S5V4N54A-DOrGV6DQ.js} +1 -1
- package/workframe-ui/public/assets/{dagre-BM42HDAG-BdU1Rv-H.js → dagre-BM42HDAG-DXTPvJkX.js} +1 -1
- package/workframe-ui/public/assets/{diagram-2AECGRRQ-DWowSo85.js → diagram-2AECGRRQ-xX_v-pbf.js} +1 -1
- package/workframe-ui/public/assets/{diagram-5GNKFQAL-MnxBbceO.js → diagram-5GNKFQAL-Cd2pXbBe.js} +1 -1
- package/workframe-ui/public/assets/{diagram-KO2AKTUF-DQaLRXFf.js → diagram-KO2AKTUF-Df3XvUtk.js} +1 -1
- package/workframe-ui/public/assets/{diagram-LMA3HP47-CQaBud9k.js → diagram-LMA3HP47-CsijIPaD.js} +1 -1
- package/workframe-ui/public/assets/{diagram-OG6HWLK6-D8bAXbY9.js → diagram-OG6HWLK6-aq5fmfHd.js} +1 -1
- package/workframe-ui/public/assets/{dist-DGpTLHr_.js → dist-D1c0mkbB.js} +1 -1
- package/workframe-ui/public/assets/{erDiagram-TEJ5UH35-1E-xSvBK.js → erDiagram-TEJ5UH35-DnFysVRY.js} +1 -1
- package/workframe-ui/public/assets/eventmodeling-FCH6USID-Ci8mdb44.js +1 -0
- package/workframe-ui/public/assets/{flowDiagram-I6XJVG4X-CgOVD5hu.js → flowDiagram-I6XJVG4X-C6Ebi3su.js} +1 -1
- package/workframe-ui/public/assets/{ganttDiagram-6RSMTGT7-JFYAIauo.js → ganttDiagram-6RSMTGT7-BQXQtUpa.js} +1 -1
- package/workframe-ui/public/assets/{gitGraph-WXDBUCRP-B9REenIl.js → gitGraph-WXDBUCRP-Dt0zIs_M.js} +1 -1
- package/workframe-ui/public/assets/{gitGraphDiagram-PVQCEYII-BQ7NcMSn.js → gitGraphDiagram-PVQCEYII-BF8gHzRn.js} +1 -1
- package/workframe-ui/public/assets/index-DpoUZAxh.css +1 -0
- package/workframe-ui/public/assets/{index-Dnw6vjqb.js → index-lRpzpNPT.js} +2 -2
- package/workframe-ui/public/assets/{info-J43DQDTF-CL6-eTjH.js → info-J43DQDTF-CSmszQJT.js} +1 -1
- package/workframe-ui/public/assets/{infoDiagram-5YYISTIA-LJTODW4W.js → infoDiagram-5YYISTIA-CVTKGW6p.js} +1 -1
- package/workframe-ui/public/assets/{ishikawaDiagram-YF4QCWOH-bchrQVuo.js → ishikawaDiagram-YF4QCWOH-Z8pT09Lv.js} +1 -1
- package/workframe-ui/public/assets/{journeyDiagram-JHISSGLW-DkrvYuxP.js → journeyDiagram-JHISSGLW-r3wD68_T.js} +1 -1
- package/workframe-ui/public/assets/{kanban-definition-UN3LZRKU-DFRbj0IG.js → kanban-definition-UN3LZRKU-Il8VglqN.js} +1 -1
- package/workframe-ui/public/assets/{line-Vd48P7-O.js → line-oyjpfz2A.js} +1 -1
- package/workframe-ui/public/assets/{linear-Ckizh2G7.js → linear-Cf7p5tVp.js} +1 -1
- package/workframe-ui/public/assets/{mermaid-parser.core-Bkimsnqj.js → mermaid-parser.core-YmbZ-AfY.js} +2 -2
- package/workframe-ui/public/assets/{mermaid.core-x0TvVuPo.js → mermaid.core-BFdCAqCo.js} +3 -3
- package/workframe-ui/public/assets/{mindmap-definition-RKZ34NQL-6ykAFPEz.js → mindmap-definition-RKZ34NQL-Cy2iCtEl.js} +1 -1
- package/workframe-ui/public/assets/{packet-YPE3B663-Dw3xgMDt.js → packet-YPE3B663-DwOBZL6K.js} +1 -1
- package/workframe-ui/public/assets/{pie-LRSECV5Y-DATysawG.js → pie-LRSECV5Y-04PPhnKK.js} +1 -1
- package/workframe-ui/public/assets/{pieDiagram-4H26LBE5-SJKD1S0S.js → pieDiagram-4H26LBE5-LxIpgHqi.js} +1 -1
- package/workframe-ui/public/assets/{quadrantDiagram-W4KKPZXB-BrYDZX8q.js → quadrantDiagram-W4KKPZXB-0nBYfYm4.js} +1 -1
- package/workframe-ui/public/assets/{radar-GUYGQ44K-BmWYPCds.js → radar-GUYGQ44K-D2-vBqps.js} +1 -1
- package/workframe-ui/public/assets/{requirementDiagram-4Y6WPE33-DwL9Mc8e.js → requirementDiagram-4Y6WPE33-DbuU0nlu.js} +1 -1
- package/workframe-ui/public/assets/{sankeyDiagram-5OEKKPKP-DYIFsL8h.js → sankeyDiagram-5OEKKPKP-B2hQ6B2x.js} +1 -1
- package/workframe-ui/public/assets/{sequenceDiagram-3UESZ5HK-0-FPkFk8.js → sequenceDiagram-3UESZ5HK-BBrU30e1.js} +1 -1
- package/workframe-ui/public/assets/{src-B_od6b6h.js → src-BJEDmV70.js} +1 -1
- package/workframe-ui/public/assets/{stateDiagram-AJRCARHV-BQCiBk6u.js → stateDiagram-AJRCARHV-7FGO4kkH.js} +1 -1
- package/workframe-ui/public/assets/stateDiagram-v2-BHNVJYJU-DLTSizMg.js +1 -0
- package/workframe-ui/public/assets/{timeline-definition-PNZ67QCA-DS3tFcXj.js → timeline-definition-PNZ67QCA-ptDm4rCN.js} +1 -1
- package/workframe-ui/public/assets/{treeView-BLDUP644-DSyUCKLY.js → treeView-BLDUP644-CS6Z-0q8.js} +1 -1
- package/workframe-ui/public/assets/{treemap-LRROVOQU-CEZaNh5Y.js → treemap-LRROVOQU-DqV4Y2VA.js} +1 -1
- package/workframe-ui/public/assets/{vennDiagram-CIIHVFJN-CD-Vc9NF.js → vennDiagram-CIIHVFJN-C0UrZJYt.js} +1 -1
- package/workframe-ui/public/assets/{wardley-L42UT6IY-Drq5w1Mc.js → wardley-L42UT6IY-bNDN3_Sa.js} +1 -1
- package/workframe-ui/public/assets/{wardleyDiagram-YWT4CUSO-DouXDJoF.js → wardleyDiagram-YWT4CUSO-jWiJsefM.js} +1 -1
- package/workframe-ui/public/assets/{xychartDiagram-2RQKCTM6-DDf_Lol5.js → xychartDiagram-2RQKCTM6-Dsh_fLCy.js} +1 -1
- package/workframe-ui/public/favicon.svg +7 -7
- package/workframe-ui/public/index.html +50 -50
- package/workframe-ui/public/workframe-config.json +3 -3
- package/scripts/security_audit.py +0 -156
- package/scripts/test-scaffold.mjs +0 -390
- package/workframe-api/tests/__init__.py +0 -0
- package/workframe-api/tests/db_setup.py +0 -13
- package/workframe-api/tests/test_admin_updates_gated.py +0 -30
- package/workframe-api/tests/test_agent_dm_bootstrap.py +0 -196
- package/workframe-api/tests/test_agent_profile_sync.py +0 -76
- package/workframe-api/tests/test_auth_email.py +0 -222
- package/workframe-api/tests/test_auth_hole_fix_selfcheck.py +0 -99
- package/workframe-api/tests/test_auth_rate_limit.py +0 -19
- package/workframe-api/tests/test_avatar_resolve.py +0 -77
- package/workframe-api/tests/test_child_soul_template.py +0 -71
- package/workframe-api/tests/test_credential_canary.py +0 -135
- package/workframe-api/tests/test_credential_isolation.py +0 -448
- package/workframe-api/tests/test_credential_resolution.py +0 -206
- package/workframe-api/tests/test_device_oauth.py +0 -108
- package/workframe-api/tests/test_doctor_repair.py +0 -103
- package/workframe-api/tests/test_ensure_profile_api.py +0 -77
- package/workframe-api/tests/test_gateway_compose_security.py +0 -136
- package/workframe-api/tests/test_install_secure_host.py +0 -39
- package/workframe-api/tests/test_internal_proxy_auth.py +0 -125
- package/workframe-api/tests/test_invite_runtime_bootstrap.py +0 -72
- package/workframe-api/tests/test_kanban_delegation.py +0 -185
- package/workframe-api/tests/test_llm_proxy.py +0 -155
- package/workframe-api/tests/test_login_access_policy.py +0 -183
- package/workframe-api/tests/test_mvp_model_bootstrap.py +0 -75
- package/workframe-api/tests/test_onboarding_bootstrap.py +0 -248
- package/workframe-api/tests/test_platform_auth.py +0 -47
- package/workframe-api/tests/test_profile_config_path.py +0 -56
- package/workframe-api/tests/test_profile_config_yaml_repair.py +0 -63
- package/workframe-api/tests/test_profile_create.py +0 -72
- package/workframe-api/tests/test_profile_identity_overlay.py +0 -61
- package/workframe-api/tests/test_profile_install_health.py +0 -45
- package/workframe-api/tests/test_profile_secret_policy.py +0 -57
- package/workframe-api/tests/test_profile_workspace_cwd.py +0 -34
- package/workframe-api/tests/test_provider_bootstrap.py +0 -75
- package/workframe-api/tests/test_provider_connect.py +0 -54
- package/workframe-api/tests/test_room_crud.py +0 -192
- package/workframe-api/tests/test_room_tenancy.py +0 -701
- package/workframe-api/tests/test_runtime_identity_backfill.py +0 -34
- package/workframe-api/tests/test_site_meta.py +0 -81
- package/workframe-api/tests/test_soul_stub.py +0 -42
- package/workframe-api/tests/test_space_member_sync.py +0 -99
- package/workframe-api/tests/test_stripe_stack_config.py +0 -37
- package/workframe-api/tests/test_supervisor_lifecycle.py +0 -52
- package/workframe-api/tests/test_turn_credential_vault.py +0 -125
- package/workframe-api/tests/test_updates.py +0 -176
- package/workframe-api/tests/test_user_cohort.py +0 -113
- package/workframe-api/tests/test_vault_envelope.py +0 -110
- package/workframe-api/tests/test_workspace_members.py +0 -183
- package/workframe-api/tests/test_workspace_messaging_sync.py +0 -125
- package/workframe-api/tests/test_workspace_provider_list.py +0 -57
- package/workframe-supervisor/tests/test_exec_guard.py +0 -42
- package/workframe-supervisor/tests/test_server_import.py +0 -21
- package/workframe-ui/public/assets/architecture-7EHR7CIX-CtbQKTuT.js +0 -1
- package/workframe-ui/public/assets/channel-Dy4Z4-jn.js +0 -1
- package/workframe-ui/public/assets/chunk-QZHKN3VN-CtBEchFK.js +0 -1
- package/workframe-ui/public/assets/chunk-WU5MYG2G-B9pBtriN.js +0 -1
- package/workframe-ui/public/assets/classDiagram-4FO5ZUOK-BMAEA8jI.js +0 -1
- package/workframe-ui/public/assets/classDiagram-v2-Q7XG4LA2-BMAEA8jI.js +0 -1
- package/workframe-ui/public/assets/eventmodeling-FCH6USID-D75cstNT.js +0 -1
- package/workframe-ui/public/assets/index-DpAGxump.css +0 -1
- package/workframe-ui/public/assets/stateDiagram-v2-BHNVJYJU-B89jAMFF.js +0 -1
|
@@ -1,92 +1,92 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Set public URL keys in compose .env (APP_BASE_URL, WORKFRAME_PUBLIC_HOST, CORS, ALLOWED_HOSTS).
|
|
4
|
-
* HERMES_DASHBOARD_PUBLIC_URL is derived from APP_BASE_URL in docker-compose.yml.
|
|
5
|
-
* Usage: node set-compose-public-url.mjs https://dev.example.com [--env path/to/.env]
|
|
6
|
-
*/
|
|
7
|
-
import fs from 'node:fs';
|
|
8
|
-
import path from 'node:path';
|
|
9
|
-
import { fileURLToPath } from 'node:url';
|
|
10
|
-
|
|
11
|
-
const args = process.argv.slice(2);
|
|
12
|
-
|
|
13
|
-
if (args.includes('--self-check')) {
|
|
14
|
-
function normalizePublicUrl(raw) {
|
|
15
|
-
let u = String(raw || '').trim();
|
|
16
|
-
if (!u) throw new Error('url required');
|
|
17
|
-
if (!/^https?:\/\//i.test(u)) u = `https://${u}`;
|
|
18
|
-
const parsed = new URL(u);
|
|
19
|
-
if (!parsed.hostname) throw new Error('invalid hostname');
|
|
20
|
-
return `https://${parsed.hostname}`;
|
|
21
|
-
}
|
|
22
|
-
if (normalizePublicUrl('dev.example.com') !== 'https://dev.example.com') {
|
|
23
|
-
throw new Error('normalizePublicUrl failed');
|
|
24
|
-
}
|
|
25
|
-
console.log('self-check ok');
|
|
26
|
-
process.exit(0);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const envFlag = args.indexOf('--env');
|
|
30
|
-
let envPath =
|
|
31
|
-
envFlag >= 0 ? args[envFlag + 1] : path.join(path.dirname(fileURLToPath(import.meta.url)), '../../infra/compose/workframe/.env');
|
|
32
|
-
const urlArg = args.find((a) => !a.startsWith('--') && a !== envPath);
|
|
33
|
-
|
|
34
|
-
if (!urlArg?.trim()) {
|
|
35
|
-
console.error('Usage: node set-compose-public-url.mjs <https://host> [--env path/to/.env]');
|
|
36
|
-
process.exit(1);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function normalizePublicUrl(raw) {
|
|
40
|
-
let u = String(raw || '').trim();
|
|
41
|
-
if (!u) throw new Error('url required');
|
|
42
|
-
if (!/^https?:\/\//i.test(u)) u = `https://${u}`;
|
|
43
|
-
const parsed = new URL(u);
|
|
44
|
-
if (!parsed.hostname) throw new Error('invalid hostname');
|
|
45
|
-
return `https://${parsed.hostname}`;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function hostnameFromUrl(url) {
|
|
49
|
-
return new URL(url).hostname;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function setKv(text, key, val) {
|
|
53
|
-
const line = `${key}=${val}`;
|
|
54
|
-
const re = new RegExp(`^${key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}=.*$`, 'm');
|
|
55
|
-
if (re.test(text)) return text.replace(re, line);
|
|
56
|
-
return `${text}${text.endsWith('\n') || !text ? '' : '\n'}${line}\n`;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const publicUrl = normalizePublicUrl(urlArg);
|
|
60
|
-
const host = hostnameFromUrl(publicUrl);
|
|
61
|
-
|
|
62
|
-
if (!fs.existsSync(envPath)) {
|
|
63
|
-
const example = `${envPath}.example`;
|
|
64
|
-
if (fs.existsSync(example)) {
|
|
65
|
-
fs.mkdirSync(path.dirname(envPath), { recursive: true });
|
|
66
|
-
fs.copyFileSync(example, envPath);
|
|
67
|
-
console.log(`Created ${envPath} from example`);
|
|
68
|
-
} else {
|
|
69
|
-
throw new Error(`Missing env file: ${envPath}`);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
let text = fs.readFileSync(envPath, 'utf8');
|
|
74
|
-
text = setKv(text, 'APP_BASE_URL', publicUrl);
|
|
75
|
-
text = setKv(text, 'WORKFRAME_PUBLIC_HOST', host);
|
|
76
|
-
text = setKv(text, 'ALLOWED_HOSTS', host);
|
|
77
|
-
text = setKv(text, 'CORS_ALLOW_ORIGIN', publicUrl);
|
|
78
|
-
fs.writeFileSync(envPath, text);
|
|
79
|
-
|
|
80
|
-
console.log(
|
|
81
|
-
JSON.stringify(
|
|
82
|
-
{
|
|
83
|
-
ok: true,
|
|
84
|
-
env: envPath,
|
|
85
|
-
app_base_url: publicUrl,
|
|
86
|
-
hermes_dashboard_public_url: `${publicUrl}/hermes-dashboard`,
|
|
87
|
-
host,
|
|
88
|
-
},
|
|
89
|
-
null,
|
|
90
|
-
2,
|
|
91
|
-
),
|
|
92
|
-
);
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Set public URL keys in compose .env (APP_BASE_URL, WORKFRAME_PUBLIC_HOST, CORS, ALLOWED_HOSTS).
|
|
4
|
+
* HERMES_DASHBOARD_PUBLIC_URL is derived from APP_BASE_URL in docker-compose.yml.
|
|
5
|
+
* Usage: node set-compose-public-url.mjs https://dev.example.com [--env path/to/.env]
|
|
6
|
+
*/
|
|
7
|
+
import fs from 'node:fs';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import { fileURLToPath } from 'node:url';
|
|
10
|
+
|
|
11
|
+
const args = process.argv.slice(2);
|
|
12
|
+
|
|
13
|
+
if (args.includes('--self-check')) {
|
|
14
|
+
function normalizePublicUrl(raw) {
|
|
15
|
+
let u = String(raw || '').trim();
|
|
16
|
+
if (!u) throw new Error('url required');
|
|
17
|
+
if (!/^https?:\/\//i.test(u)) u = `https://${u}`;
|
|
18
|
+
const parsed = new URL(u);
|
|
19
|
+
if (!parsed.hostname) throw new Error('invalid hostname');
|
|
20
|
+
return `https://${parsed.hostname}`;
|
|
21
|
+
}
|
|
22
|
+
if (normalizePublicUrl('dev.example.com') !== 'https://dev.example.com') {
|
|
23
|
+
throw new Error('normalizePublicUrl failed');
|
|
24
|
+
}
|
|
25
|
+
console.log('self-check ok');
|
|
26
|
+
process.exit(0);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const envFlag = args.indexOf('--env');
|
|
30
|
+
let envPath =
|
|
31
|
+
envFlag >= 0 ? args[envFlag + 1] : path.join(path.dirname(fileURLToPath(import.meta.url)), '../../infra/compose/workframe/.env');
|
|
32
|
+
const urlArg = args.find((a) => !a.startsWith('--') && a !== envPath);
|
|
33
|
+
|
|
34
|
+
if (!urlArg?.trim()) {
|
|
35
|
+
console.error('Usage: node set-compose-public-url.mjs <https://host> [--env path/to/.env]');
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function normalizePublicUrl(raw) {
|
|
40
|
+
let u = String(raw || '').trim();
|
|
41
|
+
if (!u) throw new Error('url required');
|
|
42
|
+
if (!/^https?:\/\//i.test(u)) u = `https://${u}`;
|
|
43
|
+
const parsed = new URL(u);
|
|
44
|
+
if (!parsed.hostname) throw new Error('invalid hostname');
|
|
45
|
+
return `https://${parsed.hostname}`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function hostnameFromUrl(url) {
|
|
49
|
+
return new URL(url).hostname;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function setKv(text, key, val) {
|
|
53
|
+
const line = `${key}=${val}`;
|
|
54
|
+
const re = new RegExp(`^${key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}=.*$`, 'm');
|
|
55
|
+
if (re.test(text)) return text.replace(re, line);
|
|
56
|
+
return `${text}${text.endsWith('\n') || !text ? '' : '\n'}${line}\n`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const publicUrl = normalizePublicUrl(urlArg);
|
|
60
|
+
const host = hostnameFromUrl(publicUrl);
|
|
61
|
+
|
|
62
|
+
if (!fs.existsSync(envPath)) {
|
|
63
|
+
const example = `${envPath}.example`;
|
|
64
|
+
if (fs.existsSync(example)) {
|
|
65
|
+
fs.mkdirSync(path.dirname(envPath), { recursive: true });
|
|
66
|
+
fs.copyFileSync(example, envPath);
|
|
67
|
+
console.log(`Created ${envPath} from example`);
|
|
68
|
+
} else {
|
|
69
|
+
throw new Error(`Missing env file: ${envPath}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
let text = fs.readFileSync(envPath, 'utf8');
|
|
74
|
+
text = setKv(text, 'APP_BASE_URL', publicUrl);
|
|
75
|
+
text = setKv(text, 'WORKFRAME_PUBLIC_HOST', host);
|
|
76
|
+
text = setKv(text, 'ALLOWED_HOSTS', host);
|
|
77
|
+
text = setKv(text, 'CORS_ALLOW_ORIGIN', publicUrl);
|
|
78
|
+
fs.writeFileSync(envPath, text);
|
|
79
|
+
|
|
80
|
+
console.log(
|
|
81
|
+
JSON.stringify(
|
|
82
|
+
{
|
|
83
|
+
ok: true,
|
|
84
|
+
env: envPath,
|
|
85
|
+
app_base_url: publicUrl,
|
|
86
|
+
hermes_dashboard_public_url: `${publicUrl}/hermes-dashboard`,
|
|
87
|
+
host,
|
|
88
|
+
},
|
|
89
|
+
null,
|
|
90
|
+
2,
|
|
91
|
+
),
|
|
92
|
+
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* Copy canonical Workframe BFF into create-workframe package tree before npm pack.
|
|
4
|
-
* Run from
|
|
4
|
+
* Run from repository root: node packages/create-workframe/scripts/sync-canonical-to-package.mjs
|
|
5
5
|
*/
|
|
6
6
|
import fs from 'node:fs';
|
|
7
7
|
import path from 'node:path';
|
|
@@ -9,14 +9,15 @@ import { fileURLToPath } from 'node:url';
|
|
|
9
9
|
|
|
10
10
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
11
|
const PKG_ROOT = path.resolve(__dirname, '..');
|
|
12
|
-
const
|
|
13
|
-
const CANONICAL_API = path.join(
|
|
12
|
+
const REPO_ROOT = path.resolve(PKG_ROOT, '../..');
|
|
13
|
+
const CANONICAL_API = path.join(REPO_ROOT, 'services/workframe-api');
|
|
14
14
|
const PKG_API = path.join(PKG_ROOT, 'workframe-api');
|
|
15
|
-
const CANONICAL_SUPERVISOR = path.join(
|
|
15
|
+
const CANONICAL_SUPERVISOR = path.join(REPO_ROOT, 'services/workframe-supervisor');
|
|
16
16
|
const PKG_SUPERVISOR = path.join(PKG_ROOT, 'workframe-supervisor');
|
|
17
17
|
|
|
18
18
|
const SKIP_DIRS = new Set([
|
|
19
19
|
'data',
|
|
20
|
+
'tests',
|
|
20
21
|
'__pycache__',
|
|
21
22
|
'.pytest_cache',
|
|
22
23
|
'.venv',
|
|
@@ -56,6 +57,17 @@ function removeIfExists(p) {
|
|
|
56
57
|
if (fs.existsSync(p)) fs.rmSync(p, { recursive: true, force: true });
|
|
57
58
|
}
|
|
58
59
|
|
|
60
|
+
/** Alpine sh breaks on CRLF (then\r). Normalize at pack time — Windows checkout is CRLF. */
|
|
61
|
+
function copyIntoPackage(src, dst) {
|
|
62
|
+
fs.mkdirSync(path.dirname(dst), { recursive: true });
|
|
63
|
+
if (dst.endsWith('.sh')) {
|
|
64
|
+
const text = fs.readFileSync(src, 'utf8').replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
65
|
+
fs.writeFileSync(dst, text, 'utf8');
|
|
66
|
+
} else {
|
|
67
|
+
fs.copyFileSync(src, dst);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
59
71
|
console.log(`Sync canonical BFF: ${CANONICAL_API} -> ${PKG_API}`);
|
|
60
72
|
copyTree(CANONICAL_API, PKG_API);
|
|
61
73
|
|
|
@@ -103,15 +115,21 @@ const applyScripts = [
|
|
|
103
115
|
'ensure-compose-host-paths.mjs',
|
|
104
116
|
];
|
|
105
117
|
for (const name of applyScripts) {
|
|
106
|
-
const src = path.join(
|
|
118
|
+
const src = path.join(REPO_ROOT, 'scripts/workframe', name);
|
|
107
119
|
const dst = path.join(PKG_ROOT, 'scripts', name);
|
|
108
120
|
if (!fs.existsSync(src)) throw new Error(`Missing apply script: ${src}`);
|
|
109
|
-
|
|
110
|
-
fs.copyFileSync(src, dst);
|
|
121
|
+
copyIntoPackage(src, dst);
|
|
111
122
|
console.log(`Synced ${name} -> package/scripts/`);
|
|
112
123
|
}
|
|
113
124
|
|
|
114
|
-
const
|
|
125
|
+
for (const sh of fs.readdirSync(path.join(PKG_ROOT, 'scripts')).filter((n) => n.endsWith('.sh'))) {
|
|
126
|
+
const p = path.join(PKG_ROOT, 'scripts', sh);
|
|
127
|
+
if (fs.readFileSync(p).includes(0x0d)) {
|
|
128
|
+
throw new Error(`CRLF remains in package script after sync: ${sh}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const publicDeploySrc = path.join(REPO_ROOT, 'infra/compose/workframe/PUBLIC_DEPLOY.md');
|
|
115
133
|
const publicDeployDst = path.join(PKG_ROOT, 'docs/PUBLIC_DEPLOY.md');
|
|
116
134
|
if (fs.existsSync(publicDeploySrc)) {
|
|
117
135
|
fs.mkdirSync(path.dirname(publicDeployDst), { recursive: true });
|
|
@@ -120,7 +138,7 @@ if (fs.existsSync(publicDeploySrc)) {
|
|
|
120
138
|
}
|
|
121
139
|
|
|
122
140
|
for (const name of ['LICENSE', 'NOTICE', 'SECURITY.md']) {
|
|
123
|
-
const src = path.join(
|
|
141
|
+
const src = path.join(REPO_ROOT, name);
|
|
124
142
|
const dst = path.join(PKG_ROOT, name);
|
|
125
143
|
if (!fs.existsSync(src)) throw new Error(`Missing publish file: ${src}`);
|
|
126
144
|
fs.copyFileSync(src, dst);
|
|
@@ -8,23 +8,23 @@ Canonical behavior location
|
|
|
8
8
|
- Runtime: `Agents/profiles/{nativeProfileSlug}/SOUL.md`
|
|
9
9
|
- Bootstrap seed: `scripts/seed/profiles/{nativeProfileSlug}/SOUL.md`
|
|
10
10
|
|
|
11
|
-
Default specialist catalog
|
|
12
|
-
- visionary
|
|
13
|
-
- architect
|
|
14
|
-
- docs
|
|
15
|
-
- dev
|
|
16
|
-
- research
|
|
17
|
-
- designer
|
|
18
|
-
|
|
19
|
-
Install-time starter packs
|
|
20
|
-
- Recorded in `workframe-manifest.json` (`pack`, `profiles`, `native_agent`)
|
|
21
|
-
- Default scaffold pack is `native` (native agent only)
|
|
22
|
-
- Reference packs can still be chosen explicitly
|
|
23
|
-
- See `docs/SETUP.md` for the pack chosen at install
|
|
24
|
-
|
|
25
|
-
Extension pattern
|
|
26
|
-
- Add niche specialists only when recurring demand exists.
|
|
27
|
-
- Preferred path: spawn specialists on demand through botfather/lifecycle flows instead of preinstalling the whole crew.
|
|
11
|
+
Default specialist catalog
|
|
12
|
+
- visionary
|
|
13
|
+
- architect
|
|
14
|
+
- docs
|
|
15
|
+
- dev
|
|
16
|
+
- research
|
|
17
|
+
- designer
|
|
18
|
+
|
|
19
|
+
Install-time starter packs
|
|
20
|
+
- Recorded in `workframe-manifest.json` (`pack`, `profiles`, `native_agent`)
|
|
21
|
+
- Default scaffold pack is `native` (native agent only)
|
|
22
|
+
- Reference packs can still be chosen explicitly
|
|
23
|
+
- See `docs/SETUP.md` for the pack chosen at install
|
|
24
|
+
|
|
25
|
+
Extension pattern
|
|
26
|
+
- Add niche specialists only when recurring demand exists.
|
|
27
|
+
- Preferred path: spawn specialists on demand through botfather/lifecycle flows instead of preinstalling the whole crew.
|
|
28
28
|
|
|
29
29
|
Curation rule
|
|
30
30
|
- Keep role-specific skill/tool bundles lean.
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
Goal
|
|
4
4
|
- keep the agent library dynamic but controlled.
|
|
5
5
|
|
|
6
|
-
Concierge responsibilities
|
|
7
|
-
- detect recurring specialist needs
|
|
8
|
-
- propose profile add/remove/swap
|
|
9
|
-
- route work through existing profiles until approved change lands
|
|
10
|
-
- spawn specialists only when a real role gap exists
|
|
6
|
+
Concierge responsibilities
|
|
7
|
+
- detect recurring specialist needs
|
|
8
|
+
- propose profile add/remove/swap
|
|
9
|
+
- route work through existing profiles until approved change lands
|
|
10
|
+
- spawn specialists only when a real role gap exists
|
|
11
11
|
|
|
12
12
|
Profile operations policy
|
|
13
13
|
- Add profile: when repeated tasks do not fit existing specialists.
|
|
@@ -17,13 +17,13 @@ Profile operations policy
|
|
|
17
17
|
Approval
|
|
18
18
|
- owner/admin approves profile topology changes in team environments.
|
|
19
19
|
|
|
20
|
-
Preferred implementation path
|
|
21
|
-
1) Update runtime profile SOUL under `Agents/profiles/`.
|
|
22
|
-
2) Update bootstrap seeds under `scripts/seed/profiles/` when templates change.
|
|
23
|
-
3) Spawn or update the runtime profile set through lifecycle/botfather flows.
|
|
24
|
-
4) Announce changed routing behavior in docs and chat status.
|
|
25
|
-
|
|
26
|
-
Default topology policy
|
|
27
|
-
- Start native-only.
|
|
28
|
-
- Treat specialist packs as reference presets, not mandatory first boot state.
|
|
29
|
-
- Keep the installed crew as small as possible until real demand appears.
|
|
20
|
+
Preferred implementation path
|
|
21
|
+
1) Update runtime profile SOUL under `Agents/profiles/`.
|
|
22
|
+
2) Update bootstrap seeds under `scripts/seed/profiles/` when templates change.
|
|
23
|
+
3) Spawn or update the runtime profile set through lifecycle/botfather flows.
|
|
24
|
+
4) Announce changed routing behavior in docs and chat status.
|
|
25
|
+
|
|
26
|
+
Default topology policy
|
|
27
|
+
- Start native-only.
|
|
28
|
+
- Treat specialist packs as reference presets, not mandatory first boot state.
|
|
29
|
+
- Keep the installed crew as small as possible until real demand appears.
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": 2,
|
|
3
|
-
"packs": {
|
|
4
|
-
"native": {
|
|
5
|
-
"description": "One native project agent only. Spawn specialists later through Workframe botfather flows.",
|
|
6
|
-
"profiles": [
|
|
7
|
-
"project-agent"
|
|
8
|
-
]
|
|
9
|
-
},
|
|
10
|
-
"vanilla": {
|
|
11
|
-
"description": "Reference default crew pack (native project agent + all core specialists)",
|
|
12
|
-
"profiles": [
|
|
13
|
-
"project-agent",
|
|
14
|
-
"visionary",
|
|
2
|
+
"version": 2,
|
|
3
|
+
"packs": {
|
|
4
|
+
"native": {
|
|
5
|
+
"description": "One native project agent only. Spawn specialists later through Workframe botfather flows.",
|
|
6
|
+
"profiles": [
|
|
7
|
+
"project-agent"
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
"vanilla": {
|
|
11
|
+
"description": "Reference default crew pack (native project agent + all core specialists)",
|
|
12
|
+
"profiles": [
|
|
13
|
+
"project-agent",
|
|
14
|
+
"visionary",
|
|
15
15
|
"architect",
|
|
16
16
|
"docs",
|
|
17
17
|
"dev",
|
|
@@ -48,11 +48,11 @@
|
|
|
48
48
|
"research"
|
|
49
49
|
]
|
|
50
50
|
},
|
|
51
|
-
"full": {
|
|
52
|
-
"description": "Alias of vanilla for compatibility",
|
|
53
|
-
"profiles": [
|
|
54
|
-
"project-agent",
|
|
55
|
-
"visionary",
|
|
51
|
+
"full": {
|
|
52
|
+
"description": "Alias of vanilla for compatibility",
|
|
53
|
+
"profiles": [
|
|
54
|
+
"project-agent",
|
|
55
|
+
"visionary",
|
|
56
56
|
"architect",
|
|
57
57
|
"docs",
|
|
58
58
|
"dev",
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
version: 2
|
|
2
|
-
packs:
|
|
3
|
-
native:
|
|
4
|
-
description: One native project agent only. Spawn specialists later through Workframe botfather flows.
|
|
5
|
-
profiles: [project-agent]
|
|
6
|
-
vanilla:
|
|
7
|
-
description: Reference default crew pack (native project agent + all core specialists)
|
|
8
|
-
profiles: [project-agent, visionary, architect, docs, dev, research, designer]
|
|
1
|
+
version: 2
|
|
2
|
+
packs:
|
|
3
|
+
native:
|
|
4
|
+
description: One native project agent only. Spawn specialists later through Workframe botfather flows.
|
|
5
|
+
profiles: [project-agent]
|
|
6
|
+
vanilla:
|
|
7
|
+
description: Reference default crew pack (native project agent + all core specialists)
|
|
8
|
+
profiles: [project-agent, visionary, architect, docs, dev, research, designer]
|
|
9
9
|
core:
|
|
10
10
|
description: Minimal operational baseline
|
|
11
11
|
profiles: [project-agent, docs, dev]
|
|
@@ -21,7 +21,7 @@ Tool curation rules
|
|
|
21
21
|
3) Add a skill only after repeated need.
|
|
22
22
|
4) Remove stale skills quarterly.
|
|
23
23
|
|
|
24
|
-
Install-time selection
|
|
25
|
-
- default to the `native` starter pack unless a larger reference pack is explicitly requested
|
|
26
|
-
- reference packs remain available (`core` / `product` / `engineering` / `full`)
|
|
27
|
-
- concierge can request profile add/remove later with owner approval.
|
|
24
|
+
Install-time selection
|
|
25
|
+
- default to the `native` starter pack unless a larger reference pack is explicitly requested
|
|
26
|
+
- reference packs remain available (`core` / `product` / `engineering` / `full`)
|
|
27
|
+
- concierge can request profile add/remove later with owner approval.
|
package/workframe-api/README.md
CHANGED
|
@@ -1,28 +1,26 @@
|
|
|
1
|
-
# Workframe API Service
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
. .
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
For VPS deployment, mount clean persistent volumes into `/opt/data` and `/workspace`.
|
|
1
|
+
# Workframe API Service
|
|
2
|
+
|
|
3
|
+
Python BFF for the Workframe UI. See [docs/VERSION.md](../../docs/VERSION.md) for release version.
|
|
4
|
+
|
|
5
|
+
Canonical implementation — not rewritten into a separate `apps/api` service.
|
|
6
|
+
|
|
7
|
+
## Local (outside Docker)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
cd services/workframe-api
|
|
11
|
+
python3 -m venv .venv
|
|
12
|
+
. .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
13
|
+
pip install -r requirements.txt
|
|
14
|
+
HOST=0.0.0.0 PORT=8080 HERMES_DATA=/opt/data WORKSPACE=/workspace python3 server.py
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Runtime state (not committed)
|
|
18
|
+
|
|
19
|
+
- `data/*.db`, vault files under `WORKFRAME_API_DATA_DIR`
|
|
20
|
+
- Hermes `Agents/` tree on mounted volume
|
|
21
|
+
|
|
22
|
+
## Docs
|
|
23
|
+
|
|
24
|
+
- [Runtime operations](../../docs/public/runtime-operations.md)
|
|
25
|
+
- [Security](../../docs/public/security.md)
|
|
26
|
+
- [BFF route map](../../docs/public/bff-route-map.md)
|