oasis_test 0.1.32 → 0.1.34
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 +276 -116
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -387,6 +387,8 @@ function fold(model, op) {
|
|
|
387
387
|
head: artifact.currentRev,
|
|
388
388
|
at: op.timestamp,
|
|
389
389
|
seq: op.seq,
|
|
390
|
+
by: op.actor,
|
|
391
|
+
note: p2.note,
|
|
390
392
|
gate: p2.gate ? { quorum: p2.gate.quorum, eligible: [...p2.gate.eligible] } : null
|
|
391
393
|
});
|
|
392
394
|
break;
|
|
@@ -404,6 +406,7 @@ function fold(model, op) {
|
|
|
404
406
|
head: artifact.currentRev,
|
|
405
407
|
at: op.timestamp,
|
|
406
408
|
seq: op.seq,
|
|
409
|
+
by: op.actor,
|
|
407
410
|
gate: null,
|
|
408
411
|
forced: { by: op.actor, reason: p2.reason }
|
|
409
412
|
});
|
|
@@ -3795,6 +3798,7 @@ function computeProduceJobs(model) {
|
|
|
3795
3798
|
out.push({ artifactId: artifact.id });
|
|
3796
3799
|
continue;
|
|
3797
3800
|
}
|
|
3801
|
+
if (partHasOpenBackpressure(model, artifact.id, null)) continue;
|
|
3798
3802
|
for (const part of parts) {
|
|
3799
3803
|
if (gaps.some((g2) => g2.part === part.name) || partHasOpenBackpressure(model, artifact.id, part.name)) continue;
|
|
3800
3804
|
if (partProduced(model, artifact.id, part.name) && !partReworkNeeded(model, artifact.id, part.name)) continue;
|
|
@@ -23535,9 +23539,20 @@ async function resolveContent(blobs, args) {
|
|
|
23535
23539
|
throw new Error("propose \u9700\u8981 content\uFF08\u5355\u6587\u4EF6\uFF09/ files\uFF08\u591A\u6587\u4EF6\uFF09/ externalPin\uFF08\u5916\u90E8\u5927\u4EF6\uFF09\u4E4B\u4E00");
|
|
23536
23540
|
}
|
|
23537
23541
|
async function resolveProposeContent(kernel, blobs, args, artifactId, ctx) {
|
|
23538
|
-
const
|
|
23539
|
-
|
|
23540
|
-
|
|
23542
|
+
const hasInline = typeof args["content"] === "string" || Array.isArray(args["files"]);
|
|
23543
|
+
const pin = optStr(args, "externalPin");
|
|
23544
|
+
const art = kernel.model.artifacts.get(artifactId);
|
|
23545
|
+
const typeDef = art ? ctx.schema?.find((t) => t.name === art.type) : void 0;
|
|
23546
|
+
const isCode = typeDef?.contentType === "code";
|
|
23547
|
+
const knownNonCode = typeDef !== void 0 && !isCode;
|
|
23548
|
+
if (isCode && hasInline) {
|
|
23549
|
+
throw new Error(
|
|
23550
|
+
"\u4EE3\u7801\u8282\u70B9\u7684\u5185\u5BB9\u5728 git\uFF0C\u4E0D\u63A5\u53D7 --file/--from-dir \u5185\u8054\u5185\u5BB9\u3002\u8BF7\u5728\u4F60\u6539\u8FC7\u7684\u4ED3\u5E93 commit \u5E76 `git push` \u5230\u5DE5\u5355 feat \u5206\u652F\u540E\uFF0C\u76F4\u63A5 `oasis propose <id> --reason`\uFF08\u7CFB\u7EDF\u81EA\u52A8\u4ECE git \u6536\u96C6\uFF09\uFF0C\u6216\u7528 `oasis propose <id> --git-commit <sha>` \u624B\u52A8\u6307\u5B9A\u90A3\u6B21\u63D0\u4EA4\u3002"
|
|
23551
|
+
);
|
|
23552
|
+
}
|
|
23553
|
+
if (pin !== void 0) return { contentRef: pin, contentKind: "external-pin" };
|
|
23554
|
+
if (!hasInline && !knownNonCode && ctx.resolveCodeRepo) {
|
|
23555
|
+
const ws = art?.workspace;
|
|
23541
23556
|
const repos = ws ? (await ctx.resolveCodeRepo(ws))?.repos : void 0;
|
|
23542
23557
|
if (repos?.length) {
|
|
23543
23558
|
const slug6 = (id) => id.replace(/[^a-zA-Z0-9_-]+/g, "_");
|
|
@@ -23549,6 +23564,14 @@ async function resolveProposeContent(kernel, blobs, args, artifactId, ctx) {
|
|
|
23549
23564
|
}
|
|
23550
23565
|
return { contentRef: JSON.stringify(commits), contentKind: "external-pin" };
|
|
23551
23566
|
}
|
|
23567
|
+
if (isCode) {
|
|
23568
|
+
throw new Error(
|
|
23569
|
+
'\u4EE3\u7801\u8282\u70B9\u4F46\u672C\u5DE5\u5355\u672A\u914D\u7F6E\u4EE3\u7801\u4ED3\u5E93\uFF0C\u6536\u96C6\u4E0D\u5230 git \u5185\u5BB9\u3002\u8BF7\u7528 `oasis gap <id> --desc "\u7F3A\u4EE3\u7801\u4ED3\u5E93\u914D\u7F6E"` \u4E0A\u62A5\uFF0C\u522B\u7528 --file \u515C\u5E95\u3002'
|
|
23570
|
+
);
|
|
23571
|
+
}
|
|
23572
|
+
}
|
|
23573
|
+
if (!hasInline && knownNonCode) {
|
|
23574
|
+
throw new Error("\u9700\u8981\u5185\u5BB9\uFF1A`--file <\u6587\u4EF6>`\uFF08\u5355\u6587\u4EF6\uFF09\u6216 `--from-dir <\u76EE\u5F55>`\uFF08\u591A\u6587\u4EF6\uFF09\u3002");
|
|
23552
23575
|
}
|
|
23553
23576
|
return resolveContent(blobs, args);
|
|
23554
23577
|
}
|
|
@@ -24975,7 +24998,9 @@ async function startOasisServer(opts) {
|
|
|
24975
24998
|
...streamedParts.length ? { parts: streamedParts } : {}
|
|
24976
24999
|
}).catch(() => void 0);
|
|
24977
25000
|
await chatStore.updateSession(persistTarget.id, {
|
|
24978
|
-
|
|
25001
|
+
// 优先落 runtime-native id(codex rollout / ACP session/new 返回),让下一轮 resume
|
|
25002
|
+
// 能命中 runtime 认可的 id;claude-code 等接受任意外部 id 的仍回退 session.id 兼容原行为。
|
|
25003
|
+
runtimeSessionId: session.nativeSessionId ?? session.id,
|
|
24979
25004
|
touchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
24980
25005
|
}).catch(() => void 0);
|
|
24981
25006
|
};
|
|
@@ -34164,6 +34189,94 @@ var init_image_upload = __esm({
|
|
|
34164
34189
|
}
|
|
34165
34190
|
});
|
|
34166
34191
|
|
|
34192
|
+
// ../server/src/domains/actors/skill-materializer.ts
|
|
34193
|
+
async function listSkillMetadataForActor(args) {
|
|
34194
|
+
const skills = await args.service.listInstalledSkillsForActor(args.actorId);
|
|
34195
|
+
if (skills.length === 0) return [];
|
|
34196
|
+
const listMeta = args.service.listSkillFilesMeta;
|
|
34197
|
+
if (!listMeta) {
|
|
34198
|
+
throw new Error("SkillFileSource.listSkillFilesMeta \u672A\u5B9E\u73B0\u2014\u2014\u6280\u80FD\u589E\u91CF\u7F13\u5B58\u9700\u8981\u5B83");
|
|
34199
|
+
}
|
|
34200
|
+
const out = [];
|
|
34201
|
+
const usedDirs = /* @__PURE__ */ new Set();
|
|
34202
|
+
for (const skill of skills) {
|
|
34203
|
+
const metas = await listMeta.call(args.service, skill.id);
|
|
34204
|
+
if (metas.length === 0) continue;
|
|
34205
|
+
let dir = sanitizeSkillDir(skill.name);
|
|
34206
|
+
if (usedDirs.has(dir)) {
|
|
34207
|
+
let n = 2;
|
|
34208
|
+
while (usedDirs.has(`${dir}-${n}`)) n++;
|
|
34209
|
+
dir = `${dir}-${n}`;
|
|
34210
|
+
}
|
|
34211
|
+
usedDirs.add(dir);
|
|
34212
|
+
const sorted = [...metas].sort((a, b2) => a.path.localeCompare(b2.path));
|
|
34213
|
+
let latest = "1970-01-01T00:00:00.000Z";
|
|
34214
|
+
const hasher = (0, import_node_crypto7.createHash)("sha256");
|
|
34215
|
+
for (const m2 of sorted) {
|
|
34216
|
+
if (m2.updatedAt > latest) latest = m2.updatedAt;
|
|
34217
|
+
hasher.update(m2.path);
|
|
34218
|
+
hasher.update("\0");
|
|
34219
|
+
hasher.update(m2.blobHash);
|
|
34220
|
+
hasher.update("\0");
|
|
34221
|
+
}
|
|
34222
|
+
out.push({
|
|
34223
|
+
id: skill.id,
|
|
34224
|
+
name: skill.name,
|
|
34225
|
+
dir,
|
|
34226
|
+
updatedAt: latest,
|
|
34227
|
+
contentHash: `sha256:${hasher.digest("hex")}`,
|
|
34228
|
+
fileList: sorted.map((m2) => m2.path)
|
|
34229
|
+
});
|
|
34230
|
+
}
|
|
34231
|
+
return out;
|
|
34232
|
+
}
|
|
34233
|
+
function skillsDirForRuntime(runtimeKind) {
|
|
34234
|
+
switch (runtimeKind) {
|
|
34235
|
+
case "claude":
|
|
34236
|
+
case "claude-code":
|
|
34237
|
+
return ".claude/skills";
|
|
34238
|
+
default:
|
|
34239
|
+
return ".agent_context/skills";
|
|
34240
|
+
}
|
|
34241
|
+
}
|
|
34242
|
+
function sanitizeSkillDir(name) {
|
|
34243
|
+
const s2 = name.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
34244
|
+
return s2 || "skill";
|
|
34245
|
+
}
|
|
34246
|
+
async function materializeSkillFiles(args) {
|
|
34247
|
+
const skills = await args.service.listInstalledSkillsForActor(args.actorId);
|
|
34248
|
+
if (skills.length === 0) return {};
|
|
34249
|
+
const prefix = skillsDirForRuntime(args.runtimeKind);
|
|
34250
|
+
const out = {};
|
|
34251
|
+
const usedDirs = /* @__PURE__ */ new Set();
|
|
34252
|
+
for (const skill of skills) {
|
|
34253
|
+
const files = await args.service.listSkillFiles(skill.id);
|
|
34254
|
+
if (files.length === 0) continue;
|
|
34255
|
+
let dir = sanitizeSkillDir(skill.name);
|
|
34256
|
+
if (usedDirs.has(dir)) {
|
|
34257
|
+
let n = 2;
|
|
34258
|
+
while (usedDirs.has(`${dir}-${n}`)) n++;
|
|
34259
|
+
dir = `${dir}-${n}`;
|
|
34260
|
+
}
|
|
34261
|
+
usedDirs.add(dir);
|
|
34262
|
+
for (const f2 of files) {
|
|
34263
|
+
if (!f2.content) {
|
|
34264
|
+
console.warn(`[skill-materializer] skip ${skill.id}/${f2.path}\uFF1Acontent \u4E3A\u7A7A\uFF08\u672A\u56DE\u586B\uFF1F\uFF09\uFF0C\u4E0D\u5199\u7A7A\u6280\u80FD\u6587\u4EF6`);
|
|
34265
|
+
continue;
|
|
34266
|
+
}
|
|
34267
|
+
out[`${prefix}/${dir}/${f2.path}`] = f2.content;
|
|
34268
|
+
}
|
|
34269
|
+
}
|
|
34270
|
+
return out;
|
|
34271
|
+
}
|
|
34272
|
+
var import_node_crypto7;
|
|
34273
|
+
var init_skill_materializer = __esm({
|
|
34274
|
+
"../server/src/domains/actors/skill-materializer.ts"() {
|
|
34275
|
+
"use strict";
|
|
34276
|
+
import_node_crypto7 = require("node:crypto");
|
|
34277
|
+
}
|
|
34278
|
+
});
|
|
34279
|
+
|
|
34167
34280
|
// ../server/src/domains/actors/routes.ts
|
|
34168
34281
|
function positionsFromPayload(body) {
|
|
34169
34282
|
if (!body) return void 0;
|
|
@@ -34554,6 +34667,16 @@ function actorsDomain(opts) {
|
|
|
34554
34667
|
await service.deleteSkillFile(req.params.id, req.params["*"] ?? "");
|
|
34555
34668
|
return { status: 200, body: { ok: true } };
|
|
34556
34669
|
});
|
|
34670
|
+
router.get("/api/skill-cache/manifest", async (req) => {
|
|
34671
|
+
const { service } = await resolveCtx(req.auth.companyId);
|
|
34672
|
+
const items = await listSkillMetadataForActor({ service, actorId: req.auth.actor });
|
|
34673
|
+
return { status: 200, body: { items } };
|
|
34674
|
+
});
|
|
34675
|
+
router.get("/api/skill-cache/files/:skillId", async (req) => {
|
|
34676
|
+
const { service } = await resolveCtx(req.auth.companyId);
|
|
34677
|
+
const files = await service.listSkillFiles(req.params.skillId);
|
|
34678
|
+
return { status: 200, body: { files } };
|
|
34679
|
+
});
|
|
34557
34680
|
};
|
|
34558
34681
|
}
|
|
34559
34682
|
var init_routes = __esm({
|
|
@@ -34564,94 +34687,7 @@ var init_routes = __esm({
|
|
|
34564
34687
|
init_stats();
|
|
34565
34688
|
init_activity();
|
|
34566
34689
|
init_image_upload();
|
|
34567
|
-
|
|
34568
|
-
});
|
|
34569
|
-
|
|
34570
|
-
// ../server/src/domains/actors/skill-materializer.ts
|
|
34571
|
-
async function listSkillMetadataForActor(args) {
|
|
34572
|
-
const skills = await args.service.listInstalledSkillsForActor(args.actorId);
|
|
34573
|
-
if (skills.length === 0) return [];
|
|
34574
|
-
const listMeta = args.service.listSkillFilesMeta;
|
|
34575
|
-
if (!listMeta) {
|
|
34576
|
-
throw new Error("SkillFileSource.listSkillFilesMeta \u672A\u5B9E\u73B0\u2014\u2014\u6280\u80FD\u589E\u91CF\u7F13\u5B58\u9700\u8981\u5B83");
|
|
34577
|
-
}
|
|
34578
|
-
const out = [];
|
|
34579
|
-
const usedDirs = /* @__PURE__ */ new Set();
|
|
34580
|
-
for (const skill of skills) {
|
|
34581
|
-
const metas = await listMeta.call(args.service, skill.id);
|
|
34582
|
-
if (metas.length === 0) continue;
|
|
34583
|
-
let dir = sanitizeSkillDir(skill.name);
|
|
34584
|
-
if (usedDirs.has(dir)) {
|
|
34585
|
-
let n = 2;
|
|
34586
|
-
while (usedDirs.has(`${dir}-${n}`)) n++;
|
|
34587
|
-
dir = `${dir}-${n}`;
|
|
34588
|
-
}
|
|
34589
|
-
usedDirs.add(dir);
|
|
34590
|
-
const sorted = [...metas].sort((a, b2) => a.path.localeCompare(b2.path));
|
|
34591
|
-
let latest = "1970-01-01T00:00:00.000Z";
|
|
34592
|
-
const hasher = (0, import_node_crypto7.createHash)("sha256");
|
|
34593
|
-
for (const m2 of sorted) {
|
|
34594
|
-
if (m2.updatedAt > latest) latest = m2.updatedAt;
|
|
34595
|
-
hasher.update(m2.path);
|
|
34596
|
-
hasher.update("\0");
|
|
34597
|
-
hasher.update(m2.blobHash);
|
|
34598
|
-
hasher.update("\0");
|
|
34599
|
-
}
|
|
34600
|
-
out.push({
|
|
34601
|
-
id: skill.id,
|
|
34602
|
-
name: skill.name,
|
|
34603
|
-
dir,
|
|
34604
|
-
updatedAt: latest,
|
|
34605
|
-
contentHash: `sha256:${hasher.digest("hex")}`,
|
|
34606
|
-
fileList: sorted.map((m2) => m2.path)
|
|
34607
|
-
});
|
|
34608
|
-
}
|
|
34609
|
-
return out;
|
|
34610
|
-
}
|
|
34611
|
-
function skillsDirForRuntime(runtimeKind) {
|
|
34612
|
-
switch (runtimeKind) {
|
|
34613
|
-
case "claude":
|
|
34614
|
-
case "claude-code":
|
|
34615
|
-
return ".claude/skills";
|
|
34616
|
-
default:
|
|
34617
|
-
return ".agent_context/skills";
|
|
34618
|
-
}
|
|
34619
|
-
}
|
|
34620
|
-
function sanitizeSkillDir(name) {
|
|
34621
|
-
const s2 = name.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
34622
|
-
return s2 || "skill";
|
|
34623
|
-
}
|
|
34624
|
-
async function materializeSkillFiles(args) {
|
|
34625
|
-
const skills = await args.service.listInstalledSkillsForActor(args.actorId);
|
|
34626
|
-
if (skills.length === 0) return {};
|
|
34627
|
-
const prefix = skillsDirForRuntime(args.runtimeKind);
|
|
34628
|
-
const out = {};
|
|
34629
|
-
const usedDirs = /* @__PURE__ */ new Set();
|
|
34630
|
-
for (const skill of skills) {
|
|
34631
|
-
const files = await args.service.listSkillFiles(skill.id);
|
|
34632
|
-
if (files.length === 0) continue;
|
|
34633
|
-
let dir = sanitizeSkillDir(skill.name);
|
|
34634
|
-
if (usedDirs.has(dir)) {
|
|
34635
|
-
let n = 2;
|
|
34636
|
-
while (usedDirs.has(`${dir}-${n}`)) n++;
|
|
34637
|
-
dir = `${dir}-${n}`;
|
|
34638
|
-
}
|
|
34639
|
-
usedDirs.add(dir);
|
|
34640
|
-
for (const f2 of files) {
|
|
34641
|
-
if (!f2.content) {
|
|
34642
|
-
console.warn(`[skill-materializer] skip ${skill.id}/${f2.path}\uFF1Acontent \u4E3A\u7A7A\uFF08\u672A\u56DE\u586B\uFF1F\uFF09\uFF0C\u4E0D\u5199\u7A7A\u6280\u80FD\u6587\u4EF6`);
|
|
34643
|
-
continue;
|
|
34644
|
-
}
|
|
34645
|
-
out[`${prefix}/${dir}/${f2.path}`] = f2.content;
|
|
34646
|
-
}
|
|
34647
|
-
}
|
|
34648
|
-
return out;
|
|
34649
|
-
}
|
|
34650
|
-
var import_node_crypto7;
|
|
34651
|
-
var init_skill_materializer = __esm({
|
|
34652
|
-
"../server/src/domains/actors/skill-materializer.ts"() {
|
|
34653
|
-
"use strict";
|
|
34654
|
-
import_node_crypto7 = require("node:crypto");
|
|
34690
|
+
init_skill_materializer();
|
|
34655
34691
|
}
|
|
34656
34692
|
});
|
|
34657
34693
|
|
|
@@ -36739,7 +36775,13 @@ var init_claude_code = __esm({
|
|
|
36739
36775
|
fs7.mkdirSync(dir, { recursive: true });
|
|
36740
36776
|
if (this.opts.syncSkills) {
|
|
36741
36777
|
try {
|
|
36742
|
-
await this.opts.syncSkills({
|
|
36778
|
+
await this.opts.syncSkills({
|
|
36779
|
+
actorId: job.actor,
|
|
36780
|
+
actorToken: job.actorToken,
|
|
36781
|
+
serverUrl: job.server.url,
|
|
36782
|
+
runtimeKind: "claude",
|
|
36783
|
+
sessionDir: dir
|
|
36784
|
+
});
|
|
36743
36785
|
} catch (err) {
|
|
36744
36786
|
console.warn(`[claude-code] syncSkills \u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}`);
|
|
36745
36787
|
}
|
|
@@ -37300,6 +37342,49 @@ var init_skill_cache = __esm({
|
|
|
37300
37342
|
}
|
|
37301
37343
|
});
|
|
37302
37344
|
|
|
37345
|
+
// ../adapters/src/_core/skill-cache-http.ts
|
|
37346
|
+
function makeHttpSkillMetadataSource(opts) {
|
|
37347
|
+
const doFetch = opts.fetchImpl ?? fetch;
|
|
37348
|
+
const timeout = opts.timeoutMs ?? 1e4;
|
|
37349
|
+
const base = opts.serverUrl.replace(/\/+$/, "");
|
|
37350
|
+
const headers = {
|
|
37351
|
+
"authorization": `Bearer ${opts.actorToken}`,
|
|
37352
|
+
"accept": "application/json"
|
|
37353
|
+
};
|
|
37354
|
+
const withDeadline = async (fn) => {
|
|
37355
|
+
const ctrl = new AbortController();
|
|
37356
|
+
const timer = setTimeout(() => ctrl.abort(), timeout);
|
|
37357
|
+
try {
|
|
37358
|
+
return await fn(ctrl.signal);
|
|
37359
|
+
} finally {
|
|
37360
|
+
clearTimeout(timer);
|
|
37361
|
+
}
|
|
37362
|
+
};
|
|
37363
|
+
return {
|
|
37364
|
+
listSkillMetadata: async (_actorId) => {
|
|
37365
|
+
return withDeadline(async (signal) => {
|
|
37366
|
+
const res = await doFetch(`${base}/api/skill-cache/manifest`, { headers, signal });
|
|
37367
|
+
if (!res.ok) throw new Error(`skill-cache manifest \u62C9\u53D6\u5931\u8D25\uFF1AHTTP ${res.status} ${res.statusText}`);
|
|
37368
|
+
const body = await res.json();
|
|
37369
|
+
return body.items ?? [];
|
|
37370
|
+
});
|
|
37371
|
+
},
|
|
37372
|
+
fetchSkillFiles: async (skillId) => {
|
|
37373
|
+
return withDeadline(async (signal) => {
|
|
37374
|
+
const res = await doFetch(`${base}/api/skill-cache/files/${encodeURIComponent(skillId)}`, { headers, signal });
|
|
37375
|
+
if (!res.ok) throw new Error(`skill-cache files \u62C9\u53D6\u5931\u8D25\uFF08${skillId}\uFF09\uFF1AHTTP ${res.status} ${res.statusText}`);
|
|
37376
|
+
const body = await res.json();
|
|
37377
|
+
return body.files ?? [];
|
|
37378
|
+
});
|
|
37379
|
+
}
|
|
37380
|
+
};
|
|
37381
|
+
}
|
|
37382
|
+
var init_skill_cache_http = __esm({
|
|
37383
|
+
"../adapters/src/_core/skill-cache-http.ts"() {
|
|
37384
|
+
"use strict";
|
|
37385
|
+
}
|
|
37386
|
+
});
|
|
37387
|
+
|
|
37303
37388
|
// ../adapters/src/_core/models.ts
|
|
37304
37389
|
async function listModels(runtime, executablePath) {
|
|
37305
37390
|
switch (runtime) {
|
|
@@ -37556,6 +37641,19 @@ var init_models = __esm({
|
|
|
37556
37641
|
function codexNum(v2) {
|
|
37557
37642
|
return typeof v2 === "number" && Number.isFinite(v2) ? v2 : 0;
|
|
37558
37643
|
}
|
|
37644
|
+
function parseCodexSessionId(lines) {
|
|
37645
|
+
const first = lines[0];
|
|
37646
|
+
if (!first) return void 0;
|
|
37647
|
+
let o;
|
|
37648
|
+
try {
|
|
37649
|
+
o = JSON.parse(first);
|
|
37650
|
+
} catch {
|
|
37651
|
+
return void 0;
|
|
37652
|
+
}
|
|
37653
|
+
if (o?.type !== "session_meta") return void 0;
|
|
37654
|
+
const id = o.payload?.id;
|
|
37655
|
+
return typeof id === "string" && id ? id : void 0;
|
|
37656
|
+
}
|
|
37559
37657
|
function parseCodexTokenUsage(lines) {
|
|
37560
37658
|
let last;
|
|
37561
37659
|
for (const line of lines) {
|
|
@@ -37660,7 +37758,12 @@ function scanCodexTelemetry(workdir, sinceMs, sessionsRoot = codexSessionsRoot()
|
|
|
37660
37758
|
if (meta?.type === "session_meta" && meta.payload?.cwd === workdir) {
|
|
37661
37759
|
const usage = parseCodexTokenUsage(lines);
|
|
37662
37760
|
const model = parseCodexModel(lines);
|
|
37663
|
-
|
|
37761
|
+
const sessionId = parseCodexSessionId(lines);
|
|
37762
|
+
return {
|
|
37763
|
+
...usage ? { usage } : {},
|
|
37764
|
+
...model ? { model } : {},
|
|
37765
|
+
...sessionId ? { sessionId } : {}
|
|
37766
|
+
};
|
|
37664
37767
|
}
|
|
37665
37768
|
}
|
|
37666
37769
|
} catch {
|
|
@@ -37861,8 +37964,9 @@ var init_codex = __esm({
|
|
|
37861
37964
|
const task = job.bundle.files["TASK.md"];
|
|
37862
37965
|
if (!task) throw new Error("bundle \u7F3A TASK.md\uFF08\u88C5\u914D\u5668\u5951\u7EA6\uFF09");
|
|
37863
37966
|
const prompt = job.systemPrompt ? ["# System Prompt", job.systemPrompt, "", "# Task", task].join("\n") : task;
|
|
37967
|
+
const resumeArgs = job.resumeRuntimeSession && job.runtimeSessionId ? ["exec", "resume", job.runtimeSessionId] : ["exec"];
|
|
37864
37968
|
const args = [
|
|
37865
|
-
|
|
37969
|
+
...resumeArgs,
|
|
37866
37970
|
"--json",
|
|
37867
37971
|
"--dangerously-bypass-approvals-and-sandbox",
|
|
37868
37972
|
"--skip-git-repo-check",
|
|
@@ -37949,12 +38053,14 @@ var init_codex = __esm({
|
|
|
37949
38053
|
clearTimeout(timer);
|
|
37950
38054
|
const telemetry = scanCodexTelemetry(dir, startedAtMs);
|
|
37951
38055
|
const model = telemetry.model ?? job.model ?? this.opts.model;
|
|
38056
|
+
const runtimeSessionId = telemetry.sessionId ?? (job.resumeRuntimeSession ? job.runtimeSessionId : void 0);
|
|
37952
38057
|
finish({
|
|
37953
38058
|
code: killedByUs ? null : code,
|
|
37954
38059
|
reason: killedByUs ? "timeout" : code === 0 ? "clean" : "error",
|
|
37955
38060
|
transcriptRef,
|
|
37956
38061
|
...telemetry.usage ? { usage: telemetry.usage } : {},
|
|
37957
|
-
...model ? { model } : {}
|
|
38062
|
+
...model ? { model } : {},
|
|
38063
|
+
...runtimeSessionId ? { runtimeSessionId } : {}
|
|
37958
38064
|
});
|
|
37959
38065
|
});
|
|
37960
38066
|
return {
|
|
@@ -38406,9 +38512,11 @@ async function runACPSession(job, cfg) {
|
|
|
38406
38512
|
let exited;
|
|
38407
38513
|
let killedByUs = false;
|
|
38408
38514
|
let actualModel;
|
|
38515
|
+
let capturedSessionId;
|
|
38409
38516
|
const finish = (info) => {
|
|
38410
38517
|
if (exited) return;
|
|
38411
38518
|
if (actualModel && !info.model) info = { ...info, model: actualModel };
|
|
38519
|
+
if (capturedSessionId && !info.runtimeSessionId) info = { ...info, runtimeSessionId: capturedSessionId };
|
|
38412
38520
|
if (cfg.cleanupWorkdir) {
|
|
38413
38521
|
try {
|
|
38414
38522
|
const keepDir = path9.join(cfg.workRoot ?? os5.tmpdir(), "oasis-transcripts");
|
|
@@ -38481,13 +38589,31 @@ async function runACPSession(job, cfg) {
|
|
|
38481
38589
|
clientCapabilities: {}
|
|
38482
38590
|
});
|
|
38483
38591
|
const resolvedModel = job.model ?? cfg.model;
|
|
38484
|
-
|
|
38485
|
-
|
|
38486
|
-
|
|
38487
|
-
|
|
38488
|
-
|
|
38489
|
-
|
|
38490
|
-
|
|
38592
|
+
let sessionId = "";
|
|
38593
|
+
if (job.resumeRuntimeSession && job.runtimeSessionId) {
|
|
38594
|
+
const method = cfg.resumeMethod ?? "session/load";
|
|
38595
|
+
try {
|
|
38596
|
+
const resumeRes = await client.request(method, {
|
|
38597
|
+
cwd: dir,
|
|
38598
|
+
sessionId: job.runtimeSessionId,
|
|
38599
|
+
mcpServers: [],
|
|
38600
|
+
...resolvedModel ? { model: resolvedModel } : {}
|
|
38601
|
+
});
|
|
38602
|
+
sessionId = extractSessionID(resumeRes) || job.runtimeSessionId;
|
|
38603
|
+
} catch {
|
|
38604
|
+
sessionId = "";
|
|
38605
|
+
}
|
|
38606
|
+
}
|
|
38607
|
+
if (!sessionId) {
|
|
38608
|
+
const sessionRes = await client.request("session/new", {
|
|
38609
|
+
cwd: dir,
|
|
38610
|
+
mcpServers: [],
|
|
38611
|
+
...resolvedModel ? { model: resolvedModel } : {}
|
|
38612
|
+
});
|
|
38613
|
+
sessionId = extractSessionID(sessionRes);
|
|
38614
|
+
if (!sessionId) throw new Error("session/new returned no sessionId");
|
|
38615
|
+
}
|
|
38616
|
+
capturedSessionId = sessionId;
|
|
38491
38617
|
if (resolvedModel) {
|
|
38492
38618
|
await client.request("session/set_model", { sessionId, modelId: resolvedModel });
|
|
38493
38619
|
actualModel = resolvedModel;
|
|
@@ -39496,6 +39622,7 @@ var init_src4 = __esm({
|
|
|
39496
39622
|
init_claude_code();
|
|
39497
39623
|
init_resilient();
|
|
39498
39624
|
init_skill_cache();
|
|
39625
|
+
init_skill_cache_http();
|
|
39499
39626
|
init_models();
|
|
39500
39627
|
init_codex();
|
|
39501
39628
|
init_hermes();
|
|
@@ -54904,12 +55031,14 @@ async function startServe(opts) {
|
|
|
54904
55031
|
for (const cb of telemetryCbs) cb(event);
|
|
54905
55032
|
enqueueTrace(() => traceStore.appendEvents(traceRunId, [trajectoryEventToRunEvent(event, ++traceSeq)]).then(() => void 0));
|
|
54906
55033
|
});
|
|
55034
|
+
let capturedNativeSessionId;
|
|
54907
55035
|
const done = new Promise((resolve4, reject) => {
|
|
54908
55036
|
handle.onExit((info) => {
|
|
54909
55037
|
chatLiveSessions.delete(chatJobKey);
|
|
54910
55038
|
void provision.cleanup();
|
|
54911
55039
|
const endedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
54912
55040
|
const durationMs = Date.parse(endedAt) - Date.parse(traceStartedAt);
|
|
55041
|
+
if (info.runtimeSessionId) capturedNativeSessionId = info.runtimeSessionId;
|
|
54913
55042
|
enqueueTrace(async () => {
|
|
54914
55043
|
await traceStore.appendEvents(traceRunId, [{
|
|
54915
55044
|
seq: ++traceSeq,
|
|
@@ -54954,7 +55083,10 @@ async function startServe(opts) {
|
|
|
54954
55083
|
telemetryCbs.push(cb);
|
|
54955
55084
|
},
|
|
54956
55085
|
done,
|
|
54957
|
-
kill: () => handle.kill()
|
|
55086
|
+
kill: () => handle.kill(),
|
|
55087
|
+
get nativeSessionId() {
|
|
55088
|
+
return capturedNativeSessionId;
|
|
55089
|
+
}
|
|
54958
55090
|
};
|
|
54959
55091
|
},
|
|
54960
55092
|
trajectoryFeed: {
|
|
@@ -55868,7 +56000,27 @@ async function startNode(opts) {
|
|
|
55868
56000
|
} else {
|
|
55869
56001
|
console.log(`[oasis node] \u5DF2\u627E\u5230: ${adapters.join(", ")}`);
|
|
55870
56002
|
}
|
|
55871
|
-
const
|
|
56003
|
+
const skillCacheRoot = process.env["OASIS_SKILL_CACHE_ROOT"]?.trim();
|
|
56004
|
+
const skillCacheEnabled = process.env["OASIS_SKILL_CACHE"] === "1" || !!skillCacheRoot;
|
|
56005
|
+
if (skillCacheEnabled) {
|
|
56006
|
+
console.log(`[oasis node] skill-cache \u5F00\u542F\uFF0Croot=${skillCacheRoot ?? "~/.oasis/skill-cache"}`);
|
|
56007
|
+
}
|
|
56008
|
+
const claudeSyncSkills = skillCacheEnabled ? async (args) => {
|
|
56009
|
+
const source = makeHttpSkillMetadataSource({ serverUrl: args.serverUrl, actorToken: args.actorToken });
|
|
56010
|
+
await syncActorSkills({
|
|
56011
|
+
actorId: args.actorId,
|
|
56012
|
+
runtimeKind: args.runtimeKind,
|
|
56013
|
+
sessionDir: args.sessionDir,
|
|
56014
|
+
source,
|
|
56015
|
+
...skillCacheRoot ? { cacheRoot: skillCacheRoot } : {},
|
|
56016
|
+
logger: (level, msg, err) => {
|
|
56017
|
+
const prefix = `[skill-cache:node] ${msg}`;
|
|
56018
|
+
if (level === "warn") console.warn(prefix, err ?? "");
|
|
56019
|
+
else console.log(prefix);
|
|
56020
|
+
}
|
|
56021
|
+
});
|
|
56022
|
+
} : void 0;
|
|
56023
|
+
const claude = new ClaudeCodeAdapter({ streamJson: true, ...claudeSyncSkills ? { syncSkills: claudeSyncSkills } : {} });
|
|
55872
56024
|
const rawAdapters = {
|
|
55873
56025
|
"claude-code": claude,
|
|
55874
56026
|
claude,
|
|
@@ -56009,15 +56161,16 @@ var USAGE = `oasis \u2014\u2014 artifact-centric \u534F\u4F5C\u5185\u6838 CLI\uF
|
|
|
56009
56161
|
spawn <artifactId> --type <t> [--title <\u77ED\u540D>] [--brief <\u89C4\u683C>] [--input <\u4E0A\u6E38id>[,<id>\u2026]] [--owner <actorId>] [--workspace ws] [--persistence temp|persistent] [--parts-file <json>] [--<\u5B57\u6BB5> <\u503C>] [--set-json <json>]
|
|
56010
56162
|
# --parts-file\uFF1Aconvergent \u5E76\u884C\u5206\u89E3\u7684\u90E8\u4EF6\u6E05\u5355 JSON [{name, spec?, deps?}]\uFF08Stage 3\uFF0C\u7CFB\u7EDF\u6309\u90E8\u4EF6\u6D3E N \u8DEF\uFF09
|
|
56011
56163
|
# --<\u5B57\u6BB5> <\u503C>\uFF1A\u8BE5\u7C7B\u578B\u3010\u52A8\u6001\u58F0\u660E\u3011\u7684\u81EA\u5B9A\u4E49\u5B57\u6BB5\uFF08\u4E0D\u662F\u56FA\u5B9A\u6E05\u5355\uFF09\u2014\u2014\u7528 "oasis artifact-types show <type>" \u770B\u53EF\u586B\u5B57\u6BB5\uFF1Bstring[]/\u6279\u91CF\u7528 --set-json\uFF1B\u7F3A\u5FC5\u586B\u4F1A\u62A5\u9519\u5217\u51FA
|
|
56012
|
-
propose <artifactId>
|
|
56164
|
+
propose <artifactId> [--file <path> | --from-dir <path> | --git-commit <sha>] --reason <text> [--base <revisionId|none>] [--part <name>] [--rebase-of <revisionId>] [--checkpoint --continue]
|
|
56013
56165
|
# --file \u5355\u6587\u4EF6\uFF1B--from-dir \u9012\u5F52\u6574\u76EE\u5F55\u4E3A\u591A\u6587\u4EF6 revision\uFF08\u88C5\u7BB1\u5355\uFF0C\u8DE8\u7248\u672C\u53BB\u91CD\uFF0CF1\uFF09\u3002
|
|
56014
|
-
#
|
|
56166
|
+
# \u4EE3\u7801\u8282\u70B9\u53EF\u3010\u7701\u7565\u5168\u90E8\u5185\u5BB9\u53C2\u6570\u3011\uFF0C\u4EC5 --reason\uFF1A\u5148\u628A\u6539\u52A8 push \u5230\u5DE5\u5355 feat \u5206\u652F\uFF0C\u7CFB\u7EDF\u81EA\u52A8\u4ECE git \u6536\u96C6\uFF08\u672C\u4F53\u5728 git\uFF09\u3002
|
|
56167
|
+
# --git-commit\uFF1A\u624B\u52A8 external-pin \u90A3\u4E2A commit sha\uFF08\u7B49\u4EF7\u4E8E\u7CFB\u7EDF\u6536\u96C6\uFF0C\u7528\u4E8E\u7CBE\u786E\u6307\u5B9A\uFF09\u3002
|
|
56015
56168
|
# --part\uFF1A\u672C revision \u4EA7 convergent \u5206\u89E3\u91CC\u7684\u54EA\u4E2A\u90E8\u4EF6\uFF08\u89C1 spawn --parts-file\uFF09
|
|
56016
56169
|
# \u6CE8\u610F --from-dir \u662F"\u5185\u5BB9\u6E90\u76EE\u5F55"\uFF0C\u4E0E\u5168\u5C40 --dir\uFF08\u6570\u636E\u76EE\u5F55/operator-token \u6240\u5728\uFF09\u662F\u4E24\u56DE\u4E8B
|
|
56017
56170
|
queue <artifactId>
|
|
56018
56171
|
merge <artifactId> [revisionId]
|
|
56019
56172
|
advance <artifactId>
|
|
56020
|
-
integrate <artifactId>
|
|
56173
|
+
integrate <artifactId> [--file <path> | --from-dir <path> | --git-commit <sha>] --reason <text> # \u4EE3\u7801\u8282\u70B9\u53EF\u7701\u7565\u5185\u5BB9\u53C2\u6570\uFF1A\u7CFB\u7EDF\u4ECE\u5DE5\u5355 feat \u5206\u652F\u6536\u96C6\u6574\u5408\u7248
|
|
56021
56174
|
reject <artifactId> <revisionId> --reason <text>
|
|
56022
56175
|
conclude <artifactId> [--note <text>] # \u673A\u68B0 grounding \u786C\u62E6\uFF1B\u6709 gate \u5219\u8FDB\u5165\u5F85\u5BA1
|
|
56023
56176
|
review <artifactId> --verdict approve|request_changes [--note <t>]
|
|
@@ -56891,12 +57044,15 @@ ${res.warning}`);
|
|
|
56891
57044
|
const baseFlag = flags.get("base");
|
|
56892
57045
|
const dirFlag = flags.get("from-dir");
|
|
56893
57046
|
const gitCommit = flags.get("git-commit");
|
|
57047
|
+
const fileFlag = flags.get("file");
|
|
56894
57048
|
const checkpoint = flags.get("checkpoint") === "true";
|
|
56895
57049
|
const continueDispatch = flags.get("continue") === "true";
|
|
56896
57050
|
if (checkpoint !== continueDispatch) throw new Error("--checkpoint \u4E0E --continue \u5FC5\u987B\u540C\u65F6\u4F7F\u7528");
|
|
56897
57051
|
const { message } = await api.cmd("propose", {
|
|
56898
57052
|
artifactId,
|
|
56899
|
-
|
|
57053
|
+
// 内容四选一——【全缺则不带内容字段】,交服务端按节点类型定夺(code:从 git 收集;text:精确报错)。
|
|
57054
|
+
// 这是 HANDOFF 止血:从前 CLI 本地就 need(--file) 抛错,逼 agent 兜底成 --file HANDOFF.md 落 inline 假货。
|
|
57055
|
+
...gitCommit !== void 0 ? { externalPin: gitCommit } : dirFlag !== void 0 ? { files: readDirFiles(dirFlag) } : fileFlag !== void 0 ? { content: readFileArg(fileFlag) } : {},
|
|
56900
57056
|
reason: need(flags, "reason"),
|
|
56901
57057
|
...baseFlag !== void 0 ? { base: baseFlag === "none" ? null : baseFlag } : {},
|
|
56902
57058
|
...flags.get("part") !== void 0 ? { part: flags.get("part") } : {},
|
|
@@ -56924,11 +57080,14 @@ ${res.warning}`);
|
|
|
56924
57080
|
break;
|
|
56925
57081
|
}
|
|
56926
57082
|
case "integrate": {
|
|
56927
|
-
const artifactId = needPos(positional, 0, "oasis integrate <artifactId>
|
|
57083
|
+
const artifactId = needPos(positional, 0, "oasis integrate <artifactId> [--file f | --from-dir d | --git-commit sha] --reason r");
|
|
56928
57084
|
const dirFlag = flags.get("from-dir");
|
|
57085
|
+
const fileFlag = flags.get("file");
|
|
57086
|
+
const gitCommit = flags.get("git-commit");
|
|
56929
57087
|
const { message } = await api.cmd("integrate", {
|
|
56930
57088
|
artifactId,
|
|
56931
|
-
|
|
57089
|
+
// 内容全缺则不带内容字段,交服务端定夺(code:从工单 feat 分支收集整合版;text:精确报错)。HANDOFF 止血。
|
|
57090
|
+
...gitCommit !== void 0 ? { externalPin: gitCommit } : dirFlag !== void 0 ? { files: readDirFiles(dirFlag) } : fileFlag !== void 0 ? { content: readFileArg(fileFlag) } : {},
|
|
56932
57091
|
reason: need(flags, "reason")
|
|
56933
57092
|
});
|
|
56934
57093
|
println(message);
|
|
@@ -56961,11 +57120,12 @@ ${res.warning}`);
|
|
|
56961
57120
|
break;
|
|
56962
57121
|
}
|
|
56963
57122
|
case "annotate": {
|
|
57123
|
+
const raisedFromPart = flags.get("part") ?? process.env["OASIS_PART"];
|
|
56964
57124
|
const { message } = await api.cmd("annotate", {
|
|
56965
57125
|
artifactId: needPos(positional, 0, "oasis annotate <artifactId> --body t [--from d] [--part p]"),
|
|
56966
57126
|
body: need(flags, "body"),
|
|
56967
57127
|
raisedFrom: flags.get("from"),
|
|
56968
|
-
...
|
|
57128
|
+
...raisedFromPart !== void 0 ? { raisedFromPart } : {},
|
|
56969
57129
|
// @(信箱 ④):--at a,b —— @ 权只属于人(agent 用会被服务端拒);@agent=召它回话,@人=进其收件箱
|
|
56970
57130
|
...flags.get("at") !== void 0 ? { mentions: flags.get("at").split(",").map((x2) => x2.trim()).filter(Boolean) } : {},
|
|
56971
57131
|
blocks: flags.get("blocks") === "true"
|
|
@@ -57472,7 +57632,7 @@ ${res.warning}`);
|
|
|
57472
57632
|
}
|
|
57473
57633
|
|
|
57474
57634
|
// src/index.ts
|
|
57475
|
-
var PKG_VERSION = true ? "0.1.
|
|
57635
|
+
var PKG_VERSION = true ? "0.1.34" : "dev";
|
|
57476
57636
|
var OASIS_DIR = path18.join(os10.homedir(), ".oasis");
|
|
57477
57637
|
var CONFIG_FILE = path18.join(OASIS_DIR, "node-config.json");
|
|
57478
57638
|
var PID_FILE = path18.join(OASIS_DIR, "node.pid");
|
|
@@ -57613,7 +57773,7 @@ function selfUpdate() {
|
|
|
57613
57773
|
if (!cfg?.serverUrl) throw new Error("no config \u2014 run `oasis start` first");
|
|
57614
57774
|
const nameArg = cfg.name ? ` --name '${cfg.name.replace(/'/g, "'\\''")}'` : "";
|
|
57615
57775
|
const startCmd = `"$(npm prefix -g)/bin/oasis" start --server-ws '${cfg.serverUrl}'${nameArg}`;
|
|
57616
|
-
const inner = `sleep 2; npm install -g --prefer-online '${PKG_NAME}@latest' && ${startCmd} >> '${LOG_FILE}' 2>&1`;
|
|
57776
|
+
const inner = `{ echo "[oasis] self-update \u2192 npm install -g ${PKG_NAME}@latest (then restart)"; sleep 2; npm install -g --prefer-online '${PKG_NAME}@latest' && ${startCmd}; } >> '${LOG_FILE}' 2>&1`;
|
|
57617
57777
|
const hasSystemd = process.platform === "linux" && (() => {
|
|
57618
57778
|
try {
|
|
57619
57779
|
(0, import_node_child_process15.execSync)("command -v systemd-run", { stdio: "ignore" });
|
|
@@ -57622,14 +57782,14 @@ function selfUpdate() {
|
|
|
57622
57782
|
return false;
|
|
57623
57783
|
}
|
|
57624
57784
|
})();
|
|
57785
|
+
const log3 = fs19.openSync(LOG_FILE, "a");
|
|
57625
57786
|
if (hasSystemd) {
|
|
57626
57787
|
const child = (0, import_node_child_process15.spawn)("systemd-run", ["--user", "--scope", "--quiet", "sh", "-c", inner], {
|
|
57627
57788
|
detached: true,
|
|
57628
|
-
stdio: "ignore"
|
|
57789
|
+
stdio: ["ignore", log3, log3]
|
|
57629
57790
|
});
|
|
57630
57791
|
child.unref();
|
|
57631
57792
|
} else {
|
|
57632
|
-
const log3 = fs19.openSync(LOG_FILE, "a");
|
|
57633
57793
|
const child = (0, import_node_child_process15.spawn)("sh", ["-c", inner], { detached: true, stdio: ["ignore", log3, log3] });
|
|
57634
57794
|
child.unref();
|
|
57635
57795
|
}
|