jiva-core 0.3.45-dev.53be99d → 0.3.46-dev.478c47b
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/Dockerfile +7 -3
- package/cloud-run-deploy.yaml +1 -1
- package/cloud-run.yaml +5 -8
- package/dist/core/agent-spawner.js +1 -1
- package/dist/core/client-agent.d.ts +3 -1
- package/dist/core/client-agent.d.ts.map +1 -1
- package/dist/core/client-agent.js +6 -4
- package/dist/core/client-agent.js.map +1 -1
- package/dist/core/config.d.ts +174 -86
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +25 -9
- package/dist/core/config.js.map +1 -1
- package/dist/core/dual-agent.d.ts +8 -0
- package/dist/core/dual-agent.d.ts.map +1 -1
- package/dist/core/dual-agent.js +14 -10
- package/dist/core/dual-agent.js.map +1 -1
- package/dist/core/manager-agent.d.ts +3 -1
- package/dist/core/manager-agent.d.ts.map +1 -1
- package/dist/core/manager-agent.js +37 -17
- package/dist/core/manager-agent.js.map +1 -1
- package/dist/core/worker-agent.d.ts +3 -1
- package/dist/core/worker-agent.d.ts.map +1 -1
- package/dist/core/worker-agent.js +23 -9
- package/dist/core/worker-agent.js.map +1 -1
- package/dist/interfaces/cli/index.js +2 -2
- package/dist/interfaces/cli/index.js.map +1 -1
- package/dist/interfaces/http/session-manager.d.ts +7 -1
- package/dist/interfaces/http/session-manager.d.ts.map +1 -1
- package/dist/interfaces/http/session-manager.js +83 -47
- package/dist/interfaces/http/session-manager.js.map +1 -1
- package/dist/models/base.d.ts +8 -0
- package/dist/models/base.d.ts.map +1 -1
- package/dist/models/google-adc.d.ts +26 -0
- package/dist/models/google-adc.d.ts.map +1 -0
- package/dist/models/google-adc.js +118 -0
- package/dist/models/google-adc.js.map +1 -0
- package/dist/models/harmony.d.ts.map +1 -1
- package/dist/models/harmony.js +39 -3
- package/dist/models/harmony.js.map +1 -1
- package/dist/models/model-client.d.ts +19 -2
- package/dist/models/model-client.d.ts.map +1 -1
- package/dist/models/model-client.js +48 -17
- package/dist/models/model-client.js.map +1 -1
- package/dist/storage/factory.d.ts.map +1 -1
- package/dist/storage/factory.js +5 -0
- package/dist/storage/factory.js.map +1 -1
- package/dist/storage/gcp-bucket-provider.d.ts +10 -0
- package/dist/storage/gcp-bucket-provider.d.ts.map +1 -1
- package/dist/storage/gcp-bucket-provider.js +61 -6
- package/dist/storage/gcp-bucket-provider.js.map +1 -1
- package/dist/storage/local-provider.d.ts +7 -0
- package/dist/storage/local-provider.d.ts.map +1 -1
- package/dist/storage/local-provider.js +12 -0
- package/dist/storage/local-provider.js.map +1 -1
- package/dist/storage/provider.d.ts +15 -0
- package/dist/storage/provider.d.ts.map +1 -1
- package/dist/storage/provider.js +19 -0
- package/dist/storage/provider.js.map +1 -1
- package/dist/utils/orchestration-logger.d.ts +16 -4
- package/dist/utils/orchestration-logger.d.ts.map +1 -1
- package/dist/utils/orchestration-logger.js +24 -4
- package/dist/utils/orchestration-logger.js.map +1 -1
- package/package.json +1 -1
- package/scripts/generate-image.js +130 -0
- package/scripts/package.json +7 -0
- package/scripts/post-to-gritsa.js +212 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Gritsa Blog Publisher
|
|
4
|
+
*
|
|
5
|
+
* Publishes a markdown blog post (with optional featured image) to the
|
|
6
|
+
* gritsa/www-gritsa.github.io GitHub repository.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* node post-to-gritsa.js <post-markdown-path> [image-path]
|
|
10
|
+
*
|
|
11
|
+
* If image-path is omitted, checks /tmp/gritsa-blog-image.png automatically.
|
|
12
|
+
* If an image is found, it is uploaded to assets/img/posts/ in the repo and
|
|
13
|
+
* the featured_image front-matter field is injected into the post.
|
|
14
|
+
*/
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
const https = require('https');
|
|
18
|
+
const fs = require('fs');
|
|
19
|
+
const path = require('path');
|
|
20
|
+
|
|
21
|
+
// ── Config ──────────────────────────────────────────────────────────────────
|
|
22
|
+
const GITHUB_PAT = process.env.GITHUB_PAT || process.env.GRITSA_GITHUB_PAT || '';
|
|
23
|
+
const REPO_OWNER = 'gritsa';
|
|
24
|
+
const REPO_NAME = 'www-gritsa.github.io';
|
|
25
|
+
const BRANCH = 'main';
|
|
26
|
+
const POSTS_DIR = '_posts';
|
|
27
|
+
const IMAGES_DIR = 'assets/img/posts';
|
|
28
|
+
const AUTHOR = 'Gritsa';
|
|
29
|
+
const DEFAULT_IMG = '/tmp/gritsa-blog-image.png';
|
|
30
|
+
|
|
31
|
+
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
32
|
+
function slugify(text) {
|
|
33
|
+
return text.toLowerCase()
|
|
34
|
+
.replace(/['"]/g, '')
|
|
35
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
36
|
+
.replace(/^-+|-+$/g, '');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function todayISO() {
|
|
40
|
+
return new Date().toISOString().split('T')[0];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function todayJekyll() {
|
|
44
|
+
const now = new Date();
|
|
45
|
+
const pad = n => String(n).padStart(2, '0');
|
|
46
|
+
return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ` +
|
|
47
|
+
`${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())} +0000`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function parseFrontMatter(content) {
|
|
51
|
+
const m = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/);
|
|
52
|
+
if (!m) return { frontMatter: {}, body: content };
|
|
53
|
+
const fm = {};
|
|
54
|
+
for (const line of m[1].split('\n')) {
|
|
55
|
+
const kv = line.match(/^(\w+):\s*"?(.+?)"?\s*$/);
|
|
56
|
+
if (kv) fm[kv[1]] = kv[2];
|
|
57
|
+
}
|
|
58
|
+
return { frontMatter: fm, body: m[2] };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function extractTitle(body) {
|
|
62
|
+
const h1 = body.match(/^#\s+(.+)$/m);
|
|
63
|
+
return h1 ? h1[1].trim() : 'New Post';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function extractExcerpt(body) {
|
|
67
|
+
const p = body.replace(/^#+.+$/gm, '').trim().split(/\n\n/)[0]
|
|
68
|
+
.replace(/[#*`]/g, '').trim();
|
|
69
|
+
return p.length > 200 ? p.substring(0, 197) + '...' : p;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function buildFrontMatter(fm) {
|
|
73
|
+
const title = fm.title || 'New Post';
|
|
74
|
+
const date = fm.date || todayJekyll();
|
|
75
|
+
const author = fm.author || AUTHOR;
|
|
76
|
+
const excerpt = fm.excerpt || '';
|
|
77
|
+
const image = fm.featured_image || '';
|
|
78
|
+
|
|
79
|
+
let b = `---\nlayout: post\ntitle: "${title.replace(/"/g, '\\"')}"\ndate: ${date}\nauthor: "${author}"\n`;
|
|
80
|
+
if (excerpt) b += `excerpt: "${excerpt.replace(/"/g, '\\"')}"\n`;
|
|
81
|
+
if (image) b += `featured_image: "${image}"\n`;
|
|
82
|
+
return b + '---\n';
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function githubRequest(method, apiPath, body) {
|
|
86
|
+
return new Promise((resolve, reject) => {
|
|
87
|
+
const payload = body ? JSON.stringify(body) : null;
|
|
88
|
+
const req = https.request({
|
|
89
|
+
hostname: 'api.github.com',
|
|
90
|
+
path: apiPath,
|
|
91
|
+
method,
|
|
92
|
+
headers: {
|
|
93
|
+
'Authorization': `token ${GITHUB_PAT}`,
|
|
94
|
+
'User-Agent': 'jiva-auto-blogger/2.0',
|
|
95
|
+
'Accept': 'application/vnd.github.v3+json',
|
|
96
|
+
'Content-Type': 'application/json',
|
|
97
|
+
...(payload ? { 'Content-Length': Buffer.byteLength(payload) } : {}),
|
|
98
|
+
},
|
|
99
|
+
}, res => {
|
|
100
|
+
let data = '';
|
|
101
|
+
res.on('data', c => data += c);
|
|
102
|
+
res.on('end', () => {
|
|
103
|
+
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
104
|
+
resolve(JSON.parse(data));
|
|
105
|
+
} else {
|
|
106
|
+
reject(new Error(`GitHub API ${res.statusCode}: ${data}`));
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
req.on('error', reject);
|
|
111
|
+
if (payload) req.write(payload);
|
|
112
|
+
req.end();
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async function getExistingSha(apiPath) {
|
|
117
|
+
try {
|
|
118
|
+
const e = await githubRequest('GET', apiPath);
|
|
119
|
+
return e.sha;
|
|
120
|
+
} catch {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ── Image upload ──────────────────────────────────────────────────────────────
|
|
126
|
+
async function uploadImage(imagePath, slug) {
|
|
127
|
+
if (!imagePath || !fs.existsSync(imagePath)) return null;
|
|
128
|
+
|
|
129
|
+
const ext = path.extname(imagePath).toLowerCase() || '.png';
|
|
130
|
+
const imgName = `${todayISO()}-${slug}${ext}`;
|
|
131
|
+
const apiPath = `/repos/${REPO_OWNER}/${REPO_NAME}/contents/${IMAGES_DIR}/${imgName}`;
|
|
132
|
+
const imgBytes = fs.readFileSync(imagePath);
|
|
133
|
+
const b64 = imgBytes.toString('base64');
|
|
134
|
+
|
|
135
|
+
console.log(`🖼️ Uploading image: ${imgName} (${(imgBytes.length / 1024).toFixed(0)} KB)`);
|
|
136
|
+
|
|
137
|
+
const existingSha = await getExistingSha(apiPath);
|
|
138
|
+
|
|
139
|
+
await githubRequest('PUT', apiPath, {
|
|
140
|
+
message: `blog: add image for "${slug}"`,
|
|
141
|
+
content: b64,
|
|
142
|
+
branch: BRANCH,
|
|
143
|
+
...(existingSha ? { sha: existingSha } : {}),
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
const publicPath = `/${IMAGES_DIR}/${imgName}`;
|
|
147
|
+
console.log(` ✅ Image path: ${publicPath}`);
|
|
148
|
+
return publicPath;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// ── Main ──────────────────────────────────────────────────────────────────────
|
|
152
|
+
async function main() {
|
|
153
|
+
const filePath = process.argv[2];
|
|
154
|
+
const imgArg = process.argv[3] || DEFAULT_IMG;
|
|
155
|
+
|
|
156
|
+
if (!filePath) {
|
|
157
|
+
console.error('Usage: node post-to-gritsa.js <post.md> [image.png]');
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// ── Parse post ───────────────────────────────────────────────────────────
|
|
162
|
+
const rawContent = fs.readFileSync(path.resolve(filePath), 'utf8');
|
|
163
|
+
let { frontMatter: fm, body } = parseFrontMatter(rawContent);
|
|
164
|
+
|
|
165
|
+
if (!fm.title) fm.title = extractTitle(body);
|
|
166
|
+
if (!fm.excerpt) fm.excerpt = extractExcerpt(body);
|
|
167
|
+
|
|
168
|
+
const datePrefix = todayISO();
|
|
169
|
+
const slug = slugify(fm.title);
|
|
170
|
+
const filename = `${datePrefix}-${slug}.md`;
|
|
171
|
+
const postPath = `/repos/${REPO_OWNER}/${REPO_NAME}/contents/${POSTS_DIR}/${filename}`;
|
|
172
|
+
|
|
173
|
+
console.log(`📝 Preparing post: ${filename}`);
|
|
174
|
+
console.log(` Title : ${fm.title}`);
|
|
175
|
+
|
|
176
|
+
// ── Upload image first (so we can inject path into front matter) ──────────
|
|
177
|
+
const imageFsPath = fs.existsSync(imgArg) ? imgArg : null;
|
|
178
|
+
if (imageFsPath) {
|
|
179
|
+
const imgPublicPath = await uploadImage(imageFsPath, slug);
|
|
180
|
+
if (imgPublicPath) fm.featured_image = imgPublicPath;
|
|
181
|
+
} else {
|
|
182
|
+
console.log(' (no featured image found — skipping image upload)');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// ── Build final post content ───────────────────────────────────────────────
|
|
186
|
+
const finalContent = buildFrontMatter(fm) + '\n' + body.trimStart();
|
|
187
|
+
|
|
188
|
+
// ── Publish post ──────────────────────────────────────────────────────────
|
|
189
|
+
const existingSha = await getExistingSha(postPath);
|
|
190
|
+
if (existingSha) {
|
|
191
|
+
console.log(` Updating existing post (sha: ${existingSha.substring(0, 8)})`);
|
|
192
|
+
} else {
|
|
193
|
+
console.log(' Creating new post');
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const result = await githubRequest('PUT', postPath, {
|
|
197
|
+
message: `blog: add "${fm.title}"`,
|
|
198
|
+
content: Buffer.from(finalContent, 'utf8').toString('base64'),
|
|
199
|
+
branch: BRANCH,
|
|
200
|
+
...(existingSha ? { sha: existingSha } : {}),
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
const postUrl = `https://gritsa.github.io/${datePrefix.replace(/-/g, '/')}/${slug}.html`;
|
|
204
|
+
console.log(`\n✅ Published successfully!`);
|
|
205
|
+
console.log(` GitHub : ${result.content.html_url}`);
|
|
206
|
+
console.log(` Blog : ${postUrl}`);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
main().catch(err => {
|
|
210
|
+
console.error('❌ Publishing failed:', err.message);
|
|
211
|
+
process.exit(1);
|
|
212
|
+
});
|