oasis_test 0.1.107 → 0.1.108

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.
Files changed (2) hide show
  1. package/dist/index.js +90 -35
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -993,20 +993,27 @@ function pinnedReviewerOf(model, artifactId, role) {
993
993
  }
994
994
  return best?.actor ?? null;
995
995
  }
996
+ function latestAttempt(attempts) {
997
+ let best = null;
998
+ for (const a of attempts) {
999
+ if (best === null || a.at > best.at || a.at === best.at && a.seq >= best.seq) best = a;
1000
+ }
1001
+ return best;
1002
+ }
996
1003
  function concludeMilestones(model, id) {
997
1004
  return (model.concludeAttempts.get(id) ?? []).filter(
998
1005
  (a) => attemptStatus(model, a) === "satisfied"
999
1006
  );
1000
1007
  }
1001
1008
  function pendingConcludeAttempt(model, id) {
1002
- const last = model.concludeAttempts.get(id)?.at(-1);
1009
+ const last = latestAttempt(model.concludeAttempts.get(id) ?? []);
1003
1010
  return last && attemptStatus(model, last) === "pending" ? last : null;
1004
1011
  }
1005
1012
  function isConcluded(model, id) {
1006
1013
  return concludeMilestones(model, id).length > 0;
1007
1014
  }
1008
1015
  function concludedHead(model, id) {
1009
- return concludeMilestones(model, id).at(-1)?.head ?? null;
1016
+ return latestAttempt(concludeMilestones(model, id))?.head ?? null;
1010
1017
  }
1011
1018
  function revisionsOf(model, id) {
1012
1019
  return [...model.revisions.values()].filter((r) => r.artifactId === id);
@@ -4068,6 +4075,25 @@ ${m2.spec.split("\n").map((l) => ` > ${l}`).join("\n")}`);
4068
4075
  });
4069
4076
  })()
4070
4077
  ),
4078
+ // ★ 2026-08-18:交稿时把「系统看不出来的四件事」一并带上。
4079
+ //
4080
+ // 为什么必须写在**任务书**里:adapter 只把 TASK.md 当提示词喂给模型,其余 bundle 文件(包括
4081
+ // execution/CONTINUITY.md)只是躺在工作目录里、没人读。`--reason` 之所以交付过的节点 100% 都有,
4082
+ // 正因为它既进了任务书又是必填;这四项此前只活在 `oasis help propose` 里——next 上节点全部更新到
4083
+ // 认得它们之后的 10 小时里,两次真实交付**一次都没带**(实测 0/2)。
4084
+ //
4085
+ // 给 `none` 出口是刻意的:逼着写自由文本只会得到「暂无」这种假保证,而「确认没有」与「没人写」
4086
+ // 对下游是两条完全不同的信息(渲染侧据此分流,见 renderDeliveredWorkHandoff)。
4087
+ ...args.action === "review" ? [] : [
4088
+ ``,
4089
+ `### \u4EA4\u7A3F\u65F6\u4E00\u5E76\u5E26\u4E0A\uFF1A\u4E0B\u6E38\u8981\u7528\u7684\u56DB\u4EF6\u4E8B`,
4090
+ `\u8FD9\u56DB\u9879\u4F1A\u539F\u6837\u51FA\u73B0\u5728\u4E0B\u6E38\u8282\u70B9\u7684 \`inputs/<\u672C\u8282\u70B9>@<\u7248\u672C>/${UPSTREAM_HANDOFF_BASENAME}\` \u91CC\u3002\u5206\u53F7\u5206\u9694\uFF1B**\u786E\u5B9E\u6CA1\u6709\u5C31\u5199 \`none\`\uFF0C\u522B\u7F16\u300C\u6682\u65E0\u300D**\uFF1A`,
4091
+ `- \`--gaps\` **\u4F60\u6CA1\u80FD\u6838\u9A8C\u7684\u90E8\u5206** \u2014\u2014 \u6700\u8981\u7D27\u7684\u4E00\u9879\u3002\u4E0B\u6E38\u9ED8\u8BA4\u300C\u4E0A\u6E38\u4EA4\u4E86\u5C31\u662F\u9A8C\u8FC7\u4E86\u300D\uFF0C\u4F60\u4E0D\u5199\uFF0C\u6CA1\u9A8C\u7684\u90A3\u5757\u5C31\u76F4\u63A5\u8FDB\u4E0B\u4E00\u73AF\u3002\u4F8B\uFF1A\`--gaps "\u6CA1\u505A\u538B\u6D4B;\u53EA\u5728 dev \u9A8C\u8FC7"\``,
4092
+ `- \`--unresolved\` **\u4F60\u77E5\u9053\u4F46\u6CA1\u89E3\u51B3\u7684** \u2014\u2014 \u514D\u5F97\u4E0B\u6E38\u91CD\u590D\u8E29\u4F60\u5DF2\u7ECF\u8E29\u8FC7\u7684\u5751\u3002\u4F8B\uFF1A\`--unresolved "\u7EBF\u4E0A\u914D\u989D\u6CA1\u786E\u8BA4"\``,
4093
+ `- \`--risks\` **\u4EA4\u4ED8\u7269\u672C\u8EAB\u6CA1\u9519\u3001\u4F46\u7528\u7684\u65F6\u5019\u8981\u5F53\u5FC3\u7684** \u2014\u2014 \u4F8B\uFF1A\`--risks "\u5E76\u53D1\u8C03\u7528\u53EF\u80FD\u89E6\u53D1\u9650\u6D41"\``,
4094
+ `- \`--next\` **\u5EFA\u8BAE\u4E0B\u6E38\u5148\u505A\u54EA\u4E00\u6B65**\uFF08\u53EF\u9009\uFF09\u2014\u2014 \u4F8B\uFF1A\`--next "\u5148\u8DD1\u4E00\u6B21\u5C0F\u6D41\u91CF\u7070\u5EA6"\``,
4095
+ `\u5199 \`none\` = \u300C\u6211\u786E\u8BA4\u6CA1\u6709\u300D\uFF1B\u4E0D\u5199 = \u300C\u6CA1\u4EBA\u5199\u8FC7\u300D\u3002**\u8FD9\u4E24\u4EF6\u4E8B\u5BF9\u4E0B\u6E38\u5B8C\u5168\u4E0D\u540C\uFF0C\u522B\u6DF7\u3002**`
4096
+ ],
4071
4097
  // 兜底(§10):上次失败了 → 明确告诉它发生了什么 + 怎么破(首选 add-revision 拆出去)
