oasis_test 0.1.84 → 0.1.85
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 +277 -69
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -138754,6 +138754,16 @@ function nodeLabel(a) {
|
|
|
138754
138754
|
const tail = a.id.split(":").slice(2).join(":");
|
|
138755
138755
|
return tail ? `\u672A\u547D\u540D ${a.type}\uFF08${tail}\uFF09` : `\u672A\u547D\u540D ${a.type}`;
|
|
138756
138756
|
}
|
|
138757
|
+
function workspaceTitleMap(model) {
|
|
138758
|
+
const titleOf = /* @__PURE__ */ new Map();
|
|
138759
|
+
for (const a of model.artifacts.values()) {
|
|
138760
|
+
if (a.type === "brief") {
|
|
138761
|
+
const title = a.title ?? a.description;
|
|
138762
|
+
if (title) titleOf.set(a.workspace, title);
|
|
138763
|
+
}
|
|
138764
|
+
}
|
|
138765
|
+
return titleOf;
|
|
138766
|
+
}
|
|
138757
138767
|
function isCurrentHeadConcluded2(model, a) {
|
|
138758
138768
|
return a.currentRev !== null && concludedHead(model, a.id) === a.currentRev;
|
|
138759
138769
|
}
|
|
@@ -141042,6 +141052,56 @@ var init_session_creds = __esm({
|
|
|
141042
141052
|
}
|
|
141043
141053
|
});
|
|
141044
141054
|
|
|
141055
|
+
// ../connectors/src/_base/refresh.ts
|
|
141056
|
+
function isExpiringSoon(expiresAtMs, nowMs, skewMs = CREDENTIAL_REFRESH_SKEW_MS) {
|
|
141057
|
+
if (!expiresAtMs) return true;
|
|
141058
|
+
return nowMs >= expiresAtMs - skewMs;
|
|
141059
|
+
}
|
|
141060
|
+
async function refreshCredentialsIfNeeded(connector, credentials, opts = {}) {
|
|
141061
|
+
if (!connector.refreshCredentials) {
|
|
141062
|
+
return { status: "unsupported", detail: `${connector.config.slug}: \u51ED\u636E\u4E0D\u8FC7\u671F\uFF0C\u65E0\u9700\u7EED\u671F` };
|
|
141063
|
+
}
|
|
141064
|
+
const nowMs = opts.nowMs ?? Date.now();
|
|
141065
|
+
const skewMs = opts.skewMs ?? CREDENTIAL_REFRESH_SKEW_MS;
|
|
141066
|
+
const expiresAt = readEpochMs(credentials, connector.expiresAtCredentialKey);
|
|
141067
|
+
if (!isExpiringSoon(expiresAt, nowMs, skewMs)) {
|
|
141068
|
+
return { status: "fresh" };
|
|
141069
|
+
}
|
|
141070
|
+
const materialExpiresAt = readEpochMs(credentials, connector.refreshMaterialExpiresAtCredentialKey);
|
|
141071
|
+
if (materialExpiresAt && nowMs >= materialExpiresAt) {
|
|
141072
|
+
return { status: "expired", detail: `${connector.config.slug}: \u7EED\u671F\u6750\u6599\u5DF2\u8FC7\u671F\uFF0C\u9700\u91CD\u65B0\u6388\u6743` };
|
|
141073
|
+
}
|
|
141074
|
+
try {
|
|
141075
|
+
const result = await connector.refreshCredentials(credentials);
|
|
141076
|
+
if (!result) return { status: "not-refreshable", detail: `${connector.config.slug}: \u65E0\u53EF\u7528\u7EED\u671F\u6750\u6599` };
|
|
141077
|
+
return {
|
|
141078
|
+
status: "refreshed",
|
|
141079
|
+
credentials: result.credentials,
|
|
141080
|
+
...result.expiresAt ? { expiresAt: result.expiresAt } : {}
|
|
141081
|
+
};
|
|
141082
|
+
} catch (err) {
|
|
141083
|
+
return { status: "failed", detail: summarize(err) };
|
|
141084
|
+
}
|
|
141085
|
+
}
|
|
141086
|
+
function readEpochMs(credentials, key) {
|
|
141087
|
+
if (!key) return void 0;
|
|
141088
|
+
const raw = credentials[key];
|
|
141089
|
+
if (!raw) return void 0;
|
|
141090
|
+
const n = Number(raw);
|
|
141091
|
+
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
141092
|
+
}
|
|
141093
|
+
function summarize(err) {
|
|
141094
|
+
const e = err;
|
|
141095
|
+
return (typeof e?.message === "string" ? e.message : String(err)).slice(0, 300);
|
|
141096
|
+
}
|
|
141097
|
+
var CREDENTIAL_REFRESH_SKEW_MS;
|
|
141098
|
+
var init_refresh = __esm({
|
|
141099
|
+
"../connectors/src/_base/refresh.ts"() {
|
|
141100
|
+
"use strict";
|
|
141101
|
+
CREDENTIAL_REFRESH_SKEW_MS = 5 * 60 * 1e3;
|
|
141102
|
+
}
|
|
141103
|
+
});
|
|
141104
|
+
|
|
141045
141105
|
// ../connectors/src/_base/cli-connector.ts
|
|
141046
141106
|
function summarizeError(err) {
|
|
141047
141107
|
const e = err;
|
|
@@ -141184,13 +141244,32 @@ var init_base = __esm({
|
|
|
141184
141244
|
init_tool_home();
|
|
141185
141245
|
init_wrapper_assets();
|
|
141186
141246
|
init_session_creds();
|
|
141247
|
+
init_refresh();
|
|
141187
141248
|
init_cli_connector();
|
|
141188
141249
|
init_mcp_connector();
|
|
141189
141250
|
}
|
|
141190
141251
|
});
|
|
141191
141252
|
|
|
141192
141253
|
// ../connectors/src/feishu/index.ts
|
|
141193
|
-
|
|
141254
|
+
function parseFeishuTokenResponse(data, nowMs) {
|
|
141255
|
+
const accessToken = String(data["access_token"] ?? "");
|
|
141256
|
+
const refreshToken = String(data["refresh_token"] ?? "");
|
|
141257
|
+
const expiresInSec = Number(data["expires_in"] ?? 7200);
|
|
141258
|
+
const refreshExpiresInSec = Number(
|
|
141259
|
+
data["refresh_token_expires_in"] ?? data["refresh_expires_in"] ?? 30 * 24 * 3600
|
|
141260
|
+
);
|
|
141261
|
+
const expiresAtMs = nowMs + expiresInSec * 1e3;
|
|
141262
|
+
return {
|
|
141263
|
+
credentials: {
|
|
141264
|
+
...accessToken ? { user_access_token: accessToken } : {},
|
|
141265
|
+
...refreshToken ? { refresh_token: refreshToken } : {},
|
|
141266
|
+
user_token_expires_at: String(expiresAtMs),
|
|
141267
|
+
refresh_token_expires_at: String(nowMs + refreshExpiresInSec * 1e3)
|
|
141268
|
+
},
|
|
141269
|
+
expiresAt: new Date(expiresAtMs)
|
|
141270
|
+
};
|
|
141271
|
+
}
|
|
141272
|
+
var import_node_child_process7, import_node_util4, import_node_path6, import_node_url2, import_promises3, execFileAsync2, __dirname2, FEISHU_WELL_KNOWN_SKILLS_BASE, FEISHU_TOKEN_URL, FeishuConnector;
|
|
141194
141273
|
var init_feishu = __esm({
|
|
141195
141274
|
"../connectors/src/feishu/index.ts"() {
|
|
141196
141275
|
"use strict";
|
|
@@ -141203,6 +141282,7 @@ var init_feishu = __esm({
|
|
|
141203
141282
|
execFileAsync2 = (0, import_node_util4.promisify)(import_node_child_process7.execFile);
|
|
141204
141283
|
__dirname2 = (0, import_node_path6.dirname)((0, import_node_url2.fileURLToPath)(__esm_import_meta_url));
|
|
141205
141284
|
FEISHU_WELL_KNOWN_SKILLS_BASE = "https://open.feishu.cn/.well-known/skills";
|
|
141285
|
+
FEISHU_TOKEN_URL = "https://open.feishu.cn/open-apis/authen/v2/oauth/token";
|
|
141206
141286
|
FeishuConnector = class extends CliConnector {
|
|
141207
141287
|
config = {
|
|
141208
141288
|
slug: "feishu",
|
|
@@ -141220,12 +141300,28 @@ var init_feishu = __esm({
|
|
|
141220
141300
|
commandName = "lark-cli";
|
|
141221
141301
|
requiredCommands = ["lark-cli"];
|
|
141222
141302
|
envPrefix = "FEISHU_";
|
|
141223
|
-
/** server 侧从 actor 变量表组装凭据的声明(见 provision.ts
|
|
141303
|
+
/** server 侧从 actor 变量表组装凭据的声明(见 provision.ts)。这些会随 job 下发到节点。 */
|
|
141224
141304
|
credentialSources = [
|
|
141225
141305
|
{ key: "app_id", from: "FEISHU_APP_ID", required: true },
|
|
141226
141306
|
{ key: "app_secret", from: "FEISHU_APP_SECRET", required: true },
|
|
141227
141307
|
{ key: "user_access_token", from: "FEISHU_USER_ACCESS_TOKEN", required: false }
|
|
141228
141308
|
];
|
|
141309
|
+
/**
|
|
141310
|
+
* 续期材料——**只在 server 侧读,不下发节点**。refresh_token 能换出新的 user token,
|
|
141311
|
+
* 属于"长期材料",没有任何理由让它出现在 agent 所在的机器上。
|
|
141312
|
+
*/
|
|
141313
|
+
refreshCredentialSources = [
|
|
141314
|
+
{ key: "app_id", from: "FEISHU_APP_ID", required: true },
|
|
141315
|
+
{ key: "app_secret", from: "FEISHU_APP_SECRET", required: true },
|
|
141316
|
+
{ key: "refresh_token", from: "FEISHU_REFRESH_TOKEN", required: true },
|
|
141317
|
+
{ key: "user_token_expires_at", from: "FEISHU_USER_TOKEN_EXPIRES_AT", required: false },
|
|
141318
|
+
{ key: "refresh_token_expires_at", from: "FEISHU_REFRESH_TOKEN_EXPIRES_AT", required: false },
|
|
141319
|
+
{ key: "user_access_token", from: "FEISHU_USER_ACCESS_TOKEN", required: false }
|
|
141320
|
+
];
|
|
141321
|
+
/** 过期判定只认这个键——必须与注入时消费的 token 同源(见接口注释里的历史坑)。 */
|
|
141322
|
+
expiresAtCredentialKey = "user_token_expires_at";
|
|
141323
|
+
/** refresh_token 自身 ~30d 过期,过了只能重新授权。 */
|
|
141324
|
+
refreshMaterialExpiresAtCredentialKey = "refresh_token_expires_at";
|
|
141229
141325
|
/**
|
|
141230
141326
|
* 绝不允许进入 agent 进程环境的原始变量。
|
|
141231
141327
|
* 含 APP_ID 与几个过期时间戳:它们本身不算密钥,但同属飞书凭据材料,一并挡在 agent 之外,
|
|
@@ -141316,6 +141412,36 @@ var init_feishu = __esm({
|
|
|
141316
141412
|
sessionEnv.set("FEISHU_RUN_TMPDIR", creds.dir);
|
|
141317
141413
|
sessionEnv.set("LARKSUITE_CLI_CONFIG_DIR", configDir);
|
|
141318
141414
|
}
|
|
141415
|
+
/**
|
|
141416
|
+
* 用 refresh_token 换一对新的 user token(飞书 v2 OAuth)。
|
|
141417
|
+
*
|
|
141418
|
+
* **纯换取,不落库**——持久化由调用方做(server 侧 `oauth.ts`)。这样平台知识
|
|
141419
|
+
* (端点、字段名、~2h/~30d 的寿命)全部收在连接器里,与 GitHub App 的续期共用
|
|
141420
|
+
* `_base/refresh.ts` 那套判定。
|
|
141421
|
+
*
|
|
141422
|
+
* 返回 null=没有可用的续期材料(未完成授权)。平台报错则抛,由上层收敛成 failed。
|
|
141423
|
+
*/
|
|
141424
|
+
async refreshCredentials(credentials) {
|
|
141425
|
+
const appId = credentials["app_id"];
|
|
141426
|
+
const appSecret = credentials["app_secret"];
|
|
141427
|
+
const refreshToken = credentials["refresh_token"];
|
|
141428
|
+
if (!appId || !appSecret || !refreshToken) return null;
|
|
141429
|
+
const resp = await fetch(FEISHU_TOKEN_URL, {
|
|
141430
|
+
method: "POST",
|
|
141431
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
141432
|
+
body: new URLSearchParams({
|
|
141433
|
+
grant_type: "refresh_token",
|
|
141434
|
+
refresh_token: refreshToken,
|
|
141435
|
+
client_id: appId,
|
|
141436
|
+
client_secret: appSecret
|
|
141437
|
+
}).toString()
|
|
141438
|
+
});
|
|
141439
|
+
const data = await resp.json();
|
|
141440
|
+
if (!resp.ok || data["error"]) {
|
|
141441
|
+
throw new Error(`feishu refresh failed: HTTP ${resp.status} ${String(data["error"] ?? "")}`.trim());
|
|
141442
|
+
}
|
|
141443
|
+
return parseFeishuTokenResponse(data, Date.now());
|
|
141444
|
+
}
|
|
141319
141445
|
async initNewApp() {
|
|
141320
141446
|
await new Promise((resolve9, reject) => {
|
|
141321
141447
|
const proc = (0, import_node_child_process7.spawn)(this.larkBin, ["config", "init", "--new"], { stdio: "inherit" });
|
|
@@ -141526,52 +141652,54 @@ var init_scopes = __esm({
|
|
|
141526
141652
|
|
|
141527
141653
|
// ../connectors/src/feishu/oauth.ts
|
|
141528
141654
|
async function persistFeishuUserTokens(store, actorId, data, nowMs) {
|
|
141529
|
-
const
|
|
141530
|
-
|
|
141531
|
-
|
|
141532
|
-
|
|
141533
|
-
const
|
|
141534
|
-
|
|
141535
|
-
|
|
141536
|
-
|
|
141537
|
-
|
|
141655
|
+
const { credentials } = parseFeishuTokenResponse(data, nowMs);
|
|
141656
|
+
await persistRefreshedCredentials(store, actorId, credentials);
|
|
141657
|
+
}
|
|
141658
|
+
async function persistRefreshedCredentials(store, actorId, credentials) {
|
|
141659
|
+
const connector = new FeishuConnector();
|
|
141660
|
+
const secretKeys = new Set(connector.config.schema.filter((f2) => f2.secret).map((f2) => f2.key));
|
|
141661
|
+
for (const src of connector.refreshCredentialSources ?? []) {
|
|
141662
|
+
const value2 = credentials[src.key];
|
|
141663
|
+
if (value2 === void 0) continue;
|
|
141664
|
+
await store.putVariable({
|
|
141665
|
+
key: src.from,
|
|
141666
|
+
value: value2,
|
|
141667
|
+
scope: "personal",
|
|
141668
|
+
actorId,
|
|
141669
|
+
connectorId: "feishu",
|
|
141670
|
+
encrypted: secretKeys.has(src.key)
|
|
141671
|
+
});
|
|
141672
|
+
}
|
|
141538
141673
|
}
|
|
141539
141674
|
async function refreshFeishuUserTokenIfNeeded(store, actorId) {
|
|
141540
|
-
const
|
|
141541
|
-
const
|
|
141542
|
-
|
|
141543
|
-
|
|
141544
|
-
|
|
141545
|
-
|
|
141546
|
-
|
|
141547
|
-
|
|
141548
|
-
|
|
141549
|
-
|
|
141550
|
-
|
|
141551
|
-
|
|
141552
|
-
|
|
141675
|
+
const connector = new FeishuConnector();
|
|
141676
|
+
const credentials = {};
|
|
141677
|
+
for (const src of connector.refreshCredentialSources ?? []) {
|
|
141678
|
+
const v2 = src.key === "app_id" || src.key === "app_secret" ? await store.revealResolvedVariable(src.from, actorId) : await store.revealVariable(src.from, actorId);
|
|
141679
|
+
if (v2) credentials[src.key] = v2;
|
|
141680
|
+
}
|
|
141681
|
+
const outcome = await refreshCredentialsIfNeeded(connector, credentials);
|
|
141682
|
+
if (outcome.status === "refreshed" && outcome.credentials) {
|
|
141683
|
+
await persistRefreshedCredentials(store, actorId, outcome.credentials);
|
|
141684
|
+
return;
|
|
141685
|
+
}
|
|
141686
|
+
if (outcome.status === "expired") {
|
|
141687
|
+
for (const key of [
|
|
141688
|
+
"FEISHU_USER_ACCESS_TOKEN",
|
|
141689
|
+
"FEISHU_REFRESH_TOKEN",
|
|
141690
|
+
"FEISHU_USER_TOKEN_EXPIRES_AT",
|
|
141691
|
+
"FEISHU_REFRESH_TOKEN_EXPIRES_AT"
|
|
141692
|
+
]) {
|
|
141693
|
+
await store.deleteVariable(key, actorId);
|
|
141694
|
+
}
|
|
141553
141695
|
return;
|
|
141554
141696
|
}
|
|
141555
|
-
const resp = await fetch(FEISHU_TOKEN_URL, {
|
|
141556
|
-
method: "POST",
|
|
141557
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
141558
|
-
body: new URLSearchParams({
|
|
141559
|
-
grant_type: "refresh_token",
|
|
141560
|
-
refresh_token: refreshToken,
|
|
141561
|
-
client_id: appId,
|
|
141562
|
-
client_secret: appSecret
|
|
141563
|
-
}).toString()
|
|
141564
|
-
});
|
|
141565
|
-
const data = await resp.json();
|
|
141566
|
-
if (!resp.ok || data["error"]) return;
|
|
141567
|
-
await persistFeishuUserTokens(store, actorId, data, nowMs);
|
|
141568
141697
|
}
|
|
141569
|
-
var FEISHU_TOKEN_URL, REFRESH_SKEW_MS;
|
|
141570
141698
|
var init_oauth = __esm({
|
|
141571
141699
|
"../connectors/src/feishu/oauth.ts"() {
|
|
141572
141700
|
"use strict";
|
|
141573
|
-
|
|
141574
|
-
|
|
141701
|
+
init_refresh();
|
|
141702
|
+
init_feishu();
|
|
141575
141703
|
}
|
|
141576
141704
|
});
|
|
141577
141705
|
|
|
@@ -146518,6 +146646,7 @@ var init_src5 = __esm({
|
|
|
146518
146646
|
init_base();
|
|
146519
146647
|
init_base();
|
|
146520
146648
|
init_base();
|
|
146649
|
+
init_base();
|
|
146521
146650
|
init_feishu();
|
|
146522
146651
|
init_scopes();
|
|
146523
146652
|
init_oauth();
|
|
@@ -151023,6 +151152,7 @@ var init_memory_control_plane_store = __esm({
|
|
|
151023
151152
|
else c.avatar = patch.avatar;
|
|
151024
151153
|
}
|
|
151025
151154
|
if (patch.status !== void 0) c.status = patch.status;
|
|
151155
|
+
if (patch.onboardingVariant !== void 0) c.onboardingVariant = patch.onboardingVariant;
|
|
151026
151156
|
this.companies.set(id, c);
|
|
151027
151157
|
}
|
|
151028
151158
|
// —— 成员 ——
|
|
@@ -157804,7 +157934,7 @@ function clip(text2) {
|
|
|
157804
157934
|
const s2 = typeof text2 === "string" ? text2.trim() : "";
|
|
157805
157935
|
return s2.length > CLIP ? `${s2.slice(0, CLIP)}\u2026` : s2;
|
|
157806
157936
|
}
|
|
157807
|
-
function
|
|
157937
|
+
function summarize2(kind, payload) {
|
|
157808
157938
|
const p2 = payload;
|
|
157809
157939
|
switch (kind) {
|
|
157810
157940
|
case "report_gap":
|
|
@@ -157853,7 +157983,7 @@ async function actorActivity(oplog, actorId, limit = 50) {
|
|
|
157853
157983
|
for await (const { op } of oplog.readAll()) {
|
|
157854
157984
|
if (op.actor !== actorId) continue;
|
|
157855
157985
|
total++;
|
|
157856
|
-
matched.push({ at: op.timestamp, kind: op.kind, target: op.target, ...
|
|
157986
|
+
matched.push({ at: op.timestamp, kind: op.kind, target: op.target, ...summarize2(op.kind, op.payload) });
|
|
157857
157987
|
if (matched.length > capped) matched.shift();
|
|
157858
157988
|
}
|
|
157859
157989
|
matched.reverse();
|
|
@@ -159068,7 +159198,11 @@ function toApiError(e) {
|
|
|
159068
159198
|
const code = e.code;
|
|
159069
159199
|
const message = e instanceof Error ? e.message : String(e);
|
|
159070
159200
|
if (code === "FORBIDDEN") throw new ApiError(403, code, message);
|
|
159071
|
-
if (code === "ASSISTANT_LAZY_CREATE_FAILED")
|
|
159201
|
+
if (code === "ASSISTANT_LAZY_CREATE_FAILED") {
|
|
159202
|
+
const step = e.step;
|
|
159203
|
+
if (step === "no-runtime" || step === "probe-failed") throw new ApiError(503, "ASSISTANT_SERVICE_UNAVAILABLE", message);
|
|
159204
|
+
throw new ApiError(409, code, message);
|
|
159205
|
+
}
|
|
159072
159206
|
if (code === "AUTO_ASSIGN_OFF") throw new ApiError(409, code, message);
|
|
159073
159207
|
if (code === "ASSISTANT_ARCHIVED_CANNOT_REACTIVATE") throw new ApiError(409, code, message);
|
|
159074
159208
|
if (code === "LEGACY_AGENT_NOT_ELIGIBLE_FOR_REBIND") throw new ApiError(409, code, message);
|
|
@@ -160136,6 +160270,31 @@ var init_service4 = __esm({
|
|
|
160136
160270
|
async get(id) {
|
|
160137
160271
|
return this.store.getCompany(id);
|
|
160138
160272
|
}
|
|
160273
|
+
/**
|
|
160274
|
+
* 读取公司的登录后助理引导变体(首个 per-company 配置字段)。
|
|
160275
|
+
* 缺省/未设一律视为 "A"(默认);**读取失败绝不抛给调用方**——降级到 "A",
|
|
160276
|
+
* 保证登录后引导流程永远有一个确定的默认路径,不因控制面读故障而阻塞。
|
|
160277
|
+
*/
|
|
160278
|
+
async getOnboardingVariant(companyId) {
|
|
160279
|
+
try {
|
|
160280
|
+
const c = await this.store.getCompany(companyId);
|
|
160281
|
+
return c?.onboardingVariant ?? "A";
|
|
160282
|
+
} catch {
|
|
160283
|
+
return "A";
|
|
160284
|
+
}
|
|
160285
|
+
}
|
|
160286
|
+
/**
|
|
160287
|
+
* 设置公司的登录后助理引导变体("A" | "B")。公司不存在则抛 404,非法值抛 400。
|
|
160288
|
+
* 权限(owner/admin)由路由层强制。
|
|
160289
|
+
*/
|
|
160290
|
+
async setOnboardingVariant(companyId, variant) {
|
|
160291
|
+
if (variant !== "A" && variant !== "B") {
|
|
160292
|
+
throw new CompanyError(400, "BAD_REQUEST", `onboardingVariant \u987B\u4E3A "A" | "B"`);
|
|
160293
|
+
}
|
|
160294
|
+
const company = await this.requireCompany(companyId);
|
|
160295
|
+
await this.store.updateCompany(companyId, { onboardingVariant: variant });
|
|
160296
|
+
return { ...company, onboardingVariant: variant };
|
|
160297
|
+
}
|
|
160139
160298
|
/** 设置/清除公司头像引用("blob:<哈希>";null = 回到默认首字母标识)。 */
|
|
160140
160299
|
async setAvatar(id, ref2) {
|
|
160141
160300
|
const company = await this.requireCompany(id);
|
|
@@ -160472,6 +160631,13 @@ function companiesDomain(opts) {
|
|
|
160472
160631
|
throw e;
|
|
160473
160632
|
};
|
|
160474
160633
|
const whoami = (req) => currentUser(req.auth, req.raw.headers);
|
|
160634
|
+
const requireOwnerOrAdmin = async (req, companyId) => {
|
|
160635
|
+
const me = await whoami(req);
|
|
160636
|
+
const member = await service.getMember(companyId, me.accountId);
|
|
160637
|
+
if (!member || member.role !== "owner" && member.role !== "admin") {
|
|
160638
|
+
throw new ApiError(403, "FORBIDDEN", "\u9700\u8981\u8BE5\u516C\u53F8\u7684 owner/admin \u6743\u9650");
|
|
160639
|
+
}
|
|
160640
|
+
};
|
|
160475
160641
|
return (router) => {
|
|
160476
160642
|
router.get("/api/companies", async (req) => {
|
|
160477
160643
|
const me = await whoami(req);
|
|
@@ -160483,6 +160649,19 @@ function companiesDomain(opts) {
|
|
|
160483
160649
|
if (!company) throw new ApiError(404, "NOT_FOUND", `\u6CA1\u6709\u8FD9\u4E2A\u516C\u53F8\uFF1A${req.params.id}`);
|
|
160484
160650
|
return { status: 200, body: company };
|
|
160485
160651
|
});
|
|
160652
|
+
router.patch("/api/companies/:id", async (req) => {
|
|
160653
|
+
const cid = req.params.id;
|
|
160654
|
+
const b2 = req.body ?? {};
|
|
160655
|
+
if (b2.onboardingVariant === void 0) {
|
|
160656
|
+
throw new ApiError(400, "BAD_REQUEST", "\u7F3A\u5C11\u53EF\u66F4\u65B0\u5B57\u6BB5\uFF08onboardingVariant\uFF09");
|
|
160657
|
+
}
|
|
160658
|
+
if (b2.onboardingVariant !== "A" && b2.onboardingVariant !== "B") {
|
|
160659
|
+
throw new ApiError(400, "BAD_REQUEST", `onboardingVariant \u987B\u4E3A "A" | "B"`);
|
|
160660
|
+
}
|
|
160661
|
+
await requireOwnerOrAdmin(req, cid);
|
|
160662
|
+
const company = await service.setOnboardingVariant(cid, b2.onboardingVariant).catch(mapErr);
|
|
160663
|
+
return { status: 200, body: company };
|
|
160664
|
+
});
|
|
160486
160665
|
router.post("/api/companies", async (req) => {
|
|
160487
160666
|
const b2 = req.body ?? {};
|
|
160488
160667
|
const me = await whoami(req);
|
|
@@ -162047,14 +162226,10 @@ function buildInbox(model, me, leadOf, resolveActor, markers = [], slaMs, nowIso
|
|
|
162047
162226
|
const downstreamCount = (id) => consumersOf(model, id).length;
|
|
162048
162227
|
const firstSentence = (s2, max = 80) => (s2 ?? "").replace(/\s+/g, " ").trim().slice(0, max);
|
|
162049
162228
|
const creatorOf = /* @__PURE__ */ new Map();
|
|
162050
|
-
const titleOf = /* @__PURE__ */ new Map();
|
|
162051
162229
|
for (const a of model.artifacts.values()) {
|
|
162052
|
-
if (a.type === "brief")
|
|
162053
|
-
creatorOf.set(a.workspace, a.owner);
|
|
162054
|
-
const title = a.title ?? a.description;
|
|
162055
|
-
if (title) titleOf.set(a.workspace, title);
|
|
162056
|
-
}
|
|
162230
|
+
if (a.type === "brief") creatorOf.set(a.workspace, a.owner);
|
|
162057
162231
|
}
|
|
162232
|
+
const titleOf = workspaceTitleMap(model);
|
|
162058
162233
|
const staffingSeen = /* @__PURE__ */ new Set();
|
|
162059
162234
|
for (const a of model.artifacts.values()) {
|
|
162060
162235
|
if (!isPendingOwner(a.owner) || creatorOf.get(a.workspace) !== me) continue;
|
|
@@ -162445,8 +162620,20 @@ function toAuditEntry(op) {
|
|
|
162445
162620
|
summary: `${KIND_LABEL[op.kind] ?? op.kind} \xB7 ${op.artifactId}`
|
|
162446
162621
|
};
|
|
162447
162622
|
}
|
|
162448
|
-
|
|
162623
|
+
function enrichAudit(entry, model, titleOf) {
|
|
162624
|
+
const a = model.artifacts.get(entry.artifactId);
|
|
162625
|
+
if (!a) return { ...entry, visibility: "deleted" };
|
|
162626
|
+
const workspaceTitle = titleOf.get(a.workspace);
|
|
162627
|
+
return {
|
|
162628
|
+
...entry,
|
|
162629
|
+
nodeName: nodeLabel(a),
|
|
162630
|
+
...workspaceTitle ? { workspaceTitle } : {},
|
|
162631
|
+
visibility: "ok"
|
|
162632
|
+
};
|
|
162633
|
+
}
|
|
162634
|
+
async function buildAudit(oplog, q = {}, model) {
|
|
162449
162635
|
const limit = Math.min(Math.max(q.limit ?? 100, 1), 500);
|
|
162636
|
+
const titleOf = model ? workspaceTitleMap(model) : void 0;
|
|
162450
162637
|
const items = [];
|
|
162451
162638
|
let lastCursor = null;
|
|
162452
162639
|
let truncated = false;
|
|
@@ -162456,7 +162643,8 @@ async function buildAudit(oplog, q = {}) {
|
|
|
162456
162643
|
if (q.kind && op.kind !== q.kind) continue;
|
|
162457
162644
|
if (q.from && op.timestamp < q.from) continue;
|
|
162458
162645
|
if (q.to && op.timestamp > q.to) continue;
|
|
162459
|
-
|
|
162646
|
+
const base = toAuditEntry(op);
|
|
162647
|
+
items.push(model && titleOf ? enrichAudit(base, model, titleOf) : base);
|
|
162460
162648
|
lastCursor = cursor;
|
|
162461
162649
|
if (items.length >= limit) {
|
|
162462
162650
|
truncated = true;
|
|
@@ -162469,6 +162657,7 @@ var KIND_LABEL;
|
|
|
162469
162657
|
var init_audit = __esm({
|
|
162470
162658
|
"../server/src/domains/collab/audit.ts"() {
|
|
162471
162659
|
"use strict";
|
|
162660
|
+
init_node_state();
|
|
162472
162661
|
KIND_LABEL = {
|
|
162473
162662
|
spawn_artifact: "\u5EFA\u4EA7\u7269",
|
|
162474
162663
|
propose_revision: "\u63D0\u4FEE\u8BA2",
|
|
@@ -163457,7 +163646,7 @@ function collabDomain(opts) {
|
|
|
163457
163646
|
return { status: 200, body: { ok: true } };
|
|
163458
163647
|
});
|
|
163459
163648
|
router.get("/api/audit", async (req) => {
|
|
163460
|
-
const { oplog } = await resolveCtx(req.auth.companyId);
|
|
163649
|
+
const { oplog, kernel } = await resolveCtx(req.auth.companyId);
|
|
163461
163650
|
const q = req.query;
|
|
163462
163651
|
const audit = {};
|
|
163463
163652
|
const actor = q.get("actor");
|
|
@@ -163472,7 +163661,7 @@ function collabDomain(opts) {
|
|
|
163472
163661
|
if (cursor) audit.cursor = cursor;
|
|
163473
163662
|
const limit = q.get("limit");
|
|
163474
163663
|
if (limit) audit.limit = Number(limit);
|
|
163475
|
-
return { status: 200, body: await buildAudit(oplog, audit) };
|
|
163664
|
+
return { status: 200, body: await buildAudit(oplog, audit, kernel.model) };
|
|
163476
163665
|
});
|
|
163477
163666
|
router.get("/api/dashboard", async (req) => {
|
|
163478
163667
|
const { kernel, oplog, registry: registry2 } = await resolveCtx(req.auth.companyId);
|
|
@@ -165643,7 +165832,7 @@ function validateTriggers(raw) {
|
|
|
165643
165832
|
}
|
|
165644
165833
|
function automationsDomain(opts) {
|
|
165645
165834
|
const { service } = opts;
|
|
165646
|
-
const
|
|
165835
|
+
const summarize3 = async (id) => {
|
|
165647
165836
|
const automation = await service.getAutomation(id);
|
|
165648
165837
|
if (!automation) return null;
|
|
165649
165838
|
const [triggers, recent] = await Promise.all([
|
|
@@ -165668,7 +165857,7 @@ function automationsDomain(opts) {
|
|
|
165668
165857
|
return { status: 200, body };
|
|
165669
165858
|
});
|
|
165670
165859
|
router.get("/api/automations/:id", async (req) => {
|
|
165671
|
-
const summary = await
|
|
165860
|
+
const summary = await summarize3(req.params.id);
|
|
165672
165861
|
if (!summary) throw new ApiError(404, "NOT_FOUND", `\u6CA1\u6709\u8FD9\u4E2A\u81EA\u52A8\u5316\uFF1A${req.params.id}`);
|
|
165673
165862
|
return { status: 200, body: summary };
|
|
165674
165863
|
});
|
|
@@ -165698,7 +165887,7 @@ function automationsDomain(opts) {
|
|
|
165698
165887
|
...b2.createdBy !== void 0 ? { createdBy: b2.createdBy } : {},
|
|
165699
165888
|
...triggers !== void 0 ? { triggers } : {}
|
|
165700
165889
|
});
|
|
165701
|
-
const summary = await
|
|
165890
|
+
const summary = await summarize3(created.id);
|
|
165702
165891
|
return { status: 201, body: summary };
|
|
165703
165892
|
});
|
|
165704
165893
|
router.patch("/api/automations/:id", async (req) => {
|
|
@@ -165717,7 +165906,7 @@ function automationsDomain(opts) {
|
|
|
165717
165906
|
...b2.enabled !== void 0 ? { enabled: b2.enabled } : {},
|
|
165718
165907
|
...triggers !== void 0 ? { triggers } : {}
|
|
165719
165908
|
});
|
|
165720
|
-
const summary = await
|
|
165909
|
+
const summary = await summarize3(id);
|
|
165721
165910
|
return { status: 200, body: summary };
|
|
165722
165911
|
});
|
|
165723
165912
|
router.post("/api/automations/:id/enabled", async (req) => {
|
|
@@ -165726,7 +165915,7 @@ function automationsDomain(opts) {
|
|
|
165726
165915
|
const b2 = req.body ?? {};
|
|
165727
165916
|
if (typeof b2.enabled !== "boolean") throw new ApiError(400, "BAD_REQUEST", "\u7F3A\u5C11 enabled\uFF08boolean\uFF09");
|
|
165728
165917
|
await service.setEnabled(id, b2.enabled);
|
|
165729
|
-
const summary = await
|
|
165918
|
+
const summary = await summarize3(id);
|
|
165730
165919
|
return { status: 200, body: summary };
|
|
165731
165920
|
});
|
|
165732
165921
|
router.post("/api/automations/:id/run-now", async (req) => {
|
|
@@ -174895,7 +175084,9 @@ var init_registry3 = __esm({
|
|
|
174895
175084
|
dependsOn: ["diagnosis:\u6839\u56E0\u5206\u6790"],
|
|
174896
175085
|
role: "\u5F00\u53D1",
|
|
174897
175086
|
ownerRole: "dev",
|
|
174898
|
-
brief: () =>
|
|
175087
|
+
brief: () => `**\u4EA7\u51FA**\uFF1A\u6309\u300C\u6839\u56E0\u5206\u6790\u300D\u7ED9\u51FA\u7684\u65B9\u6848\u4FEE\u590D\u5E76\u4EA4\u4ED8\u4EE3\u7801\u3002
|
|
175088
|
+
**\u8D1F\u8D23\u5230\u54EA**\uFF1A\u53EA\u6539\u6839\u56E0\u6D89\u53CA\u7684\u90E8\u5206\uFF0C\u907F\u514D\u8FC7\u5EA6\u6269\u6563\uFF1B\u4E0A\u7EBF\u4E0E\u9A8C\u8BC1\u5F52\u4E0B\u6E38\u3002
|
|
175089
|
+
**\u4EA4\u4ED8\u524D\u5FC5\u987B\u80FD\u56DE\u7B54**\uFF1A\u2460 \u5DE5\u5355\u63CF\u8FF0\u91CC\u6240\u62A5\u7684\u90A3\u6761\u8DEF\u5F84\uFF0C\u81EA\u6D4B\u8DD1\u901A\u4E86\u5417\u3001\u600E\u4E48\u8DD1\u7684\uFF1F\u2461 \u672C\u6B21\u65B0\u5F15\u5165\u6216\u6539\u5199\u7684\u5224\u65AD\uFF0C\u5728\u5B83\u7684\u6BCF\u4E00\u79CD\u72B6\u6001\u4E0B\u7ED3\u8BBA\u5206\u522B\u662F\u4EC0\u4E48\uFF1F\u2462 \u8BCA\u65AD\u91CC\u7684\u65B9\u6848\u6709\u6CA1\u6709\u54EA\u6761\u4F60\u6CA1\u7167\u505A\u3001\u4E3A\u4EC0\u4E48\uFF1F`
|
|
174899
175090
|
},
|
|
174900
175091
|
{
|
|
174901
175092
|
// 修复与冒烟之间必须隔一道上线核验:dev 收尾的**同一刻**下游就解除阻塞,而那时合并才刚发生、
|
|
@@ -174906,7 +175097,9 @@ var init_registry3 = __esm({
|
|
|
174906
175097
|
dependsOn: ["dev:\u4FEE\u590D\u5B9E\u73B0"],
|
|
174907
175098
|
role: "\u8FD0\u7EF4\u90E8\u7F72",
|
|
174908
175099
|
ownerRole: "devops",
|
|
174909
|
-
brief: () =>
|
|
175100
|
+
brief: () => `**\u4EA7\u51FA**\uFF1A\u4E00\u4EFD\u90E8\u7F72\u8BB0\u5F55\uFF0C\u786E\u8BA4\u300C\u4FEE\u590D\u5B9E\u73B0\u300D\u4EA4\u4ED8\u7684\u90A3\u4E2A commit **\u771F\u7684\u8DD1\u5230\u4E86\u76EE\u6807\u73AF\u5883\u4E0A**\uFF0C\u7136\u540E\u653E\u884C\u4E0B\u6E38\u5192\u70DF\u3002
|
|
175101
|
+
**\u8D1F\u8D23\u5230\u54EA**\uFF1A\u53EA\u786E\u8BA4\u300C\u4E0A\u6CA1\u4E0A\u53BB\u300D\uFF0C\u4E0D\u5224\u65AD\u529F\u80FD\u5BF9\u9519\u2014\u2014\u90A3\u662F\u5192\u70DF\u7684\u4E8B\u3002
|
|
175102
|
+
**\u4EA4\u4ED8\u524D\u5FC5\u987B\u80FD\u56DE\u7B54**\uFF1A\u2460 \u4E0A\u7EBF\u7684\u662F\u54EA\u4E2A commit\uFF1F\u2461 \u4E0B\u6E38\u8981\u9A8C\u7684\u662F\u54EA\u4E2A\u73AF\u5883\u5730\u5740\uFF08\u5192\u70DF\u5168\u9760\u8FD9\u6761\u77E5\u9053\u53BB\u54EA\u6D4B\uFF09\uFF1F\u2462 \u63A2\u9488\u5B9E\u9645\u8FD4\u56DE\u4E86\u4EC0\u4E48\uFF1F
|
|
174910
175103
|
|
|
174911
175104
|
**\u5224\u636E\u4E24\u6761\uFF0C\u7F3A\u4E00\u4E0D\u53EF**\uFF1A
|
|
174912
175105
|
\u2460 \u90E8\u7F72\u6D41\u6C34\u7EBF\u5728\u8BE5 commit \u4E0A\u7684\u8FD0\u884C\u7ED3\u8BBA\u4E3A success\uFF1B
|
|
@@ -174916,8 +175109,6 @@ var init_registry3 = __esm({
|
|
|
174916
175109
|
|
|
174917
175110
|
**\u4F60\u63A5\u5230\u8FD9\u4E2A\u4EFB\u52A1\u65F6\uFF0C\u90E8\u7F72\u516B\u6210\u8FD8\u6CA1\u5B8C\u6210**\uFF08\u5408\u5E76\u5230\u4E0A\u7EBF\u8981\u51E0\u5206\u949F\uFF09\u3002\u505A\u6CD5\uFF1A**\u5728\u540C\u4E00\u4E2A\u56DE\u5408\u91CC\u8F6E\u8BE2\u7740\u7B49**\u2014\u2014\u67E5\u4E00\u6B21\u3001\`sleep\` \u4E00\u4F1A\u513F\u3001\u518D\u67E5\u3002\u6BCF\u8F6E\u628A\u89C2\u5BDF\u5230\u7684\u5199\u4E0B\u6765\uFF08\u7B2C\u51E0\u6B21\u67E5\u3001\u6D41\u6C34\u7EBF\u4EC0\u4E48\u72B6\u6001\u3001\u63A2\u9488\u62A5\u7684\u662F\u54EA\u4E2A sha\uFF09\uFF0C\u8BA9\u4EBA\u5728\u8F68\u8FF9\u91CC\u770B\u5F97\u89C1\u4F60\u5728\u7B49\u4EC0\u4E48\u3002**\u7EDD\u4E0D\u8981\u7ED3\u675F\u56DE\u5408\u53BB\u7B49\u5524\u9192**\uFF08\u90A3\u7C7B\u5DE5\u5177\u5728\u8FD9\u91CC\u5FC5\u6B7B\uFF0C\u4F1A\u53D8\u6210\u96F6\u4EA7\u51FA\u4F1A\u8BDD\uFF09\u3002\u7B49\u5230\u4E0A\u9650\uFF08\u5EFA\u8BAE 10 \u5206\u949F\uFF09\u4ECD\u4E0D\u5230\u4F4D\uFF0C\u5C31**\u5982\u5B9E\u4E0A\u62A5\u7B49\u4E0D\u5230\u3001\u8BF4\u660E\u5361\u5728\u54EA\u4E00\u6B65**\uFF0C\u4E0D\u8BB8\u5047\u88C5\u901A\u8FC7\u3002
|
|
174918
175111
|
|
|
174919
|
-
**\u4EA7\u51FA\u90E8\u7F72\u8BB0\u5F55**\uFF0C\u5FC5\u987B\u5305\u542B\uFF1A\u4E0A\u7EBF\u7684\u662F\u54EA\u4E2A commit\u3001**\u4E0B\u6E38\u8981\u9A8C\u7684\u662F\u54EA\u4E2A\u73AF\u5883\u5730\u5740**\uFF08\u5192\u70DF\u5168\u9760\u8FD9\u6761\u77E5\u9053\u53BB\u54EA\u6D4B\uFF09\u3001\u63A2\u9488\u5B9E\u9645\u8FD4\u56DE\u4E86\u4EC0\u4E48\u3002
|
|
174920
|
-
|
|
174921
175112
|
**\u4F60\u8BF4\u901A\u8FC7\u4E0D\u7B97\u6570**\u2014\u2014\u6536\u5C3E\u65F6\u673A\u5668\u4F1A\u62FF\u540C\u6837\u7684\u5224\u636E\u5B9E\u6D4B\u590D\u6838\u4E00\u904D\uFF0C\u5BF9\u4E0D\u4E0A\u4F1A\u6253\u56DE\u3002\u6240\u4EE5\u522B\u53EA\u8BFB\u4EE3\u7801\u5C31\u5224\u5B9A\uFF0C\u4E5F\u522B\u5728\u63A2\u9488\u6253\u4E0D\u901A\u65F6\u731C\u300C\u5E94\u8BE5\u597D\u4E86\u300D\u3002\u82E5\u67E5\u660E\u662F\u73AF\u5883/\u6D41\u6C34\u7EBF\u95EE\u9898\u800C\u4E0D\u662F\u4EE3\u7801\u95EE\u9898\uFF0C\u5982\u5B9E\u4E0A\u62A5\u5347\u7EA7\uFF0C**\u4E0D\u8981\u6253\u56DE\u4E0A\u6E38\u7684\u300C\u4FEE\u590D\u5B9E\u73B0\u300D**\u2014\u2014\u8BA9\u5F00\u53D1\u91CD\u5199\u4EE3\u7801\u89E3\u51B3\u4E0D\u4E86\u90E8\u7F72\u73AF\u5883\u7684\u95EE\u9898\u3002`
|
|
174922
175113
|
},
|
|
174923
175114
|
{
|
|
@@ -174928,7 +175119,15 @@ var init_registry3 = __esm({
|
|
|
174928
175119
|
dependsOn: ["cd:\u4E0A\u7EBF\u6838\u9A8C"],
|
|
174929
175120
|
role: "\u5192\u70DF\u6D4B\u8BD5",
|
|
174930
175121
|
ownerRole: "smoke",
|
|
174931
|
-
brief: () =>
|
|
175122
|
+
brief: () => `**\u4EA7\u51FA**\uFF1A\u4E00\u4EFD\u9A8C\u8BC1\u8BB0\u5F55\u2014\u2014\u7167\u5DE5\u5355\u63CF\u8FF0\u91CC\u6240\u62A5\u7684\u73B0\u8C61\u5728\u771F\u5B9E\u73AF\u5883\u8D70\u4E00\u904D\uFF0C\u786E\u8BA4\u5B83\u786E\u5B9E\u4E0D\u518D\u51FA\u73B0\u3002
|
|
175123
|
+
**\u8D1F\u8D23\u5230\u54EA**\uFF1A\u53EA\u9A8C\u6240\u62A5\u73B0\u8C61 + \u76F4\u63A5\u76F8\u90BB\u7684\u8DEF\u5F84\u6709\u6CA1\u6709\u88AB\u6253\u574F\uFF1B**\u4E0D\u505A\u5168\u91CF\u56DE\u5F52\u3001\u4E0D\u5199\u6D4B\u8BD5\u8BA1\u5212**\u3002
|
|
175124
|
+
**\u4EA4\u4ED8\u524D\u5FC5\u987B\u80FD\u56DE\u7B54**\uFF1A\u2460 \u6BCF\u6761\u9A8C\u6536\u6807\u51C6\u4F60\u5B9E\u9645\u6267\u884C\u4E86\u4EC0\u4E48\u547D\u4EE4/\u64CD\u4F5C\u3001\u770B\u5230\u4E86\u4EC0\u4E48\u8F93\u51FA\uFF1F\u2461 \u6709\u6CA1\u6709\u54EA\u4E00\u6761\u4F60\u6CA1\u80FD\u5B9E\u6D4B\uFF1F\u6CA1\u80FD\u5B9E\u6D4B\u7684\uFF0C\u662F**\u88AB\u6D4B\u7269\u6709\u7F3A\u9677**\u3001\u8FD8\u662F**\u9700\u6C42\u672C\u8EAB\u8C41\u514D**\u3001\u8FD8\u662F**\u4F60\u5361\u4F4F\u4E86\u9700\u8981\u4EBA\u5E2E\u5FD9**\u2014\u2014\u9010\u6761\u8BF4\u6E05\u662F\u54EA\u4E00\u79CD\u3002\u2462 \u76F8\u90BB\u4E09\u533A/\u76F8\u90BB\u8DEF\u5F84\u6539\u52A8\u524D\u540E\u884C\u4E3A\u4E00\u81F4\u5417\uFF1F
|
|
175125
|
+
|
|
175126
|
+
\u5224\u636E\u6765\u81EA\u5DE5\u5355\u63CF\u8FF0\u672C\u8EAB\u2014\u2014**\u6CA1\u6709\u771F\u5B9E\u6267\u884C\u8FC7\u4E0D\u7B97\u9A8C\u8BC1\u8FC7**\u3002\u63CF\u8FF0\u91CC\u6CA1\u6709\u53EF\u6267\u884C\u7684\u590D\u73B0\u65B9\u5F0F\u65F6\uFF0C\u5148\u5982\u5B9E\u8BF4\u660E\u8FD9\u4E00\u70B9\uFF0C\u518D\u7ED9\u51FA\u4F60\u5B9E\u9645\u91C7\u7528\u7684\u9A8C\u8BC1\u65B9\u5F0F\uFF0C\u4E0D\u8981\u56E0\u4E3A\u300C\u4EE3\u7801\u770B\u8D77\u6765\u5BF9\u300D\u5C31\u5224\u901A\u8FC7\u3002
|
|
175127
|
+
|
|
175128
|
+
**\u300C\u76F8\u90BB\u8DEF\u5F84\u6CA1\u6253\u574F\u300D\u2260\u300C\u65E2\u6709\u6D4B\u8BD5\u5168\u7EFF\u300D**\uFF1A\u672C\u6B21\u65B0\u5F15\u5165\u6216\u6539\u5199\u7684\u5224\u65AD\uFF0C\u5728\u5B83\u7684\u6BCF\u4E00\u79CD\u72B6\u6001\u4E0B\u90FD\u8981\u6709\u5BF9\u5E94\u8BC1\u636E\u3002\u65E7\u5957\u4EF6\u91CC\u672C\u6765\u5C31\u6CA1\u6709\u8FD9\u4E9B\u72B6\u6001\u7684\u7528\u4F8B\uFF0C\u5168\u7EFF\u53EA\u8BC1\u660E\u300C\u6CA1\u6253\u574F\u65E7\u884C\u4E3A\u300D\u3002
|
|
175129
|
+
|
|
175130
|
+
\u9A8C\u4E0D\u8FC7\u5982\u5B9E\u6253\u56DE\u300C\u4FEE\u590D\u5B9E\u73B0\u300D\u5E76\u5199\u6E05\u5361\u5728\u54EA\u4E00\u6B65\u3001\u5B9E\u9645\u770B\u5230\u4EC0\u4E48\u3002`,
|
|
174932
175131
|
isFinalOutput: true
|
|
174933
175132
|
}
|
|
174934
175133
|
];
|
|
@@ -184706,8 +184905,10 @@ var init_postgres_control_plane = __esm({
|
|
|
184706
184905
|
name text NOT NULL,
|
|
184707
184906
|
avatar text, -- "blob:<hash>"\uFF0C\u7A7A=\u9ED8\u8BA4
|
|
184708
184907
|
status text NOT NULL, -- active | suspended
|
|
184709
|
-
created_at timestamptz NOT NULL
|
|
184908
|
+
created_at timestamptz NOT NULL,
|
|
184909
|
+
onboarding_variant text -- \u767B\u5F55\u540E\u52A9\u7406\u5F15\u5BFC\u53D8\u4F53 A|B\uFF1BNULL=\u7F3A\u7701\u89C6\u4E3A A
|
|
184710
184910
|
)`);
|
|
184911
|
+
await pool.query(`ALTER TABLE "${s2}".companies ADD COLUMN IF NOT EXISTS onboarding_variant text`);
|
|
184711
184912
|
await pool.query(`
|
|
184712
184913
|
CREATE TABLE IF NOT EXISTS "${s2}".company_members (
|
|
184713
184914
|
company_id text NOT NULL,
|
|
@@ -184752,8 +184953,8 @@ var init_postgres_control_plane = __esm({
|
|
|
184752
184953
|
// —— 公司 ——
|
|
184753
184954
|
async createCompany(c) {
|
|
184754
184955
|
await this.pool.query(
|
|
184755
|
-
`INSERT INTO ${this.s}.companies (id, slug, name, avatar, status, created_at) VALUES ($1,$2,$3,$4,$5,$6)`,
|
|
184756
|
-
[c.id, c.slug, c.name, c.avatar ?? null, c.status, c.createdAt]
|
|
184956
|
+
`INSERT INTO ${this.s}.companies (id, slug, name, avatar, status, created_at, onboarding_variant) VALUES ($1,$2,$3,$4,$5,$6,$7)`,
|
|
184957
|
+
[c.id, c.slug, c.name, c.avatar ?? null, c.status, c.createdAt, c.onboardingVariant ?? null]
|
|
184757
184958
|
);
|
|
184758
184959
|
}
|
|
184759
184960
|
async getCompany(id) {
|
|
@@ -184783,6 +184984,10 @@ var init_postgres_control_plane = __esm({
|
|
|
184783
184984
|
args.push(patch.status);
|
|
184784
184985
|
sets.push(`status = $${args.length}`);
|
|
184785
184986
|
}
|
|
184987
|
+
if (patch.onboardingVariant !== void 0) {
|
|
184988
|
+
args.push(patch.onboardingVariant);
|
|
184989
|
+
sets.push(`onboarding_variant = $${args.length}`);
|
|
184990
|
+
}
|
|
184786
184991
|
args.push(id);
|
|
184787
184992
|
const sql = sets.length ? `UPDATE ${this.s}.companies SET ${sets.join(", ")} WHERE id = $${args.length}` : `SELECT 1 FROM ${this.s}.companies WHERE id = $${args.length}`;
|
|
184788
184993
|
const r = await this.pool.query(sql, args);
|
|
@@ -185046,7 +185251,8 @@ var init_postgres_control_plane = __esm({
|
|
|
185046
185251
|
name: row.name,
|
|
185047
185252
|
...row.avatar !== null && row.avatar !== void 0 ? { avatar: row.avatar } : {},
|
|
185048
185253
|
status: row.status,
|
|
185049
|
-
createdAt: new Date(row.created_at).toISOString()
|
|
185254
|
+
createdAt: new Date(row.created_at).toISOString(),
|
|
185255
|
+
...row.onboarding_variant ? { onboardingVariant: row.onboarding_variant } : {}
|
|
185050
185256
|
});
|
|
185051
185257
|
rowToMember = (row) => ({
|
|
185052
185258
|
companyId: row.company_id,
|
|
@@ -192366,7 +192572,7 @@ async function runCli(argv, println = console.log) {
|
|
|
192366
192572
|
return uploaded;
|
|
192367
192573
|
};
|
|
192368
192574
|
const STAGE_COMMANDS = /* @__PURE__ */ new Set(["link", "spawn", "unlink", "cancel", "freeze", "cancel-part", "edit", "assign", "reopen"]);
|
|
192369
|
-
const GLOBAL_NON_FIELD_FLAGS = /* @__PURE__ */ new Set(["server", "token", "dir", "set-json", "clear"]);
|
|
192575
|
+
const GLOBAL_NON_FIELD_FLAGS = /* @__PURE__ */ new Set(["server", "token", "dir", "set-json", "clear", "workspace"]);
|
|
192370
192576
|
const SPAWN_OWN_FLAGS = /* @__PURE__ */ new Set(["type", "owner", "workspace", "persistence", "title", "brief", "description", "input", "parts-file"]);
|
|
192371
192577
|
const EDIT_OWN_FLAGS = /* @__PURE__ */ new Set(["title", "brief"]);
|
|
192372
192578
|
const fieldsFromFlags = (ownFlags) => {
|
|
@@ -194206,7 +194412,7 @@ function syncRuntimeAssets(candidateRoots, binDir) {
|
|
|
194206
194412
|
}
|
|
194207
194413
|
|
|
194208
194414
|
// src/index.ts
|
|
194209
|
-
var PKG_VERSION = true ? "0.1.
|
|
194415
|
+
var PKG_VERSION = true ? "0.1.85" : "dev";
|
|
194210
194416
|
var OASIS_DIR = path29.join(os9.homedir(), ".oasis");
|
|
194211
194417
|
var CONFIG_FILE = path29.join(OASIS_DIR, "node-config.json");
|
|
194212
194418
|
var PID_FILE = path29.join(OASIS_DIR, "node.pid");
|
|
@@ -194279,9 +194485,11 @@ exec node "${BIN_FILE}" "$@"
|
|
|
194279
194485
|
function setupAutostart() {
|
|
194280
194486
|
const cmd = `${process.execPath} "${BIN_FILE}" --_daemon`;
|
|
194281
194487
|
const home = os9.homedir();
|
|
194488
|
+
const pnpmHome = process.env["PNPM_HOME"] || path29.join(home, ".local", "share", "pnpm");
|
|
194282
194489
|
const extraBins = [
|
|
194283
194490
|
path29.join(home, ".npm-global", "bin"),
|
|
194284
194491
|
path29.join(home, ".local", "bin"),
|
|
194492
|
+
path29.join(pnpmHome, "bin"),
|
|
194285
194493
|
"/usr/local/bin"
|
|
194286
194494
|
];
|
|
194287
194495
|
const daemonPath = sanitizeDaemonPath([process.env["PATH"] ?? "", ...extraBins].filter(Boolean).join(":"));
|