@bendyline/gilde 0.1.46 → 0.1.47

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.
@@ -20,8 +20,8 @@
20
20
  "name": "Alibaba",
21
21
  "url": "https://huggingface.co/Qwen/Qwen3.8-27B"
22
22
  },
23
- "version": "1.0.2",
24
- "updatedAt": "2026-08-15T00:00:00Z",
23
+ "version": "1.0.3",
24
+ "updatedAt": "2026-08-29T00:00:00Z",
25
25
  "license": "Apache-2.0",
26
26
  "licenseClass": "open",
27
27
  "licenseShortName": "Apache 2.0",
@@ -0,0 +1,116 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "version": "1.0.3",
4
+ "releasedAt": "2026-08-29T00:00:00Z",
5
+ "approxSizeBytes": 16464440224,
6
+ "llamaCpp": {
7
+ "huggingfaceRepo": "unsloth/Qwen3.8-27B-GGUF",
8
+ "revision": "27af057ecb382ddfea5d12837360a8980560e3ed",
9
+ "filename": "Qwen3.8-27B-UD-Q4_K_M.gguf",
10
+ "sha256": "322e194ff79741c7baa497c240f677f54b201b0efab44ca8e50f122b39123482",
11
+ "approxSizeBytes": 16464440224,
12
+ "quantization": "UD-Q4_K_M",
13
+ "mmproj": {
14
+ "filename": "mmproj-F16.gguf",
15
+ "sha256": "cbb841a9ee0636b2ec172f5bb8df2ea8dfeb01e90fe7c6126581d662a0b4e43e",
16
+ "sizeBytes": 927607488
17
+ }
18
+ },
19
+ "mlx": {
20
+ "huggingfaceRepo": "mlx-community/Qwen3.8-27B-4bit",
21
+ "revision": "3e6447f082e89cc7f0bc6e5441afd38dfce760ff",
22
+ "quantization": "4bit",
23
+ "approxSizeBytes": 16081488731,
24
+ "files": [
25
+ {
26
+ "name": "chat_template.jinja",
27
+ "sha256": "c3cf9e34abf4f9e36c2d72165aa9c132d3e2a725b6c2586aaa3a8af9d7a81041",
28
+ "sizeBytes": 8952
29
+ },
30
+ {
31
+ "name": "config.json",
32
+ "sha256": "14b65a0ee06517060a6bbd979bb1a8ff54e7b304b1a1f01d54344b88b8285e85",
33
+ "sizeBytes": 4932
34
+ },
35
+ {
36
+ "name": "generation_config.json",
37
+ "sha256": "e70c136c1b78ddc1fb0905bac8e733a4dc448d4f852a5dd75143fffc70be550e",
38
+ "sizeBytes": 202
39
+ },
40
+ {
41
+ "name": "model-00001-of-00003.safetensors",
42
+ "sha256": "6cc1508e96fb5d0865dfd5753a79f4ec60651bf3e2a82844a7e8ae9c60528c0d",
43
+ "sizeBytes": 5343268662
44
+ },
45
+ {
46
+ "name": "model-00002-of-00003.safetensors",
47
+ "sha256": "83f2a20ca8058f486a3634a27faf99587f4cd3c156a83dee34fb99e6ac178670",
48
+ "sizeBytes": 5354185130
49
+ },
50
+ {
51
+ "name": "model-00003-of-00003.safetensors",
52
+ "sha256": "31b8c91ef899f79efaaa69e3d2c096f6e2ebeb2ff20e29222abbd9ebc79e560a",
53
+ "sizeBytes": 5357087557
54
+ },
55
+ {
56
+ "name": "model.safetensors.index.json",
57
+ "sha256": "13b840162b4cb35c66fef7df072f7dbb4717908204364f5e5d9f9655a2758fa8",
58
+ "sizeBytes": 218281
59
+ },
60
+ {
61
+ "name": "preprocessor_config.json",
62
+ "sha256": "27225450ac9c6529872ee1924fcb0962ff5634834f817040f444118116f4e516",
63
+ "sizeBytes": 390
64
+ },
65
+ {
66
+ "name": "processor_config.json",
67
+ "sha256": "45fc17c8dd2474af6b493b52483c26c0584b0082d368c480f9fa611e73070040",
68
+ "sizeBytes": 991
69
+ },
70
+ {
71
+ "name": "tokenizer.json",
72
+ "sha256": "06b9509352d2af50381ab2247e083b80d32d5c0aba91c272ca9ff729b6a0e523",
73
+ "sizeBytes": 19989325
74
+ },
75
+ {
76
+ "name": "tokenizer_config.json",
77
+ "sha256": "792fa3f0cb88b111e54ef3134c873531008c4df471d108da17903426e308aa7b",
78
+ "sizeBytes": 1165
79
+ },
80
+ {
81
+ "name": "video_preprocessor_config.json",
82
+ "sha256": "7768af27c1fafa9cc9011c1dc20067e03f8915e03b63504550e11d5066986d13",
83
+ "sizeBytes": 385
84
+ },
85
+ {
86
+ "name": "vocab.json",
87
+ "sha256": "ce99b4cb2983d118806ce0a8b777a35b093e2000a503ebde25853284c9dfa003",
88
+ "sizeBytes": 6722759
89
+ }
90
+ ],
91
+ "drafter": {
92
+ "huggingfaceRepo": "Bendyline/Qwen3.8-27B-mtp-drafter-mlx-4bit",
93
+ "revision": "7e359eb37e379884da87116cc375f8869d3e7783",
94
+ "kind": "mtp",
95
+ "approxSizeBytes": 238955214,
96
+ "residentBytes": 869269504,
97
+ "files": [
98
+ {
99
+ "name": "config.json",
100
+ "sha256": "bb11ae5c0e28eb0a931ae329d9a9652c82235d2cf2702c993c2a56360a1712a1",
101
+ "sizeBytes": 3149
102
+ },
103
+ {
104
+ "name": "model.safetensors",
105
+ "sha256": "76663c101e7e8ea9c0ae17bcb95183cd7f733ce424c912b8b264a7b1c48e4cc6",
106
+ "sizeBytes": 238934137
107
+ },
108
+ {
109
+ "name": "tokenizer_config.json",
110
+ "sha256": "b11349aafa7cdc6a320767cf7ceb29ed82f7eda5d65e8e0819e76f0ce947bf27",
111
+ "sizeBytes": 17928
112
+ }
113
+ ]
114
+ }
115
+ }
116
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "kind": "connector-type",
4
+ "id": "azure-monitor-logs",
5
+ "name": "Azure Monitor Logs",
6
+ "description": "Mirror a Log Analytics workspace table — request logs, diagnostics, app telemetry — into a queryable data table. Azure reports the column types, so your gezels get a real schema and can answer questions with SQL instead of reading files.",
7
+ "tags": [
8
+ "azure",
9
+ "logs",
10
+ "telemetry",
11
+ "data",
12
+ "table",
13
+ "observations"
14
+ ],
15
+ "maintainer": {
16
+ "name": "Gezel"
17
+ }
18
+ }
@@ -0,0 +1,81 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "version": "1.0.0",
4
+ "releasedAt": "2026-08-29T00:00:00Z",
5
+ "driver": "native",
6
+ "source": {
7
+ "adapterId": "azure-monitor-logs"
8
+ },
9
+ "configSchema": {
10
+ "type": "object",
11
+ "properties": {
12
+ "workspaceId": {
13
+ "type": "string",
14
+ "title": "Log Analytics workspace ID"
15
+ },
16
+ "kqlTable": {
17
+ "type": "string",
18
+ "title": "Table to mirror (e.g. AppRequests)"
19
+ },
20
+ "filter": {
21
+ "type": "string",
22
+ "title": "Extra KQL filter (optional)"
23
+ },
24
+ "table": {
25
+ "type": "string",
26
+ "title": "Name for the table in Gezel (optional)"
27
+ },
28
+ "timeColumn": {
29
+ "type": "string",
30
+ "title": "Timestamp column"
31
+ },
32
+ "backfillDays": {
33
+ "type": "integer",
34
+ "title": "Days of history on the first sync",
35
+ "minimum": 1,
36
+ "maximum": 365
37
+ },
38
+ "pageRows": {
39
+ "type": "integer",
40
+ "title": "Rows per sync",
41
+ "minimum": 100,
42
+ "maximum": 50000
43
+ },
44
+ "apiBaseUrl": {
45
+ "type": "string",
46
+ "title": "API base URL (sovereign clouds only)"
47
+ }
48
+ },
49
+ "required": [
50
+ "workspaceId",
51
+ "kqlTable"
52
+ ]
53
+ },
54
+ "secretShape": {
55
+ "kind": "apikey",
56
+ "field": "token",
57
+ "label": "Azure access token",
58
+ "required": true,
59
+ "description": "An Azure AD access token for https://api.loganalytics.io with Log Analytics Reader on the workspace. Stored in your keychain; it never reaches the model.",
60
+ "helpUrl": "https://learn.microsoft.com/azure/azure-monitor/logs/api/overview",
61
+ "helpLabel": "Azure Monitor Logs API docs"
62
+ },
63
+ "setupInstructions": {
64
+ "title": "Connect a Log Analytics workspace",
65
+ "description": "Gezel reads one table from your workspace on a schedule and stores it locally as a data table. Nothing is written back to Azure, and the query only ever reads.",
66
+ "steps": [
67
+ "In the Azure portal, open your Log Analytics workspace and copy its Workspace ID from the Overview page.",
68
+ "Name the table you want mirrored — AppRequests, AzureDiagnostics, and AppExceptions are common starting points.",
69
+ "Give Gezel an access token for the Log Analytics API with the Log Analytics Reader role. Read access is all it needs.",
70
+ "Optionally add a KQL filter to narrow what is mirrored, and set how many days of history the first sync should reach back."
71
+ ]
72
+ },
73
+ "normalize": {
74
+ "kind": "observations"
75
+ },
76
+ "allowedOrigins": [
77
+ "https://api.loganalytics.io"
78
+ ],
79
+ "completeness": "window",
80
+ "notes": "An observation corpus: rows land as partitioned columnar files and gezels read them through list_tables/describe_table/query_table rather than as files. Log Analytics has no continuation token, so syncing pages over time — each pass reads rows strictly newer than the last one written, oldest-first, up to the row budget. The watermark advances only after a clean write, so a failed pass re-reads its window instead of skipping it. Because the comparison is strict, a row sharing a timestamp to the tick with the previous page's last row can be missed; the alternative re-delivers that row on every pass forever. Azure reports each column's type, so the table's schema comes from the source rather than being inferred from a sample."
81
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "kind": "connector-type",
4
+ "id": "http-json-rows",
5
+ "name": "JSON Rows over HTTP",
6
+ "description": "Mirror rows from any JSON or NDJSON HTTP endpoint into a queryable data table. For high-volume sources — request logs, exports, metrics — that are far too large to read as files. Gezels query the result with SQL instead of reading it.",
7
+ "tags": [
8
+ "data",
9
+ "table",
10
+ "json",
11
+ "http",
12
+ "script",
13
+ "observations"
14
+ ],
15
+ "maintainer": {
16
+ "name": "Gezel"
17
+ }
18
+ }
@@ -0,0 +1,74 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "version": "1.0.0",
4
+ "releasedAt": "2026-08-29T00:00:00Z",
5
+ "driver": "script",
6
+ "source": {
7
+ "inlineFetch": "import { defineScript, gezel } from '@bendyline/gezel-sdk';\n\nexport const meta = defineScript({\n name: 'http-json-rows-fetch',\n description: 'Fetches a bounded page of rows from a JSON or NDJSON HTTP endpoint.',\n inputs: {\n cursor: { type: 'json', description: 'Opaque continuation value from the previous pass.' },\n config: { type: 'json', description: 'Endpoint URL, item path, and paging fields.', required: true },\n },\n outputs: {\n records: { type: 'array', description: 'Rows for the observation table.', itemType: 'object' },\n cursor: { type: 'string', description: 'Continuation value for the next pass.', nullable: true },\n rateLimited: { type: 'boolean', description: 'True when the source throttled the pass.', nullable: true },\n partial: { type: 'boolean', description: 'True when more pages remained after the page budget.', nullable: true },\n },\n requires: ['network', 'credential:$credential'],\n} as const);\n\ntype Config = {\n url?: unknown;\n itemsPath?: unknown;\n format?: unknown;\n timeField?: unknown;\n sinceParam?: unknown;\n pageParam?: unknown;\n nextPagePath?: unknown;\n maxPages?: unknown;\n};\n\nconst input = gezel.input as { cursor?: unknown; config?: Config };\nconst config = input.config ?? {};\n\nconst rawUrl = typeof config.url === 'string' ? config.url.trim() : '';\nif (!rawUrl) throw new Error('An endpoint URL is required.');\nlet origin: string;\ntry {\n const parsed = new URL(rawUrl);\n if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') throw new Error('bad protocol');\n origin = parsed.origin;\n} catch {\n throw new Error('The endpoint URL must be an absolute HTTP or HTTPS URL.');\n}\n\nconst itemsPath = typeof config.itemsPath === 'string' ? config.itemsPath.trim() : '';\nconst format = config.format === 'ndjson' ? 'ndjson' : 'json';\nconst timeField = typeof config.timeField === 'string' ? config.timeField.trim() : '';\nconst sinceParam = typeof config.sinceParam === 'string' ? config.sinceParam.trim() : '';\nconst nextPagePath = typeof config.nextPagePath === 'string' ? config.nextPagePath.trim() : '';\nconst maxPages = Number.isFinite(Number(config.maxPages))\n ? Math.max(1, Math.min(Number(config.maxPages), 20))\n : 5;\n\n/** Walk a dotted `a.b.c` path (with or without a leading `$.`). */\nfunction pick(value: unknown, path: string): unknown {\n if (!path) return value;\n let current = value;\n for (const key of path.replace(/^\\$\\.?/, '').split('.')) {\n if (!key) continue;\n if (current === null || typeof current !== 'object') return undefined;\n current = (current as Record<string, unknown>)[key];\n }\n return current;\n}\n\nfunction rowsFrom(body: string): Record<string, unknown>[] {\n if (format === 'ndjson') {\n const out: Record<string, unknown>[] = [];\n for (const line of body.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n const parsed = JSON.parse(trimmed) as unknown;\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n out.push(parsed as Record<string, unknown>);\n }\n }\n return out;\n }\n const parsed = JSON.parse(body) as unknown;\n const items = itemsPath ? pick(parsed, itemsPath) : parsed;\n if (!Array.isArray(items)) {\n throw new Error(\n itemsPath\n ? 'The item path did not resolve to a list. Check `itemsPath` against the response shape.'\n : 'The endpoint did not return a list. Set `itemsPath` to where the rows live in the response.',\n );\n }\n return items.filter(\n (item): item is Record<string, unknown> =>\n Boolean(item) && typeof item === 'object' && !Array.isArray(item),\n );\n}\n\nfunction isThrottle(status: number, headers: Record<string, string | undefined>): boolean {\n if (status === 429) return true;\n return status === 503 && Boolean(headers['retry-after']);\n}\n\nconst priorCursor = typeof input.cursor === 'string' ? input.cursor : '';\nlet nextUrl = rawUrl;\nif (sinceParam && priorCursor) {\n const target = new URL(rawUrl);\n target.searchParams.set(sinceParam, priorCursor);\n nextUrl = target.toString();\n}\n\nconst records: Record<string, unknown>[] = [];\nlet newestSeen = priorCursor;\nlet rateLimited = false;\nlet more = false;\n\nfor (let page = 0; page < maxPages && nextUrl; page++) {\n const target = new URL(nextUrl);\n // Never forward the credential across an origin change — a redirect or a\n // hostile `nextPagePath` would otherwise leak it to a third party.\n if (target.origin !== origin) {\n throw new Error('Pagination changed origin; refusing to forward the credential.');\n }\n const headers = { Accept: format === 'ndjson' ? 'application/x-ndjson' : 'application/json' };\n let response;\n try {\n response = await gezel.http.authed(target.toString(), { credential: '$credential', headers });\n } catch (error) {\n if ((error as { code?: string }).code !== 'CREDENTIAL_MISSING') throw error;\n response = await gezel.http.request(target.toString(), { headers });\n }\n if (isThrottle(response.status, response.headers)) {\n // Emit what this pass collected and flag the throttle rather than\n // throwing: a throw voids the batch and re-fetches the same window next\n // tick, which is how a rate-limited API gets hammered.\n rateLimited = true;\n break;\n }\n if (!response.ok) {\n throw new Error('Row fetch failed (' + response.status + '): ' + response.body.slice(0, 240));\n }\n\n const pageRows = rowsFrom(response.body);\n for (const row of pageRows) {\n records.push(row);\n if (timeField) {\n const value = pick(row, timeField);\n if (typeof value === 'string' && (!newestSeen || value > newestSeen)) newestSeen = value;\n }\n }\n\n let candidate = '';\n if (nextPagePath && format === 'json') {\n const link = pick(JSON.parse(response.body) as unknown, nextPagePath);\n if (typeof link === 'string' && link) candidate = link;\n }\n if (candidate && new URL(candidate, origin).origin === origin) {\n nextUrl = new URL(candidate, origin).toString();\n more = page + 1 >= maxPages;\n } else {\n nextUrl = '';\n }\n}\n\ngezel.output({\n records,\n cursor: newestSeen || null,\n ...(rateLimited ? { rateLimited: true } : {}),\n ...(more && !rateLimited ? { partial: true } : {}),\n});\n",
8
+ "table": "rows"
9
+ },
10
+ "configSchema": {
11
+ "type": "object",
12
+ "properties": {
13
+ "url": {
14
+ "type": "string",
15
+ "title": "Endpoint URL"
16
+ },
17
+ "itemsPath": {
18
+ "type": "string",
19
+ "title": "Path to the rows in the response (e.g. data.results)"
20
+ },
21
+ "format": {
22
+ "type": "string",
23
+ "title": "Response format",
24
+ "enum": [
25
+ "json",
26
+ "ndjson"
27
+ ]
28
+ },
29
+ "timeField": {
30
+ "type": "string",
31
+ "title": "Field holding each row's timestamp"
32
+ },
33
+ "sinceParam": {
34
+ "type": "string",
35
+ "title": "Query parameter for incremental fetches"
36
+ },
37
+ "nextPagePath": {
38
+ "type": "string",
39
+ "title": "Path to the next-page URL in the response"
40
+ },
41
+ "maxPages": {
42
+ "type": "integer",
43
+ "title": "Pages per sync",
44
+ "minimum": 1,
45
+ "maximum": 20
46
+ }
47
+ },
48
+ "required": [
49
+ "url"
50
+ ]
51
+ },
52
+ "secretShape": {
53
+ "kind": "apikey",
54
+ "field": "token",
55
+ "label": "API token",
56
+ "required": false,
57
+ "description": "Sent as a bearer token. Leave blank for an endpoint that needs no authentication."
58
+ },
59
+ "setupInstructions": {
60
+ "title": "Point Gezel at a JSON endpoint",
61
+ "description": "Any endpoint that returns a list of rows works — an export URL, a query API, an NDJSON log feed. Gezel stores the rows as a data table and your gezels query it with SQL instead of reading files.",
62
+ "steps": [
63
+ "Paste the endpoint URL. If it needs a token, add one below; it is stored in your keychain and never reaches the model.",
64
+ "If the rows are nested in the response (for example under `data.results`), set the item path to where they live.",
65
+ "Set the timestamp field if the rows carry one. Gezel partitions by day on that field, which is what keeps queries fast as the table grows.",
66
+ "For an endpoint that supports incremental reads, name its since-parameter so each sync only fetches what is new."
67
+ ]
68
+ },
69
+ "normalize": {
70
+ "kind": "observations"
71
+ },
72
+ "completeness": "window",
73
+ "notes": "An observation corpus: rows land as partitioned columnar files rather than one file per record, and gezels read them through list_tables/describe_table/query_table. The column schema is inferred from the first rows that arrive, so `describe_table` marks it inferred — cast explicitly if a comparison behaves oddly. Pagination is bounded per sync and never follows a link to a different origin, so the credential cannot leak to a third party. A throttled source is reported rather than thrown, so the engine backs off instead of re-fetching the same window."
74
+ }