@hopping-dev/hub 0.1.0
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/assets/hopping-skill/SKILL.md +221 -0
- package/dist/approval/manager.d.ts +60 -0
- package/dist/approval/manager.d.ts.map +1 -0
- package/dist/approval/manager.js +101 -0
- package/dist/approval/manager.js.map +1 -0
- package/dist/approval/session-memory.d.ts +37 -0
- package/dist/approval/session-memory.d.ts.map +1 -0
- package/dist/approval/session-memory.js +63 -0
- package/dist/approval/session-memory.js.map +1 -0
- package/dist/cli/config-writer.d.ts +57 -0
- package/dist/cli/config-writer.d.ts.map +1 -0
- package/dist/cli/config-writer.js +318 -0
- package/dist/cli/config-writer.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +82 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/path-resolver.d.ts +48 -0
- package/dist/cli/path-resolver.d.ts.map +1 -0
- package/dist/cli/path-resolver.js +212 -0
- package/dist/cli/path-resolver.js.map +1 -0
- package/dist/cli/setup.d.ts +10 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +268 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cloud/connector.d.ts +74 -0
- package/dist/cloud/connector.d.ts.map +1 -0
- package/dist/cloud/connector.js +524 -0
- package/dist/cloud/connector.js.map +1 -0
- package/dist/cloud/index.d.ts +3 -0
- package/dist/cloud/index.d.ts.map +1 -0
- package/dist/cloud/index.js +6 -0
- package/dist/cloud/index.js.map +1 -0
- package/dist/config/manager.d.ts +76 -0
- package/dist/config/manager.d.ts.map +1 -0
- package/dist/config/manager.js +296 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/dev-mode.d.ts +30 -0
- package/dist/dev-mode.d.ts.map +1 -0
- package/dist/dev-mode.js +53 -0
- package/dist/dev-mode.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +354 -0
- package/dist/index.js.map +1 -0
- package/dist/ipc/index.d.ts +12 -0
- package/dist/ipc/index.d.ts.map +1 -0
- package/dist/ipc/index.js +15 -0
- package/dist/ipc/index.js.map +1 -0
- package/dist/ipc/watcher.d.ts +226 -0
- package/dist/ipc/watcher.d.ts.map +1 -0
- package/dist/ipc/watcher.js +745 -0
- package/dist/ipc/watcher.js.map +1 -0
- package/dist/local/approval-dialog.d.ts +30 -0
- package/dist/local/approval-dialog.d.ts.map +1 -0
- package/dist/local/approval-dialog.js +214 -0
- package/dist/local/approval-dialog.js.map +1 -0
- package/dist/local/index.d.ts +8 -0
- package/dist/local/index.d.ts.map +1 -0
- package/dist/local/index.js +13 -0
- package/dist/local/index.js.map +1 -0
- package/dist/local/local-approval.d.ts +55 -0
- package/dist/local/local-approval.d.ts.map +1 -0
- package/dist/local/local-approval.js +125 -0
- package/dist/local/local-approval.js.map +1 -0
- package/dist/local/notifier.d.ts +19 -0
- package/dist/local/notifier.d.ts.map +1 -0
- package/dist/local/notifier.js +110 -0
- package/dist/local/notifier.js.map +1 -0
- package/dist/local/sanitize.d.ts +20 -0
- package/dist/local/sanitize.d.ts.map +1 -0
- package/dist/local/sanitize.js +28 -0
- package/dist/local/sanitize.js.map +1 -0
- package/dist/mcp/file-extractor.d.ts +11 -0
- package/dist/mcp/file-extractor.d.ts.map +1 -0
- package/dist/mcp/file-extractor.js +74 -0
- package/dist/mcp/file-extractor.js.map +1 -0
- package/dist/mcp/risk-level.d.ts +44 -0
- package/dist/mcp/risk-level.d.ts.map +1 -0
- package/dist/mcp/risk-level.js +127 -0
- package/dist/mcp/risk-level.js.map +1 -0
- package/dist/mcp/schemas.d.ts +83 -0
- package/dist/mcp/schemas.d.ts.map +1 -0
- package/dist/mcp/schemas.js +84 -0
- package/dist/mcp/schemas.js.map +1 -0
- package/dist/mcp/summary.d.ts +11 -0
- package/dist/mcp/summary.d.ts.map +1 -0
- package/dist/mcp/summary.js +150 -0
- package/dist/mcp/summary.js.map +1 -0
- package/dist/mcp/tools.d.ts +45 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +1217 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/pairing/auto-pairing.d.ts +37 -0
- package/dist/pairing/auto-pairing.d.ts.map +1 -0
- package/dist/pairing/auto-pairing.js +144 -0
- package/dist/pairing/auto-pairing.js.map +1 -0
- package/dist/pairing/binding-poller.d.ts +26 -0
- package/dist/pairing/binding-poller.d.ts.map +1 -0
- package/dist/pairing/binding-poller.js +108 -0
- package/dist/pairing/binding-poller.js.map +1 -0
- package/dist/pairing/pairing-server.d.ts +14 -0
- package/dist/pairing/pairing-server.d.ts.map +1 -0
- package/dist/pairing/pairing-server.js +277 -0
- package/dist/pairing/pairing-server.js.map +1 -0
- package/dist/pairing/qr-display.d.ts +14 -0
- package/dist/pairing/qr-display.d.ts.map +1 -0
- package/dist/pairing/qr-display.js +40 -0
- package/dist/pairing/qr-display.js.map +1 -0
- package/dist/policy/engine.d.ts +31 -0
- package/dist/policy/engine.d.ts.map +1 -0
- package/dist/policy/engine.js +187 -0
- package/dist/policy/engine.js.map +1 -0
- package/dist/policy/store.d.ts +26 -0
- package/dist/policy/store.d.ts.map +1 -0
- package/dist/policy/store.js +70 -0
- package/dist/policy/store.js.map +1 -0
- package/dist/policy/system-policies.d.ts +15 -0
- package/dist/policy/system-policies.d.ts.map +1 -0
- package/dist/policy/system-policies.js +265 -0
- package/dist/policy/system-policies.js.map +1 -0
- package/dist/policy/tool-mapping.d.ts +45 -0
- package/dist/policy/tool-mapping.d.ts.map +1 -0
- package/dist/policy/tool-mapping.js +88 -0
- package/dist/policy/tool-mapping.js.map +1 -0
- package/dist/policy/tool-registry.json +85 -0
- package/dist/store/db.d.ts +17 -0
- package/dist/store/db.d.ts.map +1 -0
- package/dist/store/db.js +193 -0
- package/dist/store/db.js.map +1 -0
- package/dist/store/index.d.ts +4 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +7 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/metadata.d.ts +31 -0
- package/dist/store/metadata.d.ts.map +1 -0
- package/dist/store/metadata.js +178 -0
- package/dist/store/metadata.js.map +1 -0
- package/dist/store/operations.d.ts +26 -0
- package/dist/store/operations.d.ts.map +1 -0
- package/dist/store/operations.js +171 -0
- package/dist/store/operations.js.map +1 -0
- package/dist/utils/json.d.ts +7 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/json.js +33 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/logger.d.ts +13 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +58 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/open-browser.d.ts +8 -0
- package/dist/utils/open-browser.d.ts.map +1 -0
- package/dist/utils/open-browser.js +38 -0
- package/dist/utils/open-browser.js.map +1 -0
- package/node_modules/@hopping/shared/dist/types.d.ts +649 -0
- package/node_modules/@hopping/shared/dist/types.js +48 -0
- package/node_modules/@hopping/shared/dist/types.js.map +1 -0
- package/node_modules/@hopping/shared/package.json +14 -0
- package/node_modules/@hopping/shared/tsconfig.json +16 -0
- package/node_modules/@hopping/shared/types.d.ts +650 -0
- package/node_modules/@hopping/shared/types.d.ts.map +1 -0
- package/node_modules/@hopping/shared/types.js +48 -0
- package/node_modules/@hopping/shared/types.js.map +1 -0
- package/node_modules/@hopping/shared/types.ts +895 -0
- package/package.json +52 -0
package/dist/store/db.js
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.HubDatabase = void 0;
|
|
40
|
+
exports.resolveDbPath = resolveDbPath;
|
|
41
|
+
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
42
|
+
const os = __importStar(require("os"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
const operations_1 = require("./operations");
|
|
46
|
+
const metadata_1 = require("./metadata");
|
|
47
|
+
// ============================================
|
|
48
|
+
// DB Path Resolution
|
|
49
|
+
// ============================================
|
|
50
|
+
function resolveDbPath(dbPath) {
|
|
51
|
+
if (dbPath !== undefined)
|
|
52
|
+
return dbPath;
|
|
53
|
+
const envPath = process.env.HOPPING_DB_PATH;
|
|
54
|
+
if (envPath)
|
|
55
|
+
return envPath.replace(/^~/, os.homedir());
|
|
56
|
+
return path.join(os.homedir(), '.hopping', 'hopping.db');
|
|
57
|
+
}
|
|
58
|
+
// ============================================
|
|
59
|
+
// Schema Initialization
|
|
60
|
+
// ============================================
|
|
61
|
+
const CURRENT_SCHEMA_VERSION = 4;
|
|
62
|
+
/** 檢查某 table 是否已有指定欄位(用於安全 migration) */
|
|
63
|
+
function hasColumn(db, table, column) {
|
|
64
|
+
const columns = db.prepare(`PRAGMA table_info('${table}')`).all();
|
|
65
|
+
return columns.some((c) => c.name === column);
|
|
66
|
+
}
|
|
67
|
+
function initSchema(db) {
|
|
68
|
+
const version = db.pragma('user_version', { simple: true });
|
|
69
|
+
if (version >= CURRENT_SCHEMA_VERSION)
|
|
70
|
+
return;
|
|
71
|
+
// v0(全新安裝):建立所有表格(含 v2+v3 欄位),直接跳到最新版本
|
|
72
|
+
if (version === 0) {
|
|
73
|
+
db.exec(`
|
|
74
|
+
CREATE TABLE IF NOT EXISTS operations (
|
|
75
|
+
id TEXT PRIMARY KEY,
|
|
76
|
+
approval_id TEXT,
|
|
77
|
+
tool_name TEXT NOT NULL,
|
|
78
|
+
tool_params TEXT,
|
|
79
|
+
file_paths TEXT,
|
|
80
|
+
risk_level TEXT,
|
|
81
|
+
decision TEXT,
|
|
82
|
+
created_at TEXT NOT NULL,
|
|
83
|
+
decided_at TEXT,
|
|
84
|
+
tool_use_id TEXT,
|
|
85
|
+
prompt_type TEXT,
|
|
86
|
+
response_type TEXT,
|
|
87
|
+
response_data TEXT
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
CREATE TABLE IF NOT EXISTS metadata (
|
|
91
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
92
|
+
operation_id TEXT REFERENCES operations(id),
|
|
93
|
+
agent_type TEXT,
|
|
94
|
+
session_id TEXT,
|
|
95
|
+
duration_ms INTEGER,
|
|
96
|
+
token_usage INTEGER,
|
|
97
|
+
context_tags TEXT,
|
|
98
|
+
source TEXT,
|
|
99
|
+
result_status TEXT,
|
|
100
|
+
tool_result_summary TEXT,
|
|
101
|
+
created_at TEXT NOT NULL
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
CREATE INDEX IF NOT EXISTS idx_operations_created_at ON operations(created_at);
|
|
105
|
+
CREATE INDEX IF NOT EXISTS idx_operations_tool_use_id ON operations(tool_use_id);
|
|
106
|
+
CREATE INDEX IF NOT EXISTS idx_metadata_operation_id ON metadata(operation_id);
|
|
107
|
+
CREATE INDEX IF NOT EXISTS idx_metadata_session_id ON metadata(session_id);
|
|
108
|
+
CREATE INDEX IF NOT EXISTS idx_metadata_source ON metadata(source);
|
|
109
|
+
`);
|
|
110
|
+
db.pragma(`user_version = ${CURRENT_SCHEMA_VERSION}`);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
// --- 以下為既有安裝的增量 migration ---
|
|
114
|
+
// v1 → v2:metadata 新增 source / result_status / tool_result_summary
|
|
115
|
+
if (version <= 1) {
|
|
116
|
+
const migrateToV2 = db.transaction(() => {
|
|
117
|
+
if (!hasColumn(db, 'metadata', 'source')) {
|
|
118
|
+
db.exec(`ALTER TABLE metadata ADD COLUMN source TEXT`);
|
|
119
|
+
}
|
|
120
|
+
if (!hasColumn(db, 'metadata', 'result_status')) {
|
|
121
|
+
db.exec(`ALTER TABLE metadata ADD COLUMN result_status TEXT`);
|
|
122
|
+
}
|
|
123
|
+
if (!hasColumn(db, 'metadata', 'tool_result_summary')) {
|
|
124
|
+
db.exec(`ALTER TABLE metadata ADD COLUMN tool_result_summary TEXT`);
|
|
125
|
+
}
|
|
126
|
+
db.exec(`CREATE INDEX IF NOT EXISTS idx_metadata_session_id ON metadata(session_id)`);
|
|
127
|
+
db.exec(`CREATE INDEX IF NOT EXISTS idx_metadata_source ON metadata(source)`);
|
|
128
|
+
});
|
|
129
|
+
migrateToV2();
|
|
130
|
+
}
|
|
131
|
+
// v2 → v3:operations 新增 tool_use_id(pre/post 關聯鍵)
|
|
132
|
+
if (version <= 2) {
|
|
133
|
+
const migrateToV3 = db.transaction(() => {
|
|
134
|
+
if (!hasColumn(db, 'operations', 'tool_use_id')) {
|
|
135
|
+
db.exec(`ALTER TABLE operations ADD COLUMN tool_use_id TEXT`);
|
|
136
|
+
}
|
|
137
|
+
db.exec(`CREATE INDEX IF NOT EXISTS idx_operations_tool_use_id ON operations(tool_use_id)`);
|
|
138
|
+
});
|
|
139
|
+
migrateToV3();
|
|
140
|
+
}
|
|
141
|
+
// v3 → v4:operations 新增 prompt_type/response_type/response_data(Rich Permission)
|
|
142
|
+
if (version <= 3) {
|
|
143
|
+
const migrateToV4 = db.transaction(() => {
|
|
144
|
+
if (!hasColumn(db, 'operations', 'prompt_type')) {
|
|
145
|
+
db.exec(`ALTER TABLE operations ADD COLUMN prompt_type TEXT`);
|
|
146
|
+
}
|
|
147
|
+
if (!hasColumn(db, 'operations', 'response_type')) {
|
|
148
|
+
db.exec(`ALTER TABLE operations ADD COLUMN response_type TEXT`);
|
|
149
|
+
}
|
|
150
|
+
if (!hasColumn(db, 'operations', 'response_data')) {
|
|
151
|
+
db.exec(`ALTER TABLE operations ADD COLUMN response_data TEXT`);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
migrateToV4();
|
|
155
|
+
}
|
|
156
|
+
db.pragma(`user_version = ${CURRENT_SCHEMA_VERSION}`);
|
|
157
|
+
}
|
|
158
|
+
// ============================================
|
|
159
|
+
// HubDatabase Class
|
|
160
|
+
// ============================================
|
|
161
|
+
class HubDatabase {
|
|
162
|
+
db;
|
|
163
|
+
operations;
|
|
164
|
+
metadata;
|
|
165
|
+
/**
|
|
166
|
+
* @param dbPath - undefined = 預設路徑, ':memory:' = 測試用
|
|
167
|
+
*/
|
|
168
|
+
constructor(dbPath) {
|
|
169
|
+
const resolvedPath = resolveDbPath(dbPath);
|
|
170
|
+
// 若不是記憶體模式,自動建立父目錄
|
|
171
|
+
if (resolvedPath !== ':memory:') {
|
|
172
|
+
const dir = path.dirname(resolvedPath);
|
|
173
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
174
|
+
}
|
|
175
|
+
this.db = new better_sqlite3_1.default(resolvedPath);
|
|
176
|
+
// 啟用 WAL 模式(讀寫並行,Hook IPC 安全)
|
|
177
|
+
this.db.pragma('journal_mode = WAL');
|
|
178
|
+
// 啟用外鍵約束
|
|
179
|
+
this.db.pragma('foreign_keys = ON');
|
|
180
|
+
initSchema(this.db);
|
|
181
|
+
this.operations = (0, operations_1.createOperationStore)(this.db);
|
|
182
|
+
this.metadata = (0, metadata_1.createMetadataStore)(this.db);
|
|
183
|
+
}
|
|
184
|
+
close() {
|
|
185
|
+
this.db.close();
|
|
186
|
+
}
|
|
187
|
+
/** 取得底層 Database 實例(僅供測試使用) */
|
|
188
|
+
get _db() {
|
|
189
|
+
return this.db;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
exports.HubDatabase = HubDatabase;
|
|
193
|
+
//# sourceMappingURL=db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/store/db.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveDbPath = exports.HubDatabase = void 0;
|
|
4
|
+
var db_1 = require("./db");
|
|
5
|
+
Object.defineProperty(exports, "HubDatabase", { enumerable: true, get: function () { return db_1.HubDatabase; } });
|
|
6
|
+
Object.defineProperty(exports, "resolveDbPath", { enumerable: true, get: function () { return db_1.resolveDbPath; } });
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":";;;AAAA,2BAAkD;AAAzC,iGAAA,WAAW,OAAA;AAAE,mGAAA,aAAa,OAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import type { OperationMetadataRecord, OperationSource, ResultStatus } from '@hopping/shared';
|
|
3
|
+
export interface ToolUsageStat {
|
|
4
|
+
toolName: string;
|
|
5
|
+
count: number;
|
|
6
|
+
avgDurationMs: number | null;
|
|
7
|
+
successRate: number | null;
|
|
8
|
+
}
|
|
9
|
+
export interface SessionTimelineEntry {
|
|
10
|
+
operationId: string;
|
|
11
|
+
toolName: string;
|
|
12
|
+
riskLevel: string | null;
|
|
13
|
+
decision: string | null;
|
|
14
|
+
durationMs: number | null;
|
|
15
|
+
resultStatus: ResultStatus | null;
|
|
16
|
+
source: OperationSource | null;
|
|
17
|
+
createdAt: string;
|
|
18
|
+
}
|
|
19
|
+
export interface MetadataStore {
|
|
20
|
+
insert(record: Omit<OperationMetadataRecord, 'id'>): void;
|
|
21
|
+
getByOperationId(operationId: string): OperationMetadataRecord[];
|
|
22
|
+
getBySessionId(sessionId: string, limit?: number): OperationMetadataRecord[];
|
|
23
|
+
getToolUsageStats(date?: string): ToolUsageStat[];
|
|
24
|
+
/** Get tool usage stats across a UTC datetime range, sorted by count DESC. startUtc inclusive, endUtc exclusive. */
|
|
25
|
+
getToolUsageStatsRange(startUtc: string, endUtc: string, limit?: number): ToolUsageStat[];
|
|
26
|
+
getSessionTimeline(sessionId: string, limit?: number): SessionTimelineEntry[];
|
|
27
|
+
/** Get the most recent N timeline entries regardless of session, ordered by created_at DESC. */
|
|
28
|
+
getRecentTimeline(limit?: number): SessionTimelineEntry[];
|
|
29
|
+
}
|
|
30
|
+
export declare function createMetadataStore(db: Database.Database): MetadataStore;
|
|
31
|
+
//# sourceMappingURL=metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/store/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,KAAK,EAAE,uBAAuB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAM9F,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,uBAAuB,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1D,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,uBAAuB,EAAE,CAAC;IACjE,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,uBAAuB,EAAE,CAAC;IAC7E,iBAAiB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa,EAAE,CAAC;IAClD,oHAAoH;IACpH,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,aAAa,EAAE,CAAC;IAC1F,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,oBAAoB,EAAE,CAAC;IAC9E,gGAAgG;IAChG,iBAAiB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,oBAAoB,EAAE,CAAC;CAC3D;AAoFD,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,aAAa,CA0KxE"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createMetadataStore = createMetadataStore;
|
|
4
|
+
// ============================================
|
|
5
|
+
// Mapping Helpers
|
|
6
|
+
// ============================================
|
|
7
|
+
function rowToRecord(row) {
|
|
8
|
+
return {
|
|
9
|
+
id: row.id,
|
|
10
|
+
operationId: row.operation_id,
|
|
11
|
+
agentType: row.agent_type,
|
|
12
|
+
sessionId: row.session_id,
|
|
13
|
+
durationMs: row.duration_ms,
|
|
14
|
+
tokenUsage: row.token_usage,
|
|
15
|
+
contextTags: row.context_tags,
|
|
16
|
+
source: row.source,
|
|
17
|
+
resultStatus: row.result_status,
|
|
18
|
+
toolResultSummary: row.tool_result_summary,
|
|
19
|
+
createdAt: row.created_at,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function rowToToolUsageStat(row) {
|
|
23
|
+
return {
|
|
24
|
+
toolName: row.tool_name,
|
|
25
|
+
count: row.count,
|
|
26
|
+
avgDurationMs: row.avg_duration_ms,
|
|
27
|
+
successRate: row.success_rate,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function rowToSessionTimelineEntry(row) {
|
|
31
|
+
return {
|
|
32
|
+
operationId: row.operation_id,
|
|
33
|
+
toolName: row.tool_name,
|
|
34
|
+
riskLevel: row.risk_level,
|
|
35
|
+
decision: row.decision,
|
|
36
|
+
durationMs: row.duration_ms,
|
|
37
|
+
resultStatus: row.result_status,
|
|
38
|
+
source: row.source,
|
|
39
|
+
createdAt: row.created_at,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
// ============================================
|
|
43
|
+
// Factory
|
|
44
|
+
// ============================================
|
|
45
|
+
function createMetadataStore(db) {
|
|
46
|
+
const insertStmt = db.prepare(`
|
|
47
|
+
INSERT INTO metadata (operation_id, agent_type, session_id, duration_ms, token_usage, context_tags, source, result_status, tool_result_summary, created_at)
|
|
48
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
49
|
+
`);
|
|
50
|
+
const getByOperationIdStmt = db.prepare(`
|
|
51
|
+
SELECT id, operation_id, agent_type, session_id, duration_ms, token_usage, context_tags,
|
|
52
|
+
source, result_status, tool_result_summary, created_at
|
|
53
|
+
FROM metadata
|
|
54
|
+
WHERE operation_id = ?
|
|
55
|
+
ORDER BY id ASC
|
|
56
|
+
`);
|
|
57
|
+
const getBySessionIdStmt = db.prepare(`
|
|
58
|
+
SELECT id, operation_id, agent_type, session_id, duration_ms, token_usage, context_tags,
|
|
59
|
+
source, result_status, tool_result_summary, created_at
|
|
60
|
+
FROM metadata
|
|
61
|
+
WHERE session_id = ?
|
|
62
|
+
ORDER BY id ASC
|
|
63
|
+
LIMIT ?
|
|
64
|
+
`);
|
|
65
|
+
// getToolUsageStats — 兩個 prepared statements(有/無日期過濾)
|
|
66
|
+
const getToolUsageStatsAllStmt = db.prepare(`
|
|
67
|
+
SELECT
|
|
68
|
+
o.tool_name,
|
|
69
|
+
COUNT(*) as count,
|
|
70
|
+
AVG(m.duration_ms) as avg_duration_ms,
|
|
71
|
+
AVG(
|
|
72
|
+
CASE
|
|
73
|
+
WHEN m.result_status = 'success' THEN 1.0
|
|
74
|
+
WHEN m.result_status = 'failure' THEN 0.0
|
|
75
|
+
ELSE NULL
|
|
76
|
+
END
|
|
77
|
+
) as success_rate
|
|
78
|
+
FROM metadata m
|
|
79
|
+
JOIN operations o ON m.operation_id = o.id
|
|
80
|
+
GROUP BY o.tool_name
|
|
81
|
+
ORDER BY count DESC
|
|
82
|
+
`);
|
|
83
|
+
const getToolUsageStatsByDateStmt = db.prepare(`
|
|
84
|
+
SELECT
|
|
85
|
+
o.tool_name,
|
|
86
|
+
COUNT(*) as count,
|
|
87
|
+
AVG(m.duration_ms) as avg_duration_ms,
|
|
88
|
+
AVG(
|
|
89
|
+
CASE
|
|
90
|
+
WHEN m.result_status = 'success' THEN 1.0
|
|
91
|
+
WHEN m.result_status = 'failure' THEN 0.0
|
|
92
|
+
ELSE NULL
|
|
93
|
+
END
|
|
94
|
+
) as success_rate
|
|
95
|
+
FROM metadata m
|
|
96
|
+
JOIN operations o ON m.operation_id = o.id
|
|
97
|
+
WHERE DATE(m.created_at) = ?
|
|
98
|
+
GROUP BY o.tool_name
|
|
99
|
+
ORDER BY count DESC
|
|
100
|
+
`);
|
|
101
|
+
const getToolUsageStatsRangeStmt = db.prepare(`
|
|
102
|
+
SELECT
|
|
103
|
+
o.tool_name,
|
|
104
|
+
COUNT(*) as count,
|
|
105
|
+
AVG(m.duration_ms) as avg_duration_ms,
|
|
106
|
+
AVG(
|
|
107
|
+
CASE
|
|
108
|
+
WHEN m.result_status = 'success' THEN 1.0
|
|
109
|
+
WHEN m.result_status = 'failure' THEN 0.0
|
|
110
|
+
ELSE NULL
|
|
111
|
+
END
|
|
112
|
+
) as success_rate
|
|
113
|
+
FROM metadata m
|
|
114
|
+
JOIN operations o ON m.operation_id = o.id
|
|
115
|
+
WHERE o.created_at >= ? AND o.created_at < ?
|
|
116
|
+
GROUP BY o.tool_name
|
|
117
|
+
ORDER BY count DESC
|
|
118
|
+
LIMIT ?
|
|
119
|
+
`);
|
|
120
|
+
const getSessionTimelineStmt = db.prepare(`
|
|
121
|
+
SELECT
|
|
122
|
+
o.id as operation_id,
|
|
123
|
+
o.tool_name,
|
|
124
|
+
o.risk_level,
|
|
125
|
+
o.decision,
|
|
126
|
+
m.duration_ms,
|
|
127
|
+
m.result_status,
|
|
128
|
+
m.source,
|
|
129
|
+
m.created_at
|
|
130
|
+
FROM metadata m
|
|
131
|
+
JOIN operations o ON m.operation_id = o.id
|
|
132
|
+
WHERE m.session_id = ?
|
|
133
|
+
ORDER BY m.created_at ASC
|
|
134
|
+
LIMIT ?
|
|
135
|
+
`);
|
|
136
|
+
const getRecentTimelineStmt = db.prepare(`
|
|
137
|
+
SELECT
|
|
138
|
+
o.id as operation_id,
|
|
139
|
+
o.tool_name,
|
|
140
|
+
o.risk_level,
|
|
141
|
+
o.decision,
|
|
142
|
+
m.duration_ms,
|
|
143
|
+
m.result_status,
|
|
144
|
+
m.source,
|
|
145
|
+
m.created_at
|
|
146
|
+
FROM metadata m
|
|
147
|
+
JOIN operations o ON m.operation_id = o.id
|
|
148
|
+
ORDER BY m.created_at DESC
|
|
149
|
+
LIMIT ?
|
|
150
|
+
`);
|
|
151
|
+
return {
|
|
152
|
+
insert(record) {
|
|
153
|
+
insertStmt.run(record.operationId, record.agentType, record.sessionId, record.durationMs ?? null, record.tokenUsage ?? null, record.contextTags ?? null, record.source ?? null, record.resultStatus ?? null, record.toolResultSummary?.slice(0, 500) ?? null, record.createdAt);
|
|
154
|
+
},
|
|
155
|
+
getByOperationId(operationId) {
|
|
156
|
+
return getByOperationIdStmt.all(operationId).map(rowToRecord);
|
|
157
|
+
},
|
|
158
|
+
getBySessionId(sessionId, limit = 100) {
|
|
159
|
+
return getBySessionIdStmt.all(sessionId, limit).map(rowToRecord);
|
|
160
|
+
},
|
|
161
|
+
getToolUsageStats(date) {
|
|
162
|
+
if (date) {
|
|
163
|
+
return getToolUsageStatsByDateStmt.all(date).map(rowToToolUsageStat);
|
|
164
|
+
}
|
|
165
|
+
return getToolUsageStatsAllStmt.all().map(rowToToolUsageStat);
|
|
166
|
+
},
|
|
167
|
+
getToolUsageStatsRange(startUtc, endUtc, limit = 10) {
|
|
168
|
+
return getToolUsageStatsRangeStmt.all(startUtc, endUtc, limit).map(rowToToolUsageStat);
|
|
169
|
+
},
|
|
170
|
+
getSessionTimeline(sessionId, limit = 50) {
|
|
171
|
+
return getSessionTimelineStmt.all(sessionId, limit).map(rowToSessionTimelineEntry);
|
|
172
|
+
},
|
|
173
|
+
getRecentTimeline(limit = 100) {
|
|
174
|
+
return getRecentTimelineStmt.all(limit).map(rowToSessionTimelineEntry);
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/store/metadata.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import type { OperationRecord } from '@hopping/shared';
|
|
3
|
+
export interface DecisionCounts {
|
|
4
|
+
approved: number;
|
|
5
|
+
denied: number;
|
|
6
|
+
autoApproved: number;
|
|
7
|
+
total: number;
|
|
8
|
+
}
|
|
9
|
+
export interface OperationStore {
|
|
10
|
+
insert(record: OperationRecord): void;
|
|
11
|
+
getById(id: string): OperationRecord | undefined;
|
|
12
|
+
/** 透過 tool_use_id 查找 operation(pre/post 關聯用) */
|
|
13
|
+
getByToolUseId(toolUseId: string): OperationRecord | undefined;
|
|
14
|
+
countToday(): number;
|
|
15
|
+
updateDecision(id: string, decision: string, decidedAt: string): void;
|
|
16
|
+
/** 更新 response_data(Rich Permission 回應後寫入) */
|
|
17
|
+
updateResponseData(id: string, responseData: string): void;
|
|
18
|
+
/** List recent operations, ordered by created_at DESC */
|
|
19
|
+
listRecent(limit: number): OperationRecord[];
|
|
20
|
+
/** Count operations by decision for a given date (YYYY-MM-DD) */
|
|
21
|
+
countByDecision(date?: string): DecisionCounts;
|
|
22
|
+
/** Count operations by decision across a UTC datetime range (timezone-aware). startUtc inclusive, endUtc exclusive. */
|
|
23
|
+
countByDecisionRange(startUtc: string, endUtc: string): DecisionCounts;
|
|
24
|
+
}
|
|
25
|
+
export declare function createOperationStore(db: Database.Database): OperationStore;
|
|
26
|
+
//# sourceMappingURL=operations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../../src/store/operations.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAMvD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;IACtC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAAC;IACjD,gDAAgD;IAChD,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAAC;IAC/D,UAAU,IAAI,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACtE,8CAA8C;IAC9C,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3D,yDAAyD;IACzD,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,EAAE,CAAC;IAC7C,iEAAiE;IACjE,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,cAAc,CAAC;IAC/C,uHAAuH;IACvH,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,cAAc,CAAC;CACxE;AAgDD,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,cAAc,CAqM1E"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createOperationStore = createOperationStore;
|
|
4
|
+
// ============================================
|
|
5
|
+
// Mapping Helpers
|
|
6
|
+
// ============================================
|
|
7
|
+
function rowToRecord(row) {
|
|
8
|
+
return {
|
|
9
|
+
id: row.id,
|
|
10
|
+
approvalId: row.approval_id,
|
|
11
|
+
toolName: row.tool_name,
|
|
12
|
+
toolParams: row.tool_params,
|
|
13
|
+
filePaths: row.file_paths,
|
|
14
|
+
riskLevel: row.risk_level,
|
|
15
|
+
decision: row.decision,
|
|
16
|
+
createdAt: row.created_at,
|
|
17
|
+
decidedAt: row.decided_at,
|
|
18
|
+
toolUseId: row.tool_use_id,
|
|
19
|
+
promptType: row.prompt_type,
|
|
20
|
+
responseType: row.response_type,
|
|
21
|
+
responseData: row.response_data,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
// ============================================
|
|
25
|
+
// Factory
|
|
26
|
+
// ============================================
|
|
27
|
+
function createOperationStore(db) {
|
|
28
|
+
const insertStmt = db.prepare(`
|
|
29
|
+
INSERT INTO operations (id, approval_id, tool_name, tool_params, file_paths, risk_level, decision, created_at, decided_at, tool_use_id, prompt_type, response_type, response_data)
|
|
30
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
31
|
+
`);
|
|
32
|
+
const getByIdStmt = db.prepare(`
|
|
33
|
+
SELECT id, approval_id, tool_name, tool_params, file_paths, risk_level, decision, created_at, decided_at, tool_use_id, prompt_type, response_type, response_data
|
|
34
|
+
FROM operations
|
|
35
|
+
WHERE id = ?
|
|
36
|
+
`);
|
|
37
|
+
const getByToolUseIdStmt = db.prepare(`
|
|
38
|
+
SELECT id, approval_id, tool_name, tool_params, file_paths, risk_level, decision, created_at, decided_at, tool_use_id, prompt_type, response_type, response_data
|
|
39
|
+
FROM operations
|
|
40
|
+
WHERE tool_use_id = ?
|
|
41
|
+
LIMIT 1
|
|
42
|
+
`);
|
|
43
|
+
const countTodayStmt = db.prepare(`
|
|
44
|
+
SELECT COUNT(*) AS count
|
|
45
|
+
FROM operations
|
|
46
|
+
WHERE date(created_at) = ?
|
|
47
|
+
`);
|
|
48
|
+
const updateDecisionStmt = db.prepare(`
|
|
49
|
+
UPDATE operations
|
|
50
|
+
SET decision = ?, decided_at = ?
|
|
51
|
+
WHERE id = ?
|
|
52
|
+
`);
|
|
53
|
+
const updateResponseDataStmt = db.prepare(`
|
|
54
|
+
UPDATE operations
|
|
55
|
+
SET response_data = ?
|
|
56
|
+
WHERE id = ?
|
|
57
|
+
`);
|
|
58
|
+
const listRecentStmt = db.prepare(`
|
|
59
|
+
SELECT id, approval_id, tool_name, tool_params, file_paths, risk_level, decision, created_at, decided_at, tool_use_id, prompt_type, response_type, response_data
|
|
60
|
+
FROM operations
|
|
61
|
+
ORDER BY created_at DESC
|
|
62
|
+
LIMIT ?
|
|
63
|
+
`);
|
|
64
|
+
const countByDecisionStmt = db.prepare(`
|
|
65
|
+
SELECT decision, COUNT(*) AS count
|
|
66
|
+
FROM operations
|
|
67
|
+
WHERE date(created_at) = ?
|
|
68
|
+
GROUP BY decision
|
|
69
|
+
`);
|
|
70
|
+
const countAutoApprovedStmt = db.prepare(`
|
|
71
|
+
SELECT COUNT(*) AS count FROM operations
|
|
72
|
+
WHERE date(created_at) = ? AND decision = 'approved' AND risk_level = 'low'
|
|
73
|
+
`);
|
|
74
|
+
const countByDecisionRangeStmt = db.prepare(`
|
|
75
|
+
SELECT decision, COUNT(*) AS count
|
|
76
|
+
FROM operations
|
|
77
|
+
WHERE created_at >= ? AND created_at < ?
|
|
78
|
+
GROUP BY decision
|
|
79
|
+
`);
|
|
80
|
+
const countAutoApprovedRangeStmt = db.prepare(`
|
|
81
|
+
SELECT COUNT(*) AS count FROM operations
|
|
82
|
+
WHERE created_at >= ? AND created_at < ? AND decision = 'approved' AND risk_level = 'low'
|
|
83
|
+
`);
|
|
84
|
+
return {
|
|
85
|
+
insert(record) {
|
|
86
|
+
insertStmt.run(record.id, record.approvalId ?? null, record.toolName, record.toolParams ?? null, record.filePaths ?? null, record.riskLevel ?? null, record.decision ?? null, record.createdAt, record.decidedAt ?? null, record.toolUseId ?? null, record.promptType ?? null, record.responseType ?? null, record.responseData ?? null);
|
|
87
|
+
},
|
|
88
|
+
getById(id) {
|
|
89
|
+
const row = getByIdStmt.get(id);
|
|
90
|
+
return row ? rowToRecord(row) : undefined;
|
|
91
|
+
},
|
|
92
|
+
getByToolUseId(toolUseId) {
|
|
93
|
+
const row = getByToolUseIdStmt.get(toolUseId);
|
|
94
|
+
return row ? rowToRecord(row) : undefined;
|
|
95
|
+
},
|
|
96
|
+
countToday() {
|
|
97
|
+
// Compute UTC date in JS to guarantee consistency with ISO 8601 created_at values
|
|
98
|
+
const todayUTC = new Date().toISOString().slice(0, 10);
|
|
99
|
+
const result = countTodayStmt.get(todayUTC);
|
|
100
|
+
return result?.count ?? 0;
|
|
101
|
+
},
|
|
102
|
+
updateDecision(id, decision, decidedAt) {
|
|
103
|
+
updateDecisionStmt.run(decision, decidedAt, id);
|
|
104
|
+
},
|
|
105
|
+
updateResponseData(id, responseData) {
|
|
106
|
+
updateResponseDataStmt.run(responseData, id);
|
|
107
|
+
},
|
|
108
|
+
listRecent(limit) {
|
|
109
|
+
return listRecentStmt.all(limit).map(rowToRecord);
|
|
110
|
+
},
|
|
111
|
+
countByDecision(date) {
|
|
112
|
+
const targetDate = date ?? new Date().toISOString().slice(0, 10);
|
|
113
|
+
const rows = countByDecisionStmt.all(targetDate);
|
|
114
|
+
const counts = { approved: 0, denied: 0, autoApproved: 0, total: 0 };
|
|
115
|
+
for (const row of rows) {
|
|
116
|
+
const c = row.count;
|
|
117
|
+
counts.total += c;
|
|
118
|
+
switch (row.decision) {
|
|
119
|
+
case 'approved':
|
|
120
|
+
counts.approved += c;
|
|
121
|
+
break;
|
|
122
|
+
case 'denied':
|
|
123
|
+
case 'timeout':
|
|
124
|
+
counts.denied += c;
|
|
125
|
+
break;
|
|
126
|
+
case 'answered':
|
|
127
|
+
// hopping.ask 問題回答 — 非審核操作,僅計入 total
|
|
128
|
+
break;
|
|
129
|
+
case null:
|
|
130
|
+
// Operations with null decision are pending or auto-processed
|
|
131
|
+
break;
|
|
132
|
+
default:
|
|
133
|
+
// conditional, etc.
|
|
134
|
+
counts.approved += c;
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
counts.autoApproved = countAutoApprovedStmt.get(targetDate)?.count ?? 0;
|
|
139
|
+
return counts;
|
|
140
|
+
},
|
|
141
|
+
countByDecisionRange(startUtc, endUtc) {
|
|
142
|
+
const rows = countByDecisionRangeStmt.all(startUtc, endUtc);
|
|
143
|
+
const counts = { approved: 0, denied: 0, autoApproved: 0, total: 0 };
|
|
144
|
+
for (const row of rows) {
|
|
145
|
+
const c = row.count;
|
|
146
|
+
counts.total += c;
|
|
147
|
+
switch (row.decision) {
|
|
148
|
+
case 'approved':
|
|
149
|
+
counts.approved += c;
|
|
150
|
+
break;
|
|
151
|
+
case 'denied':
|
|
152
|
+
case 'timeout':
|
|
153
|
+
counts.denied += c;
|
|
154
|
+
break;
|
|
155
|
+
case 'answered':
|
|
156
|
+
// hopping.ask 問題回答 — 非審核操作,僅計入 total
|
|
157
|
+
break;
|
|
158
|
+
case null:
|
|
159
|
+
break;
|
|
160
|
+
default:
|
|
161
|
+
// conditional → approved
|
|
162
|
+
counts.approved += c;
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
counts.autoApproved = countAutoApprovedRangeStmt.get(startUtc, endUtc)?.count ?? 0;
|
|
167
|
+
return counts;
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=operations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../../src/store/operations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safe JSON parse helpers — 從 SQLite 讀取 JSON 字串時使用
|
|
3
|
+
* 解析失敗回傳 undefined,不 throw
|
|
4
|
+
*/
|
|
5
|
+
export declare function safeJsonParseObject(value: string): Record<string, unknown> | undefined;
|
|
6
|
+
export declare function safeJsonParseArray(value: string): string[] | undefined;
|
|
7
|
+
//# sourceMappingURL=json.d.ts.map
|