4072
4098
  ...args.lastFailure ? args.lastFailure.resumed ? [
4073
4099
  // 续跑分支:上文还在它眼前,别再说"没留下任何产出"(自相矛盾),改成"接着干 + 先核现场"。
@@ -7994,14 +8020,13 @@ FROM ${schema}.workflow_nodes n
7994
8020
  LEFT JOIN ${schema}.works lw ON lw.id = n.latest_work_id
7995
8021
  LEFT JOIN ${schema}.works ls ON ls.id = n.latest_success_work_id;
7996
8022
 
8023
+ -- workorder_view \u5DF2\u4E0B\u7EBF\uFF08\u5DE5\u5355 1aa1f35b\uFF09\uFF1A\u5B83\u53EA\u989D\u5916\u7ED9\u51FA total_count / done_count \u4E24\u4E2A\u8FDB\u5EA6\u6570\uFF0C\u5168\u4ED3\u96F6\u6D88\u8D39\u65B9\uFF0C
8024
+ -- \u4E14\u53E3\u5F84\u4E0E\u540E\u7AEF\u771F\u6E90\uFF08server summaryOfWorkspace \u7684 progressExcludingBrief\uFF09\u4E0D\u540C\u2014\u2014total \u53EA\u6392 cancelled\u3001done \u7528
8025
+ -- latest_accept_id IS NOT NULL\uFF08\u66FE\u88AB\u9A8C\u6536\u8FC7\u81F3\u5C11\u4E00\u6B21\uFF09\uFF0C\u800C\u771F\u6E90\u6392\u9664 brief + \u5DF2\u4F5C\u5E9F\u3001\u6309\u300C\u9A8C\u6536\u843D\u5728\u5F53\u524D\u7248\u300D\u7B97\u3002
8026
+ -- \u4FDD\u7559\u4E00\u4EFD\u89C6\u56FE\u65E2\u6CA1\u4EBA\u8BFB\u3001\u53E3\u5F84\u53C8\u5BF9\u4E0D\u4E0A\uFF0C\u53EA\u4F1A\u662F\u7B2C\u4E09\u5904\u5BF9\u4E0D\u4E0A\u7684\u8FDB\u5EA6\u6570\u3002\u8FD9\u91CC\u4E0D\u518D CREATE\uFF1B\u4E0B\u9762\u7684 DROP \u8BA9\u5B58\u91CF\u5E93
8027
+ -- \u5728\u4E0B\u6B21 migrate \u65F6\u628A\u65E7\u89C6\u56FE\u5220\u6389\uFF08ENGINE_DDL \u6BB5\u4EA6\u6709\u4E00\u5904 DROP\uFF0C\u4E8C\u8005\u90FD\u7559\u4EE5\u9632\u91CD\u6392\uFF09\u3002\u5DE5\u5355\u8FDB\u5EA6\u7EDF\u4E00\u8D70\u540E\u7AEF\u8BFB\u6A21\u578B\uFF0C
8028
+ -- \u9700\u8981 SQL \u4FA7\u7EDF\u8BA1\u65F6\u53E6\u7ACB\u4E0E\u771F\u6E90\u540C\u53E3\u5F84\u7684\u89C6\u56FE\u5E76\u6CE8\u660E\u670D\u52A1\u5BF9\u8C61\uFF0C\u522B\u590D\u6D3B\u8FD9\u4E24\u4E2A\u6570\u3002
7997
8029
  DROP VIEW IF EXISTS ${schema}.workorder_view;
7998
- CREATE VIEW ${schema}.workorder_view AS
7999
- SELECT o.*,
8000
- (SELECT count(*) FROM ${schema}.workflow_nodes n
8001
- WHERE n.workorder_id = o.id AND n.cancelled_at IS NULL) AS total_count,
8002
- (SELECT count(*) FROM ${schema}.workflow_nodes n
8003
- WHERE n.workorder_id = o.id AND n.cancelled_at IS NULL AND n.latest_accept_id IS NOT NULL) AS done_count
8004
- FROM ${schema}.workorders o;
8005
8030
  `;
8006
8031
  }
8007
8032
  var init_schema2 = __esm({
@@ -13215,7 +13240,10 @@ var init_store_postgres = __esm({
13215
13240
  JOIN ${this.s}.workflow_nodes n ON n.id = r.node_id WHERE n.workorder_id = $1`,
13216
13241
  [id]
13217
13242
  );
