maqam 0.1.0
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 +21 -0
- package/README.md +176 -0
- package/app/app.js +113 -0
- package/app/assets/maqam-brand-board.png +0 -0
- package/app/assets/maqam-logo.svg +17 -0
- package/app/assets/maqam-readme-hero.png +0 -0
- package/app/assets/maqam-system-map.svg +114 -0
- package/app/index.html +113 -0
- package/app/styles.css +397 -0
- package/bin/ajnas-crawl.js +119 -0
- package/bin/maqam.js +22 -0
- package/package.json +74 -0
- package/src/framework/errors.js +35 -0
- package/src/framework/evidence-ledger.js +72 -0
- package/src/framework/policy.js +119 -0
- package/src/framework/research-workflow.js +80 -0
- package/src/framework/runtime.js +101 -0
- package/src/framework/skill-registry.js +52 -0
- package/src/framework/tool-gateway.js +65 -0
- package/src/index.js +351 -0
- package/src/maqam/server.js +189 -0
package/app/styles.css
ADDED
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
color-scheme: dark;
|
|
3
|
+
--bg: #080d0c;
|
|
4
|
+
--panel: #111816;
|
|
5
|
+
--panel-2: #18211f;
|
|
6
|
+
--line: #2d3935;
|
|
7
|
+
--text: #f4f7f3;
|
|
8
|
+
--muted: #a9b7b0;
|
|
9
|
+
--blue: #48c7ff;
|
|
10
|
+
--green: #84e07f;
|
|
11
|
+
--danger: #ff7a73;
|
|
12
|
+
--radius: 14px;
|
|
13
|
+
font-family: "Aptos", "Segoe UI", sans-serif;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
* {
|
|
17
|
+
box-sizing: border-box;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
body {
|
|
21
|
+
margin: 0;
|
|
22
|
+
background:
|
|
23
|
+
linear-gradient(135deg, rgb(72 199 255 / .08), transparent 35%),
|
|
24
|
+
linear-gradient(315deg, rgb(132 224 127 / .08), transparent 42%),
|
|
25
|
+
var(--bg);
|
|
26
|
+
color: var(--text);
|
|
27
|
+
min-width: 320px;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
a {
|
|
31
|
+
color: inherit;
|
|
32
|
+
text-decoration: none;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.shell {
|
|
36
|
+
width: min(1180px, calc(100% - 32px));
|
|
37
|
+
margin: 0 auto;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.topbar {
|
|
41
|
+
min-height: 76px;
|
|
42
|
+
display: flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
justify-content: space-between;
|
|
45
|
+
gap: 24px;
|
|
46
|
+
border-bottom: 1px solid var(--line);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.brand {
|
|
50
|
+
display: inline-flex;
|
|
51
|
+
align-items: center;
|
|
52
|
+
gap: 12px;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.brand img {
|
|
56
|
+
border-radius: 12px;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.brand span {
|
|
60
|
+
display: grid;
|
|
61
|
+
gap: 2px;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.brand strong {
|
|
65
|
+
font-size: 1rem;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.brand small,
|
|
69
|
+
.hint,
|
|
70
|
+
.section-heading p,
|
|
71
|
+
.policy-band p,
|
|
72
|
+
.metrics span {
|
|
73
|
+
color: var(--muted);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.nav {
|
|
77
|
+
display: flex;
|
|
78
|
+
gap: 6px;
|
|
79
|
+
padding: 6px;
|
|
80
|
+
border: 1px solid var(--line);
|
|
81
|
+
border-radius: 999px;
|
|
82
|
+
background: rgb(17 24 22 / .8);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.nav a {
|
|
86
|
+
color: var(--muted);
|
|
87
|
+
padding: 8px 12px;
|
|
88
|
+
border-radius: 999px;
|
|
89
|
+
font-size: .92rem;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.nav a:hover {
|
|
93
|
+
color: var(--text);
|
|
94
|
+
background: rgb(244 247 243 / .08);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.hero {
|
|
98
|
+
min-height: calc(100dvh - 76px);
|
|
99
|
+
display: grid;
|
|
100
|
+
grid-template-columns: minmax(0, 1.08fr) minmax(340px, .72fr);
|
|
101
|
+
align-items: center;
|
|
102
|
+
gap: 52px;
|
|
103
|
+
padding: 52px 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.kicker {
|
|
107
|
+
color: var(--green);
|
|
108
|
+
font-weight: 700;
|
|
109
|
+
margin: 0 0 20px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
h1,
|
|
113
|
+
h2,
|
|
114
|
+
p {
|
|
115
|
+
margin-top: 0;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
h1 {
|
|
119
|
+
max-width: 820px;
|
|
120
|
+
font-size: clamp(3rem, 8vw, 7.6rem);
|
|
121
|
+
line-height: .96;
|
|
122
|
+
letter-spacing: 0;
|
|
123
|
+
margin-bottom: 28px;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
h2 {
|
|
127
|
+
font-size: 1.35rem;
|
|
128
|
+
letter-spacing: 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.lede {
|
|
132
|
+
max-width: 680px;
|
|
133
|
+
color: var(--muted);
|
|
134
|
+
font-size: 1.2rem;
|
|
135
|
+
line-height: 1.65;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.run-panel,
|
|
139
|
+
.metrics article,
|
|
140
|
+
.stack > article,
|
|
141
|
+
.policy-band {
|
|
142
|
+
border: 1px solid var(--line);
|
|
143
|
+
border-radius: var(--radius);
|
|
144
|
+
background: linear-gradient(180deg, rgb(244 247 243 / .06), rgb(244 247 243 / .025));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.run-panel {
|
|
148
|
+
padding: 22px;
|
|
149
|
+
box-shadow: 0 24px 80px rgb(0 0 0 / .22);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.panel-header {
|
|
153
|
+
display: flex;
|
|
154
|
+
justify-content: space-between;
|
|
155
|
+
gap: 16px;
|
|
156
|
+
margin-bottom: 24px;
|
|
157
|
+
color: var(--muted);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.panel-header strong {
|
|
161
|
+
color: var(--green);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
form {
|
|
165
|
+
display: grid;
|
|
166
|
+
gap: 16px;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
label {
|
|
170
|
+
display: grid;
|
|
171
|
+
gap: 8px;
|
|
172
|
+
color: var(--muted);
|
|
173
|
+
font-size: .94rem;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
input,
|
|
177
|
+
select {
|
|
178
|
+
width: 100%;
|
|
179
|
+
min-height: 46px;
|
|
180
|
+
border: 1px solid var(--line);
|
|
181
|
+
border-radius: 10px;
|
|
182
|
+
background: var(--panel);
|
|
183
|
+
color: var(--text);
|
|
184
|
+
padding: 0 12px;
|
|
185
|
+
font: inherit;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
input:focus,
|
|
189
|
+
select:focus,
|
|
190
|
+
button:focus-visible,
|
|
191
|
+
a:focus-visible {
|
|
192
|
+
outline: 3px solid rgb(72 199 255 / .45);
|
|
193
|
+
outline-offset: 2px;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.form-grid {
|
|
197
|
+
display: grid;
|
|
198
|
+
grid-template-columns: 1fr 1fr;
|
|
199
|
+
gap: 12px;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
button {
|
|
203
|
+
min-height: 48px;
|
|
204
|
+
border: 0;
|
|
205
|
+
border-radius: 999px;
|
|
206
|
+
background: var(--text);
|
|
207
|
+
color: #0c1110;
|
|
208
|
+
font: inherit;
|
|
209
|
+
font-weight: 800;
|
|
210
|
+
cursor: pointer;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
button:hover {
|
|
214
|
+
background: var(--green);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
button:active {
|
|
218
|
+
transform: translateY(1px);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
button:disabled {
|
|
222
|
+
cursor: wait;
|
|
223
|
+
opacity: .7;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.hint {
|
|
227
|
+
margin: 0;
|
|
228
|
+
font-size: .9rem;
|
|
229
|
+
line-height: 1.5;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.metrics {
|
|
233
|
+
display: grid;
|
|
234
|
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
235
|
+
gap: 14px;
|
|
236
|
+
margin-bottom: 26px;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.metrics article {
|
|
240
|
+
padding: 18px;
|
|
241
|
+
display: grid;
|
|
242
|
+
gap: 8px;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.metrics strong {
|
|
246
|
+
font-size: 1.25rem;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.workspace {
|
|
250
|
+
display: grid;
|
|
251
|
+
grid-template-columns: 1fr 1fr;
|
|
252
|
+
gap: 26px;
|
|
253
|
+
padding: 38px 0;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.section-heading {
|
|
257
|
+
border-bottom: 1px solid var(--line);
|
|
258
|
+
margin-bottom: 16px;
|
|
259
|
+
padding-bottom: 14px;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.section-heading p {
|
|
263
|
+
margin-bottom: 0;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.stack {
|
|
267
|
+
display: grid;
|
|
268
|
+
gap: 12px;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.empty {
|
|
272
|
+
min-height: 150px;
|
|
273
|
+
align-content: center;
|
|
274
|
+
padding: 20px;
|
|
275
|
+
border: 1px dashed var(--line);
|
|
276
|
+
border-radius: var(--radius);
|
|
277
|
+
color: var(--muted);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.stack > article {
|
|
281
|
+
padding: 16px;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.stack h3 {
|
|
285
|
+
margin: 0 0 8px;
|
|
286
|
+
font-size: 1rem;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.stack p {
|
|
290
|
+
color: var(--muted);
|
|
291
|
+
line-height: 1.55;
|
|
292
|
+
margin-bottom: 12px;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.tag-row {
|
|
296
|
+
display: flex;
|
|
297
|
+
flex-wrap: wrap;
|
|
298
|
+
gap: 8px;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
.tag {
|
|
302
|
+
display: inline-flex;
|
|
303
|
+
align-items: center;
|
|
304
|
+
min-height: 28px;
|
|
305
|
+
padding: 0 10px;
|
|
306
|
+
border-radius: 999px;
|
|
307
|
+
border: 1px solid var(--line);
|
|
308
|
+
color: var(--green);
|
|
309
|
+
background: rgb(132 224 127 / .08);
|
|
310
|
+
font-size: .82rem;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.policy-band {
|
|
314
|
+
display: grid;
|
|
315
|
+
grid-template-columns: .9fr 1.1fr;
|
|
316
|
+
gap: 24px;
|
|
317
|
+
padding: 24px;
|
|
318
|
+
margin: 20px 0 54px;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.policy-band ol {
|
|
322
|
+
margin: 0;
|
|
323
|
+
display: grid;
|
|
324
|
+
gap: 10px;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
.policy-band li {
|
|
328
|
+
color: var(--muted);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.error {
|
|
332
|
+
color: var(--danger);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
@media (max-width: 860px) {
|
|
336
|
+
.topbar,
|
|
337
|
+
.hero,
|
|
338
|
+
.workspace,
|
|
339
|
+
.policy-band {
|
|
340
|
+
grid-template-columns: 1fr;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.topbar {
|
|
344
|
+
align-items: flex-start;
|
|
345
|
+
flex-direction: column;
|
|
346
|
+
padding: 16px 0;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
.nav {
|
|
350
|
+
width: 100%;
|
|
351
|
+
justify-content: space-between;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
.hero {
|
|
355
|
+
min-height: auto;
|
|
356
|
+
padding: 38px 0;
|
|
357
|
+
gap: 30px;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.run-panel {
|
|
361
|
+
order: -1;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
h1 {
|
|
365
|
+
font-size: clamp(2.35rem, 11vw, 3.6rem);
|
|
366
|
+
line-height: 1.02;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.metrics {
|
|
370
|
+
grid-template-columns: 1fr 1fr;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
@media (max-width: 560px) {
|
|
375
|
+
.shell {
|
|
376
|
+
width: min(100% - 24px, 1180px);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.metrics,
|
|
380
|
+
.form-grid {
|
|
381
|
+
grid-template-columns: 1fr;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
.nav a {
|
|
385
|
+
padding-inline: 9px;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
@media (prefers-reduced-motion: reduce) {
|
|
390
|
+
*,
|
|
391
|
+
*::before,
|
|
392
|
+
*::after {
|
|
393
|
+
scroll-behavior: auto !important;
|
|
394
|
+
transition: none !important;
|
|
395
|
+
animation: none !important;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createWriteStream } from "node:fs";
|
|
3
|
+
import { crawl } from "../src/index.js";
|
|
4
|
+
|
|
5
|
+
function usage() {
|
|
6
|
+
console.log(`
|
|
7
|
+
Maqam Crawler
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
maqam-crawl <url> [more urls...] [options]
|
|
11
|
+
|
|
12
|
+
Options:
|
|
13
|
+
--max-pages <n> Maximum pages to return. Default: 50
|
|
14
|
+
--concurrency <n> Concurrent workers. Default: 4
|
|
15
|
+
--delay <ms> Minimum delay per origin. Default: 250
|
|
16
|
+
--timeout <ms> Request timeout. Default: 15000
|
|
17
|
+
--sitemaps Discover URLs from robots.txt sitemaps and /sitemap.xml
|
|
18
|
+
--all-origins Allow crawling across origins discovered from links
|
|
19
|
+
--jsonl Output JSON Lines instead of a JSON array
|
|
20
|
+
--output <file> Write output to a file
|
|
21
|
+
--user-agent <ua> Custom user agent
|
|
22
|
+
--help Show this help
|
|
23
|
+
|
|
24
|
+
This crawler is Maqam's first governed connector. It respects robots.txt by default and does not bypass access controls.
|
|
25
|
+
`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function readArgs(argv) {
|
|
29
|
+
const urls = [];
|
|
30
|
+
const options = {
|
|
31
|
+
maxPages: 50,
|
|
32
|
+
concurrency: 4,
|
|
33
|
+
delayMs: 250,
|
|
34
|
+
timeoutMs: 15_000,
|
|
35
|
+
includeSitemaps: false,
|
|
36
|
+
sameOrigin: true,
|
|
37
|
+
jsonl: false,
|
|
38
|
+
output: null,
|
|
39
|
+
userAgent: undefined
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
43
|
+
const arg = argv[i];
|
|
44
|
+
if (arg === "--help" || arg === "-h") {
|
|
45
|
+
options.help = true;
|
|
46
|
+
} else if (arg === "--max-pages") {
|
|
47
|
+
options.maxPages = Number(argv[++i]);
|
|
48
|
+
} else if (arg === "--concurrency") {
|
|
49
|
+
options.concurrency = Number(argv[++i]);
|
|
50
|
+
} else if (arg === "--delay") {
|
|
51
|
+
options.delayMs = Number(argv[++i]);
|
|
52
|
+
} else if (arg === "--timeout") {
|
|
53
|
+
options.timeoutMs = Number(argv[++i]);
|
|
54
|
+
} else if (arg === "--sitemaps") {
|
|
55
|
+
options.includeSitemaps = true;
|
|
56
|
+
} else if (arg === "--all-origins") {
|
|
57
|
+
options.sameOrigin = false;
|
|
58
|
+
} else if (arg === "--jsonl") {
|
|
59
|
+
options.jsonl = true;
|
|
60
|
+
} else if (arg === "--output" || arg === "-o") {
|
|
61
|
+
options.output = argv[++i];
|
|
62
|
+
} else if (arg === "--user-agent") {
|
|
63
|
+
options.userAgent = argv[++i];
|
|
64
|
+
} else if (arg.startsWith("-")) {
|
|
65
|
+
throw new Error(`Unknown option: ${arg}`);
|
|
66
|
+
} else {
|
|
67
|
+
urls.push(arg);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return { urls, options };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function writeOutput(pages, options) {
|
|
75
|
+
const body = options.jsonl
|
|
76
|
+
? pages.map((page) => JSON.stringify(page)).join("\n") + "\n"
|
|
77
|
+
: JSON.stringify(pages, null, 2) + "\n";
|
|
78
|
+
|
|
79
|
+
if (!options.output) {
|
|
80
|
+
process.stdout.write(body);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const stream = createWriteStream(options.output, { encoding: "utf8" });
|
|
84
|
+
stream.end(body);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function main() {
|
|
88
|
+
const { urls, options } = readArgs(process.argv.slice(2));
|
|
89
|
+
if (options.help) {
|
|
90
|
+
usage();
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (!urls.length) {
|
|
94
|
+
usage();
|
|
95
|
+
process.exitCode = 1;
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const pages = await crawl({
|
|
100
|
+
seeds: urls,
|
|
101
|
+
maxPages: options.maxPages,
|
|
102
|
+
concurrency: options.concurrency,
|
|
103
|
+
delayMs: options.delayMs,
|
|
104
|
+
timeoutMs: options.timeoutMs,
|
|
105
|
+
includeSitemaps: options.includeSitemaps,
|
|
106
|
+
sameOrigin: options.sameOrigin,
|
|
107
|
+
userAgent: options.userAgent,
|
|
108
|
+
onError: (failure) => {
|
|
109
|
+
process.stderr.write(`crawl warning: ${failure.url}: ${failure.error}\n`);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
writeOutput(pages, options);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
main().catch((error) => {
|
|
117
|
+
process.stderr.write(`${error.stack || error.message || String(error)}\n`);
|
|
118
|
+
process.exitCode = 1;
|
|
119
|
+
});
|
package/bin/maqam.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { startMaqamServer } from "../src/maqam/server.js";
|
|
3
|
+
|
|
4
|
+
function readPort(argv) {
|
|
5
|
+
const index = argv.indexOf("--port");
|
|
6
|
+
if (index === -1) return undefined;
|
|
7
|
+
return Number(argv[index + 1]);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (process.argv.includes("--help") || process.argv.includes("-h")) {
|
|
11
|
+
console.log(`
|
|
12
|
+
Maqam
|
|
13
|
+
|
|
14
|
+
Usage:
|
|
15
|
+
maqam [--port 8787]
|
|
16
|
+
|
|
17
|
+
Starts the local Maqam enterprise agent framework console.
|
|
18
|
+
`);
|
|
19
|
+
process.exit(0);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
startMaqamServer({ port: readPort(process.argv.slice(2)) });
|
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "maqam",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Maqam is an MIT-licensed Ajnas agent framework for governed workflows, policy, evidence, skills, and crawler-backed research.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "Ajnas",
|
|
8
|
+
"email": "ajnasnb@gmail.com"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"bin": {
|
|
12
|
+
"maqam": "bin/maqam.js",
|
|
13
|
+
"maqam-crawl": "bin/ajnas-crawl.js",
|
|
14
|
+
"ajnas-crawl": "bin/ajnas-crawl.js",
|
|
15
|
+
"ajnas-agent-crawler": "bin/ajnas-crawl.js"
|
|
16
|
+
},
|
|
17
|
+
"main": "src/index.js",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": "./src/index.js"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"app/",
|
|
23
|
+
"bin/",
|
|
24
|
+
"src/",
|
|
25
|
+
"README.md",
|
|
26
|
+
"LICENSE"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"test": "node --test",
|
|
30
|
+
"start": "node bin/maqam.js",
|
|
31
|
+
"crawl": "node bin/ajnas-crawl.js",
|
|
32
|
+
"maqam": "node bin/maqam.js"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"maqam",
|
|
36
|
+
"agent-framework",
|
|
37
|
+
"agent-runtime",
|
|
38
|
+
"governance",
|
|
39
|
+
"policy-engine",
|
|
40
|
+
"evidence-ledger",
|
|
41
|
+
"provenance",
|
|
42
|
+
"skills",
|
|
43
|
+
"tool-orchestration",
|
|
44
|
+
"human-approval",
|
|
45
|
+
"crawler",
|
|
46
|
+
"agent",
|
|
47
|
+
"web-crawler",
|
|
48
|
+
"scraper",
|
|
49
|
+
"robots.txt",
|
|
50
|
+
"sitemap",
|
|
51
|
+
"markdown",
|
|
52
|
+
"jsonl",
|
|
53
|
+
"research"
|
|
54
|
+
],
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"cheerio": "^1.0.0",
|
|
57
|
+
"robots-parser": "^3.0.1",
|
|
58
|
+
"turndown": "^7.2.0"
|
|
59
|
+
},
|
|
60
|
+
"engines": {
|
|
61
|
+
"node": ">=20"
|
|
62
|
+
},
|
|
63
|
+
"repository": {
|
|
64
|
+
"type": "git",
|
|
65
|
+
"url": "git+https://github.com/AjnasNB/maqam.git"
|
|
66
|
+
},
|
|
67
|
+
"bugs": {
|
|
68
|
+
"url": "https://github.com/AjnasNB/maqam/issues"
|
|
69
|
+
},
|
|
70
|
+
"homepage": "https://github.com/AjnasNB/maqam#readme",
|
|
71
|
+
"publishConfig": {
|
|
72
|
+
"access": "public"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export class AjnasFrameworkError extends Error {
|
|
2
|
+
constructor(message, options = {}) {
|
|
3
|
+
super(message, options.cause ? { cause: options.cause } : undefined);
|
|
4
|
+
this.name = new.target.name;
|
|
5
|
+
this.code = options.code || "AJNAS_FRAMEWORK_ERROR";
|
|
6
|
+
this.details = options.details || {};
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class PolicyDeniedError extends AjnasFrameworkError {
|
|
11
|
+
constructor(message, options = {}) {
|
|
12
|
+
super(message, {
|
|
13
|
+
...options,
|
|
14
|
+
code: options.code || "POLICY_DENIED"
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class ApprovalRequiredError extends AjnasFrameworkError {
|
|
20
|
+
constructor(message, options = {}) {
|
|
21
|
+
super(message, {
|
|
22
|
+
...options,
|
|
23
|
+
code: options.code || "APPROVAL_REQUIRED"
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function toErrorRecord(error) {
|
|
29
|
+
return {
|
|
30
|
+
name: error?.name || "Error",
|
|
31
|
+
code: error?.code || "ERROR",
|
|
32
|
+
message: error?.message || String(error),
|
|
33
|
+
details: error?.details || {}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
function sha256(value) {
|
|
4
|
+
return `sha256:${createHash("sha256").update(value).digest("hex")}`;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function clampConfidence(value) {
|
|
8
|
+
const number = Number(value);
|
|
9
|
+
if (!Number.isFinite(number)) return 0.5;
|
|
10
|
+
return Math.max(0, Math.min(1, number));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class EvidenceLedger {
|
|
14
|
+
constructor(options = {}) {
|
|
15
|
+
this.clock = options.clock || (() => new Date());
|
|
16
|
+
this.evidence = [];
|
|
17
|
+
this.claims = [];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
addEvidence(input = {}) {
|
|
21
|
+
const record = {
|
|
22
|
+
evidenceId: input.evidenceId || `ev_${this.evidence.length + 1}`,
|
|
23
|
+
runId: input.runId || null,
|
|
24
|
+
taskId: input.taskId || null,
|
|
25
|
+
sourceType: input.sourceType || "unknown",
|
|
26
|
+
source: input.source || "unknown",
|
|
27
|
+
retrievedAt: input.retrievedAt || this.clock().toISOString(),
|
|
28
|
+
excerpt: input.excerpt || "",
|
|
29
|
+
hash: input.hash || sha256(`${input.source || ""}\n${input.excerpt || ""}`),
|
|
30
|
+
tool: input.tool || null,
|
|
31
|
+
confidence: clampConfidence(input.confidence)
|
|
32
|
+
};
|
|
33
|
+
this.evidence.push(record);
|
|
34
|
+
return record;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
addClaim(input = {}) {
|
|
38
|
+
const claim = {
|
|
39
|
+
claimId: input.claimId || `claim_${this.claims.length + 1}`,
|
|
40
|
+
runId: input.runId || null,
|
|
41
|
+
taskId: input.taskId || null,
|
|
42
|
+
text: input.text || "",
|
|
43
|
+
evidenceIds: input.evidenceIds || [],
|
|
44
|
+
confidence: clampConfidence(input.confidence)
|
|
45
|
+
};
|
|
46
|
+
this.claims.push(claim);
|
|
47
|
+
return claim;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
listEvidence() {
|
|
51
|
+
return [...this.evidence];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
listClaims() {
|
|
55
|
+
return [...this.claims];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
unsupportedClaims() {
|
|
59
|
+
const known = new Set(this.evidence.map((record) => record.evidenceId));
|
|
60
|
+
return this.claims.filter((claim) => {
|
|
61
|
+
return !claim.evidenceIds.length || claim.evidenceIds.some((id) => !known.has(id));
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
toJSON() {
|
|
66
|
+
return {
|
|
67
|
+
evidence: this.listEvidence(),
|
|
68
|
+
claims: this.listClaims(),
|
|
69
|
+
unsupportedClaims: this.unsupportedClaims()
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|