hanoman 0.1.46 → 0.1.50
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/README.md +43 -1
- package/dist/build-info.json +3 -3
- package/dist/cli.js +100 -38
- package/dist/server.js +27934 -27449
- package/docs/agent-integration.md +10 -0
- package/package.json +1 -1
- package/prisma/migrations/20260819120000_spec_attachment/migration.sql +19 -0
- package/prisma/migrations/20260819130000_session_history_ended_reason/migration.sql +27 -0
- package/prisma/schema.prisma +31 -0
- package/web/assets/index-Ddz2nble.js +7606 -0
- package/web/index.html +1 -1
- package/web/assets/index-pMhBDQcJ.js +0 -7779
package/README.md
CHANGED
|
@@ -84,13 +84,55 @@ Sesudah `hanoman update`, instance yang berjalan perlu di-restart (mis. `systemc
|
|
|
84
84
|
|
|
85
85
|
| Env | Default | Untuk apa |
|
|
86
86
|
|---|---|---|
|
|
87
|
-
| `HANOMAN_HOME` | `~/.hanoman` |
|
|
87
|
+
| `HANOMAN_HOME` | `~/.hanoman` | akar seluruh state hanoman — lihat [Isi `$HANOMAN_HOME`](#isi-hanoman_home) |
|
|
88
88
|
| `HANOMAN_DATABASE_URL` | — | berkas DB khusus hanoman; hanya URL `file:` (nilai lain **melempar**) |
|
|
89
89
|
| `DATABASE_URL` | `file:$HANOMAN_HOME/hanoman.db` | dipakai bila ber-`file:`; nilai lain **diabaikan** dengan peringatan |
|
|
90
|
+
| `HANOMAN_TRANSCRIPT_DIR` | `$HANOMAN_HOME/transcripts` | transkrip sesi yang sudah ditutup |
|
|
91
|
+
| `HANOMAN_UPLOAD_DIR` | `$HANOMAN_HOME/uploads` | lampiran tiket & lampiran gambar sesi terminal |
|
|
92
|
+
| `HANOMAN_SSH_KEY_DIR` | `$HANOMAN_HOME` | keypair identitas hanoman untuk VPS |
|
|
90
93
|
| `PORT` / `HOST` | `8787` / `127.0.0.1` | alamat bind |
|
|
91
94
|
| `HANOMAN_CLAUDE_BIN` / `HANOMAN_CODEX_BIN` | `claude` / `codex` | biner agen |
|
|
92
95
|
| `HANOMAN_TMUX_SOCKET` | `hanoman` | socket tmux terpisah dari milikmu |
|
|
93
96
|
|
|
97
|
+
<a id="isi-hanoman_home"></a>
|
|
98
|
+
|
|
99
|
+
## Isi `$HANOMAN_HOME` — satu batas backup/restore
|
|
100
|
+
|
|
101
|
+
Tanpa override, **seluruh** state hanoman hidup di bawah satu direktori. Itulah batas yang harus
|
|
102
|
+
disalin: memindahkan DB saja meninggalkan metadata yang menunjuk byte yang tak ada (SPEC-846).
|
|
103
|
+
|
|
104
|
+
| Path | Isi | Hilang berarti |
|
|
105
|
+
|---|---|---|
|
|
106
|
+
| `hanoman.db` (+ `-wal`/`-shm`) | seluruh state aplikasi | semuanya |
|
|
107
|
+
| `secret.key` | kunci AES untuk RuntimeConfig & webhook secret | credential terenkripsi tak bisa dibuka |
|
|
108
|
+
| `id_ed25519` + `.pub` | identitas SSH hanoman ke VPS | akses VPS mati; `authorized_keys` tak lagi cocok |
|
|
109
|
+
| `transcripts/` | transkrip sesi yang ditutup | `hasTranscript` benar, isinya tak terbaca |
|
|
110
|
+
| `uploads/` | lampiran tiket, byte source-map lama | lampiran 404 walau metadata utuh |
|
|
111
|
+
| `uploads/terminal/<sessionId>/` | lampiran gambar sesi terminal | path di prompt agen menunjuk berkas hilang |
|
|
112
|
+
| `setup.token` | token bootstrap admin pertama (one-time, 15 menit) | hanya relevan sebelum admin pertama |
|
|
113
|
+
| `agent-token` | agent token yang dibaca `hanoman mcp` | klien MCP lokal kehilangan autentikasi |
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# Backup — SQLite disalin konsisten, sisanya berkas biasa.
|
|
117
|
+
sqlite3 "$HANOMAN_HOME/hanoman.db" ".backup '/backup/hanoman.db'"
|
|
118
|
+
tar -C "$HANOMAN_HOME" -czf /backup/hanoman-files.tgz \
|
|
119
|
+
secret.key id_ed25519 id_ed25519.pub transcripts uploads
|
|
120
|
+
|
|
121
|
+
# Restore di host lain — umask dulu, isinya memuat kunci privat.
|
|
122
|
+
umask 077
|
|
123
|
+
install -d -m 0700 "$HANOMAN_HOME"
|
|
124
|
+
cp /backup/hanoman.db "$HANOMAN_HOME/hanoman.db"
|
|
125
|
+
tar -C "$HANOMAN_HOME" -xzf /backup/hanoman-files.tgz
|
|
126
|
+
hanoman doctor # memverifikasi tiap path data efektif + izin tulisnya
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
`setup.token` dan `agent-token` sengaja **tidak** ikut: yang pertama one-time dan lahir ulang
|
|
130
|
+
sendiri bila DB belum punya user, yang kedua sebaiknya diterbitkan ulang di host baru.
|
|
131
|
+
|
|
132
|
+
Mengeset `HANOMAN_TRANSCRIPT_DIR`, `HANOMAN_UPLOAD_DIR`, atau `HANOMAN_SSH_KEY_DIR` memindahkan
|
|
133
|
+
bagian itu ke luar batas ini — sah, tapi backup-nya menjadi tanggung jawabmu. `hanoman doctor`
|
|
134
|
+
mencetak path efektifnya supaya tak perlu ditebak.
|
|
135
|
+
|
|
94
136
|
## Bind & TLS
|
|
95
137
|
|
|
96
138
|
Default `127.0.0.1:8787`. hanoman punya auth, tapi cookie sesinya `Secure` — set
|
package/dist/build-info.json
CHANGED
package/dist/cli.js
CHANGED
|
@@ -5022,7 +5022,7 @@ var init_cron_expr = __esm({
|
|
|
5022
5022
|
});
|
|
5023
5023
|
|
|
5024
5024
|
// ../shared/src/dto.ts
|
|
5025
|
-
var zIssueDeviceToken, zSessionResult, zSessionHistory, zCreateProject, zProjectId, zRenameProject, zUpdateProject, zCreateSpec, zPatchSpec, zChangeSpecSource, zMarkSpecDone, 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, zSetup, zChangePassword, zCreateClientAccount, zUpdateClientAccount, zVpsCheck, zMarkNa, zMarkNaBulk, zAttest, zRemediate, UPDATE_RESTART_EXIT, zUpdateApplyBody, zTicketView, zTicketAttachmentView, zTicketDetail, zTicketEditInput, zHelpInfo, zPublicTicketStatus, zCronExpr, zCreateCron, zPatchCron, zSchedulerCron, zSchedulerCronRun;
|
|
5025
|
+
var zIssueDeviceToken, zSessionResult, zSessionHistory, zCreateProject, zProjectId, zRenameProject, zUpdateProject, zCreateSpec, zPatchSpec, zChangeSpecSource, zMarkSpecDone, 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, zSetup, zChangePassword, zCreateClientAccount, zUpdateClientAccount, zVpsCheck, zMarkNa, zMarkNaBulk, zAttest, zRemediate, UPDATE_RESTART_EXIT, zUpdateApplyBody, zTicketView, zTicketAttachmentView, zSpecAttachmentView, zTicketDetail, zTicketEditInput, zHelpInfo, zPublicTicketStatus, zCronExpr, zCreateCron, zPatchCron, zSchedulerCron, zSchedulerCronRun;
|
|
5026
5026
|
var init_dto = __esm({
|
|
5027
5027
|
"../shared/src/dto.ts"() {
|
|
5028
5028
|
"use strict";
|
|
@@ -5064,6 +5064,10 @@ var init_dto = __esm({
|
|
|
5064
5064
|
cwd: external_exports.string(),
|
|
5065
5065
|
startedAt: external_exports.string(),
|
|
5066
5066
|
endedAt: external_exports.string().nullable(),
|
|
5067
|
+
// SPEC-844 · ADR-0125 · `string` longgar, bukan enum: baris lama null dan nilai asing dari
|
|
5068
|
+
// instance lebih baru tak boleh melempar di boundary — `sessionOutcome()` yang menafsirkannya.
|
|
5069
|
+
endedReason: external_exports.string().nullable(),
|
|
5070
|
+
reconciledAt: external_exports.string().nullable(),
|
|
5067
5071
|
exitCode: external_exports.number().nullable(),
|
|
5068
5072
|
transcriptBytes: external_exports.number().nullable()
|
|
5069
5073
|
});
|
|
@@ -5505,6 +5509,13 @@ var init_dto = __esm({
|
|
|
5505
5509
|
mimeType: external_exports.string(),
|
|
5506
5510
|
size: external_exports.number().int()
|
|
5507
5511
|
});
|
|
5512
|
+
zSpecAttachmentView = external_exports.object({
|
|
5513
|
+
id: external_exports.string(),
|
|
5514
|
+
filename: external_exports.string(),
|
|
5515
|
+
mimeType: external_exports.string(),
|
|
5516
|
+
size: external_exports.number().int(),
|
|
5517
|
+
createdAt: external_exports.string()
|
|
5518
|
+
});
|
|
5508
5519
|
zTicketDetail = zTicketView.extend({
|
|
5509
5520
|
detail: external_exports.string(),
|
|
5510
5521
|
attachments: external_exports.array(zTicketAttachmentView),
|
|
@@ -5606,6 +5617,9 @@ var init_api = __esm({
|
|
|
5606
5617
|
specSource: (id) => `${API}/specs/${id}/source`,
|
|
5607
5618
|
// SPEC-804 · ADR-0120 · tandai item selesai manual (operasi khusus, bukan field PATCH).
|
|
5608
5619
|
specDone: (id) => `${API}/specs/${id}/done`,
|
|
5620
|
+
// SPEC-843 · ADR-0124 · lampiran backlog item (multi-berkas per request).
|
|
5621
|
+
specAttachments: (id) => `${API}/specs/${id}/attachments`,
|
|
5622
|
+
specAttachment: (id, attId) => `${API}/specs/${id}/attachments/${attId}`,
|
|
5609
5623
|
specReview: (id) => `${API}/specs/${id}/review`,
|
|
5610
5624
|
specReviewFile: (id, path) => `${API}/specs/${id}/review/${path}`,
|
|
5611
5625
|
settings: `${API}/settings`,
|
|
@@ -5908,6 +5922,13 @@ var init_session_kind = __esm({
|
|
|
5908
5922
|
}
|
|
5909
5923
|
});
|
|
5910
5924
|
|
|
5925
|
+
// ../shared/src/session-end.ts
|
|
5926
|
+
var init_session_end = __esm({
|
|
5927
|
+
"../shared/src/session-end.ts"() {
|
|
5928
|
+
"use strict";
|
|
5929
|
+
}
|
|
5930
|
+
});
|
|
5931
|
+
|
|
5911
5932
|
// ../shared/src/config.ts
|
|
5912
5933
|
var zHanomanConfig;
|
|
5913
5934
|
var init_config = __esm({
|
|
@@ -6281,6 +6302,8 @@ var init_webhook = __esm({
|
|
|
6281
6302
|
"branch",
|
|
6282
6303
|
"startedAt",
|
|
6283
6304
|
"endedAt",
|
|
6305
|
+
"endedReason",
|
|
6306
|
+
"reconciledAt",
|
|
6284
6307
|
"exitCode"
|
|
6285
6308
|
],
|
|
6286
6309
|
projectIdField: "projectId",
|
|
@@ -6289,9 +6312,9 @@ var init_webhook = __esm({
|
|
|
6289
6312
|
},
|
|
6290
6313
|
derived: [{
|
|
6291
6314
|
type: "session.ended",
|
|
6292
|
-
label: "Sesi selesai atau
|
|
6315
|
+
label: "Sesi selesai, gagal, atau terputus",
|
|
6293
6316
|
changed: ["endedAt"],
|
|
6294
|
-
when:
|
|
6317
|
+
when: 'Sesi berakhir dan endedAt terisi. endedReason memberi tahu CARANYA: "closed" = hanoman menutupnya, jadi exitCode berlaku (null = agen masih hidup saat ditutup, 0 = keluar bersih, selain itu gagal); "reconciled" = panenya sudah lenyap saat hanoman menyala lagi (reboot, kill-server, host mati) sehingga hasilnya TAK DIKETAHUI, exitCode selalu null, dan reconciledAt menyebut kapan hanoman menemukannya \u2014 endedAt di kasus itu batas BAWAH, bukan waktu berakhir sebenarnya. null = baris lahir sebelum SPEC-844.'
|
|
6295
6318
|
}],
|
|
6296
6319
|
sample: {
|
|
6297
6320
|
id: "6f0c1c1e-1a2b-4c3d-8e9f-0a1b2c3d4e5f",
|
|
@@ -6307,6 +6330,8 @@ var init_webhook = __esm({
|
|
|
6307
6330
|
branch: "hanoman/spec-481",
|
|
6308
6331
|
startedAt: "2026-08-01T02:12:31.000Z",
|
|
6309
6332
|
endedAt: "2026-08-01T09:44:02.000Z",
|
|
6333
|
+
endedReason: "closed",
|
|
6334
|
+
reconciledAt: null,
|
|
6310
6335
|
exitCode: 0
|
|
6311
6336
|
}
|
|
6312
6337
|
},
|
|
@@ -7241,6 +7266,7 @@ var init_src = __esm({
|
|
|
7241
7266
|
init_portal();
|
|
7242
7267
|
init_prd_status();
|
|
7243
7268
|
init_session_kind();
|
|
7269
|
+
init_session_end();
|
|
7244
7270
|
init_config();
|
|
7245
7271
|
init_config_registry();
|
|
7246
7272
|
init_semver();
|
|
@@ -7433,6 +7459,16 @@ function resolveHome(env = process.env, home = homedir()) {
|
|
|
7433
7459
|
const v = env.HANOMAN_HOME?.trim();
|
|
7434
7460
|
return v ? v : join(home, ".hanoman");
|
|
7435
7461
|
}
|
|
7462
|
+
function resolveDataDirs(env = process.env, home = homedir()) {
|
|
7463
|
+
const root = resolveHome(env, home);
|
|
7464
|
+
const dir = (key, name) => env[key]?.trim() || join(root, name);
|
|
7465
|
+
return {
|
|
7466
|
+
home: root,
|
|
7467
|
+
transcripts: dir("HANOMAN_TRANSCRIPT_DIR", "transcripts"),
|
|
7468
|
+
uploads: dir("HANOMAN_UPLOAD_DIR", "uploads"),
|
|
7469
|
+
sshKeys: env.HANOMAN_SSH_KEY_DIR?.trim() || root
|
|
7470
|
+
};
|
|
7471
|
+
}
|
|
7436
7472
|
function schemeOf(raw) {
|
|
7437
7473
|
return raw.split("://")[0] ?? "?";
|
|
7438
7474
|
}
|
|
@@ -7691,10 +7727,10 @@ function ensureSpawnHelpersExecutable(paths2, ops) {
|
|
|
7691
7727
|
}
|
|
7692
7728
|
return fixed;
|
|
7693
7729
|
}
|
|
7694
|
-
function repairSpawnHelper(
|
|
7730
|
+
function repairSpawnHelper(resolve5, notify) {
|
|
7695
7731
|
let ptyDir;
|
|
7696
7732
|
try {
|
|
7697
|
-
ptyDir = dirname3(
|
|
7733
|
+
ptyDir = dirname3(resolve5("node-pty/package.json"));
|
|
7698
7734
|
} catch {
|
|
7699
7735
|
return [];
|
|
7700
7736
|
}
|
|
@@ -8096,7 +8132,7 @@ __export(doctor_exports, {
|
|
|
8096
8132
|
});
|
|
8097
8133
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
8098
8134
|
import { accessSync, constants, existsSync as existsSync4 } from "node:fs";
|
|
8099
|
-
import { dirname as dirname5 } from "node:path";
|
|
8135
|
+
import { dirname as dirname5, resolve as resolve4 } from "node:path";
|
|
8100
8136
|
function doctorReport(p) {
|
|
8101
8137
|
const major = Number(/^v?(\d+)/.exec(p.node)?.[1] ?? 0);
|
|
8102
8138
|
const rows = [
|
|
@@ -8111,7 +8147,13 @@ function doctorReport(p) {
|
|
|
8111
8147
|
text: p.gh ? `gh ${p.gh}` : "gh \u2014 tak ada (tarik issue akan lewat HTTP + GITHUB_TOKEN)",
|
|
8112
8148
|
fatal: false
|
|
8113
8149
|
},
|
|
8114
|
-
|
|
8150
|
+
// Direktori turunan lahir saat dipakai, jadi izin tulis yang belum ada di situ adalah
|
|
8151
|
+
// peringatan — bukan alasan menyatakan hanoman tak bisa menjalankan sesi. Home tetap fatal.
|
|
8152
|
+
...p.dirs.map((d) => ({
|
|
8153
|
+
mark: d.writable ? "\u2713" : d.fatal ? "\u2717" : "!",
|
|
8154
|
+
text: `${d.label} ${d.path}${d.writable ? "" : " \u2014 TAK bisa ditulis"}`,
|
|
8155
|
+
fatal: d.fatal && !d.writable
|
|
8156
|
+
})),
|
|
8115
8157
|
{ mark: p.web ? "\u2713" : "!", text: p.web ? "aset dashboard ada" : "aset dashboard tak ada \u2014 API jalan, dashboard tidak", fatal: false },
|
|
8116
8158
|
{ mark: "\xB7", text: `db ${p.db}`, fatal: false },
|
|
8117
8159
|
{
|
|
@@ -8134,6 +8176,21 @@ function doctorReport(p) {
|
|
|
8134
8176
|
}
|
|
8135
8177
|
return { lines: rows.map((r) => ` ${r.mark} ${r.text}`), ok: !rows.some((r) => r.fatal) };
|
|
8136
8178
|
}
|
|
8179
|
+
function writable(path) {
|
|
8180
|
+
for (let p = resolve4(path); ; ) {
|
|
8181
|
+
if (existsSync4(p)) {
|
|
8182
|
+
try {
|
|
8183
|
+
accessSync(p, constants.W_OK);
|
|
8184
|
+
return true;
|
|
8185
|
+
} catch {
|
|
8186
|
+
return false;
|
|
8187
|
+
}
|
|
8188
|
+
}
|
|
8189
|
+
const up = dirname5(p);
|
|
8190
|
+
if (up === p) return false;
|
|
8191
|
+
p = up;
|
|
8192
|
+
}
|
|
8193
|
+
}
|
|
8137
8194
|
function version(bin, args) {
|
|
8138
8195
|
try {
|
|
8139
8196
|
return execFileSync3(bin, args, { encoding: "utf8", timeout: 1e4, stdio: ["ignore", "pipe", "ignore"] }).trim().split("\n")[0] ?? null;
|
|
@@ -8152,13 +8209,13 @@ async function doctor(_argv, ctx) {
|
|
|
8152
8209
|
`);
|
|
8153
8210
|
return 1;
|
|
8154
8211
|
}
|
|
8155
|
-
const
|
|
8156
|
-
|
|
8157
|
-
|
|
8158
|
-
|
|
8159
|
-
|
|
8160
|
-
|
|
8161
|
-
|
|
8212
|
+
const d = resolveDataDirs(ctx.env);
|
|
8213
|
+
const dirs = [
|
|
8214
|
+
{ label: "data dir", path: d.home, writable: writable(d.home), fatal: true },
|
|
8215
|
+
{ label: "transkrip", path: d.transcripts, writable: writable(d.transcripts), fatal: false },
|
|
8216
|
+
{ label: "upload", path: d.uploads, writable: writable(d.uploads), fatal: false },
|
|
8217
|
+
{ label: "key SSH", path: d.sshKeys, writable: writable(d.sshKeys), fatal: false }
|
|
8218
|
+
];
|
|
8162
8219
|
const claude = version(ctx.env.HANOMAN_CLAUDE_BIN ?? "claude", ["--version"]);
|
|
8163
8220
|
const codex = version(ctx.env.HANOMAN_CODEX_BIN ?? "codex", ["--version"]);
|
|
8164
8221
|
const method = METHODS[DEFAULT_METHOD];
|
|
@@ -8188,7 +8245,7 @@ async function doctor(_argv, ctx) {
|
|
|
8188
8245
|
claude,
|
|
8189
8246
|
codex,
|
|
8190
8247
|
gh: version(ctx.env.HANOMAN_GH_BIN ?? "gh", ["--version"]),
|
|
8191
|
-
|
|
8248
|
+
dirs,
|
|
8192
8249
|
web: layout.web !== null,
|
|
8193
8250
|
db,
|
|
8194
8251
|
methods,
|
|
@@ -17578,14 +17635,14 @@ function inputRequiredRoundsExceededMessage(method, maxRounds) {
|
|
|
17578
17635
|
return `Multi-round-trip request '${method}' still required input after ${maxRounds} rounds (inputRequired.maxRounds)`;
|
|
17579
17636
|
}
|
|
17580
17637
|
function sleep(ms, signal) {
|
|
17581
|
-
return new Promise((
|
|
17638
|
+
return new Promise((resolve5, reject) => {
|
|
17582
17639
|
if (signal?.aborted) {
|
|
17583
17640
|
reject(signal.reason instanceof SdkError ? signal.reason : new SdkError(SdkErrorCode.RequestTimeout, String(signal.reason)));
|
|
17584
17641
|
return;
|
|
17585
17642
|
}
|
|
17586
17643
|
const timer = setTimeout(() => {
|
|
17587
17644
|
signal?.removeEventListener("abort", onAbort);
|
|
17588
|
-
|
|
17645
|
+
resolve5();
|
|
17589
17646
|
}, ms);
|
|
17590
17647
|
const onAbort = () => {
|
|
17591
17648
|
clearTimeout(timer);
|
|
@@ -19396,7 +19453,7 @@ var init_src_CX2iR2pK = __esm({
|
|
|
19396
19453
|
const flowStartedAt = Date.now();
|
|
19397
19454
|
let onAbort;
|
|
19398
19455
|
let cleanupMessageId;
|
|
19399
|
-
return new Promise((
|
|
19456
|
+
return new Promise((resolve5, reject) => {
|
|
19400
19457
|
const earlyReject = (error2) => {
|
|
19401
19458
|
reject(error2);
|
|
19402
19459
|
};
|
|
@@ -19464,7 +19521,7 @@ var init_src_CX2iR2pK = __esm({
|
|
|
19464
19521
|
}
|
|
19465
19522
|
if (decoded.kind === "invalid") return reject(decoded.error);
|
|
19466
19523
|
if (decoded.kind === "input_required") {
|
|
19467
|
-
if (options?.allowInputRequired === true) return
|
|
19524
|
+
if (options?.allowInputRequired === true) return resolve5(manualInputRequiredValue(decoded));
|
|
19468
19525
|
const flow = {
|
|
19469
19526
|
codec,
|
|
19470
19527
|
request,
|
|
@@ -19476,11 +19533,11 @@ var init_src_CX2iR2pK = __esm({
|
|
|
19476
19533
|
params
|
|
19477
19534
|
}, resultSchema, legOptions)
|
|
19478
19535
|
};
|
|
19479
|
-
return
|
|
19536
|
+
return resolve5(this._resolveNonCompleteResult(decoded, flow));
|
|
19480
19537
|
}
|
|
19481
19538
|
const result = decoded.result;
|
|
19482
19539
|
validateStandardSchema(resultSchema, result).then((parseResult) => {
|
|
19483
|
-
if (parseResult.success)
|
|
19540
|
+
if (parseResult.success) resolve5(parseResult.data);
|
|
19484
19541
|
else reject(new SdkError(SdkErrorCode.InvalidResult, `Invalid result for ${request.method}: ${parseResult.error}`));
|
|
19485
19542
|
}, reject);
|
|
19486
19543
|
});
|
|
@@ -22296,7 +22353,7 @@ var init_ajvProvider_CEoC_sr = __esm({
|
|
|
22296
22353
|
ref = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, ref);
|
|
22297
22354
|
const schOrFunc = root.refs[ref];
|
|
22298
22355
|
if (schOrFunc) return schOrFunc;
|
|
22299
|
-
let _sch =
|
|
22356
|
+
let _sch = resolve5.call(this, root, ref);
|
|
22300
22357
|
if (_sch === void 0) {
|
|
22301
22358
|
const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
|
|
22302
22359
|
const { schemaId } = this.opts;
|
|
@@ -22322,7 +22379,7 @@ var init_ajvProvider_CEoC_sr = __esm({
|
|
|
22322
22379
|
function sameSchemaEnv(s1, s2) {
|
|
22323
22380
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
22324
22381
|
}
|
|
22325
|
-
function
|
|
22382
|
+
function resolve5(root, ref) {
|
|
22326
22383
|
let sch;
|
|
22327
22384
|
while (typeof (sch = this.refs[ref]) == "string") ref = sch;
|
|
22328
22385
|
return sch || this.schemas[ref] || resolveSchema.call(this, root, ref);
|
|
@@ -22772,7 +22829,7 @@ var init_ajvProvider_CEoC_sr = __esm({
|
|
|
22772
22829
|
else if (typeof uri === "object") uri = parse4(serialize(uri, options), options);
|
|
22773
22830
|
return uri;
|
|
22774
22831
|
}
|
|
22775
|
-
function
|
|
22832
|
+
function resolve5(baseURI, relativeURI, options) {
|
|
22776
22833
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
22777
22834
|
const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
22778
22835
|
schemelessOptions.skipEscape = true;
|
|
@@ -22946,7 +23003,7 @@ var init_ajvProvider_CEoC_sr = __esm({
|
|
|
22946
23003
|
const fastUri = {
|
|
22947
23004
|
SCHEMES,
|
|
22948
23005
|
normalize,
|
|
22949
|
-
resolve:
|
|
23006
|
+
resolve: resolve5,
|
|
22950
23007
|
resolveComponent,
|
|
22951
23008
|
equal,
|
|
22952
23009
|
serialize,
|
|
@@ -28638,7 +28695,7 @@ var init_stdio = __esm({
|
|
|
28638
28695
|
}
|
|
28639
28696
|
send(message) {
|
|
28640
28697
|
if (this._closed) return Promise.reject(/* @__PURE__ */ new Error("StdioServerTransport is closed"));
|
|
28641
|
-
return new Promise((
|
|
28698
|
+
return new Promise((resolve5, reject) => {
|
|
28642
28699
|
const json = serializeMessage(message);
|
|
28643
28700
|
let settled = false;
|
|
28644
28701
|
const onError = (error2) => {
|
|
@@ -28653,14 +28710,14 @@ var init_stdio = __esm({
|
|
|
28653
28710
|
settled = true;
|
|
28654
28711
|
this._stdout.off("error", onError);
|
|
28655
28712
|
this._stdout.off("drain", onDrain);
|
|
28656
|
-
|
|
28713
|
+
resolve5();
|
|
28657
28714
|
};
|
|
28658
28715
|
this._stdout.once("error", onError);
|
|
28659
28716
|
if (this._stdout.write(json)) {
|
|
28660
28717
|
if (settled) return;
|
|
28661
28718
|
settled = true;
|
|
28662
28719
|
this._stdout.off("error", onError);
|
|
28663
|
-
|
|
28720
|
+
resolve5();
|
|
28664
28721
|
} else if (!settled) this._stdout.once("drain", onDrain);
|
|
28665
28722
|
});
|
|
28666
28723
|
}
|
|
@@ -28714,14 +28771,14 @@ var init_stdio = __esm({
|
|
|
28714
28771
|
*/
|
|
28715
28772
|
async whenRequestsAnswered(timeoutMs) {
|
|
28716
28773
|
if (this._closed || this._pendingRequests.size === 0) return true;
|
|
28717
|
-
return await new Promise((
|
|
28774
|
+
return await new Promise((resolve5) => {
|
|
28718
28775
|
const waiter = () => {
|
|
28719
28776
|
clearTimeout(timer);
|
|
28720
|
-
|
|
28777
|
+
resolve5(true);
|
|
28721
28778
|
};
|
|
28722
28779
|
const timer = setTimeout(() => {
|
|
28723
28780
|
this._drainWaiters = this._drainWaiters.filter((pending) => pending !== waiter);
|
|
28724
|
-
|
|
28781
|
+
resolve5(false);
|
|
28725
28782
|
}, timeoutMs);
|
|
28726
28783
|
this._drainWaiters.push(waiter);
|
|
28727
28784
|
});
|
|
@@ -28998,10 +29055,10 @@ var init_server = __esm({
|
|
|
28998
29055
|
// src/commands/mcp.ts
|
|
28999
29056
|
var mcp_exports = {};
|
|
29000
29057
|
__export(mcp_exports, {
|
|
29058
|
+
agentTokenPath: () => agentTokenPath,
|
|
29001
29059
|
default: () => mcp
|
|
29002
29060
|
});
|
|
29003
29061
|
import { readFileSync as readFileSync2 } from "node:fs";
|
|
29004
|
-
import { homedir as homedir3 } from "node:os";
|
|
29005
29062
|
import { join as join6 } from "node:path";
|
|
29006
29063
|
async function mcp(argv, ctx) {
|
|
29007
29064
|
const cfg = resolveMcpConfig(argv, ctx.env, () => tokenFile(ctx.env));
|
|
@@ -29016,26 +29073,27 @@ async function mcp(argv, ctx) {
|
|
|
29016
29073
|
await handle.close();
|
|
29017
29074
|
return 0;
|
|
29018
29075
|
}
|
|
29019
|
-
await new Promise((
|
|
29020
|
-
process.stdin.once("close",
|
|
29021
|
-
process.stdin.once("end",
|
|
29076
|
+
await new Promise((resolve5) => {
|
|
29077
|
+
process.stdin.once("close", resolve5);
|
|
29078
|
+
process.stdin.once("end", resolve5);
|
|
29022
29079
|
});
|
|
29023
29080
|
return 0;
|
|
29024
29081
|
}
|
|
29025
|
-
var tokenFile;
|
|
29082
|
+
var agentTokenPath, tokenFile;
|
|
29026
29083
|
var init_mcp2 = __esm({
|
|
29027
29084
|
"src/commands/mcp.ts"() {
|
|
29028
29085
|
"use strict";
|
|
29086
|
+
init_src2();
|
|
29029
29087
|
init_stdio();
|
|
29030
29088
|
init_router();
|
|
29031
29089
|
init_config2();
|
|
29032
29090
|
init_client();
|
|
29033
29091
|
init_server();
|
|
29034
29092
|
init_redact();
|
|
29093
|
+
agentTokenPath = (env) => join6(resolveHome(env), "agent-token");
|
|
29035
29094
|
tokenFile = (env) => {
|
|
29036
|
-
const home = env.HANOMAN_HOME ?? join6(homedir3(), ".hanoman");
|
|
29037
29095
|
try {
|
|
29038
|
-
return readFileSync2(
|
|
29096
|
+
return readFileSync2(agentTokenPath(env), "utf8");
|
|
29039
29097
|
} catch {
|
|
29040
29098
|
return null;
|
|
29041
29099
|
}
|
|
@@ -29249,6 +29307,10 @@ var init_migrate_pg = __esm({
|
|
|
29249
29307
|
"TelegramAudit",
|
|
29250
29308
|
"Ticket",
|
|
29251
29309
|
"TicketAttachment",
|
|
29310
|
+
// SPEC-843 · ADR-0124 · SpecAttachment WAJIB sesudah Spec (FK specId, cascade). Tabel ini
|
|
29311
|
+
// LOCAL-only dan lazimnya TIDAK ada di sumber Postgres lama — jalur 42P01 memperlakukannya
|
|
29312
|
+
// sebagai nol baris, cermin Changelog.
|
|
29313
|
+
"SpecAttachment",
|
|
29252
29314
|
// SPEC-471 · ADR-0095 · GithubIssue sesudah Project (FK projectId) DAN sesudah Spec: `specId`
|
|
29253
29315
|
// memang tanpa FK, tapi memindahkannya lebih awal membuat urutan tabel tak lagi mencerminkan
|
|
29254
29316
|
// arah tautannya bagi pembaca berikutnya.
|