oasis_test 0.1.9 → 0.1.10
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 +180 -66
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1275,6 +1275,19 @@ var init_kernel = __esm({
|
|
|
1275
1275
|
const payload = { owner: args.owner };
|
|
1276
1276
|
await this.commit(args.artifactId, args.actor, "assign_owner", args.artifactId, payload);
|
|
1277
1277
|
}
|
|
1278
|
+
// ── artifactType 目录(决策 0021):运行时可变的命令期策略,**不进 oplog、不参与 fold/重放** ──
|
|
1279
|
+
/** 当前注册的全部类型(视图/CLI 读活目录)。 */
|
|
1280
|
+
listTypes() {
|
|
1281
|
+
return [...this.schema.values()];
|
|
1282
|
+
}
|
|
1283
|
+
/** 增/改一个类型(按 name upsert)——只改命令期策略,重放不受影响(schema-free fold)。持久化由管理层调 store。 */
|
|
1284
|
+
setType(def) {
|
|
1285
|
+
this.schema.set(def.name, def);
|
|
1286
|
+
}
|
|
1287
|
+
/** 删一个类型(管理层先以 typeUsage.total===0 把关,避免孤儿存量节点命令期落空)。 */
|
|
1288
|
+
removeType(name) {
|
|
1289
|
+
this.schema.delete(name);
|
|
1290
|
+
}
|
|
1278
1291
|
// ── 版本机(§5)────────────────────────────────────────────────────────
|
|
1279
1292
|
/**
|
|
1280
1293
|
* propose:进入队列(review 机制随 M4,proposed 即 approved 入队)。
|
|
@@ -16130,7 +16143,10 @@ async function buildDynamicWorkorderPlan(input) {
|
|
|
16130
16143
|
ops.push({ action: "annotate", artifactId: briefId, body: workorderSpecBody(spec), blocks: false });
|
|
16131
16144
|
}
|
|
16132
16145
|
const spawned = [{ id: briefId, type: "brief", role: "pm", owner: briefOwner }];
|
|
16133
|
-
const agentGraph = input.agentPlan ? normalizeAgentPlan(input.agentPlan,
|
|
16146
|
+
const agentGraph = input.agentPlan ? normalizeAgentPlan(input.agentPlan, schema.map((d) => d.name)) : null;
|
|
16147
|
+
const briefByType = new Map(
|
|
16148
|
+
(input.agentPlan?.nodes ?? []).filter((n) => typeof n.brief === "string" && n.brief.trim().length > 0).map((n) => [n.type.trim().toLowerCase(), n.brief.trim()])
|
|
16149
|
+
);
|
|
16134
16150
|
if (input.agentPlan && !agentGraph) {
|
|
16135
16151
|
issues.push({
|
|
16136
16152
|
code: "planner_invalid",
|
|
@@ -16152,13 +16168,10 @@ async function buildDynamicWorkorderPlan(input) {
|
|
|
16152
16168
|
continue;
|
|
16153
16169
|
}
|
|
16154
16170
|
const owner = await resolveRole(def.ownerRole, type);
|
|
16155
|
-
|
|
16171
|
+
const ownerActor = owner.actor ?? (type === primaryType ? input.actor : void 0);
|
|
16172
|
+
if (!ownerActor) continue;
|
|
16156
16173
|
const id = type === primaryType ? primaryId : `artifact:${type}:${slug4}`;
|
|
16157
|
-
availableNodes.push({ type, id, role: def.ownerRole, owner:
|
|
16158
|
-
}
|
|
16159
|
-
const hasPrimary = availableNodes.some((node) => node.id === primaryId);
|
|
16160
|
-
if (!hasPrimary && schemaByName.has("prd")) {
|
|
16161
|
-
availableNodes.unshift({ type: "prd", id: primaryId, role: "pm", owner: planner.actor ?? input.actor });
|
|
16174
|
+
availableNodes.push({ type, id, role: def.ownerRole, owner: ownerActor });
|
|
16162
16175
|
}
|
|
16163
16176
|
for (const node of availableNodes) {
|
|
16164
16177
|
const inputs = inputEdgesFor(node.type, availableNodes, briefId, agentGraph?.dependsOn);
|
|
@@ -16174,7 +16187,7 @@ async function buildDynamicWorkorderPlan(input) {
|
|
|
16174
16187
|
ops.push({
|
|
16175
16188
|
action: "annotate",
|
|
16176
16189
|
artifactId: node.id,
|
|
16177
|
-
body: taskBookFor(node.type, input.description, node.role, issues, agentGraph?.notes),
|
|
16190
|
+
body: briefByType.get(node.type) ?? taskBookFor(node.type, input.description, node.role, issues, agentGraph?.notes),
|
|
16178
16191
|
blocks: false
|
|
16179
16192
|
});
|
|
16180
16193
|
spawned.push(node);
|
|
@@ -16193,7 +16206,7 @@ async function buildDynamicWorkorderPlan(input) {
|
|
|
16193
16206
|
ops
|
|
16194
16207
|
},
|
|
16195
16208
|
rootArtifactId: briefId,
|
|
16196
|
-
primaryArtifactId:
|
|
16209
|
+
primaryArtifactId: availableNodes[0]?.id ?? briefId,
|
|
16197
16210
|
issues: dedupeIssues(issues),
|
|
16198
16211
|
spawned,
|
|
16199
16212
|
fallback: issues.length > 0
|
|
@@ -16231,23 +16244,17 @@ function buildPmAgentPlannerPrompt(input) {
|
|
|
16231
16244
|
"",
|
|
16232
16245
|
JSON.stringify({
|
|
16233
16246
|
nodes: [
|
|
16234
|
-
{ type: "prd", dependsOn: ["brief"], title: "\u9700\u6C42\u4E0E\u8303\u56F4\u8BF4\u660E" },
|
|
16235
|
-
{ type: "
|
|
16236
|
-
{ type: "dev", dependsOn: ["adr"], title: "\u5B9E\u73B0" },
|
|
16237
|
-
{ type: "qa", dependsOn: ["dev"], title: "\u9A8C\u6536" }
|
|
16247
|
+
{ type: "prd", dependsOn: ["brief"], title: "\u9700\u6C42\u4E0E\u8303\u56F4\u8BF4\u660E", brief: "\u8FD9\u4E2A\u8282\u70B9\u5177\u4F53\u8981\u505A\u4EC0\u4E48\u7684\u89C4\u683C\uFF1A\u4EA7\u51FA\u4EC0\u4E48\u3001\u8981\u70B9\u3001\u7EA6\u675F" },
|
|
16248
|
+
{ type: "dev", dependsOn: ["prd"], title: "\u5B9E\u73B0", brief: "\u2026" }
|
|
16238
16249
|
],
|
|
16239
16250
|
notes: ["\u53EF\u9009\uFF1A\u89C4\u5212\u7406\u7531\u6216\u98CE\u9669\u63D0\u793A"]
|
|
16240
16251
|
}, null, 2),
|
|
16241
16252
|
"",
|
|
16242
16253
|
"\u89C4\u5219\uFF1A",
|
|
16243
16254
|
"- brief \u6839\u8282\u70B9\u7531\u7CFB\u7EDF\u56FA\u5B9A\u521B\u5EFA\uFF0C\u4F60\u4E0D\u8981\u628A brief \u5199\u8FDB nodes\u3002",
|
|
16244
|
-
"- type \u53EA\u80FD\u4ECE ArtifactType
|
|
16245
|
-
"- \
|
|
16246
|
-
"- \
|
|
16247
|
-
"- \u6D89\u53CA UI/UX/Figma/\u9875\u9762/\u4EA4\u4E92\u65F6\u52A0 design\u3002",
|
|
16248
|
-
"- \u6D89\u53CA\u67B6\u6784/API/\u6570\u636E\u6A21\u578B/\u5B89\u5168/\u6280\u672F\u9009\u578B\u65F6\u52A0 adr\u3002",
|
|
16249
|
-
"- \u6D89\u53CA\u5F00\u53D1/\u4EE3\u7801/\u524D\u7AEF/\u540E\u7AEF/\u6570\u636E\u5E93/bug \u4FEE\u590D/\u96C6\u6210\u65F6\u52A0 dev\u3002",
|
|
16250
|
-
"- \u6D89\u53CA\u6D4B\u8BD5/\u9A8C\u6536/\u56DE\u5F52\uFF0C\u6216\u521B\u5EFA\u4E86 dev \u65F6\uFF0C\u52A0 qa\u3002",
|
|
16255
|
+
"- type \u53EA\u80FD\u4ECE\u4E0A\u9762\u3010\u53EF\u7528 ArtifactType\u3011\u76EE\u5F55\u91CC\u9009\uFF08\u4EE5\u6CE8\u5165\u76EE\u5F55\u4E3A\u51C6\uFF0C\u4E0D\u9650\u4E8E\u67D0\u51E0\u4E2A\u56FA\u5B9A\u7C7B\u578B\uFF09\u3002",
|
|
16256
|
+
"- \u6BCF\u4E2A\u8282\u70B9\u5199 brief\uFF1A\u8FD9\u4E2A\u8282\u70B9\u5177\u4F53\u8981\u505A\u4EC0\u4E48\u7684\u89C4\u683C\uFF08\u4EA7\u51FA\u4EC0\u4E48\u3001\u8981\u70B9\u3001\u7EA6\u675F\uFF09\uFF0C\u522B\u5957\u6A21\u677F\u3001\u522B\u53EA\u5199\u7C7B\u578B\u540D\u3002",
|
|
16257
|
+
"- \u7B80\u5355\u9700\u6C42\u53EF\u4EE5\u53EA\u8981 prd\uFF1B\u6709\u8C03\u7814/\u8BBE\u8BA1/\u5F00\u53D1/\u6D4B\u8BD5/\u67B6\u6784\u9700\u8981\u65F6\u518D\u52A0\u5BF9\u5E94\u7C7B\u578B\u7684\u8282\u70B9\u3002",
|
|
16251
16258
|
"- dependsOn \u4F7F\u7528 type \u540D\uFF0C\u5141\u8BB8\u5F15\u7528 brief\u3002"
|
|
16252
16259
|
].join("\n");
|
|
16253
16260
|
}
|
|
@@ -16268,7 +16275,8 @@ function parseAgentWorkorderPlan(text) {
|
|
|
16268
16275
|
nodes.push({
|
|
16269
16276
|
type: n.type.trim().toLowerCase(),
|
|
16270
16277
|
...Array.isArray(n.dependsOn) ? { dependsOn: n.dependsOn.filter((x2) => typeof x2 === "string").map((x2) => x2.trim().toLowerCase()).filter(Boolean) } : {},
|
|
16271
|
-
...typeof n.title === "string" && n.title.trim() ? { title: n.title.trim() } : {}
|
|
16278
|
+
...typeof n.title === "string" && n.title.trim() ? { title: n.title.trim() } : {},
|
|
16279
|
+
...typeof n.brief === "string" && n.brief.trim() ? { brief: n.brief.trim() } : {}
|
|
16272
16280
|
});
|
|
16273
16281
|
}
|
|
16274
16282
|
if (nodes.length === 0) return null;
|
|
@@ -16343,8 +16351,8 @@ function desiredArtifacts(primaryType, description) {
|
|
|
16343
16351
|
if (needsQa) wanted.add("qa");
|
|
16344
16352
|
return ["prd", "research", "design", "adr", "dev", "qa"].filter((type) => wanted.has(type));
|
|
16345
16353
|
}
|
|
16346
|
-
function normalizeAgentPlan(plan,
|
|
16347
|
-
const allowed =
|
|
16354
|
+
function normalizeAgentPlan(plan, validTypes) {
|
|
16355
|
+
const allowed = validTypes.map((t) => t.trim().toLowerCase()).filter((t) => t !== "brief");
|
|
16348
16356
|
const types2 = [];
|
|
16349
16357
|
const dependsOn = /* @__PURE__ */ new Map();
|
|
16350
16358
|
for (const node of plan.nodes) {
|
|
@@ -16353,8 +16361,6 @@ function normalizeAgentPlan(plan, primaryType) {
|
|
|
16353
16361
|
if (!types2.includes(type)) types2.push(type);
|
|
16354
16362
|
if (node.dependsOn?.length) dependsOn.set(type, [...new Set(node.dependsOn.map((dep) => dep.trim().toLowerCase()).filter(Boolean))]);
|
|
16355
16363
|
}
|
|
16356
|
-
const normalizedPrimary = primaryType === "brief" ? "prd" : primaryType;
|
|
16357
|
-
if (!types2.includes(normalizedPrimary)) types2.unshift(normalizedPrimary);
|
|
16358
16364
|
const filtered = allowed.filter((type) => types2.includes(type));
|
|
16359
16365
|
return filtered.length > 0 ? { types: filtered, dependsOn, ...plan.notes?.length ? { notes: plan.notes } : {} } : null;
|
|
16360
16366
|
}
|
|
@@ -16765,7 +16771,14 @@ async function runCommand(kernel, blobs, oplog, actor, command, args, ctx = {})
|
|
|
16765
16771
|
${acceptanceCriteria.map((c) => `- ${c}`).join("\n")}` : brief;
|
|
16766
16772
|
const agentIssues = [];
|
|
16767
16773
|
let agentPlan = null;
|
|
16768
|
-
|
|
16774
|
+
const inlinePlan = args["plan"];
|
|
16775
|
+
if (inlinePlan !== void 0 && inlinePlan !== null) {
|
|
16776
|
+
agentPlan = parseAgentWorkorderPlan(typeof inlinePlan === "string" ? inlinePlan : JSON.stringify(inlinePlan));
|
|
16777
|
+
if (!agentPlan) {
|
|
16778
|
+
agentIssues.push({ code: "planner_invalid", severity: "warning", role: "pm", message: "\u524D\u7AEF\u63D0\u4F9B\u7684 plan \u7ED3\u6784\u65E0\u6548\uFF0C\u5DF2\u56DE\u9000\u5230\u89C4\u5219 planner\u3002" });
|
|
16779
|
+
}
|
|
16780
|
+
}
|
|
16781
|
+
if (agentPlan === null && ctx.planWorkorderWithAgent) {
|
|
16769
16782
|
try {
|
|
16770
16783
|
const availableActors = ctx.registry ? (await ctx.registry.listActors({ status: "active" })).map((a) => ({
|
|
16771
16784
|
id: a.id,
|
|
@@ -17324,6 +17337,25 @@ async function startOasisServer(opts) {
|
|
|
17324
17337
|
res.writeHead(result.status, headers).end(JSON.stringify(result.body ?? null));
|
|
17325
17338
|
return;
|
|
17326
17339
|
}
|
|
17340
|
+
if (url.pathname === "/api/nodes/exchange" && req.method === "POST") {
|
|
17341
|
+
const matched2 = domainRouter.match(req.method, url.pathname);
|
|
17342
|
+
if (!matched2) {
|
|
17343
|
+
res.writeHead(404).end();
|
|
17344
|
+
return;
|
|
17345
|
+
}
|
|
17346
|
+
const chunks2 = [];
|
|
17347
|
+
for await (const chunk of req) chunks2.push(chunk);
|
|
17348
|
+
const rawBody2 = Buffer.concat(chunks2).toString("utf8");
|
|
17349
|
+
const out = await matched2.handler({
|
|
17350
|
+
params: matched2.params,
|
|
17351
|
+
query: url.searchParams,
|
|
17352
|
+
body: rawBody2 ? JSON.parse(rawBody2) : void 0,
|
|
17353
|
+
auth: { actor: "actor:system:enroll" },
|
|
17354
|
+
raw: req
|
|
17355
|
+
});
|
|
17356
|
+
res.writeHead(out.status, { "content-type": "application/json" }).end(JSON.stringify(out.body ?? null));
|
|
17357
|
+
return;
|
|
17358
|
+
}
|
|
17327
17359
|
let actor;
|
|
17328
17360
|
if (opts.resolvePrincipal) {
|
|
17329
17361
|
actor = await opts.resolvePrincipal(req.headers);
|
|
@@ -18101,31 +18133,48 @@ function createNodeTokenStore(file) {
|
|
|
18101
18133
|
}
|
|
18102
18134
|
};
|
|
18103
18135
|
}
|
|
18104
|
-
function createEnrollTokenStore(defaultTtlMs = 30 * 60 * 1e3) {
|
|
18136
|
+
function createEnrollTokenStore(defaultTtlMs = 30 * 60 * 1e3, file) {
|
|
18137
|
+
const read = () => {
|
|
18138
|
+
if (!file) return table;
|
|
18139
|
+
try {
|
|
18140
|
+
return new Map(Object.entries(JSON.parse(fs.readFileSync(file, "utf8"))));
|
|
18141
|
+
} catch {
|
|
18142
|
+
return /* @__PURE__ */ new Map();
|
|
18143
|
+
}
|
|
18144
|
+
};
|
|
18145
|
+
const write = (m2) => {
|
|
18146
|
+
if (!file) return;
|
|
18147
|
+
fs.writeFileSync(file, JSON.stringify(Object.fromEntries(m2), null, 2), { mode: 384 });
|
|
18148
|
+
};
|
|
18105
18149
|
const table = /* @__PURE__ */ new Map();
|
|
18106
18150
|
const prune = () => {
|
|
18151
|
+
const m2 = read();
|
|
18107
18152
|
const now = Date.now();
|
|
18108
|
-
for (const [token, entry] of
|
|
18153
|
+
for (const [token, entry] of m2) if (entry.expiresAt <= now) m2.delete(token);
|
|
18154
|
+
write(m2);
|
|
18155
|
+
return m2;
|
|
18109
18156
|
};
|
|
18110
18157
|
return {
|
|
18111
18158
|
issue(nodeId, ttlMs = defaultTtlMs) {
|
|
18112
|
-
prune();
|
|
18159
|
+
const m2 = prune();
|
|
18113
18160
|
const token = `ent_${(0, import_node_crypto3.randomBytes)(24).toString("base64url")}`;
|
|
18114
18161
|
const expiresAt = Date.now() + ttlMs;
|
|
18115
|
-
|
|
18162
|
+
m2.set(token, { nodeId, expiresAt });
|
|
18163
|
+
write(m2);
|
|
18116
18164
|
return { token, expiresAt: new Date(expiresAt).toISOString() };
|
|
18117
18165
|
},
|
|
18118
18166
|
peek(token) {
|
|
18119
|
-
prune();
|
|
18120
|
-
const entry =
|
|
18167
|
+
const m2 = prune();
|
|
18168
|
+
const entry = m2.get(token);
|
|
18121
18169
|
if (!entry) return null;
|
|
18122
18170
|
return { nodeId: entry.nodeId };
|
|
18123
18171
|
},
|
|
18124
18172
|
consume(token) {
|
|
18125
|
-
prune();
|
|
18126
|
-
const entry =
|
|
18173
|
+
const m2 = prune();
|
|
18174
|
+
const entry = m2.get(token);
|
|
18127
18175
|
if (!entry) return null;
|
|
18128
|
-
|
|
18176
|
+
m2.delete(token);
|
|
18177
|
+
write(m2);
|
|
18129
18178
|
return { nodeId: entry.nodeId };
|
|
18130
18179
|
}
|
|
18131
18180
|
};
|
|
@@ -18328,6 +18377,13 @@ var init_memory_registry_store = __esm({
|
|
|
18328
18377
|
}
|
|
18329
18378
|
});
|
|
18330
18379
|
|
|
18380
|
+
// ../testkit/src/memory-type-registry-store.ts
|
|
18381
|
+
var init_memory_type_registry_store = __esm({
|
|
18382
|
+
"../testkit/src/memory-type-registry-store.ts"() {
|
|
18383
|
+
"use strict";
|
|
18384
|
+
}
|
|
18385
|
+
});
|
|
18386
|
+
|
|
18331
18387
|
// ../testkit/src/memory-trace-store.ts
|
|
18332
18388
|
var MemoryTraceStore;
|
|
18333
18389
|
var init_memory_trace_store = __esm({
|
|
@@ -18846,6 +18902,7 @@ var init_src3 = __esm({
|
|
|
18846
18902
|
init_memory_oplog_store();
|
|
18847
18903
|
init_fake_adapter();
|
|
18848
18904
|
init_memory_registry_store();
|
|
18905
|
+
init_memory_type_registry_store();
|
|
18849
18906
|
init_memory_trace_store();
|
|
18850
18907
|
init_memory_automation_store();
|
|
18851
18908
|
init_memory_control_plane_store();
|
|
@@ -21007,10 +21064,22 @@ var init_company_engine_router = __esm({
|
|
|
21007
21064
|
has(companyId) {
|
|
21008
21065
|
return this.cache.has(companyId);
|
|
21009
21066
|
}
|
|
21067
|
+
/** 当前已持有(缓存)的全部活引擎——不触发懒建。给"全局类型变更传播到每个活内核"用(决策 0021)。 */
|
|
21068
|
+
liveEngines() {
|
|
21069
|
+
return [...this.cache.values()];
|
|
21070
|
+
}
|
|
21010
21071
|
};
|
|
21011
21072
|
}
|
|
21012
21073
|
});
|
|
21013
21074
|
|
|
21075
|
+
// ../server/src/types-admin.ts
|
|
21076
|
+
var init_types_admin = __esm({
|
|
21077
|
+
"../server/src/types-admin.ts"() {
|
|
21078
|
+
"use strict";
|
|
21079
|
+
init_src2();
|
|
21080
|
+
}
|
|
21081
|
+
});
|
|
21082
|
+
|
|
21014
21083
|
// ../server/src/file-engine.ts
|
|
21015
21084
|
async function openFileEngine(dir, seed = {}) {
|
|
21016
21085
|
fs4.mkdirSync(dir, { recursive: true });
|
|
@@ -27685,18 +27754,21 @@ function nodesDomain(deps) {
|
|
|
27685
27754
|
enrolledAt: existing?.enrolledAt ?? now(),
|
|
27686
27755
|
...d.meta.nodeName ? { name: d.meta.nodeName } : existing?.name ? { name: existing.name } : {}
|
|
27687
27756
|
});
|
|
27688
|
-
|
|
27689
|
-
|
|
27690
|
-
|
|
27691
|
-
|
|
27692
|
-
|
|
27693
|
-
|
|
27694
|
-
|
|
27695
|
-
|
|
27696
|
-
|
|
27697
|
-
|
|
27698
|
-
|
|
27699
|
-
|
|
27757
|
+
if (d.meta.runtimes) {
|
|
27758
|
+
for (const cap of d.meta.runtimes) {
|
|
27759
|
+
await nodeStore.upsertRuntime({
|
|
27760
|
+
id: `runtime:${daemonId}:${cap.kind}`,
|
|
27761
|
+
nodeId: daemonId,
|
|
27762
|
+
kind: cap.kind,
|
|
27763
|
+
hostname: d.meta.hostname,
|
|
27764
|
+
...cap.binary ? { binary: cap.binary } : {},
|
|
27765
|
+
...cap.version ? { version: cap.version } : {},
|
|
27766
|
+
status: "online",
|
|
27767
|
+
lastSeenAt: now()
|
|
27768
|
+
});
|
|
27769
|
+
}
|
|
27770
|
+
} else {
|
|
27771
|
+
await nodeStore.setNodeRuntimesOnline(daemonId, true);
|
|
27700
27772
|
}
|
|
27701
27773
|
});
|
|
27702
27774
|
hub.onDaemonDisconnected = async (daemonId) => {
|
|
@@ -27718,18 +27790,21 @@ function nodesDomain(deps) {
|
|
|
27718
27790
|
enrolledAt: existing?.enrolledAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
27719
27791
|
...d.meta.nodeName ? { name: d.meta.nodeName } : existing?.name ? { name: existing.name } : {}
|
|
27720
27792
|
});
|
|
27721
|
-
|
|
27722
|
-
|
|
27723
|
-
|
|
27724
|
-
|
|
27725
|
-
|
|
27726
|
-
|
|
27727
|
-
|
|
27728
|
-
|
|
27729
|
-
|
|
27730
|
-
|
|
27731
|
-
|
|
27732
|
-
|
|
27793
|
+
if (d.meta.runtimes) {
|
|
27794
|
+
for (const cap of d.meta.runtimes) {
|
|
27795
|
+
await deps.nodeStore.upsertRuntime({
|
|
27796
|
+
id: `runtime:${daemonId}:${cap.kind}`,
|
|
27797
|
+
nodeId: daemonId,
|
|
27798
|
+
kind: cap.kind,
|
|
27799
|
+
hostname: d.meta.hostname,
|
|
27800
|
+
...cap.binary ? { binary: cap.binary } : {},
|
|
27801
|
+
...cap.version ? { version: cap.version } : {},
|
|
27802
|
+
status: "online",
|
|
27803
|
+
lastSeenAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
27804
|
+
});
|
|
27805
|
+
}
|
|
27806
|
+
} else {
|
|
27807
|
+
await deps.nodeStore.setNodeRuntimesOnline(daemonId, true);
|
|
27733
27808
|
}
|
|
27734
27809
|
}
|
|
27735
27810
|
router.get("/api/nodes", async () => {
|
|
@@ -27810,6 +27885,7 @@ function nodesDomain(deps) {
|
|
|
27810
27885
|
const consumed = deps.enrollTokens.consume(enrollToken);
|
|
27811
27886
|
if (!consumed) return { status: 401, body: { error: "invalid or expired enroll token" } };
|
|
27812
27887
|
const nodeId = requestedNodeId;
|
|
27888
|
+
await deps.nodeStore.clearDeletedRuntimesForNode(nodeId);
|
|
27813
27889
|
const existing = deps.nodeTokens.list().find((e) => e.nodeId === nodeId);
|
|
27814
27890
|
const token = existing?.token ?? deps.nodeTokens.issue(nodeId);
|
|
27815
27891
|
return { status: 200, body: { nodeId, token } };
|
|
@@ -27905,6 +27981,11 @@ var init_node_store = __esm({
|
|
|
27905
27981
|
if (k2.startsWith(`runtime:${id}:`)) this.deletedRuntimeIds.delete(k2);
|
|
27906
27982
|
}
|
|
27907
27983
|
}
|
|
27984
|
+
async clearDeletedRuntimesForNode(nodeId) {
|
|
27985
|
+
for (const id of [...this.deletedRuntimeIds]) {
|
|
27986
|
+
if (id.startsWith(`runtime:${nodeId}:`)) this.deletedRuntimeIds.delete(id);
|
|
27987
|
+
}
|
|
27988
|
+
}
|
|
27908
27989
|
async deleteRuntime(id) {
|
|
27909
27990
|
this.deletedRuntimeIds.add(id);
|
|
27910
27991
|
const rt = this.runtimes.get(id);
|
|
@@ -27966,6 +28047,10 @@ var init_node_store = __esm({
|
|
|
27966
28047
|
await super.deleteNode(id);
|
|
27967
28048
|
this.flush();
|
|
27968
28049
|
}
|
|
28050
|
+
async clearDeletedRuntimesForNode(nodeId) {
|
|
28051
|
+
await super.clearDeletedRuntimesForNode(nodeId);
|
|
28052
|
+
this.flush();
|
|
28053
|
+
}
|
|
27969
28054
|
async deleteRuntime(id) {
|
|
27970
28055
|
const r = await super.deleteRuntime(id);
|
|
27971
28056
|
this.flush();
|
|
@@ -31122,6 +31207,7 @@ var init_src4 = __esm({
|
|
|
31122
31207
|
init_dev_store();
|
|
31123
31208
|
init_control_plane_file_store();
|
|
31124
31209
|
init_company_engine_router();
|
|
31210
|
+
init_types_admin();
|
|
31125
31211
|
init_file_engine();
|
|
31126
31212
|
init_daemon_hub();
|
|
31127
31213
|
init_router();
|
|
@@ -40698,7 +40784,7 @@ async function startServe(opts) {
|
|
|
40698
40784
|
const operatorToken = issuer.issue(operatorActor);
|
|
40699
40785
|
fs13.writeFileSync(path11.join(opts.dir, "operator-token"), operatorToken, { mode: 384 });
|
|
40700
40786
|
const nodeTokens = createNodeTokenStore(path11.join(opts.dir, "node-tokens.json"));
|
|
40701
|
-
const enrollTokens = createEnrollTokenStore();
|
|
40787
|
+
const enrollTokens = createEnrollTokenStore(30 * 60 * 1e3, path11.join(opts.dir, "enroll-tokens.json"));
|
|
40702
40788
|
const nodeStore = await FileNodeStore.open(path11.join(opts.dir, "nodes.json"));
|
|
40703
40789
|
const registryAuditFile = path11.join(opts.dir, "registry-audit.ndjson");
|
|
40704
40790
|
const registryListeners = /* @__PURE__ */ new Set();
|
|
@@ -40971,7 +41057,13 @@ async function startServe(opts) {
|
|
|
40971
41057
|
// 暴露注册的 artifact 类型,给前端「发起工单」动态拉取根产物可选类型——schema.json 增改即自动扩展,
|
|
40972
41058
|
// 前端不再写死枚举。走通用 /api/view(generic data),非域路由契约,不进 gen:api。
|
|
40973
41059
|
views: {
|
|
40974
|
-
"artifact-types": () => schema.map((d) => ({
|
|
41060
|
+
"artifact-types": () => schema.map((d) => ({
|
|
41061
|
+
name: d.name,
|
|
41062
|
+
...d.description ? { description: d.description } : {},
|
|
41063
|
+
contentType: d.contentType,
|
|
41064
|
+
ownerRole: d.ownerRole,
|
|
41065
|
+
status: d.status ?? "active"
|
|
41066
|
+
})),
|
|
40975
41067
|
dispatches: () => ({
|
|
40976
41068
|
recent: journalRing.slice(-100),
|
|
40977
41069
|
fused: dispatcher?.fusedJobs() ?? [],
|
|
@@ -41441,7 +41533,7 @@ function log2(tag, msg, extra) {
|
|
|
41441
41533
|
var RECONNECT_DELAY_MS = 3e3;
|
|
41442
41534
|
var PING_INTERVAL_MS = 2e4;
|
|
41443
41535
|
var DaemonWsClient = class {
|
|
41444
|
-
constructor(serverUrl, daemonId, sessions, adapters = ["claude-code"], token, runtimes = adapters.map((kind) => ({ kind })), nodeName) {
|
|
41536
|
+
constructor(serverUrl, daemonId, sessions, adapters = ["claude-code"], token, runtimes = adapters.map((kind) => ({ kind })), nodeName, reportRuntimes = false) {
|
|
41445
41537
|
this.serverUrl = serverUrl;
|
|
41446
41538
|
this.daemonId = daemonId;
|
|
41447
41539
|
this.sessions = sessions;
|
|
@@ -41449,6 +41541,7 @@ var DaemonWsClient = class {
|
|
|
41449
41541
|
this.token = token;
|
|
41450
41542
|
this.runtimes = runtimes;
|
|
41451
41543
|
this.nodeName = nodeName;
|
|
41544
|
+
this.reportRuntimes = reportRuntimes;
|
|
41452
41545
|
}
|
|
41453
41546
|
ws = null;
|
|
41454
41547
|
pingTimer = null;
|
|
@@ -41535,7 +41628,7 @@ var DaemonWsClient = class {
|
|
|
41535
41628
|
if (this.ws?.readyState === import_websocket.default.OPEN) this.ws.send(JSON.stringify(msg));
|
|
41536
41629
|
}
|
|
41537
41630
|
buildMeta() {
|
|
41538
|
-
return { hostname: (0, import_node_os2.hostname)(), adapters: this.adapters, runtimes: this.runtimes, nodeVersion: process.version, ...this.nodeName ? { nodeName: this.nodeName } : {} };
|
|
41631
|
+
return { hostname: (0, import_node_os2.hostname)(), adapters: this.adapters, ...this.reportRuntimes ? { runtimes: this.runtimes } : {}, nodeVersion: process.version, ...this.nodeName ? { nodeName: this.nodeName } : {} };
|
|
41539
41632
|
}
|
|
41540
41633
|
};
|
|
41541
41634
|
|
|
@@ -41637,7 +41730,7 @@ async function startNode(opts) {
|
|
|
41637
41730
|
claude
|
|
41638
41731
|
)
|
|
41639
41732
|
);
|
|
41640
|
-
const client = new DaemonWsClient(opts.serverUrl, opts.nodeId, sessions, adapters, opts.token, runtimes, opts.nodeName);
|
|
41733
|
+
const client = new DaemonWsClient(opts.serverUrl, opts.nodeId, sessions, adapters, opts.token, runtimes, opts.nodeName, opts.reportRuntimes ?? false);
|
|
41641
41734
|
console.log(`[oasis node] ${opts.nodeId} \u2192 ${opts.serverUrl}`);
|
|
41642
41735
|
client.start();
|
|
41643
41736
|
await new Promise((resolve3) => {
|
|
@@ -41703,6 +41796,7 @@ var USAGE = `oasis \u2014\u2014 artifact-centric \u534F\u4F5C\u5185\u6838 CLI\uF
|
|
|
41703
41796
|
gc # \u5B64\u513F blob \u56DE\u6536\uFF08mark-and-sweep\uFF1B\u64CD\u4F5C\u8005\u547D\u4EE4\uFF0CF1\uFF09
|
|
41704
41797
|
\u8BFB\u4EA7\u7269: status <id>\uFF08\u72B6\u6001\u7D22\u5F15\uFF0C\u4E0D\u542B\u6B63\u6587\uFF09/ content <id> [path]\uFF08\u5B9E\u9645\u5185\u5BB9\uFF0C\u591A\u6587\u4EF6\u7ED9 path \u53D6\u5355\u4E2A\uFF09/ projects [--search q]\uFF08\u5217/\u641C\u9879\u76EE\uFF09/ project <id>\uFF08\u9879\u76EE\u76EE\u5F55\uFF09 # \u7ED9 agent\uFF0C\u6E10\u8FDB\u62AB\u9732
|
|
41705
41798
|
graph / show / log / ls # \u5168\u5C40/\u8BE6\u5C3D\u89C6\u56FE\uFF08\u534F\u8C03\u8005\u3001\u4EBA\uFF1Bls \u4EC5\u534F\u8C03\u8005\uFF09
|
|
41799
|
+
artifact-types [list | search <q>] # \u770B/\u68C0\u7D22\u5DF2\u6CE8\u518C\u7684 artifact \u7C7B\u578B\uFF08\u7528\u9014/owner/\u72B6\u6001\uFF09\u2014\u2014\u7ED9\u4EBA\u548C agent \u9009 type
|
|
41706
41800
|
|
|
41707
41801
|
\u6CBB\u7406\uFF08\xA711\uFF09
|
|
41708
41802
|
reopen <artifactId> [--note t] # \u89E3\u5C01\uFF08lifecycle \u2192 active\uFF09
|
|
@@ -42656,6 +42750,23 @@ async function runCli(argv, println = console.log) {
|
|
|
42656
42750
|
}
|
|
42657
42751
|
break;
|
|
42658
42752
|
}
|
|
42753
|
+
case "artifact-types": {
|
|
42754
|
+
const sub = positional[0] ?? "list";
|
|
42755
|
+
const all = await api.view(
|
|
42756
|
+
"artifact-types"
|
|
42757
|
+
);
|
|
42758
|
+
const q = sub === "search" ? positional[1]?.toLowerCase() : void 0;
|
|
42759
|
+
const rows = q ? all.filter((t) => t.name.toLowerCase().includes(q) || (t.description ?? "").toLowerCase().includes(q)) : all;
|
|
42760
|
+
if (rows.length === 0) {
|
|
42761
|
+
println("\uFF08\u65E0\u5339\u914D\u7684 artifact \u7C7B\u578B\uFF09");
|
|
42762
|
+
break;
|
|
42763
|
+
}
|
|
42764
|
+
for (const t of rows) {
|
|
42765
|
+
const dep = t.status === "deprecated" ? " [\u5DF2\u5F03\u7528]" : "";
|
|
42766
|
+
println(`${t.name}${dep} (${t.contentType}, owner=${t.ownerRole})${t.description ? ` \u2014\u2014 ${t.description}` : ""}`);
|
|
42767
|
+
}
|
|
42768
|
+
break;
|
|
42769
|
+
}
|
|
42659
42770
|
case "staged": {
|
|
42660
42771
|
const r = await api.request("GET", "/api/stage");
|
|
42661
42772
|
if (r.ops.length === 0) {
|
|
@@ -42841,6 +42952,8 @@ void (async () => {
|
|
|
42841
42952
|
cleanup();
|
|
42842
42953
|
process.exit(0);
|
|
42843
42954
|
});
|
|
42955
|
+
const reportRuntimes = cfg.reportRuntimesOnNextStart === true;
|
|
42956
|
+
if (reportRuntimes) saveConfig({ ...cfg, reportRuntimesOnNextStart: false });
|
|
42844
42957
|
if (cfg.nodeId && cfg.name) {
|
|
42845
42958
|
const base = httpBase(cfg.serverUrl);
|
|
42846
42959
|
fetch(`${base}/api/nodes/${cfg.nodeId}`, {
|
|
@@ -42854,7 +42967,8 @@ void (async () => {
|
|
|
42854
42967
|
serverUrl: cfg.serverUrl,
|
|
42855
42968
|
token: cfg.token,
|
|
42856
42969
|
nodeId: cfg.nodeId ?? `node-${(0, import_node_crypto21.randomUUID)()}`,
|
|
42857
|
-
nodeName: cfg.name ?? cfg.nodeId ?? `node-${(0, import_node_crypto21.randomUUID)()}
|
|
42970
|
+
nodeName: cfg.name ?? cfg.nodeId ?? `node-${(0, import_node_crypto21.randomUUID)()}`,
|
|
42971
|
+
reportRuntimes
|
|
42858
42972
|
});
|
|
42859
42973
|
return;
|
|
42860
42974
|
}
|
|
@@ -42892,7 +43006,7 @@ void (async () => {
|
|
|
42892
43006
|
}
|
|
42893
43007
|
const name = flags.get("name") ?? prev?.name;
|
|
42894
43008
|
const nameChanged = prev?.name !== void 0 && name !== prev.name;
|
|
42895
|
-
saveConfig({ serverUrl, token, nodeId, ...name ? { name } : {} });
|
|
43009
|
+
saveConfig({ serverUrl, token, nodeId, ...name ? { name } : {}, reportRuntimesOnNextStart: true });
|
|
42896
43010
|
installBinary();
|
|
42897
43011
|
stopDaemon();
|
|
42898
43012
|
setupAutostart();
|