- Add full Telegram bot functionality with Z.AI API integration
- Implement 4 tools: Bash, FileEdit, WebSearch, Git
- Add 3 agents: Code Reviewer, Architect, DevOps Engineer
- Add 6 skills for common coding tasks
- Add systemd service file for 24/7 operation
- Add nginx configuration for HTTPS webhook
- Add comprehensive documentation
- Implement WebSocket server for real-time updates
- Add logging system with Winston
- Add environment validation
🤖 zCode CLI X - Agentic coder with Z.AI + Telegram integration
222 lines
7.4 KiB
JavaScript
222 lines
7.4 KiB
JavaScript
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.StickyBucketServiceSync = exports.StickyBucketService = exports.RedisStickyBucketService = exports.LocalStorageStickyBucketService = exports.ExpressCookieStickyBucketService = exports.BrowserCookieStickyBucketService = void 0;
|
|
var _util = require("./util");
|
|
var _core = require("./core");
|
|
/**
|
|
* Responsible for reading and writing documents which describe sticky bucket assignments.
|
|
*/
|
|
class StickyBucketService {
|
|
constructor(opts) {
|
|
opts = opts || {};
|
|
this.prefix = opts.prefix || "";
|
|
}
|
|
/**
|
|
* The SDK calls getAllAssignments to populate sticky buckets. This in turn will
|
|
* typically loop through individual getAssignments calls. However, some StickyBucketService
|
|
* instances (i.e. Redis) will instead perform a multi-query inside getAllAssignments instead.
|
|
*/
|
|
async getAllAssignments(attributes) {
|
|
const docs = {};
|
|
(await Promise.all(Object.entries(attributes).map(([attributeName, attributeValue]) => this.getAssignments(attributeName, attributeValue)))).forEach(doc => {
|
|
if (doc) {
|
|
const key = (0, _core.getStickyBucketAttributeKey)(doc.attributeName, doc.attributeValue);
|
|
docs[key] = doc;
|
|
}
|
|
});
|
|
return docs;
|
|
}
|
|
getKey(attributeName, attributeValue) {
|
|
return `${this.prefix}${attributeName}||${attributeValue}`;
|
|
}
|
|
}
|
|
exports.StickyBucketService = StickyBucketService;
|
|
class StickyBucketServiceSync extends StickyBucketService {
|
|
async getAssignments(attributeName, attributeValue) {
|
|
return this.getAssignmentsSync(attributeName, attributeValue);
|
|
}
|
|
async saveAssignments(doc) {
|
|
this.saveAssignmentsSync(doc);
|
|
}
|
|
getAllAssignmentsSync(attributes) {
|
|
const docs = {};
|
|
Object.entries(attributes).map(([attributeName, attributeValue]) => this.getAssignmentsSync(attributeName, attributeValue)).forEach(doc => {
|
|
if (doc) {
|
|
const key = (0, _core.getStickyBucketAttributeKey)(doc.attributeName, doc.attributeValue);
|
|
docs[key] = doc;
|
|
}
|
|
});
|
|
return docs;
|
|
}
|
|
}
|
|
exports.StickyBucketServiceSync = StickyBucketServiceSync;
|
|
class LocalStorageStickyBucketService extends StickyBucketService {
|
|
constructor(opts) {
|
|
opts = opts || {};
|
|
super();
|
|
this.prefix = opts.prefix || "gbStickyBuckets__";
|
|
try {
|
|
this.localStorage = opts.localStorage || globalThis.localStorage;
|
|
} catch (e) {
|
|
// Ignore localStorage errors
|
|
}
|
|
}
|
|
async getAssignments(attributeName, attributeValue) {
|
|
const key = this.getKey(attributeName, attributeValue);
|
|
let doc = null;
|
|
if (!this.localStorage) return doc;
|
|
try {
|
|
const raw = (await this.localStorage.getItem(key)) || "{}";
|
|
const data = JSON.parse(raw);
|
|
if (data.attributeName && data.attributeValue && data.assignments) {
|
|
doc = data;
|
|
}
|
|
} catch (e) {
|
|
// Ignore localStorage errors
|
|
}
|
|
return doc;
|
|
}
|
|
async saveAssignments(doc) {
|
|
const key = this.getKey(doc.attributeName, doc.attributeValue);
|
|
if (!this.localStorage) return;
|
|
try {
|
|
await this.localStorage.setItem(key, JSON.stringify(doc));
|
|
} catch (e) {
|
|
// Ignore localStorage errors
|
|
}
|
|
}
|
|
}
|
|
exports.LocalStorageStickyBucketService = LocalStorageStickyBucketService;
|
|
class ExpressCookieStickyBucketService extends StickyBucketServiceSync {
|
|
/**
|
|
* Intended to be used with cookieParser() middleware from npm: 'cookie-parser'.
|
|
* Assumes:
|
|
* - reading a cookie is automatically decoded via decodeURIComponent() or similar
|
|
* - writing a cookie name & value must be manually encoded via encodeURIComponent() or similar
|
|
* - all cookie bodies are JSON encoded strings and are manually encoded/decoded
|
|
*/
|
|
|
|
constructor({
|
|
prefix = "gbStickyBuckets__",
|
|
req,
|
|
res,
|
|
cookieAttributes = {
|
|
maxAge: 180 * 24 * 3600 * 1000
|
|
} // 180 days
|
|
}) {
|
|
super();
|
|
this.prefix = prefix;
|
|
this.req = req;
|
|
this.res = res;
|
|
this.cookieAttributes = cookieAttributes;
|
|
}
|
|
getAssignmentsSync(attributeName, attributeValue) {
|
|
const key = this.getKey(attributeName, attributeValue);
|
|
let doc = null;
|
|
if (!this.req) return doc;
|
|
try {
|
|
const raw = this.req.cookies[key] || "{}";
|
|
const data = JSON.parse(raw);
|
|
if (data.attributeName && data.attributeValue && data.assignments) {
|
|
doc = data;
|
|
}
|
|
} catch (e) {
|
|
// Ignore cookie errors
|
|
}
|
|
return doc;
|
|
}
|
|
saveAssignmentsSync(doc) {
|
|
const key = this.getKey(doc.attributeName, doc.attributeValue);
|
|
if (!this.res) return;
|
|
const str = JSON.stringify(doc);
|
|
this.res.cookie(encodeURIComponent(key), encodeURIComponent(str), this.cookieAttributes);
|
|
}
|
|
}
|
|
exports.ExpressCookieStickyBucketService = ExpressCookieStickyBucketService;
|
|
class BrowserCookieStickyBucketService extends StickyBucketServiceSync {
|
|
/**
|
|
* Intended to be used with npm: 'js-cookie'.
|
|
* Assumes:
|
|
* - reading a cookie is automatically decoded via decodeURIComponent() or similar
|
|
* - writing a cookie name & value is automatically encoded via encodeURIComponent() or similar
|
|
* - all cookie bodies are JSON encoded strings and are manually encoded/decoded
|
|
*/
|
|
|
|
constructor({
|
|
prefix = "gbStickyBuckets__",
|
|
jsCookie,
|
|
cookieAttributes = {
|
|
expires: 180
|
|
} // 180 days
|
|
}) {
|
|
super();
|
|
this.prefix = prefix;
|
|
this.jsCookie = jsCookie;
|
|
this.cookieAttributes = cookieAttributes;
|
|
}
|
|
getAssignmentsSync(attributeName, attributeValue) {
|
|
const key = this.getKey(attributeName, attributeValue);
|
|
let doc = null;
|
|
if (!this.jsCookie) return doc;
|
|
try {
|
|
const raw = this.jsCookie.get(key);
|
|
const data = JSON.parse(raw || "{}");
|
|
if (data.attributeName && data.attributeValue && data.assignments) {
|
|
doc = data;
|
|
}
|
|
} catch (e) {
|
|
// Ignore cookie errors
|
|
}
|
|
return doc;
|
|
}
|
|
async saveAssignmentsSync(doc) {
|
|
const key = this.getKey(doc.attributeName, doc.attributeValue);
|
|
if (!this.jsCookie) return;
|
|
const str = JSON.stringify(doc);
|
|
this.jsCookie.set(key, str, this.cookieAttributes);
|
|
}
|
|
}
|
|
exports.BrowserCookieStickyBucketService = BrowserCookieStickyBucketService;
|
|
class RedisStickyBucketService extends StickyBucketService {
|
|
/** Intended to be used with npm: 'ioredis'. **/
|
|
|
|
constructor({
|
|
redis
|
|
}) {
|
|
super();
|
|
this.redis = redis;
|
|
}
|
|
async getAllAssignments(attributes) {
|
|
const docs = {};
|
|
const keys = Object.entries(attributes).map(([attributeName, attributeValue]) => (0, _core.getStickyBucketAttributeKey)(attributeName, attributeValue));
|
|
if (!this.redis) return docs;
|
|
await this.redis.mget(...keys).then(values => {
|
|
values.forEach(raw => {
|
|
try {
|
|
const data = JSON.parse(raw || "{}");
|
|
if (data.attributeName && "attributeValue" in data && data.assignments) {
|
|
const key = (0, _core.getStickyBucketAttributeKey)(data.attributeName, (0, _util.toString)(data.attributeValue));
|
|
docs[key] = data;
|
|
}
|
|
} catch (e) {
|
|
// ignore redis doc parse errors
|
|
}
|
|
});
|
|
});
|
|
return docs;
|
|
}
|
|
async getAssignments(_attributeName, _attributeValue) {
|
|
// not implemented
|
|
return null;
|
|
}
|
|
async saveAssignments(doc) {
|
|
const key = this.getKey(doc.attributeName, doc.attributeValue);
|
|
if (!this.redis) return;
|
|
await this.redis.set(key, JSON.stringify(doc));
|
|
}
|
|
}
|
|
exports.RedisStickyBucketService = RedisStickyBucketService;
|
|
//# sourceMappingURL=sticky-bucket-service.js.map
|