human-in-the-loop 0.1.0 → 2.0.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/.turbo/turbo-build.log +5 -0
- package/CHANGELOG.md +17 -0
- package/README.md +600 -166
- package/dist/helpers.d.ts +308 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +275 -0
- package/dist/helpers.js.map +1 -0
- package/dist/human.d.ts +315 -0
- package/dist/human.d.ts.map +1 -0
- package/dist/human.js +476 -0
- package/dist/human.js.map +1 -0
- package/dist/index.d.ts +48 -343
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -793
- package/dist/index.js.map +1 -0
- package/dist/store.d.ts +61 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +162 -0
- package/dist/store.js.map +1 -0
- package/dist/types.d.ts +399 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/examples/basic-usage.ts +386 -0
- package/package.json +23 -54
- package/src/helpers.ts +379 -0
- package/src/human.test.ts +384 -0
- package/src/human.ts +626 -0
- package/src/index.ts +102 -6
- package/src/store.ts +201 -0
- package/src/types.ts +431 -0
- package/tsconfig.json +6 -11
- package/TODO.md +0 -53
- package/dist/index.cjs +0 -899
- package/dist/index.d.cts +0 -344
- package/src/core/factory.test.ts +0 -69
- package/src/core/factory.ts +0 -30
- package/src/core/types.ts +0 -191
- package/src/platforms/email/index.tsx +0 -137
- package/src/platforms/react/index.tsx +0 -218
- package/src/platforms/slack/index.ts +0 -84
- package/src/platforms/teams/index.ts +0 -84
- package/vitest.config.ts +0 -15
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basic usage examples for human-in-the-loop
|
|
3
|
+
*
|
|
4
|
+
* This file demonstrates common patterns and use cases
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
Human,
|
|
9
|
+
Role,
|
|
10
|
+
Team,
|
|
11
|
+
Goals,
|
|
12
|
+
approve,
|
|
13
|
+
ask,
|
|
14
|
+
decide,
|
|
15
|
+
notify,
|
|
16
|
+
kpis,
|
|
17
|
+
okrs,
|
|
18
|
+
registerHuman,
|
|
19
|
+
type HumanType,
|
|
20
|
+
type ApprovalResponse,
|
|
21
|
+
} from '../src/index.js'
|
|
22
|
+
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// Setup: Define roles, teams, and humans
|
|
25
|
+
// ============================================================================
|
|
26
|
+
|
|
27
|
+
// Define roles
|
|
28
|
+
const techLead = Role({
|
|
29
|
+
id: 'tech-lead',
|
|
30
|
+
name: 'Tech Lead',
|
|
31
|
+
description: 'Technical leadership and architecture decisions',
|
|
32
|
+
capabilities: ['approve-prs', 'deploy-prod', 'review-code'],
|
|
33
|
+
escalatesTo: 'engineering-manager',
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const engineer = Role({
|
|
37
|
+
id: 'engineer',
|
|
38
|
+
name: 'Software Engineer',
|
|
39
|
+
description: 'Software development',
|
|
40
|
+
capabilities: ['write-code', 'review-code'],
|
|
41
|
+
escalatesTo: 'tech-lead',
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
// Define teams
|
|
45
|
+
const engineeringTeam = Team({
|
|
46
|
+
id: 'engineering',
|
|
47
|
+
name: 'Engineering Team',
|
|
48
|
+
description: 'Product development team',
|
|
49
|
+
members: ['alice', 'bob', 'charlie'],
|
|
50
|
+
lead: 'alice',
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
// Register humans
|
|
54
|
+
const alice: HumanType = registerHuman({
|
|
55
|
+
id: 'alice',
|
|
56
|
+
name: 'Alice Smith',
|
|
57
|
+
email: 'alice@example.com',
|
|
58
|
+
roles: ['tech-lead'],
|
|
59
|
+
teams: ['engineering'],
|
|
60
|
+
channels: {
|
|
61
|
+
slack: '@alice',
|
|
62
|
+
email: 'alice@example.com',
|
|
63
|
+
web: true,
|
|
64
|
+
},
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
const bob: HumanType = registerHuman({
|
|
68
|
+
id: 'bob',
|
|
69
|
+
name: 'Bob Johnson',
|
|
70
|
+
email: 'bob@example.com',
|
|
71
|
+
roles: ['engineer'],
|
|
72
|
+
teams: ['engineering'],
|
|
73
|
+
channels: {
|
|
74
|
+
slack: '@bob',
|
|
75
|
+
email: 'bob@example.com',
|
|
76
|
+
},
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
// ============================================================================
|
|
80
|
+
// Example 1: Approval workflow
|
|
81
|
+
// ============================================================================
|
|
82
|
+
|
|
83
|
+
async function approvalExample() {
|
|
84
|
+
console.log('=== Approval Example ===\n')
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
// Request approval for production deployment
|
|
88
|
+
const deployment: ApprovalResponse = await approve({
|
|
89
|
+
title: 'Production Deployment',
|
|
90
|
+
description: 'Deploy version 2.0.0 to production',
|
|
91
|
+
subject: 'Production Deployment - v2.0.0',
|
|
92
|
+
input: {
|
|
93
|
+
version: '2.0.0',
|
|
94
|
+
environment: 'production',
|
|
95
|
+
changes: ['New AI features', 'Performance improvements', 'Bug fixes'],
|
|
96
|
+
},
|
|
97
|
+
assignee: alice.email,
|
|
98
|
+
priority: 'high',
|
|
99
|
+
timeout: 3600000, // 1 hour
|
|
100
|
+
escalatesTo: 'engineering-manager',
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
if (deployment.approved) {
|
|
104
|
+
console.log('✅ Deployment approved!')
|
|
105
|
+
console.log('Comments:', deployment.comments)
|
|
106
|
+
|
|
107
|
+
// Proceed with deployment
|
|
108
|
+
await deploy()
|
|
109
|
+
|
|
110
|
+
// Send success notification
|
|
111
|
+
await notify({
|
|
112
|
+
type: 'success',
|
|
113
|
+
title: 'Deployment Complete',
|
|
114
|
+
message: 'Version 2.0.0 successfully deployed to production',
|
|
115
|
+
recipient: [alice.email!, engineeringTeam.id],
|
|
116
|
+
channels: ['slack', 'email'],
|
|
117
|
+
priority: 'normal',
|
|
118
|
+
})
|
|
119
|
+
} else {
|
|
120
|
+
console.log('❌ Deployment rejected')
|
|
121
|
+
console.log('Reason:', deployment.comments)
|
|
122
|
+
}
|
|
123
|
+
} catch (error) {
|
|
124
|
+
console.error('Approval failed:', error)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// ============================================================================
|
|
129
|
+
// Example 2: Ask a question
|
|
130
|
+
// ============================================================================
|
|
131
|
+
|
|
132
|
+
async function questionExample() {
|
|
133
|
+
console.log('\n=== Question Example ===\n')
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
const answer = await ask({
|
|
137
|
+
title: 'Product Naming Decision',
|
|
138
|
+
question: 'What should we name the new AI assistant feature?',
|
|
139
|
+
context: {
|
|
140
|
+
feature: 'AI-powered code assistant',
|
|
141
|
+
targetAudience: 'developers',
|
|
142
|
+
competitors: ['GitHub Copilot', 'Cursor', 'Tabnine'],
|
|
143
|
+
},
|
|
144
|
+
assignee: 'product-manager@example.com',
|
|
145
|
+
suggestions: ['CodeMate', 'DevAssist', 'SmartCode', 'AIHelper'],
|
|
146
|
+
priority: 'normal',
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
console.log('Answer received:', answer)
|
|
150
|
+
} catch (error) {
|
|
151
|
+
console.error('Question failed:', error)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ============================================================================
|
|
156
|
+
// Example 3: Decision with options
|
|
157
|
+
// ============================================================================
|
|
158
|
+
|
|
159
|
+
async function decisionExample() {
|
|
160
|
+
console.log('\n=== Decision Example ===\n')
|
|
161
|
+
|
|
162
|
+
try {
|
|
163
|
+
const strategy = await decide({
|
|
164
|
+
title: 'Deployment Strategy',
|
|
165
|
+
description: 'Choose the deployment strategy for the new release',
|
|
166
|
+
options: ['blue-green', 'canary', 'rolling', 'all-at-once'],
|
|
167
|
+
context: {
|
|
168
|
+
riskLevel: 'high',
|
|
169
|
+
activeUsers: 100000,
|
|
170
|
+
deploymentWindow: '2 hours',
|
|
171
|
+
rollbackTime: '5 minutes',
|
|
172
|
+
},
|
|
173
|
+
criteria: [
|
|
174
|
+
'Minimize risk to users',
|
|
175
|
+
'Enable fast rollback',
|
|
176
|
+
'Complete within deployment window',
|
|
177
|
+
],
|
|
178
|
+
assignee: alice.email,
|
|
179
|
+
priority: 'high',
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
console.log('Selected strategy:', strategy)
|
|
183
|
+
} catch (error) {
|
|
184
|
+
console.error('Decision failed:', error)
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ============================================================================
|
|
189
|
+
// Example 4: Goals and OKRs
|
|
190
|
+
// ============================================================================
|
|
191
|
+
|
|
192
|
+
function goalsExample() {
|
|
193
|
+
console.log('\n=== Goals and OKRs Example ===\n')
|
|
194
|
+
|
|
195
|
+
// Define team goals
|
|
196
|
+
const q1Goals = Goals({
|
|
197
|
+
id: 'engineering-q1-2024',
|
|
198
|
+
objectives: [
|
|
199
|
+
'Launch AI assistant v2.0',
|
|
200
|
+
'Improve system performance by 50%',
|
|
201
|
+
'Reduce bug count by 40%',
|
|
202
|
+
],
|
|
203
|
+
successCriteria: [
|
|
204
|
+
'Release by March 31',
|
|
205
|
+
'Pass all performance benchmarks',
|
|
206
|
+
'Achieve customer satisfaction score of 4.5+',
|
|
207
|
+
],
|
|
208
|
+
targetDate: new Date('2024-03-31'),
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
console.log('Q1 Goals:', q1Goals)
|
|
212
|
+
|
|
213
|
+
// Define OKRs
|
|
214
|
+
const q1OKRs = okrs({
|
|
215
|
+
id: 'engineering-okrs-q1-2024',
|
|
216
|
+
objective: 'Build world-class AI development tools',
|
|
217
|
+
keyResults: [
|
|
218
|
+
{
|
|
219
|
+
description: 'Increase active users by 50%',
|
|
220
|
+
progress: 0.3,
|
|
221
|
+
current: 13000,
|
|
222
|
+
target: 15000,
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
description: 'Achieve 95% uptime',
|
|
226
|
+
progress: 0.92,
|
|
227
|
+
current: 0.95,
|
|
228
|
+
target: 0.95,
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
description: 'Reduce average response time to <100ms',
|
|
232
|
+
progress: 0.75,
|
|
233
|
+
current: 120,
|
|
234
|
+
target: 100,
|
|
235
|
+
},
|
|
236
|
+
],
|
|
237
|
+
period: 'Q1 2024',
|
|
238
|
+
owner: alice.email,
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
console.log('Q1 OKRs:', q1OKRs)
|
|
242
|
+
|
|
243
|
+
// Track KPIs
|
|
244
|
+
const performanceKPI = kpis({
|
|
245
|
+
id: 'api-response-time',
|
|
246
|
+
name: 'API Response Time',
|
|
247
|
+
value: 120,
|
|
248
|
+
target: 100,
|
|
249
|
+
unit: 'ms',
|
|
250
|
+
trend: 'down',
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
console.log('Performance KPI:', performanceKPI)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// ============================================================================
|
|
257
|
+
// Example 5: Using Human instance for advanced operations
|
|
258
|
+
// ============================================================================
|
|
259
|
+
|
|
260
|
+
async function advancedExample() {
|
|
261
|
+
console.log('\n=== Advanced Example ===\n')
|
|
262
|
+
|
|
263
|
+
// Create a custom Human instance with specific configuration
|
|
264
|
+
const human = Human({
|
|
265
|
+
defaultTimeout: 7200000, // 2 hours
|
|
266
|
+
defaultPriority: 'high',
|
|
267
|
+
autoEscalate: true,
|
|
268
|
+
escalationPolicies: [
|
|
269
|
+
{
|
|
270
|
+
id: 'critical-approval',
|
|
271
|
+
name: 'Critical Approval Policy',
|
|
272
|
+
conditions: {
|
|
273
|
+
timeout: 1800000, // 30 minutes
|
|
274
|
+
minPriority: 'critical',
|
|
275
|
+
},
|
|
276
|
+
escalationPath: [
|
|
277
|
+
{
|
|
278
|
+
assignee: 'tech-lead',
|
|
279
|
+
afterMs: 1800000, // 30 minutes
|
|
280
|
+
notifyVia: ['slack', 'sms'],
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
assignee: 'engineering-manager',
|
|
284
|
+
afterMs: 3600000, // 1 hour
|
|
285
|
+
notifyVia: ['slack', 'email', 'sms'],
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
assignee: 'cto',
|
|
289
|
+
afterMs: 7200000, // 2 hours
|
|
290
|
+
notifyVia: ['slack', 'email', 'sms'],
|
|
291
|
+
},
|
|
292
|
+
],
|
|
293
|
+
},
|
|
294
|
+
],
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
// Create an approval workflow
|
|
298
|
+
const deploymentWorkflow = human.createWorkflow({
|
|
299
|
+
id: 'prod-deployment-workflow',
|
|
300
|
+
name: 'Production Deployment Workflow',
|
|
301
|
+
steps: [
|
|
302
|
+
{
|
|
303
|
+
name: 'Code Review',
|
|
304
|
+
role: 'engineer',
|
|
305
|
+
approvers: [bob.id],
|
|
306
|
+
requireAll: true,
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
name: 'Security Review',
|
|
310
|
+
role: 'security-engineer',
|
|
311
|
+
approvers: ['security-team'],
|
|
312
|
+
requireAll: false,
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
name: 'Tech Lead Approval',
|
|
316
|
+
role: 'tech-lead',
|
|
317
|
+
approvers: [alice.id],
|
|
318
|
+
requireAll: true,
|
|
319
|
+
},
|
|
320
|
+
],
|
|
321
|
+
currentStep: 0,
|
|
322
|
+
status: 'pending',
|
|
323
|
+
})
|
|
324
|
+
|
|
325
|
+
console.log('Created workflow:', deploymentWorkflow)
|
|
326
|
+
|
|
327
|
+
// Get the review queue
|
|
328
|
+
const queue = await human.getQueue({
|
|
329
|
+
name: 'High Priority Queue',
|
|
330
|
+
description: 'All high priority pending requests',
|
|
331
|
+
filters: {
|
|
332
|
+
status: ['pending', 'in_progress'],
|
|
333
|
+
priority: ['high', 'critical'],
|
|
334
|
+
},
|
|
335
|
+
sortBy: 'priority',
|
|
336
|
+
sortDirection: 'desc',
|
|
337
|
+
limit: 10,
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
console.log('Queue:', queue.name, 'Items:', queue.items.length)
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// ============================================================================
|
|
344
|
+
// Mock deployment function
|
|
345
|
+
// ============================================================================
|
|
346
|
+
|
|
347
|
+
async function deploy() {
|
|
348
|
+
console.log('🚀 Deploying to production...')
|
|
349
|
+
// Simulate deployment
|
|
350
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
351
|
+
console.log('✅ Deployment successful!')
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// ============================================================================
|
|
355
|
+
// Run examples
|
|
356
|
+
// ============================================================================
|
|
357
|
+
|
|
358
|
+
async function main() {
|
|
359
|
+
console.log('Human-in-the-Loop Examples\n')
|
|
360
|
+
console.log('Note: These examples demonstrate the API.')
|
|
361
|
+
console.log('Actual human responses would need to be provided via the store.\n')
|
|
362
|
+
|
|
363
|
+
// Run examples (most will timeout or error without actual human responses)
|
|
364
|
+
// In a real system, humans would respond via UI, webhooks, or API calls
|
|
365
|
+
|
|
366
|
+
goalsExample()
|
|
367
|
+
|
|
368
|
+
// Uncomment to test async examples (they will wait for human responses)
|
|
369
|
+
// await approvalExample()
|
|
370
|
+
// await questionExample()
|
|
371
|
+
// await decisionExample()
|
|
372
|
+
// await advancedExample()
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// Run if executed directly
|
|
376
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
377
|
+
main().catch(console.error)
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
export {
|
|
381
|
+
approvalExample,
|
|
382
|
+
questionExample,
|
|
383
|
+
decisionExample,
|
|
384
|
+
goalsExample,
|
|
385
|
+
advancedExample,
|
|
386
|
+
}
|
package/package.json
CHANGED
|
@@ -1,65 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "human-in-the-loop",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.0.2",
|
|
4
|
+
"description": "Primitives for integrating human oversight and intervention in AI workflows",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"main": "dist/index.js",
|
|
6
|
-
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"require": "./dist/index.js"
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
13
12
|
}
|
|
14
13
|
},
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"email"
|
|
23
|
-
],
|
|
24
|
-
"author": "Drivly",
|
|
25
|
-
"license": "MIT",
|
|
26
|
-
"repository": {
|
|
27
|
-
"type": "git",
|
|
28
|
-
"url": "https://github.com/drivly/primitives.org.ai.git"
|
|
29
|
-
},
|
|
30
|
-
"bugs": {
|
|
31
|
-
"url": "https://github.com/drivly/primitives.org.ai/issues"
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"dev": "tsc --watch",
|
|
17
|
+
"test": "vitest",
|
|
18
|
+
"typecheck": "tsc --noEmit",
|
|
19
|
+
"lint": "eslint .",
|
|
20
|
+
"clean": "rm -rf dist"
|
|
32
21
|
},
|
|
33
|
-
"homepage": "https://primitives.org.ai",
|
|
34
22
|
"dependencies": {
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
"peerDependencies": {
|
|
39
|
-
"react": "^19.0.0",
|
|
40
|
-
"react-dom": "^19.0.0",
|
|
41
|
-
"react-email": "^1.10.0"
|
|
23
|
+
"ai-functions": "2.0.2",
|
|
24
|
+
"digital-workers": "2.0.2",
|
|
25
|
+
"rpc.do": "^0.1.0"
|
|
42
26
|
},
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"vitest": "^3.0.9"
|
|
52
|
-
},
|
|
53
|
-
"type": "module",
|
|
54
|
-
"engines": {
|
|
55
|
-
"node": ">=18"
|
|
56
|
-
},
|
|
57
|
-
"scripts": {
|
|
58
|
-
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
59
|
-
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
60
|
-
"test": "vitest run",
|
|
61
|
-
"test:watch": "vitest",
|
|
62
|
-
"lint": "eslint .",
|
|
63
|
-
"format": "prettier --write ."
|
|
64
|
-
}
|
|
65
|
-
}
|
|
27
|
+
"keywords": [
|
|
28
|
+
"human",
|
|
29
|
+
"oversight",
|
|
30
|
+
"hitl",
|
|
31
|
+
"primitives"
|
|
32
|
+
],
|
|
33
|
+
"license": "MIT"
|
|
34
|
+
}
|