hanoman 0.1.25 → 0.1.26
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/dist/build-info.json +3 -3
- package/dist/cli.js +122 -1
- package/dist/server.js +490 -4
- package/package.json +1 -1
- package/prisma/migrations/20260811000000_scheduler_cron/migration.sql +34 -0
- package/prisma/schema.prisma +45 -0
- package/web/assets/{index-CnAQHtuX.css → index-B0GzvSQL.css} +1 -1
- package/web/assets/{index-D68Z05gR.js → index-BfOACraN.js} +1544 -1544
- package/web/index.html +2 -2
package/dist/build-info.json
CHANGED
package/dist/cli.js
CHANGED
|
@@ -4985,8 +4985,68 @@ var init_prd_status = __esm({
|
|
|
4985
4985
|
}
|
|
4986
4986
|
});
|
|
4987
4987
|
|
|
4988
|
+
// ../shared/src/cron-expr.ts
|
|
4989
|
+
function parseField(raw, lo, hi) {
|
|
4990
|
+
const out = /* @__PURE__ */ new Set();
|
|
4991
|
+
for (const part of raw.split(",")) {
|
|
4992
|
+
const slash = part.indexOf("/");
|
|
4993
|
+
const rangePart = slash === -1 ? part : part.slice(0, slash);
|
|
4994
|
+
const stepPart = slash === -1 ? void 0 : part.slice(slash + 1);
|
|
4995
|
+
let step = 1;
|
|
4996
|
+
if (stepPart !== void 0) {
|
|
4997
|
+
if (!/^\d{1,2}$/.test(stepPart)) return null;
|
|
4998
|
+
step = Number(stepPart);
|
|
4999
|
+
if (step < 1) return null;
|
|
5000
|
+
}
|
|
5001
|
+
let from;
|
|
5002
|
+
let to;
|
|
5003
|
+
if (rangePart === "*") {
|
|
5004
|
+
from = lo;
|
|
5005
|
+
to = hi;
|
|
5006
|
+
} else if (/^\d{1,2}$/.test(rangePart)) {
|
|
5007
|
+
from = Number(rangePart);
|
|
5008
|
+
to = stepPart === void 0 ? from : hi;
|
|
5009
|
+
} else {
|
|
5010
|
+
const m = /^(\d{1,2})-(\d{1,2})$/.exec(rangePart);
|
|
5011
|
+
if (!m) return null;
|
|
5012
|
+
from = Number(m[1]);
|
|
5013
|
+
to = Number(m[2]);
|
|
5014
|
+
}
|
|
5015
|
+
if (from < lo || to > hi || from > to) return null;
|
|
5016
|
+
for (let v = from; v <= to; v += step) out.add(v);
|
|
5017
|
+
}
|
|
5018
|
+
return out.size ? out : null;
|
|
5019
|
+
}
|
|
5020
|
+
function parseCron(expr) {
|
|
5021
|
+
const parts = expr.trim().split(/\s+/);
|
|
5022
|
+
if (parts.length !== 5) return null;
|
|
5023
|
+
const sets = [];
|
|
5024
|
+
for (let i = 0; i < 5; i++) {
|
|
5025
|
+
const [lo, hi] = BOUNDS[i];
|
|
5026
|
+
const s2 = parseField(parts[i], lo, hi);
|
|
5027
|
+
if (!s2) return null;
|
|
5028
|
+
sets.push(s2);
|
|
5029
|
+
}
|
|
5030
|
+
return {
|
|
5031
|
+
minute: sets[0],
|
|
5032
|
+
hour: sets[1],
|
|
5033
|
+
dom: sets[2],
|
|
5034
|
+
month: sets[3],
|
|
5035
|
+
dow: new Set([...sets[4]].map((n2) => n2 === 7 ? 0 : n2)),
|
|
5036
|
+
domRestricted: parts[2] !== "*",
|
|
5037
|
+
dowRestricted: parts[4] !== "*"
|
|
5038
|
+
};
|
|
5039
|
+
}
|
|
5040
|
+
var BOUNDS;
|
|
5041
|
+
var init_cron_expr = __esm({
|
|
5042
|
+
"../shared/src/cron-expr.ts"() {
|
|
5043
|
+
"use strict";
|
|
5044
|
+
BOUNDS = [[0, 59], [0, 23], [1, 31], [1, 12], [0, 7]];
|
|
5045
|
+
}
|
|
5046
|
+
});
|
|
5047
|
+
|
|
4988
5048
|
// ../shared/src/dto.ts
|
|
4989
|
-
var zIssueDeviceToken, zSessionResult, zSessionHistory, zCreateProject, zProjectId, zRenameProject, zUpdateProject, zCreateSpec, zPatchSpec, zChangeSpecSource, zIntegrate, zSessionSummary, zProjectView, zSchedulerQueueItem, zSchedulerSourceView, zSchedulerSessionView, zSchedulerQueueCounts, zSchedulerState, zLeadDecisionView, zLeadFlowView, zLeadAnswer, zLeadProjectStatus, zLeadStatusView, zFlow, zPrdBrief, zPrdDoc, zBreakdownItem, zBreakdownDoc, zBatchCreateSpec, zEscalationTarget, zEscalationPrefill, zAuditEscalation, zAuditEscalationView, zTerminalSession, zDocFileContent, zDocIndexCat, zDocIndex, HOST_RE, USER_RE, zCreateVps, zPatchVps, USER_ROLES, zUserRole, zLogin, zSignup, zChangePassword, zCreateClientAccount, zUpdateClientAccount, zVpsCheck, zMarkNa, zMarkNaBulk, zAttest, zRemediate, UPDATE_RESTART_EXIT, zUpdateApplyBody, zTicketView, zTicketAttachmentView, zTicketDetail, zTicketEditInput, zHelpInfo, zPublicTicketStatus;
|
|
5049
|
+
var zIssueDeviceToken, zSessionResult, zSessionHistory, zCreateProject, zProjectId, zRenameProject, zUpdateProject, zCreateSpec, zPatchSpec, zChangeSpecSource, zIntegrate, zSessionSummary, zProjectView, zSchedulerQueueItem, zSchedulerSourceView, zSchedulerSessionView, zSchedulerQueueCounts, zSchedulerState, zLeadDecisionView, zLeadFlowView, zLeadAnswer, zLeadProjectStatus, zLeadStatusView, zFlow, zPrdBrief, zPrdDoc, zBreakdownItem, zBreakdownDoc, zBatchCreateSpec, zEscalationTarget, zEscalationPrefill, zAuditEscalation, zAuditEscalationView, zTerminalSession, zDocFileContent, zDocIndexCat, zDocIndex, HOST_RE, USER_RE, zCreateVps, zPatchVps, USER_ROLES, zUserRole, zLogin, zSignup, zChangePassword, zCreateClientAccount, zUpdateClientAccount, zVpsCheck, zMarkNa, zMarkNaBulk, zAttest, zRemediate, UPDATE_RESTART_EXIT, zUpdateApplyBody, zTicketView, zTicketAttachmentView, zTicketDetail, zTicketEditInput, zHelpInfo, zPublicTicketStatus, zCronExpr, zCreateCron, zPatchCron, zSchedulerCron, zSchedulerCronRun;
|
|
4990
5050
|
var init_dto = __esm({
|
|
4991
5051
|
"../shared/src/dto.ts"() {
|
|
4992
5052
|
"use strict";
|
|
@@ -4997,6 +5057,7 @@ var init_dto = __esm({
|
|
|
4997
5057
|
init_prd_status();
|
|
4998
5058
|
init_enums();
|
|
4999
5059
|
init_spec_source();
|
|
5060
|
+
init_cron_expr();
|
|
5000
5061
|
zIssueDeviceToken = external_exports.object({ name: external_exports.string().min(1) });
|
|
5001
5062
|
zSessionResult = external_exports.object({
|
|
5002
5063
|
id: external_exports.string(),
|
|
@@ -5473,6 +5534,53 @@ var init_dto = __esm({
|
|
|
5473
5534
|
status: external_exports.string(),
|
|
5474
5535
|
createdAt: external_exports.string()
|
|
5475
5536
|
});
|
|
5537
|
+
zCronExpr = external_exports.string().trim().refine((v) => parseCron(v) !== null, "cron expression tak sah");
|
|
5538
|
+
zCreateCron = external_exports.object({
|
|
5539
|
+
project: external_exports.string().min(1),
|
|
5540
|
+
name: external_exports.string().trim().min(1).max(120),
|
|
5541
|
+
expr: zCronExpr,
|
|
5542
|
+
prompt: external_exports.string().trim().min(1).max(8e3),
|
|
5543
|
+
agent: zAgent.optional(),
|
|
5544
|
+
model: external_exports.string().optional(),
|
|
5545
|
+
effort: external_exports.string().optional(),
|
|
5546
|
+
enabled: external_exports.boolean().default(false)
|
|
5547
|
+
// default aman: cron baru lahir nonaktif
|
|
5548
|
+
});
|
|
5549
|
+
zPatchCron = external_exports.object({
|
|
5550
|
+
name: external_exports.string().trim().min(1).max(120).optional(),
|
|
5551
|
+
expr: zCronExpr.optional(),
|
|
5552
|
+
prompt: external_exports.string().trim().min(1).max(8e3).optional(),
|
|
5553
|
+
agent: zAgent.nullable().optional(),
|
|
5554
|
+
model: external_exports.string().nullable().optional(),
|
|
5555
|
+
effort: external_exports.string().nullable().optional(),
|
|
5556
|
+
enabled: external_exports.boolean().optional()
|
|
5557
|
+
});
|
|
5558
|
+
zSchedulerCron = external_exports.object({
|
|
5559
|
+
id: external_exports.string(),
|
|
5560
|
+
projectId: external_exports.string(),
|
|
5561
|
+
name: external_exports.string(),
|
|
5562
|
+
expr: external_exports.string(),
|
|
5563
|
+
prompt: external_exports.string(),
|
|
5564
|
+
agent: external_exports.string().nullable(),
|
|
5565
|
+
model: external_exports.string().nullable(),
|
|
5566
|
+
effort: external_exports.string().nullable(),
|
|
5567
|
+
enabled: external_exports.boolean(),
|
|
5568
|
+
nextRunAt: external_exports.string().nullable(),
|
|
5569
|
+
lastRunAt: external_exports.string().nullable(),
|
|
5570
|
+
createdAt: external_exports.string()
|
|
5571
|
+
});
|
|
5572
|
+
zSchedulerCronRun = external_exports.object({
|
|
5573
|
+
id: external_exports.string(),
|
|
5574
|
+
cronId: external_exports.string(),
|
|
5575
|
+
projectId: external_exports.string(),
|
|
5576
|
+
dueAt: external_exports.string(),
|
|
5577
|
+
startedAt: external_exports.string().nullable(),
|
|
5578
|
+
status: external_exports.string(),
|
|
5579
|
+
sessionId: external_exports.string().nullable(),
|
|
5580
|
+
note: external_exports.string().nullable(),
|
|
5581
|
+
manual: external_exports.boolean(),
|
|
5582
|
+
createdAt: external_exports.string()
|
|
5583
|
+
});
|
|
5476
5584
|
}
|
|
5477
5585
|
});
|
|
5478
5586
|
|
|
@@ -5619,6 +5727,13 @@ var init_api = __esm({
|
|
|
5619
5727
|
schedulerQueueRequeue: (id) => `${API}/scheduler/queue/${encodeURIComponent(id)}/requeue`,
|
|
5620
5728
|
// SPEC-523 · antrean sebagai daftar berhalaman (page/limit + status), lepas dari `state`.
|
|
5621
5729
|
schedulerQueue: `${API}/scheduler/queue`,
|
|
5730
|
+
// SPEC-646 · ADR-0112 · cronjob per project. Di bawah prefix `scheduler` seperti tetangganya,
|
|
5731
|
+
// TAPI capability-nya bukan turunan otomatis: `capabilityForRoute` memberi `crons` cabang
|
|
5732
|
+
// COOKIE_ONLY sendiri — sebuah cron adalah `POST /terminal/sessions` yang ditunda.
|
|
5733
|
+
schedulerCrons: `${API}/scheduler/crons`,
|
|
5734
|
+
schedulerCron: (id) => `${API}/scheduler/crons/${encodeURIComponent(id)}`,
|
|
5735
|
+
schedulerCronRunNow: (id) => `${API}/scheduler/crons/${encodeURIComponent(id)}/run`,
|
|
5736
|
+
schedulerCronRuns: (id) => `${API}/scheduler/crons/${encodeURIComponent(id)}/runs`,
|
|
5622
5737
|
// SPEC-409 · ADR-0091 · hanoman-lead. Semua HTTP (polling) — tak ada kanal WS baru (AC-26).
|
|
5623
5738
|
leadConfig: `${API}/lead/config`,
|
|
5624
5739
|
leadStatus: `${API}/lead/status`,
|
|
@@ -7053,6 +7168,7 @@ var init_src = __esm({
|
|
|
7053
7168
|
init_mcp();
|
|
7054
7169
|
init_auto_merge();
|
|
7055
7170
|
init_changelog();
|
|
7171
|
+
init_cron_expr();
|
|
7056
7172
|
}
|
|
7057
7173
|
});
|
|
7058
7174
|
|
|
@@ -28630,7 +28746,12 @@ var init_migrate_pg = __esm({
|
|
|
28630
28746
|
"SyncConflict",
|
|
28631
28747
|
// SPEC-485 · ADR-0102 · LeadFlow SEBELUM LeadDecision: `flowId` menunjuk ke sana. Tanpa FK, tapi
|
|
28632
28748
|
// urutan tabel harus tetap mencerminkan arah tautannya bagi pembaca berikutnya.
|
|
28749
|
+
// SPEC-646 · ADR-0112 · SchedulerCron SEBELUM SchedulerCronRun: `cronId` menunjuk ke sana. Tanpa
|
|
28750
|
+
// FK (cermin SchedulerQueueItem/LeadDecision), tapi urutan tabel harus tetap mencerminkan arah
|
|
28751
|
+
// tautannya bagi pembaca berikutnya.
|
|
28633
28752
|
"SchedulerQueueItem",
|
|
28753
|
+
"SchedulerCron",
|
|
28754
|
+
"SchedulerCronRun",
|
|
28634
28755
|
"RuntimeConfig",
|
|
28635
28756
|
"LeadFlow",
|
|
28636
28757
|
"LeadDecision",
|