13218
- const works = await this.c.query(`SELECT * FROM ${this.s}.works WHERE workorder_id = $1`, [id]);
13243
+ const works = await this.c.query(
13244
+ `SELECT * FROM ${this.s}.works WHERE workorder_id = $1 ORDER BY created_at ASC, id ASC`,
13245
+ [id]
13246
+ );
13219
13247
  const arts = await this.c.query(
13220
13248
  `SELECT a.* FROM ${this.s}.work_artifacts a JOIN ${this.s}.works w ON w.id = a.work_id WHERE w.workorder_id = $1`,
13221
13249
  [id]
@@ -14063,6 +14091,11 @@ var init_plan = __esm({
14063
14091
  if (!node || node.cancelledAt) return;
14064
14092
  killLatestWork(state, e.nodeId, ctx.at);
14065
14093
  killNodeReviews(state, e.nodeId, ctx.at);
14094
+ for (const issue2 of state.allIssues()) {
14095
+ if (issue2.resolvedAt !== null) continue;
14096
+ if (issue2.aboutNodeId !== e.nodeId && issue2.raisedByNodeId !== e.nodeId) continue;
14097
+ state.updateIssue(issue2.id, { resolvedAt: ctx.at, resolution: "wontfix" });
14098
+ }
14066
14099
  state.updateNode(e.nodeId, { cancelledAt: ctx.at, updatedAt: ctx.at });
14067
14100
  for (const edge of state.edgesFrom(e.nodeId)) {
14068
14101
  const dn = state.node(edge.toNodeId);
@@ -16007,6 +16040,7 @@ function bridgeLoadReadModel(input) {
16007
16040
  const holds = /* @__PURE__ */ new Map();
16008
16041
  for (const node of allNodes) {
16009
16042
  if (!node.latestWorkId) continue;
16043
+ if (node.cancelledAt) continue;
16010
16044
  const lw = allWorks.find((w2) => w2.id === node.latestWorkId);
16011
16045
  if (!lw || !lw.deadAt) continue;
16012
16046
  if (node.latestAcceptId === node.latestWorkId) continue;
@@ -149101,6 +149135,7 @@ function stallOf(model, id, runtime, dispatcherSignals) {
149101
149135
  if (gaps.length > 0) {
149102
149136
  return { kind: "waiting_human", action: "resolve_gap", detail: `\u5361\u5728\u7F3A\u53E3\u4E0A\u5F85\u4EBA\u8865\uFF1A${gaps[0].description}` };
149103
149137
  }
149138
+ if (isDeliveredSettled(model, id)) return null;
149104
149139
  if (isHeld(model, id)) {
149105
149140
  const h = holdOf(model, id);
149106
149141
  return { kind: "held", action: "resume", detail: `\u5DF2\u6682\u505C\u6D3E\u53D1${h?.reason ? `\uFF1A${h.reason}` : ""}\u2014\u2014\u5F85\u6062\u590D`, ...h?.at ? { since: h.at } : {} };
@@ -149146,7 +149181,7 @@ function stallOf(model, id, runtime, dispatcherSignals) {
149146
149181
  if (dep) return { kind: "waiting_system", ref: dep.to, detail: `\u7B49\u4E0A\u6E38\u6536\u53E3\uFF1A${dep.to}` };
149147
149182
  return { kind: "waiting_system", detail: `\u963B\u585E\u4E2D\uFF1A${b2.reasons[0] ?? "\u5F85\u524D\u7F6E\u5C31\u7EEA"}` };
149148
149183
  }
149149
- const queueCause = lifecycleOf(model, id) === "active" ? queueBlockCauseOf(model, id) : null;
149184
+ const queueCause = queueBlockCauseOf(model, id);
149150
149185
  if (queueCause !== null) {
149151
149186
  const pending = queueOf(model, id);
149152
149187
  const since = pending[0]?.createdAt;
@@ -149973,9 +150008,10 @@ function summaryOfWorkspace(model, workspace, arts, ref2, resolveProject, dispat
149973
150008
  owner: ref2(seed.owner),
149974
150009
  participants: participantIds.map(ref2),
149975
150010
  artifactCount: arts.length,
150011
+ // 原始计数(含 brief、含已作废)——仅作旧客户端回退;界面真源是下面的 progressExcludingBrief。
149976
150012
  progress: { concluded, total: arts.length },
149977
- // ADR 0088 D1:两个派生位内联,前端不再按行拉详情。口径逐字对齐它替代的旧前端函数。
149978
- progressExcludingBrief: progressExcludingBrief(arts, members, { concluded, total: arts.length }),
150013
+ // ADR 0088 D1:派生位内联,前端不再按行拉详情。这是进度的唯一真源(排除 brief + 已作废,见函数注释)。
150014
+ progressExcludingBrief: progressExcludingBrief(arts, members),
149979
150015
  ...runtimeAlertOf(arts, members, runtimeOf) ?? {},
149980
150016
  updatedAt: lastOps[lastOps.length - 1] ?? "",
149981
150017
  projectId: resolveProject?.(workspace) ?? null,
@@ -149990,20 +150026,17 @@ function tagsOf(seed) {
149990
150026
  if (!Array.isArray(raw)) return [];
149991
150027
  return [...new Set(raw.map((v2) => typeof v2 === "string" ? v2.trim() : "").filter(Boolean))];
149992
150028
  }
149993
- function progressExcludingBrief(arts, members, progress) {
149994
- let briefCount = 0;
149995
- let briefConcluded = 0;
150029
+ function progressExcludingBrief(arts, members) {
150030
+ let total = 0;
150031
+ let concluded = 0;
149996
150032
  for (let i = 0; i < arts.length; i++) {
149997
- if (arts[i].type !== "brief") continue;
149998
- briefCount++;
149999
- const s2 = deriveNodeStage(members[i]);
150000
- if (s2 === "concluded" || s2 === "sealed") briefConcluded++;
150033
+ const info = members[i];
150034
+ if (arts[i].type === "brief") continue;
150035
+ if (info.sealed) continue;
150036
+ total++;
150037
+ if (info.concluded) concluded++;
150001
150038
  }
150002
- if (briefCount === 0) return progress;
150003
- return {
150004
- concluded: Math.max(0, progress.concluded - briefConcluded),
150005
- total: Math.max(0, progress.total - briefCount)
150006
- };
150039
+ return { concluded, total };
150007
150040
  }
150008
150041
  function runtimeAlertOf(arts, members, runtimeOf) {
150009
150042
  if (!runtimeOf) return void 0;
@@ -159376,6 +159409,7 @@ var init_codex = __esm({
159376
159409
  "../adapters/src/codex/index.ts"() {
159377
159410
  "use strict";
159378
159411
  import_node_child_process9 = require("node:child_process");
159412
+ init_container_runtime();
159379
159413
  import_node_crypto15 = require("node:crypto");
159380
159414
  fs10 = __toESM(require("node:fs"), 1);
159381
159415
  os5 = __toESM(require("node:os"), 1);
@@ -159421,9 +159455,6 @@ var init_codex = __esm({
159421
159455
  */
159422
159456
  capabilities = { appendInput: false };
159423
159457
  async spawn(job) {
159424
- if (job.executionEnv) {
159425
- throw new Error("executionEnv\uFF1Acodex runtime \u5C1A\u672A\u652F\u6301\u5BB9\u5668\u5316\u6267\u884C\uFF08ADR-0147\uFF09\uFF0C\u8BF7\u6539\u6D3E claude-code \u5458\u5DE5\u6216\u53BB\u6389\u8BE5\u8282\u70B9\u7684 executionEnv \u58F0\u660E");
159426
- }
159427
159458
  const slug6 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
159428
159459
  const id = `codex-${slug6}-${(0, import_node_crypto15.randomUUID)().slice(0, 8)}`;
159429
159460
  const startedAtMs = Date.now();
@@ -159483,7 +159514,21 @@ var init_codex = __esm({
159483
159514
  ),
159484
159515
  promptViaStdin ? "-" : prompt
159485
159516
  ];
159486
- const child = (0, import_node_child_process9.spawn)(this.opts.codexBin ?? "codex", args, {
159517
+ const containerized = await maybeContainerize({
159518
+ bin: this.opts.codexBin ?? "codex",
159519
+ args,
159520
+ cwd: dir,
159521
+ job,
159522
+ ...this.opts.workRoot !== void 0 ? { workRoot: this.opts.workRoot } : {},
159523
+ ...this.opts.env !== void 0 ? { extraEnvEarly: this.opts.env } : {}
159524
+ });
159525
+ const child = containerized ? (0, import_node_child_process9.spawn)(containerized.bin, containerized.args, {
159526
+ cwd: dir,
159527
+ env: scrubLeakyEnv(process.env),
159528
+ // stdin 的开合口径与宿主分支一致:codex 只在走 stdin 时才该收到管道(见下方长注释)。
159529
+ // 容器包装本身带 `-i`,podman 会把这条管道透传给容器内进程。
159530
+ stdio: [promptViaStdin ? "pipe" : "ignore", "pipe", "pipe"]
159531
+ }) : (0, import_node_child_process9.spawn)(this.opts.codexBin ?? "codex", args, {
159487
159532
  cwd: dir,
159488
159533
  env: {
159489
159534
  ...scrubLeakyEnv(process.env),
@@ -159598,6 +159643,7 @@ var init_codex = __esm({
159598
159643
  };
159599
159644
  const timer = setTimeout(() => {
159600
159645
  killReason ??= "timeout";
159646
+ if (containerized) killContainerBestEffort(containerized.containerName, containerized.mode);
159601
159647
  child.kill("SIGKILL");
159602
159648
  }, job.limits.wallClockMs);
159603
159649
  child.on("error", () => {
@@ -159625,13 +159671,16 @@ var init_codex = __esm({
159625
159671
  ...telemetry.usage ? { usage: telemetry.usage } : {},
159626
159672
  ...model ? { model } : {},
159627
159673
  ...runtimeSessionId ? { runtimeSessionId } : {},
159628
- ...errorMessage ? { errorMessage } : {}
159674
+ ...errorMessage ? { errorMessage } : {},
159675
+ // 跑在哪个镜像上要落账:同一题换了镜像,分数就不可比(ADR-0147 M5)
159676
+ ...containerized?.imageDigest ? { imageDigest: containerized.imageDigest } : {}
159629
159677
  });
159630
159678
  });
159631
159679
  return {
159632
159680
  id,
159633
159681
  async kill() {
159634
159682
  killReason ??= "cancelled";
159683
+ if (containerized) killContainerBestEffort(containerized.containerName, containerized.mode);
159635
159684
  child.kill("SIGKILL");
159636
159685
  },
159637
159686
  onExit(cb) {
@@ -183662,15 +183711,20 @@ var init_handoff_work_bridge = __esm({
183662
183711
 
183663
183712
  // ../server/src/domains/execution-continuity/upstream-handoff-input.ts
183664
183713
  function renderRefs(refs) {
183665
- return refs.map(
183666
- (ref2) => `- ${ref2.kind}:${ref2.id}${ref2.version ? `@${ref2.version}` : ""}${ref2.label ? ` \u2014 ${ref2.label}` : ""}`
183667
- );
183714
+ return refs.map((ref2) => {
183715
+ const label = ref2.id.startsWith(`${ref2.kind}:`) ? ref2.id : `${ref2.kind}:${ref2.id}`;
183716
+ return `- ${label}${ref2.version ? `@${ref2.version}` : ""}${ref2.label ? ` \u2014 ${ref2.label}` : ""}`;
183717
+ });
183668
183718
  }
183669
183719
  function bounded(text) {
183670
183720
  const t = text.trim();
183671
183721
  return [...t].length <= INJECTED_TEXT_LIMIT ? t : `${[...t].slice(0, INJECTED_TEXT_LIMIT).join("")}\u2026\uFF08\u539F\u6587\u8FC7\u957F\uFF0C\u6B64\u5904\u622A\u65AD\uFF1B\u5B8C\u6574\u5185\u5BB9\u89C1\u8BE5\u4E0A\u6E38\u8282\u70B9\u7684\u4EA4\u4ED8\u8BF4\u660E\uFF09`;
183672
183722
  }
183723
+ function isExplicitNone(values) {
183724
+ return values.length === 1 && NONE_TOKENS.has((values[0] ?? "").trim().toLowerCase());
183725
+ }
183673
183726
  function renderList(title, values) {
183727
+ if (isExplicitNone(values)) return [`## ${title}`, "- \u6267\u884C\u4EBA\u786E\u8BA4\uFF1A\u65E0", ""];
183674
183728
  return [
183675
183729
  `## ${title}`,
183676
183730
  ...values.length > 0 ? values.map((value) => `- ${value}`) : ["- None"],
@@ -183813,12 +183867,13 @@ function createUpstreamHandoffInputResolver(opts) {
183813
183867
  }
183814
183868
  };
183815
183869
  }
183816
- var INJECTED_TEXT_LIMIT;
183870
+ var INJECTED_TEXT_LIMIT, NONE_TOKENS;
183817
183871
  var init_upstream_handoff_input = __esm({
183818
183872
  "../server/src/domains/execution-continuity/upstream-handoff-input.ts"() {
183819
183873
  "use strict";
183820
183874
  init_src3();
183821
183875
  INJECTED_TEXT_LIMIT = 4e3;
183876
+ NONE_TOKENS = /* @__PURE__ */ new Set(["none", "n/a", "na", "nil", "\u65E0", "\u6CA1\u6709", "\u6682\u65E0"]);
183822
183877
  }
183823
183878
  });
183824
183879
 
@@ -202949,7 +203004,7 @@ function syncRuntimeAssets(candidateRoots, binDir) {
202949
203004
  }
202950
203005
 
202951
203006
  // src/index.ts
202952
- var PKG_VERSION = true ? "0.1.107" : "dev";
203007
+ var PKG_VERSION = true ? "0.1.108" : "dev";
202953
203008
  var OASIS_DIR = path28.join(os11.homedir(), ".oasis");
202954
203009
  var CONFIG_FILE = path28.join(OASIS_DIR, "node-config.json");
202955
203010
  var PID_FILE = path28.join(OASIS_DIR, "node.pid");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oasis_test",
3
- "version": "0.1.107",
3
+ "version": "0.1.108",
4
4
  "description": "Oasis node daemon + CLI — background daemon, auto-start, full server CLI",
5
5
  "bin": {
6
6
  "oasis": "./dist/index.js"