oasis_test_v2 2.2.106 → 2.2.107
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/index.js +125 -11
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -43276,7 +43276,7 @@ var require_websocket = __commonJS({
|
|
|
43276
43276
|
var http2 = require("http");
|
|
43277
43277
|
var net = require("net");
|
|
43278
43278
|
var tls = require("tls");
|
|
43279
|
-
var { randomBytes: randomBytes17, createHash:
|
|
43279
|
+
var { randomBytes: randomBytes17, createHash: createHash47 } = require("crypto");
|
|
43280
43280
|
var { Duplex, Readable } = require("stream");
|
|
43281
43281
|
var { URL: URL2 } = require("url");
|
|
43282
43282
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -43944,7 +43944,7 @@ var require_websocket = __commonJS({
|
|
|
43944
43944
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
43945
43945
|
return;
|
|
43946
43946
|
}
|
|
43947
|
-
const digest =
|
|
43947
|
+
const digest = createHash47("sha1").update(key2 + GUID).digest("base64");
|
|
43948
43948
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
43949
43949
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
43950
43950
|
return;
|
|
@@ -44313,7 +44313,7 @@ var require_websocket_server = __commonJS({
|
|
|
44313
44313
|
var EventEmitter = require("events");
|
|
44314
44314
|
var http2 = require("http");
|
|
44315
44315
|
var { Duplex } = require("stream");
|
|
44316
|
-
var { createHash:
|
|
44316
|
+
var { createHash: createHash47 } = require("crypto");
|
|
44317
44317
|
var extension3 = require_extension();
|
|
44318
44318
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
44319
44319
|
var subprotocol2 = require_subprotocol();
|
|
@@ -44620,7 +44620,7 @@ var require_websocket_server = __commonJS({
|
|
|
44620
44620
|
);
|
|
44621
44621
|
}
|
|
44622
44622
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
44623
|
-
const digest =
|
|
44623
|
+
const digest = createHash47("sha1").update(key2 + GUID).digest("base64");
|
|
44624
44624
|
const headers = [
|
|
44625
44625
|
"HTTP/1.1 101 Switching Protocols",
|
|
44626
44626
|
"Upgrade: websocket",
|
|
@@ -220270,6 +220270,9 @@ var init_memory_control_plane_store = __esm({
|
|
|
220270
220270
|
/** protected:FileControlPlaneStore 子类 open() 回放快照时直接恢复(密码须持久化)。 */
|
|
220271
220271
|
accountSecrets = /* @__PURE__ */ new Map();
|
|
220272
220272
|
// accountId → { passwordHash?, tokenVersion }
|
|
220273
|
+
/** 已登出会话(ADR 0636;protected:文件版子类回放快照时直接恢复——不持久化的话重启即「复活」)。 */
|
|
220274
|
+
revokedSessions = /* @__PURE__ */ new Map();
|
|
220275
|
+
// tokenHash → record
|
|
220273
220276
|
verificationCodes = /* @__PURE__ */ new Map();
|
|
220274
220277
|
// email → record(短 TTL,文件版不持久化)
|
|
220275
220278
|
/** 组织模型三表(protected:文件版子类回放快照时直接恢复)。 */
|
|
@@ -220631,6 +220634,15 @@ var init_memory_control_plane_store = __esm({
|
|
|
220631
220634
|
this.accountSecrets.set(accountId, { ...cur, tokenVersion: next });
|
|
220632
220635
|
return next;
|
|
220633
220636
|
}
|
|
220637
|
+
// —— 已登出会话(ADR 0636)——
|
|
220638
|
+
async revokeSession(rec2) {
|
|
220639
|
+
const cutoff = Date.parse(rec2.revokedAt);
|
|
220640
|
+
for (const [k2, r] of this.revokedSessions) if (Date.parse(r.expiresAt) < cutoff) this.revokedSessions.delete(k2);
|
|
220641
|
+
if (!this.revokedSessions.has(rec2.tokenHash)) this.revokedSessions.set(rec2.tokenHash, { ...rec2 });
|
|
220642
|
+
}
|
|
220643
|
+
async isSessionRevoked(tokenHash) {
|
|
220644
|
+
return this.revokedSessions.has(tokenHash);
|
|
220645
|
+
}
|
|
220634
220646
|
// —— 邮箱验证码(单邮箱一条 active)——
|
|
220635
220647
|
async putVerificationCode(rec2) {
|
|
220636
220648
|
this.verificationCodes.set(rec2.email, { ...rec2 });
|
|
@@ -225833,6 +225845,7 @@ var init_control_plane_file_store = __esm({
|
|
|
225833
225845
|
"upsertAccount",
|
|
225834
225846
|
"setAccountPassword",
|
|
225835
225847
|
"bumpAccountTokenVersion",
|
|
225848
|
+
"revokeSession",
|
|
225836
225849
|
"upsertDigitalEmployee",
|
|
225837
225850
|
"patchDigitalEmployee",
|
|
225838
225851
|
"putAgentCredential",
|
|
@@ -225872,6 +225885,7 @@ var init_control_plane_file_store = __esm({
|
|
|
225872
225885
|
for (const link of snap.inviteLinks ?? []) await MemoryControlPlaneStore.prototype.createInviteLink.call(store, link);
|
|
225873
225886
|
for (const a of snap.accounts ?? []) await MemoryControlPlaneStore.prototype.upsertAccount.call(store, a);
|
|
225874
225887
|
for (const e of snap.accountSecrets ?? []) store.accountSecrets.set(e.accountId, { ...e.secret });
|
|
225888
|
+
for (const r of snap.revokedSessions ?? []) store.revokedSessions.set(r.tokenHash, { ...r });
|
|
225875
225889
|
for (const e of snap.digitalEmployees ?? []) await MemoryControlPlaneStore.prototype.upsertDigitalEmployee.call(store, e);
|
|
225876
225890
|
for (const c of snap.agentCredentials ?? []) await MemoryControlPlaneStore.prototype.putAgentCredential.call(store, c);
|
|
225877
225891
|
for (const b2 of snap.principalBridges ?? []) await MemoryControlPlaneStore.prototype.putPrincipalBridge.call(store, b2);
|
|
@@ -225910,6 +225924,8 @@ var init_control_plane_file_store = __esm({
|
|
|
225910
225924
|
inviteLinks: [...this.inviteLinks.values()],
|
|
225911
225925
|
accounts,
|
|
225912
225926
|
accountSecrets,
|
|
225927
|
+
// 只有按哈希查的读面,直接读 protected map(同 offboardings)。
|
|
225928
|
+
revokedSessions: [...this.revokedSessions.values()],
|
|
225913
225929
|
digitalEmployees,
|
|
225914
225930
|
agentCredentials,
|
|
225915
225931
|
principalBridges,
|
|
@@ -230576,6 +230592,12 @@ function verifySession(token2, secret, nowMs) {
|
|
|
230576
230592
|
if (typeof claims.exp !== "number" || claims.exp <= nowMs) return null;
|
|
230577
230593
|
return claims;
|
|
230578
230594
|
}
|
|
230595
|
+
function sessionTokenHash(token2) {
|
|
230596
|
+
return (0, import_node_crypto54.createHash)("sha256").update(token2).digest("base64url");
|
|
230597
|
+
}
|
|
230598
|
+
function newSessionId() {
|
|
230599
|
+
return (0, import_node_crypto54.randomBytes)(16).toString("base64url");
|
|
230600
|
+
}
|
|
230579
230601
|
function generateCode() {
|
|
230580
230602
|
return String((0, import_node_crypto54.randomInt)(0, 1e6)).padStart(6, "0");
|
|
230581
230603
|
}
|
|
@@ -246652,7 +246674,7 @@ function createAuth(opts) {
|
|
|
246652
246674
|
const passwordFailures = /* @__PURE__ */ new Map();
|
|
246653
246675
|
const sessionCookie = (accountId, tokenVersion) => {
|
|
246654
246676
|
const t = now();
|
|
246655
|
-
const jwt = signSession({ sub: accountId, tokenVersion, iat: t, exp: t + sessionTtlMs }, jwtSecret);
|
|
246677
|
+
const jwt = signSession({ sub: accountId, tokenVersion, iat: t, exp: t + sessionTtlMs, jti: newSessionId() }, jwtSecret);
|
|
246656
246678
|
const attrs = [`${cookieName}=${jwt}`, "Path=/", "HttpOnly", "SameSite=Lax", `Max-Age=${Math.floor(sessionTtlMs / 1e3)}`];
|
|
246657
246679
|
if (opts.secureCookie) attrs.push("Secure");
|
|
246658
246680
|
return attrs.join("; ");
|
|
@@ -246710,11 +246732,13 @@ function createAuth(opts) {
|
|
|
246710
246732
|
await store.deleteVerificationCode(key2);
|
|
246711
246733
|
return "ok";
|
|
246712
246734
|
};
|
|
246735
|
+
const sessionToken = (headers) => parseCookies(typeof headers.cookie === "string" ? headers.cookie : void 0)[cookieName];
|
|
246713
246736
|
const currentAccount = async (headers) => {
|
|
246714
|
-
const raw =
|
|
246737
|
+
const raw = sessionToken(headers);
|
|
246715
246738
|
if (!raw) return null;
|
|
246716
246739
|
const claims = verifySession(raw, jwtSecret, now());
|
|
246717
246740
|
if (!claims) return null;
|
|
246741
|
+
if (await store.isSessionRevoked(sessionTokenHash(raw))) return null;
|
|
246718
246742
|
const sec = await store.getAccountSecret(claims.sub);
|
|
246719
246743
|
if (!sec || sec.tokenVersion !== claims.tokenVersion) return null;
|
|
246720
246744
|
const account = await store.getAccount(claims.sub);
|
|
@@ -246891,6 +246915,21 @@ function createAuth(opts) {
|
|
|
246891
246915
|
return { status: 200, body: { ticket, expiresAt: new Date(exp).toISOString() } };
|
|
246892
246916
|
}
|
|
246893
246917
|
if (route2 === "logout") {
|
|
246918
|
+
const raw = sessionToken(headers);
|
|
246919
|
+
const claims = raw ? verifySession(raw, jwtSecret, now()) : null;
|
|
246920
|
+
if (raw && claims) {
|
|
246921
|
+
try {
|
|
246922
|
+
await store.revokeSession({
|
|
246923
|
+
tokenHash: sessionTokenHash(raw),
|
|
246924
|
+
accountId: claims.sub,
|
|
246925
|
+
revokedAt: new Date(now()).toISOString(),
|
|
246926
|
+
expiresAt: new Date(claims.exp).toISOString()
|
|
246927
|
+
});
|
|
246928
|
+
} catch (e) {
|
|
246929
|
+
console.error(`[auth] \u767B\u51FA\u540A\u9500\u5931\u8D25 ${claims.sub}: ${e instanceof Error ? e.message : String(e)}`);
|
|
246930
|
+
return { status: 500, body: { error: { code: "LOGOUT_REVOKE_FAILED", message: "\u767B\u51FA\u672A\u5B8C\u6210\uFF0C\u8BF7\u91CD\u8BD5" } }, setCookie: clearCookie() };
|
|
246931
|
+
}
|
|
246932
|
+
}
|
|
246894
246933
|
return { status: 200, body: { ok: true }, setCookie: clearCookie() };
|
|
246895
246934
|
}
|
|
246896
246935
|
return { status: 404, body: { error: { code: "NOT_FOUND", message: pathname } } };
|
|
@@ -264917,6 +264956,14 @@ var init_postgres_control_plane = __esm({
|
|
|
264917
264956
|
expires_at timestamptz NOT NULL,
|
|
264918
264957
|
attempts int NOT NULL DEFAULT 0
|
|
264919
264958
|
)`);
|
|
264959
|
+
await pool.query(`
|
|
264960
|
+
CREATE TABLE IF NOT EXISTS "${s2}".revoked_sessions (
|
|
264961
|
+
token_hash text PRIMARY KEY, -- SHA-256(base64url) of the oasis_auth JWT
|
|
264962
|
+
account_id text NOT NULL,
|
|
264963
|
+
revoked_at timestamptz NOT NULL,
|
|
264964
|
+
expires_at timestamptz NOT NULL -- = \u4EE4\u724C exp\uFF1B\u8FC7\u4E86\u4EE4\u724C\u672C\u6765\u5C31\u9A8C\u4E0D\u8FC7\uFF0C\u884C\u53EF\u5220
|
|
264965
|
+
)`);
|
|
264966
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS revoked_sessions_expires_idx ON "${s2}".revoked_sessions (expires_at)`);
|
|
264920
264967
|
await pool.query(`ALTER TABLE "${s2}".company_members ADD COLUMN IF NOT EXISTS display_name text`);
|
|
264921
264968
|
await pool.query(`ALTER TABLE "${s2}".company_members ADD COLUMN IF NOT EXISTS created_at timestamptz`);
|
|
264922
264969
|
await pool.query(`ALTER TABLE "${s2}".company_members ADD COLUMN IF NOT EXISTS updated_at timestamptz`);
|
|
@@ -265807,6 +265854,19 @@ var init_postgres_control_plane = __esm({
|
|
|
265807
265854
|
if (r.rowCount === 0) throw new Error(`account not found: ${accountId}`);
|
|
265808
265855
|
return Number(r.rows[0].token_version);
|
|
265809
265856
|
}
|
|
265857
|
+
// —— 已登出会话(ADR 0636)——
|
|
265858
|
+
async revokeSession(rec2) {
|
|
265859
|
+
await this.pool.query(`DELETE FROM ${this.s}.revoked_sessions WHERE expires_at < $1`, [rec2.revokedAt]);
|
|
265860
|
+
await this.pool.query(
|
|
265861
|
+
`INSERT INTO ${this.s}.revoked_sessions (token_hash, account_id, revoked_at, expires_at) VALUES ($1,$2,$3,$4)
|
|
265862
|
+
ON CONFLICT (token_hash) DO NOTHING`,
|
|
265863
|
+
[rec2.tokenHash, rec2.accountId, rec2.revokedAt, rec2.expiresAt]
|
|
265864
|
+
);
|
|
265865
|
+
}
|
|
265866
|
+
async isSessionRevoked(tokenHash) {
|
|
265867
|
+
const r = await this.pool.query(`SELECT 1 FROM ${this.s}.revoked_sessions WHERE token_hash = $1`, [tokenHash]);
|
|
265868
|
+
return (r.rowCount ?? 0) > 0;
|
|
265869
|
+
}
|
|
265810
265870
|
// —— 邮箱验证码(单邮箱一条 active)——
|
|
265811
265871
|
async putVerificationCode(rec2) {
|
|
265812
265872
|
await this.pool.query(
|
|
@@ -298359,12 +298419,13 @@ var COMMAND_DECLS = {
|
|
|
298359
298419
|
// 填(agent 调 = 它绑定的那个真人),命令行不收。开关 OASIS_PERSONAL_TODO=off 时服务端 404。 ——
|
|
298360
298420
|
todo: {
|
|
298361
298421
|
group: "\u4E2A\u4EBA\u5F85\u529E",
|
|
298362
|
-
usage: "oasis todo <add|list|edit|done|cancel|reopen> ...",
|
|
298422
|
+
usage: "oasis todo <add|list|show|edit|done|cancel|reopen> ...",
|
|
298363
298423
|
description: "\u4E2A\u4EBA\u5F85\u529E\uFF1A\u66FF\u4F60\u7ED1\u5B9A\u7684\u90A3\u4E2A\u771F\u4EBA\u8BB0\u4E0B\u6709\u622A\u6B62\u65E5\u7684\u4E8B\uFF0C\u5230\u671F\u524D\u4E00\u5929 09:00\u3001\u5F53\u5929 09:00 \u7CFB\u7EDF\u4F1A\u63D0\u9192 TA\uFF08\u8BBE\u4E86\u5F00\u59CB\u65E5\u7684\uFF0C\u5F00\u59CB\u5F53\u5929 09:00 \u4E5F\u63D0\u9192\u4E00\u6B21\uFF09\u3002\u6BCF\u6761\u8F93\u51FA\u7B2C\u4E00\u884C\u662F\u300C\u4ECA\u5929\uFF1AYYYY-MM-DD \u5468X\uFF08\u65F6\u533A\uFF09\u300D\u2014\u2014\u6362\u7B97\u300C\u8FD9\u5468\u4E94\u300D\u300C\u6708\u5E95\u300D\u4E00\u5F8B\u4EE5\u5B83\u4E3A\u51C6\u3002**\u6CA1\u6709 `oasis todo` \u547D\u4EE4\u6267\u884C\u6210\u529F\uFF0C\u5C31\u4E0D\u80FD\u8BF4\u8BB0\u4E0B\u4E86\u3002**",
|
|
298364
|
-
subCommands: ["todo add", "todo list", "todo edit", "todo done", "todo cancel", "todo reopen"],
|
|
298424
|
+
subCommands: ["todo add", "todo list", "todo show", "todo edit", "todo done", "todo cancel", "todo reopen"],
|
|
298365
298425
|
examples: [
|
|
298366
298426
|
'oasis todo add --title "\u4EA4 Q3 \u590D\u76D8\u62A5\u544A" --note "\u738B\u603B\u8981\uFF0C\u5468\u4F1A\u524D\u8FC7\u4E00\u904D" --due 2026-10-09',
|
|
298367
298427
|
"oasis todo list",
|
|
298428
|
+
"oasis todo show td_3f9a1c2b",
|
|
298368
298429
|
'oasis todo edit td_3f9a1c2b --due 2026-10-12 --reason "\u6392\u671F\u8C03\u6574"',
|
|
298369
298430
|
"oasis todo done td_3f9a1c2b"
|
|
298370
298431
|
]
|
|
@@ -298389,6 +298450,13 @@ var COMMAND_DECLS = {
|
|
|
298389
298450
|
description: "\u5217\u51FA\u5F85\u529E\uFF0C\u6309\u622A\u6B62\u65E5\u6392\u5E8F\uFF0C\u8FC7\u671F\u7684\u6807\u300C\u5DF2\u8FC7\u671F\u300D\uFF1B\u8BBE\u4E86\u5F00\u59CB\u65E5\u7684\u663E\u793A\u300CX \u6708 X \u65E5\u5F00\u59CB \u2192 X \u6708 X \u65E5\u622A\u6B62\u300D\u3002\u9ED8\u8BA4\u53EA\u5217\u672A\u5B8C\u6210\u7684\uFF1B--all \u8FDE\u5DF2\u5B8C\u6210\u3001\u5DF2\u53D6\u6D88\u7684\u4E00\u8D77\u5217\u3002",
|
|
298390
298451
|
flags: [{ name: "all", desc: "\u8FDE\u5DF2\u5B8C\u6210 / \u5DF2\u53D6\u6D88\u7684\u4E00\u8D77\u5217", boolean: true, own: true }]
|
|
298391
298452
|
},
|
|
298453
|
+
"todo show": {
|
|
298454
|
+
group: "\u4E2A\u4EBA\u5F85\u529E",
|
|
298455
|
+
usage: "oasis todo show <id>",
|
|
298456
|
+
description: "\u770B\u4E00\u6761\u5F85\u529E\u7684\u5168\u8C8C\uFF1A\u6807\u9898\u3001\u5F00\u59CB \u2192 \u622A\u6B62\u3001\u72B6\u6001\u3001\u5907\u6CE8\u5168\u6587\uFF0C\u4EE5\u53CA\u53D8\u66F4\u8BB0\u5F55\uFF08\u65F6\u95F4\u3001\u8C01\u6539\u7684 / \u7ECF\u624B agent\u3001\u5B57\u6BB5\u3001\u65E7\u503C \u2192 \u65B0\u503C\u3001\u539F\u56E0\uFF0C\u65B0\u7684\u5728\u524D\uFF09\u3002\u6539\u5907\u6CE8\u524D\u5148\u7528\u5B83\u8BFB\u51FA\u5F53\u524D\u5907\u6CE8\u5168\u6587\uFF1B\u7528\u6237\u95EE\u300C\u4E4B\u524D\u5199\u7684\u662F\u4EC0\u4E48\u300D\u4E5F\u67E5\u8FD9\u91CC\u3002",
|
|
298457
|
+
positional: [{ name: "<id>", required: true, desc: "\u5F85\u529E id\uFF08oasis todo list \u7B2C\u4E00\u5217\uFF09" }],
|
|
298458
|
+
examples: ["oasis todo show td_3f9a1c2b"]
|
|
298459
|
+
},
|
|
298392
298460
|
"todo edit": {
|
|
298393
298461
|
group: "\u4E2A\u4EBA\u5F85\u529E",
|
|
298394
298462
|
usage: "oasis todo edit <id> [--title \u2026] [--note \u2026] [--start YYYY-MM-DD|none] [--start-time HH:mm|none] [--due YYYY-MM-DD] [--time HH:mm|none] [--workorder <\u5DE5\u5355 id>|none] [--reason \u2026]",
|
|
@@ -299279,7 +299347,7 @@ async function waitForCommandAuthorization(base, headers, draftId, fallback) {
|
|
|
299279
299347
|
}
|
|
299280
299348
|
}
|
|
299281
299349
|
}
|
|
299282
|
-
var CLI_VERSION = "2.2.
|
|
299350
|
+
var CLI_VERSION = "2.2.107" ? "2.2.107" : "dev";
|
|
299283
299351
|
function apiHeaders(token2, company) {
|
|
299284
299352
|
const headers = {
|
|
299285
299353
|
authorization: `Bearer ${token2}`,
|
|
@@ -301711,6 +301779,52 @@ ${res.warning}`);
|
|
|
301711
301779
|
}
|
|
301712
301780
|
break;
|
|
301713
301781
|
}
|
|
301782
|
+
if (sub === "show") {
|
|
301783
|
+
const id = idOf();
|
|
301784
|
+
const [one2, day] = await Promise.all([
|
|
301785
|
+
call("GET", todoPath(id)),
|
|
301786
|
+
call("GET", "/api/todos")
|
|
301787
|
+
]);
|
|
301788
|
+
const t = one2.todo;
|
|
301789
|
+
const statusText = t.status === "done" ? "\u5DF2\u5B8C\u6210" : t.status === "cancelled" ? "\u5DF2\u53D6\u6D88" : t.dueDate < day.today.date ? "\u672A\u5B8C\u6210\uFF08\u5DF2\u8FC7\u671F\uFF09" : "\u672A\u5B8C\u6210";
|
|
301790
|
+
println(day.todayLine);
|
|
301791
|
+
println(`${t.id} ${t.title}`);
|
|
301792
|
+
println(`\u65F6\u95F4\uFF1A${due(t)}`);
|
|
301793
|
+
println(`\u72B6\u6001\uFF1A${statusText}`);
|
|
301794
|
+
if (t.linkedWorkorderId) println(`\u5DE5\u5355\uFF1A${t.linkedWorkorderId}`);
|
|
301795
|
+
println("\u5907\u6CE8\uFF1A");
|
|
301796
|
+
println(t.note ? t.note : "\uFF08\u65E0\uFF09");
|
|
301797
|
+
const FIELD = {
|
|
301798
|
+
created: "\u8BB0\u4E0B",
|
|
301799
|
+
status: "\u72B6\u6001",
|
|
301800
|
+
title: "\u6807\u9898",
|
|
301801
|
+
note: "\u5907\u6CE8",
|
|
301802
|
+
startDate: "\u5F00\u59CB\u65E5",
|
|
301803
|
+
startTime: "\u5F00\u59CB\u65F6\u523B",
|
|
301804
|
+
dueDate: "\u622A\u6B62\u65E5",
|
|
301805
|
+
dueTime: "\u622A\u6B62\u65F6\u523B",
|
|
301806
|
+
linkedWorkorderId: "\u5DE5\u5355"
|
|
301807
|
+
};
|
|
301808
|
+
const STATUS = { open: "\u672A\u5B8C\u6210", done: "\u5DF2\u5B8C\u6210", cancelled: "\u5DF2\u53D6\u6D88" };
|
|
301809
|
+
const val = (field, v2) => v2 === void 0 || v2 === "" ? "\uFF08\u7A7A\uFF09" : field === "status" ? STATUS[v2] ?? v2 : v2;
|
|
301810
|
+
const fmtAt = (iso9) => new Intl.DateTimeFormat("sv-SE", {
|
|
301811
|
+
timeZone: day.today.timeZone,
|
|
301812
|
+
year: "numeric",
|
|
301813
|
+
month: "2-digit",
|
|
301814
|
+
day: "2-digit",
|
|
301815
|
+
hour: "2-digit",
|
|
301816
|
+
minute: "2-digit",
|
|
301817
|
+
hour12: false
|
|
301818
|
+
}).format(new Date(iso9));
|
|
301819
|
+
const changes = [...one2.changes].sort((a, b2) => b2.at.localeCompare(a.at));
|
|
301820
|
+
println(`\u53D8\u66F4\u8BB0\u5F55\uFF08${changes.length} \u6761\uFF0C\u65B0\u7684\u5728\u524D\uFF09\uFF1A`);
|
|
301821
|
+
for (const c of changes) {
|
|
301822
|
+
const who = c.handActorId ? `${c.actorId}\uFF08\u7ECF\u624B ${c.handActorId}\uFF09` : c.actorId;
|
|
301823
|
+
const what = c.field === "created" ? `\u8BB0\u4E0B\uFF1A${c.newValue ?? ""}` : `${FIELD[c.field] ?? c.field}\uFF1A${val(c.field, c.oldValue)} \u2192 ${val(c.field, c.newValue)}`;
|
|
301824
|
+
println(`- ${fmtAt(c.at)} ${who} ${what}${c.reason ? ` \u539F\u56E0\uFF1A${c.reason}` : ""}`);
|
|
301825
|
+
}
|
|
301826
|
+
break;
|
|
301827
|
+
}
|
|
301714
301828
|
if (sub === "edit") {
|
|
301715
301829
|
const id = idOf();
|
|
301716
301830
|
const body2 = {};
|
|
@@ -301736,7 +301850,7 @@ ${res.warning}`);
|
|
|
301736
301850
|
println(`${sub === "done" ? "\u5DF2\u5B8C\u6210" : sub === "cancel" ? "\u5DF2\u53D6\u6D88" : "\u5DF2\u91CD\u65B0\u6253\u5F00"}\uFF1A${r.todo.title}\uFF0C${due(r.todo)}`);
|
|
301737
301851
|
break;
|
|
301738
301852
|
}
|
|
301739
|
-
throw new Error("\u7528\u6CD5: oasis todo <add|list|edit|done|cancel|reopen> \u2026\uFF08oasis todo --help \u770B\u8BE6\u60C5\uFF09");
|
|
301853
|
+
throw new Error("\u7528\u6CD5: oasis todo <add|list|show|edit|done|cancel|reopen> \u2026\uFF08oasis todo --help \u770B\u8BE6\u60C5\uFF09");
|
|
301740
301854
|
}
|
|
301741
301855
|
case "skill": {
|
|
301742
301856
|
const sub = positional[0];
|
|
@@ -303404,7 +303518,7 @@ function shimScript() {
|
|
|
303404
303518
|
}
|
|
303405
303519
|
|
|
303406
303520
|
// src/index.ts
|
|
303407
|
-
var PKG_VERSION = true ? "2.2.
|
|
303521
|
+
var PKG_VERSION = true ? "2.2.107" : "dev";
|
|
303408
303522
|
var LOCAL_BIN = localBin();
|
|
303409
303523
|
var NPM_PREFIX = npmPrefix();
|
|
303410
303524
|
var INSTANCE = DEFAULT_INSTANCE;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oasis_test_v2",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.107",
|
|
4
4
|
"description": "Oasis node daemon + CLI — background daemon, auto-start, full server CLI",
|
|
5
5
|
"bin": {
|
|
6
6
|
"oasis": "./dist/index.js"
|
|
@@ -26,6 +26,6 @@
|
|
|
26
26
|
"node": ">=20"
|
|
27
27
|
},
|
|
28
28
|
"oasisRelease": {
|
|
29
|
-
"sourceHead": "
|
|
29
|
+
"sourceHead": "180e4e814716f1a7eb4870a1f88cd4d10398d726"
|
|
30
30
|
}
|
|
31
31
|
}
|