fraim-framework 2.0.170 → 2.0.173
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/src/ai-hub/hosts.js +227 -6
- package/dist/src/ai-hub/server.js +1014 -35
- package/dist/src/cli/commands/add-ide.js +4 -2
- package/dist/src/cli/commands/cleanup-artifacts.js +38 -0
- package/dist/src/cli/commands/init-project.js +12 -5
- package/dist/src/cli/commands/setup.js +1 -1
- package/dist/src/cli/commands/sync.js +74 -7
- package/dist/src/cli/doctor/checks/ide-config-checks.js +2 -2
- package/dist/src/cli/fraim.js +2 -0
- package/dist/src/cli/mcp/ide-formats.js +10 -2
- package/dist/src/cli/setup/auto-mcp-setup.js +4 -2
- package/dist/src/cli/setup/ide-detector.js +26 -0
- package/dist/src/cli/setup/ide-global-integration.js +6 -2
- package/dist/src/cli/setup/ide-invocation-surfaces.js +12 -4
- package/dist/src/cli/setup/mcp-config-generator.js +12 -1
- package/dist/src/cli/utils/agent-adapters.js +42 -17
- package/dist/src/cli/utils/fraim-gitignore.js +13 -0
- package/dist/src/cli/utils/remote-sync.js +129 -53
- package/dist/src/cli/utils/user-config.js +12 -0
- package/dist/src/config/ai-manager-hiring.js +121 -0
- package/dist/src/config/compat.js +16 -0
- package/dist/src/config/feature-flags.js +25 -0
- package/dist/src/config/persona-capability-bundles.js +273 -0
- package/dist/src/config/persona-hiring.js +270 -0
- package/dist/src/config/portfolio-slug-overrides.js +17 -0
- package/dist/src/config/pricing.js +37 -0
- package/dist/src/config/stripe.js +43 -0
- package/dist/src/core/fraim-config-schema.generated.js +8 -2
- package/dist/src/core/utils/local-registry-resolver.js +26 -0
- package/dist/src/core/utils/project-fraim-paths.js +89 -2
- package/dist/src/first-run/session-service.js +12 -3
- package/dist/src/local-mcp-server/artifact-retention-cleanup.js +255 -0
- package/dist/src/local-mcp-server/learning-context-builder.js +41 -81
- package/dist/src/local-mcp-server/stdio-server.js +42 -7
- package/package.json +5 -1
- package/public/ai-hub/index.html +205 -89
- package/public/ai-hub/review.css +12 -0
- package/public/ai-hub/script.js +1734 -253
- package/public/ai-hub/styles.css +473 -6
|
@@ -570,7 +570,7 @@ class FraimLocalMCPServer {
|
|
|
570
570
|
while (currentDir !== root) {
|
|
571
571
|
const fraimDir = (0, project_fraim_paths_1.getWorkspaceConfigPath)(currentDir).replace(/[\\/]config\.json$/, '');
|
|
572
572
|
this.log(` Checking: ${fraimDir}`);
|
|
573
|
-
if ((0,
|
|
573
|
+
if ((0, project_fraim_paths_1.workspaceFraimExists)(currentDir)) {
|
|
574
574
|
// Skip the home directory FRAIM dir and continue searching for a project-specific one
|
|
575
575
|
if (homeDir && currentDir === homeDir) {
|
|
576
576
|
this.log(`Skipping home directory ${(0, project_fraim_paths_1.getWorkspaceFraimDisplayPath)()}, continuing search...`);
|
|
@@ -640,8 +640,8 @@ class FraimLocalMCPServer {
|
|
|
640
640
|
return false;
|
|
641
641
|
}
|
|
642
642
|
}
|
|
643
|
-
getLocalCatalogMetadataPath(
|
|
644
|
-
return (0, path_1.join)((0, project_fraim_paths_1.
|
|
643
|
+
getLocalCatalogMetadataPath(_projectRoot) {
|
|
644
|
+
return (0, path_1.join)((0, project_fraim_paths_1.getUserFraimDirPath)(), FraimLocalMCPServer.CONNECT_SYNC_METADATA_PATH);
|
|
645
645
|
}
|
|
646
646
|
readLocalCatalogMetadata(projectRoot) {
|
|
647
647
|
const metadataPath = this.getLocalCatalogMetadataPath(projectRoot);
|
|
@@ -657,6 +657,7 @@ class FraimLocalMCPServer {
|
|
|
657
657
|
}
|
|
658
658
|
writeLocalCatalogMetadata(projectRoot) {
|
|
659
659
|
const metadataPath = this.getLocalCatalogMetadataPath(projectRoot);
|
|
660
|
+
(0, fs_1.mkdirSync)((0, project_fraim_paths_1.getUserFraimDirPath)(), { recursive: true });
|
|
660
661
|
const metadata = {
|
|
661
662
|
localVersion: this.localVersion,
|
|
662
663
|
mode: this.shouldUseLocalSyncTarget() ? 'local' : 'remote',
|
|
@@ -1838,10 +1839,12 @@ class FraimLocalMCPServer {
|
|
|
1838
1839
|
}
|
|
1839
1840
|
const resolvedRequestStr = requestSubstitution.content;
|
|
1840
1841
|
const finalRequest = JSON.parse(resolvedRequestStr);
|
|
1841
|
-
const
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1842
|
+
const canRetryTransientRemoteReset = request.method === 'initialize' ||
|
|
1843
|
+
request.method === 'tools/list' ||
|
|
1844
|
+
request.method === 'resources/list' ||
|
|
1845
|
+
request.method === 'prompts/list' ||
|
|
1846
|
+
(request.method === 'tools/call' && request.params?.name === 'fraim_connect');
|
|
1847
|
+
const response = await this.postRemoteMcpRequest(finalRequest, headers, requestId, canRetryTransientRemoteReset);
|
|
1845
1848
|
return response.data;
|
|
1846
1849
|
}
|
|
1847
1850
|
catch (error) {
|
|
@@ -1884,6 +1887,38 @@ class FraimLocalMCPServer {
|
|
|
1884
1887
|
};
|
|
1885
1888
|
}
|
|
1886
1889
|
}
|
|
1890
|
+
isTransientRemoteReset(error) {
|
|
1891
|
+
if (error?.response) {
|
|
1892
|
+
return false;
|
|
1893
|
+
}
|
|
1894
|
+
const code = String(error?.code || '');
|
|
1895
|
+
const message = String(error?.message || '');
|
|
1896
|
+
return ['ECONNRESET', 'ETIMEDOUT', 'ECONNABORTED', 'EPIPE', 'socket hang up'].some((needle) => code.includes(needle) || message.includes(needle));
|
|
1897
|
+
}
|
|
1898
|
+
async postRemoteMcpRequest(requestBody, headers, requestId, retryTransientReset) {
|
|
1899
|
+
let lastError;
|
|
1900
|
+
const attempts = retryTransientReset ? 3 : 1;
|
|
1901
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
1902
|
+
try {
|
|
1903
|
+
return await axios_1.default.post(`${this.remoteUrl}/mcp`, requestBody, {
|
|
1904
|
+
headers: {
|
|
1905
|
+
...headers,
|
|
1906
|
+
Connection: 'close'
|
|
1907
|
+
},
|
|
1908
|
+
timeout: 30000
|
|
1909
|
+
});
|
|
1910
|
+
}
|
|
1911
|
+
catch (error) {
|
|
1912
|
+
lastError = error;
|
|
1913
|
+
if (!retryTransientReset || !this.isTransientRemoteReset(error) || attempt === attempts) {
|
|
1914
|
+
throw error;
|
|
1915
|
+
}
|
|
1916
|
+
this.logError(`[req:${requestId}] Remote request reset; retrying (${attempt + 1}/${attempts})`);
|
|
1917
|
+
await new Promise((resolve) => setTimeout(resolve, 250 * attempt));
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
throw lastError;
|
|
1921
|
+
}
|
|
1887
1922
|
/**
|
|
1888
1923
|
* Try to request workspace roots from MCP client
|
|
1889
1924
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fraim-framework",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.173",
|
|
4
4
|
"description": "FRAIM: AI Workforce Infrastructure — the organizational capability that turns AI agents into an accountable workforce, their operators into capable AI managers, and executives into leaders with clear optics on AI proficiency.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
"test-all": "npm run test && npm run test:isolated tests/isolated/test-*.ts && npm run test:ui",
|
|
17
17
|
"test": "node scripts/test-with-server.js",
|
|
18
18
|
"test:isolated": "node scripts/test-isolated.js",
|
|
19
|
+
"test:evals": "node scripts/evals/run-promptfoo-evals.cjs --suite all",
|
|
20
|
+
"test:evals:smoke": "node scripts/evals/run-promptfoo-evals.cjs --suite all --tag smoke",
|
|
19
21
|
"test:smoke": "node scripts/test-with-server.js --tags=smoke",
|
|
20
22
|
"test:coverage": "node scripts/test-with-server.js --tags=smoke --coverage",
|
|
21
23
|
"test:stripe": "node scripts/test-with-server.js tests/test-stripe-payment-complete.ts",
|
|
@@ -110,6 +112,7 @@
|
|
|
110
112
|
"node-cron": "^4.2.1",
|
|
111
113
|
"playwright": "^1.58.2",
|
|
112
114
|
"pptxgenjs": "^4.0.1",
|
|
115
|
+
"promptfoo": "^0.121.17",
|
|
113
116
|
"puppeteer": "^24.36.1",
|
|
114
117
|
"qrcode": "^1.5.4",
|
|
115
118
|
"sharp": "^0.34.5",
|
|
@@ -122,6 +125,7 @@
|
|
|
122
125
|
"dist/src/ai-hub/",
|
|
123
126
|
"dist/src/first-run/",
|
|
124
127
|
"dist/src/core/",
|
|
128
|
+
"dist/src/config/",
|
|
125
129
|
"bin/fraim.js",
|
|
126
130
|
"bin/fraim-mcp.js",
|
|
127
131
|
"public/ai-hub/",
|
package/public/ai-hub/index.html
CHANGED
|
@@ -14,16 +14,6 @@
|
|
|
14
14
|
</head>
|
|
15
15
|
<body>
|
|
16
16
|
|
|
17
|
-
<!-- Issue #512: First-run "Get started" rail (self-dismissing). Hidden by
|
|
18
|
-
default; shown by JS when bootstrap.firstRun is incomplete and surface=hub. -->
|
|
19
|
-
<div id="gs-rail" class="gs-rail" hidden>
|
|
20
|
-
<span class="gs-rocket">🚀</span>
|
|
21
|
-
<div class="gs-steps" id="gs-steps"></div>
|
|
22
|
-
<button class="gs-cta" id="gs-cta" type="button">Continue setup →</button>
|
|
23
|
-
<button class="gs-hide" id="gs-hide" type="button" title="Hide — it'll wait in the corner">✕</button>
|
|
24
|
-
</div>
|
|
25
|
-
<button id="gs-pill" class="gs-pill" type="button" hidden>🚀 Finish setup</button>
|
|
26
|
-
|
|
27
17
|
<!-- Issue #512: three-area top nav + account menu (surface=hub only). -->
|
|
28
18
|
<nav class="hub-tabs" id="hub-tabs" hidden>
|
|
29
19
|
<button class="hub-tab" type="button" data-area="company">Company</button>
|
|
@@ -63,28 +53,31 @@
|
|
|
63
53
|
<div class="area-shell">
|
|
64
54
|
<nav class="area-rail" id="company-rail"></nav>
|
|
65
55
|
<div class="area-main">
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
<div class="area-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
<
|
|
72
|
-
<div
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
<
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
56
|
+
<!-- Info view: context/learnings accordions shown when no conv is active -->
|
|
57
|
+
<div class="area-info-view" id="company-info-view">
|
|
58
|
+
<div class="hub-area-page">
|
|
59
|
+
<div class="eyebrow">FRAIM Hub</div>
|
|
60
|
+
<div class="area-h1">Company</div>
|
|
61
|
+
<p class="area-lede">Your organization's identity — what you do, how you operate, and the guardrails every employee follows on every job.</p>
|
|
62
|
+
<div id="company-push-banner"></div>
|
|
63
|
+
<details class="ctx-acc" id="company-ctx-acc">
|
|
64
|
+
<summary><span class="ca-chev">▸</span> <span>🏢 Context & rules</span></summary>
|
|
65
|
+
<div class="ctx-acc-body"><div class="card area-profile" id="company-profile"></div></div>
|
|
66
|
+
</details>
|
|
67
|
+
<details class="ctx-acc" id="company-learn-acc">
|
|
68
|
+
<summary><span class="ca-chev">▸</span> <span>🧠 Company learnings</span>
|
|
69
|
+
<span class="ca-note">— org-wide, applied on every project</span></summary>
|
|
70
|
+
<div class="ctx-acc-body"><div id="company-learnings"></div></div>
|
|
71
|
+
</details>
|
|
72
|
+
<!-- Issue #540 R1-R3: AI employee persona grid (collapsed by default) -->
|
|
73
|
+
<details class="ctx-acc" id="company-emp-acc">
|
|
74
|
+
<summary><span class="ca-chev">▸</span> <span>Your AI employees</span></summary>
|
|
75
|
+
<div class="ctx-acc-body"><div id="persona-grid" class="persona-grid"></div></div>
|
|
76
|
+
</details>
|
|
77
|
+
</div>
|
|
84
78
|
</div>
|
|
85
|
-
|
|
86
|
-
<div
|
|
87
|
-
<div id="company-persona-roster" class="persona-roster-grid"></div>
|
|
79
|
+
<!-- Conversation host: the shared .page conversation panel is moved here when a company job is active -->
|
|
80
|
+
<div class="area-conv-host workspace-conv" id="company-conv-host" hidden></div>
|
|
88
81
|
</div>
|
|
89
82
|
</div>
|
|
90
83
|
</section>
|
|
@@ -94,47 +87,35 @@
|
|
|
94
87
|
<div class="area-shell">
|
|
95
88
|
<nav class="area-rail" id="manager-rail"></nav>
|
|
96
89
|
<div class="area-main">
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
<div class="area-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
<
|
|
103
|
-
<
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
<div class="
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
<strong>Your AI employees deserve a strong human manager.</strong>
|
|
124
|
-
<small>Pick a role and we'll pre-fill a candidate search and job description with the qualities of a strong AI manager.</small>
|
|
125
|
-
</div>
|
|
126
|
-
<button class="pr-cta" id="manager-hire-btn" type="button" style="width:auto;margin:0;padding:10px 16px;">Find a manager →</button>
|
|
127
|
-
</div>
|
|
128
|
-
</div>
|
|
129
|
-
</details>
|
|
130
|
-
<!-- Issue #540 R4-R7: Your team pool (collapsed by default) -->
|
|
131
|
-
<details class="ctx-acc" id="manager-team-acc">
|
|
132
|
-
<summary><span class="ca-chev">▸</span> <span>Your team</span></summary>
|
|
133
|
-
<div class="ctx-acc-body"><div id="manager-team-pool" class="manager-team-pool"></div></div>
|
|
134
|
-
</details>
|
|
90
|
+
<!-- Info view: context/learnings accordions shown when no conv is active -->
|
|
91
|
+
<div class="area-info-view" id="manager-info-view">
|
|
92
|
+
<div class="hub-area-page">
|
|
93
|
+
<div class="eyebrow">FRAIM Hub</div>
|
|
94
|
+
<div class="area-h1">Manager</div>
|
|
95
|
+
<p class="area-lede">How you manage — your working style, preferences, and the standing rules your team follows when working with you.</p>
|
|
96
|
+
<details class="ctx-acc" id="manager-ctx-acc">
|
|
97
|
+
<summary><span class="ca-chev">▸</span> <span>🤝 Context & rules</span></summary>
|
|
98
|
+
<div class="ctx-acc-body"><div class="card area-profile" id="manager-profile"></div></div>
|
|
99
|
+
</details>
|
|
100
|
+
<details class="ctx-acc" id="manager-learn-acc">
|
|
101
|
+
<summary><span class="ca-chev">▸</span> <span>🧠 Manager learnings</span>
|
|
102
|
+
<span class="ca-note">— how your team adapts to you</span></summary>
|
|
103
|
+
<div class="ctx-acc-body"><div id="manager-learnings"></div></div>
|
|
104
|
+
</details>
|
|
105
|
+
<details class="ctx-acc" id="manager-reverse-acc">
|
|
106
|
+
<summary><span class="ca-chev">▸</span> <span>🪞 Reverse mentoring</span>
|
|
107
|
+
<span class="ca-note">— what you can improve on as a manager</span></summary>
|
|
108
|
+
<div class="ctx-acc-body"><div id="reverse-mentoring"></div></div>
|
|
109
|
+
</details>
|
|
110
|
+
<!-- Issue #540 R4-R7: Your team pool (collapsed by default) -->
|
|
111
|
+
<details class="ctx-acc" id="manager-team-acc">
|
|
112
|
+
<summary><span class="ca-chev">▸</span> <span>Your team</span></summary>
|
|
113
|
+
<div class="ctx-acc-body"><div id="manager-team-pool" class="manager-team-pool"></div></div>
|
|
114
|
+
</details>
|
|
115
|
+
</div>
|
|
135
116
|
</div>
|
|
136
|
-
|
|
137
|
-
<div
|
|
117
|
+
<!-- Conversation host: the shared .page conversation panel is moved here when a manager job is active -->
|
|
118
|
+
<div class="area-conv-host workspace-conv" id="manager-conv-host" hidden></div>
|
|
138
119
|
</div>
|
|
139
120
|
</div>
|
|
140
121
|
</section>
|
|
@@ -194,10 +175,22 @@
|
|
|
194
175
|
<span class="ca-note">— from <strong>sleep-on-learnings</strong> · promote to a scope</span></summary>
|
|
195
176
|
<div class="ctx-acc-body"><div id="project-learnings"></div></div>
|
|
196
177
|
</details>
|
|
178
|
+
<!-- Issue #578: Scheduled + Reactive Employees — deployment roster -->
|
|
179
|
+
<details class="ctx-acc" id="proj-deployments-acc">
|
|
180
|
+
<summary><span class="ca-chev">▸</span> <span>📋 Assignments</span>
|
|
181
|
+
<span class="ca-note">— scheduled and triggered assignments for this project</span></summary>
|
|
182
|
+
<div class="ctx-acc-body">
|
|
183
|
+
<div id="proj-deployments-list"></div>
|
|
184
|
+
<div class="dep-actions">
|
|
185
|
+
<button class="dep-add-btn" id="dep-add-schedule-btn" type="button">+ Schedule</button>
|
|
186
|
+
<button class="dep-add-btn" id="dep-add-webhook-btn" type="button">+ Trigger</button>
|
|
187
|
+
</div>
|
|
188
|
+
</div>
|
|
189
|
+
</details>
|
|
197
190
|
</div>
|
|
198
191
|
|
|
199
192
|
|
|
200
|
-
<div class="page">
|
|
193
|
+
<div class="page" id="hub-conv-page">
|
|
201
194
|
|
|
202
195
|
<header class="header" style="-webkit-app-region: drag;">
|
|
203
196
|
<h1 class="header-title">Manage your FRAIM Employees</h1>
|
|
@@ -567,32 +560,37 @@
|
|
|
567
560
|
</div>
|
|
568
561
|
</div>
|
|
569
562
|
|
|
570
|
-
<!--
|
|
571
|
-
<div id="
|
|
563
|
+
<!-- #594: Area onboarding pre-flight context modal (org onboarding, learning synthesis, manager agreements) -->
|
|
564
|
+
<div id="area-onboard-modal" class="modal-overlay" hidden>
|
|
572
565
|
<div class="modal-card">
|
|
573
566
|
<div class="modal-hdr">
|
|
574
|
-
<div
|
|
575
|
-
|
|
567
|
+
<div>
|
|
568
|
+
<h2 id="aom-title">Run onboarding</h2>
|
|
569
|
+
<p id="aom-desc">Add any specific focus areas or context before starting.</p>
|
|
570
|
+
</div>
|
|
571
|
+
<button class="modal-close" id="aom-close" type="button">×</button>
|
|
572
|
+
</div>
|
|
573
|
+
<div class="modal-body">
|
|
574
|
+
<div class="np-field">
|
|
575
|
+
<label for="aom-context">Any specific direction for this run? <span class="np-optional">(optional — leave blank to start with defaults)</span></label>
|
|
576
|
+
<textarea id="aom-context" rows="4" placeholder="e.g. Focus on our new remote-work policy and async-first communication norms."></textarea>
|
|
577
|
+
</div>
|
|
578
|
+
</div>
|
|
579
|
+
<div class="modal-footer">
|
|
580
|
+
<button type="button" class="aom-cancel-btn" id="aom-cancel">Cancel</button>
|
|
581
|
+
<button type="button" class="modal-next" id="aom-start">Start →</button>
|
|
576
582
|
</div>
|
|
577
|
-
<div class="modal-body" id="aj-body"></div>
|
|
578
583
|
</div>
|
|
579
584
|
</div>
|
|
580
585
|
|
|
581
|
-
<!-- #
|
|
582
|
-
|
|
583
|
-
<div id="onboard-input-modal" class="modal-overlay" hidden>
|
|
586
|
+
<!-- Issue #512: Assign-job modal (job-first, with locks + per-employee filter) -->
|
|
587
|
+
<div id="assign-job-modal" class="modal-overlay" hidden>
|
|
584
588
|
<div class="modal-card">
|
|
585
589
|
<div class="modal-hdr">
|
|
586
|
-
<div><h2 id="
|
|
587
|
-
<button class="modal-close" id="
|
|
588
|
-
</div>
|
|
589
|
-
<div class="modal-body">
|
|
590
|
-
<textarea id="obi-input" class="obi-input" rows="5" placeholder="e.g. We added a new auth service under /services/auth — please incorporate it and its README. (optional)"></textarea>
|
|
591
|
-
<div class="obi-actions">
|
|
592
|
-
<button class="obi-cancel" id="obi-cancel" type="button">Cancel</button>
|
|
593
|
-
<button class="obi-start" id="obi-start" type="button">Start</button>
|
|
594
|
-
</div>
|
|
590
|
+
<div><h2 id="aj-title">Assign a job</h2><p>Pick the work — we'll route it to the right specialist. Locked jobs need a teammate you haven't hired yet.</p></div>
|
|
591
|
+
<button class="modal-close" id="aj-close" type="button">×</button>
|
|
595
592
|
</div>
|
|
593
|
+
<div class="modal-body" id="aj-body"></div>
|
|
596
594
|
</div>
|
|
597
595
|
</div>
|
|
598
596
|
|
|
@@ -668,6 +666,124 @@
|
|
|
668
666
|
</div>
|
|
669
667
|
</div>
|
|
670
668
|
|
|
669
|
+
<!-- Issue #578: Add Schedule deployment modal -->
|
|
670
|
+
<div id="dep-schedule-modal" class="modal-overlay" hidden>
|
|
671
|
+
<div class="modal-card dep-modal-card">
|
|
672
|
+
<div class="modal-hdr">
|
|
673
|
+
<button class="modal-close" id="dep-schedule-close" type="button" aria-label="Close">×</button>
|
|
674
|
+
<h2 id="dep-sch-modal-title">New Scheduled Assignment</h2>
|
|
675
|
+
<p id="dep-sch-modal-sub">Run a job automatically on a recurring schedule.</p>
|
|
676
|
+
</div>
|
|
677
|
+
<div class="modal-body">
|
|
678
|
+
<div class="hm-field">
|
|
679
|
+
<label for="dep-sch-label">Name</label>
|
|
680
|
+
<input type="text" id="dep-sch-label" placeholder="e.g. Daily standup digest" />
|
|
681
|
+
</div>
|
|
682
|
+
<div class="hm-fieldrow">
|
|
683
|
+
<div class="hm-field">
|
|
684
|
+
<label for="dep-sch-job">Job</label>
|
|
685
|
+
<select id="dep-sch-job"></select>
|
|
686
|
+
</div>
|
|
687
|
+
<div class="hm-field">
|
|
688
|
+
<label for="dep-sch-host">Employee</label>
|
|
689
|
+
<select id="dep-sch-host"></select>
|
|
690
|
+
</div>
|
|
691
|
+
</div>
|
|
692
|
+
<div class="hm-field">
|
|
693
|
+
<label>Runs</label>
|
|
694
|
+
<div class="dep-preset-chips" id="dep-sch-presets">
|
|
695
|
+
<button type="button" class="dep-preset-chip" data-preset="daily">Daily</button>
|
|
696
|
+
<button type="button" class="dep-preset-chip" data-preset="weekdays">Weekdays</button>
|
|
697
|
+
<button type="button" class="dep-preset-chip" data-preset="weekly">Weekly</button>
|
|
698
|
+
<button type="button" class="dep-preset-chip" data-preset="custom">Custom</button>
|
|
699
|
+
</div>
|
|
700
|
+
</div>
|
|
701
|
+
<div id="dep-sch-time-row" class="hm-fieldrow" hidden>
|
|
702
|
+
<div class="hm-field" id="dep-sch-day-field" hidden>
|
|
703
|
+
<label for="dep-sch-day">Day</label>
|
|
704
|
+
<select id="dep-sch-day">
|
|
705
|
+
<option value="1">Monday</option>
|
|
706
|
+
<option value="2">Tuesday</option>
|
|
707
|
+
<option value="3">Wednesday</option>
|
|
708
|
+
<option value="4">Thursday</option>
|
|
709
|
+
<option value="5">Friday</option>
|
|
710
|
+
<option value="6">Saturday</option>
|
|
711
|
+
<option value="0">Sunday</option>
|
|
712
|
+
</select>
|
|
713
|
+
</div>
|
|
714
|
+
<div class="hm-field">
|
|
715
|
+
<label for="dep-sch-time">Time</label>
|
|
716
|
+
<input type="time" id="dep-sch-time" value="09:00" />
|
|
717
|
+
</div>
|
|
718
|
+
</div>
|
|
719
|
+
<div id="dep-sch-custom-row" hidden>
|
|
720
|
+
<div class="hm-field">
|
|
721
|
+
<label for="dep-sch-cron">Cron expression</label>
|
|
722
|
+
<input type="text" id="dep-sch-cron" placeholder="e.g. 0 9 * * 1-5" />
|
|
723
|
+
<p id="dep-sch-cron-preview" class="dep-cron-preview"></p>
|
|
724
|
+
</div>
|
|
725
|
+
</div>
|
|
726
|
+
<!-- hidden cron store for preset modes -->
|
|
727
|
+
<input type="hidden" id="dep-sch-cron-preset" />
|
|
728
|
+
<div class="hm-field">
|
|
729
|
+
<label for="dep-sch-instructions">Instructions <span class="dep-optional">(optional)</span></label>
|
|
730
|
+
<textarea id="dep-sch-instructions" rows="2" placeholder="Optional message sent to the employee at the start of each run"></textarea>
|
|
731
|
+
</div>
|
|
732
|
+
<div class="dep-modal-actions">
|
|
733
|
+
<button type="button" id="dep-sch-save-btn" class="send-button">Add assignment</button>
|
|
734
|
+
<button type="button" id="dep-sch-cancel-btn" class="cancel-button">Cancel</button>
|
|
735
|
+
</div>
|
|
736
|
+
<p id="dep-sch-error" class="dep-error" hidden></p>
|
|
737
|
+
</div>
|
|
738
|
+
</div>
|
|
739
|
+
</div>
|
|
740
|
+
|
|
741
|
+
<!-- Issue #578: Add Webhook deployment modal -->
|
|
742
|
+
<div id="dep-webhook-modal" class="modal-overlay" hidden>
|
|
743
|
+
<div class="modal-card dep-modal-card">
|
|
744
|
+
<div class="modal-hdr">
|
|
745
|
+
<button class="modal-close" id="dep-webhook-close" type="button" aria-label="Close">×</button>
|
|
746
|
+
<h2 id="dep-wh-modal-title">New Triggered Assignment</h2>
|
|
747
|
+
<p>Run a job when an external system calls the inbound URL.</p>
|
|
748
|
+
</div>
|
|
749
|
+
<div class="modal-body">
|
|
750
|
+
<div class="hm-field">
|
|
751
|
+
<label for="dep-wh-label">Name</label>
|
|
752
|
+
<input type="text" id="dep-wh-label" placeholder="e.g. ServiceNow escalation handler" />
|
|
753
|
+
</div>
|
|
754
|
+
<div class="hm-fieldrow">
|
|
755
|
+
<div class="hm-field">
|
|
756
|
+
<label for="dep-wh-job">Job</label>
|
|
757
|
+
<select id="dep-wh-job"></select>
|
|
758
|
+
</div>
|
|
759
|
+
<div class="hm-field">
|
|
760
|
+
<label for="dep-wh-host">Employee</label>
|
|
761
|
+
<select id="dep-wh-host"></select>
|
|
762
|
+
</div>
|
|
763
|
+
</div>
|
|
764
|
+
<div class="hm-field">
|
|
765
|
+
<label for="dep-wh-instructions">Instructions <span class="dep-optional">(optional)</span></label>
|
|
766
|
+
<textarea id="dep-wh-instructions" rows="2" placeholder="Optional context prepended to each triggered run"></textarea>
|
|
767
|
+
</div>
|
|
768
|
+
<div class="dep-modal-actions">
|
|
769
|
+
<button type="button" id="dep-wh-save-btn" class="send-button">Add assignment</button>
|
|
770
|
+
<button type="button" id="dep-wh-cancel-btn" class="cancel-button">Cancel</button>
|
|
771
|
+
</div>
|
|
772
|
+
<p id="dep-wh-error" class="dep-error" hidden></p>
|
|
773
|
+
<div id="dep-wh-inbound-row" class="dep-wh-inbound-reveal" hidden>
|
|
774
|
+
<div class="dep-wh-inbound-header">
|
|
775
|
+
<span class="dep-wh-inbound-label">Inbound URL</span>
|
|
776
|
+
<span class="dep-wh-inbound-hint">POST to this URL from any external system to trigger a run</span>
|
|
777
|
+
</div>
|
|
778
|
+
<div class="dep-inbound-url-row">
|
|
779
|
+
<code id="dep-wh-inbound-url" class="dep-inbound-url"></code>
|
|
780
|
+
<button type="button" id="dep-wh-copy-btn" class="hm-copy-btn">Copy</button>
|
|
781
|
+
</div>
|
|
782
|
+
</div>
|
|
783
|
+
</div>
|
|
784
|
+
</div>
|
|
785
|
+
</div>
|
|
786
|
+
|
|
671
787
|
<!-- Issue #539: Command palette overlay — replaces 2-step modal as job-launch surface -->
|
|
672
788
|
<div id="cp-modal" class="cp-backdrop" role="dialog" aria-modal="true" aria-label="Start a job" hidden>
|
|
673
789
|
<div class="cp-palette">
|
package/public/ai-hub/review.css
CHANGED
|
@@ -104,6 +104,12 @@
|
|
|
104
104
|
font-weight: 700;
|
|
105
105
|
}
|
|
106
106
|
.review-actions .rb-approve:hover { filter: brightness(0.94); }
|
|
107
|
+
.review-actions .rb-approve:disabled,
|
|
108
|
+
.review-actions .rb-approve.managed-disabled {
|
|
109
|
+
background: var(--soft, #e8e8e8);
|
|
110
|
+
color: var(--muted, #888);
|
|
111
|
+
filter: none;
|
|
112
|
+
}
|
|
107
113
|
.review-actions .rb-secondary {
|
|
108
114
|
background: var(--warn, #f57c00);
|
|
109
115
|
border: none;
|
|
@@ -114,6 +120,12 @@
|
|
|
114
120
|
color: #fff;
|
|
115
121
|
}
|
|
116
122
|
.review-actions .rb-secondary:hover { filter: brightness(0.94); }
|
|
123
|
+
.review-actions .rb-secondary:disabled,
|
|
124
|
+
.review-actions .rb-secondary.managed-disabled {
|
|
125
|
+
background: var(--soft, #e8e8e8);
|
|
126
|
+
color: var(--muted, #888);
|
|
127
|
+
filter: none;
|
|
128
|
+
}
|
|
117
129
|
.review-actions .rb-handoff {
|
|
118
130
|
font-size: 12px;
|
|
119
131
|
color: var(--muted);
|